-
Notifications
You must be signed in to change notification settings - Fork 671
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
lib: add strict key exchange mode support
- Loading branch information
Showing
3 changed files
with
59 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -218,11 +218,18 @@ class Protocol { | |
if (typeof offer !== 'object' || offer === null) { | ||
offer = (this._server ? DEFAULT_KEXINIT_SERVER : DEFAULT_KEXINIT_CLIENT); | ||
} else if (offer.constructor !== KexInit) { | ||
if (!this._server) | ||
offer.kex = offer.kex.concat(['ext-info-c']); | ||
if (this._server) { | ||
offer.kex = offer.kex.concat(['[email protected]']); | ||
} else { | ||
offer.kex = offer.kex.concat([ | ||
'ext-info-c', | ||
'[email protected]', | ||
]); | ||
} | ||
offer = new KexInit(offer); | ||
} | ||
this._kex = undefined; | ||
this._strictMode = undefined; | ||
this._kexinit = undefined; | ||
this._offer = offer; | ||
this._cipher = new NullCipher(0, this._onWrite); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -232,13 +232,37 @@ function handleKexInit(self, payload) { | |
clientList = localKex; | ||
remoteExtInfoEnabled = (serverList.indexOf('ext-info-s') !== -1); | ||
} | ||
if (self._strictMode === undefined) { | ||
if (self._server) { | ||
self._strictMode = | ||
(clientList.indexOf('[email protected]') !== -1); | ||
} else { | ||
self._strictMode = | ||
(serverList.indexOf('[email protected]') !== -1); | ||
} | ||
// Note: We check for seqno of 1 instead of 0 since we increment before | ||
// calling the packet handler | ||
if (self._strictMode) { | ||
debug && debug('Handshake: strict KEX mode enabled'); | ||
if (self._decipher.inSeqno !== 1) { | ||
if (debug) | ||
debug('Handshake: KEXINIT not first packet in strict KEX mode'); | ||
return doFatalError( | ||
self, | ||
'Handshake failed: KEXINIT not first packet in strict KEX mode', | ||
'handshake', | ||
DISCONNECT_REASON.KEY_EXCHANGE_FAILED | ||
); | ||
} | ||
} | ||
} | ||
// Check for agreeable key exchange algorithm | ||
for (i = 0; | ||
i < clientList.length && serverList.indexOf(clientList[i]) === -1; | ||
++i); | ||
if (i === clientList.length) { | ||
// No suitable match found! | ||
debug && debug('Handshake: No matching key exchange algorithm'); | ||
debug && debug('Handshake: no matching key exchange algorithm'); | ||
return doFatalError( | ||
self, | ||
'Handshake failed: no matching key exchange algorithm', | ||
|
@@ -1236,6 +1260,8 @@ const createKeyExchange = (() => { | |
'Inbound: NEWKEYS' | ||
); | ||
this._receivedNEWKEYS = true; | ||
if (this._protocol._strictMode) | ||
this._protocol._decipher.inSeqno = 0; | ||
++this._step; | ||
|
||
return this.finish(!this._protocol._server && !this._hostVerified); | ||
|
@@ -1756,11 +1782,20 @@ function onKEXPayload(state, payload) { | |
payload = this._packetRW.read.read(payload); | ||
|
||
const type = payload[0]; | ||
|
||
if (!this._strictMode) { | ||
switch (type) { | ||
case MESSAGE.IGNORE: | ||
case MESSAGE.UNIMPLEMENTED: | ||
case MESSAGE.DEBUG: | ||
if (!MESSAGE_HANDLERS) | ||
MESSAGE_HANDLERS = require('./handlers.js'); | ||
return MESSAGE_HANDLERS[type](this, payload); | ||
} | ||
} | ||
|
||
switch (type) { | ||
case MESSAGE.DISCONNECT: | ||
case MESSAGE.IGNORE: | ||
case MESSAGE.UNIMPLEMENTED: | ||
case MESSAGE.DEBUG: | ||
if (!MESSAGE_HANDLERS) | ||
MESSAGE_HANDLERS = require('./handlers.js'); | ||
return MESSAGE_HANDLERS[type](this, payload); | ||
|
@@ -1776,6 +1811,8 @@ function onKEXPayload(state, payload) { | |
state.firstPacket = false; | ||
return handleKexInit(this, payload); | ||
default: | ||
// Ensure packet is either an algorithm negotiation or KEX | ||
// algorithm-specific packet | ||
if (type < 20 || type > 49) { | ||
return doFatalError( | ||
this, | ||
|
@@ -1824,6 +1861,8 @@ function trySendNEWKEYS(kex) { | |
kex._protocol._packetRW.write.finalize(packet, true) | ||
); | ||
kex._sentNEWKEYS = true; | ||
if (kex._protocol._strictMode) | ||
kex._protocol._cipher.outSeqno = 0; | ||
} | ||
} | ||
|
||
|
@@ -1832,7 +1871,7 @@ module.exports = { | |
kexinit, | ||
onKEXPayload, | ||
DEFAULT_KEXINIT_CLIENT: new KexInit({ | ||
kex: DEFAULT_KEX.concat(['ext-info-c']), | ||
kex: DEFAULT_KEX.concat(['ext-info-c', '[email protected]']), | ||
serverHostKey: DEFAULT_SERVER_HOST_KEY, | ||
cs: { | ||
cipher: DEFAULT_CIPHER, | ||
|
@@ -1848,7 +1887,7 @@ module.exports = { | |
}, | ||
}), | ||
DEFAULT_KEXINIT_SERVER: new KexInit({ | ||
kex: DEFAULT_KEX, | ||
kex: DEFAULT_KEX.concat(['[email protected]']), | ||
serverHostKey: DEFAULT_SERVER_HOST_KEY, | ||
cs: { | ||
cipher: DEFAULT_CIPHER, | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -294,7 +294,11 @@ class Server extends EventEmitter { | |
} | ||
|
||
const algorithms = { | ||
kex: generateAlgorithmList(cfgAlgos.kex, DEFAULT_KEX, SUPPORTED_KEX), | ||
kex: generateAlgorithmList( | ||
cfgAlgos.kex, | ||
DEFAULT_KEX, | ||
SUPPORTED_KEX | ||
).concat(['[email protected]']), | ||
serverHostKey: hostKeyAlgoOrder, | ||
cs: { | ||
cipher: generateAlgorithmList( | ||
|