crypto/ssh: return unexpected msg error when server fails keyboard-in… · golang/crypto@28c1119 (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
``
`@@ -1282,3 +1283,147 @@ 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
`+
// Start testserver
`
``
1291
`+
dst, err := func() (string, error) {
`
``
1292
`+
var serverAddr string
`
``
1293
`+
var serverErr error
`
``
1294
`+
var wg sync.WaitGroup
`
``
1295
`+
wg.Add(1)
`
``
1296
+
``
1297
`+
go func() {
`
``
1298
`+
config := &ServerConfig{
`
``
1299
`+
MaxAuthTries: maxAuthTries,
`
``
1300
`+
KeyboardInteractiveCallback: func(c ConnMetadata,
`
``
1301
`+
client KeyboardInteractiveChallenge) (*Permissions, error) {
`
``
1302
`+
// Fail keyboard-interactive authentication early before
`
``
1303
`+
// any prompt is sent to client.
`
``
1304
`+
return nil, errors.New("keyboard-interactive auth failed")
`
``
1305
`+
},
`
``
1306
`+
PasswordCallback: func(c ConnMetadata,
`
``
1307
`+
pass []byte) (*Permissions, error) {
`
``
1308
`+
if string(pass) == clientPassword {
`
``
1309
`+
return nil, nil
`
``
1310
`+
}
`
``
1311
`+
return nil, errors.New("password auth failed")
`
``
1312
`+
},
`
``
1313
`+
}
`
``
1314
+
``
1315
`+
// Use a static hostkey.
`
``
1316
`+
// This key has been generated with following ssh-keygen command
`
``
1317
`+
// and used exclusively in this unit test:
`
``
1318
`+
// $ ssh-keygen -t RSA -b 2048 -f /tmp/static_hostkey \
`
``
1319
`+
// -C "Static RSA hostkey for golang.org/x/crypto/ssh unit test"
`
``
1320
+
``
1321
`` +
const privKeyData = `-----BEGIN OPENSSH PRIVATE KEY-----
``
``
1322
`+
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn
`
``
1323
`+
NhAAAAAwEAAQAAAQEAsg9ZsQ3vbWppRLe2NzzUIV5NcPbpO5EBvLyzfItURKmYHmwa6aoy
`
``
1324
`+
P34fmEG3BVVx5f1pgw54Rdaic4hG2p2nvGIijTktDxFz+tREwwMfywpwrlJbGslUTi0TKO
`
``
1325
`+
jTWkyDACjMwo65yXbsSZLq+8rGD3uinf3Vq1bVlaEckmClhWMLTsynr/YpdF2I/+InPCep
`
``
1326
`+
1AuaWj1dHFNL8fbWXd8xNONumkMS1i6xtP3PnzdUqN+DuoGy26x5ic3qxWVrUp69/J2J42
`
``
1327
`+
/B0WEYbATAfCQiL8iGeeM7Ll45GASI4r93uDnXropnHQy+RThG5BFBRiAqmzN6kncri/k5
`
``
1328
`+
65p63Jb33QAAA/AX6WXzF+ll8wAAAAdzc2gtcnNhAAABAQCyD1mxDe9tamlEt7Y3PNQhXk
`
``
1329
`+
1w9uk7kQG8vLN8i1REqZgebBrpqjI/fh+YQbcFVXHl/WmDDnhF1qJziEbanae8YiKNOS0P
`
``
1330
`+
EXP61ETDAx/LCnCuUlsayVROLRMo6NNaTIMAKMzCjrnJduxJkur7ysYPe6Kd/dWrVtWVoR
`
``
1331
`+
ySYKWFYwtOzKev9il0XYj/4ic8J6nUC5paPV0cU0vx9tZd3zE0426aQxLWLrG0/c+fN1So
`
``
1332
`+
34O6gbLbrHmJzerFZWtSnr38nYnjb8HRYRhsBMB8JCIvyIZ54zsuXjkYBIjiv3e4Odeuim
`
``
1333
`+
cdDL5FOEbkEUFGICqbM3qSdyuL+TnrmnrclvfdAAAAAwEAAQAAAQAJjuVjqbnWh8XK2InB
`
``
1334
`+
gVRpziQeEkMG3YvYU9DWuKv3W5s81tTDAk3cNqr/g1eNw75veCD31gkCxrjFtuUGyzu70x
`
``
1335
`+
DDv/P5QRiWuFpQlZRZU+Akm2skjvYllCnZIlZmHIFTutzy/LJgbC/W6zoN9h6Xqi1aicu0
`
``
1336
`+
fN7OP23HNcTs2gNAhzidpDMGOAxdzpcnXeQ3JCFOcv4LSi7TgmJHvLv1AgXQggSHeB8Nf1
`
``
1337
`+
DvS+E86O9Wm6Xj+OKRiEgrRlngNQQ0om9yhLmUMat7Nw3hn2ZSb2+ByaaYuDfQ6FAG9nno
`
``
1338
`+
HjxaqSHF83/8fKXJW/wku6ee3hvjTBNuuvUCLkLF48DBAAAAgQDUV28GyoWTqIR+uOa/4t
`
``
1339
`+
OyFjfTtTdQ6fnLaqxbiwOaPz6SXCiwE6qIEZF5Ll5QK+7tMPDKWcOak2uGaSUHcjaEXVh0
`
``
1340
`+
kaKwFqiFIBY3IGwCuyixjJITl+g+48SrFgLWNrNpwVrw1NOv+iBz+z6SGqcsi5f030qyzv
`
``
1341
`+
O2P2wkSZkQqgAAAIEA5UB0F2+Lh63JHvdoUDZutBvTgrsjpwiReIuy+7WgxeGHe54DaXTY
`
``
1342
`+
HMOORZM6unDRvi6uBBul7ON9Cs20UGeER+ZMA2SKXTicb0UwJuCYKKO8AIlMP0ykyfaF1p
`
``
1343
`+
ZJw9DciKEu92jx+e2MdhEOnIIt1jQ9e5UIMLsI/SicnseTDLUAAACBAMbV19NIEhjLczBp
`
``
1344
`+
MEYSBGDnyN6HWyrHCuCFLSpnHWePd6/apExGE049YRmAgLYaycmnjX9VJRKoumk9zYv1zu
`
``
1345
`+
W9WTuewZVuLjLpOq/4mO5/jOQortL1dUigiiA7ZTGazTFMHwG+fZdfVqgSxbMfEU2rYhND
`
``
1346
`+
S0UghNmRaqbzNl+JAAAAOFN0YXRpYyBSU0EgaG9zdGtleSBmb3IgZ29sYW5nLm9yZy94L2
`
``
1347
`+
NyeXB0by9zc2ggdW5pdCB0ZXN0AQI=
`
``
1348
`` +
-----END OPENSSH PRIVATE KEY-----`
``
``
1349
+
``
1350
`+
private, err := ParsePrivateKey([]byte(privKeyData))
`
``
1351
`+
if err != nil {
`
``
1352
`+
serverErr = err
`
``
1353
`+
wg.Done()
`
``
1354
`+
return
`
``
1355
`+
}
`
``
1356
`+
config.AddHostKey(private)
`
``
1357
+
``
1358
`+
listener, err := net.Listen("tcp", "127.0.0.1:")
`
``
1359
`+
if err != nil {
`
``
1360
`+
serverErr = err
`
``
1361
`+
wg.Done()
`
``
1362
`+
return
`
``
1363
`+
}
`
``
1364
`+
defer listener.Close()
`
``
1365
`+
serverAddr = listener.Addr().String()
`
``
1366
`+
wg.Done()
`
``
1367
+
``
1368
`+
nConn, err := listener.Accept()
`
``
1369
`+
if err != nil {
`
``
1370
`+
return
`
``
1371
`+
}
`
``
1372
+
``
1373
`+
conn, chans, reqs, err := NewServerConn(nConn, config)
`
``
1374
`+
if err != nil {
`
``
1375
`+
return
`
``
1376
`+
}
`
``
1377
`+
_ = conn.Close()
`
``
1378
+
``
1379
`+
var connWg sync.WaitGroup
`
``
1380
`+
connWg.Add(1)
`
``
1381
`+
go func() {
`
``
1382
`+
defer connWg.Done()
`
``
1383
`+
DiscardRequests(reqs)
`
``
1384
`+
}()
`
``
1385
`+
for newChannel := range chans {
`
``
1386
`+
newChannel.Reject(Prohibited,
`
``
1387
`+
"testserver not accepting requests")
`
``
1388
`+
}
`
``
1389
`+
connWg.Wait()
`
``
1390
`+
}()
`
``
1391
+
``
1392
`+
wg.Wait()
`
``
1393
`+
return serverAddr, serverErr
`
``
1394
`+
}()
`
``
1395
`+
if err != nil {
`
``
1396
`+
t.Fatalf("failed to start testserver: %v", err)
`
``
1397
`+
}
`
``
1398
+
``
1399
`+
// Connect to testserver expect KeyboardInteractive() to be not called and
`
``
1400
`+
// PasswordCallback() to be called.
`
``
1401
`+
passwordCallbackCalled := false
`
``
1402
`+
cfg := &ClientConfig{
`
``
1403
`+
User: "testuser",
`
``
1404
`+
Auth: []AuthMethod{
`
``
1405
`+
RetryableAuthMethod(KeyboardInteractive(func(name,
`
``
1406
`+
instruction string, questions []string,
`
``
1407
`+
echos []bool) ([]string, error) {
`
``
1408
`+
t.Errorf("unexpected call to KeyboardInteractive()")
`
``
1409
`+
return []string{clientPassword}, nil
`
``
1410
`+
}), maxAuthTries),
`
``
1411
`+
RetryableAuthMethod(PasswordCallback(func() (secret string,
`
``
1412
`+
err error) {
`
``
1413
`+
t.Logf("PasswordCallback()")
`
``
1414
`+
passwordCallbackCalled = true
`
``
1415
`+
return clientPassword, nil
`
``
1416
`+
}), maxAuthTries),
`
``
1417
`+
},
`
``
1418
`+
HostKeyCallback: InsecureIgnoreHostKey(),
`
``
1419
`+
}
`
``
1420
+
``
1421
`+
conn, _ := Dial("tcp", dst, cfg)
`
``
1422
`+
if conn != nil {
`
``
1423
`+
conn.Close()
`
``
1424
`+
}
`
``
1425
+
``
1426
`+
if !passwordCallbackCalled {
`
``
1427
`+
t.Errorf("expected PasswordCallback() to be called")
`
``
1428
`+
}
`
``
1429
`+
}
`