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