diff --git a/cmd/sshpiperd/daemon.go b/cmd/sshpiperd/daemon.go index 711f255c..954dbaf5 100644 --- a/cmd/sshpiperd/daemon.go +++ b/cmd/sshpiperd/daemon.go @@ -134,7 +134,7 @@ func newDaemon(ctx *cli.Context) (*daemon, error) { bannerfile := ctx.String("banner-file") if bannertext != "" || bannerfile != "" { - config.BannerCallback = func(_ ssh.ConnMetadata, _ ssh.ChallengeContext) string { + config.DownstreamBannerCallback = func(_ ssh.ConnMetadata, _ ssh.ChallengeContext) string { if bannerfile != "" { text, err := os.ReadFile(bannerfile) if err != nil { @@ -147,6 +147,18 @@ func newDaemon(ctx *cli.Context) (*daemon, error) { } } + switch ctx.String("upstream-banner-mode") { + case "passthrough": + // library will handle the banner to client + case "ignore": + config.UpstreamBannerCallback = func(downconn ssh.ServerPreAuthConn, banner string, challengeCtx ssh.ChallengeContext) error { + return nil + } + // case "dedup": + default: + return nil, fmt.Errorf("unknown upstream banner mode %q; allowed: 'passthrough' or 'ignore'", ctx.String("upstream-banner-mode")) + } + return &daemon{ config: config, lis: lis, diff --git a/cmd/sshpiperd/internal/plugin/chain.go b/cmd/sshpiperd/internal/plugin/chain.go index 5a85ebd7..7b7a2bc0 100644 --- a/cmd/sshpiperd/internal/plugin/chain.go +++ b/cmd/sshpiperd/internal/plugin/chain.go @@ -54,7 +54,7 @@ type chainConnMeta struct { current int } -func (cp *ChainPlugins) CreateChallengeContext(conn ssh.ConnMetadata) (ssh.ChallengeContext, error) { +func (cp *ChainPlugins) CreateChallengeContext(conn ssh.ServerPreAuthConn) (ssh.ChallengeContext, error) { uiq, err := uuid.NewRandom() if err != nil { return nil, err @@ -109,7 +109,7 @@ func (cp *ChainPlugins) NextAuthMethods(conn ssh.ConnMetadata, challengeCtx ssh. func (cp *ChainPlugins) InstallPiperConfig(config *GrpcPluginConfig) error { - config.CreateChallengeContext = func(conn ssh.ConnMetadata) (ssh.ChallengeContext, error) { + config.CreateChallengeContext = func(conn ssh.ServerPreAuthConn) (ssh.ChallengeContext, error) { ctx, err := cp.CreateChallengeContext(conn) if err != nil { log.Errorf("cannot create challenge context %v", err) @@ -143,10 +143,10 @@ func (cp *ChainPlugins) InstallPiperConfig(config *GrpcPluginConfig) error { } } - config.BannerCallback = func(conn ssh.ConnMetadata, challengeCtx ssh.ChallengeContext) string { + config.DownstreamBannerCallback = func(conn ssh.ConnMetadata, challengeCtx ssh.ChallengeContext) string { cur := cp.pluginsCallback[challengeCtx.(*chainConnMeta).current] - if cur.BannerCallback != nil { - return cur.BannerCallback(conn, challengeCtx) + if cur.DownstreamBannerCallback != nil { + return cur.DownstreamBannerCallback(conn, challengeCtx) } return "" diff --git a/cmd/sshpiperd/internal/plugin/grpc.go b/cmd/sshpiperd/internal/plugin/grpc.go index d052bb1c..0c3a721a 100644 --- a/cmd/sshpiperd/internal/plugin/grpc.go +++ b/cmd/sshpiperd/internal/plugin/grpc.go @@ -56,7 +56,7 @@ func (g *GrpcPlugin) InstallPiperConfig(config *GrpcPluginConfig) error { return err } - config.CreateChallengeContext = func(conn ssh.ConnMetadata) (ssh.ChallengeContext, error) { + config.CreateChallengeContext = func(conn ssh.ServerPreAuthConn) (ssh.ChallengeContext, error) { ctx, err := g.CreateChallengeContext(conn) if err != nil { log.Errorf("cannot create challenge context %v", err) @@ -121,7 +121,7 @@ func (g *GrpcPlugin) InstallPiperConfig(config *GrpcPluginConfig) error { g.UpstreamAuthFailureCallbackRemote(conn, method, err, challengeCtx) } case "Banner": - config.BannerCallback = g.BannerCallback + config.DownstreamBannerCallback = g.DownstreamBannerCallback case "VerifyHostKey": // ignore case "PipeStart": @@ -155,7 +155,7 @@ func (m *connMeta) Meta() interface{} { return m } -func (g *GrpcPlugin) CreateChallengeContext(conn ssh.ConnMetadata) (ssh.ChallengeContext, error) { +func (g *GrpcPlugin) CreateChallengeContext(conn ssh.ServerPreAuthConn) (ssh.ChallengeContext, error) { uiq, err := uuid.NewRandom() if err != nil { return nil, err @@ -494,7 +494,7 @@ func (g *GrpcPlugin) KeyboardInteractiveCallback(conn ssh.ConnMetadata, client s } } -func (g *GrpcPlugin) BannerCallback(conn ssh.ConnMetadata, challengeCtx ssh.ChallengeContext) string { +func (g *GrpcPlugin) DownstreamBannerCallback(conn ssh.ConnMetadata, challengeCtx ssh.ChallengeContext) string { meta := toMeta(challengeCtx, conn) reply, err := g.client.Banner(context.Background(), &libplugin.BannerRequest{ Meta: meta, diff --git a/cmd/sshpiperd/main.go b/cmd/sshpiperd/main.go index 1f9aa120..3f5bfbe8 100644 --- a/cmd/sshpiperd/main.go +++ b/cmd/sshpiperd/main.go @@ -166,6 +166,12 @@ func main() { Usage: "display a banner from file before authentication", EnvVars: []string{"SSHPIPERD_BANNERFILE"}, }, + &cli.StringFlag{ + Name: "upstream-banner-mode", + Value: "passthrough", + Usage: "upstream banner mode, allowed values: 'passthrough' (pass the banner from upstream to client) or 'ignore' (ignore the banner from upstream)", + EnvVars: []string{"SSHPIPERD_UPSTREAM_BANNER_MODE"}, + }, &cli.BoolFlag{ Name: "drop-hostkeys-message", Value: false, @@ -299,6 +305,7 @@ func main() { log.Errorf("plugin %v recv logs error: %v", p.Name, err) } }() + plugins = append(plugins, p) } diff --git a/crypto b/crypto index 2a4b9c24..ff1e56f4 160000 --- a/crypto +++ b/crypto @@ -1 +1 @@ -Subproject commit 2a4b9c2448bc0257714a950e5d61a55d3633eb65 +Subproject commit ff1e56f4b7ef0bf248a7bba9c996414504ffa09a diff --git a/e2e/sshdconfig/banner b/e2e/sshdconfig/banner index e0b8fdc5..3de2e879 100644 --- a/e2e/sshdconfig/banner +++ b/e2e/sshdconfig/banner @@ -1 +1 @@ -sshpiper banner from upstream test \ No newline at end of file +sshpiper banner from upstream test