123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112 |
- 'use strict';
- const Packet = require('../packets/packet');
- const ClientConstants = require('../constants/client.js');
- // https://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::Handshake
- class Handshake {
- constructor(args) {
- this.protocolVersion = args.protocolVersion;
- this.serverVersion = args.serverVersion;
- this.capabilityFlags = args.capabilityFlags;
- this.connectionId = args.connectionId;
- this.authPluginData1 = args.authPluginData1;
- this.authPluginData2 = args.authPluginData2;
- this.characterSet = args.characterSet;
- this.statusFlags = args.statusFlags;
- this.autPluginName = args.autPluginName;
- }
- setScrambleData(cb) {
- require('crypto').randomBytes(20, (err, data) => {
- if (err) {
- cb(err);
- return;
- }
- this.authPluginData1 = data.slice(0, 8);
- this.authPluginData2 = data.slice(8, 20);
- cb();
- });
- }
- toPacket(sequenceId) {
- const length = 68 + Buffer.byteLength(this.serverVersion, 'utf8');
- const buffer = Buffer.alloc(length + 4, 0); // zero fill, 10 bytes filler later needs to contain zeros
- const packet = new Packet(sequenceId, buffer, 0, length + 4);
- packet.offset = 4;
- packet.writeInt8(this.protocolVersion);
- packet.writeString(this.serverVersion, 'cesu8');
- packet.writeInt8(0);
- packet.writeInt32(this.connectionId);
- packet.writeBuffer(this.authPluginData1);
- packet.writeInt8(0);
- const capabilityFlagsBuffer = Buffer.allocUnsafe(4);
- capabilityFlagsBuffer.writeUInt32LE(this.capabilityFlags, 0);
- packet.writeBuffer(capabilityFlagsBuffer.slice(0, 2));
- packet.writeInt8(this.characterSet);
- packet.writeInt16(this.statusFlags);
- packet.writeBuffer(capabilityFlagsBuffer.slice(2, 4));
- packet.writeInt8(21); // authPluginDataLength
- packet.skip(10);
- packet.writeBuffer(this.authPluginData2);
- packet.writeInt8(0);
- packet.writeString('mysql_native_password', 'latin1');
- packet.writeInt8(0);
- return packet;
- }
- static fromPacket(packet) {
- const args = {};
- args.protocolVersion = packet.readInt8();
- args.serverVersion = packet.readNullTerminatedString('cesu8');
- args.connectionId = packet.readInt32();
- args.authPluginData1 = packet.readBuffer(8);
- packet.skip(1);
- const capabilityFlagsBuffer = Buffer.allocUnsafe(4);
- capabilityFlagsBuffer[0] = packet.readInt8();
- capabilityFlagsBuffer[1] = packet.readInt8();
- if (packet.haveMoreData()) {
- args.characterSet = packet.readInt8();
- args.statusFlags = packet.readInt16();
- // upper 2 bytes
- capabilityFlagsBuffer[2] = packet.readInt8();
- capabilityFlagsBuffer[3] = packet.readInt8();
- args.capabilityFlags = capabilityFlagsBuffer.readUInt32LE(0);
- if (args.capabilityFlags & ClientConstants.PLUGIN_AUTH) {
- args.authPluginDataLength = packet.readInt8();
- } else {
- args.authPluginDataLength = 0;
- packet.skip(1);
- }
- packet.skip(10);
- } else {
- args.capabilityFlags = capabilityFlagsBuffer.readUInt16LE(0);
- }
- const isSecureConnection =
- args.capabilityFlags & ClientConstants.SECURE_CONNECTION;
- if (isSecureConnection) {
- const authPluginDataLength = args.authPluginDataLength;
- if (authPluginDataLength === 0) {
- // for Secure Password Authentication
- args.authPluginDataLength = 20;
- args.authPluginData2 = packet.readBuffer(12);
- packet.skip(1);
- } else {
- // length > 0
- // for Custom Auth Plugin (PLUGIN_AUTH)
- const len = Math.max(13, authPluginDataLength - 8);
- args.authPluginData2 = packet.readBuffer(len);
- }
- }
- if (args.capabilityFlags & ClientConstants.PLUGIN_AUTH) {
- args.autPluginName = packet.readNullTerminatedString('ascii');
- }
- return new Handshake(args);
- }
- }
- module.exports = Handshake;
|