node-firebird 2.3.2 → 2.3.4

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.
Files changed (49) hide show
  1. package/README.md +163 -31
  2. package/lib/index.d.ts +12 -0
  3. package/lib/pool.js +10 -1
  4. package/lib/srp.js +12 -1
  5. package/lib/wire/connection.js +39 -7
  6. package/lib/wire/socket.js +13 -1
  7. package/lib/wire/xsqlvar.js +69 -6
  8. package/package.json +1 -1
  9. package/poc/node_modules/.package-lock.json +14 -0
  10. package/poc/node_modules/node-firebird/.eslintrc.json +12 -0
  11. package/poc/node_modules/node-firebird/.github/workflows/codeql.yml +76 -0
  12. package/poc/node_modules/node-firebird/.github/workflows/node.js.yml +95 -0
  13. package/poc/node_modules/node-firebird/BIGINT_MIGRATION.md +374 -0
  14. package/poc/node_modules/node-firebird/CI_DEBUGGING_GUIDE.md +148 -0
  15. package/poc/node_modules/node-firebird/ENCRYPTION_CALLBACK.md +152 -0
  16. package/poc/node_modules/node-firebird/FIREBIRD_LOG_FEATURE.md +145 -0
  17. package/poc/node_modules/node-firebird/LICENSE +373 -0
  18. package/poc/node_modules/node-firebird/MINIMAL_CHANGES_SUMMARY.md +136 -0
  19. package/poc/node_modules/node-firebird/PR_SUMMARY.md +96 -0
  20. package/poc/node_modules/node-firebird/README.md +794 -0
  21. package/poc/node_modules/node-firebird/ROADMAP.md +223 -0
  22. package/poc/node_modules/node-firebird/SRP_PROTOCOL.md +482 -0
  23. package/poc/node_modules/node-firebird/lib/callback.js +38 -0
  24. package/poc/node_modules/node-firebird/lib/firebird.msg +0 -0
  25. package/poc/node_modules/node-firebird/lib/firebird.msg.json +1371 -0
  26. package/poc/node_modules/node-firebird/lib/gdscodes.d.ts +1524 -0
  27. package/poc/node_modules/node-firebird/lib/gdscodes.js +1531 -0
  28. package/poc/node_modules/node-firebird/lib/ieee754-decimal.js +500 -0
  29. package/poc/node_modules/node-firebird/lib/index.d.ts +316 -0
  30. package/poc/node_modules/node-firebird/lib/index.js +128 -0
  31. package/poc/node_modules/node-firebird/lib/messages.js +162 -0
  32. package/poc/node_modules/node-firebird/lib/pool.js +108 -0
  33. package/poc/node_modules/node-firebird/lib/srp.js +299 -0
  34. package/poc/node_modules/node-firebird/lib/unix-crypt.js +343 -0
  35. package/poc/node_modules/node-firebird/lib/utils.js +164 -0
  36. package/poc/node_modules/node-firebird/lib/wire/connection.js +2510 -0
  37. package/poc/node_modules/node-firebird/lib/wire/const.js +807 -0
  38. package/poc/node_modules/node-firebird/lib/wire/database.js +378 -0
  39. package/poc/node_modules/node-firebird/lib/wire/eventConnection.js +118 -0
  40. package/poc/node_modules/node-firebird/lib/wire/fbEventManager.js +326 -0
  41. package/poc/node_modules/node-firebird/lib/wire/serialize.js +588 -0
  42. package/poc/node_modules/node-firebird/lib/wire/service.js +1058 -0
  43. package/poc/node_modules/node-firebird/lib/wire/socket.js +175 -0
  44. package/poc/node_modules/node-firebird/lib/wire/statement.js +48 -0
  45. package/poc/node_modules/node-firebird/lib/wire/transaction.js +206 -0
  46. package/poc/node_modules/node-firebird/lib/wire/xsqlvar.js +703 -0
  47. package/poc/node_modules/node-firebird/package.json +38 -0
  48. package/poc/node_modules/node-firebird/vitest.config.js +24 -0
  49. package/vitest.config.js +3 -1
@@ -0,0 +1,108 @@
1
+ /***************************************
2
+ *
3
+ * Simple Pooling
4
+ *
5
+ ***************************************/
6
+
7
+ class Pool {
8
+ constructor(attach, max, options) {
9
+ this.attach = attach;
10
+ this.internaldb = []; // connection created by the pool (for destroy)
11
+ this.pooldb = []; // available connection in the pool
12
+ this.dbinuse = 0; // connection currently in use into the pool
13
+ this._creating = 0; // connections currently being created
14
+ this.max = max || 4;
15
+ this.pending = [];
16
+ this.options = options;
17
+ }
18
+
19
+ get(callback) {
20
+ var self = this;
21
+ self.pending.push(callback);
22
+ self.check();
23
+ return self;
24
+ }
25
+
26
+ check() {
27
+ var self = this;
28
+ if ((self.dbinuse + self._creating) >= self.max)
29
+ return self;
30
+
31
+ var cb = self.pending.shift();
32
+ if (!cb)
33
+ return self;
34
+ if (self.pooldb.length) {
35
+ self.dbinuse++;
36
+ cb(null, self.pooldb.shift());
37
+ } else {
38
+ self._creating++;
39
+ this.attach(self.options, function (err, db) {
40
+ self._creating--;
41
+ if (!err) {
42
+ self.dbinuse++;
43
+ self.internaldb.push(db);
44
+ db.on('detach', function () {
45
+ // also in pool (could be a twice call to detach)
46
+ if (self.pooldb.indexOf(db) !== -1 || self.internaldb.indexOf(db) === -1)
47
+ return;
48
+ // if not usable don't put in again in the pool and remove reference on it
49
+ if (db.connection._isClosed || db.connection._isDetach || db.connection._pooled === false)
50
+ self.internaldb.splice(self.internaldb.indexOf(db), 1);
51
+ else
52
+ self.pooldb.push(db);
53
+
54
+ self.dbinuse--;
55
+ self.check();
56
+ });
57
+ }
58
+
59
+ cb(err, db);
60
+ });
61
+ }
62
+ setImmediate(function() {
63
+ self.check();
64
+ });
65
+
66
+ return self;
67
+ }
68
+
69
+ destroy(callback) {
70
+ var self = this;
71
+
72
+ var connectionCount = this.internaldb.length;
73
+
74
+ if (connectionCount === 0 && callback) {
75
+ callback();
76
+ }
77
+
78
+ function detachCallback(err) {
79
+ if (err) {
80
+ if (callback) {
81
+ callback(err);
82
+ }
83
+ return;
84
+ }
85
+
86
+ connectionCount--;
87
+ if (connectionCount === 0 && callback) {
88
+ callback();
89
+ }
90
+ }
91
+
92
+ this.internaldb.forEach(function(db) {
93
+ if (db.connection._pooled === false) {
94
+ detachCallback();
95
+ return;
96
+ }
97
+ // check if the db is not free into the pool otherwise user should manual detach it
98
+ var _db_in_pool = self.pooldb.indexOf(db);
99
+ if (_db_in_pool !== -1) {
100
+ self.pooldb.splice(_db_in_pool, 1);
101
+ db.connection._pooled = false;
102
+ db.detach(detachCallback);
103
+ }
104
+ });
105
+ }
106
+ }
107
+
108
+ module.exports = Pool;
@@ -0,0 +1,299 @@
1
+ var crypto = require('crypto');
2
+
3
+ const SRP_KEY_SIZE = 128,
4
+ SRP_KEY_MAX = BigInt('340282366920938463463374607431768211456'), // 1 << SRP_KEY_SIZE
5
+ SRP_SALT_SIZE = 32;
6
+
7
+ const DEBUG = false;
8
+ const DEBUG_PRIVATE_KEY = BigInt('0x84316857F47914F838918D5C12CE3A3E7A9B2D7C9486346809E9EEFCE8DE7CD4259D8BE4FD0BCC2D259553769E078FA61EE2977025E4DA42F7FD97914D8A33723DFAFBC00770B7DA0C2E3778A05790F0C0F33C32A19ED88A12928567749021B3FD45DCD1CE259C45325067E3DDC972F87867349BA82C303CCCAA9B207218007B');
9
+
10
+ /**
11
+ * Prime values.
12
+ *
13
+ * @type {{g: BigInt, k: BigInt, N: BigInt}}
14
+ */
15
+ const PRIME = {
16
+ N: BigInt('0xE67D2E994B2F900C3F41F08F5BB2627ED0D49EE1FE767A52EFCD565CD6E768812C3E1E9CE8F0A8BEA6CB13CD29DDEBF7A96D4A93B55D488DF099A15C89DCB0640738EB2CBDD9A8F7BAB561AB1B0DC1C6CDABF303264A08D1BCA932D1F1EE428B619D970F342ABA9A65793B8B2F041AE5364350C16F735F56ECBCA87BD57B29E7'),
17
+ g: BigInt(2),
18
+ k: BigInt('1277432915985975349439481660349303019122249719989')
19
+ };
20
+
21
+ /**
22
+ * Generate a client key pair.
23
+ *
24
+ * @param a BigInt Client private key.
25
+ * @returns {{private: BigInt, public: BigInt}}
26
+ */
27
+ exports.clientSeed = function(a = toBigInt(crypto.randomBytes(SRP_KEY_SIZE))) {
28
+ var A = modPow(PRIME.g, a, PRIME.N);
29
+
30
+ dump('a', a);
31
+ dump('A', A);
32
+
33
+ return {
34
+ public: A,
35
+ private: a
36
+ };
37
+ }
38
+
39
+ /**
40
+ * Generate a server key pair.
41
+ *
42
+ * @param user string Connection username.
43
+ * @param password string Connection password.
44
+ * @param salt BigInt Connection salt.
45
+ * @param b BigInt Server private key.
46
+ * @returns {{private: BigInt, public: BigInt}}
47
+ */
48
+ exports.serverSeed = function(user, password, salt, b = toBigInt(crypto.randomBytes(SRP_KEY_SIZE))) {
49
+ var v = getVerifier(user, password, salt);
50
+ var gb = modPow(PRIME.g, b, PRIME.N);
51
+ var kv = (PRIME.k * v) % PRIME.N;
52
+ var B = (kv + gb) % PRIME.N;
53
+
54
+ dump('v', v);
55
+ dump('b', b);
56
+ dump('gb', b);
57
+ dump('kv', v);
58
+ dump('B', B);
59
+
60
+ return {
61
+ public: B,
62
+ private: b
63
+ };
64
+ }
65
+
66
+ /**
67
+ * Server session secret.
68
+ *
69
+ * @param user string Connection username.
70
+ * @param password string Connection password.
71
+ * @param salt BigInt Connection salt.
72
+ * @param A BigInt Client public key.
73
+ * @param B BigInt Server public key.
74
+ * @param b BigInt Server private key.
75
+ * @returns {BigInt}
76
+ */
77
+ exports.serverSession = function(user, password, salt, A, B, b) {
78
+ var u = getScramble(A, B);
79
+ var v = getVerifier(user, password, salt);
80
+ var vu = modPow(v, u, PRIME.N);
81
+ var Avu = (A * vu) % PRIME.N;
82
+ var sessionSecret = modPow(Avu, b, PRIME.N);
83
+ var K = getHash('sha1', toBuffer(sessionSecret));
84
+
85
+ dump('server sessionSecret', sessionSecret);
86
+ dump('server K', K);
87
+
88
+ return BigInt('0x' + K);
89
+ };
90
+
91
+ /**
92
+ * M = H(H(N) xor H(g), H(I), s, A, B, K)
93
+ */
94
+ exports.clientProof = function(user, password, salt, A, B, a, hashAlgo) {
95
+ var K = clientSession(user, password, salt, A, B, a);
96
+ var n1, n2;
97
+
98
+ n1 = toBigInt(getHash('sha1', toBuffer(PRIME.N)));
99
+ n2 = toBigInt(getHash('sha1', toBuffer(PRIME.g)));
100
+
101
+ dump('n1', n1);
102
+ dump('n2', n2);
103
+
104
+ n1 = modPow(n1, n2, PRIME.N);
105
+ n2 = toBigInt(getHash('sha1', user));
106
+ var M = toBigInt(getHash(hashAlgo, toBuffer(n1), toBuffer(n2), salt, toBuffer(A), toBuffer(B), toBuffer(K)));
107
+
108
+ dump('n1-2', n1);
109
+ dump('n2-2', n2);
110
+ dump('proof:M', M);
111
+
112
+ return {
113
+ clientSessionKey: K,
114
+ authData: M,
115
+ };
116
+ }
117
+
118
+ /**
119
+ * Pad hex string.
120
+ */
121
+ function hexPad(hex) {
122
+ if (hex.length % 2 !== 0) {
123
+ hex = '0' + hex;
124
+ }
125
+
126
+ return hex;
127
+ }
128
+ exports.hexPad = hexPad;
129
+
130
+ /**
131
+ * Pad key with SRP_KEY_SIZE.
132
+ *
133
+ * @param n BigInt Key to pad.
134
+ * @returns Buffer
135
+ */
136
+ function pad(n) {
137
+ var buff = Buffer.from(hexPad(n.toString(16)), 'hex');
138
+
139
+ if (buff.length > SRP_KEY_SIZE) {
140
+ buff = buff.slice(buff.length - SRP_KEY_SIZE, buff.length);
141
+ }
142
+
143
+ return buff;
144
+ }
145
+
146
+ /**
147
+ * Scramble keys.
148
+ *
149
+ * @param A BigInt Client public key.
150
+ * @param B BigInt Server public key.
151
+ * @returns {BigInt}
152
+ */
153
+ function getScramble(A, B) {
154
+ return BigInt('0x' + getHash('sha1', pad(A), pad(B)));
155
+ }
156
+
157
+ /**
158
+ * Client session secret.
159
+ *
160
+ * Both: u = H(A, B)
161
+ * User: x = H(s, p) (user enters password)
162
+ * User: S = (B - kg^x) ^ (a + ux) (computes session key)
163
+ * User: K = H(S)
164
+ *
165
+ * @param user string Connection username.
166
+ * @param password string Connection password.
167
+ * @param salt BigInt Connection salt.
168
+ * @param A BigInt Client public key.
169
+ * @param B BigInt Server public key.
170
+ * @param a BigInt Client private key.
171
+ */
172
+ function clientSession(user, password, salt, A, B, a) {
173
+ var u = getScramble(A, B);
174
+ var x = getUserHash(user, salt, password);
175
+ var gx = modPow(PRIME.g, x, PRIME.N);
176
+ var kgx = (PRIME.k * gx) % PRIME.N;
177
+ var diff = (B - kgx) % PRIME.N;
178
+
179
+ if (diff < 0n) {
180
+ diff = diff + PRIME.N;
181
+ }
182
+
183
+ // Note: While the SRP specification says exponents should not be reduced mod N,
184
+ // the Firebird engine implementation does reduce these exponents mod N.
185
+ // We must match the server's behavior for authentication to succeed.
186
+ var ux = (u * x) % PRIME.N;
187
+ var aux = (a + ux) % PRIME.N;
188
+ var sessionSecret = modPow(diff, aux, PRIME.N);
189
+ var K = toBigInt(getHash('sha1', toBuffer(sessionSecret)));
190
+
191
+ dump('B', B);
192
+ dump('u', u);
193
+ dump('x', x);
194
+ dump('gx', gx);
195
+ dump('kgx', kgx);
196
+ dump('diff', diff);
197
+ dump('ux', ux);
198
+ dump('aux', aux);
199
+ dump('sessionSecret', sessionSecret);
200
+ dump('sessionKey(K)', K);
201
+
202
+ return K;
203
+ }
204
+
205
+ /**
206
+ * Compute user hash.
207
+ *
208
+ * @param user string Connection username.
209
+ * @param salt BigInt Connection salt.
210
+ * @param password string Connection password.
211
+ * @returns {BigInt}
212
+ */
213
+ function getUserHash(user, salt, password) {
214
+ var hash1 = getHash('sha1', user.toUpperCase(), ':', password);
215
+ var hash2 = getHash('sha1', salt, toBuffer(hash1));
216
+
217
+ return toBigInt(hash2);
218
+ }
219
+
220
+ /**
221
+ * Verifier of user hash.
222
+ *
223
+ * @param user string Connection username.
224
+ * @param password string Connection password.
225
+ * @param salt BigInt Connection salt.
226
+ * @returns {BigInt}
227
+ */
228
+ function getVerifier(user, password, salt) {
229
+ return modPow(PRIME.g, getUserHash(user, salt, password), PRIME.N);
230
+ }
231
+
232
+ /**
233
+ * Hash data and return hex string.
234
+ *
235
+ * @param algo string Algorithm to use.
236
+ * @param data any[] Data to hash.
237
+ * @returns {string}
238
+ */
239
+ function getHash(algo, ...data) {
240
+ var hash = crypto.createHash(algo);
241
+
242
+ for (var d of data) {
243
+ hash.update(d);
244
+ }
245
+
246
+ return hash.digest('hex');
247
+ }
248
+
249
+ /**
250
+ * Convert BigInt to buffer.
251
+ *
252
+ * @param bigInt
253
+ * @returns {*}
254
+ */
255
+ function toBuffer(bigInt) {
256
+ return Buffer.from(typeof bigInt === 'bigint' ? hexPad(bigInt.toString(16)) : bigInt, 'hex');
257
+ }
258
+
259
+ /**
260
+ * Convert hex buffer or string to BigInt.
261
+ *
262
+ * @param hex
263
+ * @returns {BigInt}
264
+ */
265
+ function toBigInt(hex) {
266
+ return BigInt('0x' + (Buffer.isBuffer(hex) ? hex.toString('hex') : hex));
267
+ }
268
+
269
+ /**
270
+ * Dump value in debug mode.
271
+ *
272
+ * @param key
273
+ * @param value
274
+ */
275
+ function dump(key, value) {
276
+ if (DEBUG) {
277
+ if (typeof value === 'bigint') {
278
+ value = value.toString(16);
279
+ }
280
+
281
+ console.log(key + '=' + value);
282
+ }
283
+ }
284
+
285
+ /**
286
+ * Calculates (base ^ exp) % mod using native BigInt.
287
+ */
288
+ function modPow(base, exp, mod) {
289
+ let result = 1n;
290
+ base = base % mod;
291
+ while (exp > 0n) {
292
+ if (exp & 1n) {
293
+ result = (result * base) % mod;
294
+ }
295
+ base = (base * base) % mod;
296
+ exp >>= 1n;
297
+ }
298
+ return result;
299
+ }