@depup/mysql2 3.19.0-depup.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/License +19 -0
- package/README.md +114 -0
- package/index.d.ts +1 -0
- package/index.js +77 -0
- package/lib/auth_41.js +95 -0
- package/lib/auth_plugins/caching_sha2_password.js +114 -0
- package/lib/auth_plugins/caching_sha2_password.md +18 -0
- package/lib/auth_plugins/index.js +8 -0
- package/lib/auth_plugins/mysql_clear_password.js +17 -0
- package/lib/auth_plugins/mysql_native_password.js +34 -0
- package/lib/auth_plugins/sha256_password.js +68 -0
- package/lib/base/connection.js +988 -0
- package/lib/base/pool.js +282 -0
- package/lib/base/pool_connection.js +77 -0
- package/lib/commands/auth_switch.js +129 -0
- package/lib/commands/binlog_dump.js +109 -0
- package/lib/commands/change_user.js +68 -0
- package/lib/commands/client_handshake.js +383 -0
- package/lib/commands/close_statement.js +18 -0
- package/lib/commands/command.js +54 -0
- package/lib/commands/execute.js +112 -0
- package/lib/commands/index.js +27 -0
- package/lib/commands/ping.js +36 -0
- package/lib/commands/prepare.js +143 -0
- package/lib/commands/query.js +361 -0
- package/lib/commands/quit.js +29 -0
- package/lib/commands/register_slave.js +27 -0
- package/lib/commands/server_handshake.js +202 -0
- package/lib/compressed_protocol.js +153 -0
- package/lib/connection.js +12 -0
- package/lib/connection_config.js +293 -0
- package/lib/constants/charset_encodings.js +317 -0
- package/lib/constants/charsets.js +317 -0
- package/lib/constants/client.js +38 -0
- package/lib/constants/commands.js +36 -0
- package/lib/constants/cursor.js +8 -0
- package/lib/constants/encoding_charset.js +50 -0
- package/lib/constants/errors.js +3973 -0
- package/lib/constants/field_flags.js +20 -0
- package/lib/constants/server_status.js +44 -0
- package/lib/constants/session_track.js +11 -0
- package/lib/constants/ssl_profiles.js +11 -0
- package/lib/constants/types.js +64 -0
- package/lib/create_connection.js +10 -0
- package/lib/create_pool.js +10 -0
- package/lib/create_pool_cluster.js +9 -0
- package/lib/helpers.js +83 -0
- package/lib/packet_parser.js +195 -0
- package/lib/packets/auth_next_factor.js +35 -0
- package/lib/packets/auth_switch_request.js +38 -0
- package/lib/packets/auth_switch_request_more_data.js +33 -0
- package/lib/packets/auth_switch_response.js +30 -0
- package/lib/packets/binary_row.js +95 -0
- package/lib/packets/binlog_dump.js +33 -0
- package/lib/packets/binlog_query_statusvars.js +115 -0
- package/lib/packets/change_user.js +97 -0
- package/lib/packets/close_statement.js +21 -0
- package/lib/packets/column_definition.js +291 -0
- package/lib/packets/execute.js +214 -0
- package/lib/packets/handshake.js +112 -0
- package/lib/packets/handshake_response.js +173 -0
- package/lib/packets/index.js +152 -0
- package/lib/packets/packet.js +946 -0
- package/lib/packets/prepare_statement.js +27 -0
- package/lib/packets/prepared_statement_header.js +16 -0
- package/lib/packets/query.js +27 -0
- package/lib/packets/register_slave.js +46 -0
- package/lib/packets/resultset_header.js +124 -0
- package/lib/packets/ssl_request.js +25 -0
- package/lib/packets/text_row.js +47 -0
- package/lib/parsers/binary_parser.js +235 -0
- package/lib/parsers/parser_cache.js +68 -0
- package/lib/parsers/static_binary_parser.js +213 -0
- package/lib/parsers/static_text_parser.js +152 -0
- package/lib/parsers/string.js +50 -0
- package/lib/parsers/text_parser.js +214 -0
- package/lib/pool.js +12 -0
- package/lib/pool_cluster.js +375 -0
- package/lib/pool_config.js +30 -0
- package/lib/pool_connection.js +12 -0
- package/lib/promise/connection.js +228 -0
- package/lib/promise/inherit_events.js +27 -0
- package/lib/promise/make_done_cb.js +19 -0
- package/lib/promise/pool.js +118 -0
- package/lib/promise/pool_cluster.js +54 -0
- package/lib/promise/pool_connection.js +23 -0
- package/lib/promise/prepared_statement_info.js +32 -0
- package/lib/results_stream.js +38 -0
- package/lib/server.js +37 -0
- package/package.json +96 -0
- package/promise.d.ts +139 -0
- package/promise.js +208 -0
- package/typings/mysql/LICENSE.txt +15 -0
- package/typings/mysql/index.d.ts +84 -0
- package/typings/mysql/info.txt +1 -0
- package/typings/mysql/lib/Auth.d.ts +30 -0
- package/typings/mysql/lib/Connection.d.ts +442 -0
- package/typings/mysql/lib/Pool.d.ts +71 -0
- package/typings/mysql/lib/PoolCluster.d.ts +92 -0
- package/typings/mysql/lib/PoolConnection.d.ts +11 -0
- package/typings/mysql/lib/Server.d.ts +11 -0
- package/typings/mysql/lib/constants/CharsetToEncoding.d.ts +8 -0
- package/typings/mysql/lib/constants/Charsets.d.ts +326 -0
- package/typings/mysql/lib/constants/Types.d.ts +70 -0
- package/typings/mysql/lib/constants/index.d.ts +5 -0
- package/typings/mysql/lib/parsers/ParserCache.d.ts +4 -0
- package/typings/mysql/lib/parsers/index.d.ts +18 -0
- package/typings/mysql/lib/parsers/typeCast.d.ts +54 -0
- package/typings/mysql/lib/protocol/packets/Field.d.ts +10 -0
- package/typings/mysql/lib/protocol/packets/FieldPacket.d.ts +27 -0
- package/typings/mysql/lib/protocol/packets/OkPacket.d.ts +23 -0
- package/typings/mysql/lib/protocol/packets/ProcedurePacket.d.ts +13 -0
- package/typings/mysql/lib/protocol/packets/ResultSetHeader.d.ts +18 -0
- package/typings/mysql/lib/protocol/packets/RowDataPacket.d.ts +9 -0
- package/typings/mysql/lib/protocol/packets/index.d.ts +28 -0
- package/typings/mysql/lib/protocol/packets/params/ErrorPacketParams.d.ts +6 -0
- package/typings/mysql/lib/protocol/packets/params/OkPacketParams.d.ts +9 -0
- package/typings/mysql/lib/protocol/sequences/ExecutableBase.d.ts +41 -0
- package/typings/mysql/lib/protocol/sequences/Prepare.d.ts +65 -0
- package/typings/mysql/lib/protocol/sequences/Query.d.ts +228 -0
- package/typings/mysql/lib/protocol/sequences/QueryableBase.d.ts +41 -0
- package/typings/mysql/lib/protocol/sequences/Sequence.d.ts +5 -0
- package/typings/mysql/lib/protocol/sequences/promise/ExecutableBase.d.ts +17 -0
- package/typings/mysql/lib/protocol/sequences/promise/QueryableBase.d.ts +18 -0
package/License
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
Copyright (c) 2016 Andrey Sidorov (sidorares@yandex.ru) and contributors
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
5
|
+
in the Software without restriction, including without limitation the rights
|
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
8
|
+
furnished to do so, subject to the following conditions:
|
|
9
|
+
|
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
|
11
|
+
all copies or substantial portions of the Software.
|
|
12
|
+
|
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
19
|
+
THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
[npm-image]: https://img.shields.io/npm/v/mysql2.svg
|
|
2
|
+
[npm-url]: https://npmjs.com/package/mysql2
|
|
3
|
+
[node-version-image]: https://img.shields.io/node/v/mysql2.svg
|
|
4
|
+
[node-version-url]: https://nodejs.org/en/download
|
|
5
|
+
[downloads-image]: https://img.shields.io/npm/dm/mysql2.svg
|
|
6
|
+
[downloads-url]: https://npmjs.com/package/mysql2
|
|
7
|
+
[license-url]: https://github.com/sidorares/node-mysql2/blob/master/License
|
|
8
|
+
[license-image]: https://img.shields.io/npm/l/mysql2.svg?maxAge=2592000
|
|
9
|
+
[node-mysql]: https://github.com/mysqljs/mysql
|
|
10
|
+
[mysqljs]: https://github.com/mysqljs
|
|
11
|
+
[mysql-native]: https://github.com/sidorares/nodejs-mysql-native
|
|
12
|
+
[sidorares]: https://github.com/sidorares
|
|
13
|
+
[TooTallNate]: https://gist.github.com/TooTallNate
|
|
14
|
+
[starttls.js]: https://gist.github.com/TooTallNate/848444
|
|
15
|
+
[node-mariasql]: https://github.com/mscdex/node-mariasql
|
|
16
|
+
[contributors]: https://github.com/sidorares/node-mysql2/graphs/contributors
|
|
17
|
+
[contributing]: https://github.com/sidorares/node-mysql2/blob/master/Contributing.md
|
|
18
|
+
[docs-base]: https://sidorares.github.io/node-mysql2/docs
|
|
19
|
+
[docs-base-zh-CN]: https://sidorares.github.io/node-mysql2/zh-CN/docs
|
|
20
|
+
[docs-base-pt-BR]: https://sidorares.github.io/node-mysql2/pt-BR/docs
|
|
21
|
+
[docs-prepared-statements]: https://sidorares.github.io/node-mysql2/docs/documentation/prepared-statements
|
|
22
|
+
[docs-mysql-server]: https://sidorares.github.io/node-mysql2/docs/documentation/mysql-server
|
|
23
|
+
[docs-promise-wrapper]: https://sidorares.github.io/node-mysql2/docs/documentation/promise-wrapper
|
|
24
|
+
[docs-authentication-switch]: https://sidorares.github.io/node-mysql2/docs/documentation/authentication-switch
|
|
25
|
+
[docs-streams]: https://sidorares.github.io/node-mysql2/docs/documentation/extras
|
|
26
|
+
[docs-typescript-docs]: https://sidorares.github.io/node-mysql2/docs/documentation/typescript-examples
|
|
27
|
+
[docs-qs-pooling]: https://sidorares.github.io/node-mysql2/docs#using-connection-pools
|
|
28
|
+
[docs-qs-first-query]: https://sidorares.github.io/node-mysql2/docs#first-query
|
|
29
|
+
[docs-qs-using-prepared-statements]: https://sidorares.github.io/node-mysql2/docs#using-prepared-statements
|
|
30
|
+
[docs-examples]: https://sidorares.github.io/node-mysql2/docs/examples
|
|
31
|
+
[docs-faq]: https://sidorares.github.io/node-mysql2/docs/faq
|
|
32
|
+
[docs-documentation]: https://sidorares.github.io/node-mysql2/docs/documentation
|
|
33
|
+
[docs-contributing]: https://sidorares.github.io/node-mysql2/docs/contributing/website
|
|
34
|
+
[coverage]: https://img.shields.io/codecov/c/github/sidorares/node-mysql2
|
|
35
|
+
[coverage-url]: https://app.codecov.io/github/sidorares/node-mysql2
|
|
36
|
+
[ci-url]: https://github.com/sidorares/node-mysql2/actions/workflows/ci-coverage.yml?query=branch%3Amaster
|
|
37
|
+
[ci-image]: https://img.shields.io/github/actions/workflow/status/sidorares/node-mysql2/ci-coverage.yml?event=push&style=flat&label=CI&branch=master
|
|
38
|
+
|
|
39
|
+
# MySQL2
|
|
40
|
+
|
|
41
|
+
[![NPM Version][npm-image]][npm-url]
|
|
42
|
+
[![NPM Downloads][downloads-image]][downloads-url]
|
|
43
|
+
[![Node.js Version][node-version-image]][node-version-url]
|
|
44
|
+
[![GitHub Workflow Status (with event)][ci-image]][ci-url]
|
|
45
|
+
[![Codecov][coverage]][coverage-url]
|
|
46
|
+
[![License][license-image]][license-url]
|
|
47
|
+
|
|
48
|
+
[English][docs-base] | [简体中文][docs-base-zh-CN] | [Português (BR)][docs-base-pt-BR]
|
|
49
|
+
|
|
50
|
+
> MySQL client for Node.js with focus on performance. Supports prepared statements, non-utf8 encodings, binary log protocol, compression, ssl [much more][docs-documentation].
|
|
51
|
+
|
|
52
|
+
**Table of Contents**
|
|
53
|
+
|
|
54
|
+
- [History and Why MySQL2](#history-and-why-mysql2)
|
|
55
|
+
- [Installation](#installation)
|
|
56
|
+
- [Documentation](#documentation)
|
|
57
|
+
- [Acknowledgements](#acknowledgements)
|
|
58
|
+
- [Contributing](#contributing)
|
|
59
|
+
|
|
60
|
+
## History and Why MySQL2
|
|
61
|
+
|
|
62
|
+
MySQL2 project is a continuation of [MySQL-Native][mysql-native]. Protocol parser code was rewritten from scratch and api changed to match popular [Node MySQL][node-mysql]. MySQL2 team is working together with [Node MySQL][node-mysql] team to factor out shared code and move it under [mysqljs][mysqljs] organization.
|
|
63
|
+
|
|
64
|
+
MySQL2 is mostly API compatible with [Node MySQL][node-mysql] and supports majority of features. MySQL2 also offers these additional features:
|
|
65
|
+
|
|
66
|
+
- Faster / Better Performance
|
|
67
|
+
- [Prepared Statements][docs-prepared-statements]
|
|
68
|
+
- MySQL Binary Log Protocol
|
|
69
|
+
- [MySQL Server][docs-mysql-server]
|
|
70
|
+
- Extended support for Encoding and Collation
|
|
71
|
+
- [Promise Wrapper][docs-promise-wrapper]
|
|
72
|
+
- Compression
|
|
73
|
+
- SSL and [Authentication Switch][docs-authentication-switch]
|
|
74
|
+
- [Custom Streams][docs-streams]
|
|
75
|
+
- [Pooling][docs-qs-pooling]
|
|
76
|
+
|
|
77
|
+
## Installation
|
|
78
|
+
|
|
79
|
+
MySQL2 is free from native bindings and can be installed on Linux, Mac OS or Windows without any issues.
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
npm install --save mysql2
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
If you are using TypeScript, you will need to install `@types/node`.
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
npm install --save-dev @types/node
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
> For TypeScript documentation and examples, see [here][docs-typescript-docs].
|
|
92
|
+
|
|
93
|
+
## Documentation
|
|
94
|
+
|
|
95
|
+
- [Quickstart][docs-base]
|
|
96
|
+
- [First Query][docs-qs-first-query], [Using Prepared Statements][docs-qs-using-prepared-statements], [Using Connection Pools][docs-qs-pooling] and more.
|
|
97
|
+
- [Documentation][docs-documentation]
|
|
98
|
+
- [Examples][docs-examples]
|
|
99
|
+
- [FAQ][docs-faq]
|
|
100
|
+
|
|
101
|
+
## Acknowledgements
|
|
102
|
+
|
|
103
|
+
- Internal protocol is written by [@sidorares][sidorares] [MySQL-Native][mysql-native].
|
|
104
|
+
- Constants, SQL parameters interpolation, Pooling, `ConnectionConfig` class taken from [Node MySQL][node-mysql].
|
|
105
|
+
- SSL upgrade code based on [@TooTallNate][TooTallNate] [code][starttls.js].
|
|
106
|
+
- Secure connection / compressed connection api flags compatible to [MariaSQL][node-mariasql] client.
|
|
107
|
+
- [Contributors][contributors].
|
|
108
|
+
|
|
109
|
+
## Contributing
|
|
110
|
+
|
|
111
|
+
Want to improve something in **MySQL2**?
|
|
112
|
+
Please check [Contributing.md][contributing] for detailed instruction on how to get started.
|
|
113
|
+
|
|
114
|
+
To contribute in **MySQL2 Documentation**, please visit the [Website Contributing Guidelines][docs-contributing] for detailed instruction on how to get started.
|
package/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './typings/mysql/index.js';
|
package/index.js
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const SqlString = require('sql-escaper');
|
|
4
|
+
|
|
5
|
+
const ConnectionConfig = require('./lib/connection_config.js');
|
|
6
|
+
const parserCache = require('./lib/parsers/parser_cache.js');
|
|
7
|
+
|
|
8
|
+
const Connection = require('./lib/connection.js');
|
|
9
|
+
|
|
10
|
+
exports.createConnection = require('./lib/create_connection.js');
|
|
11
|
+
exports.connect = exports.createConnection;
|
|
12
|
+
exports.Connection = Connection;
|
|
13
|
+
exports.ConnectionConfig = ConnectionConfig;
|
|
14
|
+
|
|
15
|
+
const Pool = require('./lib/pool.js');
|
|
16
|
+
const PoolCluster = require('./lib/pool_cluster.js');
|
|
17
|
+
const createPool = require('./lib/create_pool.js');
|
|
18
|
+
const createPoolCluster = require('./lib/create_pool_cluster.js');
|
|
19
|
+
|
|
20
|
+
exports.createPool = createPool;
|
|
21
|
+
|
|
22
|
+
exports.createPoolCluster = createPoolCluster;
|
|
23
|
+
|
|
24
|
+
exports.createQuery = Connection.createQuery;
|
|
25
|
+
|
|
26
|
+
exports.Pool = Pool;
|
|
27
|
+
|
|
28
|
+
exports.PoolCluster = PoolCluster;
|
|
29
|
+
|
|
30
|
+
exports.createServer = function (handler) {
|
|
31
|
+
const Server = require('./lib/server.js');
|
|
32
|
+
const s = new Server();
|
|
33
|
+
if (handler) {
|
|
34
|
+
s.on('connection', handler);
|
|
35
|
+
}
|
|
36
|
+
return s;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
exports.PoolConnection = require('./lib/pool_connection.js');
|
|
40
|
+
exports.authPlugins = require('./lib/auth_plugins');
|
|
41
|
+
exports.escape = SqlString.escape;
|
|
42
|
+
exports.escapeId = SqlString.escapeId;
|
|
43
|
+
exports.format = SqlString.format;
|
|
44
|
+
exports.raw = SqlString.raw;
|
|
45
|
+
|
|
46
|
+
exports.__defineGetter__(
|
|
47
|
+
'createConnectionPromise',
|
|
48
|
+
() => require('./promise.js').createConnection
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
exports.__defineGetter__(
|
|
52
|
+
'createPoolPromise',
|
|
53
|
+
() => require('./promise.js').createPool
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
exports.__defineGetter__(
|
|
57
|
+
'createPoolClusterPromise',
|
|
58
|
+
() => require('./promise.js').createPoolCluster
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
exports.__defineGetter__('Types', () => require('./lib/constants/types.js'));
|
|
62
|
+
|
|
63
|
+
exports.__defineGetter__('Charsets', () =>
|
|
64
|
+
require('./lib/constants/charsets.js')
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
exports.__defineGetter__('CharsetToEncoding', () =>
|
|
68
|
+
require('./lib/constants/charset_encodings.js')
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
exports.setMaxParserCache = function (max) {
|
|
72
|
+
parserCache.setMaxCache(max);
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
exports.clearParserCache = function () {
|
|
76
|
+
parserCache.clearCache();
|
|
77
|
+
};
|
package/lib/auth_41.js
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
4.1 authentication: (http://bazaar.launchpad.net/~mysql/mysql-server/5.5/view/head:/sql/password.c)
|
|
5
|
+
|
|
6
|
+
SERVER: public_seed=create_random_string()
|
|
7
|
+
send(public_seed)
|
|
8
|
+
|
|
9
|
+
CLIENT: recv(public_seed)
|
|
10
|
+
hash_stage1=sha1("password")
|
|
11
|
+
hash_stage2=sha1(hash_stage1)
|
|
12
|
+
reply=xor(hash_stage1, sha1(public_seed,hash_stage2)
|
|
13
|
+
|
|
14
|
+
// this three steps are done in scramble()
|
|
15
|
+
|
|
16
|
+
send(reply)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
SERVER: recv(reply)
|
|
20
|
+
hash_stage1=xor(reply, sha1(public_seed,hash_stage2))
|
|
21
|
+
candidate_hash2=sha1(hash_stage1)
|
|
22
|
+
check(candidate_hash2==hash_stage2)
|
|
23
|
+
|
|
24
|
+
server stores sha1(sha1(password)) ( hash_stag2)
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
const crypto = require('crypto');
|
|
28
|
+
|
|
29
|
+
function sha1(msg, msg1, msg2) {
|
|
30
|
+
const hash = crypto.createHash('sha1');
|
|
31
|
+
hash.update(msg);
|
|
32
|
+
if (msg1) {
|
|
33
|
+
hash.update(msg1);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (msg2) {
|
|
37
|
+
hash.update(msg2);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return hash.digest();
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function xor(a, b) {
|
|
44
|
+
const result = Buffer.allocUnsafe(a.length);
|
|
45
|
+
for (let i = 0; i < a.length; i++) {
|
|
46
|
+
result[i] = a[i] ^ b[i];
|
|
47
|
+
}
|
|
48
|
+
return result;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
exports.xor = xor;
|
|
52
|
+
|
|
53
|
+
function token(password, scramble1, scramble2) {
|
|
54
|
+
if (!password) {
|
|
55
|
+
return Buffer.alloc(0);
|
|
56
|
+
}
|
|
57
|
+
const stage1 = sha1(password);
|
|
58
|
+
return exports.calculateTokenFromPasswordSha(stage1, scramble1, scramble2);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
exports.calculateTokenFromPasswordSha = function (
|
|
62
|
+
passwordSha,
|
|
63
|
+
scramble1,
|
|
64
|
+
scramble2
|
|
65
|
+
) {
|
|
66
|
+
// we use AUTH 41 here, and we need only the bytes we just need.
|
|
67
|
+
const authPluginData1 = scramble1.slice(0, 8);
|
|
68
|
+
const authPluginData2 = scramble2.slice(0, 12);
|
|
69
|
+
const stage2 = sha1(passwordSha);
|
|
70
|
+
const stage3 = sha1(authPluginData1, authPluginData2, stage2);
|
|
71
|
+
return xor(stage3, passwordSha);
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
exports.calculateToken = token;
|
|
75
|
+
|
|
76
|
+
exports.verifyToken = function (publicSeed1, publicSeed2, token, doubleSha) {
|
|
77
|
+
const hashStage1 = xor(token, sha1(publicSeed1, publicSeed2, doubleSha));
|
|
78
|
+
const candidateHash2 = sha1(hashStage1);
|
|
79
|
+
return candidateHash2.compare(doubleSha) === 0;
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
exports.doubleSha1 = function (password) {
|
|
83
|
+
return sha1(sha1(password));
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
function xorRotating(a, seed) {
|
|
87
|
+
const result = Buffer.allocUnsafe(a.length);
|
|
88
|
+
const seedLen = seed.length;
|
|
89
|
+
|
|
90
|
+
for (let i = 0; i < a.length; i++) {
|
|
91
|
+
result[i] = a[i] ^ seed[i % seedLen];
|
|
92
|
+
}
|
|
93
|
+
return result;
|
|
94
|
+
}
|
|
95
|
+
exports.xorRotating = xorRotating;
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// https://mysqlserverteam.com/mysql-8-0-4-new-default-authentication-plugin-caching_sha2_password/
|
|
4
|
+
|
|
5
|
+
const PLUGIN_NAME = 'caching_sha2_password';
|
|
6
|
+
const crypto = require('crypto');
|
|
7
|
+
const { xor, xorRotating } = require('../auth_41');
|
|
8
|
+
|
|
9
|
+
const REQUEST_SERVER_KEY_PACKET = Buffer.from([2]);
|
|
10
|
+
const FAST_AUTH_SUCCESS_PACKET = Buffer.from([3]);
|
|
11
|
+
const PERFORM_FULL_AUTHENTICATION_PACKET = Buffer.from([4]);
|
|
12
|
+
|
|
13
|
+
const STATE_INITIAL = 0;
|
|
14
|
+
const STATE_TOKEN_SENT = 1;
|
|
15
|
+
const STATE_WAIT_SERVER_KEY = 2;
|
|
16
|
+
const STATE_FINAL = -1;
|
|
17
|
+
|
|
18
|
+
function sha256(msg) {
|
|
19
|
+
const hash = crypto.createHash('sha256');
|
|
20
|
+
hash.update(msg);
|
|
21
|
+
return hash.digest();
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function calculateToken(password, scramble) {
|
|
25
|
+
if (!password) {
|
|
26
|
+
return Buffer.alloc(0);
|
|
27
|
+
}
|
|
28
|
+
const stage1 = sha256(Buffer.from(password));
|
|
29
|
+
const stage2 = sha256(stage1);
|
|
30
|
+
const stage3 = sha256(Buffer.concat([stage2, scramble]));
|
|
31
|
+
return xor(stage1, stage3);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function encrypt(password, scramble, key) {
|
|
35
|
+
const stage1 = xorRotating(Buffer.from(`${password}\0`, 'utf8'), scramble);
|
|
36
|
+
return crypto.publicEncrypt(
|
|
37
|
+
{
|
|
38
|
+
key,
|
|
39
|
+
padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,
|
|
40
|
+
},
|
|
41
|
+
stage1
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const pluginFactory =
|
|
46
|
+
(pluginOptions = {}) =>
|
|
47
|
+
({ connection }) => {
|
|
48
|
+
let state = 0;
|
|
49
|
+
let scramble = null;
|
|
50
|
+
|
|
51
|
+
const password = connection.config.password;
|
|
52
|
+
|
|
53
|
+
const authWithKey = (serverKey) => {
|
|
54
|
+
const _password = encrypt(password, scramble, serverKey);
|
|
55
|
+
state = STATE_FINAL;
|
|
56
|
+
return _password;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
return (data) => {
|
|
60
|
+
switch (state) {
|
|
61
|
+
case STATE_INITIAL:
|
|
62
|
+
scramble = data.slice(0, 20);
|
|
63
|
+
state = STATE_TOKEN_SENT;
|
|
64
|
+
return calculateToken(password, scramble);
|
|
65
|
+
|
|
66
|
+
case STATE_TOKEN_SENT:
|
|
67
|
+
if (FAST_AUTH_SUCCESS_PACKET.equals(data)) {
|
|
68
|
+
state = STATE_FINAL;
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (PERFORM_FULL_AUTHENTICATION_PACKET.equals(data)) {
|
|
73
|
+
const isSecureConnection =
|
|
74
|
+
typeof pluginOptions.overrideIsSecure === 'undefined'
|
|
75
|
+
? connection.config.ssl || connection.config.socketPath
|
|
76
|
+
: pluginOptions.overrideIsSecure;
|
|
77
|
+
if (isSecureConnection) {
|
|
78
|
+
state = STATE_FINAL;
|
|
79
|
+
return Buffer.from(`${password}\0`, 'utf8');
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// if client provides key we can save one extra roundrip on first connection
|
|
83
|
+
if (pluginOptions.serverPublicKey) {
|
|
84
|
+
return authWithKey(pluginOptions.serverPublicKey);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
state = STATE_WAIT_SERVER_KEY;
|
|
88
|
+
return REQUEST_SERVER_KEY_PACKET;
|
|
89
|
+
}
|
|
90
|
+
throw new Error(
|
|
91
|
+
`Invalid AuthMoreData packet received by ${PLUGIN_NAME} plugin in STATE_TOKEN_SENT state.`
|
|
92
|
+
);
|
|
93
|
+
case STATE_WAIT_SERVER_KEY:
|
|
94
|
+
if (pluginOptions.onServerPublicKey) {
|
|
95
|
+
pluginOptions.onServerPublicKey(data);
|
|
96
|
+
}
|
|
97
|
+
return authWithKey(data);
|
|
98
|
+
case STATE_FINAL:
|
|
99
|
+
throw new Error(
|
|
100
|
+
`Unexpected data in AuthMoreData packet received by ${PLUGIN_NAME} plugin in STATE_FINAL state.`
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
throw new Error(
|
|
105
|
+
`Unexpected data in AuthMoreData packet received by ${PLUGIN_NAME} plugin in state ${state}`
|
|
106
|
+
);
|
|
107
|
+
};
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
// Export the plugin factory as default
|
|
111
|
+
module.exports = pluginFactory;
|
|
112
|
+
|
|
113
|
+
// Export calculateToken for reuse in initial handshake optimization
|
|
114
|
+
module.exports.calculateToken = calculateToken;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
##
|
|
2
|
+
|
|
3
|
+
https://dev.mysql.com/doc/refman/8.0/en/caching-sha2-pluggable-authentication.html
|
|
4
|
+
|
|
5
|
+
```js
|
|
6
|
+
const mysql = require('mysql');
|
|
7
|
+
mysql.createConnection({
|
|
8
|
+
authPlugins: {
|
|
9
|
+
caching_sha2_password: mysql.authPlugins.caching_sha2_password({
|
|
10
|
+
onServerPublikKey: function (key) {
|
|
11
|
+
console.log(key);
|
|
12
|
+
},
|
|
13
|
+
serverPublicKey: 'xxxyyy',
|
|
14
|
+
overrideIsSecure: true, //
|
|
15
|
+
}),
|
|
16
|
+
},
|
|
17
|
+
});
|
|
18
|
+
```
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
caching_sha2_password: require('./caching_sha2_password'),
|
|
5
|
+
mysql_clear_password: require('./mysql_clear_password'),
|
|
6
|
+
mysql_native_password: require('./mysql_native_password'),
|
|
7
|
+
sha256_password: require('./sha256_password'),
|
|
8
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
function bufferFromStr(str) {
|
|
4
|
+
return Buffer.from(`${str}\0`);
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
const create_mysql_clear_password_plugin = (pluginOptions) =>
|
|
8
|
+
function mysql_clear_password_plugin({ connection, command }) {
|
|
9
|
+
const password =
|
|
10
|
+
command.password || pluginOptions.password || connection.config.password;
|
|
11
|
+
|
|
12
|
+
return function (/* pluginData */) {
|
|
13
|
+
return bufferFromStr(password);
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
module.exports = create_mysql_clear_password_plugin;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
//const PLUGIN_NAME = 'mysql_native_password';
|
|
4
|
+
const auth41 = require('../auth_41.js');
|
|
5
|
+
|
|
6
|
+
module.exports =
|
|
7
|
+
(pluginOptions) =>
|
|
8
|
+
({ connection, command }) => {
|
|
9
|
+
const password =
|
|
10
|
+
command.password || pluginOptions.password || connection.config.password;
|
|
11
|
+
const passwordSha1 =
|
|
12
|
+
command.passwordSha1 ||
|
|
13
|
+
pluginOptions.passwordSha1 ||
|
|
14
|
+
connection.config.passwordSha1;
|
|
15
|
+
return (data) => {
|
|
16
|
+
const authPluginData1 = data.slice(0, 8);
|
|
17
|
+
const authPluginData2 = data.slice(8, 20);
|
|
18
|
+
let authToken;
|
|
19
|
+
if (passwordSha1) {
|
|
20
|
+
authToken = auth41.calculateTokenFromPasswordSha(
|
|
21
|
+
passwordSha1,
|
|
22
|
+
authPluginData1,
|
|
23
|
+
authPluginData2
|
|
24
|
+
);
|
|
25
|
+
} else {
|
|
26
|
+
authToken = auth41.calculateToken(
|
|
27
|
+
password,
|
|
28
|
+
authPluginData1,
|
|
29
|
+
authPluginData2
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
return authToken;
|
|
33
|
+
};
|
|
34
|
+
};
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const PLUGIN_NAME = 'sha256_password';
|
|
4
|
+
const crypto = require('crypto');
|
|
5
|
+
const { xorRotating } = require('../auth_41');
|
|
6
|
+
const Tls = require('tls');
|
|
7
|
+
|
|
8
|
+
const REQUEST_SERVER_KEY_PACKET = Buffer.from([1]);
|
|
9
|
+
|
|
10
|
+
const STATE_INITIAL = 0;
|
|
11
|
+
const STATE_WAIT_SERVER_KEY = 1;
|
|
12
|
+
const STATE_FINAL = -1;
|
|
13
|
+
|
|
14
|
+
function encrypt(password, scramble, key) {
|
|
15
|
+
const stage1 = xorRotating(Buffer.from(`${password}\0`, 'utf8'), scramble);
|
|
16
|
+
return crypto.publicEncrypt(key, stage1);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
module.exports =
|
|
20
|
+
(pluginOptions = {}) =>
|
|
21
|
+
({ connection }) => {
|
|
22
|
+
let state = 0;
|
|
23
|
+
let scramble = null;
|
|
24
|
+
|
|
25
|
+
const password = connection.config.password;
|
|
26
|
+
|
|
27
|
+
const authWithKey = (serverKey) => {
|
|
28
|
+
const _password = encrypt(password, scramble, serverKey);
|
|
29
|
+
state = STATE_FINAL;
|
|
30
|
+
return _password;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
return (data) => {
|
|
34
|
+
switch (state) {
|
|
35
|
+
case STATE_INITIAL:
|
|
36
|
+
if (
|
|
37
|
+
connection.stream instanceof Tls.TLSSocket &&
|
|
38
|
+
connection.stream.encrypted === true
|
|
39
|
+
) {
|
|
40
|
+
// We don't need to encrypt passwords over TLS connection
|
|
41
|
+
return Buffer.from(`${password}\0`, 'utf8');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
scramble = data.slice(0, 20);
|
|
45
|
+
// if client provides key we can save one extra roundrip on first connection
|
|
46
|
+
if (pluginOptions.serverPublicKey) {
|
|
47
|
+
return authWithKey(pluginOptions.serverPublicKey);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
state = STATE_WAIT_SERVER_KEY;
|
|
51
|
+
return REQUEST_SERVER_KEY_PACKET;
|
|
52
|
+
|
|
53
|
+
case STATE_WAIT_SERVER_KEY:
|
|
54
|
+
if (pluginOptions.onServerPublicKey) {
|
|
55
|
+
pluginOptions.onServerPublicKey(data);
|
|
56
|
+
}
|
|
57
|
+
return authWithKey(data);
|
|
58
|
+
case STATE_FINAL:
|
|
59
|
+
throw new Error(
|
|
60
|
+
`Unexpected data in AuthMoreData packet received by ${PLUGIN_NAME} plugin in STATE_FINAL state.`
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
throw new Error(
|
|
65
|
+
`Unexpected data in AuthMoreData packet received by ${PLUGIN_NAME} plugin in state ${state}`
|
|
66
|
+
);
|
|
67
|
+
};
|
|
68
|
+
};
|