oracledb 6.0.3 → 6.1.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/README.md +2 -2
- package/build/Release/oracledb-6.1.0-darwin-x64.node +0 -0
- package/build/Release/oracledb-6.1.0-darwin-x64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-6.1.0-js-buildinfo.txt +1 -0
- package/build/Release/oracledb-6.1.0-linux-arm64.node +0 -0
- package/build/Release/oracledb-6.1.0-linux-arm64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-6.1.0-linux-x64.node +0 -0
- package/build/Release/oracledb-6.1.0-linux-x64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-6.1.0-win32-x64.node +0 -0
- package/build/Release/oracledb-6.1.0-win32-x64.node-buildinfo.txt +1 -0
- package/examples/example.js +0 -1
- package/lib/aqQueue.js +40 -26
- package/lib/connection.js +15 -3
- package/lib/errors.js +10 -6
- package/lib/impl/connection.js +9 -0
- package/lib/impl/resultset.js +7 -4
- package/lib/oracledb.js +15 -12
- package/lib/pool.js +7 -1
- package/lib/sodaCollection.js +1 -1
- package/lib/thin/connection.js +92 -30
- package/lib/thin/pool.js +153 -68
- package/lib/thin/protocol/buffer.js +19 -1
- package/lib/thin/protocol/constants.js +3 -14
- package/lib/thin/protocol/encryptDecrypt.js +17 -17
- package/lib/thin/protocol/messages/auth.js +21 -23
- package/lib/thin/protocol/messages/base.js +22 -45
- package/lib/thin/protocol/messages/connectionCookie.js +76 -0
- package/lib/thin/protocol/messages/dataType.js +13 -9
- package/lib/thin/protocol/messages/execute.js +7 -7
- package/lib/thin/protocol/messages/index.js +2 -0
- package/lib/thin/protocol/messages/protocol.js +31 -20
- package/lib/thin/protocol/messages/withData.js +49 -43
- package/lib/thin/protocol/oson.js +4 -4
- package/lib/thin/protocol/packet.js +31 -10
- package/lib/thin/protocol/utils.js +2 -2
- package/lib/thin/resultSet.js +6 -6
- package/lib/thin/sqlnet/connStrategy.js +130 -5
- package/lib/thin/sqlnet/constants.js +2 -0
- package/lib/thin/sqlnet/ezConnectResolver.js +20 -19
- package/lib/thin/sqlnet/navNodes.js +32 -25
- package/lib/thin/sqlnet/networkSession.js +35 -30
- package/lib/thin/sqlnet/ntTcp.js +30 -14
- package/lib/thin/sqlnet/nvStrToNvPair.js +16 -16
- package/lib/thin/sqlnet/packet.js +9 -2
- package/lib/thin/sqlnet/paramParser.js +9 -9
- package/lib/thin/sqlnet/sessionAtts.js +4 -0
- package/lib/thin/statement.js +3 -3
- package/lib/thin/util.js +7 -8
- package/lib/transformer.js +3 -1
- package/lib/util.js +0 -13
- package/lib/version.js +2 -2
- package/package.json +1 -1
- package/build/Release/oracledb-6.0.3-darwin-x64.node +0 -0
- package/build/Release/oracledb-6.0.3-darwin-x64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.0.3-js-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.0.3-linux-arm64.node +0 -0
- package/build/Release/oracledb-6.0.3-linux-arm64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.0.3-linux-x64.node +0 -0
- package/build/Release/oracledb-6.0.3-linux-x64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.0.3-win32-x64.node +0 -0
- package/build/Release/oracledb-6.0.3-win32-x64.node-buildinfo.txt +0 -1
package/lib/thin/pool.js
CHANGED
|
@@ -36,6 +36,7 @@ const thinUtil = require('./util.js');
|
|
|
36
36
|
const {getConnectionInfo} = require('./sqlnet/networkSession.js');
|
|
37
37
|
const crypto = require('crypto');
|
|
38
38
|
const EventEmitter = require('events');
|
|
39
|
+
const Timers = require('timers');
|
|
39
40
|
|
|
40
41
|
class ThinPoolImpl extends PoolImpl {
|
|
41
42
|
|
|
@@ -69,30 +70,33 @@ class ThinPoolImpl extends PoolImpl {
|
|
|
69
70
|
this._privateKey = params.privateKey;
|
|
70
71
|
this._obfuscatedPrivateKey = [];
|
|
71
72
|
this._schedulerJob = null;
|
|
73
|
+
this._poolCloseWaiter = null;
|
|
74
|
+
this._pendingRequests = [];
|
|
75
|
+
|
|
72
76
|
// password obfuscation
|
|
73
77
|
if (this._password !== undefined) {
|
|
74
|
-
|
|
78
|
+
const obj = protocolUtil.setObfuscatedValue(this._password);
|
|
75
79
|
this._password = obj.value;
|
|
76
80
|
this._obfuscatedPassword = obj.obfuscatedValue;
|
|
77
81
|
this._userConfig.password = null;
|
|
78
82
|
}
|
|
79
83
|
// wallet password obfuscation
|
|
80
84
|
if (this._walletPassword !== undefined) {
|
|
81
|
-
|
|
85
|
+
const obj = protocolUtil.setObfuscatedValue(this._walletPassword);
|
|
82
86
|
this._walletPassword = obj.value;
|
|
83
87
|
this._obfuscatedWalletPassword = obj.obfuscatedValue;
|
|
84
88
|
this._userConfig.walletPassword = null;
|
|
85
89
|
}
|
|
86
90
|
// token obfuscation
|
|
87
91
|
if (this._token !== undefined) {
|
|
88
|
-
|
|
92
|
+
const obj = protocolUtil.setObfuscatedValue(this._token);
|
|
89
93
|
this._token = obj.value;
|
|
90
94
|
this._obfuscatedToken = obj.obfuscatedValue;
|
|
91
95
|
this._userConfig.token = null;
|
|
92
96
|
}
|
|
93
97
|
// privateKey obfuscation
|
|
94
98
|
if (this._privateKey !== undefined) {
|
|
95
|
-
|
|
99
|
+
const obj = protocolUtil.setObfuscatedValue(this._privateKey);
|
|
96
100
|
this._privateKey = obj.value;
|
|
97
101
|
this._obfuscatedPrivateKey = obj.obfuscatedValue;
|
|
98
102
|
this._userConfig.privateKey = null;
|
|
@@ -121,8 +125,9 @@ class ThinPoolImpl extends PoolImpl {
|
|
|
121
125
|
this._generateConnectionClass();
|
|
122
126
|
}
|
|
123
127
|
|
|
124
|
-
// create minimum connections
|
|
125
|
-
|
|
128
|
+
// create a background task. It will create minimum connections in the pool
|
|
129
|
+
// and expand the pool as required.
|
|
130
|
+
this.bgThreadFunc();
|
|
126
131
|
}
|
|
127
132
|
|
|
128
133
|
//---------------------------------------------------------------------------
|
|
@@ -131,13 +136,13 @@ class ThinPoolImpl extends PoolImpl {
|
|
|
131
136
|
setAccessToken(params) {
|
|
132
137
|
if (params.token) {
|
|
133
138
|
this._token = params.token;
|
|
134
|
-
|
|
139
|
+
const objToken = protocolUtil.setObfuscatedValue(this._token);
|
|
135
140
|
this._token = objToken.value;
|
|
136
141
|
this._obfuscatedToken = objToken.obfuscatedValue;
|
|
137
142
|
}
|
|
138
143
|
if (params.privateKey) {
|
|
139
144
|
this._privateKey = params.privateKey;
|
|
140
|
-
|
|
145
|
+
const objKey = protocolUtil.setObfuscatedValue(this._privateKey);
|
|
141
146
|
this._privateKey = objKey.value;
|
|
142
147
|
this._obfuscatedPrivateKey = objKey.obfuscatedValue;
|
|
143
148
|
}
|
|
@@ -151,15 +156,21 @@ class ThinPoolImpl extends PoolImpl {
|
|
|
151
156
|
async _getConnAttrs() {
|
|
152
157
|
let accessToken;
|
|
153
158
|
const clonedAttrs = Object.assign({}, this._userConfig);
|
|
159
|
+
// deobfuscate password
|
|
154
160
|
if (clonedAttrs.password === null) {
|
|
155
161
|
clonedAttrs.password = protocolUtil.getDeobfuscatedValue(this._password,
|
|
156
162
|
this._obfuscatedPassword);
|
|
157
163
|
}
|
|
164
|
+
|
|
165
|
+
// deobfuscate wallet password
|
|
158
166
|
if (clonedAttrs.walletPassword === null) {
|
|
159
167
|
clonedAttrs.walletPassword =
|
|
160
168
|
protocolUtil.getDeobfuscatedValue(this._walletPassword,
|
|
161
169
|
this._obfuscatedWalletPassword);
|
|
162
170
|
}
|
|
171
|
+
|
|
172
|
+
// deobfuscate token and private key
|
|
173
|
+
// check for token expiry
|
|
163
174
|
if (clonedAttrs.token === null) {
|
|
164
175
|
clonedAttrs.token =
|
|
165
176
|
protocolUtil.getDeobfuscatedValue(this._token, this._obfuscatedToken);
|
|
@@ -173,7 +184,7 @@ class ThinPoolImpl extends PoolImpl {
|
|
|
173
184
|
errors.throwErr(errors.ERR_TOKEN_HAS_EXPIRED);
|
|
174
185
|
} else {
|
|
175
186
|
// update pool with OAuth2 token
|
|
176
|
-
|
|
187
|
+
const obj = protocolUtil.setObfuscatedValue(clonedAttrs.token);
|
|
177
188
|
this._token = obj.value;
|
|
178
189
|
this._obfuscatedToken = obj.obfuscatedValue;
|
|
179
190
|
}
|
|
@@ -185,11 +196,11 @@ class ThinPoolImpl extends PoolImpl {
|
|
|
185
196
|
errors.throwErr(errors.ERR_TOKEN_HAS_EXPIRED);
|
|
186
197
|
} else {
|
|
187
198
|
// update pool with IAM token and private key
|
|
188
|
-
|
|
199
|
+
const objToken = protocolUtil.setObfuscatedValue(clonedAttrs.token);
|
|
189
200
|
this._token = objToken.value;
|
|
190
201
|
this._obfuscatedToken = objToken.obfuscatedValue;
|
|
191
202
|
|
|
192
|
-
|
|
203
|
+
const objKey = protocolUtil.setObfuscatedValue(clonedAttrs.privateKey);
|
|
193
204
|
this._privateKey = objKey.value;
|
|
194
205
|
this._obfuscatedPrivateKey = objKey.obfuscatedValue;
|
|
195
206
|
}
|
|
@@ -228,13 +239,34 @@ class ThinPoolImpl extends PoolImpl {
|
|
|
228
239
|
//---------------------------------------------------------------------------
|
|
229
240
|
// close pool by destroying available connections
|
|
230
241
|
//---------------------------------------------------------------------------
|
|
231
|
-
async close(
|
|
242
|
+
async close() {
|
|
243
|
+
|
|
244
|
+
// wait till background task for pool expansion is finished; if it is not
|
|
245
|
+
// currently running, wake it up!
|
|
246
|
+
await new Promise((resolve) => {
|
|
247
|
+
this._poolCloseWaiter = resolve;
|
|
248
|
+
if (this.bgWaiter) {
|
|
249
|
+
this.bgWaiter();
|
|
250
|
+
}
|
|
251
|
+
});
|
|
252
|
+
|
|
232
253
|
// clear scheduled job
|
|
233
254
|
if (this._schedulerJob) {
|
|
234
255
|
clearTimeout(this._schedulerJob);
|
|
235
256
|
this._schedulerJob = null;
|
|
236
257
|
}
|
|
237
|
-
|
|
258
|
+
|
|
259
|
+
// destroy all free connections
|
|
260
|
+
for (const conn of this._freeConnectionList) {
|
|
261
|
+
await this._destroy(conn);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// destroy all used connections
|
|
265
|
+
for (const conn of this._usedConnectionList) {
|
|
266
|
+
await this._destroy(conn);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
this.eventEmitter.removeAllListeners();
|
|
238
270
|
}
|
|
239
271
|
|
|
240
272
|
//---------------------------------------------------------------------------
|
|
@@ -307,25 +339,6 @@ class ThinPoolImpl extends PoolImpl {
|
|
|
307
339
|
return this._stmtCacheSize;
|
|
308
340
|
}
|
|
309
341
|
|
|
310
|
-
//---------------------------------------------------------------------------
|
|
311
|
-
// _growPool()
|
|
312
|
-
//
|
|
313
|
-
// Grows the pool to include the specified number of connections.
|
|
314
|
-
//---------------------------------------------------------------------------
|
|
315
|
-
async _growPool(numConns) {
|
|
316
|
-
const clonedAttrs = await this._getConnAttrs();
|
|
317
|
-
while (numConns > 0) {
|
|
318
|
-
const conn = new ThinConnectionImpl();
|
|
319
|
-
conn._pool = this;
|
|
320
|
-
await conn.connect(clonedAttrs);
|
|
321
|
-
conn._newSession = true;
|
|
322
|
-
conn._dropSess = false;
|
|
323
|
-
conn._lastTimeUsed = Date.now();
|
|
324
|
-
this._freeConnectionList.push(conn);
|
|
325
|
-
numConns--;
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
|
|
329
342
|
//---------------------------------------------------------------------------
|
|
330
343
|
// _setScheduler()
|
|
331
344
|
//
|
|
@@ -363,6 +376,94 @@ class ThinPoolImpl extends PoolImpl {
|
|
|
363
376
|
this._setScheduler();
|
|
364
377
|
}
|
|
365
378
|
|
|
379
|
+
//---------------------------------------------------------------------------
|
|
380
|
+
// _getNumConns()
|
|
381
|
+
//
|
|
382
|
+
// get number of connections need to be created
|
|
383
|
+
//---------------------------------------------------------------------------
|
|
384
|
+
_getNumConns() {
|
|
385
|
+
const usedConns = this._freeConnectionList.length + this._usedConnectionList.size;
|
|
386
|
+
// less connections in the pool than poolMin? restore to poolMin
|
|
387
|
+
if (usedConns < this._poolMin) {
|
|
388
|
+
return this._poolMin - usedConns;
|
|
389
|
+
// connections need to be created? create up to poolIncrement without exceeding poolMax
|
|
390
|
+
} else if (this._pendingRequests.length > 0) {
|
|
391
|
+
return Math.min(this._poolIncrement, this._poolMax - usedConns);
|
|
392
|
+
// no pending requests and we are already at poolMin so nothing to do!
|
|
393
|
+
} else {
|
|
394
|
+
return 0;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
//---------------------------------------------------------------------------
|
|
399
|
+
// bgThreadFunc()
|
|
400
|
+
//
|
|
401
|
+
// method which runs in a background thread and is used to create connections.
|
|
402
|
+
// When first started, it creates poolMin connections. After that, it creates
|
|
403
|
+
// poolIncrement connections up to the value of poolMax when needed.
|
|
404
|
+
// The thread terminates automatically when the pool is closed.
|
|
405
|
+
//---------------------------------------------------------------------------
|
|
406
|
+
async bgThreadFunc() {
|
|
407
|
+
|
|
408
|
+
// continue until a close request is received
|
|
409
|
+
while (!this._poolCloseWaiter) {
|
|
410
|
+
// get count for connections to be created
|
|
411
|
+
const numConns = this._getNumConns();
|
|
412
|
+
|
|
413
|
+
// connection creation is going on serially and not concurrently
|
|
414
|
+
for (let i = 0; i < numConns; i++) {
|
|
415
|
+
try {
|
|
416
|
+
// get deobfuscated value
|
|
417
|
+
const config = await this._getConnAttrs();
|
|
418
|
+
const conn = new ThinConnectionImpl();
|
|
419
|
+
conn._pool = this;
|
|
420
|
+
await conn.connect(config);
|
|
421
|
+
conn._newSession = true;
|
|
422
|
+
conn._dropSess = false;
|
|
423
|
+
conn._lastTimeUsed = Date.now();
|
|
424
|
+
this._freeConnectionList.push(conn);
|
|
425
|
+
} catch (err) {
|
|
426
|
+
this._bgErr = err;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
if (this._poolIncrement > 1 && (this._poolMax - this._usedConnectionList.size
|
|
430
|
+
- this._freeConnectionList.length) > 1) {
|
|
431
|
+
this._setScheduler();
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
// resolve pending request
|
|
435
|
+
if (this._pendingRequests.length > 0) {
|
|
436
|
+
const payload = this._pendingRequests.shift();
|
|
437
|
+
payload.resolve();
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
// give an opportunity for other "threads" to do their work.
|
|
441
|
+
await new Promise((resolve) => Timers.setImmediate(resolve));
|
|
442
|
+
|
|
443
|
+
// break loop when pool is closing
|
|
444
|
+
if (this._poolCloseWaiter) {
|
|
445
|
+
break;
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
// when pool is closing, break from while loop
|
|
450
|
+
if (this._poolCloseWaiter) {
|
|
451
|
+
break;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
// if no pending requests, wait for pending requests to appear!
|
|
455
|
+
if (this._pendingRequests.length == 0 || this._bgErr) {
|
|
456
|
+
await new Promise((resolve) => {
|
|
457
|
+
this.bgWaiter = resolve;
|
|
458
|
+
});
|
|
459
|
+
this.bgWaiter = null;
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
// notify the closer that the close can actually take place
|
|
464
|
+
this._poolCloseWaiter();
|
|
465
|
+
}
|
|
466
|
+
|
|
366
467
|
//---------------------------------------------------------------------------
|
|
367
468
|
// acquire()
|
|
368
469
|
//
|
|
@@ -410,17 +511,28 @@ class ThinPoolImpl extends PoolImpl {
|
|
|
410
511
|
|
|
411
512
|
// no free connections exist at this point; if less than poolMin
|
|
412
513
|
// connections exist, grow the pool to poolMin again; otherwise, increase
|
|
413
|
-
// the pool by poolIncrement up to poolMax
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
this._setScheduler();
|
|
514
|
+
// the pool by poolIncrement up to poolMax. We are deferring this
|
|
515
|
+
// to the background thread function!
|
|
516
|
+
await new Promise((resolve) => {
|
|
517
|
+
this._pendingRequests.push({resolve: resolve});
|
|
518
|
+
if (this.bgWaiter) {
|
|
519
|
+
// this wakes up the function to do some more work
|
|
520
|
+
this.bgWaiter();
|
|
421
521
|
}
|
|
422
|
-
}
|
|
522
|
+
});
|
|
523
|
+
|
|
524
|
+
if (this._bgErr) {
|
|
525
|
+
const err = this._bgErr;
|
|
526
|
+
this._bgErr = null;
|
|
423
527
|
|
|
528
|
+
// if an error has occurred in the background thread we clear it and then,
|
|
529
|
+
// if there are more pending requests we request the background thread
|
|
530
|
+
// function to try again.
|
|
531
|
+
if (this._pendingRequests.length > 0 && this.bgWaiter) {
|
|
532
|
+
this.bgWaiter();
|
|
533
|
+
}
|
|
534
|
+
throw err;
|
|
535
|
+
}
|
|
424
536
|
// return a connection from the ones that were just built
|
|
425
537
|
const conn = this._freeConnectionList.pop();
|
|
426
538
|
this._usedConnectionList.add(conn);
|
|
@@ -438,33 +550,6 @@ class ThinPoolImpl extends PoolImpl {
|
|
|
438
550
|
this._setScheduler();
|
|
439
551
|
}
|
|
440
552
|
|
|
441
|
-
//---------------------------------------------------------------------------
|
|
442
|
-
// destroyAllNow()
|
|
443
|
-
//
|
|
444
|
-
// called during pool close operation and close any available connection
|
|
445
|
-
// available in connection pool
|
|
446
|
-
//---------------------------------------------------------------------------
|
|
447
|
-
async destroyAllNow(obj) {
|
|
448
|
-
let conn;
|
|
449
|
-
while (this._freeConnectionList.length !== 0) {
|
|
450
|
-
conn = this._freeConnectionList.pop();
|
|
451
|
-
await this._destroy(conn);
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
if (obj.forceClose) {
|
|
455
|
-
for (const item of this._usedConnectionList) {
|
|
456
|
-
await this._destroy(item);
|
|
457
|
-
this._usedConnectionList.delete(item);
|
|
458
|
-
}
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
if (this._usedConnectionList.size !== 0) {
|
|
462
|
-
errors.throwErr(errors.ERR_POOL_HAS_BUSY_CONNECTIONS);
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
this.eventEmitter.removeAllListeners();
|
|
466
|
-
}
|
|
467
|
-
|
|
468
553
|
//---------------------------------------------------------------------------
|
|
469
554
|
// _generateConnectionClass()
|
|
470
555
|
//
|
|
@@ -847,7 +847,7 @@ class BaseBuffer {
|
|
|
847
847
|
buf[0] = numPairs + 1 + appendSentinel;
|
|
848
848
|
buf[1] = exponentOnWire;
|
|
849
849
|
for (let i = 0, pos = 2; i < value.length; i += 2, pos++) {
|
|
850
|
-
|
|
850
|
+
const base100Digit = Number(value.substring(i, i + 2));
|
|
851
851
|
if (isNegative) {
|
|
852
852
|
buf[pos] = 101 - base100Digit;
|
|
853
853
|
} else {
|
|
@@ -923,6 +923,24 @@ class BaseBuffer {
|
|
|
923
923
|
}
|
|
924
924
|
}
|
|
925
925
|
|
|
926
|
+
//---------------------------------------------------------------------------
|
|
927
|
+
// writeUB2()
|
|
928
|
+
//
|
|
929
|
+
// Writes an unsigned integer (up to 2 bytes in length) in variable length
|
|
930
|
+
// format to the buffer.
|
|
931
|
+
//---------------------------------------------------------------------------
|
|
932
|
+
writeUB2(value) {
|
|
933
|
+
if (value === 0) {
|
|
934
|
+
this.writeUInt8(0);
|
|
935
|
+
} else if (value <= 0xff) {
|
|
936
|
+
this.writeUInt8(1);
|
|
937
|
+
this.writeUInt8(value);
|
|
938
|
+
} else {
|
|
939
|
+
this.writeUInt8(2);
|
|
940
|
+
this.writeUInt16BE(value);
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
|
|
926
944
|
//---------------------------------------------------------------------------
|
|
927
945
|
// writeUB8()
|
|
928
946
|
//
|
|
@@ -89,10 +89,6 @@ module.exports = {
|
|
|
89
89
|
TNS_PACKET_TYPE_MARKER: 12,
|
|
90
90
|
TNS_PACKET_TYPE_CONTROL: 14,
|
|
91
91
|
|
|
92
|
-
// marker types
|
|
93
|
-
TNS_MARKER_TYPE_BREAK: 1,
|
|
94
|
-
TNS_MARKER_TYPE_RESET: 2,
|
|
95
|
-
|
|
96
92
|
// data types
|
|
97
93
|
TNS_DATA_TYPE_DEFAULT: 0,
|
|
98
94
|
TNS_DATA_TYPE_VARCHAR: 1,
|
|
@@ -429,8 +425,10 @@ module.exports = {
|
|
|
429
425
|
TNS_MSG_TYPE_FLUSH_OUT_BINDS: 19,
|
|
430
426
|
TNS_MSG_TYPE_BIT_VECTOR: 21,
|
|
431
427
|
TNS_MSG_TYPE_SERVER_SIDE_PIGGYBACK: 23,
|
|
432
|
-
TNS_MSG_TYPE_IMPLICIT_RESULTSET: 27,
|
|
433
428
|
TNS_MSG_TYPE_ONEWAY_FN: 26,
|
|
429
|
+
TNS_MSG_TYPE_IMPLICIT_RESULTSET: 27,
|
|
430
|
+
TNS_MSG_TYPE_RENEGOTIATE: 28,
|
|
431
|
+
TNS_MSG_TYPE_COOKIE: 30,
|
|
434
432
|
|
|
435
433
|
// parameter keyword numbers,
|
|
436
434
|
TNS_KEYWORD_NUM_CURRENT_SCHEMA: 168,
|
|
@@ -557,18 +555,9 @@ module.exports = {
|
|
|
557
555
|
TNS_END_TO_END_MODULE: 0x0008,
|
|
558
556
|
|
|
559
557
|
// versions
|
|
560
|
-
TNS_VERSION_DESIRED: 316,
|
|
561
|
-
TNS_VERSION_MINIMUM: 300,
|
|
562
558
|
TNS_VERSION_MIN_ACCEPTED: 315,
|
|
563
559
|
TNS_VERSION_MIN_LARGE_SDU: 315,
|
|
564
560
|
|
|
565
|
-
// other connection constants
|
|
566
|
-
TNS_SERVICE_OPTIONS: 0xc01,
|
|
567
|
-
TNS_PROTOCOL_CHARACTERISTICS: 0x4f98,
|
|
568
|
-
TNS_CONNECT_FLAGS: 0x8080,
|
|
569
|
-
TNS_CAN_RECV_ATTENTION: 0x0400,
|
|
570
|
-
TNS_CHECK_OOB: 0x01,
|
|
571
|
-
|
|
572
561
|
// TTC functions
|
|
573
562
|
TNS_FUNC_AUTH_PHASE_ONE: 118,
|
|
574
563
|
TNS_FUNC_AUTH_PHASE_TWO: 115,
|
|
@@ -50,9 +50,9 @@ class EncryptDecrypt {
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
_encrypt(key, val, padding) {
|
|
53
|
-
|
|
53
|
+
const block_size = 16;
|
|
54
54
|
const iv = Buffer.alloc(block_size, 0);
|
|
55
|
-
|
|
55
|
+
const n = block_size - (val.length % block_size);
|
|
56
56
|
const nv = Buffer.alloc(n, n);
|
|
57
57
|
if (n > 0) {
|
|
58
58
|
if (padding) {
|
|
@@ -73,15 +73,15 @@ class EncryptDecrypt {
|
|
|
73
73
|
|
|
74
74
|
// Encrypt password and newPassword using comboKey
|
|
75
75
|
_setEncryptedPasswordBuffers(passwordBytes, newPasswordBytes, comboKey, authObj) {
|
|
76
|
-
|
|
76
|
+
const salt = Buffer.alloc(16);
|
|
77
77
|
crypto.randomFillSync(salt, 0, 16);
|
|
78
|
-
|
|
78
|
+
const temp = Buffer.concat([salt, passwordBytes]);
|
|
79
79
|
authObj.encodedPassword = this._encrypt(comboKey, temp);
|
|
80
80
|
temp.fill(0);
|
|
81
81
|
authObj.encodedPassword = authObj.encodedPassword.slice().toString('hex').toUpperCase();
|
|
82
82
|
|
|
83
83
|
if (newPasswordBytes) {
|
|
84
|
-
|
|
84
|
+
const newPasswordWithSalt = Buffer.concat([salt, newPasswordBytes]);
|
|
85
85
|
authObj.encodedNewPassword = this._encrypt(comboKey, newPasswordWithSalt);
|
|
86
86
|
newPasswordWithSalt.fill(0);
|
|
87
87
|
authObj.encodedNewPassword = authObj.encodedNewPassword.slice().toString('hex').toUpperCase();
|
|
@@ -106,10 +106,10 @@ class EncryptDecrypt {
|
|
|
106
106
|
let keyLen = 32;
|
|
107
107
|
let hashAlg = 'sha512';
|
|
108
108
|
|
|
109
|
-
|
|
110
|
-
|
|
109
|
+
const verifierData = Buffer.from(sessionData['AUTH_VFR_DATA'], 'hex');
|
|
110
|
+
const encodedServerKey = Buffer.from(sessionData['AUTH_SESSKEY'], 'hex');
|
|
111
111
|
let iterations = Number(sessionData['AUTH_PBKDF2_VGEN_COUNT']);
|
|
112
|
-
|
|
112
|
+
const passwordBytes = Buffer.from(password, 'utf8');
|
|
113
113
|
let passwordHash;
|
|
114
114
|
let passwordKey;
|
|
115
115
|
|
|
@@ -117,18 +117,18 @@ class EncryptDecrypt {
|
|
|
117
117
|
algorithm = 'aes-192-cbc';
|
|
118
118
|
keyLen = 24;
|
|
119
119
|
hashAlg = 'sha1';
|
|
120
|
-
|
|
120
|
+
const h = crypto.createHash(hashAlg);
|
|
121
121
|
h.update(passwordBytes);
|
|
122
122
|
h.update(verifierData);
|
|
123
|
-
|
|
123
|
+
const ph = h.digest();
|
|
124
124
|
passwordHash = Buffer.alloc(ph.length + 4);
|
|
125
125
|
ph.copy(passwordHash, 0, 0, ph.length);
|
|
126
126
|
} else {
|
|
127
127
|
algorithm = 'aes-256-cbc';
|
|
128
|
-
|
|
129
|
-
|
|
128
|
+
const temp = Buffer.from('AUTH_PBKDF2_SPEEDY_KEY', 'utf8');
|
|
129
|
+
const salt = Buffer.concat([verifierData, temp]);
|
|
130
130
|
passwordKey = crypto.pbkdf2Sync(passwordBytes, salt, iterations, 64, 'sha512');
|
|
131
|
-
|
|
131
|
+
const h = crypto.createHash(hashAlg);
|
|
132
132
|
h.update(passwordKey);
|
|
133
133
|
h.update(verifierData);
|
|
134
134
|
passwordHash = h.digest().slice(0, keyLen);
|
|
@@ -163,10 +163,10 @@ class EncryptDecrypt {
|
|
|
163
163
|
iterations, keyLen, 'sha512');
|
|
164
164
|
}
|
|
165
165
|
|
|
166
|
-
|
|
166
|
+
const salt = Buffer.alloc(16);
|
|
167
167
|
if (!verifier11G) {
|
|
168
168
|
crypto.randomFillSync(salt, 0, 16);
|
|
169
|
-
|
|
169
|
+
const temp = Buffer.concat([salt, passwordKey]);
|
|
170
170
|
authObj.speedyKey = this._encrypt(authObj.comboKey, temp);
|
|
171
171
|
authObj.speedyKey = authObj.speedyKey.slice(0, 80).toString('hex').toUpperCase();
|
|
172
172
|
}
|
|
@@ -184,7 +184,7 @@ class EncryptDecrypt {
|
|
|
184
184
|
}
|
|
185
185
|
|
|
186
186
|
updatePasswordsWithComboKey(password, newPassword, comboKey, authObj) {
|
|
187
|
-
|
|
187
|
+
const passwordBytes = Buffer.from(password, 'utf8');
|
|
188
188
|
let newPasswordBytes;
|
|
189
189
|
if (newPassword) {
|
|
190
190
|
newPasswordBytes = Buffer.from(newPassword, 'utf8');
|
|
@@ -193,5 +193,5 @@ class EncryptDecrypt {
|
|
|
193
193
|
}
|
|
194
194
|
}
|
|
195
195
|
|
|
196
|
-
|
|
196
|
+
const encryptDecryptInst = new EncryptDecrypt();
|
|
197
197
|
module.exports = encryptDecryptInst;
|
|
@@ -103,32 +103,32 @@ class AuthMessage extends Message {
|
|
|
103
103
|
}
|
|
104
104
|
this.serviceName = this.conn.serviceName;
|
|
105
105
|
this.remoteAddress = this.conn.remoteAddress;
|
|
106
|
-
this.setAuthMode();
|
|
106
|
+
this.setAuthMode(config);
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
-
setAuthMode() {
|
|
109
|
+
setAuthMode(config) {
|
|
110
110
|
if (!this.newPassword) {
|
|
111
111
|
this.authMode = constants.TNS_AUTH_MODE_LOGON;
|
|
112
112
|
}
|
|
113
|
-
if (
|
|
113
|
+
if (config.privilege & constants.SYSDBA) {
|
|
114
114
|
this.authMode |= constants.TNS_AUTH_MODE_SYSDBA;
|
|
115
115
|
}
|
|
116
|
-
if (
|
|
116
|
+
if (config.privilege & constants.SYSOPER) {
|
|
117
117
|
this.authMode |= constants.TNS_AUTH_MODE_SYSOPER;
|
|
118
118
|
}
|
|
119
|
-
if (
|
|
119
|
+
if (config.privilege & constants.SYSASM) {
|
|
120
120
|
this.authMode |= constants.TNS_AUTH_MODE_SYSASM;
|
|
121
121
|
}
|
|
122
|
-
if (
|
|
122
|
+
if (config.privilege & constants.SYSBKP) {
|
|
123
123
|
this.authMode |= constants.TNS_AUTH_MODE_SYSBKP;
|
|
124
124
|
}
|
|
125
|
-
if (
|
|
125
|
+
if (config.privilege & constants.SYSDG) {
|
|
126
126
|
this.authMode |= constants.TNS_AUTH_MODE_SYSDGD;
|
|
127
127
|
}
|
|
128
|
-
if (
|
|
128
|
+
if (config.privilege & constants.SYSKM) {
|
|
129
129
|
this.authMode |= constants.TNS_AUTH_MODE_SYSKMT;
|
|
130
130
|
}
|
|
131
|
-
if (
|
|
131
|
+
if (config.privilege & constants.SYSRAC) {
|
|
132
132
|
this.authMode |= constants.TNS_AUTH_MODE_SYSRAC;
|
|
133
133
|
}
|
|
134
134
|
if (this.privateKey) {
|
|
@@ -221,7 +221,7 @@ class AuthMessage extends Message {
|
|
|
221
221
|
if (this.privateKey) {
|
|
222
222
|
numPairs += 2;
|
|
223
223
|
}
|
|
224
|
-
if (this.conn.
|
|
224
|
+
if (this.conn.connectionClass) {
|
|
225
225
|
numPairs += 1;
|
|
226
226
|
}
|
|
227
227
|
if (this.conn.purity) {
|
|
@@ -268,8 +268,8 @@ class AuthMessage extends Message {
|
|
|
268
268
|
if (this.encodedNewPassword) {
|
|
269
269
|
buf.writeKeyValue("AUTH_NEWPASSWORD", this.encodedNewPassword);
|
|
270
270
|
}
|
|
271
|
-
if (this.conn.
|
|
272
|
-
buf.writeKeyValue("AUTH_KPPL_CONN_CLASS", this.conn.
|
|
271
|
+
if (this.conn.connectionClass) {
|
|
272
|
+
buf.writeKeyValue("AUTH_KPPL_CONN_CLASS", this.conn.connectionClass);
|
|
273
273
|
}
|
|
274
274
|
if (this.conn.purity) {
|
|
275
275
|
buf.writeKeyValue("AUTH_KPPL_PURITY", '' + this.conn.purity);
|
|
@@ -278,11 +278,11 @@ class AuthMessage extends Message {
|
|
|
278
278
|
const currentDate = new Date();
|
|
279
279
|
const currentDateFormatted = currentDate.toGMTString();
|
|
280
280
|
|
|
281
|
-
|
|
281
|
+
const header = "date: " + currentDateFormatted + "\n" +
|
|
282
282
|
"(request-target): " + this.serviceName + "\n" +
|
|
283
283
|
"host: " + this.remoteAddress;
|
|
284
284
|
|
|
285
|
-
|
|
285
|
+
const signature = crypto.createSign('RSA-SHA256')
|
|
286
286
|
.update(header)
|
|
287
287
|
.sign(this.privateKey, 'base64');
|
|
288
288
|
|
|
@@ -297,16 +297,16 @@ class AuthMessage extends Message {
|
|
|
297
297
|
}
|
|
298
298
|
|
|
299
299
|
processReturnParameter(buf) {
|
|
300
|
-
|
|
300
|
+
const numParams = buf.readUB2();
|
|
301
301
|
for (let i = 0; i < numParams;i++) {
|
|
302
302
|
buf.skipUB4();
|
|
303
|
-
|
|
303
|
+
const key = buf.readStr(constants.CSFRM_IMPLICIT);
|
|
304
304
|
let value = "";
|
|
305
|
-
|
|
305
|
+
const numBytes = buf.readUB4();
|
|
306
306
|
if (numBytes > 0) {
|
|
307
307
|
value = buf.readStr(constants.CSFRM_IMPLICIT);
|
|
308
308
|
}
|
|
309
|
-
|
|
309
|
+
const flag = buf.readUB4();
|
|
310
310
|
if (key === "AUTH_VFR_DATA") {
|
|
311
311
|
this.verifierType = flag;
|
|
312
312
|
}
|
|
@@ -316,16 +316,14 @@ class AuthMessage extends Message {
|
|
|
316
316
|
if (this.functionCode === constants.TNS_FUNC_AUTH_PHASE_ONE) {
|
|
317
317
|
this.functionCode = constants.TNS_FUNC_AUTH_PHASE_TWO;
|
|
318
318
|
} else {
|
|
319
|
-
let versionNum;
|
|
320
319
|
let releaseNum;
|
|
321
320
|
let updateNum;
|
|
322
321
|
let portReleaseNum;
|
|
323
322
|
let portUpdateNum;
|
|
324
323
|
|
|
325
|
-
this.conn.
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
versionNum = (fullVersionNum >> 24) & 0xFF;
|
|
324
|
+
this.conn.instanceName = this.sessionData['AUTH_INSTANCENAME'];
|
|
325
|
+
const fullVersionNum = Number(this.sessionData['AUTH_VERSION_NO']);
|
|
326
|
+
const versionNum = (fullVersionNum >> 24) & 0xFF;
|
|
329
327
|
if (buf.caps.ttcFieldVersion >= constants.TNS_CCAP_FIELD_VERSION_18_1_EXT_1) {
|
|
330
328
|
releaseNum = (fullVersionNum >> 16) & 0xFF;
|
|
331
329
|
updateNum = (fullVersionNum >> 12) & 0x0F;
|