ssh: return unexpected msg error when server fails keyboard-interacti… · golang/crypto@7fafc4d (original) (raw)
`@@ -1293,3 +1293,92 @@ func TestCertAuthOpenSSHCompat(t *testing.T) {
`
1293
1293
`t.Fatalf("unable to dial remote side: %s", err)
`
1294
1294
` }
`
1295
1295
`}
`
``
1296
+
``
1297
`+
func TestKeyboardInteractiveAuthEarlyFail(t *testing.T) {
`
``
1298
`+
const maxAuthTries = 2
`
``
1299
+
``
1300
`+
c1, c2, err := netPipe()
`
``
1301
`+
if err != nil {
`
``
1302
`+
t.Fatalf("netPipe: %v", err)
`
``
1303
`+
}
`
``
1304
`+
defer c1.Close()
`
``
1305
`+
defer c2.Close()
`
``
1306
+
``
1307
`+
// Start testserver
`
``
1308
`+
serverConfig := &ServerConfig{
`
``
1309
`+
MaxAuthTries: maxAuthTries,
`
``
1310
`+
KeyboardInteractiveCallback: func(c ConnMetadata,
`
``
1311
`+
client KeyboardInteractiveChallenge) (*Permissions, error) {
`
``
1312
`+
// Fail keyboard-interactive authentication early before
`
``
1313
`+
// any prompt is sent to client.
`
``
1314
`+
return nil, errors.New("keyboard-interactive auth failed")
`
``
1315
`+
},
`
``
1316
`+
PasswordCallback: func(c ConnMetadata,
`
``
1317
`+
pass []byte) (*Permissions, error) {
`
``
1318
`+
if string(pass) == clientPassword {
`
``
1319
`+
return nil, nil
`
``
1320
`+
}
`
``
1321
`+
return nil, errors.New("password auth failed")
`
``
1322
`+
},
`
``
1323
`+
}
`
``
1324
`+
serverConfig.AddHostKey(testSigners["rsa"])
`
``
1325
+
``
1326
`+
serverDone := make(chan struct{})
`
``
1327
`+
go func() {
`
``
1328
`+
defer func() { serverDone <- struct{}{} }()
`
``
1329
`+
conn, chans, reqs, err := NewServerConn(c2, serverConfig)
`
``
1330
`+
if err != nil {
`
``
1331
`+
return
`
``
1332
`+
}
`
``
1333
`+
_ = conn.Close()
`
``
1334
+
``
1335
`+
discarderDone := make(chan struct{})
`
``
1336
`+
go func() {
`
``
1337
`+
defer func() { discarderDone <- struct{}{} }()
`
``
1338
`+
DiscardRequests(reqs)
`
``
1339
`+
}()
`
``
1340
`+
for newChannel := range chans {
`
``
1341
`+
newChannel.Reject(Prohibited,
`
``
1342
`+
"testserver not accepting requests")
`
``
1343
`+
}
`
``
1344
+
``
1345
`+
<-discarderDone
`
``
1346
`+
}()
`
``
1347
+
``
1348
`+
// Connect to testserver, expect KeyboardInteractive() to be not called,
`
``
1349
`+
// PasswordCallback() to be called and connection to succeed.
`
``
1350
`+
passwordCallbackCalled := false
`
``
1351
`+
clientConfig := &ClientConfig{
`
``
1352
`+
User: "testuser",
`
``
1353
`+
Auth: []AuthMethod{
`
``
1354
`+
RetryableAuthMethod(KeyboardInteractive(func(name,
`
``
1355
`+
instruction string, questions []string,
`
``
1356
`+
echos []bool) ([]string, error) {
`
``
1357
`+
t.Errorf("unexpected call to KeyboardInteractive()")
`
``
1358
`+
return []string{clientPassword}, nil
`
``
1359
`+
}), maxAuthTries),
`
``
1360
`+
RetryableAuthMethod(PasswordCallback(func() (secret string,
`
``
1361
`+
err error) {
`
``
1362
`+
t.Logf("PasswordCallback()")
`
``
1363
`+
passwordCallbackCalled = true
`
``
1364
`+
return clientPassword, nil
`
``
1365
`+
}), maxAuthTries),
`
``
1366
`+
},
`
``
1367
`+
HostKeyCallback: InsecureIgnoreHostKey(),
`
``
1368
`+
}
`
``
1369
+
``
1370
`+
conn, _, _, err := NewClientConn(c1, "", clientConfig)
`
``
1371
`+
if err != nil {
`
``
1372
`+
t.Errorf("unexpected NewClientConn() error: %v", err)
`
``
1373
`+
}
`
``
1374
`+
if conn != nil {
`
``
1375
`+
conn.Close()
`
``
1376
`+
}
`
``
1377
+
``
1378
`+
// Wait for server to finish.
`
``
1379
`+
<-serverDone
`
``
1380
+
``
1381
`+
if !passwordCallbackCalled {
`
``
1382
`+
t.Errorf("expected PasswordCallback() to be called")
`
``
1383
`+
}
`
``
1384
`+
}
`