From 158562f3d1248d3410d8122396a153b7b2b87cc6 Mon Sep 17 00:00:00 2001 From: Bruno Harbulot Date: Tue, 7 Aug 2012 13:51:37 +0200 Subject: [PATCH] Initial support for SSL/TLS connections. --- lib/client.js | 12 ++++++++- lib/connection.js | 63 ++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 70 insertions(+), 5 deletions(-) diff --git a/lib/client.js b/lib/client.js index a2eb2928..2b7e51a4 100644 --- a/lib/client.js +++ b/lib/client.js @@ -24,7 +24,7 @@ var Client = function(config) { this.encoding = 'utf8'; this.processID = null; this.secretKey = null; - var self = this; + this.ssl = config.ssl || false; }; util.inherits(Client, EventEmitter); @@ -43,6 +43,16 @@ p.connect = function(callback) { //once connection is established send startup message con.on('connect', function() { + if (self.ssl) { + con.requestSsl(); + } else { + con.startup({ + user: self.user, + database: self.database + }); + } + }); + con.on('sslconnect', function() { con.startup({ user: self.user, database: self.database diff --git a/lib/connection.js b/lib/connection.js index de0d6fc3..5ea1ce23 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -17,6 +17,7 @@ var Connection = function(config) { this.encoding = 'utf8'; this.parsedStatements = {}; this.writer = new Writer(); + this.checkSslResponse = false; }; util.inherits(Connection, EventEmitter); @@ -37,14 +38,42 @@ p.connect = function(port, host) { this.stream.on('connect', function() { self.emit('connect'); }); - + + this.on('sslresponse', function(msg) { + if (msg.text == 0x53) { + var tls = require('tls'); + self.stream.removeAllListeners(); + self.stream = tls.connect({ socket: self.stream, servername: host, rejectUnauthorized: true }); + self.stream.on('data', function(buffer) { + self.setBuffer(buffer); + var msg; + while(msg = self.parseMessage()) { + self.emit('message', msg); + self.emit(msg.name, msg); + } + }); + self.stream.on('error', function(error) { + self.emit('error', error); + }); + self.emit('sslconnect'); + } else { + throw new Error("The server doesn't support SSL/TLS connections."); + } + }); this.stream.on('data', function(buffer) { self.setBuffer(buffer); var msg; - while(msg = self.parseMessage()) { - self.emit('message', msg); - self.emit(msg.name, msg); + if (self.checkSslResponse) { + while(msg = self.readSslResponse()) { + self.emit('message', msg); + self.emit(msg.name, msg); + } + } else { + while(msg = self.parseMessage()) { + self.emit('message', msg); + self.emit(msg.name, msg); + } } }); @@ -53,6 +82,22 @@ p.connect = function(port, host) { }); }; +p.requestSsl = function(config) { + this.checkSslResponse = true; + + var bodyBuffer = this.writer + .addInt16(0x04D2) + .addInt16(0x162F).flush(); + + var length = bodyBuffer.length + 4; + + var buffer = new Writer() + .addInt32(length) + .add(bodyBuffer) + .join(); + this.stream.write(buffer); +} + p.startup = function(config) { var bodyBuffer = this.writer .addInt16(3) @@ -225,6 +270,16 @@ p.setBuffer = function(buffer) { this.offset = 0; }; +p.readSslResponse = function() { + var remaining = this.buffer.length - (this.offset); + if(remaining < 1) { + this.lastBuffer = this.buffer; + this.lastOffset = this.offset; + return false; + } + return { name: 'sslresponse', text: this.buffer[this.offset++] }; +}; + p.parseMessage = function() { var remaining = this.buffer.length - (this.offset); if(remaining < 5) {