@@ -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
+ }
0 commit comments