From 49170a50f8fb8b35f7296d3e1f036978f55fa644 Mon Sep 17 00:00:00 2001 From: Boshi Lian Date: Tue, 20 Feb 2018 04:49:28 +0800 Subject: [PATCH] fix remap user failed when banner enabled --- Gopkg.lock | 2 +- vendor/golang.org/x/crypto/openpgp/keys.go | 7 +- .../golang.org/x/crypto/openpgp/keys_test.go | 50 ++++++ .../x/crypto/ssh/client_auth_test.go | 4 +- vendor/golang.org/x/crypto/ssh/server.go | 10 +- vendor/golang.org/x/crypto/ssh/sshpiper.go | 162 +++++++++++------- .../golang.org/x/crypto/ssh/sshpiper_test.go | 7 +- 7 files changed, 171 insertions(+), 71 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index 2db0dc62..40435fda 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -25,7 +25,7 @@ "ssh", "ssh/testdata" ] - revision = "d47aa888633435f7d7af47a9b39ab3788b387f0c" + revision = "c832b236b4049eae471365acd18bc0b462a64a2b" source = "https://github.com/tg123/sshpiper.crypto" [solve-meta] diff --git a/vendor/golang.org/x/crypto/openpgp/keys.go b/vendor/golang.org/x/crypto/openpgp/keys.go index 744e293f..fd582a89 100644 --- a/vendor/golang.org/x/crypto/openpgp/keys.go +++ b/vendor/golang.org/x/crypto/openpgp/keys.go @@ -486,7 +486,7 @@ func NewEntity(name, comment, email string, config *packet.Config) (*Entity, err } isPrimaryId := true e.Identities[uid.Id] = &Identity{ - Name: uid.Name, + Name: uid.Id, UserId: uid, SelfSignature: &packet.Signature{ CreationTime: currentTime, @@ -507,6 +507,11 @@ func NewEntity(name, comment, email string, config *packet.Config) (*Entity, err e.Identities[uid.Id].SelfSignature.PreferredHash = []uint8{hashToHashId(config.DefaultHash)} } + // Likewise for DefaultCipher. + if config != nil && config.DefaultCipher != 0 { + e.Identities[uid.Id].SelfSignature.PreferredSymmetric = []uint8{uint8(config.DefaultCipher)} + } + e.Subkeys = make([]Subkey, 1) e.Subkeys[0] = Subkey{ PublicKey: packet.NewRSAPublicKey(currentTime, &encryptingPriv.PublicKey), diff --git a/vendor/golang.org/x/crypto/openpgp/keys_test.go b/vendor/golang.org/x/crypto/openpgp/keys_test.go index 76ba13ed..3a155063 100644 --- a/vendor/golang.org/x/crypto/openpgp/keys_test.go +++ b/vendor/golang.org/x/crypto/openpgp/keys_test.go @@ -320,6 +320,56 @@ func TestNewEntityWithoutPreferredHash(t *testing.T) { } } +func TestNewEntityCorrectName(t *testing.T) { + entity, err := NewEntity("Golang Gopher", "Test Key", "no-reply@golang.com", nil) + if err != nil { + t.Fatal(err) + } + if len(entity.Identities) != 1 { + t.Fatalf("len(entity.Identities) = %d, want 1", len(entity.Identities)) + } + var got string + for _, i := range entity.Identities { + got = i.Name + } + want := "Golang Gopher (Test Key) " + if got != want { + t.Fatalf("Identity.Name = %q, want %q", got, want) + } +} + +func TestNewEntityWithPreferredSymmetric(t *testing.T) { + c := &packet.Config{ + DefaultCipher: packet.CipherAES256, + } + entity, err := NewEntity("Golang Gopher", "Test Key", "no-reply@golang.com", c) + if err != nil { + t.Fatal(err) + } + + for _, identity := range entity.Identities { + if len(identity.SelfSignature.PreferredSymmetric) == 0 { + t.Fatal("didn't find a preferred cipher in self signature") + } + if identity.SelfSignature.PreferredSymmetric[0] != uint8(c.DefaultCipher) { + t.Fatalf("Expected preferred cipher to be %d, got %d", uint8(c.DefaultCipher), identity.SelfSignature.PreferredSymmetric[0]) + } + } +} + +func TestNewEntityWithoutPreferredSymmetric(t *testing.T) { + entity, err := NewEntity("Golang Gopher", "Test Key", "no-reply@golang.com", nil) + if err != nil { + t.Fatal(err) + } + + for _, identity := range entity.Identities { + if len(identity.SelfSignature.PreferredSymmetric) != 0 { + t.Fatalf("Expected preferred cipher to be empty but got length %d", len(identity.SelfSignature.PreferredSymmetric)) + } + } +} + const expiringKeyHex = "988d0451d1ec5d010400ba3385721f2dc3f4ab096b2ee867ab77213f0a27a8538441c35d2fa225b08798a1439a66a5150e6bdc3f40f5d28d588c712394c632b6299f77db8c0d48d37903fb72ebd794d61be6aa774688839e5fdecfe06b2684cc115d240c98c66cb1ef22ae84e3aa0c2b0c28665c1e7d4d044e7f270706193f5223c8d44e0d70b7b8da830011010001b40f4578706972792074657374206b657988be041301020028050251d1ec5d021b03050900278d00060b090807030206150802090a0b0416020301021e01021780000a091072589ad75e237d8c033503fd10506d72837834eb7f994117740723adc39227104b0d326a1161871c0b415d25b4aedef946ca77ea4c05af9c22b32cf98be86ab890111fced1ee3f75e87b7cc3c00dc63bbc85dfab91c0dc2ad9de2c4d13a34659333a85c6acc1a669c5e1d6cecb0cf1e56c10e72d855ae177ddc9e766f9b2dda57ccbb75f57156438bbdb4e42b88d0451d1ec5d0104009c64906559866c5cb61578f5846a94fcee142a489c9b41e67b12bb54cfe86eb9bc8566460f9a720cb00d6526fbccfd4f552071a8e3f7744b1882d01036d811ee5a3fb91a1c568055758f43ba5d2c6a9676b012f3a1a89e47bbf624f1ad571b208f3cc6224eb378f1645dd3d47584463f9eadeacfd1ce6f813064fbfdcc4b5a53001101000188a504180102000f021b0c050251d1f06b050900093e89000a091072589ad75e237d8c20e00400ab8310a41461425b37889c4da28129b5fae6084fafbc0a47dd1adc74a264c6e9c9cc125f40462ee1433072a58384daef88c961c390ed06426a81b464a53194c4e291ddd7e2e2ba3efced01537d713bd111f48437bde2363446200995e8e0d4e528dda377fd1e8f8ede9c8e2198b393bd86852ce7457a7e3daf74d510461a5b77b88d0451d1ece8010400b3a519f83ab0010307e83bca895170acce8964a044190a2b368892f7a244758d9fc193482648acb1fb9780d28cc22d171931f38bb40279389fc9bf2110876d4f3db4fcfb13f22f7083877fe56592b3b65251312c36f83ffcb6d313c6a17f197dd471f0712aad15a8537b435a92471ba2e5b0c72a6c72536c3b567c558d7b6051001101000188a504180102000f021b0c050251d1f07b050900279091000a091072589ad75e237d8ce69e03fe286026afacf7c97ee20673864d4459a2240b5655219950643c7dba0ac384b1d4359c67805b21d98211f7b09c2a0ccf6410c8c04d4ff4a51293725d8d6570d9d8bb0e10c07d22357caeb49626df99c180be02d77d1fe8ed25e7a54481237646083a9f89a11566cd20b9e995b1487c5f9e02aeb434f3a1897cd416dd0a87861838da3e9e" const subkeyUsageHex = "988d04533a52bc010400d26af43085558f65b9e7dbc90cb9238015259aed5e954637adcfa2181548b2d0b60c65f1f42ec5081cbf1bc0a8aa4900acfb77070837c58f26012fbce297d70afe96e759ad63531f0037538e70dbf8e384569b9720d99d8eb39d8d0a2947233ed242436cb6ac7dfe74123354b3d0119b5c235d3dd9c9d6c004f8ffaf67ad8583001101000188b7041f010200210502533b8552170c8001ce094aa433f7040bb2ddf0be3893cb843d0fe70c020700000a0910a42704b92866382aa98404009d63d916a27543da4221c60087c33f1c44bec9998c5438018ed370cca4962876c748e94b73eb39c58eb698063f3fd6346d58dd2a11c0247934c4a9d71f24754f7468f96fb24c3e791dd2392b62f626148ad724189498cbf993db2df7c0cdc2d677c35da0f16cb16c9ce7c33b4de65a4a91b1d21a130ae9cc26067718910ef8e2b417556d627261203c756d627261407379642e65642e61753e88b80413010200220502533a52bc021b03060b090807030206150802090a0b0416020301021e01021780000a0910a42704b92866382a47840400c0c2bd04f5fca586de408b395b3c280a278259c93eaaa8b79a53b97003f8ed502a8a00446dd9947fb462677e4fcac0dac2f0701847d15130aadb6cd9e0705ea0cf5f92f129136c7be21a718d46c8e641eb7f044f2adae573e11ae423a0a9ca51324f03a8a2f34b91fa40c3cc764bee4dccadedb54c768ba0469b683ea53f1c29b88d04533a52bc01040099c92a5d6f8b744224da27bc2369127c35269b58bec179de6bbc038f749344222f85a31933224f26b70243c4e4b2d242f0c4777eaef7b5502f9dad6d8bf3aaeb471210674b74de2d7078af497d55f5cdad97c7bedfbc1b41e8065a97c9c3d344b21fc81d27723af8e374bc595da26ea242dccb6ae497be26eea57e563ed517e90011010001889f0418010200090502533a52bc021b0c000a0910a42704b92866382afa1403ff70284c2de8a043ff51d8d29772602fa98009b7861c540535f874f2c230af8caf5638151a636b21f8255003997ccd29747fdd06777bb24f9593bd7d98a3e887689bf902f999915fcc94625ae487e5d13e6616f89090ebc4fdc7eb5cad8943e4056995bb61c6af37f8043016876a958ec7ebf39c43d20d53b7f546cfa83e8d2604b88d04533b8283010400c0b529316dbdf58b4c54461e7e669dc11c09eb7f73819f178ccd4177b9182b91d138605fcf1e463262fabefa73f94a52b5e15d1904635541c7ea540f07050ce0fb51b73e6f88644cec86e91107c957a114f69554548a85295d2b70bd0b203992f76eb5d493d86d9eabcaa7ef3fc7db7e458438db3fcdb0ca1cc97c638439a9170011010001889f0418010200090502533b8283021b0c000a0910a42704b92866382adc6d0400cfff6258485a21675adb7a811c3e19ebca18851533f75a7ba317950b9997fda8d1a4c8c76505c08c04b6c2cc31dc704d33da36a21273f2b388a1a706f7c3378b66d887197a525936ed9a69acb57fe7f718133da85ec742001c5d1864e9c6c8ea1b94f1c3759cebfd93b18606066c063a63be86085b7e37bdbc65f9a915bf084bb901a204533b85cd110400aed3d2c52af2b38b5b67904b0ef73d6dd7aef86adb770e2b153cd22489654dcc91730892087bb9856ae2d9f7ed1eb48f214243fe86bfe87b349ebd7c30e630e49c07b21fdabf78b7a95c8b7f969e97e3d33f2e074c63552ba64a2ded7badc05ce0ea2be6d53485f6900c7860c7aa76560376ce963d7271b9b54638a4028b573f00a0d8854bfcdb04986141568046202192263b9b67350400aaa1049dbc7943141ef590a70dcb028d730371d92ea4863de715f7f0f16d168bd3dc266c2450457d46dcbbf0b071547e5fbee7700a820c3750b236335d8d5848adb3c0da010e998908dfd93d961480084f3aea20b247034f8988eccb5546efaa35a92d0451df3aaf1aee5aa36a4c4d462c760ecd9cebcabfbe1412b1f21450f203fd126687cd486496e971a87fd9e1a8a765fe654baa219a6871ab97768596ab05c26c1aeea8f1a2c72395a58dbc12ef9640d2b95784e974a4d2d5a9b17c25fedacfe551bda52602de8f6d2e48443f5dd1a2a2a8e6a5e70ecdb88cd6e766ad9745c7ee91d78cc55c3d06536b49c3fee6c3d0b6ff0fb2bf13a314f57c953b8f4d93bf88e70418010200090502533b85cd021b0200520910a42704b92866382a47200419110200060502533b85cd000a091042ce2c64bc0ba99214b2009e26b26852c8b13b10c35768e40e78fbbb48bd084100a0c79d9ea0844fa5853dd3c85ff3ecae6f2c9dd6c557aa04008bbbc964cd65b9b8299d4ebf31f41cc7264b8cf33a00e82c5af022331fac79efc9563a822497ba012953cefe2629f1242fcdcb911dbb2315985bab060bfd58261ace3c654bdbbe2e8ed27a46e836490145c86dc7bae15c011f7e1ffc33730109b9338cd9f483e7cef3d2f396aab5bd80efb6646d7e778270ee99d934d187dd98" const revokedKeyHex = "988d045331ce82010400c4fdf7b40a5477f206e6ee278eaef888ca73bf9128a9eef9f2f1ddb8b7b71a4c07cfa241f028a04edb405e4d916c61d6beabc333813dc7b484d2b3c52ee233c6a79b1eea4e9cc51596ba9cd5ac5aeb9df62d86ea051055b79d03f8a4fa9f38386f5bd17529138f3325d46801514ea9047977e0829ed728e68636802796801be10011010001889f04200102000905025331d0e3021d03000a0910a401d9f09a34f7c042aa040086631196405b7e6af71026b88e98012eab44aa9849f6ef3fa930c7c9f23deaedba9db1538830f8652fb7648ec3fcade8dbcbf9eaf428e83c6cbcc272201bfe2fbb90d41963397a7c0637a1a9d9448ce695d9790db2dc95433ad7be19eb3de72dacf1d6db82c3644c13eae2a3d072b99bb341debba012c5ce4006a7d34a1f4b94b444526567205265766f6b657220283c52656727732022424d204261726973746122204b657920262530305c303e5c29203c72656740626d626172697374612e636f2e61753e88b704130102002205025331ce82021b03060b090807030206150802090a0b0416020301021e01021780000a0910a401d9f09a34f7c0019c03f75edfbeb6a73e7225ad3cc52724e2872e04260d7daf0d693c170d8c4b243b8767bc7785763533febc62ec2600c30603c433c095453ede59ff2fcabeb84ce32e0ed9d5cf15ffcbc816202b64370d4d77c1e9077d74e94a16fb4fa2e5bec23a56d7a73cf275f91691ae1801a976fcde09e981a2f6327ac27ea1fecf3185df0d56889c04100102000605025331cfb5000a0910fe9645554e8266b64b4303fc084075396674fb6f778d302ac07cef6bc0b5d07b66b2004c44aef711cbac79617ef06d836b4957522d8772dd94bf41a2f4ac8b1ee6d70c57503f837445a74765a076d07b829b8111fc2a918423ddb817ead7ca2a613ef0bfb9c6b3562aec6c3cf3c75ef3031d81d95f6563e4cdcc9960bcb386c5d757b104fcca5fe11fc709df884604101102000605025331cfe7000a09107b15a67f0b3ddc0317f6009e360beea58f29c1d963a22b962b80788c3fa6c84e009d148cfde6b351469b8eae91187eff07ad9d08fcaab88d045331ce820104009f25e20a42b904f3fa555530fe5c46737cf7bd076c35a2a0d22b11f7e0b61a69320b768f4a80fe13980ce380d1cfc4a0cd8fbe2d2e2ef85416668b77208baa65bf973fe8e500e78cc310d7c8705cdb34328bf80e24f0385fce5845c33bc7943cf6b11b02348a23da0bf6428e57c05135f2dc6bd7c1ce325d666d5a5fd2fd5e410011010001889f04180102000905025331ce82021b0c000a0910a401d9f09a34f7c0418003fe34feafcbeaef348a800a0d908a7a6809cc7304017d820f70f0474d5e23cb17e38b67dc6dca282c6ca00961f4ec9edf2738d0f087b1d81e4871ef08e1798010863afb4eac4c44a376cb343be929c5be66a78cfd4456ae9ec6a99d97f4e1c3ff3583351db2147a65c0acef5c003fb544ab3a2e2dc4d43646f58b811a6c3a369d1f" diff --git a/vendor/golang.org/x/crypto/ssh/client_auth_test.go b/vendor/golang.org/x/crypto/ssh/client_auth_test.go index 145b57a2..a6b8b999 100644 --- a/vendor/golang.org/x/crypto/ssh/client_auth_test.go +++ b/vendor/golang.org/x/crypto/ssh/client_auth_test.go @@ -614,8 +614,8 @@ func TestClientAuthErrorList(t *testing.T) { for i, e := range authErrs.Errors { switch i { case 0: - if e.Error() != "no auth passed yet" { - t.Fatalf("errors: got %v, want no auth passed yet", e.Error()) + if _, ok := e.(*NoAuthError); !ok { + t.Fatalf("errors: got error type %T, want NoAuthError", e) } case 1: if e != publicKeyErr { diff --git a/vendor/golang.org/x/crypto/ssh/server.go b/vendor/golang.org/x/crypto/ssh/server.go index b83d4738..f40657d3 100644 --- a/vendor/golang.org/x/crypto/ssh/server.go +++ b/vendor/golang.org/x/crypto/ssh/server.go @@ -309,6 +309,14 @@ func (l ServerAuthError) Error() string { return "[" + strings.Join(errs, ", ") + "]" } +// NoAuthError is the unique error that is returned if no authentication method +// has been passed yet +type NoAuthError struct{} + +func (e *NoAuthError) Error() string { + return "no auth passed yet" +} + func (s *connection) serverAuthenticate(config *ServerConfig) (*Permissions, error) { sessionID := s.transport.getSessionID() var cache pubKeyCache @@ -363,7 +371,7 @@ userAuthLoop: } perms = nil - authErr := errors.New("no auth passed yet") + authErr := error(&NoAuthError{}) switch userAuthReq.Method { case "none": diff --git a/vendor/golang.org/x/crypto/ssh/sshpiper.go b/vendor/golang.org/x/crypto/ssh/sshpiper.go index c6f2f9d4..95385357 100644 --- a/vendor/golang.org/x/crypto/ssh/sshpiper.go +++ b/vendor/golang.org/x/crypto/ssh/sshpiper.go @@ -14,17 +14,38 @@ import ( type AuthPipeType int const ( + // Do nothing but pass auth message to upstream AuthPipeTypePassThrough AuthPipeType = iota + + // Convert auth message to AuthMetod return by callback and pass it to upstream AuthPipeTypeMap + + // Discard auth message, do not pass it to uptream AuthPipeTypeDiscard + + // Convert auth message to NoneAuth and pass it to upstream AuthPipeTypeNone ) +// SSHPiperAuthPipe: +// Convert Auth +// Any Auth to Password +// +// Any Auth to Public Key +// SSHPiper will sign the auth packet message using the returned Signer. +// This func might be called twice, one is for query message, the other +// is real auth packet message. +// If any error occurs during this period, a NoneAuth packet will be sent to +// upstream ssh server instead. +// +// More info: https://github.com/tg123/sshpiper#publickey-sign-again type SSHPiperAuthPipe struct { + // Username to upstream User string PasswordCallback func(conn ConnMetadata, password []byte) (AuthPipeType, AuthMethod, error) + // PublicKeyCallback, if non-nil, is called when downstream requests a publickey auth. PublicKeyCallback func(conn ConnMetadata, key PublicKey) (AuthPipeType, AuthMethod, error) // HostKeyCallback is called during the cryptographic @@ -55,16 +76,12 @@ type SSHPiperConfig struct { // If any error occurs, the piped connection will be closed. FindUpstream func(conn ConnMetadata) (net.Conn, *SSHPiperAuthPipe, error) - // MapPublicKey, if non-nil, is called when downstream requests a publickey auth. - // SSHPiper will sign the auth packet message using the returned Signer. - // This func might be called twice, one is for query message, the other - // is real auth packet message. - // If any error occurs during this period, a NoneAuth packet will be sent to - // upstream ssh server instead. - // - // More info: https://github.com/tg123/sshpiper#publickey-sign-again - // MapPublicKey func(conn ConnMetadata, key PublicKey) (Signer, error) - + // ServerVersion is the version identification string to announce in + // the public handshake. + // If empty, a reasonable default is used. + // Note that RFC 4253 section 4.2 requires that this string start with + // "SSH-2.0-". + ServerVersion string } type upstream struct{ *connection } @@ -151,14 +168,10 @@ func NewSSHPiperConn(conn net.Conn, piper *SSHPiperConfig) (pipe *SSHPiperConn, return nil, errors.New("sshpiper: must specify FindUpstream") } - // TODO - //if piper.UpstreamHostKeyCallback == nil { - // return nil, errors.New("sshpiper: must specify UpstreamHostKeyCallback") - //} - d, err := newDownstream(conn, &ServerConfig{ - Config: piper.Config, - hostKeys: piper.hostKeys, + Config: piper.Config, + hostKeys: piper.hostKeys, + ServerVersion: piper.ServerVersion, }) if err != nil { return nil, err @@ -410,26 +423,26 @@ func (pipe *pipedConn) ack(key PublicKey) error { } // not used after method to method map enable -func (pipe *pipedConn) validAndAck(user string, upKey, downKey PublicKey) (*userAuthRequestMsg, error) { - - ok, err := validateKey(upKey, user, pipe.upstream.transport) - - if ok { - - if err = pipe.ack(downKey); err != nil { - return nil, err - } - - return nil, nil - } - - return noneAuthMsg(user), nil -} +//func (pipe *pipedConn) validAndAck(user string, upKey, downKey PublicKey) (*userAuthRequestMsg, error) { +// +// ok, err := validateKey(upKey, user, pipe.upstream.transport) +// +// if ok { +// +// if err = pipe.ack(downKey); err != nil { +// return nil, err +// } +// +// return nil, nil +// } +// +// return noneAuthMsg(user), nil +//} func (pipe *pipedConn) checkPublicKey(msg *userAuthRequestMsg, pubkey PublicKey, sig *Signature) (bool, error) { if !isAcceptableAlgo(sig.Format) { - return false, nil + return false, fmt.Errorf("ssh: algorithm %q not accepted", sig.Format) } signedData := buildDataSignedForAuth(pipe.downstream.transport.getSessionID(), *msg, []byte(pubkey.Type()), pubkey.Marshal()) @@ -562,6 +575,41 @@ func (pipe *pipedConn) Close() { pipe.downstream.transport.Close() } +func (pipe *pipedConn) pipeAuthSkipBanner(packet []byte) (bool, error) { + // pipe to auth succ if not a authreq + // typically, authinfo see RFC 4256 + // TODO support hook this msg + err := pipe.upstream.transport.writePacket(packet) + if err != nil { + return false, err + } + + for { + packet, err := pipe.upstream.transport.readPacket() + if err != nil { + return false, err + } + + msgType := packet[0] + + if err = pipe.downstream.transport.writePacket(packet); err != nil { + return false, err + } + + switch msgType { + case msgUserAuthSuccess: + return true, nil + case msgUserAuthBanner: + // should read another packet from upstream + continue + case msgUserAuthFailure: + default: + } + + return false, nil + } +} + func (pipe *pipedConn) pipeAuth(initUserAuthMsg *userAuthRequestMsg) error { err := pipe.upstream.sendAuthReq() if err != nil { @@ -580,61 +628,42 @@ func (pipe *pipedConn) pipeAuth(initUserAuthMsg *userAuthRequestMsg) error { // nil for ignore if userAuthMsg != nil { - err = pipe.upstream.transport.writePacket(Marshal(userAuthMsg)) + // send a mapped auth msg + succ, err := pipe.pipeAuthSkipBanner(Marshal(userAuthMsg)) + if err != nil { return err } - packet, err := pipe.upstream.transport.readPacket() - if err != nil { - return err - } - - success := packet[0] == msgUserAuthSuccess || packet[0] == msgUserAuthBanner - - if err = pipe.downstream.transport.writePacket(packet); err != nil { - return err - } - - if success { + if succ { return nil } + } var packet []byte for { + // find next msg which need to be hooked if packet, err = pipe.downstream.transport.readPacket(); err != nil { return err } // we can only handle auth req at the moment if packet[0] == msgUserAuthRequest { + // should hook, deal with it break } - // pipe to auth succ if not a authreq - // typically, authinfo see RFC 4256 - // TODO support hook this msg - err = pipe.upstream.transport.writePacket(packet) + // pipe other auth msg + succ, err := pipe.pipeAuthSkipBanner(packet) + if err != nil { return err } - // TODO clean up dup code - packet, err := pipe.upstream.transport.readPacket() - if err != nil { - return err - } - - success := packet[0] == msgUserAuthSuccess || packet[0] == msgUserAuthBanner - - if err = pipe.downstream.transport.writePacket(packet); err != nil { - return err - } - - if success { + if succ { return nil } } @@ -646,7 +675,6 @@ func (pipe *pipedConn) pipeAuth(initUserAuthMsg *userAuthRequestMsg) error { } userAuthMsg = &userAuthReq - } } @@ -756,7 +784,11 @@ func (s *connection) serverHandshakeNoAuth(config *ServerConfig) (*Permissions, } var err error - s.serverVersion = []byte("SSH-2.0-SSHPiper") + if config.ServerVersion != "" { + s.serverVersion = []byte(config.ServerVersion) + } else { + s.serverVersion = []byte("SSH-2.0-SSHPiper") + } s.clientVersion, err = exchangeVersions(s.sshConn.conn, s.serverVersion) if err != nil { return nil, err diff --git a/vendor/golang.org/x/crypto/ssh/sshpiper_test.go b/vendor/golang.org/x/crypto/ssh/sshpiper_test.go index b36a236c..2442b976 100644 --- a/vendor/golang.org/x/crypto/ssh/sshpiper_test.go +++ b/vendor/golang.org/x/crypto/ssh/sshpiper_test.go @@ -364,6 +364,7 @@ func TestPiperPasswordToMapPublicKey(t *testing.T) { func TestPiperServerWithBanner(t *testing.T) { const username = "testuser" + const mappedname = "mappedname" var called bool @@ -375,15 +376,19 @@ func TestPiperServerWithBanner(t *testing.T) { s, err := dialUpstream(simpleEchoHandler, &ServerConfig{ PasswordCallback: func(conn ConnMetadata, password []byte) (*Permissions, error) { + if mappedname != conn.User() { + t.Errorf("username changed after banner") + } + called = true return nil, nil }, BannerCallback: func(conn ConnMetadata) string { - called = true return "banner" }, }, t) return s, &SSHPiperAuthPipe{ + User: mappedname, UpstreamHostKeyCallback: InsecureIgnoreHostKey(), }, err },