Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit d916479

Browse filesBrowse files
elemountdougwilson
authored andcommitted
Support auth switch in change user flow
closes #1776
1 parent 776d843 commit d916479
Copy full SHA for d916479

File tree

Expand file treeCollapse file tree

6 files changed

+132
-9
lines changed
Filter options
Expand file treeCollapse file tree

6 files changed

+132
-9
lines changed

‎Changes.md

Copy file name to clipboardExpand all lines: Changes.md
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ you spot any mistakes.
1111
* Fix no password support for old password protocol
1212
* Remove special case for handshake in determine packet code
1313
* Small performance improvement starting command sequence
14+
* Support auth switch in change user flow #1776
1415
* Support Node.js 11.x
1516
* Update `bignumber.js` to 6.0.0
1617

‎lib/protocol/Auth.js

Copy file name to clipboardExpand all lines: lib/protocol/Auth.js
+12Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,18 @@ var Buffer = require('safe-buffer').Buffer;
22
var Crypto = require('crypto');
33
var Auth = exports;
44

5+
function auth(name, data, options) {
6+
options = options || {};
7+
8+
switch (name) {
9+
case 'mysql_native_password':
10+
return Auth.token(options.password, data.slice(0, 20));
11+
default:
12+
return undefined;
13+
}
14+
}
15+
Auth.auth = auth;
16+
517
function sha1(msg) {
618
var hash = Crypto.createHash('sha1');
719
hash.update(msg, 'binary');

‎lib/protocol/sequences/ChangeUser.js

Copy file name to clipboardExpand all lines: lib/protocol/sequences/ChangeUser.js
+26Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,14 @@ function ChangeUser(options, callback) {
1515
this._currentConfig = options.currentConfig;
1616
}
1717

18+
ChangeUser.prototype.determinePacket = function determinePacket(firstByte) {
19+
switch (firstByte) {
20+
case 0xfe: return Packets.AuthSwitchRequestPacket;
21+
case 0xff: return Packets.ErrorPacket;
22+
default: return undefined;
23+
}
24+
};
25+
1826
ChangeUser.prototype.start = function(handshakeInitializationPacket) {
1927
var scrambleBuff = handshakeInitializationPacket.scrambleBuff();
2028
scrambleBuff = Auth.token(this._password, scrambleBuff);
@@ -34,6 +42,24 @@ ChangeUser.prototype.start = function(handshakeInitializationPacket) {
3442
this.emit('packet', packet);
3543
};
3644

45+
ChangeUser.prototype['AuthSwitchRequestPacket'] = function (packet) {
46+
var name = packet.authMethodName;
47+
var data = Auth.auth(name, packet.authMethodData, {
48+
password: this._password
49+
});
50+
51+
if (data !== undefined) {
52+
this.emit('packet', new Packets.AuthSwitchResponsePacket({
53+
data: data
54+
}));
55+
} else {
56+
var err = new Error('MySQL is requesting the ' + name + ' authentication method, which is not supported.');
57+
err.code = 'UNSUPPORTED_AUTH_METHOD';
58+
err.fatal = true;
59+
this.end(err);
60+
}
61+
};
62+
3763
ChangeUser.prototype['ErrorPacket'] = function(packet) {
3864
var err = this._packetToError(packet);
3965
err.fatal = true;

‎lib/protocol/sequences/Handshake.js

Copy file name to clipboardExpand all lines: lib/protocol/sequences/Handshake.js
+8-9Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,20 +34,19 @@ Handshake.prototype.determinePacket = function determinePacket(firstByte, parser
3434
};
3535

3636
Handshake.prototype['AuthSwitchRequestPacket'] = function (packet) {
37-
if (packet.authMethodName === 'mysql_native_password') {
38-
var challenge = packet.authMethodData.slice(0, 20);
37+
var name = packet.authMethodName;
38+
var data = Auth.auth(name, packet.authMethodData, {
39+
password: this._config.password
40+
});
3941

42+
if (data !== undefined) {
4043
this.emit('packet', new Packets.AuthSwitchResponsePacket({
41-
data: Auth.token(this._config.password, challenge)
44+
data: data
4245
}));
4346
} else {
44-
var err = new Error(
45-
'MySQL is requesting the ' + packet.authMethodName + ' authentication method, which is not supported.'
46-
);
47-
48-
err.code = 'UNSUPPORTED_AUTH_METHOD';
47+
var err = new Error('MySQL is requesting the ' + name + ' authentication method, which is not supported.');
48+
err.code = 'UNSUPPORTED_AUTH_METHOD';
4949
err.fatal = true;
50-
5150
this.end(err);
5251
}
5352
};
+40Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
var assert = require('assert');
2+
var Buffer = require('safe-buffer').Buffer;
3+
var common = require('../../common');
4+
var connection = common.createConnection({
5+
port : common.fakeServerPort,
6+
user : 'user_1',
7+
password : 'pass_1'
8+
});
9+
10+
var server = common.createFakeServer();
11+
12+
server.listen(common.fakeServerPort, function(err) {
13+
assert.ifError(err);
14+
15+
connection.query('SELECT CURRENT_USER()', function (err, result) {
16+
assert.ifError(err);
17+
assert.strictEqual(result[0]['CURRENT_USER()'], 'user_1@localhost');
18+
19+
connection.changeUser({user: 'user_2', password: 'pass_2'}, function (err) {
20+
assert.ok(err);
21+
assert.equal(err.code, 'UNSUPPORTED_AUTH_METHOD');
22+
assert.equal(err.fatal, true);
23+
assert.ok(/foo_plugin_password/.test(err.message));
24+
25+
connection.destroy();
26+
server.destroy();
27+
});
28+
});
29+
});
30+
31+
server.on('connection', function (incomingConnection) {
32+
incomingConnection.on('changeUser', function () {
33+
this.authSwitchRequest({
34+
authMethodName : 'foo_plugin_password',
35+
authMethodData : Buffer.alloc(0)
36+
});
37+
});
38+
39+
incomingConnection.handshake();
40+
});
+45Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
var assert = require('assert');
2+
var Crypto = require('crypto');
3+
var common = require('../../common');
4+
var connection = common.createConnection({
5+
port : common.fakeServerPort,
6+
user : 'user_1',
7+
password : 'pass_1'
8+
});
9+
10+
var random = Crypto.pseudoRandomBytes || Crypto.randomBytes; // Depends on node.js version
11+
var server = common.createFakeServer();
12+
13+
server.listen(common.fakeServerPort, function(err) {
14+
assert.ifError(err);
15+
16+
connection.query('SELECT CURRENT_USER()', function (err, result) {
17+
assert.ifError(err);
18+
assert.strictEqual(result[0]['CURRENT_USER()'], 'user_1@localhost');
19+
20+
connection.changeUser({user: 'user_2', password: 'pass_2'}, function (err) {
21+
assert.ifError(err);
22+
connection.destroy();
23+
server.destroy();
24+
});
25+
});
26+
});
27+
28+
server.on('connection', function (incomingConnection) {
29+
random(20, function (err, scramble) {
30+
assert.ifError(err);
31+
32+
incomingConnection.on('authSwitchResponse', function (packet) {
33+
this._sendAuthResponse(packet.data, common.Auth.token('pass_2', scramble));
34+
});
35+
36+
incomingConnection.on('changeUser', function () {
37+
this.authSwitchRequest({
38+
authMethodName : 'mysql_native_password',
39+
authMethodData : scramble
40+
});
41+
});
42+
43+
incomingConnection.handshake();
44+
});
45+
});

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.