1 | 'use strict';
|
2 |
|
3 | const assert = require('assert');
|
4 | const { spawnSync } = require('child_process');
|
5 |
|
6 | const debug = false;
|
7 | const SPAWN_OPTS = { windowsHide: true };
|
8 |
|
9 |
|
10 | if (process.platform === 'win32') {
|
11 | console.log('Skipping ssh-agent test on Windows');
|
12 | process.exit(0);
|
13 | }
|
14 |
|
15 | if (process.argv[2] === 'child') {
|
16 | const {
|
17 | fixtureKey,
|
18 | mustCall,
|
19 | setup,
|
20 | } = require('./common.js');
|
21 |
|
22 | const serverCfg = { hostKeys: [ fixtureKey('ssh_host_rsa_key').raw ] };
|
23 |
|
24 | const clientKey = fixtureKey('openssh_new_rsa');
|
25 |
|
26 |
|
27 | {
|
28 | const {
|
29 | error, status
|
30 | } = spawnSync('ssh-add', [ clientKey.fullPath ], SPAWN_OPTS);
|
31 | if (error || status !== 0) {
|
32 | console.error('Failed to add key to agent');
|
33 | process.exit(1);
|
34 | }
|
35 | }
|
36 |
|
37 | const username = 'Agent User';
|
38 | const { server } = setup(
|
39 | 'Agent authentication',
|
40 | {
|
41 | client: { username, agent: process.env.SSH_AUTH_SOCK },
|
42 | server: serverCfg,
|
43 |
|
44 | debug,
|
45 | }
|
46 | );
|
47 |
|
48 | server.on('connection', mustCall((conn) => {
|
49 | let authAttempt = 0;
|
50 | conn.on('authentication', mustCall((ctx) => {
|
51 | assert(ctx.username === username,
|
52 | `Wrong username: ${ctx.username}`);
|
53 | switch (++authAttempt) {
|
54 | case 1:
|
55 | assert(ctx.method === 'none', `Wrong auth method: ${ctx.method}`);
|
56 | return ctx.reject();
|
57 | case 3:
|
58 | assert(ctx.signature, 'Missing publickey signature');
|
59 |
|
60 | case 2:
|
61 | assert(ctx.method === 'publickey',
|
62 | `Wrong auth method: ${ctx.method}`);
|
63 | assert(ctx.key.algo === clientKey.key.type,
|
64 | `Wrong key algo: ${ctx.key.algo}`);
|
65 | assert.deepStrictEqual(clientKey.key.getPublicSSH(),
|
66 | ctx.key.data,
|
67 | 'Public key mismatch');
|
68 | break;
|
69 | }
|
70 | if (ctx.signature) {
|
71 | assert(clientKey.key.verify(ctx.blob, ctx.signature) === true,
|
72 | 'Could not verify publickey signature');
|
73 | }
|
74 | ctx.accept();
|
75 | }, 3)).on('ready', mustCall(() => {
|
76 | conn.end();
|
77 | }));
|
78 | }));
|
79 | } else {
|
80 | {
|
81 | const {
|
82 | error, status
|
83 | } = spawnSync('which', ['ssh-agent'], SPAWN_OPTS);
|
84 |
|
85 | if (error || status !== 0) {
|
86 | console.log('No ssh-agent available, skipping agent test ...');
|
87 | process.exit(0);
|
88 | }
|
89 | }
|
90 |
|
91 | {
|
92 | const {
|
93 | error, status
|
94 | } = spawnSync('which', ['ssh-add'], SPAWN_OPTS);
|
95 |
|
96 | if (error || status !== 0) {
|
97 | console.log('No ssh-add available, skipping agent test ...');
|
98 | process.exit(0);
|
99 | }
|
100 | }
|
101 |
|
102 | const {
|
103 | error, status
|
104 | } = spawnSync('ssh-agent',
|
105 | [ process.execPath, __filename, 'child' ],
|
106 | { ...SPAWN_OPTS, stdio: 'inherit' });
|
107 | if (error || status !== 0)
|
108 | throw new Error('Agent test failed');
|
109 | }
|