ssh: fail keyboard-interactive auth with unexpectedMessageError() whe… · golang/crypto@95b457c (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,146 @@ 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

`+

serverAddr = listener.Addr().String()

`

``

1365

`+

wg.Done()

`

``

1366

+

``

1367

`+

nConn, err := listener.Accept()

`

``

1368

`+

if err != nil {

`

``

1369

`+

return

`

``

1370

`+

}

`

``

1371

+

``

1372

`+

conn, chans, reqs, err := NewServerConn(nConn, config)

`

``

1373

`+

if err != nil {

`

``

1374

`+

return

`

``

1375

`+

}

`

``

1376

`+

_ = conn.Close()

`

``

1377

+

``

1378

`+

var connWg sync.WaitGroup

`

``

1379

`+

connWg.Add(1)

`

``

1380

`+

go func() {

`

``

1381

`+

defer connWg.Done()

`

``

1382

`+

DiscardRequests(reqs)

`

``

1383

`+

}()

`

``

1384

`+

for newChannel := range chans {

`

``

1385

`+

newChannel.Reject(Prohibited,

`

``

1386

`+

"testserver not accepting requests")

`

``

1387

`+

}

`

``

1388

`+

connWg.Wait()

`

``

1389

`+

}()

`

``

1390

+

``

1391

`+

wg.Wait()

`

``

1392

`+

return serverAddr, serverErr

`

``

1393

`+

}()

`

``

1394

`+

if err != nil {

`

``

1395

`+

t.Fatalf("failed to start testserver: %v", err)

`

``

1396

`+

}

`

``

1397

+

``

1398

`+

// Connect to testserver expect KeyboardInteractive() to be not called and

`

``

1399

`+

// PasswordCallback() to be called.

`

``

1400

`+

passwordCallbackCalled := false

`

``

1401

`+

cfg := &ClientConfig{

`

``

1402

`+

User: "testuser",

`

``

1403

`+

Auth: []AuthMethod{

`

``

1404

`+

RetryableAuthMethod(KeyboardInteractive(func(name,

`

``

1405

`+

instruction string, questions []string,

`

``

1406

`+

echos []bool) ([]string, error) {

`

``

1407

`+

t.Errorf("unexpected call to KeyboardInteractive()")

`

``

1408

`+

return []string{clientPassword}, nil

`

``

1409

`+

}), maxAuthTries),

`

``

1410

`+

RetryableAuthMethod(PasswordCallback(func() (secret string,

`

``

1411

`+

err error) {

`

``

1412

`+

t.Logf("PasswordCallback()")

`

``

1413

`+

passwordCallbackCalled = true

`

``

1414

`+

return clientPassword, nil

`

``

1415

`+

}), maxAuthTries),

`

``

1416

`+

},

`

``

1417

`+

HostKeyCallback: InsecureIgnoreHostKey(),

`

``

1418

`+

}

`

``

1419

+

``

1420

`+

conn, _ := Dial("tcp", dst, cfg)

`

``

1421

`+

if conn != nil {

`

``

1422

`+

conn.Close()

`

``

1423

`+

}

`

``

1424

+

``

1425

`+

if !passwordCallbackCalled {

`

``

1426

`+

t.Errorf("expected PasswordCallback() to be called")

`

``

1427

`+

}

`

``

1428

`+

}

`