UNPKG

7.32 kBJavaScriptView Raw
1'use strict';
2
3const assert = require('assert');
4const { inspect } = require('util');
5
6const {
7 fixture,
8 mustCall,
9 mustCallAtLeast,
10 setup: setup_,
11} = require('./common.js');
12
13const debug = false;
14
15const clientCfg = { username: 'foo', password: 'bar' };
16const serverCfg = { hostKeys: [ fixture('ssh_host_rsa_key') ] };
17
18{
19 const { client, server } = setup_(
20 'Exec with OpenSSH agent forwarding',
21 {
22 client: {
23 ...clientCfg,
24 agent: '/path/to/agent',
25 },
26 server: serverCfg,
27
28 debug,
29 },
30 );
31
32 server.on('connection', mustCall((conn) => {
33 conn.on('authentication', mustCall((ctx) => {
34 ctx.accept();
35 })).on('ready', mustCall(() => {
36 conn.on('session', mustCall((accept, reject) => {
37 let sawAuthAgent = false;
38 accept().on('auth-agent', mustCall((accept, reject) => {
39 sawAuthAgent = true;
40 accept && accept();
41 })).on('exec', mustCall((accept, reject, info) => {
42 assert(sawAuthAgent, 'Expected auth-agent before exec');
43 assert(info.command === 'foo --bar',
44 `Wrong exec command: ${info.command}`);
45 const stream = accept();
46 stream.exit(100);
47 stream.end();
48 conn.end();
49 }));
50 }));
51 }));
52 }));
53
54 client.on('ready', mustCall(() => {
55 client.exec('foo --bar', { agentForward: true }, mustCall((err, stream) => {
56 assert(!err, `Unexpected exec error: ${err}`);
57 stream.resume();
58 }));
59 }));
60}
61
62{
63 const { client, server } = setup_(
64 'OpenSSH forwarded UNIX socket connection',
65 {
66 client: clientCfg,
67 server: {
68 ...serverCfg,
69 ident: 'OpenSSH_7.1',
70 },
71
72 debug,
73 },
74 );
75
76 const socketPath = '/foo';
77 const events = [];
78 const expected = [
79 ['client', 'openssh_forwardInStreamLocal'],
80 ['server', 'streamlocal-forward@openssh.com', { socketPath }],
81 ['client', 'forward callback'],
82 ['client', 'unix connection', { socketPath }],
83 ['client', 'socket data', '1'],
84 ['server', 'socket data', '2'],
85 ['client', 'socket end'],
86 ['server', 'cancel-streamlocal-forward@openssh.com', { socketPath }],
87 ['client', 'cancel callback']
88 ];
89
90 server.on('connection', mustCall((conn) => {
91 conn.on('authentication', mustCall((ctx) => {
92 ctx.accept();
93 })).on('ready', mustCall(() => {
94 conn.once('request', mustCall((accept, reject, name, info) => {
95 events.push(['server', name, info]);
96 assert(name === 'streamlocal-forward@openssh.com',
97 `Wrong request name: ${name}`);
98 accept();
99 conn.openssh_forwardOutStreamLocal(socketPath,
100 mustCall((err, ch) => {
101 assert(!err, `Unexpected error: ${err}`);
102 ch.write('1');
103 ch.on('data', mustCallAtLeast((data) => {
104 events.push(['server', 'socket data', data.toString()]);
105 ch.close();
106 }));
107 }));
108
109 conn.on('request', mustCall((accept, reject, name, info) => {
110 events.push(['server', name, info]);
111 assert(name === 'cancel-streamlocal-forward@openssh.com',
112 `Wrong request name: ${name}`);
113 accept();
114 }));
115 }));
116 }));
117 }));
118
119 client.on('ready', mustCall(() => {
120 // request forwarding
121 events.push(['client', 'openssh_forwardInStreamLocal']);
122 client.openssh_forwardInStreamLocal(socketPath, mustCall((err) => {
123 assert(!err, `Unexpected error: ${err}`);
124 events.push(['client', 'forward callback']);
125 }));
126 client.on('unix connection', mustCall((info, accept, reject) => {
127 events.push(['client', 'unix connection', info]);
128 const stream = accept();
129 stream.on('data', mustCallAtLeast((data) => {
130 events.push(['client', 'socket data', data.toString()]);
131 stream.write('2');
132 })).on('end', mustCall(() => {
133 events.push(['client', 'socket end']);
134 client.openssh_unforwardInStreamLocal(socketPath,
135 mustCall((err) => {
136 assert(!err, `Unexpected error: ${err}`);
137 events.push(['client', 'cancel callback']);
138 client.end();
139 }));
140 }));
141 }));
142 })).on('close', mustCall(() => {
143 assert.deepStrictEqual(
144 events,
145 expected,
146 'Events mismatch\n'
147 + `Actual:\n${inspect(events)}\n`
148 + `Expected:\n${inspect(expected)}`
149 );
150 }));
151}
152
153{
154 const { client, server } = setup_(
155 'OpenSSH UNIX socket connection',
156 {
157 client: clientCfg,
158 server: {
159 ...serverCfg,
160 ident: 'OpenSSH_8.0',
161 },
162
163 debug,
164 },
165 );
166
167 const socketPath = '/foo/bar/baz';
168 const response = 'Hello World';
169
170 server.on('connection', mustCall((conn) => {
171 conn.on('authentication', mustCall((ctx) => {
172 ctx.accept();
173 })).on('ready', mustCall(() => {
174 conn.on('openssh.streamlocal', mustCall((accept, reject, info) => {
175 assert.deepStrictEqual(
176 info,
177 { socketPath },
178 `Wrong info: ${inspect(info)}`
179 );
180
181 const stream = accept();
182 stream.on('close', mustCall(() => {
183 client.end();
184 })).end(response);
185 stream.resume();
186 }));
187 }));
188 }));
189
190 client.on('ready', mustCall(() => {
191 client.openssh_forwardOutStreamLocal(socketPath, mustCall((err, stream) => {
192 assert(!err, `Unexpected error: ${err}`);
193 let buf = '';
194 stream.on('data', mustCallAtLeast((data) => {
195 buf += data;
196 })).on('close', mustCall(() => {
197 assert(buf === response, `Wrong response: ${inspect(buf)}`);
198 }));
199 }));
200 }));
201}
202
203{
204 const { client, server } = setup_(
205 'OpenSSH 5.x workaround for binding on port 0',
206 {
207 client: clientCfg,
208 server: {
209 ...serverCfg,
210 ident: 'OpenSSH_5.3',
211 },
212
213 debug,
214 },
215 );
216
217 const boundAddr = 'good';
218 const boundPort = 1337;
219 const tcpInfo = {
220 destIP: boundAddr,
221 destPort: boundPort,
222 srcIP: 'remote',
223 srcPort: 12345,
224 };
225
226 server.on('connection', mustCall((conn) => {
227 conn.on('authentication', mustCall((ctx) => {
228 ctx.accept();
229 })).on('ready', mustCall(() => {
230 conn.on('request', mustCall((accept, reject, name, info) => {
231 assert(name === 'tcpip-forward', `Unexpected request: ${name}`);
232 assert(info.bindAddr === boundAddr, `Wrong addr: ${info.bindAddr}`);
233 assert(info.bindPort === 0, `Wrong port: ${info.bindPort}`);
234 accept(boundPort);
235 conn.forwardOut(boundAddr,
236 0,
237 tcpInfo.srcIP,
238 tcpInfo.srcPort,
239 mustCall((err, ch) => {
240 assert(!err, `Unexpected error: ${err}`);
241 client.end();
242 }));
243 }));
244 }));
245 }));
246
247 client.on('ready', mustCall(() => {
248 // request forwarding
249 client.forwardIn(boundAddr, 0, mustCall((err, port) => {
250 assert(!err, `Unexpected error: ${err}`);
251 assert(port === boundPort, `Bad bound port: ${port}`);
252 }));
253 })).on('tcp connection', mustCall((details, accept, reject) => {
254 assert.deepStrictEqual(
255 details,
256 tcpInfo,
257 `Wrong tcp details: ${inspect(details)}`
258 );
259 accept();
260 }));
261}