@electerm/ssh2 1.11.2 → 1.14.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.
@@ -222,12 +222,15 @@ function handleKexInit(self, payload) {
222
222
  // Key exchange method =======================================================
223
223
  debug && debug(`Handshake: (local) KEX method: ${localKex}`);
224
224
  debug && debug(`Handshake: (remote) KEX method: ${remote.kex}`);
225
+ let remoteExtInfoEnabled;
225
226
  if (self._server) {
226
227
  serverList = localKex;
227
228
  clientList = remote.kex;
229
+ remoteExtInfoEnabled = (clientList.indexOf('ext-info-c') !== -1);
228
230
  } else {
229
231
  serverList = remote.kex;
230
232
  clientList = localKex;
233
+ remoteExtInfoEnabled = (serverList.indexOf('ext-info-s') !== -1);
231
234
  }
232
235
  // Check for agreeable key exchange algorithm
233
236
  for (i = 0;
@@ -479,6 +482,7 @@ function handleKexInit(self, payload) {
479
482
  }
480
483
 
481
484
  self._kex = createKeyExchange(init, self, payload);
485
+ self._kex.remoteExtInfoEnabled = remoteExtInfoEnabled;
482
486
  self._kex.start();
483
487
  }
484
488
 
@@ -510,6 +514,7 @@ const createKeyExchange = (() => {
510
514
 
511
515
  this.sessionID = (protocol._kex ? protocol._kex.sessionID : undefined);
512
516
  this.negotiated = negotiated;
517
+ this.remoteExtInfoEnabled = false;
513
518
  this._step = 1;
514
519
  this._public = null;
515
520
  this._dh = null;
@@ -527,7 +532,7 @@ const createKeyExchange = (() => {
527
532
  this._dhData = undefined;
528
533
  this._sig = undefined;
529
534
  }
530
- finish() {
535
+ finish(scOnly) {
531
536
  if (this._finished)
532
537
  return false;
533
538
  this._finished = true;
@@ -778,9 +783,26 @@ const createKeyExchange = (() => {
778
783
  this._protocol._packetRW.write.finalize(packet, true)
779
784
  );
780
785
  }
781
- trySendNEWKEYS(this);
782
786
 
783
- const completeHandshake = () => {
787
+ if (isServer || !scOnly)
788
+ trySendNEWKEYS(this);
789
+
790
+ let hsCipherConfig;
791
+ let hsWrite;
792
+ const completeHandshake = (partial) => {
793
+ if (hsCipherConfig) {
794
+ trySendNEWKEYS(this);
795
+ hsCipherConfig.outbound.seqno = this._protocol._cipher.outSeqno;
796
+ this._protocol._cipher.free();
797
+ this._protocol._cipher = createCipher(hsCipherConfig);
798
+ this._protocol._packetRW.write = hsWrite;
799
+ hsCipherConfig = undefined;
800
+ hsWrite = undefined;
801
+ this._protocol._onHandshakeComplete(negotiated);
802
+
803
+ return false;
804
+ }
805
+
784
806
  if (!this.sessionID)
785
807
  this.sessionID = exchangeHash;
786
808
 
@@ -863,9 +885,8 @@ const createKeyExchange = (() => {
863
885
  macKey: (isServer ? scMacKey : csMacKey),
864
886
  },
865
887
  };
866
- this._protocol._cipher && this._protocol._cipher.free();
867
- this._protocol._decipher && this._protocol._decipher.free();
868
- this._protocol._cipher = createCipher(config);
888
+ this._protocol._decipher.free();
889
+ hsCipherConfig = config;
869
890
  this._protocol._decipher = createDecipher(config);
870
891
 
871
892
  const rw = {
@@ -932,7 +953,8 @@ const createKeyExchange = (() => {
932
953
  }
933
954
  this._protocol._packetRW.read.cleanup();
934
955
  this._protocol._packetRW.write.cleanup();
935
- this._protocol._packetRW = rw;
956
+ this._protocol._packetRW.read = rw.read;
957
+ hsWrite = rw.write;
936
958
 
937
959
  // Cleanup/reset various state
938
960
  this._public = null;
@@ -945,13 +967,16 @@ const createKeyExchange = (() => {
945
967
  this._dhData = undefined;
946
968
  this._sig = undefined;
947
969
 
948
- this._protocol._onHandshakeComplete(negotiated);
949
-
970
+ if (!partial)
971
+ return completeHandshake();
950
972
  return false;
951
973
  };
974
+
975
+ if (isServer || scOnly)
976
+ this.finish = completeHandshake;
977
+
952
978
  if (!isServer)
953
- return completeHandshake();
954
- this.finish = completeHandshake;
979
+ return completeHandshake(scOnly);
955
980
  }
956
981
 
957
982
  start() {
@@ -1212,12 +1237,8 @@ const createKeyExchange = (() => {
1212
1237
  );
1213
1238
  this._receivedNEWKEYS = true;
1214
1239
  ++this._step;
1215
- if (this._protocol._server || this._hostVerified)
1216
- return this.finish();
1217
1240
 
1218
- // Signal to current decipher that we need to change to a new decipher
1219
- // for the next packet
1220
- return false;
1241
+ return this.finish(!this._protocol._server && !this._hostVerified);
1221
1242
  default:
1222
1243
  return doFatalError(
1223
1244
  this._protocol,
@@ -1378,7 +1399,7 @@ const createKeyExchange = (() => {
1378
1399
  parse(payload) {
1379
1400
  const type = payload[0];
1380
1401
  switch (this._step) {
1381
- case 1:
1402
+ case 1: {
1382
1403
  if (this._protocol._server) {
1383
1404
  if (type !== MESSAGE.KEXDH_GEX_REQUEST) {
1384
1405
  return doFatalError(
@@ -1453,6 +1474,7 @@ const createKeyExchange = (() => {
1453
1474
 
1454
1475
  ++this._step;
1455
1476
  break;
1477
+ }
1456
1478
  case 2:
1457
1479
  if (this._protocol._server) {
1458
1480
  if (type !== MESSAGE.KEXDH_GEX_INIT) {
@@ -1809,7 +1831,23 @@ module.exports = {
1809
1831
  KexInit,
1810
1832
  kexinit,
1811
1833
  onKEXPayload,
1812
- DEFAULT_KEXINIT: new KexInit({
1834
+ DEFAULT_KEXINIT_CLIENT: new KexInit({
1835
+ kex: DEFAULT_KEX.concat(['ext-info-c']),
1836
+ serverHostKey: DEFAULT_SERVER_HOST_KEY,
1837
+ cs: {
1838
+ cipher: DEFAULT_CIPHER,
1839
+ mac: DEFAULT_MAC,
1840
+ compress: DEFAULT_COMPRESSION,
1841
+ lang: [],
1842
+ },
1843
+ sc: {
1844
+ cipher: DEFAULT_CIPHER,
1845
+ mac: DEFAULT_MAC,
1846
+ compress: DEFAULT_COMPRESSION,
1847
+ lang: [],
1848
+ },
1849
+ }),
1850
+ DEFAULT_KEXINIT_SERVER: new KexInit({
1813
1851
  kex: DEFAULT_KEX,
1814
1852
  serverHostKey: DEFAULT_SERVER_HOST_KEY,
1815
1853
  cs: {
@@ -512,7 +512,7 @@ OpenSSH_Private.prototype = BaseKey;
512
512
  switch (kdfName) {
513
513
  case 'none':
514
514
  return new Error('Malformed OpenSSH private key');
515
- case 'bcrypt':
515
+ case 'bcrypt': {
516
516
  /*
517
517
  string salt
518
518
  uint32 rounds
@@ -534,6 +534,7 @@ OpenSSH_Private.prototype = BaseKey;
534
534
  cipherKey = bufferSlice(gen, 0, encInfo.keyLen);
535
535
  cipherIV = bufferSlice(gen, encInfo.keyLen, gen.length);
536
536
  break;
537
+ }
537
538
  }
538
539
  } else if (kdfName !== 'none') {
539
540
  return new Error('Malformed OpenSSH private key');
@@ -573,6 +574,7 @@ OpenSSH_Private.prototype = BaseKey;
573
574
  cipherKey,
574
575
  cipherIV,
575
576
  options);
577
+ decipher.setAutoPadding(false);
576
578
  if (encInfo.authLen > 0) {
577
579
  if (data.length - data._pos < encInfo.authLen)
578
580
  return new Error('Malformed OpenSSH private key');
@@ -932,7 +934,7 @@ OpenSSH_Old_Private.prototype = BaseKey;
932
934
  }
933
935
  algo = 'sha1';
934
936
  break;
935
- case 'EC':
937
+ case 'EC': {
936
938
  let ecSSLName;
937
939
  let ecPriv;
938
940
  let ecOID;
@@ -981,6 +983,7 @@ OpenSSH_Old_Private.prototype = BaseKey;
981
983
  pubPEM = genOpenSSLECDSAPub(ecOID, pubBlob);
982
984
  pubSSH = genOpenSSHECDSAPub(ecOID, pubBlob);
983
985
  break;
986
+ }
984
987
  }
985
988
 
986
989
  return new OpenSSH_Old_Private(type, '', privPEM, pubPEM, pubSSH, algo,
@@ -1056,9 +1059,7 @@ PPK_Private.prototype = BaseKey;
1056
1059
  if (cipherKey.length > encInfo.keyLen)
1057
1060
  cipherKey = bufferSlice(cipherKey, 0, encInfo.keyLen);
1058
1061
  try {
1059
- const decipher = createDecipheriv(encInfo.sslName,
1060
- cipherKey,
1061
- PPK_IV);
1062
+ const decipher = createDecipheriv(encInfo.sslName, cipherKey, PPK_IV);
1062
1063
  decipher.setAutoPadding(false);
1063
1064
  privBlob = combineBuffers(decipher.update(privBlob),
1064
1065
  decipher.final());
package/lib/server.js CHANGED
@@ -136,6 +136,7 @@ class PKAuthContext extends AuthContext {
136
136
  super(protocol, username, service, method, cb);
137
137
 
138
138
  this.key = { algo: pkInfo.keyAlgo, data: pkInfo.key };
139
+ this.hashAlgo = pkInfo.hashAlgo;
139
140
  this.signature = pkInfo.signature;
140
141
  this.blob = pkInfo.blob;
141
142
  }
@@ -155,6 +156,7 @@ class HostbasedAuthContext extends AuthContext {
155
156
  super(protocol, username, service, method, cb);
156
157
 
157
158
  this.key = { algo: pkInfo.keyAlgo, data: pkInfo.key };
159
+ this.hashAlgo = pkInfo.hashAlgo;
158
160
  this.signature = pkInfo.signature;
159
161
  this.blob = pkInfo.blob;
160
162
  this.localHostname = pkInfo.localHostname;
@@ -1316,6 +1318,13 @@ class Client extends EventEmitter {
1316
1318
  this.once('rekey', cb);
1317
1319
  }
1318
1320
  }
1321
+
1322
+ setNoDelay(noDelay) {
1323
+ if (this._sock && typeof this._sock.setNoDelay === 'function')
1324
+ this._sock.setNoDelay(noDelay);
1325
+
1326
+ return this;
1327
+ }
1319
1328
  }
1320
1329
 
1321
1330
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@electerm/ssh2",
3
- "version": "1.11.2",
3
+ "version": "1.14.0",
4
4
  "author": "Brian White <mscdex@mscdex.net>",
5
5
  "description": "SSH2 client and server modules written in pure JavaScript for node.js",
6
6
  "main": "./lib/index.js",
@@ -8,13 +8,13 @@
8
8
  "node": ">=10.16.0"
9
9
  },
10
10
  "dependencies": {
11
- "asn1": "^0.2.4",
11
+ "asn1": "^0.2.6",
12
12
  "bcrypt-pbkdf": "^1.0.2"
13
13
  },
14
14
  "devDependencies": {
15
15
  "@mscdex/eslint-config": "^1.1.0",
16
- "eslint": "^7.0.0",
17
- "nan": "^2.16.0"
16
+ "eslint": "^7.32.0",
17
+ "nan": "^2.17.0"
18
18
  },
19
19
  "scripts": {
20
20
  "install": "node install.js",