github.com/deis/deis@v1.13.5-0.20170519182049-1d9e59fbdbfc/Godeps/_workspace/src/golang.org/x/crypto/ssh/client_auth_test.go (about) 1 // Copyright 2011 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package ssh 6 7 import ( 8 "bytes" 9 "crypto/rand" 10 "errors" 11 "fmt" 12 "strings" 13 "testing" 14 ) 15 16 type keyboardInteractive map[string]string 17 18 func (cr keyboardInteractive) Challenge(user string, instruction string, questions []string, echos []bool) ([]string, error) { 19 var answers []string 20 for _, q := range questions { 21 answers = append(answers, cr[q]) 22 } 23 return answers, nil 24 } 25 26 // reused internally by tests 27 var clientPassword = "tiger" 28 29 // tryAuth runs a handshake with a given config against an SSH server 30 // with config serverConfig 31 func tryAuth(t *testing.T, config *ClientConfig) error { 32 c1, c2, err := netPipe() 33 if err != nil { 34 t.Fatalf("netPipe: %v", err) 35 } 36 defer c1.Close() 37 defer c2.Close() 38 39 certChecker := CertChecker{ 40 IsAuthority: func(k PublicKey) bool { 41 return bytes.Equal(k.Marshal(), testPublicKeys["ecdsa"].Marshal()) 42 }, 43 UserKeyFallback: func(conn ConnMetadata, key PublicKey) (*Permissions, error) { 44 if conn.User() == "testuser" && bytes.Equal(key.Marshal(), testPublicKeys["rsa"].Marshal()) { 45 return nil, nil 46 } 47 48 return nil, fmt.Errorf("pubkey for %q not acceptable", conn.User()) 49 }, 50 IsRevoked: func(c *Certificate) bool { 51 return c.Serial == 666 52 }, 53 } 54 55 serverConfig := &ServerConfig{ 56 PasswordCallback: func(conn ConnMetadata, pass []byte) (*Permissions, error) { 57 if conn.User() == "testuser" && string(pass) == clientPassword { 58 return nil, nil 59 } 60 return nil, errors.New("password auth failed") 61 }, 62 PublicKeyCallback: certChecker.Authenticate, 63 KeyboardInteractiveCallback: func(conn ConnMetadata, challenge KeyboardInteractiveChallenge) (*Permissions, error) { 64 ans, err := challenge("user", 65 "instruction", 66 []string{"question1", "question2"}, 67 []bool{true, true}) 68 if err != nil { 69 return nil, err 70 } 71 ok := conn.User() == "testuser" && ans[0] == "answer1" && ans[1] == "answer2" 72 if ok { 73 challenge("user", "motd", nil, nil) 74 return nil, nil 75 } 76 return nil, errors.New("keyboard-interactive failed") 77 }, 78 AuthLogCallback: func(conn ConnMetadata, method string, err error) { 79 t.Logf("user %q, method %q: %v", conn.User(), method, err) 80 }, 81 } 82 serverConfig.AddHostKey(testSigners["rsa"]) 83 84 go newServer(c1, serverConfig) 85 _, _, _, err = NewClientConn(c2, "", config) 86 return err 87 } 88 89 func TestClientAuthPublicKey(t *testing.T) { 90 config := &ClientConfig{ 91 User: "testuser", 92 Auth: []AuthMethod{ 93 PublicKeys(testSigners["rsa"]), 94 }, 95 } 96 if err := tryAuth(t, config); err != nil { 97 t.Fatalf("unable to dial remote side: %s", err) 98 } 99 } 100 101 func TestAuthMethodPassword(t *testing.T) { 102 config := &ClientConfig{ 103 User: "testuser", 104 Auth: []AuthMethod{ 105 Password(clientPassword), 106 }, 107 } 108 109 if err := tryAuth(t, config); err != nil { 110 t.Fatalf("unable to dial remote side: %s", err) 111 } 112 } 113 114 func TestAuthMethodFallback(t *testing.T) { 115 var passwordCalled bool 116 config := &ClientConfig{ 117 User: "testuser", 118 Auth: []AuthMethod{ 119 PublicKeys(testSigners["rsa"]), 120 PasswordCallback( 121 func() (string, error) { 122 passwordCalled = true 123 return "WRONG", nil 124 }), 125 }, 126 } 127 128 if err := tryAuth(t, config); err != nil { 129 t.Fatalf("unable to dial remote side: %s", err) 130 } 131 132 if passwordCalled { 133 t.Errorf("password auth tried before public-key auth.") 134 } 135 } 136 137 func TestAuthMethodWrongPassword(t *testing.T) { 138 config := &ClientConfig{ 139 User: "testuser", 140 Auth: []AuthMethod{ 141 Password("wrong"), 142 PublicKeys(testSigners["rsa"]), 143 }, 144 } 145 146 if err := tryAuth(t, config); err != nil { 147 t.Fatalf("unable to dial remote side: %s", err) 148 } 149 } 150 151 func TestAuthMethodKeyboardInteractive(t *testing.T) { 152 answers := keyboardInteractive(map[string]string{ 153 "question1": "answer1", 154 "question2": "answer2", 155 }) 156 config := &ClientConfig{ 157 User: "testuser", 158 Auth: []AuthMethod{ 159 KeyboardInteractive(answers.Challenge), 160 }, 161 } 162 163 if err := tryAuth(t, config); err != nil { 164 t.Fatalf("unable to dial remote side: %s", err) 165 } 166 } 167 168 func TestAuthMethodWrongKeyboardInteractive(t *testing.T) { 169 answers := keyboardInteractive(map[string]string{ 170 "question1": "answer1", 171 "question2": "WRONG", 172 }) 173 config := &ClientConfig{ 174 User: "testuser", 175 Auth: []AuthMethod{ 176 KeyboardInteractive(answers.Challenge), 177 }, 178 } 179 180 if err := tryAuth(t, config); err == nil { 181 t.Fatalf("wrong answers should not have authenticated with KeyboardInteractive") 182 } 183 } 184 185 // the mock server will only authenticate ssh-rsa keys 186 func TestAuthMethodInvalidPublicKey(t *testing.T) { 187 config := &ClientConfig{ 188 User: "testuser", 189 Auth: []AuthMethod{ 190 PublicKeys(testSigners["dsa"]), 191 }, 192 } 193 194 if err := tryAuth(t, config); err == nil { 195 t.Fatalf("dsa private key should not have authenticated with rsa public key") 196 } 197 } 198 199 // the client should authenticate with the second key 200 func TestAuthMethodRSAandDSA(t *testing.T) { 201 config := &ClientConfig{ 202 User: "testuser", 203 Auth: []AuthMethod{ 204 PublicKeys(testSigners["dsa"], testSigners["rsa"]), 205 }, 206 } 207 if err := tryAuth(t, config); err != nil { 208 t.Fatalf("client could not authenticate with rsa key: %v", err) 209 } 210 } 211 212 func TestClientHMAC(t *testing.T) { 213 for _, mac := range supportedMACs { 214 config := &ClientConfig{ 215 User: "testuser", 216 Auth: []AuthMethod{ 217 PublicKeys(testSigners["rsa"]), 218 }, 219 Config: Config{ 220 MACs: []string{mac}, 221 }, 222 } 223 if err := tryAuth(t, config); err != nil { 224 t.Fatalf("client could not authenticate with mac algo %s: %v", mac, err) 225 } 226 } 227 } 228 229 // issue 4285. 230 func TestClientUnsupportedCipher(t *testing.T) { 231 config := &ClientConfig{ 232 User: "testuser", 233 Auth: []AuthMethod{ 234 PublicKeys(), 235 }, 236 Config: Config{ 237 Ciphers: []string{"aes128-cbc"}, // not currently supported 238 }, 239 } 240 if err := tryAuth(t, config); err == nil { 241 t.Errorf("expected no ciphers in common") 242 } 243 } 244 245 func TestClientUnsupportedKex(t *testing.T) { 246 config := &ClientConfig{ 247 User: "testuser", 248 Auth: []AuthMethod{ 249 PublicKeys(), 250 }, 251 Config: Config{ 252 KeyExchanges: []string{"diffie-hellman-group-exchange-sha256"}, // not currently supported 253 }, 254 } 255 if err := tryAuth(t, config); err == nil || !strings.Contains(err.Error(), "no common algorithms") { 256 t.Errorf("got %v, expected 'no common algorithms'", err) 257 } 258 } 259 260 func TestClientLoginCert(t *testing.T) { 261 cert := &Certificate{ 262 Key: testPublicKeys["rsa"], 263 ValidBefore: CertTimeInfinity, 264 CertType: UserCert, 265 } 266 cert.SignCert(rand.Reader, testSigners["ecdsa"]) 267 certSigner, err := NewCertSigner(cert, testSigners["rsa"]) 268 if err != nil { 269 t.Fatalf("NewCertSigner: %v", err) 270 } 271 272 clientConfig := &ClientConfig{ 273 User: "user", 274 } 275 clientConfig.Auth = append(clientConfig.Auth, PublicKeys(certSigner)) 276 277 t.Log("should succeed") 278 if err := tryAuth(t, clientConfig); err != nil { 279 t.Errorf("cert login failed: %v", err) 280 } 281 282 t.Log("corrupted signature") 283 cert.Signature.Blob[0]++ 284 if err := tryAuth(t, clientConfig); err == nil { 285 t.Errorf("cert login passed with corrupted sig") 286 } 287 288 t.Log("revoked") 289 cert.Serial = 666 290 cert.SignCert(rand.Reader, testSigners["ecdsa"]) 291 if err := tryAuth(t, clientConfig); err == nil { 292 t.Errorf("revoked cert login succeeded") 293 } 294 cert.Serial = 1 295 296 t.Log("sign with wrong key") 297 cert.SignCert(rand.Reader, testSigners["dsa"]) 298 if err := tryAuth(t, clientConfig); err == nil { 299 t.Errorf("cert login passed with non-authoritive key") 300 } 301 302 t.Log("host cert") 303 cert.CertType = HostCert 304 cert.SignCert(rand.Reader, testSigners["ecdsa"]) 305 if err := tryAuth(t, clientConfig); err == nil { 306 t.Errorf("cert login passed with wrong type") 307 } 308 cert.CertType = UserCert 309 310 t.Log("principal specified") 311 cert.ValidPrincipals = []string{"user"} 312 cert.SignCert(rand.Reader, testSigners["ecdsa"]) 313 if err := tryAuth(t, clientConfig); err != nil { 314 t.Errorf("cert login failed: %v", err) 315 } 316 317 t.Log("wrong principal specified") 318 cert.ValidPrincipals = []string{"fred"} 319 cert.SignCert(rand.Reader, testSigners["ecdsa"]) 320 if err := tryAuth(t, clientConfig); err == nil { 321 t.Errorf("cert login passed with wrong principal") 322 } 323 cert.ValidPrincipals = nil 324 325 t.Log("added critical option") 326 cert.CriticalOptions = map[string]string{"root-access": "yes"} 327 cert.SignCert(rand.Reader, testSigners["ecdsa"]) 328 if err := tryAuth(t, clientConfig); err == nil { 329 t.Errorf("cert login passed with unrecognized critical option") 330 } 331 332 t.Log("allowed source address") 333 cert.CriticalOptions = map[string]string{"source-address": "127.0.0.42/24"} 334 cert.SignCert(rand.Reader, testSigners["ecdsa"]) 335 if err := tryAuth(t, clientConfig); err != nil { 336 t.Errorf("cert login with source-address failed: %v", err) 337 } 338 339 t.Log("disallowed source address") 340 cert.CriticalOptions = map[string]string{"source-address": "127.0.0.42"} 341 cert.SignCert(rand.Reader, testSigners["ecdsa"]) 342 if err := tryAuth(t, clientConfig); err == nil { 343 t.Errorf("cert login with source-address succeeded") 344 } 345 } 346 347 func testPermissionsPassing(withPermissions bool, t *testing.T) { 348 serverConfig := &ServerConfig{ 349 PublicKeyCallback: func(conn ConnMetadata, key PublicKey) (*Permissions, error) { 350 if conn.User() == "nopermissions" { 351 return nil, nil 352 } else { 353 return &Permissions{}, nil 354 } 355 }, 356 } 357 serverConfig.AddHostKey(testSigners["rsa"]) 358 359 clientConfig := &ClientConfig{ 360 Auth: []AuthMethod{ 361 PublicKeys(testSigners["rsa"]), 362 }, 363 } 364 if withPermissions { 365 clientConfig.User = "permissions" 366 } else { 367 clientConfig.User = "nopermissions" 368 } 369 370 c1, c2, err := netPipe() 371 if err != nil { 372 t.Fatalf("netPipe: %v", err) 373 } 374 defer c1.Close() 375 defer c2.Close() 376 377 go NewClientConn(c2, "", clientConfig) 378 serverConn, err := newServer(c1, serverConfig) 379 if err != nil { 380 t.Fatal(err) 381 } 382 if p := serverConn.Permissions; (p != nil) != withPermissions { 383 t.Fatalf("withPermissions is %t, but Permissions object is %#v", withPermissions, p) 384 } 385 } 386 387 func TestPermissionsPassing(t *testing.T) { 388 testPermissionsPassing(true, t) 389 } 390 391 func TestNoPermissionsPassing(t *testing.T) { 392 testPermissionsPassing(false, t) 393 }