@electerm/ssh2 1.11.2 → 1.16.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/lib/client.js +141 -14
- package/lib/index.js +1 -0
- package/lib/keygen.js +582 -0
- package/lib/protocol/Protocol.js +72 -13
- package/lib/protocol/SFTP.js +190 -2
- package/lib/protocol/constants.js +5 -2
- package/lib/protocol/crypto/build/Makefile +347 -0
- package/lib/protocol/crypto/build/Release/.deps/Release/obj.target/sshcrypto/src/binding.o.d +247 -0
- package/lib/protocol/crypto/build/Release/.deps/Release/sshcrypto.node.d +1 -0
- package/lib/protocol/crypto/build/Release/obj.target/sshcrypto/src/binding.o +0 -0
- package/lib/protocol/crypto/build/Release/sshcrypto.node +0 -0
- package/lib/protocol/crypto/build/binding.Makefile +6 -0
- package/lib/protocol/crypto/build/gyp-mac-tool +772 -0
- package/lib/protocol/crypto/build/sshcrypto.target.mk +194 -0
- package/lib/protocol/handlers.misc.js +76 -5
- package/lib/protocol/kex.js +100 -23
- package/lib/protocol/keyParser.js +7 -6
- package/lib/protocol/zlib.js +6 -2
- package/lib/server.js +14 -1
- package/package.json +7 -4
package/lib/client.js
CHANGED
|
@@ -273,16 +273,14 @@ class Client extends EventEmitter {
|
|
|
273
273
|
let hostVerifier;
|
|
274
274
|
if (typeof cfg.hostVerifier === 'function') {
|
|
275
275
|
const hashCb = cfg.hostVerifier;
|
|
276
|
-
let
|
|
276
|
+
let hashAlgo;
|
|
277
277
|
if (HASHES.indexOf(cfg.hostHash) !== -1) {
|
|
278
278
|
// Default to old behavior of hashing on user's behalf
|
|
279
|
-
|
|
279
|
+
hashAlgo = cfg.hostHash;
|
|
280
280
|
}
|
|
281
281
|
hostVerifier = (key, verify) => {
|
|
282
|
-
if (
|
|
283
|
-
|
|
284
|
-
key = hasher.digest('hex');
|
|
285
|
-
}
|
|
282
|
+
if (hashAlgo)
|
|
283
|
+
key = createHash(hashAlgo).update(key).digest('hex');
|
|
286
284
|
const ret = hashCb(key, verify);
|
|
287
285
|
if (ret !== undefined)
|
|
288
286
|
verify(ret);
|
|
@@ -297,6 +295,7 @@ class Client extends EventEmitter {
|
|
|
297
295
|
const DEBUG_HANDLER = (!debug ? undefined : (p, display, msg) => {
|
|
298
296
|
debug(`Debug output from server: ${JSON.stringify(msg)}`);
|
|
299
297
|
});
|
|
298
|
+
let serverSigAlgs;
|
|
300
299
|
const proto = this._protocol = new Protocol({
|
|
301
300
|
ident: this.config.ident,
|
|
302
301
|
offer: (allOfferDefaults ? undefined : algorithms),
|
|
@@ -348,6 +347,17 @@ class Client extends EventEmitter {
|
|
|
348
347
|
if (name === 'ssh-userauth')
|
|
349
348
|
tryNextAuth();
|
|
350
349
|
},
|
|
350
|
+
EXT_INFO: (p, exts) => {
|
|
351
|
+
if (serverSigAlgs === undefined) {
|
|
352
|
+
for (const ext of exts) {
|
|
353
|
+
if (ext.name === 'server-sig-algs') {
|
|
354
|
+
serverSigAlgs = ext.algs;
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
serverSigAlgs = null;
|
|
359
|
+
}
|
|
360
|
+
},
|
|
351
361
|
USERAUTH_BANNER: (p, msg) => {
|
|
352
362
|
this.emit('banner', msg);
|
|
353
363
|
},
|
|
@@ -360,6 +370,51 @@ class Client extends EventEmitter {
|
|
|
360
370
|
this.emit('ready');
|
|
361
371
|
},
|
|
362
372
|
USERAUTH_FAILURE: (p, authMethods, partialSuccess) => {
|
|
373
|
+
// For key-based authentication, check if we should retry the current
|
|
374
|
+
// key with a different algorithm first
|
|
375
|
+
if (curAuth.keyAlgos) {
|
|
376
|
+
const oldKeyAlgo = curAuth.keyAlgos[0][0];
|
|
377
|
+
if (debug)
|
|
378
|
+
debug(`Client: ${curAuth.type} (${oldKeyAlgo}) auth failed`);
|
|
379
|
+
curAuth.keyAlgos.shift();
|
|
380
|
+
if (curAuth.keyAlgos.length) {
|
|
381
|
+
const [keyAlgo, hashAlgo] = curAuth.keyAlgos[0];
|
|
382
|
+
switch (curAuth.type) {
|
|
383
|
+
case 'agent':
|
|
384
|
+
proto.authPK(
|
|
385
|
+
curAuth.username,
|
|
386
|
+
curAuth.agentCtx.currentKey(),
|
|
387
|
+
keyAlgo
|
|
388
|
+
);
|
|
389
|
+
return;
|
|
390
|
+
case 'publickey':
|
|
391
|
+
proto.authPK(curAuth.username, curAuth.key, keyAlgo);
|
|
392
|
+
return;
|
|
393
|
+
case 'hostbased':
|
|
394
|
+
proto.authHostbased(curAuth.username,
|
|
395
|
+
curAuth.key,
|
|
396
|
+
curAuth.localHostname,
|
|
397
|
+
curAuth.localUsername,
|
|
398
|
+
keyAlgo,
|
|
399
|
+
(buf, cb) => {
|
|
400
|
+
const signature = curAuth.key.sign(buf, hashAlgo);
|
|
401
|
+
if (signature instanceof Error) {
|
|
402
|
+
signature.message =
|
|
403
|
+
`Error while signing with key: ${signature.message}`;
|
|
404
|
+
signature.level = 'client-authentication';
|
|
405
|
+
this.emit('error', signature);
|
|
406
|
+
return tryNextAuth();
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
cb(signature);
|
|
410
|
+
});
|
|
411
|
+
return;
|
|
412
|
+
}
|
|
413
|
+
} else {
|
|
414
|
+
curAuth.keyAlgos = undefined;
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
|
|
363
418
|
if (curAuth.type === 'agent') {
|
|
364
419
|
const pos = curAuth.agentCtx.pos();
|
|
365
420
|
debug && debug(`Client: Agent key #${pos + 1} failed`);
|
|
@@ -386,10 +441,15 @@ class Client extends EventEmitter {
|
|
|
386
441
|
}
|
|
387
442
|
},
|
|
388
443
|
USERAUTH_PK_OK: (p) => {
|
|
444
|
+
let keyAlgo;
|
|
445
|
+
let hashAlgo;
|
|
446
|
+
if (curAuth.keyAlgos)
|
|
447
|
+
[keyAlgo, hashAlgo] = curAuth.keyAlgos[0];
|
|
389
448
|
if (curAuth.type === 'agent') {
|
|
390
449
|
const key = curAuth.agentCtx.currentKey();
|
|
391
|
-
proto.authPK(curAuth.username, key, (buf, cb) => {
|
|
392
|
-
|
|
450
|
+
proto.authPK(curAuth.username, key, keyAlgo, (buf, cb) => {
|
|
451
|
+
const opts = { hash: hashAlgo };
|
|
452
|
+
curAuth.agentCtx.sign(key, buf, opts, (err, signed) => {
|
|
393
453
|
if (err) {
|
|
394
454
|
err.level = 'agent';
|
|
395
455
|
this.emit('error', err);
|
|
@@ -947,16 +1007,42 @@ class Client extends EventEmitter {
|
|
|
947
1007
|
case 'password':
|
|
948
1008
|
proto.authPassword(username, curAuth.password);
|
|
949
1009
|
break;
|
|
950
|
-
case 'publickey':
|
|
951
|
-
|
|
1010
|
+
case 'publickey': {
|
|
1011
|
+
let keyAlgo;
|
|
1012
|
+
curAuth.keyAlgos = getKeyAlgos(this, curAuth.key, serverSigAlgs);
|
|
1013
|
+
if (curAuth.keyAlgos) {
|
|
1014
|
+
if (curAuth.keyAlgos.length) {
|
|
1015
|
+
keyAlgo = curAuth.keyAlgos[0][0];
|
|
1016
|
+
} else {
|
|
1017
|
+
return skipAuth(
|
|
1018
|
+
'Skipping key authentication (no mutual hash algorithm)'
|
|
1019
|
+
);
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1022
|
+
proto.authPK(username, curAuth.key, keyAlgo);
|
|
952
1023
|
break;
|
|
953
|
-
|
|
1024
|
+
}
|
|
1025
|
+
case 'hostbased': {
|
|
1026
|
+
let keyAlgo;
|
|
1027
|
+
let hashAlgo;
|
|
1028
|
+
curAuth.keyAlgos = getKeyAlgos(this, curAuth.key, serverSigAlgs);
|
|
1029
|
+
if (curAuth.keyAlgos) {
|
|
1030
|
+
if (curAuth.keyAlgos.length) {
|
|
1031
|
+
[keyAlgo, hashAlgo] = curAuth.keyAlgos[0];
|
|
1032
|
+
} else {
|
|
1033
|
+
return skipAuth(
|
|
1034
|
+
'Skipping hostbased authentication (no mutual hash algorithm)'
|
|
1035
|
+
);
|
|
1036
|
+
}
|
|
1037
|
+
}
|
|
1038
|
+
|
|
954
1039
|
proto.authHostbased(username,
|
|
955
1040
|
curAuth.key,
|
|
956
1041
|
curAuth.localHostname,
|
|
957
1042
|
curAuth.localUsername,
|
|
1043
|
+
keyAlgo,
|
|
958
1044
|
(buf, cb) => {
|
|
959
|
-
const signature = curAuth.key.sign(buf);
|
|
1045
|
+
const signature = curAuth.key.sign(buf, hashAlgo);
|
|
960
1046
|
if (signature instanceof Error) {
|
|
961
1047
|
signature.message =
|
|
962
1048
|
`Error while signing with key: ${signature.message}`;
|
|
@@ -968,6 +1054,7 @@ class Client extends EventEmitter {
|
|
|
968
1054
|
cb(signature);
|
|
969
1055
|
});
|
|
970
1056
|
break;
|
|
1057
|
+
}
|
|
971
1058
|
case 'agent':
|
|
972
1059
|
curAuth.agentCtx.init((err) => {
|
|
973
1060
|
if (err) {
|
|
@@ -1012,8 +1099,21 @@ class Client extends EventEmitter {
|
|
|
1012
1099
|
tryNextAuth();
|
|
1013
1100
|
} else {
|
|
1014
1101
|
const pos = curAuth.agentCtx.pos();
|
|
1102
|
+
let keyAlgo;
|
|
1103
|
+
curAuth.keyAlgos = getKeyAlgos(this, key, serverSigAlgs);
|
|
1104
|
+
if (curAuth.keyAlgos) {
|
|
1105
|
+
if (curAuth.keyAlgos.length) {
|
|
1106
|
+
keyAlgo = curAuth.keyAlgos[0][0];
|
|
1107
|
+
} else {
|
|
1108
|
+
debug && debug(
|
|
1109
|
+
`Agent: Skipping key #${pos + 1} (no mutual hash algorithm)`
|
|
1110
|
+
);
|
|
1111
|
+
tryNextAgentKey();
|
|
1112
|
+
return;
|
|
1113
|
+
}
|
|
1114
|
+
}
|
|
1015
1115
|
debug && debug(`Agent: Trying key #${pos + 1}`);
|
|
1016
|
-
proto.authPK(curAuth.username, key);
|
|
1116
|
+
proto.authPK(curAuth.username, key, keyAlgo);
|
|
1017
1117
|
}
|
|
1018
1118
|
}
|
|
1019
1119
|
};
|
|
@@ -1044,7 +1144,6 @@ class Client extends EventEmitter {
|
|
|
1044
1144
|
localAddress: this.config.localAddress,
|
|
1045
1145
|
localPort: this.config.localPort
|
|
1046
1146
|
});
|
|
1047
|
-
sock.setNoDelay(true);
|
|
1048
1147
|
sock.setMaxListeners(0);
|
|
1049
1148
|
sock.setTimeout(typeof cfg.timeout === 'number' ? cfg.timeout : 0);
|
|
1050
1149
|
};
|
|
@@ -1524,6 +1623,13 @@ class Client extends EventEmitter {
|
|
|
1524
1623
|
|
|
1525
1624
|
return this;
|
|
1526
1625
|
}
|
|
1626
|
+
|
|
1627
|
+
setNoDelay(noDelay) {
|
|
1628
|
+
if (this._sock && typeof this._sock.setNoDelay === 'function')
|
|
1629
|
+
this._sock.setNoDelay(noDelay);
|
|
1630
|
+
|
|
1631
|
+
return this;
|
|
1632
|
+
}
|
|
1527
1633
|
}
|
|
1528
1634
|
|
|
1529
1635
|
function openChannel(self, type, opts, cb) {
|
|
@@ -2021,4 +2127,25 @@ function hostKeysProve(client, keys_, cb) {
|
|
|
2021
2127
|
);
|
|
2022
2128
|
}
|
|
2023
2129
|
|
|
2130
|
+
function getKeyAlgos(client, key, serverSigAlgs) {
|
|
2131
|
+
switch (key.type) {
|
|
2132
|
+
case 'ssh-rsa':
|
|
2133
|
+
if (client._protocol._compatFlags & COMPAT.IMPLY_RSA_SHA2_SIGALGS) {
|
|
2134
|
+
if (!Array.isArray(serverSigAlgs))
|
|
2135
|
+
serverSigAlgs = ['rsa-sha2-256', 'rsa-sha2-512'];
|
|
2136
|
+
else
|
|
2137
|
+
serverSigAlgs = ['rsa-sha2-256', 'rsa-sha2-512', ...serverSigAlgs];
|
|
2138
|
+
}
|
|
2139
|
+
if (Array.isArray(serverSigAlgs)) {
|
|
2140
|
+
if (serverSigAlgs.indexOf('rsa-sha2-256') !== -1)
|
|
2141
|
+
return [['rsa-sha2-256', 'sha256']];
|
|
2142
|
+
if (serverSigAlgs.indexOf('rsa-sha2-512') !== -1)
|
|
2143
|
+
return [['rsa-sha2-512', 'sha512']];
|
|
2144
|
+
if (serverSigAlgs.indexOf('ssh-rsa') === -1)
|
|
2145
|
+
return [];
|
|
2146
|
+
}
|
|
2147
|
+
return [['ssh-rsa', 'sha1']];
|
|
2148
|
+
}
|
|
2149
|
+
}
|
|
2150
|
+
|
|
2024
2151
|
module.exports = Client;
|