github.com/devops-filetransfer/sshego@v7.0.4+incompatible/server_test.go (about) 1 package sshego 2 3 import ( 4 "context" 5 cryrand "crypto/rand" 6 "fmt" 7 "io" 8 "io/ioutil" 9 "net" 10 "strings" 11 "testing" 12 13 cv "github.com/glycerine/goconvey/convey" 14 "github.com/glycerine/sshego/xendor/github.com/glycerine/xcryptossh" 15 "github.com/glycerine/sshego/xendor/github.com/glycerine/xcryptossh/testdata" 16 ) 17 18 func Test101StartupAndShutdown(t *testing.T) { 19 20 cv.Convey("The -esshd embedded SSHd goroutine should start and stop when requested.", t, func() { 21 cfg, r1 := GenTestConfig() 22 r1() // release the held-open ports. 23 defer TempDirCleanup(cfg.Origdir, cfg.Tempdir) 24 cfg.NewEsshd() 25 ctx := context.Background() 26 27 cfg.Esshd.Start(ctx) 28 cfg.Esshd.Stop() 29 <-cfg.Esshd.Halt.DoneChan() 30 cv.So(true, cv.ShouldEqual, true) // we should get here. 31 }) 32 } 33 34 func Test102SSHdRequiresTripleAuth(t *testing.T) { 35 36 cv.Convey("The -esshd should require triple auth: RSA key, password, and one-time-passowrd, not any (proper) subset of only two", t, func() { 37 38 srvCfg, r1 := GenTestConfig() 39 cliCfg, r2 := GenTestConfig() 40 41 // now that we have all different ports, we 42 // must release them for use below. 43 r1() 44 r2() 45 defer TempDirCleanup(srvCfg.Origdir, srvCfg.Tempdir) 46 srvCfg.NewEsshd() 47 ctx := context.Background() 48 halt := ssh.NewHalter() 49 50 srvCfg.Esshd.Start(ctx) 51 // create a new acct 52 mylogin := "bob" 53 myemail := "bob@example.com" 54 fullname := "Bob Fakey McFakester" 55 pw := fmt.Sprintf("%x", string(CryptoRandBytes(30))) 56 57 p("srvCfg.HostDb = %#v", srvCfg.HostDb) 58 toptPath, qrPath, rsaPath, err := srvCfg.HostDb.AddUser( 59 mylogin, myemail, pw, "gosshtun", fullname, "") 60 61 cv.So(err, cv.ShouldBeNil) 62 63 cv.So(strings.HasPrefix(toptPath, srvCfg.Tempdir), cv.ShouldBeTrue) 64 cv.So(strings.HasPrefix(qrPath, srvCfg.Tempdir), cv.ShouldBeTrue) 65 cv.So(strings.HasPrefix(rsaPath, srvCfg.Tempdir), cv.ShouldBeTrue) 66 67 pp("toptPath = %v", toptPath) 68 pp("qrPath = %v", qrPath) 69 pp("rsaPath = %v", rsaPath) 70 71 // try to login to esshd 72 73 // need an ssh client 74 75 // allow server to be discovered 76 cliCfg.AddIfNotKnown = true 77 cliCfg.TestAllowOneshotConnect = true 78 79 totpUrl, err := ioutil.ReadFile(toptPath) 80 panicOn(err) 81 totp := string(totpUrl) 82 83 // tell the client not to run an esshd 84 cliCfg.EmbeddedSSHd.Addr = "" 85 //cliCfg.LocalToRemote.Listen.Addr = "" 86 rev := cliCfg.RemoteToLocal.Listen.Addr 87 cliCfg.RemoteToLocal.Listen.Addr = "" 88 89 _, _, err = cliCfg.SSHConnect(ctx, cliCfg.KnownHosts, mylogin, rsaPath, 90 srvCfg.EmbeddedSSHd.Host, srvCfg.EmbeddedSSHd.Port, pw, totp, halt) 91 // we should be able to login, but then the sshd should 92 // reject the port forwarding request. 93 // 94 // Anyway, forward request denies does indicate we 95 // logged in when all three (RSA, TOTP, passphrase) 96 // were given. 97 pp("err is %#v", err) 98 // should have succeeded in logging in 99 cv.So(err, cv.ShouldBeNil) 100 101 // try with only 2 of the 3: 102 fmt.Printf("\n test with only 2 of the required 3 auth...\n") 103 cliCfg.AddIfNotKnown = false 104 _, _, err = cliCfg.SSHConnect(ctx, cliCfg.KnownHosts, mylogin, rsaPath, 105 srvCfg.EmbeddedSSHd.Host, srvCfg.EmbeddedSSHd.Port, pw, "", halt) 106 cv.So(err.Error(), cv.ShouldContainSubstring, "ssh: unable to authenticate") 107 108 _, _, err = cliCfg.SSHConnect(ctx, cliCfg.KnownHosts, mylogin, rsaPath, 109 srvCfg.EmbeddedSSHd.Host, srvCfg.EmbeddedSSHd.Port, "", totp, halt) 110 cv.So(err.Error(), cv.ShouldContainSubstring, "ssh: unable to authenticate") 111 112 _, _, err = cliCfg.SSHConnect(ctx, cliCfg.KnownHosts, mylogin, "", 113 srvCfg.EmbeddedSSHd.Host, srvCfg.EmbeddedSSHd.Port, pw, totp, halt) 114 cv.So(err.Error(), cv.ShouldContainSubstring, "ssh: unable to authenticate") 115 116 fmt.Printf("\n and test with only one auth method...\n") 117 _, _, err = cliCfg.SSHConnect(ctx, cliCfg.KnownHosts, mylogin, rsaPath, 118 srvCfg.EmbeddedSSHd.Host, srvCfg.EmbeddedSSHd.Port, "", "", halt) 119 cv.So(err.Error(), cv.ShouldContainSubstring, "ssh: unable to authenticate") 120 121 _, _, err = cliCfg.SSHConnect(ctx, cliCfg.KnownHosts, mylogin, "", 122 srvCfg.EmbeddedSSHd.Host, srvCfg.EmbeddedSSHd.Port, "", totp, halt) 123 cv.So(err.Error(), cv.ShouldContainSubstring, "ssh: unable to authenticate") 124 125 _, _, err = cliCfg.SSHConnect(ctx, cliCfg.KnownHosts, mylogin, "", 126 srvCfg.EmbeddedSSHd.Host, srvCfg.EmbeddedSSHd.Port, pw, "", halt) 127 cv.So(err.Error(), cv.ShouldContainSubstring, "ssh: unable to authenticate") 128 129 fmt.Printf("\n and test with zero auth methods...\n") 130 _, _, err = cliCfg.SSHConnect(ctx, cliCfg.KnownHosts, mylogin, "", 131 srvCfg.EmbeddedSSHd.Host, srvCfg.EmbeddedSSHd.Port, "", "", halt) 132 cv.So(err.Error(), cv.ShouldContainSubstring, "ssh: unable to authenticate") 133 134 fmt.Printf("\n test that reverse forwarding is denied by our sshd... even if all 3 proper auth is given\n") 135 cliCfg.RemoteToLocal.Listen.Addr = rev 136 _, _, err = cliCfg.SSHConnect(ctx, cliCfg.KnownHosts, mylogin, rsaPath, 137 srvCfg.EmbeddedSSHd.Host, srvCfg.EmbeddedSSHd.Port, pw, totp, halt) 138 cv.So(err.Error(), cv.ShouldEqual, "StartupReverseListener failed: ssh: tcpip-forward request denied by peer") 139 fmt.Printf("\n excellent: as expected, err was '%s'\n", err) 140 141 // done with testing, cleanup 142 halt.RequestStop() 143 halt.MarkDone() 144 srvCfg.Esshd.Stop() 145 <-srvCfg.Esshd.Halt.DoneChan() 146 cv.So(true, cv.ShouldEqual, true) // we should get here. 147 }) 148 } 149 150 // from ~/go/src/github.com/glycerine/xcryptossh/testdata_test.go : init() function. 151 152 // Copyright 2014 The Go Authors. All rights reserved. 153 // Use of this source code is governed by a BSD-style 154 // license that can be found in the LICENSE file. 155 156 type server struct { 157 *ssh.ServerConn 158 chans <-chan ssh.NewChannel 159 } 160 161 func newServer(ctx context.Context, c net.Conn, conf *ssh.ServerConfig) (*server, error) { 162 sconn, chans, reqs, err := ssh.NewServerConn(ctx, c, conf) 163 if err != nil { 164 return nil, err 165 } 166 go ssh.DiscardRequests(ctx, reqs, nil) 167 return &server{sconn, chans}, nil 168 } 169 170 // CertTimeInfinity can be used for 171 // OpenSSHCertV01.ValidBefore to indicate that 172 // a certificate does not expire. 173 const CertTimeInfinity = 1<<64 - 1 174 175 func (a *AuthState) InitTestData() error { 176 var err error 177 178 n := len(testdata.PEMBytes) 179 a.PrivateKeys = make(map[string]interface{}, n) 180 a.Signers = make(map[string]ssh.Signer, n) 181 a.PublicKeys = make(map[string]ssh.PublicKey, n) 182 for t, k := range testdata.PEMBytes { 183 a.PrivateKeys[t], err = ssh.ParseRawPrivateKey(k) 184 if err != nil { 185 panic(fmt.Sprintf("Unable to parse test key %s: %v", t, err)) 186 } 187 a.Signers[t], err = ssh.NewSignerFromKey(a.PrivateKeys[t]) 188 if err != nil { 189 panic(fmt.Sprintf("Unable to create signer for test key %s: %v", t, err)) 190 } 191 a.PublicKeys[t] = a.Signers[t].PublicKey() 192 } 193 194 nonce := make([]byte, 32) 195 if _, err := io.ReadFull(cryrand.Reader, nonce); err != nil { 196 return err 197 } 198 199 // Create a cert and sign it for use in tests. 200 a.Cert = &ssh.Certificate{ 201 Nonce: nonce, 202 ValidPrincipals: []string{"gopher1", "gopher2"}, // increases test coverage 203 ValidAfter: 0, // unix epoch 204 ValidBefore: ssh.CertTimeInfinity, // The end of currently representable time. 205 Reserved: []byte{}, // To pass reflect.DeepEqual after marshal & parse, this must be non-nil 206 Key: a.PublicKeys["ecdsa"], 207 SignatureKey: a.PublicKeys["rsa"], 208 Permissions: ssh.Permissions{ 209 CriticalOptions: map[string]string{}, 210 Extensions: map[string]string{}, 211 }, 212 } 213 a.Cert.SignCert(cryrand.Reader, a.Signers["rsa"]) 214 a.PrivateKeys["cert"] = a.PrivateKeys["ecdsa"] 215 a.Signers["cert"], err = ssh.NewCertSigner(a.Cert, a.Signers["ecdsa"]) 216 if err != nil { 217 panic(fmt.Sprintf("Unable to create certificate signer: %v", err)) 218 } 219 return nil 220 }