Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: mscdex/ssh2
base: 028006c670
...
head fork: mscdex/ssh2
compare: a95bef762a
Checking mergeability… Don't worry, you can still create the pull request.
  • 3 commits
  • 3 files changed
  • 0 commit comments
  • 1 contributor
Showing with 222 additions and 65 deletions.
  1. +161 −43 lib/Connection.js
  2. +10 −0 lib/Parser.constants.js
  3. +51 −22 lib/Parser.js
View
204 lib/Connection.js
@@ -19,6 +19,7 @@ var Parser = require('./Parser'),
var MODULE_VER = require('../package.json').version,
SSH_IDENT = 'SSH-2.0-ssh2js' + MODULE_VER,
MAX_CHANNEL = Math.pow(2, 32) - 1,
+ RE_SHA1 = /^group|gex-sha1$/i,
ALGORITHMS = consts.ALGORITHMS,
MESSAGE = consts.MESSAGE,
SSH_TO_OPENSSL = consts.SSH_TO_OPENSSL,
@@ -27,8 +28,17 @@ var MODULE_VER = require('../package.json').version,
EMPTY_BUFFER = new Buffer(0),
PING_PACKET = new Buffer([MESSAGE.IGNORE, 0, 0, 0, 0]),
AUTO_KB_PACKET = new Buffer([consts.USERAUTH_INFO_RESPONSE, 0, 0, 0, 0]),
- NEWKEYS_PACKET = new Buffer([MESSAGE.NEWKEYS]);
-
+ NEWKEYS_PACKET = new Buffer([MESSAGE.NEWKEYS]),
+ KEXDH_GEX_REQ_PACKET = new Buffer([
+ consts.KEXDH_GEX_REQUEST,
+ // minimal size in bits of an acceptable group
+ 0, 0, 4, 0, // 1024, modp2
+ // preferred size in bits of the group the server will send
+ 0, 0, 10, 0, // 4096, modp16
+ // maximal size in bits of an acceptable group
+ 0, 0, 20, 0 // 8192, modp18
+ ]);
+require('buffer').INSPECT_MAX_BYTES = Infinity;
function Connection(opts) {
if (!(this instanceof Connection))
return new Connection(opts);
@@ -68,6 +78,7 @@ function Connection(opts) {
this._hmac = false;
this._server_ident_raw = undefined;
this._kexinit = undefined;
+ this._kexdh = undefined;
this._sessionid = undefined;
this._curChan = -1;
@@ -101,6 +112,10 @@ function Connection(opts) {
onKEXDH_REPLY(self, info);
});
+ this._parser.on('KEXDH_GEX_GROUP', function(prime, gen) {
+ onKEXDH_GEX_GROUP(self, prime, gen);
+ });
+
this._parser.on('NEWKEYS', function() {
onNEWKEYS(self);
});
@@ -219,6 +234,7 @@ Connection.prototype.connect = function(opts) {
this._hmac = false;
this._server_ident_raw = undefined;
this._kexinit = undefined;
+ this._kexdh = undefined;
this._sessionid = undefined;
this._pinger = undefined;
@@ -628,7 +644,7 @@ Connection.prototype.forwardIn = function(address, port, cb) {
cb();
});
- this._debug && this._debug('DEBUG: Connection: Sent GLOBAL_REQUEST (tcpip-forward)');
+ this._debug && this._debug('DEBUG: Connection: Sending GLOBAL_REQUEST (tcpip-forward)');
return this._send(buf);
};
@@ -660,7 +676,7 @@ Connection.prototype.unforwardIn = function(address, port, cb) {
cb();
});
- this._debug && this._debug('DEBUG: Connection: Sent GLOBAL_REQUEST (cancel-tcpip-forward)');
+ this._debug && this._debug('DEBUG: Connection: Sending GLOBAL_REQUEST (cancel-tcpip-forward)');
return this._send(buf);
};
@@ -819,7 +835,7 @@ Connection.prototype._openChan = function(type, blob, cb) {
if (blob)
blob.copy(buf, p += 4);
- this._debug && this._debug('DEBUG: Connection: Sent CHANNEL_OPEN');
+ this._debug && this._debug('DEBUG: Connection: Sending CHANNEL_OPEN');
return this._send(buf);
};
@@ -841,7 +857,7 @@ Connection.prototype._nextChan = function() {
Connection.prototype._ping = function() {
// simply send an SSH_MSG_IGNORE message for keepalive purposes
- this._debug && this._debug('DEBUG: Connection: Sent ping');
+ this._debug && this._debug('DEBUG: Connection: Sending ping');
this._send(PING_PACKET);
};
@@ -916,7 +932,7 @@ Connection.prototype._authPwd = function(newpwd) {
}
this._parser._authMethod = 'password';
- this._debug && this._debug('DEBUG: Connection: Sent USERAUTH_REQUEST (password)');
+ this._debug && this._debug('DEBUG: Connection: Sending USERAUTH_REQUEST (password)');
return this._send(buf);
};
@@ -951,7 +967,7 @@ Connection.prototype._authKeyboard = function() {
buf.writeUInt32BE(0, p += 4, true);
this._parser._authMethod = 'keyboard-interactive';
- this._debug && this._debug('DEBUG: Connection: Sent USERAUTH_REQUEST (keyboard-interactive)');
+ this._debug && this._debug('DEBUG: Connection: Sending USERAUTH_REQUEST (keyboard-interactive)');
return this._send(buf);
};
@@ -1016,7 +1032,7 @@ Connection.prototype._authPK = function(sign) {
pubKey.copy(sig, p += 4);
if (!sign) {
- this._debug && this._debug('DEBUG: Connection: Sent USERAUTH_REQUEST (publickey -- check)');
+ this._debug && this._debug('DEBUG: Connection: Sending USERAUTH_REQUEST (publickey -- check)');
return this._send(sig);
}
@@ -1116,7 +1132,7 @@ Connection.prototype._authPK = function(sign) {
buf.writeUInt32BE(sigLen, p += privAlgoLen, true);
signature.copy(buf, p += 4);
- self._debug && self._debug('DEBUG: Connection: Sent USERAUTH_REQUEST (publickey)');
+ self._debug && self._debug('DEBUG: Connection: Sending USERAUTH_REQUEST (publickey)');
return self._send(buf);
}
};
@@ -1170,7 +1186,7 @@ Connection.prototype._disconnect = function(reason) {
buf[0] = MESSAGE.DISCONNECT;
buf.writeUInt32BE(reason, 1, true);
- self._debug && self._debug('DEBUG: Connection: Sent DISCONNECT');
+ self._debug && self._debug('DEBUG: Connection: Sending DISCONNECT');
return this._send(buf, function() {
self._sock.end();
});
@@ -1342,7 +1358,7 @@ function sendKEXInit(self, cb) {
// skip language lists, first_kex_packet_follows, and reserved bytes
- self._debug && self._debug('DEBUG: Connection: Sent KEXINIT');
+ self._debug && self._debug('DEBUG: Connection: Sending KEXINIT');
self._kexinit = bufKexInit;
if (self._state === 'reexchg')
self._send(bufKexInit, undefined, true);
@@ -1525,25 +1541,55 @@ function checkSKEXInit(self, init) {
else if (kex_algorithm === 'diffie-hellman-group14-sha1')
self._kex = crypto.getDiffieHellman('modp14');
- self._pubkey = new Buffer(self._kex.generateKeys('binary'), 'binary');
+ if (self._kex) {
+ self._kexdh = self._parser._kexdh = 'group';
+ self._pubkey = new Buffer(self._kex.generateKeys('binary'), 'binary');
+ if (self._pubkey[0] & 0x80) {
+ var key = new Buffer(self._pubkey.length + 1);
+ key[0] = 0;
+ self._pubkey.copy(key, 1);
+ self._pubkey = key;
+ }
+ } else if (kex_algorithm === 'diffie-hellman-group-exchange-sha1')
+ self._kexdh = self._parser._kexdh = 'gex-sha1';
+ else if (kex_algorithm === 'diffie-hellman-group-exchange-sha256')
+ self._kexdh = self._parser._kexdh = 'gex-sha256';
+
+ return true;
+}
+
+function sendKEXDHGEXReq(self) {
+ self._debug && self._debug('DEBUG: Connection: Sending KEXDH_GEX_REQUEST');
+ if (self._state === 'reexchg')
+ self._send(KEXDH_GEX_REQ_PACKET, undefined, true);
+ else
+ self._send(KEXDH_GEX_REQ_PACKET);
+}
+function onKEXDH_GEX_GROUP(self, prime, gen) {
+ self._kex = crypto.createDiffieHellman(prime, gen);
+ self._pubkey = new Buffer(self._kex.generateKeys('binary'), 'binary');
if (self._pubkey[0] & 0x80) {
var key = new Buffer(self._pubkey.length + 1);
key[0] = 0;
self._pubkey.copy(key, 1);
self._pubkey = key;
}
-
- return true;
+ sendKEXDHInit(self);
}
function sendKEXDHInit(self) {
var bufDHInit = new Buffer(1 + 4 + self._pubkey.length);
- bufDHInit[0] = MESSAGE.KEXDH_INIT;
+ if (self._kexdh !== 'group') {
+ bufDHInit[0] = consts.KEXDH_GEX_INIT;
+ self._debug && self._debug('DEBUG: Connection: Sending KEXDH_GEX_INIT');
+ } else {
+ bufDHInit[0] = MESSAGE.KEXDH_INIT;
+ self._debug && self._debug('DEBUG: Connection: Sending KEXDH_INIT');
+ }
bufDHInit.writeUInt32BE(self._pubkey.length, 1, true);
self._pubkey.copy(bufDHInit, 5);
- self._debug && self._debug('DEBUG: Connection: Sent KEXDH_INIT');
if (self._state === 'reexchg')
self._send(bufDHInit, undefined, true);
else
@@ -1567,8 +1613,12 @@ function onKEXINIT(self, init) {
doCheck();
function doCheck() {
- if (checkSKEXInit(self, init) === true)
- sendKEXDHInit(self);
+ if (checkSKEXInit(self, init) === true) {
+ if (self._kexdh !== 'group')
+ sendKEXDHGEXReq(self);
+ else
+ sendKEXDHInit(self);
+ }
}
}
@@ -1616,16 +1666,32 @@ function onKEXDH_REPLY(self, info) {
info.pubkey = info.pubkey.slice(slicepos + 1);
var compSecret = self._kex.computeSecret(info.pubkey, 'binary', 'binary');
info.secret = new Buffer(compSecret, 'binary');
- // SHA1 for supported DH group1 and group14 kex methods
- var hash = crypto.createHash('sha1');
+ var hash = crypto.createHash(RE_SHA1.test(self._kexdh)
+ ? 'sha1'
+ : 'sha256');
var len_ident = Buffer.byteLength(SSH_IDENT),
len_sident = Buffer.byteLength(self._server_ident_raw),
len_init = self._kexinit.length,
len_sinit = self._parser._kexinit.length,
len_hostkey = info.hostkey.length,
+ len_gex_req = 0,
+ len_gex_prime = 0,
+ len_gex_gen = 0,
len_pubkey = self._pubkey.length,
len_spubkey = info.pubkey.length,
len_secret = info.secret.length;
+ var gex_prime, gex_gen;
+ if (self._kexdh !== 'group') {
+ len_gex_req = 12;
+ gex_prime = self._kex.getPrime();
+ gex_gen = self._kex.getGenerator();
+ len_gex_prime = gex_prime.length;
+ len_gex_gen = gex_gen.length;
+ if (gex_prime[0] & 0x80)
+ ++len_gex_prime;
+ if (gex_gen[0] & 0x80)
+ ++len_gex_gen;
+ }
if (self._pubkey[0] & 0x80)
++len_pubkey;
if (info.pubkey[0] & 0x80)
@@ -1638,10 +1704,14 @@ function onKEXDH_REPLY(self, info) {
+ len_init
+ len_sinit
+ len_hostkey
+ + len_gex_req
+ + len_gex_prime
+ + len_gex_gen
+ len_pubkey
+ len_spubkey
+ len_secret
- + (4 * 8));
+ + (4 * 8)
+ + (self._kexdh !== 'group' ? (4 * 2) : 0));
exchangeBuf.writeUInt32BE(len_ident, bp, true);
bp += 4;
exchangeBuf.write(SSH_IDENT, bp, 'utf8'); // V_C
@@ -1667,6 +1737,25 @@ function onKEXDH_REPLY(self, info) {
info.hostkey.copy(exchangeBuf, bp); // K_S
bp += len_hostkey;
+ if (self._kexdh !== 'group') {
+ KEXDH_GEX_REQ_PACKET.slice(1).copy(exchangeBuf, bp); // min, n, max
+ bp += len_gex_req;
+
+ exchangeBuf.writeUInt32BE(len_gex_prime, bp, true);
+ bp += 4;
+ if (gex_prime[0] & 0x80)
+ exchangeBuf[bp++] = 0;
+ gex_prime.copy(exchangeBuf, bp); // p
+ bp += len_gex_prime - (gex_prime[0] & 0x80 ? 1 : 0);
+
+ exchangeBuf.writeUInt32BE(len_gex_gen, bp, true);
+ bp += 4;
+ if (gex_gen[0] & 0x80)
+ exchangeBuf[bp++] = 0;
+ gex_gen.copy(exchangeBuf, bp); // g
+ bp += len_gex_gen - (gex_gen[0] & 0x80 ? 1 : 0);
+ }
+
exchangeBuf.writeUInt32BE(len_pubkey, bp, true);
bp += 4;
if (self._pubkey[0] & 0x80)
@@ -1764,7 +1853,7 @@ function onKEXDH_REPLY(self, info) {
if (self._sessionid === undefined)
self._sessionid = self._exchange_hash;
self._kexreply = info;
- debug && debug('DEBUG: Connection: Sent NEWKEYS');
+ debug && debug('DEBUG: Connection: Sending NEWKEYS');
if (self._state === 'reexchg')
self._send(NEWKEYS_PACKET, undefined, true);
else
@@ -1772,9 +1861,14 @@ function onKEXDH_REPLY(self, info) {
}
function onNEWKEYS(self) {
- var iv, key, blocklen = 8, keylen = 0, p = 0,
- secret, len_secret = (self._kexreply.secret[0] & 0x80 ? 1 : 0)
- + self._kexreply.secret.length;
+ var iv,
+ key,
+ blocklen = 8,
+ keylen = 0,
+ p = 0,
+ secret,
+ len_secret = (self._kexreply.secret[0] & 0x80 ? 1 : 0)
+ + self._kexreply.secret.length;
secret = new Buffer(4 + len_secret);
secret.writeUInt32BE(len_secret, p, true);
p += 4;
@@ -1782,7 +1876,9 @@ function onNEWKEYS(self) {
secret[p++] = 0;
self._kexreply.secret.copy(secret, p);
if (!isStreamCipher(self._encryptType)) {
- iv = new Buffer(crypto.createHash('sha1')
+ iv = new Buffer(crypto.createHash(RE_SHA1.test(self._kexdh)
+ ? 'sha1'
+ : 'sha256')
.update(secret)
.update(self._exchange_hash)
.update('A', 'ascii')
@@ -1805,7 +1901,9 @@ function onNEWKEYS(self) {
}
self._encryptSize = blocklen;
while (blocklen > iv.length) {
- iv = Buffer.concat([iv, new Buffer(crypto.createHash('sha1')
+ iv = Buffer.concat([iv, new Buffer(crypto.createHash(RE_SHA1.test(self._kexdh)
+ ? 'sha1'
+ : 'sha256')
.update(secret)
.update(self._exchange_hash)
.update(iv)
@@ -1841,14 +1939,18 @@ function onNEWKEYS(self) {
keylen = 16; // eg. 128 / 8
break;
}
- key = new Buffer(crypto.createHash('sha1')
+ key = new Buffer(crypto.createHash(RE_SHA1.test(self._kexdh)
+ ? 'sha1'
+ : 'sha256')
.update(secret)
.update(self._exchange_hash)
.update('C', 'ascii')
.update(self._sessionid)
.digest('binary'), 'binary');
while (keylen > key.length) {
- key = Buffer.concat([key, new Buffer(crypto.createHash('sha1')
+ key = Buffer.concat([key, new Buffer(crypto.createHash(RE_SHA1.test(self._kexdh)
+ ? 'sha1'
+ : 'sha256')
.update(secret)
.update(self._exchange_hash)
.update(key)
@@ -1872,7 +1974,9 @@ function onNEWKEYS(self) {
blocklen = 8;
keylen = 0;
if (!isStreamCipher(self._parser._decryptType)) {
- iv = new Buffer(crypto.createHash('sha1')
+ iv = new Buffer(crypto.createHash(RE_SHA1.test(self._kexdh)
+ ? 'sha1'
+ : 'sha256')
.update(secret)
.update(self._exchange_hash)
.update('B', 'ascii')
@@ -1898,7 +2002,9 @@ function onNEWKEYS(self) {
else
self._parser._decryptSize = blocklen;
while (blocklen > iv.length) {
- iv = Buffer.concat([iv, new Buffer(crypto.createHash('sha1')
+ iv = Buffer.concat([iv, new Buffer(crypto.createHash(RE_SHA1.test(self._kexdh)
+ ? 'sha1'
+ : 'sha256')
.update(secret)
.update(self._exchange_hash)
.update(iv)
@@ -1938,14 +2044,18 @@ function onNEWKEYS(self) {
keylen = 16; // eg. 128 / 8
break;
}
- key = new Buffer(crypto.createHash('sha1')
+ key = new Buffer(crypto.createHash(RE_SHA1.test(self._kexdh)
+ ? 'sha1'
+ : 'sha256')
.update(secret)
.update(self._exchange_hash)
.update('D', 'ascii')
.update(self._sessionid)
.digest('binary'), 'binary');
while (keylen > key.length) {
- key = Buffer.concat([key, new Buffer(crypto.createHash('sha1')
+ key = Buffer.concat([key, new Buffer(crypto.createHash(RE_SHA1.test(self._kexdh)
+ ? 'sha1'
+ : 'sha256')
.update(secret)
.update(self._exchange_hash)
.update(key)
@@ -2019,14 +2129,18 @@ function onNEWKEYS(self) {
}
if (!isGCM(self._encryptType)) {
- key = new Buffer(crypto.createHash('sha1')
+ key = new Buffer(crypto.createHash(RE_SHA1.test(self._kexdh)
+ ? 'sha1'
+ : 'sha256')
.update(secret)
.update(self._exchange_hash)
.update('E', 'ascii')
.update(self._sessionid)
.digest('binary'), 'binary');
while (createKeyLen > key.length) {
- key = Buffer.concat([key, new Buffer(crypto.createHash('sha1')
+ key = Buffer.concat([key, new Buffer(crypto.createHash(RE_SHA1.test(self._kexdh)
+ ? 'sha1'
+ : 'sha256')
.update(secret)
.update(self._exchange_hash)
.update(key)
@@ -2036,14 +2150,18 @@ function onNEWKEYS(self) {
} else
self._hmacKey = undefined;
if (!isGCM(self._parser._decryptType)) {
- key = new Buffer(crypto.createHash('sha1')
+ key = new Buffer(crypto.createHash(RE_SHA1.test(self._kexdh)
+ ? 'sha1'
+ : 'sha256')
.update(secret)
.update(self._exchange_hash)
.update('F', 'ascii')
.update(self._sessionid)
.digest('binary'), 'binary');
while (checkKeyLen > key.length) {
- key = Buffer.concat([key, new Buffer(crypto.createHash('sha1')
+ key = Buffer.concat([key, new Buffer(crypto.createHash(RE_SHA1.test(self._kexdh)
+ ? 'sha1'
+ : 'sha256')
.update(secret)
.update(self._exchange_hash)
.update(key)
@@ -2071,7 +2189,7 @@ function onNEWKEYS(self) {
svcBuf[0] = MESSAGE.SERVICE_REQUEST;
svcBuf.writeUInt32BE(12, 1, true);
svcBuf.write('ssh-userauth', 5, 12, 'ascii');
- self._debug && self._debug('DEBUG: Connection: Sent SERVICE_REQUEST');
+ self._debug && self._debug('DEBUG: Connection: Sending SERVICE_REQUEST');
self._send(svcBuf);
} else if (self._state === 'reexchg') {
self._state = 'authenticated';
@@ -2157,7 +2275,7 @@ function onUSERAUTH_PASSWD_CHANGEREQ(self, message, lang) {
function onUSERAUTH_INFO_REQUEST(self, name, inst, lang, prompts) {
var nprompts = (Array.isArray(prompts) ? prompts.length : 0);
if (nprompts === 0) {
- self._debug && self._debug('DEBUG: Connection: Sent automatic USERAUTH_INFO_RESPONSE');
+ self._debug && self._debug('DEBUG: Connection: Sending automatic USERAUTH_INFO_RESPONSE');
return self._send(AUTO_KB_PACKET);
}
// we sent a keyboard-interactive user authentication request and now the
@@ -2184,7 +2302,7 @@ function onUSERAUTH_INFO_REQUEST(self, name, inst, lang, prompts) {
buf.write(answers[i], p += 4, size, 'utf8');
p += size;
}
- self._debug && self._debug('DEBUG: Connection: Sent USERAUTH_INFO_RESPONSE');
+ self._debug && self._debug('DEBUG: Connection: Sending USERAUTH_INFO_RESPONSE');
self._send(buf);
} else {
var err = new Error('Not connected');
@@ -2246,7 +2364,7 @@ function onCHANNEL_OPEN(self, info) {
buf.writeUInt32BE(Channel.MAX_WINDOW, 9, true);
buf.writeUInt32BE(Channel.MAX_WINDOW, 13, true);
- self._debug && self._debug('DEBUG: Connection: Sent CHANNEL_OPEN_CONFIRMATION');
+ self._debug && self._debug('DEBUG: Connection: Sending CHANNEL_OPEN_CONFIRMATION');
self._send(buf);
return stream;
@@ -2272,7 +2390,7 @@ function onCHANNEL_OPEN(self, info) {
buf.writeUInt32BE(2, 13, true);
buf.write('en', 17, 2, 'ascii');
- self._debug && self._debug('DEBUG: Connection: Sent CHANNEL_OPEN_FAILURE');
+ self._debug && self._debug('DEBUG: Connection: Sending CHANNEL_OPEN_FAILURE');
self._send(buf);
};
View
10 lib/Parser.constants.js
@@ -54,6 +54,10 @@ exports.USERAUTH_PASSWD_CHANGEREQ = 60;
exports.USERAUTH_PK_OK = 60;
exports.USERAUTH_INFO_REQUEST = 60;
exports.USERAUTH_INFO_RESPONSE = 61;
+exports.KEXDH_GEX_REQUEST = 34;
+exports.KEXDH_GEX_GROUP = 31;
+exports.KEXDH_GEX_INIT = 32;
+exports.KEXDH_GEX_REPLY = 33;
var DISCONNECT_REASON = exports.DISCONNECT_REASON = {
HOST_NOT_ALLOWED_TO_CONNECT: 1,
@@ -216,6 +220,12 @@ if (process.versions.openssl >= '1.0.1') {
'aes256-gcm',
'aes256-gcm@openssh.com'
].concat(CIPHER);
+
+ KEX = [
+ 'diffie-hellman-group-exchange-sha256',
+ 'diffie-hellman-group-exchange-sha1'
+ ].concat(KEX);
+ KEX_LIST = new Buffer(KEX.join(','));
}
CIPHER = [
// http://tools.ietf.org/html/rfc4344#section-4
View
73 lib/Parser.js
@@ -38,7 +38,14 @@ Parser.prototype.execute = function(b, start, end) {
start || (start = 0);
end || (end = b.length);
- var i = start, buffer, skipDecrypt = false, buf, self = this, p = i, r;
+ var i = start,
+ buffer,
+ skipDecrypt = false,
+ buf,
+ self = this,
+ p = i,
+ r,
+ doDecryptGCM = false;
while (true) {
if (this._expectType !== undefined) {
@@ -149,7 +156,7 @@ Parser.prototype.execute = function(b, start, end) {
this._state = STATE_PACKET;
} else if (this._state === STATE_PACKET) {
this.debug&&this.debug('DEBUG: Parser: STATE_PACKET');
- var doDecryptGCM = (this._decrypt && isGCM(this._decryptType));
+ doDecryptGCM = (this._decrypt && isGCM(this._decryptType));
if (this._decrypt && !isGCM(this._decryptType))
buffer = this.decrypt(buffer);
this._pktLen = buffer.readUInt32BE(0, true);
@@ -182,7 +189,7 @@ Parser.prototype.execute = function(b, start, end) {
}
} else if (this._state === STATE_PACKETDATA) {
this.debug&&this.debug('DEBUG: Parser: STATE_PACKETDATA');
- var doDecryptGCM = (this._decrypt && isGCM(this._decryptType));
+ doDecryptGCM = (this._decrypt && isGCM(this._decryptType));
if (this._decrypt && !skipDecrypt && !doDecryptGCM)
buffer = this.decrypt(buffer);
else if (skipDecrypt)
@@ -230,7 +237,11 @@ Parser.prototype.execute = function(b, start, end) {
this.debug('DEBUG: Parser: STATE_PACKETDATAAFTER, packet: USERAUTH_INFO_REQUEST');
else if (this._authMethod === 'pubkey')
this.debug('DEBUG: Parser: STATE_PACKETDATAAFTER, packet: USERAUTH_PK_OK');
- } else {
+ } else if (this._payload[0] === 31 && this._kexdh !== 'group')
+ this.debug('DEBUG: Parser: STATE_PACKETDATAAFTER, packet: KEXDH_GEX_GROUP');
+ else if (this._payload[0] === 33 && this._kexdh !== 'group')
+ this.debug('DEBUG: Parser: STATE_PACKETDATAAFTER, packet: KEXDH_GEX_REPLY');
+ else {
this.debug('DEBUG: Parser: STATE_PACKETDATAAFTER, packet: '
+ MESSAGE[this._payload[0]]);
}
@@ -436,24 +447,21 @@ Parser.prototype.parsePacket = function() {
this.emit('DEBUG', message, lang);
} else if (type === MESSAGE.KEXINIT)
this.parseKEXInit();
- else if (type === MESSAGE.KEXDH_REPLY) {
- /*
- byte SSH_MSG_KEXDH_REPLY
- string server public host key and certificates (K_S)
- mpint f
- string signature of H
- */
- info = {
- hostkey: readString(payload, 1),
- hostkey_format: undefined,
- pubkey: readString(payload, payload._pos),
- sig: readString(payload, payload._pos),
- sig_format: undefined
- };
- info.hostkey_format = readString(info.hostkey, 0, 'ascii');
- info.sig_format = readString(info.sig, 0, 'ascii');
- this.emit('KEXDH_REPLY', info);
- } else if (type === MESSAGE.NEWKEYS) {
+ else if (type === 31) { // key exchange method-specific message
+ if (this._kexdh !== 'group') {
+ /*
+ byte SSH_MSG_KEX_DH_GEX_GROUP
+ mpint p, safe prime
+ mpint g, generator for subgroup in GF(p)
+ */
+ var prime = readString(payload, 1),
+ gen = readString(payload, payload._pos);
+ this.emit('KEXDH_GEX_GROUP', prime, gen);
+ } else
+ this.parseKEXDH_REPLY();
+ } else if (type === consts.KEXDH_GEX_REPLY)
+ this.parseKEXDH_REPLY();
+ else if (type === MESSAGE.NEWKEYS) {
/*
byte SSH_MSG_NEW_KEYS
*/
@@ -635,6 +643,26 @@ Parser.prototype.parsePacket = function() {
}
};
+Parser.prototype.parseKEXDH_REPLY = function() {
+ var payload = this._payload;
+ /*
+ byte SSH_MSG_KEXDH_REPLY / SSH_MSG_KEX_DH_GEX_REPLY
+ string server public host key and certificates (K_S)
+ mpint f
+ string signature of H
+ */
+ info = {
+ hostkey: readString(payload, 1),
+ hostkey_format: undefined,
+ pubkey: readString(payload, payload._pos),
+ sig: readString(payload, payload._pos),
+ sig_format: undefined
+ };
+ info.hostkey_format = readString(info.hostkey, 0, 'ascii');
+ info.sig_format = readString(info.sig, 0, 'ascii');
+ this.emit('KEXDH_REPLY', info);
+};
+
Parser.prototype.hmacVerify = function(hmac) {
this.debug&&this.debug('DEBUG: Parser: Verifying MAC');
if (isGCM(this._decryptType)) {
@@ -706,6 +734,7 @@ Parser.prototype.reset = function() {
this._seqno = 0;
this._kexinit_info = undefined;
this._kexinit = undefined;
+ this._kexdh = undefined;
};
function readString(buffer, start, encoding) {

No commit comments for this range

Something went wrong with that request. Please try again.