Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test1 #1

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion lib/auth_41.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@
server stores sha1(sha1(password)) ( hash_stag2)
*/

const crypto = require('crypto');
const crypto = require('node:crypto');

function sha1(msg, msg1, msg2) {
console.log("auth41")
const hash = crypto.createHash('sha1');
hash.update(msg);
if (msg1) {
Expand Down
4 changes: 3 additions & 1 deletion lib/auth_plugins/caching_sha2_password.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// https://mysqlserverteam.com/mysql-8-0-4-new-default-authentication-plugin-caching_sha2_password/

const PLUGIN_NAME = 'caching_sha2_password';
const crypto = require('crypto');
const crypto = require('node:crypto');
const { xor, xorRotating } = require('../auth_41');

const REQUEST_SERVER_KEY_PACKET = Buffer.from([2]);
Expand All @@ -16,6 +16,7 @@ const STATE_WAIT_SERVER_KEY = 2;
const STATE_FINAL = -1;

function sha256(msg) {
console.log("sha2")
const hash = crypto.createHash('sha256');
hash.update(msg);
return hash.digest();
Expand All @@ -36,6 +37,7 @@ function encrypt(password, scramble, key) {
Buffer.from(`${password}\0`, 'utf8'),
scramble
);
console.log("sha2-encrypt")
return crypto.publicEncrypt(key, stage1);
}

Expand Down
3 changes: 2 additions & 1 deletion lib/auth_plugins/sha256_password.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use strict';

const PLUGIN_NAME = 'sha256_password';
const crypto = require('crypto');
const crypto = require('node:crypto');
const { xorRotating } = require('../auth_41');

const REQUEST_SERVER_KEY_PACKET = Buffer.from([1]);
Expand All @@ -15,6 +15,7 @@ function encrypt(password, scramble, key) {
Buffer.from(`${password}\0`, 'utf8'),
scramble
);
console.log("sha256-encrypt")
return crypto.publicEncrypt(key, stage1);
}

Expand Down
17 changes: 3 additions & 14 deletions lib/commands/client_handshake.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const Packets = require('../packets/index.js');
const ClientConstants = require('../constants/client.js');
const CharsetToEncoding = require('../constants/charset_encodings.js');
const auth41 = require('../auth_41.js');
const {secureStream} = require('../stream.js');

function flagNames(flags) {
const res = [];
Expand Down Expand Up @@ -146,21 +147,9 @@ class ClientHandshake extends Command {
// send ssl upgrade request and immediately upgrade connection to secure
this.clientFlags |= ClientConstants.SSL;
this.sendSSLRequest(connection);
connection.startTLS(err => {
// after connection is secure
if (err) {
// SSL negotiation error are fatal
err.code = 'HANDSHAKE_SSL_ERROR';
err.fatal = true;
this.emit('error', err);
return;
}
// rest of communication is encrypted
this.sendCredentials(connection);
});
} else {
this.sendCredentials(connection);
secureStream(connection)
}
this.sendCredentials(connection);
if (multiFactorAuthentication) {
// if the server supports multi-factor authentication, we enable it in
// the client
Expand Down
8 changes: 4 additions & 4 deletions lib/commands/query.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const Readable = require('stream').Readable;

const Command = require('./command.js');
const Packets = require('../packets/index.js');
const getTextParser = require('../parsers/text_parser.js');
const staticParser = require('../parsers/static_text_parser.js');
const ServerStatus = require('../constants/server_status.js');

const EmptyPacket = new Packets.Packet(0, Buffer.allocUnsafe(4), 0, 4);
Expand Down Expand Up @@ -212,7 +212,7 @@ class Query extends Command {
if (this._receivedFieldsCount === this._fieldCount) {
const fields = this._fields[this._resultIndex];
this.emit('fields', fields);
this._rowParser = new (getTextParser(fields, this.options, connection.config))(fields);
this._rowParser = staticParser(fields, this.options, connection.config);
return Query.prototype.fieldsEOF;
}
return Query.prototype.readField;
Expand All @@ -227,7 +227,7 @@ class Query extends Command {
}

/* eslint no-unused-vars: ["error", { "argsIgnorePattern": "^_" }] */
row(packet, _connection) {
row(packet, _connection) {
if (packet.isEOF()) {
const status = packet.eofStatusFlags();
const moreResults = status & ServerStatus.SERVER_MORE_RESULTS_EXISTS;
Expand Down Expand Up @@ -302,7 +302,7 @@ class Query extends Command {
Timers.clearTimeout(this.queryTimeout);
this.queryTimeout = null;
}

const err = new Error('Query inactivity timeout');
err.errorno = 'PROTOCOL_SEQUENCE_TIMEOUT';
err.code = 'PROTOCOL_SEQUENCE_TIMEOUT';
Expand Down
30 changes: 14 additions & 16 deletions lib/connection.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@

'use strict';

const Net = require('net');
const Tls = require('tls');
const Timers = require('timers');
const EventEmitter = require('events').EventEmitter;
const Readable = require('stream').Readable;
Expand All @@ -29,6 +27,8 @@ const Packets = require('./packets/index.js');
const Commands = require('./commands/index.js');
const ConnectionConfig = require('./connection_config.js');
const CharsetToEncoding = require('./constants/charset_encodings.js');
const {getStream} = require("./stream");


let _connectionId = 0;

Expand All @@ -44,14 +44,11 @@ class Connection extends EventEmitter {
// TODO: use `/usr/local/mysql/bin/mysql_config --socket` output? as default socketPath
// if there is no host/port and no socketPath parameters?
if (!opts.config.stream) {
this.stream = getStream(opts.config.ssl);
if (opts.config.socketPath) {
this.stream = Net.connect(opts.config.socketPath);
this.stream.connect(opts.config.socketPath);
} else {
this.stream = Net.connect(
opts.config.port,
opts.config.host
);

this.stream.connect(opts.config.port, opts.config.host)
// Optionally enable keep-alive on the socket.
if (this.config.enableKeepAlive) {
this.stream.on('connect', () => {
Expand Down Expand Up @@ -146,13 +143,13 @@ class Connection extends EventEmitter {
// most common example: "Too many connections" error ( packet is sent immediately on connection attempt, we don't know server encoding yet)
// will be overwritten with actual encoding value as soon as server handshake packet is received
this.serverEncoding = 'utf8';
if (this.config.connectTimeout) {
const timeoutHandler = this._handleTimeoutError.bind(this);
this.connectTimeout = Timers.setTimeout(
timeoutHandler,
this.config.connectTimeout
);
}
// if (this.config.connectTimeout) {
// const timeoutHandler = this._handleTimeoutError.bind(this);
// this.connectTimeout = Timers.setTimeout(
// timeoutHandler,
// this.config.connectTimeout
// );
// }
}

promise(promiseImpl) {
Expand Down Expand Up @@ -340,6 +337,7 @@ class Connection extends EventEmitter {

// 0.11+ environment
startTLS(onSecure) {
const Tls = require('tls');
if (this.config.debug) {
// eslint-disable-next-line no-console
console.log('Upgrading connection to TLS');
Expand Down Expand Up @@ -408,7 +406,7 @@ class Connection extends EventEmitter {
err.code = code || 'PROTOCOL_ERROR';
this.emit('error', err);
}

get fatalError() {
return this._fatalError;
}
Expand Down
69 changes: 69 additions & 0 deletions lib/crypto/utils-legacy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
'use strict'
// This file contains crypto utility functions for versions of Node.js < 15.0.0,
// which does not support the WebCrypto.subtle API.

const nodeCrypto = require('crypto')

function md5(string) {
return nodeCrypto.createHash('md5').update(string, 'utf-8').digest('hex')
}

// See AuthenticationMD5Password at https://www.postgresql.org/docs/current/static/protocol-flow.html
function postgresMd5PasswordHash(user, password, salt) {
const inner = md5(password + user);
const outer = md5(Buffer.concat([Buffer.from(inner), salt]));
return `md5${outer}`
}

function sha256(text) {
return nodeCrypto.createHash('sha256').update(text).digest()
}

async function sha1(msg,msg1,msg2) {
const hash = nodeCrypto.createHash('sha1');
hash.update(msg);
if (msg1) {
hash.update(msg1);
}
if (msg2) {
hash.update(msg2);
}
return hash.digest();
}

function xorRotating(a, seed) {
const result = Buffer.allocUnsafe(a.length);
const seedLen = seed.length;

for (let i = 0; i < a.length; i++) {
result[i] = a[i] ^ seed[i % seedLen];
}
return result;
}

function encrypt(password, scramble, key) {
const stage1 = xorRotating(
Buffer.from(`${password}\0`, 'utf8'),
scramble
);
return nodeCrypto.publicEncrypt(key, stage1);
}

function hmacSha256(key, msg) {
return nodeCrypto.createHmac('sha256', key).update(msg).digest()
}

function deriveKey(password, salt, iterations) {
return nodeCrypto.pbkdf2Sync(password, salt, iterations, 32, 'sha256')
}

module.exports = {
postgresMd5PasswordHash,
randomBytes: nodeCrypto.randomBytes,
deriveKey,
sha256,
hmacSha256,
md5,
sha1,
encrypt,
}
106 changes: 106 additions & 0 deletions lib/crypto/utils-webcrypto.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
'use strict'

const nodeCrypto = require('crypto')

/**
* The Web Crypto API - grabbed from the Node.js library or the global
* @type Crypto
*/
// eslint-disable-next-line no-undef
const webCrypto = nodeCrypto.webcrypto || globalThis.crypto
/**
* The SubtleCrypto API for low level crypto operations.
* @type SubtleCrypto
*/
const subtleCrypto = webCrypto.subtle
const textEncoder = new TextEncoder()

/**
*
* @param {*} length
* @returns
*/
function randomBytes(length) {
return webCrypto.getRandomValues(Buffer.alloc(length))
}

async function md5(string) {
try {
return nodeCrypto.createHash('md5').update(string, 'utf-8').digest('hex')
} catch (e) {
// `createHash()` failed so we are probably not in Node.js, use the WebCrypto API instead.
// Note that the MD5 algorithm on WebCrypto is not available in Node.js.
// This is why we cannot just use WebCrypto in all environments.
const data = typeof string === 'string' ? textEncoder.encode(string) : string
const hash = await subtleCrypto.digest('MD5', data)
return Array.from(new Uint8Array(hash))
.map(b => b.toString(16).padStart(2, '0'))
.join('')
}
}

// See AuthenticationMD5Password at https://www.postgresql.org/docs/current/static/protocol-flow.html
async function postgresMd5PasswordHash(user, password, salt) {
const inner = await md5(password + user);
const outer = await md5(Buffer.concat([Buffer.from(inner), salt]));
return `md5${outer}`
}

/**
* Create a SHA-256 digest of the given data
* @param {Buffer} data
*/
async function sha256(text) {
return await subtleCrypto.digest('SHA-256', text)
}

/**
* Sign the message with the given key
* @param {ArrayBuffer} keyBuffer
* @param {string} msg
*/
async function hmacSha256(keyBuffer, msg) {
const key = await subtleCrypto.importKey('raw', keyBuffer, { name: 'HMAC', hash: 'SHA-256' }, false, ['sign'])
return await subtleCrypto.sign('HMAC', key, textEncoder.encode(msg))
}

/**
* Derive a key from the password and salt
* @param {string} password
* @param {Uint8Array} salt
* @param {number} iterations
*/
async function deriveKey(password, salt, iterations) {
const key = await subtleCrypto.importKey('raw', textEncoder.encode(password), 'PBKDF2', false, ['deriveBits'])
const params = { name: 'PBKDF2', hash: 'SHA-256', salt: salt, iterations: iterations }
return await subtleCrypto.deriveBits(params, key, 32 * 8, ['deriveBits'])
}

function concatenateBuffers(buffer1, buffer2) {
const combined = new Uint8Array(buffer1.length + buffer2.length);
combined.set(new Uint8Array(buffer1), 0);
combined.set(new Uint8Array(buffer2), buffer1.length);
return combined;
}


async function sha1(msg,msg1,msg2) {

let concatenatedData = textEncoder.encode(msg);
concatenatedData = concatenateBuffers(concatenatedData, textEncoder.encode(msg1));
concatenatedData = concatenateBuffers(concatenatedData, textEncoder.encode(msg2));

const arrayBuffer = await subtleCrypto.digest('SHA-1', concatenatedData)
return Buffer.from(arrayBuffer)
}

module.exports = {
postgresMd5PasswordHash,
randomBytes,
deriveKey,
sha256,
hmacSha256,
md5,
sha1,
}

11 changes: 11 additions & 0 deletions lib/crypto/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
'use strict'

const useLegacyCrypto = parseInt(process.versions && process.versions.node && process.versions.node.split('.')[0]) < 15
if (useLegacyCrypto) {
// We are on an old version of Node.js that requires legacy crypto utilities.
console.log('using legacy')
module.exports = require('./utils-legacy')
} else {
console.log('using webcrypto')
module.exports = require('./utils-webcrypto');
}
2 changes: 1 addition & 1 deletion lib/packets/handshake.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class Handshake {
}

setScrambleData(cb) {
require('crypto').randomBytes(20, (err, data) => {
require('node:crypto').randomBytes(20, (err, data) => {
if (err) {
cb(err);
return;
Expand Down
Loading