1 | 'use strict';
|
2 |
|
3 | const assert = require('assert');
|
4 |
|
5 | const {
|
6 | fixtureKey,
|
7 | mustCall,
|
8 | setup,
|
9 | } = require('./common.js');
|
10 |
|
11 | const debug = false;
|
12 |
|
13 | [
|
14 | { desc: 'RSA user key (old OpenSSH)',
|
15 | hostKey: fixtureKey('id_rsa') },
|
16 | { desc: 'RSA user key (new OpenSSH)',
|
17 | hostKey: fixtureKey('openssh_new_rsa') },
|
18 | { desc: 'DSA host key',
|
19 | hostKey: fixtureKey('ssh_host_dsa_key') },
|
20 | { desc: 'ECDSA host key',
|
21 | hostKey: fixtureKey('ssh_host_ecdsa_key') },
|
22 | { desc: 'PPK',
|
23 | hostKey: fixtureKey('id_rsa.ppk') },
|
24 | ].forEach((test) => {
|
25 | const { desc, hostKey } = test;
|
26 | const clientKey = fixtureKey('openssh_new_rsa');
|
27 | const username = 'KeyUser';
|
28 | const { server } = setup(
|
29 | desc,
|
30 | {
|
31 | client: {
|
32 | username,
|
33 | privateKey: clientKey.raw,
|
34 | algorithms: {
|
35 | serverHostKey: [ hostKey.key.type ],
|
36 | }
|
37 | },
|
38 | server: { hostKeys: [ hostKey.raw ] },
|
39 | debug,
|
40 | }
|
41 | );
|
42 |
|
43 | server.on('connection', mustCall((conn) => {
|
44 | let authAttempt = 0;
|
45 | conn.on('authentication', mustCall((ctx) => {
|
46 | assert(ctx.username === username,
|
47 | `Wrong username: ${ctx.username}`);
|
48 | switch (++authAttempt) {
|
49 | case 1:
|
50 | assert(ctx.method === 'none',
|
51 | `Wrong auth method: ${ctx.method}`);
|
52 | return ctx.reject();
|
53 | case 3:
|
54 | assert(ctx.signature, 'Missing publickey signature');
|
55 |
|
56 | case 2:
|
57 | assert(ctx.method === 'publickey',
|
58 | `Wrong auth method: ${ctx.method}`);
|
59 | assert(ctx.key.algo === clientKey.key.type,
|
60 | `Wrong key algo: ${ctx.key.algo}`);
|
61 | assert.deepStrictEqual(clientKey.key.getPublicSSH(),
|
62 | ctx.key.data,
|
63 | 'Public key mismatch');
|
64 | break;
|
65 | }
|
66 | if (ctx.signature) {
|
67 | assert(clientKey.key.verify(ctx.blob, ctx.signature) === true,
|
68 | 'Could not verify publickey signature');
|
69 | }
|
70 | ctx.accept();
|
71 | }, 3)).on('ready', mustCall(() => {
|
72 | conn.end();
|
73 | }));
|
74 | }));
|
75 | });
|
76 |
|
77 |
|
78 | {
|
79 | const RSA_KEY = fixtureKey('ssh_host_rsa_key');
|
80 | const ECDSA_KEY = fixtureKey('ssh_host_ecdsa_key');
|
81 | [ RSA_KEY, ECDSA_KEY ].forEach((key) => {
|
82 | const selKeyType = key.key.type;
|
83 | const clientKey = fixtureKey('openssh_new_rsa');
|
84 | const username = 'KeyUser';
|
85 | const { client, server } = setup(
|
86 | `Multiple host key types (${key.type} selected)`,
|
87 | {
|
88 | client: {
|
89 | username,
|
90 | privateKey: clientKey.raw,
|
91 | algorithms: {
|
92 | serverHostKey: [ selKeyType ],
|
93 | }
|
94 | },
|
95 | server: { hostKeys: [ RSA_KEY.raw, ECDSA_KEY.raw ] },
|
96 | debug,
|
97 | }
|
98 | );
|
99 |
|
100 | server.on('connection', mustCall((conn) => {
|
101 | let authAttempt = 0;
|
102 | conn.on('authentication', mustCall((ctx) => {
|
103 | assert(ctx.username === username,
|
104 | `Wrong username: ${ctx.username}`);
|
105 | switch (++authAttempt) {
|
106 | case 1:
|
107 | assert(ctx.method === 'none',
|
108 | `Wrong auth method: ${ctx.method}`);
|
109 | return ctx.reject();
|
110 | case 3:
|
111 | assert(ctx.signature, 'Missing publickey signature');
|
112 |
|
113 | case 2:
|
114 | assert(ctx.method === 'publickey',
|
115 | `Wrong auth method: ${ctx.method}`);
|
116 | assert(ctx.key.algo === clientKey.key.type,
|
117 | `Wrong key algo: ${ctx.key.algo}`);
|
118 | assert.deepStrictEqual(clientKey.key.getPublicSSH(),
|
119 | ctx.key.data,
|
120 | 'Public key mismatch');
|
121 | break;
|
122 | }
|
123 | if (ctx.signature) {
|
124 | assert(clientKey.key.verify(ctx.blob, ctx.signature) === true,
|
125 | 'Could not verify publickey signature');
|
126 | }
|
127 | ctx.accept();
|
128 | }, 3)).on('ready', mustCall(() => {
|
129 | conn.end();
|
130 | }));
|
131 | }));
|
132 | client.on('handshake', mustCall((info) => {
|
133 | assert(info.serverHostKey === selKeyType, 'Wrong host key selected');
|
134 | }));
|
135 | });
|
136 | }
|