crypto/ssh: return unexpected msg error when server fails keyboard-in… · golang/crypto@f2a8ba2 (original) (raw)
`@@ -15,6 +15,7 @@ import (
`
15
15
`"os"
`
16
16
`"runtime"
`
17
17
`"strings"
`
``
18
`+
"sync"
`
18
19
`"testing"
`
19
20
`)
`
20
21
``
`@@ -1293,3 +1294,84 @@ func TestCertAuthOpenSSHCompat(t *testing.T) {
`
1293
1294
`t.Fatalf("unable to dial remote side: %s", err)
`
1294
1295
` }
`
1295
1296
`}
`
``
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
`+
}
`