Skip to content

Commit a83cc76

Browse files
committed
Add basic SSL test against fake server
closes #730
1 parent b51fa01 commit a83cc76

File tree

6 files changed

+118
-8
lines changed

6 files changed

+118
-8
lines changed

lib/protocol/packets/HandshakeInitializationPacket.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
var Client = require('../constants/client');
2+
13
module.exports = HandshakeInitializationPacket;
24
function HandshakeInitializationPacket(options) {
35
options = options || {};
@@ -17,6 +19,11 @@ function HandshakeInitializationPacket(options) {
1719
this.filler3 = options.filler3;
1820
this.pluginData = options.pluginData;
1921
this.protocol41 = options.protocol41;
22+
23+
if (this.protocol41) {
24+
// force set the bit in serverCapabilities1
25+
this.serverCapabilities1 |= Client.CLIENT_PROTOCOL_41;
26+
}
2027
}
2128

2229
HandshakeInitializationPacket.prototype.parse = function(parser) {

test/FakeServer.js

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// An experimental fake MySQL server for tricky integration tests. Expanded
22
// as needed.
33

4+
var common = require('./common');
45
var _ = require('underscore');
56
var Net = require('net');
67
var Packets = require('../lib/protocol/packets');
@@ -42,6 +43,7 @@ function FakeConnection(socket) {
4243
EventEmitter.call(this);
4344

4445
this._socket = socket;
46+
this._stream = socket;
4547
this._parser = new Parser({onPacket: this._parsePacket.bind(this)});
4648

4749
this._handshakeInitializationPacket = null;
@@ -92,7 +94,7 @@ FakeConnection.prototype._sendAuthResponse = function(packet, expected) {
9294
FakeConnection.prototype._sendPacket = function(packet) {
9395
var writer = new PacketWriter();
9496
packet.write(writer);
95-
this._socket.write(writer.toBuffer(this._parser));
97+
this._stream.write(writer.toBuffer(this._parser));
9698
};
9799

98100
FakeConnection.prototype._handleData = function(buffer) {
@@ -102,13 +104,13 @@ FakeConnection.prototype._handleData = function(buffer) {
102104
FakeConnection.prototype._parsePacket = function(header) {
103105
var Packet = this._determinePacket(header);
104106
var packet = new Packet({protocol41: true});
107+
var parser = this._parser;
105108

106-
packet.parse(this._parser);
109+
packet.parse(parser);
107110

108111
switch (Packet) {
109112
case Packets.ClientAuthenticationPacket:
110113
this._clientAuthenticationPacket = packet;
111-
112114
if (this._handshakeOptions.oldPassword) {
113115
this._sendPacket(new Packets.UseOldPasswordPacket());
114116
} else if (this._handshakeOptions.password === 'passwd') {
@@ -118,8 +120,29 @@ FakeConnection.prototype._parsePacket = function(header) {
118120
throw new Error('not implemented');
119121
} else {
120122
this._sendPacket(new Packets.OkPacket());
121-
this._parser.resetPacketNumber();
123+
parser.resetPacketNumber();
122124
}
125+
break;
126+
case Packets.SSLRequestPacket:
127+
// halt parser
128+
parser.pause();
129+
this._socket.removeAllListeners('data');
130+
131+
// inject secure pair
132+
var securePair = common.createSecurePair();
133+
this._socket.pipe(securePair.encrypted);
134+
this._stream = securePair.cleartext;
135+
securePair.cleartext.on('data', this._handleData.bind(this));
136+
securePair.encrypted.pipe(this._socket);
137+
138+
// resume
139+
process.nextTick(function() {
140+
var buffer = parser._buffer.slice(parser._offset);
141+
parser._offset = parser._buffer.length;
142+
parser.resume();
143+
securePair.encrypted.write(buffer);
144+
});
145+
123146
break;
124147
case Packets.OldPasswordPacket:
125148
this._oldPasswordPacket = packet;
@@ -133,7 +156,7 @@ FakeConnection.prototype._parsePacket = function(header) {
133156
break;
134157
case Packets.ComPingPacket:
135158
this._sendPacket(new Packets.OkPacket());
136-
this._parser.resetPacketNumber();
159+
parser.resetPacketNumber();
137160
break;
138161
case Packets.ComChangeUserPacket:
139162
this._clientAuthenticationPacket = new Packets.ClientAuthenticationPacket({
@@ -147,7 +170,7 @@ FakeConnection.prototype._parsePacket = function(header) {
147170
user : packet.user
148171
});
149172
this._sendPacket(new Packets.OkPacket());
150-
this._parser.resetPacketNumber();
173+
parser.resetPacketNumber();
151174
break;
152175
case Packets.ComQuitPacket:
153176
this.emit('quit', packet);
@@ -158,10 +181,18 @@ FakeConnection.prototype._parsePacket = function(header) {
158181
}
159182
};
160183

161-
FakeConnection.prototype._determinePacket = function() {
184+
FakeConnection.prototype._determinePacket = function(header) {
162185
if (!this._clientAuthenticationPacket) {
186+
// first packet phase
187+
188+
if (header.length === 32) {
189+
return Packets.SSLRequestPacket;
190+
}
191+
163192
return Packets.ClientAuthenticationPacket;
164-
} else if (this._handshakeOptions.oldPassword && !this._oldPasswordPacket) {
193+
}
194+
195+
if (this._handshakeOptions.oldPassword && !this._oldPasswordPacket) {
165196
return Packets.OldPasswordPacket;
166197
}
167198

test/common.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
var common = exports;
2+
var crypto = require('crypto');
3+
var fs = require('fs');
24
var path = require('path');
5+
var tls = require('tls');
36
var _ = require('underscore');
47
var FakeServer = require('./FakeServer');
58

@@ -45,6 +48,12 @@ common.createFakeServer = function(options) {
4548
return new FakeServer(_.extend({}, options));
4649
};
4750

51+
common.createSecurePair = function() {
52+
var credentials = crypto.createCredentials(common.getSSLConfig());
53+
54+
return tls.createSecurePair(credentials, true);
55+
};
56+
4857
common.useTestDb = function(connection) {
4958
var query = connection.query('CREATE DATABASE ' + common.testDatabase, function(err) {
5059
if (err && err.code !== 'ER_DB_CREATE_EXISTS') throw err;
@@ -57,6 +66,13 @@ common.getTestConfig = function(config) {
5766
return mergeTestConfig(config);
5867
};
5968

69+
common.getSSLConfig = function() {
70+
return {
71+
cert : fs.readFileSync(path.join(common.fixtures, 'server.crt'), 'ascii'),
72+
key : fs.readFileSync(path.join(common.fixtures, 'server.key'), 'ascii')
73+
};
74+
};
75+
6076
function mergeTestConfig(config) {
6177
if (common.isTravis()) {
6278
// see: http://about.travis-ci.org/docs/user/database-setup/

test/fixtures/server.crt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIIB3zCCAUgCCQCZc7IfkXLWeDANBgkqhkiG9w0BAQUFADA0MQswCQYDVQQGEwJV
3+
UzEQMA4GA1UECBMHSW5kaWFuYTETMBEGA1UEChMKbm9kZS1teXNxbDAeFw0xNDA1
4+
MTQxODM2NTdaFw0yNDA1MTExODM2NTdaMDQxCzAJBgNVBAYTAlVTMRAwDgYDVQQI
5+
EwdJbmRpYW5hMRMwEQYDVQQKEwpub2RlLW15c3FsMIGfMA0GCSqGSIb3DQEBAQUA
6+
A4GNADCBiQKBgQDX4dUmhwwzqy8zCrNK5WybifZ4Z5vd12CnnrBpLgqw0VWiKa2b
7+
QQ5vmex4LhEPwr5p+tDntS1sbQf4HY69AgjHtcPAdoykWtUBDCrOjnhEBroLGzE2
8+
BbW0XnolsWUp8Zwnlq3nGOceCcvYX3AjUkK89B3L7YY+Rie/1QQ62FSS2wIDAQAB
9+
MA0GCSqGSIb3DQEBBQUAA4GBABNcExz8o1QxcTBuFIcdny4s6H7diTKeweqAtbPo
10+
JefVNokYjTjFDRdZqDOLKKJPgfyPYHCX170SQ/wr/b0qzNYL1QvBsDM7tvckBK5a
11+
OfKg/4TfMfHORNGRECBJAAn2Zi/DWfcdwOb39wIOG3hDk09IGOJ5F3wsUZFC/qiv
12+
152/
13+
-----END CERTIFICATE-----

test/fixtures/server.key

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
-----BEGIN RSA PRIVATE KEY-----
2+
MIICXAIBAAKBgQDX4dUmhwwzqy8zCrNK5WybifZ4Z5vd12CnnrBpLgqw0VWiKa2b
3+
QQ5vmex4LhEPwr5p+tDntS1sbQf4HY69AgjHtcPAdoykWtUBDCrOjnhEBroLGzE2
4+
BbW0XnolsWUp8Zwnlq3nGOceCcvYX3AjUkK89B3L7YY+Rie/1QQ62FSS2wIDAQAB
5+
AoGAUJvTsjIk/ToDQsTRE7s85YsLTAQr8BbW0V/wsSVu+nz/w7BaUalmEYfhAzL4
6+
TfFClmIAFTTShDTmD+BBhxO2YOQW0+aThwU2jyF6sq7VhHxgXnSVDps9ebmVXMjU
7+
jSZEV/Q3lOvxvQfcBYzV3jfEeyi7jNr5oCL7Y6OwxLLx1XkCQQD3Jv9CNBH0J8c1
8+
nIpkj3Mhd0ona7wFna7hKlIfjZjsK0B9aMvj5I5tTGIis16g4uzSISS4zymHv/yp
9+
njCwi54HAkEA35xDXEsfbvS8d/9MsdJEtuMWGQeHEu8Tdxt5U/WnUPo0r00blrD5
10+
G5+zElKYbJgN15QLOLTUpq8U2dvEjGrvjQJAeO84D+jysAmWzIDgpvwaVdHNEyUA
11+
R680lzDiJlZe8ZDoaXUR710y5ABwNJKYRxlC0D8vfM7Bf49NzqF9KaXnmQJAQyeI
12+
y1T8UbRKTbdsbxL48/vrDQVHuZX3QJQNsftajmU2IVeE65KmnXcurlgD0skvjwi0
13+
/gjAvHZkSrFHq+wJmQJBAK32f4/ssi/SQolzL3xVrEUayxOEVhDWslXtwdcr7ZCq
14+
bbOmEU5AoOVXSS+PsWrLmrDRs3gc9BRHxD7yYVBT9ts=
15+
-----END RSA PRIVATE KEY-----
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
var assert = require('assert');
2+
var common = require('../../common');
3+
var ClientConstants = require('../../../lib/protocol/constants/client');
4+
var connection = common.createConnection({
5+
port : common.fakeServerPort,
6+
ssl : {
7+
ca : common.getSSLConfig().ca
8+
}
9+
});
10+
11+
var server = common.createFakeServer();
12+
13+
var connectErr;
14+
server.listen(common.fakeServerPort, function(err) {
15+
if (err) throw err;
16+
17+
connection.ping(function(err) {
18+
assert.ifError(err);
19+
connection.destroy();
20+
server.destroy();
21+
});
22+
});
23+
24+
server.on('connection', function(incomingConnection) {
25+
incomingConnection.handshake({
26+
serverCapabilities1: ClientConstants.CLIENT_SSL
27+
});
28+
});

0 commit comments

Comments
 (0)