@@ -15,6 +15,7 @@ import (
15
15
"os"
16
16
"runtime"
17
17
"strings"
18
+ "sync"
18
19
"testing"
19
20
)
20
21
@@ -1282,3 +1283,84 @@ func TestCertAuthOpenSSHCompat(t *testing.T) {
1282
1283
t .Fatalf ("unable to dial remote side: %s" , err )
1283
1284
}
1284
1285
}
1286
+
1287
+ func TestKeyboardInteractiveAuthEarlyFail (t * testing.T ) {
1288
+ const maxAuthTries = 2
1289
+
1290
+ c1 , c2 , err := netPipe ()
1291
+ if err != nil {
1292
+ t .Fatalf ("netPipe: %v" , err )
1293
+ }
1294
+ defer c1 .Close ()
1295
+ defer c2 .Close ()
1296
+
1297
+ // Start testserver
1298
+ go func () {
1299
+ config := & ServerConfig {
1300
+ MaxAuthTries : maxAuthTries ,
1301
+ KeyboardInteractiveCallback : func (c ConnMetadata ,
1302
+ client KeyboardInteractiveChallenge ) (* Permissions , error ) {
1303
+ // Fail keyboard-interactive authentication early before
1304
+ // any prompt is sent to client.
1305
+ return nil , errors .New ("keyboard-interactive auth failed" )
1306
+ },
1307
+ PasswordCallback : func (c ConnMetadata ,
1308
+ pass []byte ) (* Permissions , error ) {
1309
+ if string (pass ) == clientPassword {
1310
+ return nil , nil
1311
+ }
1312
+ return nil , errors .New ("password auth failed" )
1313
+ },
1314
+ }
1315
+ config .AddHostKey (testSigners ["rsa" ])
1316
+
1317
+ conn , chans , reqs , err := NewServerConn (c2 , config )
1318
+ if err != nil {
1319
+ return
1320
+ }
1321
+ _ = conn .Close ()
1322
+
1323
+ var wg sync.WaitGroup
1324
+ wg .Add (1 )
1325
+ go func () {
1326
+ defer wg .Done ()
1327
+ DiscardRequests (reqs )
1328
+ }()
1329
+ for newChannel := range chans {
1330
+ newChannel .Reject (Prohibited ,
1331
+ "testserver not accepting requests" )
1332
+ }
1333
+ wg .Wait ()
1334
+ }()
1335
+
1336
+ // Connect to testserver expect KeyboardInteractive() to be not called and
1337
+ // PasswordCallback() to be called.
1338
+ passwordCallbackCalled := false
1339
+ cfg := & ClientConfig {
1340
+ User : "testuser" ,
1341
+ Auth : []AuthMethod {
1342
+ RetryableAuthMethod (KeyboardInteractive (func (name ,
1343
+ instruction string , questions []string ,
1344
+ echos []bool ) ([]string , error ) {
1345
+ t .Errorf ("unexpected call to KeyboardInteractive()" )
1346
+ return []string {clientPassword }, nil
1347
+ }), maxAuthTries ),
1348
+ RetryableAuthMethod (PasswordCallback (func () (secret string ,
1349
+ err error ) {
1350
+ t .Logf ("PasswordCallback()" )
1351
+ passwordCallbackCalled = true
1352
+ return clientPassword , nil
1353
+ }), maxAuthTries ),
1354
+ },
1355
+ HostKeyCallback : InsecureIgnoreHostKey (),
1356
+ }
1357
+
1358
+ conn , _ , _ , _ := NewClientConn (c1 , "" , cfg )
1359
+ if conn != nil {
1360
+ conn .Close ()
1361
+ }
1362
+
1363
+ if ! passwordCallbackCalled {
1364
+ t .Errorf ("expected PasswordCallback() to be called" )
1365
+ }
1366
+ }
0 commit comments