From 71517e26e4212f5877954eaa799b37186def7f41 Mon Sep 17 00:00:00 2001 From: Mike D Pilsbury Date: Tue, 26 Mar 2013 22:50:13 +0000 Subject: [PATCH] Make encrypted connections work with node v0.10. Initiate TLS handshake by writing LOGIN7 packet to tls SecurePair cleartext stream. Needed because streams2 are lazy. Default ciphers to RC4-MD5, as I can't get the default DES-CBC3-SHA to work (yet). fixes #86 --- src/connection.coffee | 13 +++++++------ src/message-io.coffee | 21 ++++++++++++++++----- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/connection.coffee b/src/connection.coffee index 9c4713868..e25bc4ab5 100644 --- a/src/connection.coffee +++ b/src/connection.coffee @@ -61,6 +61,7 @@ class Connection extends EventEmitter @transitionTo(@STATE.SENT_LOGIN7_WITH_STANDARD_LOGIN) tls: -> @initiateTlsSslHandshake() + @sendLogin7Packet() @transitionTo(@STATE.SENT_TLSSSLNEGOTIATION) SENT_TLSSSLNEGOTIATION: @@ -74,11 +75,9 @@ class Connection extends EventEmitter data: (data) -> @securePair.encrypted.write(data) tlsNegotiated: -> - @encryptAllFutureTraffic() @tlsNegotiationComplete = true message: -> if @tlsNegotiationComplete - @sendLogin7Packet() @transitionTo(@STATE.SENT_LOGIN7_WITH_STANDARD_LOGIN) else @@ -399,15 +398,19 @@ class Connection extends EventEmitter ) initiateTlsSslHandshake: -> + @config.options.cryptoCredentialsDetails.ciphers ||= 'RC4-MD5' + credentials = crypto.createCredentials(@config.options.cryptoCredentialsDetails) @securePair = tls.createSecurePair(credentials) @securePair.on('secure', => cipher = @securePair.cleartext.getCipher() @debug.log("TLS negotiated (#{cipher.name}, #{cipher.version})") - #console.log @securePair.cleartext.getPeerCertificate() + # console.log cipher + # console.log @securePair.cleartext.getPeerCertificate() @emit('secure', @securePair.cleartext) + @messageIo.encryptAllFutureTraffic() @dispatchEvent('tlsNegotiated') ) @@ -415,9 +418,7 @@ class Connection extends EventEmitter @messageIo.sendMessage(TYPE.PRELOGIN, data) ) - encryptAllFutureTraffic: -> - @securePair.encrypted.removeAllListeners() - @messageIo.encryptAllFutureTraffic(@securePair) + @messageIo.tlsNegotiationStarting(@securePair) sendDataToTokenStreamParser: (data) -> @tokenStreamParser.addBuffer(data) diff --git a/src/message-io.coffee b/src/message-io.coffee index 54ecc69a1..b44ab1148 100644 --- a/src/message-io.coffee +++ b/src/message-io.coffee @@ -4,6 +4,7 @@ isPacketComplete = require('./packet').isPacketComplete packetLength = require('./packet').packetLength packetHeaderLength = require('./packet').HEADER_LENGTH Packet = require('./packet').Packet +TYPE = require('./packet').TYPE class MessageIO extends EventEmitter constructor: (@socket, @_packetSize, @debug) -> @@ -46,9 +47,11 @@ class MessageIO extends EventEmitter @_packetSize - encryptAllFutureTraffic: (securePair) -> + tlsNegotiationStarting: (securePair) -> @securePair = securePair + @tlsNegotiationInProgress = true; + encryptAllFutureTraffic: () -> @socket.removeAllListeners('data') @securePair.encrypted.removeAllListeners('data') @@ -57,6 +60,8 @@ class MessageIO extends EventEmitter @securePair.cleartext.addListener('data', @eventData) + @tlsNegotiationInProgress = false; + # TODO listen for 'drain' event when socket.write returns false. sendMessage: (packetType, data, resetConnection) -> numberOfPackets = (Math.floor((data.length - 1) / @packetDataSize)) + 1 @@ -75,15 +80,21 @@ class MessageIO extends EventEmitter packet.packetId(packetNumber + 1) packet.addData(packetPayload) - @sendPacket(packet) + @sendPacket(packet, packetType) - sendPacket: (packet) => + sendPacket: (packet, packetType) => @logPacket('Sent', packet); - if (@securePair) + if @tlsNegotiationInProgress && packetType != TYPE.PRELOGIN + # LOGIN7 packet. + # Something written to cleartext stream will initiate TLS handshake. + # Will not emerge from the encrypted stream until after negotiation has completed. @securePair.cleartext.write(packet.buffer) else - @socket.write(packet.buffer) + if (@securePair && !@tlsNegotiationInProgress) + @securePair.cleartext.write(packet.buffer) + else + @socket.write(packet.buffer) logPacket: (direction, packet) -> @debug.packet(direction, packet)