@electerm/ssh2 0.8.11 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -1
- package/install.js +20 -0
- package/lib/Channel.js +236 -450
- package/lib/agent.js +1080 -376
- package/lib/client.js +1698 -1258
- package/lib/http-agents.js +72 -51
- package/lib/index.js +43 -0
- package/lib/protocol/Protocol.js +2077 -0
- package/lib/protocol/SFTP.js +3778 -0
- package/lib/protocol/constants.js +342 -0
- package/lib/protocol/crypto/binding.gyp +14 -0
- package/lib/protocol/crypto/poly1305.js +43 -0
- package/lib/protocol/crypto/src/binding.cc +2003 -0
- package/lib/protocol/crypto.js +1602 -0
- package/lib/protocol/handlers.js +16 -0
- package/lib/protocol/handlers.misc.js +1214 -0
- package/lib/protocol/kex.js +1831 -0
- package/lib/protocol/keyParser.js +1481 -0
- package/lib/protocol/node-fs-compat.js +115 -0
- package/lib/protocol/utils.js +356 -0
- package/lib/protocol/zlib.js +255 -0
- package/lib/server.js +1226 -1019
- package/lib/utils.js +336 -0
- package/package.json +42 -9
- package/lib/SFTPWrapper.js +0 -145
- package/lib/buffer-helpers.js +0 -22
- package/lib/keepalivemgr.js +0 -80
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const assert = require('assert');
|
|
4
|
+
const { inspect } = require('util');
|
|
5
|
+
|
|
6
|
+
// Only use this for integers! Decimal numbers do not work with this function.
|
|
7
|
+
function addNumericalSeparator(val) {
|
|
8
|
+
let res = '';
|
|
9
|
+
let i = val.length;
|
|
10
|
+
const start = val[0] === '-' ? 1 : 0;
|
|
11
|
+
for (; i >= start + 4; i -= 3)
|
|
12
|
+
res = `_${val.slice(i - 3, i)}${res}`;
|
|
13
|
+
return `${val.slice(0, i)}${res}`;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function oneOf(expected, thing) {
|
|
17
|
+
assert(typeof thing === 'string', '`thing` has to be of type string');
|
|
18
|
+
if (Array.isArray(expected)) {
|
|
19
|
+
const len = expected.length;
|
|
20
|
+
assert(len > 0, 'At least one expected value needs to be specified');
|
|
21
|
+
expected = expected.map((i) => String(i));
|
|
22
|
+
if (len > 2) {
|
|
23
|
+
return `one of ${thing} ${expected.slice(0, len - 1).join(', ')}, or `
|
|
24
|
+
+ expected[len - 1];
|
|
25
|
+
} else if (len === 2) {
|
|
26
|
+
return `one of ${thing} ${expected[0]} or ${expected[1]}`;
|
|
27
|
+
}
|
|
28
|
+
return `of ${thing} ${expected[0]}`;
|
|
29
|
+
}
|
|
30
|
+
return `of ${thing} ${String(expected)}`;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
exports.ERR_INTERNAL_ASSERTION = class ERR_INTERNAL_ASSERTION extends Error {
|
|
35
|
+
constructor(message) {
|
|
36
|
+
super();
|
|
37
|
+
Error.captureStackTrace(this, ERR_INTERNAL_ASSERTION);
|
|
38
|
+
|
|
39
|
+
const suffix = 'This is caused by either a bug in ssh2 '
|
|
40
|
+
+ 'or incorrect usage of ssh2 internals.\n'
|
|
41
|
+
+ 'Please open an issue with this stack trace at '
|
|
42
|
+
+ 'https://github.com/mscdex/ssh2/issues\n';
|
|
43
|
+
|
|
44
|
+
this.message = (message === undefined ? suffix : `${message}\n${suffix}`);
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const MAX_32BIT_INT = 2 ** 32;
|
|
49
|
+
const MAX_32BIT_BIGINT = (() => {
|
|
50
|
+
try {
|
|
51
|
+
return new Function('return 2n ** 32n')();
|
|
52
|
+
} catch {}
|
|
53
|
+
})();
|
|
54
|
+
exports.ERR_OUT_OF_RANGE = class ERR_OUT_OF_RANGE extends RangeError {
|
|
55
|
+
constructor(str, range, input, replaceDefaultBoolean) {
|
|
56
|
+
super();
|
|
57
|
+
Error.captureStackTrace(this, ERR_OUT_OF_RANGE);
|
|
58
|
+
|
|
59
|
+
assert(range, 'Missing "range" argument');
|
|
60
|
+
let msg = (replaceDefaultBoolean
|
|
61
|
+
? str
|
|
62
|
+
: `The value of "${str}" is out of range.`);
|
|
63
|
+
let received;
|
|
64
|
+
if (Number.isInteger(input) && Math.abs(input) > MAX_32BIT_INT) {
|
|
65
|
+
received = addNumericalSeparator(String(input));
|
|
66
|
+
} else if (typeof input === 'bigint') {
|
|
67
|
+
received = String(input);
|
|
68
|
+
if (input > MAX_32BIT_BIGINT || input < -MAX_32BIT_BIGINT)
|
|
69
|
+
received = addNumericalSeparator(received);
|
|
70
|
+
received += 'n';
|
|
71
|
+
} else {
|
|
72
|
+
received = inspect(input);
|
|
73
|
+
}
|
|
74
|
+
msg += ` It must be ${range}. Received ${received}`;
|
|
75
|
+
|
|
76
|
+
this.message = msg;
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
class ERR_INVALID_ARG_TYPE extends TypeError {
|
|
81
|
+
constructor(name, expected, actual) {
|
|
82
|
+
super();
|
|
83
|
+
Error.captureStackTrace(this, ERR_INVALID_ARG_TYPE);
|
|
84
|
+
|
|
85
|
+
assert(typeof name === 'string', `'name' must be a string`);
|
|
86
|
+
|
|
87
|
+
// determiner: 'must be' or 'must not be'
|
|
88
|
+
let determiner;
|
|
89
|
+
if (typeof expected === 'string' && expected.startsWith('not ')) {
|
|
90
|
+
determiner = 'must not be';
|
|
91
|
+
expected = expected.replace(/^not /, '');
|
|
92
|
+
} else {
|
|
93
|
+
determiner = 'must be';
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
let msg;
|
|
97
|
+
if (name.endsWith(' argument')) {
|
|
98
|
+
// For cases like 'first argument'
|
|
99
|
+
msg = `The ${name} ${determiner} ${oneOf(expected, 'type')}`;
|
|
100
|
+
} else {
|
|
101
|
+
const type = (name.includes('.') ? 'property' : 'argument');
|
|
102
|
+
msg = `The "${name}" ${type} ${determiner} ${oneOf(expected, 'type')}`;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
msg += `. Received type ${typeof actual}`;
|
|
106
|
+
|
|
107
|
+
this.message = msg;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
exports.ERR_INVALID_ARG_TYPE = ERR_INVALID_ARG_TYPE;
|
|
111
|
+
|
|
112
|
+
exports.validateNumber = function validateNumber(value, name) {
|
|
113
|
+
if (typeof value !== 'number')
|
|
114
|
+
throw new ERR_INVALID_ARG_TYPE(name, 'number', value);
|
|
115
|
+
};
|
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const Ber = require('asn1').Ber;
|
|
4
|
+
|
|
5
|
+
let DISCONNECT_REASON;
|
|
6
|
+
|
|
7
|
+
const FastBuffer = Buffer[Symbol.species];
|
|
8
|
+
const TypedArrayFill = Object.getPrototypeOf(Uint8Array.prototype).fill;
|
|
9
|
+
|
|
10
|
+
function readUInt32BE(buf, offset) {
|
|
11
|
+
return (buf[offset++] * 16777216)
|
|
12
|
+
+ (buf[offset++] * 65536)
|
|
13
|
+
+ (buf[offset++] * 256)
|
|
14
|
+
+ buf[offset];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function bufferCopy(src, dest, srcStart, srcEnd, destStart) {
|
|
18
|
+
if (!destStart)
|
|
19
|
+
destStart = 0;
|
|
20
|
+
if (srcEnd > src.length)
|
|
21
|
+
srcEnd = src.length;
|
|
22
|
+
let nb = srcEnd - srcStart;
|
|
23
|
+
const destLeft = (dest.length - destStart);
|
|
24
|
+
if (nb > destLeft)
|
|
25
|
+
nb = destLeft;
|
|
26
|
+
dest.set(new Uint8Array(src.buffer, src.byteOffset + srcStart, nb),
|
|
27
|
+
destStart);
|
|
28
|
+
return nb;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function bufferSlice(buf, start, end) {
|
|
32
|
+
if (end === undefined)
|
|
33
|
+
end = buf.length;
|
|
34
|
+
return new FastBuffer(buf.buffer, buf.byteOffset + start, end - start);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function makeBufferParser() {
|
|
38
|
+
let pos = 0;
|
|
39
|
+
let buffer;
|
|
40
|
+
|
|
41
|
+
const self = {
|
|
42
|
+
init: (buf, start) => {
|
|
43
|
+
buffer = buf;
|
|
44
|
+
pos = (typeof start === 'number' ? start : 0);
|
|
45
|
+
},
|
|
46
|
+
pos: () => pos,
|
|
47
|
+
length: () => (buffer ? buffer.length : 0),
|
|
48
|
+
avail: () => (buffer && pos < buffer.length ? buffer.length - pos : 0),
|
|
49
|
+
clear: () => {
|
|
50
|
+
buffer = undefined;
|
|
51
|
+
},
|
|
52
|
+
readUInt32BE: () => {
|
|
53
|
+
if (!buffer || pos + 3 >= buffer.length)
|
|
54
|
+
return;
|
|
55
|
+
return (buffer[pos++] * 16777216)
|
|
56
|
+
+ (buffer[pos++] * 65536)
|
|
57
|
+
+ (buffer[pos++] * 256)
|
|
58
|
+
+ buffer[pos++];
|
|
59
|
+
},
|
|
60
|
+
readUInt64BE: (behavior) => {
|
|
61
|
+
if (!buffer || pos + 7 >= buffer.length)
|
|
62
|
+
return;
|
|
63
|
+
switch (behavior) {
|
|
64
|
+
case 'always':
|
|
65
|
+
return BigInt(`0x${buffer.hexSlice(pos, pos += 8)}`);
|
|
66
|
+
case 'maybe':
|
|
67
|
+
if (buffer[pos] > 0x1F)
|
|
68
|
+
return BigInt(`0x${buffer.hexSlice(pos, pos += 8)}`);
|
|
69
|
+
// FALLTHROUGH
|
|
70
|
+
default:
|
|
71
|
+
return (buffer[pos++] * 72057594037927940)
|
|
72
|
+
+ (buffer[pos++] * 281474976710656)
|
|
73
|
+
+ (buffer[pos++] * 1099511627776)
|
|
74
|
+
+ (buffer[pos++] * 4294967296)
|
|
75
|
+
+ (buffer[pos++] * 16777216)
|
|
76
|
+
+ (buffer[pos++] * 65536)
|
|
77
|
+
+ (buffer[pos++] * 256)
|
|
78
|
+
+ buffer[pos++];
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
skip: (n) => {
|
|
82
|
+
if (buffer && n > 0)
|
|
83
|
+
pos += n;
|
|
84
|
+
},
|
|
85
|
+
skipString: () => {
|
|
86
|
+
const len = self.readUInt32BE();
|
|
87
|
+
if (len === undefined)
|
|
88
|
+
return;
|
|
89
|
+
pos += len;
|
|
90
|
+
return (pos <= buffer.length ? len : undefined);
|
|
91
|
+
},
|
|
92
|
+
readByte: () => {
|
|
93
|
+
if (buffer && pos < buffer.length)
|
|
94
|
+
return buffer[pos++];
|
|
95
|
+
},
|
|
96
|
+
readBool: () => {
|
|
97
|
+
if (buffer && pos < buffer.length)
|
|
98
|
+
return !!buffer[pos++];
|
|
99
|
+
},
|
|
100
|
+
readList: () => {
|
|
101
|
+
const list = self.readString(true);
|
|
102
|
+
if (list === undefined)
|
|
103
|
+
return;
|
|
104
|
+
return (list ? list.split(',') : []);
|
|
105
|
+
},
|
|
106
|
+
readString: (dest, maxLen) => {
|
|
107
|
+
if (typeof dest === 'number') {
|
|
108
|
+
maxLen = dest;
|
|
109
|
+
dest = undefined;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const len = self.readUInt32BE();
|
|
113
|
+
if (len === undefined)
|
|
114
|
+
return;
|
|
115
|
+
|
|
116
|
+
if ((buffer.length - pos) < len
|
|
117
|
+
|| (typeof maxLen === 'number' && len > maxLen)) {
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (dest) {
|
|
122
|
+
if (Buffer.isBuffer(dest))
|
|
123
|
+
return bufferCopy(buffer, dest, pos, pos += len);
|
|
124
|
+
return buffer.utf8Slice(pos, pos += len);
|
|
125
|
+
}
|
|
126
|
+
return bufferSlice(buffer, pos, pos += len);
|
|
127
|
+
},
|
|
128
|
+
readRaw: (len) => {
|
|
129
|
+
if (!buffer)
|
|
130
|
+
return;
|
|
131
|
+
if (typeof len !== 'number')
|
|
132
|
+
return bufferSlice(buffer, pos, pos += (buffer.length - pos));
|
|
133
|
+
if ((buffer.length - pos) >= len)
|
|
134
|
+
return bufferSlice(buffer, pos, pos += len);
|
|
135
|
+
},
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
return self;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function makeError(msg, level, fatal) {
|
|
142
|
+
const err = new Error(msg);
|
|
143
|
+
if (typeof level === 'boolean') {
|
|
144
|
+
fatal = level;
|
|
145
|
+
err.level = 'protocol';
|
|
146
|
+
} else {
|
|
147
|
+
err.level = level || 'protocol';
|
|
148
|
+
}
|
|
149
|
+
err.fatal = !!fatal;
|
|
150
|
+
return err;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function writeUInt32BE(buf, value, offset) {
|
|
154
|
+
buf[offset++] = (value >>> 24);
|
|
155
|
+
buf[offset++] = (value >>> 16);
|
|
156
|
+
buf[offset++] = (value >>> 8);
|
|
157
|
+
buf[offset++] = value;
|
|
158
|
+
return offset;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const utilBufferParser = makeBufferParser();
|
|
162
|
+
|
|
163
|
+
module.exports = {
|
|
164
|
+
bufferCopy,
|
|
165
|
+
bufferSlice,
|
|
166
|
+
FastBuffer,
|
|
167
|
+
bufferFill: (buf, value, start, end) => {
|
|
168
|
+
return TypedArrayFill.call(buf, value, start, end);
|
|
169
|
+
},
|
|
170
|
+
makeError,
|
|
171
|
+
doFatalError: (protocol, msg, level, reason) => {
|
|
172
|
+
let err;
|
|
173
|
+
if (DISCONNECT_REASON === undefined)
|
|
174
|
+
({ DISCONNECT_REASON } = require('./utils.js'));
|
|
175
|
+
if (msg instanceof Error) {
|
|
176
|
+
// doFatalError(protocol, err[, reason])
|
|
177
|
+
err = msg;
|
|
178
|
+
if (typeof level !== 'number')
|
|
179
|
+
reason = DISCONNECT_REASON.PROTOCOL_ERROR;
|
|
180
|
+
else
|
|
181
|
+
reason = level;
|
|
182
|
+
} else {
|
|
183
|
+
// doFatalError(protocol, msg[, level[, reason]])
|
|
184
|
+
err = makeError(msg, level, true);
|
|
185
|
+
}
|
|
186
|
+
if (typeof reason !== 'number')
|
|
187
|
+
reason = DISCONNECT_REASON.PROTOCOL_ERROR;
|
|
188
|
+
protocol.disconnect(reason);
|
|
189
|
+
protocol._destruct();
|
|
190
|
+
protocol._onError(err);
|
|
191
|
+
return Infinity;
|
|
192
|
+
},
|
|
193
|
+
readUInt32BE,
|
|
194
|
+
writeUInt32BE,
|
|
195
|
+
writeUInt32LE: (buf, value, offset) => {
|
|
196
|
+
buf[offset++] = value;
|
|
197
|
+
buf[offset++] = (value >>> 8);
|
|
198
|
+
buf[offset++] = (value >>> 16);
|
|
199
|
+
buf[offset++] = (value >>> 24);
|
|
200
|
+
return offset;
|
|
201
|
+
},
|
|
202
|
+
makeBufferParser,
|
|
203
|
+
bufferParser: makeBufferParser(),
|
|
204
|
+
readString: (buffer, start, dest, maxLen) => {
|
|
205
|
+
if (typeof dest === 'number') {
|
|
206
|
+
maxLen = dest;
|
|
207
|
+
dest = undefined;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
if (start === undefined)
|
|
211
|
+
start = 0;
|
|
212
|
+
|
|
213
|
+
const left = (buffer.length - start);
|
|
214
|
+
if (start < 0 || start >= buffer.length || left < 4)
|
|
215
|
+
return;
|
|
216
|
+
|
|
217
|
+
const len = readUInt32BE(buffer, start);
|
|
218
|
+
if (left < (4 + len) || (typeof maxLen === 'number' && len > maxLen))
|
|
219
|
+
return;
|
|
220
|
+
|
|
221
|
+
start += 4;
|
|
222
|
+
const end = start + len;
|
|
223
|
+
buffer._pos = end;
|
|
224
|
+
|
|
225
|
+
if (dest) {
|
|
226
|
+
if (Buffer.isBuffer(dest))
|
|
227
|
+
return bufferCopy(buffer, dest, start, end);
|
|
228
|
+
return buffer.utf8Slice(start, end);
|
|
229
|
+
}
|
|
230
|
+
return bufferSlice(buffer, start, end);
|
|
231
|
+
},
|
|
232
|
+
sigSSHToASN1: (sig, type) => {
|
|
233
|
+
switch (type) {
|
|
234
|
+
case 'ssh-dss': {
|
|
235
|
+
if (sig.length > 40)
|
|
236
|
+
return sig;
|
|
237
|
+
// Change bare signature r and s values to ASN.1 BER values for OpenSSL
|
|
238
|
+
const asnWriter = new Ber.Writer();
|
|
239
|
+
asnWriter.startSequence();
|
|
240
|
+
let r = sig.slice(0, 20);
|
|
241
|
+
let s = sig.slice(20);
|
|
242
|
+
if (r[0] & 0x80) {
|
|
243
|
+
const rNew = Buffer.allocUnsafe(21);
|
|
244
|
+
rNew[0] = 0x00;
|
|
245
|
+
r.copy(rNew, 1);
|
|
246
|
+
r = rNew;
|
|
247
|
+
} else if (r[0] === 0x00 && !(r[1] & 0x80)) {
|
|
248
|
+
r = r.slice(1);
|
|
249
|
+
}
|
|
250
|
+
if (s[0] & 0x80) {
|
|
251
|
+
const sNew = Buffer.allocUnsafe(21);
|
|
252
|
+
sNew[0] = 0x00;
|
|
253
|
+
s.copy(sNew, 1);
|
|
254
|
+
s = sNew;
|
|
255
|
+
} else if (s[0] === 0x00 && !(s[1] & 0x80)) {
|
|
256
|
+
s = s.slice(1);
|
|
257
|
+
}
|
|
258
|
+
asnWriter.writeBuffer(r, Ber.Integer);
|
|
259
|
+
asnWriter.writeBuffer(s, Ber.Integer);
|
|
260
|
+
asnWriter.endSequence();
|
|
261
|
+
return asnWriter.buffer;
|
|
262
|
+
}
|
|
263
|
+
case 'ecdsa-sha2-nistp256':
|
|
264
|
+
case 'ecdsa-sha2-nistp384':
|
|
265
|
+
case 'ecdsa-sha2-nistp521': {
|
|
266
|
+
utilBufferParser.init(sig, 0);
|
|
267
|
+
const r = utilBufferParser.readString();
|
|
268
|
+
const s = utilBufferParser.readString();
|
|
269
|
+
utilBufferParser.clear();
|
|
270
|
+
if (r === undefined || s === undefined)
|
|
271
|
+
return;
|
|
272
|
+
|
|
273
|
+
const asnWriter = new Ber.Writer();
|
|
274
|
+
asnWriter.startSequence();
|
|
275
|
+
asnWriter.writeBuffer(r, Ber.Integer);
|
|
276
|
+
asnWriter.writeBuffer(s, Ber.Integer);
|
|
277
|
+
asnWriter.endSequence();
|
|
278
|
+
return asnWriter.buffer;
|
|
279
|
+
}
|
|
280
|
+
default:
|
|
281
|
+
return sig;
|
|
282
|
+
}
|
|
283
|
+
},
|
|
284
|
+
convertSignature: (signature, keyType) => {
|
|
285
|
+
switch (keyType) {
|
|
286
|
+
case 'ssh-dss': {
|
|
287
|
+
if (signature.length <= 40)
|
|
288
|
+
return signature;
|
|
289
|
+
// This is a quick and dirty way to get from BER encoded r and s that
|
|
290
|
+
// OpenSSL gives us, to just the bare values back to back (40 bytes
|
|
291
|
+
// total) like OpenSSH (and possibly others) are expecting
|
|
292
|
+
const asnReader = new Ber.Reader(signature);
|
|
293
|
+
asnReader.readSequence();
|
|
294
|
+
let r = asnReader.readString(Ber.Integer, true);
|
|
295
|
+
let s = asnReader.readString(Ber.Integer, true);
|
|
296
|
+
let rOffset = 0;
|
|
297
|
+
let sOffset = 0;
|
|
298
|
+
if (r.length < 20) {
|
|
299
|
+
const rNew = Buffer.allocUnsafe(20);
|
|
300
|
+
rNew.set(r, 1);
|
|
301
|
+
r = rNew;
|
|
302
|
+
r[0] = 0;
|
|
303
|
+
}
|
|
304
|
+
if (s.length < 20) {
|
|
305
|
+
const sNew = Buffer.allocUnsafe(20);
|
|
306
|
+
sNew.set(s, 1);
|
|
307
|
+
s = sNew;
|
|
308
|
+
s[0] = 0;
|
|
309
|
+
}
|
|
310
|
+
if (r.length > 20 && r[0] === 0)
|
|
311
|
+
rOffset = 1;
|
|
312
|
+
if (s.length > 20 && s[0] === 0)
|
|
313
|
+
sOffset = 1;
|
|
314
|
+
const newSig =
|
|
315
|
+
Buffer.allocUnsafe((r.length - rOffset) + (s.length - sOffset));
|
|
316
|
+
bufferCopy(r, newSig, rOffset, r.length, 0);
|
|
317
|
+
bufferCopy(s, newSig, sOffset, s.length, r.length - rOffset);
|
|
318
|
+
return newSig;
|
|
319
|
+
}
|
|
320
|
+
case 'ecdsa-sha2-nistp256':
|
|
321
|
+
case 'ecdsa-sha2-nistp384':
|
|
322
|
+
case 'ecdsa-sha2-nistp521': {
|
|
323
|
+
if (signature[0] === 0)
|
|
324
|
+
return signature;
|
|
325
|
+
// Convert SSH signature parameters to ASN.1 BER values for OpenSSL
|
|
326
|
+
const asnReader = new Ber.Reader(signature);
|
|
327
|
+
asnReader.readSequence();
|
|
328
|
+
const r = asnReader.readString(Ber.Integer, true);
|
|
329
|
+
const s = asnReader.readString(Ber.Integer, true);
|
|
330
|
+
if (r === null || s === null)
|
|
331
|
+
return;
|
|
332
|
+
const newSig = Buffer.allocUnsafe(4 + r.length + 4 + s.length);
|
|
333
|
+
writeUInt32BE(newSig, r.length, 0);
|
|
334
|
+
newSig.set(r, 4);
|
|
335
|
+
writeUInt32BE(newSig, s.length, 4 + r.length);
|
|
336
|
+
newSig.set(s, 4 + 4 + r.length);
|
|
337
|
+
return newSig;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
return signature;
|
|
342
|
+
},
|
|
343
|
+
sendPacket: (proto, packet, bypass) => {
|
|
344
|
+
if (!bypass && proto._kexinit !== undefined) {
|
|
345
|
+
// We're currently in the middle of a handshake
|
|
346
|
+
|
|
347
|
+
if (proto._queue === undefined)
|
|
348
|
+
proto._queue = [];
|
|
349
|
+
proto._queue.push(packet);
|
|
350
|
+
proto._debug && proto._debug('Outbound: ... packet queued');
|
|
351
|
+
return false;
|
|
352
|
+
}
|
|
353
|
+
proto._cipher.encrypt(packet);
|
|
354
|
+
return true;
|
|
355
|
+
},
|
|
356
|
+
};
|