oracledb 6.10.0 → 7.0.1
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.txt +1 -1
- package/NOTICE.txt +1 -1
- package/README.md +9 -9
- package/build/Release/oracledb-7.0.1-darwin-arm64.node +0 -0
- package/build/Release/oracledb-7.0.1-darwin-arm64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-7.0.1-js-buildinfo.txt +1 -0
- package/build/Release/oracledb-7.0.1-linux-arm64.node +0 -0
- package/build/Release/oracledb-7.0.1-linux-arm64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-7.0.1-linux-x64.node +0 -0
- package/build/Release/oracledb-7.0.1-linux-x64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-7.0.1-win32-x64.node +0 -0
- package/build/Release/oracledb-7.0.1-win32-x64.node-buildinfo.txt +1 -0
- package/lib/aqDeqOptions.js +4 -4
- package/lib/aqEnqOptions.js +2 -2
- package/lib/aqQueue.js +11 -6
- package/lib/connection.js +407 -40
- package/lib/endUserSecurityContext.js +169 -0
- package/lib/errors.js +108 -5
- package/lib/impl/connection.js +76 -2
- package/lib/impl/datahandlers/buffer.js +19 -5
- package/lib/impl/datahandlers/vector.js +25 -5
- package/lib/impl/lob.js +9 -0
- package/lib/impl/parserHelpers.js +447 -0
- package/lib/impl/resultset.js +1 -1
- package/lib/lob.js +27 -14
- package/lib/obfuscation.js +97 -0
- package/lib/oracledb.js +148 -43
- package/lib/parser.js +204 -0
- package/lib/pipeline.js +113 -0
- package/lib/pool.js +16 -1
- package/lib/resultset.js +42 -21
- package/lib/settings.js +1 -0
- package/lib/thin/connection.js +461 -53
- package/lib/thin/dbObject.js +10 -4
- package/lib/thin/lob.js +20 -1
- package/lib/thin/pool.js +43 -63
- package/lib/thin/protocol/capabilities.js +18 -3
- package/lib/thin/protocol/constants.js +82 -2
- package/lib/thin/protocol/encryptDecrypt.js +43 -8
- package/lib/thin/protocol/messages/aqArray.js +2 -2
- package/lib/thin/protocol/messages/aqBase.js +2 -2
- package/lib/thin/protocol/messages/auth.js +6 -1
- package/lib/thin/protocol/messages/base.js +246 -5
- package/lib/thin/protocol/messages/dataType.js +8 -3
- package/lib/thin/protocol/messages/directPathLoadStream.js +377 -0
- package/lib/thin/protocol/messages/directPathOp.js +65 -0
- package/lib/thin/protocol/messages/directPathPrepare.js +158 -0
- package/lib/thin/protocol/messages/endPipeline.js +56 -0
- package/lib/thin/protocol/messages/execute.js +9 -7
- package/lib/thin/protocol/messages/index.js +9 -1
- package/lib/thin/protocol/messages/protocol.js +2 -2
- package/lib/thin/protocol/messages/withData.js +10 -143
- package/lib/thin/protocol/packet.js +115 -24
- package/lib/thin/protocol/protocol.js +110 -25
- package/lib/thin/protocol/utils.js +1 -26
- package/lib/thin/resultSet.js +13 -19
- package/lib/thin/sqlnet/ezConnectResolver.js +4 -4
- package/lib/thin/sqlnet/navNodes.js +4 -2
- package/lib/thin/sqlnet/networkSession.js +78 -50
- package/lib/thin/sqlnet/ntTcp.js +24 -0
- package/lib/thin/sqlnet/nvStrToNvPair.js +50 -25
- package/lib/thin/sqlnet/packet.js +49 -8
- package/lib/thin/sqlnet/paramParser.js +10 -7
- package/lib/thin/sqlnet/sessionAtts.js +2 -2
- package/lib/thin/statementCache.js +2 -4
- package/lib/traceHandler.js +59 -2
- package/lib/transformer.js +8 -3
- package/lib/types.js +35 -21
- package/lib/util.js +6 -6
- package/lib/version.js +4 -4
- package/package/install.js +5 -5
- package/package/prunebinaries.js +1 -1
- package/package.json +1 -1
- package/plugins/configProviders/awsCommon.js +125 -0
- package/plugins/configProviders/awss3/index.js +138 -0
- package/plugins/configProviders/awssecretsmanager/index.js +147 -0
- package/plugins/configProviders/azure/index.js +4 -5
- package/plugins/token/extensionAzure/index.js +0 -1
- package/plugins/token/extensionOci/index.js +0 -1
- package/build/Release/oracledb-6.10.0-darwin-arm64.node +0 -0
- package/build/Release/oracledb-6.10.0-darwin-arm64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.10.0-darwin-x64.node +0 -0
- package/build/Release/oracledb-6.10.0-darwin-x64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.10.0-js-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.10.0-linux-arm64.node +0 -0
- package/build/Release/oracledb-6.10.0-linux-arm64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.10.0-linux-x64.node +0 -0
- package/build/Release/oracledb-6.10.0-linux-x64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.10.0-win32-x64.node +0 -0
- package/build/Release/oracledb-6.10.0-win32-x64.node-buildinfo.txt +0 -1
package/lib/thin/dbObject.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright (c) 2023,
|
|
1
|
+
// Copyright (c) 2023, 2026, Oracle and/or its affiliates.
|
|
2
2
|
|
|
3
3
|
//-----------------------------------------------------------------------------
|
|
4
4
|
//
|
|
@@ -74,6 +74,9 @@ class DbObjectPickleBuffer extends GrowableBuffer {
|
|
|
74
74
|
obj.imageFlags = this.readUInt8();
|
|
75
75
|
obj.imageVersion = this.readUInt8();
|
|
76
76
|
this.readLength();
|
|
77
|
+
if (obj.imageFlags & constants.TNS_OBJ_IS_DEGENERATE) {
|
|
78
|
+
errors.throwNotImplemented('DbObject attributes stored as a locator');
|
|
79
|
+
}
|
|
77
80
|
if ((obj.imageFlags & constants.TNS_OBJ_NO_PREFIX_SEG) === 0) {
|
|
78
81
|
const prefixSegLength = this.readLength();
|
|
79
82
|
this.skipBytes(prefixSegLength);
|
|
@@ -302,7 +305,7 @@ class ThinDbObjectImpl extends DbObjectImpl {
|
|
|
302
305
|
}
|
|
303
306
|
break;
|
|
304
307
|
default:
|
|
305
|
-
errors.
|
|
308
|
+
errors.throwNotImplemented(type);
|
|
306
309
|
}
|
|
307
310
|
}
|
|
308
311
|
}
|
|
@@ -366,6 +369,7 @@ class ThinDbObjectImpl extends DbObjectImpl {
|
|
|
366
369
|
//---------------------------------------------------------------------------
|
|
367
370
|
_unpackValue(buf, type, typeClass) {
|
|
368
371
|
let isNull, obj, value, isCollection;
|
|
372
|
+
const caps = this._objType._connection._protocol.caps;
|
|
369
373
|
switch (type) {
|
|
370
374
|
case types.DB_TYPE_NUMBER:
|
|
371
375
|
return buf.readOracleNumber();
|
|
@@ -373,9 +377,11 @@ class ThinDbObjectImpl extends DbObjectImpl {
|
|
|
373
377
|
return buf.readBinaryInteger();
|
|
374
378
|
case types.DB_TYPE_VARCHAR:
|
|
375
379
|
case types.DB_TYPE_CHAR:
|
|
380
|
+
caps.checkCharsetId();
|
|
376
381
|
return buf.readStr(constants.CSFRM_IMPLICIT);
|
|
377
382
|
case types.DB_TYPE_NVARCHAR:
|
|
378
383
|
case types.DB_TYPE_NCHAR:
|
|
384
|
+
caps.checkNCharsetId();
|
|
379
385
|
return buf.readStr(constants.CSFRM_NCHAR);
|
|
380
386
|
case types.DB_TYPE_RAW:
|
|
381
387
|
value = buf.readBytesWithLength();
|
|
@@ -393,7 +399,7 @@ class ThinDbObjectImpl extends DbObjectImpl {
|
|
|
393
399
|
case types.DB_TYPE_TIMESTAMP_TZ:
|
|
394
400
|
return buf.readOracleDate(false);
|
|
395
401
|
case types.DB_TYPE_BOOLEAN:
|
|
396
|
-
return buf.readBool();
|
|
402
|
+
return buf.readBool(true);
|
|
397
403
|
case types.DB_TYPE_OBJECT:
|
|
398
404
|
case types.DB_TYPE_XMLTYPE:
|
|
399
405
|
obj = new ThinDbObjectImpl(typeClass);
|
|
@@ -412,7 +418,7 @@ class ThinDbObjectImpl extends DbObjectImpl {
|
|
|
412
418
|
}
|
|
413
419
|
return obj;
|
|
414
420
|
default:
|
|
415
|
-
errors.
|
|
421
|
+
errors.throwNotImplemented(type);
|
|
416
422
|
}
|
|
417
423
|
}
|
|
418
424
|
|
package/lib/thin/lob.js
CHANGED
|
@@ -172,6 +172,23 @@ class ThinLobImpl extends LobImpl {
|
|
|
172
172
|
return await this._sendMessage(options);
|
|
173
173
|
}
|
|
174
174
|
|
|
175
|
+
//---------------------------------------------------------------------------
|
|
176
|
+
// trim()
|
|
177
|
+
//
|
|
178
|
+
// Internal method for trimming the LOB.
|
|
179
|
+
//---------------------------------------------------------------------------
|
|
180
|
+
async trim(newSize) {
|
|
181
|
+
this.checkConn();
|
|
182
|
+
const options = {
|
|
183
|
+
operation: constants.TNS_LOB_OP_TRIM,
|
|
184
|
+
sourceLobImpl: this,
|
|
185
|
+
sendAmount: true,
|
|
186
|
+
amount: newSize
|
|
187
|
+
};
|
|
188
|
+
await this._sendMessage(options);
|
|
189
|
+
this._length = newSize;
|
|
190
|
+
}
|
|
191
|
+
|
|
175
192
|
//---------------------------------------------------------------------------
|
|
176
193
|
// write()
|
|
177
194
|
//
|
|
@@ -186,7 +203,9 @@ class ThinLobImpl extends LobImpl {
|
|
|
186
203
|
data: data
|
|
187
204
|
};
|
|
188
205
|
await this._sendMessage(options);
|
|
189
|
-
|
|
206
|
+
// Take the offset into account while setting the length
|
|
207
|
+
// Note that offset is 1-based
|
|
208
|
+
this._length = Math.max(this._length, (offset - 1) + data.length);
|
|
190
209
|
}
|
|
191
210
|
|
|
192
211
|
//---------------------------------------------------------------------------
|
package/lib/thin/pool.js
CHANGED
|
@@ -28,10 +28,10 @@
|
|
|
28
28
|
|
|
29
29
|
const PoolImpl = require('../impl/pool.js');
|
|
30
30
|
const ThinConnectionImpl = require('./connection.js');
|
|
31
|
-
const protocolUtil = require('./protocol/utils.js');
|
|
32
31
|
const errors = require('../errors.js');
|
|
33
32
|
const settings = require('../settings.js');
|
|
34
33
|
const util = require('../util.js');
|
|
34
|
+
const { ObfuscatedValue } = require('../obfuscation.js');
|
|
35
35
|
const thinUtil = require('./util.js');
|
|
36
36
|
const {getConnectionInfo} = require('./sqlnet/networkSession.js');
|
|
37
37
|
const crypto = require('crypto');
|
|
@@ -41,7 +41,7 @@ class ThinPoolImpl extends PoolImpl {
|
|
|
41
41
|
|
|
42
42
|
_init(params) {
|
|
43
43
|
if (!params.homogeneous) {
|
|
44
|
-
errors.
|
|
44
|
+
errors.throwNotImplemented('Heterogeneous Pooling');
|
|
45
45
|
}
|
|
46
46
|
if (!params.connectString) {
|
|
47
47
|
errors.throwErr(errors.ERR_EMPTY_CONNECT_STRING);
|
|
@@ -65,15 +65,11 @@ class ThinPoolImpl extends PoolImpl {
|
|
|
65
65
|
this._userConfig = params;
|
|
66
66
|
this._freeConnectionList = [];
|
|
67
67
|
this._usedConnectionList = new Set();
|
|
68
|
-
this._password =
|
|
69
|
-
this._walletPassword =
|
|
70
|
-
this._walletContent =
|
|
71
|
-
this.
|
|
72
|
-
this.
|
|
73
|
-
this._token = params.token;
|
|
74
|
-
this._obfuscatedToken = [];
|
|
75
|
-
this._privateKey = params.privateKey;
|
|
76
|
-
this._obfuscatedPrivateKey = [];
|
|
68
|
+
this._password = new ObfuscatedValue();
|
|
69
|
+
this._walletPassword = new ObfuscatedValue();
|
|
70
|
+
this._walletContent = new ObfuscatedValue();
|
|
71
|
+
this._token = new ObfuscatedValue();
|
|
72
|
+
this._privateKey = new ObfuscatedValue();
|
|
77
73
|
this._schedulerJob = null;
|
|
78
74
|
this._poolCloseWaiter = null;
|
|
79
75
|
this._pendingRequests = [];
|
|
@@ -82,38 +78,28 @@ class ThinPoolImpl extends PoolImpl {
|
|
|
82
78
|
this._poolCloseCleaner = null;
|
|
83
79
|
|
|
84
80
|
// password obfuscation
|
|
85
|
-
if (
|
|
86
|
-
|
|
87
|
-
this._password = obj.value;
|
|
88
|
-
this._obfuscatedPassword = obj.obfuscatedValue;
|
|
81
|
+
if (params.password !== undefined) {
|
|
82
|
+
this._password.set(params.password);
|
|
89
83
|
this._userConfig.password = null;
|
|
90
84
|
}
|
|
91
85
|
// wallet password obfuscation
|
|
92
|
-
if (
|
|
93
|
-
|
|
94
|
-
this._walletPassword = obj.value;
|
|
95
|
-
this._obfuscatedWalletPassword = obj.obfuscatedValue;
|
|
86
|
+
if (params.walletPassword !== undefined) {
|
|
87
|
+
this._walletPassword.set(params.walletPassword);
|
|
96
88
|
this._userConfig.walletPassword = null;
|
|
97
89
|
}
|
|
98
90
|
// wallet content obfuscation
|
|
99
|
-
if (
|
|
100
|
-
|
|
101
|
-
this.
|
|
102
|
-
this._obfuscatedWalletContent = obj.obfuscatedValue;
|
|
103
|
-
this._userConfig.walletConent = null;
|
|
91
|
+
if (params.walletContent !== undefined) {
|
|
92
|
+
this._walletContent.set(params.walletContent);
|
|
93
|
+
this._userConfig.walletContent = null;
|
|
104
94
|
}
|
|
105
95
|
// token obfuscation
|
|
106
|
-
if (
|
|
107
|
-
|
|
108
|
-
this._token = obj.value;
|
|
109
|
-
this._obfuscatedToken = obj.obfuscatedValue;
|
|
96
|
+
if (params.token !== undefined) {
|
|
97
|
+
this._token.set(params.token);
|
|
110
98
|
this._userConfig.token = null;
|
|
111
99
|
}
|
|
112
100
|
// privateKey obfuscation
|
|
113
|
-
if (
|
|
114
|
-
|
|
115
|
-
this._privateKey = obj.value;
|
|
116
|
-
this._obfuscatedPrivateKey = obj.obfuscatedValue;
|
|
101
|
+
if (params.privateKey !== undefined) {
|
|
102
|
+
this._privateKey.set(params.privateKey);
|
|
117
103
|
this._userConfig.privateKey = null;
|
|
118
104
|
}
|
|
119
105
|
this._accessTokenFn = params.accessTokenFn;
|
|
@@ -128,6 +114,7 @@ class ThinPoolImpl extends PoolImpl {
|
|
|
128
114
|
//---------------------------------------------------------------------------
|
|
129
115
|
async create(params) {
|
|
130
116
|
this._init(params);
|
|
117
|
+
this._eventCallback = params.poolEventReg;
|
|
131
118
|
this._userConfig._connInfo =
|
|
132
119
|
await getConnectionInfo(params);
|
|
133
120
|
this._isDRCPEnabled =
|
|
@@ -150,16 +137,12 @@ class ThinPoolImpl extends PoolImpl {
|
|
|
150
137
|
//---------------------------------------------------------------------------
|
|
151
138
|
setAccessToken(params) {
|
|
152
139
|
if (params.token) {
|
|
153
|
-
this._token
|
|
154
|
-
|
|
155
|
-
this._token = objToken.value;
|
|
156
|
-
this._obfuscatedToken = objToken.obfuscatedValue;
|
|
140
|
+
this._token.set(params.token);
|
|
141
|
+
this._userConfig.token = null;
|
|
157
142
|
}
|
|
158
143
|
if (params.privateKey) {
|
|
159
|
-
this._privateKey
|
|
160
|
-
|
|
161
|
-
this._privateKey = objKey.value;
|
|
162
|
-
this._obfuscatedPrivateKey = objKey.obfuscatedValue;
|
|
144
|
+
this._privateKey.set(params.privateKey);
|
|
145
|
+
this._userConfig.privateKey = null;
|
|
163
146
|
}
|
|
164
147
|
}
|
|
165
148
|
|
|
@@ -173,29 +156,23 @@ class ThinPoolImpl extends PoolImpl {
|
|
|
173
156
|
const clonedAttrs = Object.assign({}, this._userConfig);
|
|
174
157
|
// deobfuscate password
|
|
175
158
|
if (clonedAttrs.password === null) {
|
|
176
|
-
clonedAttrs.password =
|
|
177
|
-
this._obfuscatedPassword);
|
|
159
|
+
clonedAttrs.password = this._password.get();
|
|
178
160
|
}
|
|
179
161
|
|
|
180
162
|
// deobfuscate wallet password
|
|
181
163
|
if (clonedAttrs.walletPassword === null) {
|
|
182
|
-
clonedAttrs.walletPassword =
|
|
183
|
-
protocolUtil.getDeobfuscatedValue(this._walletPassword,
|
|
184
|
-
this._obfuscatedWalletPassword);
|
|
164
|
+
clonedAttrs.walletPassword = this._walletPassword.get();
|
|
185
165
|
}
|
|
186
166
|
|
|
187
167
|
// deobfuscate wallet content
|
|
188
168
|
if (clonedAttrs.walletContent === null) {
|
|
189
|
-
clonedAttrs.walletContent =
|
|
190
|
-
protocolUtil.getDeobfuscatedValue(this._walletContent,
|
|
191
|
-
this._obfuscatedWalletContent);
|
|
169
|
+
clonedAttrs.walletContent = this._walletContent.get();
|
|
192
170
|
}
|
|
193
171
|
|
|
194
172
|
// deobfuscate token and private key
|
|
195
173
|
// check for token expiry
|
|
196
174
|
if (clonedAttrs.token === null) {
|
|
197
|
-
clonedAttrs.token =
|
|
198
|
-
protocolUtil.getDeobfuscatedValue(this._token, this._obfuscatedToken);
|
|
175
|
+
clonedAttrs.token = this._token.get();
|
|
199
176
|
if (util.isTokenExpired(clonedAttrs.token)) {
|
|
200
177
|
if (typeof this._accessTokenFn === 'function') {
|
|
201
178
|
try {
|
|
@@ -210,9 +187,7 @@ class ThinPoolImpl extends PoolImpl {
|
|
|
210
187
|
errors.throwErr(errors.ERR_TOKEN_HAS_EXPIRED);
|
|
211
188
|
} else {
|
|
212
189
|
// update pool with OAuth2 token
|
|
213
|
-
|
|
214
|
-
this._token = obj.value;
|
|
215
|
-
this._obfuscatedToken = obj.obfuscatedValue;
|
|
190
|
+
this._token.set(clonedAttrs.token);
|
|
216
191
|
}
|
|
217
192
|
} else if (typeof accessToken === 'object') {
|
|
218
193
|
clonedAttrs.token = accessToken.token;
|
|
@@ -222,12 +197,8 @@ class ThinPoolImpl extends PoolImpl {
|
|
|
222
197
|
errors.throwErr(errors.ERR_TOKEN_HAS_EXPIRED);
|
|
223
198
|
} else {
|
|
224
199
|
// update pool with IAM token and private key
|
|
225
|
-
|
|
226
|
-
this.
|
|
227
|
-
this._obfuscatedToken = objToken.obfuscatedValue;
|
|
228
|
-
const objKey = protocolUtil.setObfuscatedValue(clonedAttrs.privateKey);
|
|
229
|
-
this._privateKey = objKey.value;
|
|
230
|
-
this._obfuscatedPrivateKey = objKey.obfuscatedValue;
|
|
200
|
+
this._token.set(clonedAttrs.token);
|
|
201
|
+
this._privateKey.set(clonedAttrs.privateKey);
|
|
231
202
|
}
|
|
232
203
|
}
|
|
233
204
|
} else {
|
|
@@ -236,9 +207,7 @@ class ThinPoolImpl extends PoolImpl {
|
|
|
236
207
|
}
|
|
237
208
|
}
|
|
238
209
|
if (clonedAttrs.privateKey === null) {
|
|
239
|
-
clonedAttrs.privateKey =
|
|
240
|
-
protocolUtil.getDeobfuscatedValue(this._privateKey,
|
|
241
|
-
this._obfuscatedPrivateKey);
|
|
210
|
+
clonedAttrs.privateKey = this._privateKey.get();
|
|
242
211
|
}
|
|
243
212
|
return clonedAttrs;
|
|
244
213
|
}
|
|
@@ -259,8 +228,10 @@ class ThinPoolImpl extends PoolImpl {
|
|
|
259
228
|
if (connection.nscon.ntAdapter.connected) {
|
|
260
229
|
connection._dropSess = true;
|
|
261
230
|
await connection.close();
|
|
231
|
+
// emit pool event when a connection is destroyed
|
|
232
|
+
this._eventCallback("onPoolShrink");
|
|
262
233
|
}
|
|
263
|
-
} catch
|
|
234
|
+
} catch {
|
|
264
235
|
return;
|
|
265
236
|
}
|
|
266
237
|
}
|
|
@@ -301,6 +272,10 @@ class ThinPoolImpl extends PoolImpl {
|
|
|
301
272
|
if (this._bgCleaner)
|
|
302
273
|
this._bgCleaner();
|
|
303
274
|
});
|
|
275
|
+
|
|
276
|
+
// clear _eventCallback to break the reference cycle created by the closure
|
|
277
|
+
// capturing the user pool object.
|
|
278
|
+
this._eventCallback = null;
|
|
304
279
|
}
|
|
305
280
|
|
|
306
281
|
//---------------------------------------------------------------------------
|
|
@@ -473,6 +448,9 @@ class ThinPoolImpl extends PoolImpl {
|
|
|
473
448
|
conn._creationTime = Date.now();
|
|
474
449
|
conn._lastTimeUsed = Date.now();
|
|
475
450
|
this._freeConnectionList.push(conn);
|
|
451
|
+
|
|
452
|
+
// emit pool event when new connections are created in background
|
|
453
|
+
this._eventCallback("onPoolExpand");
|
|
476
454
|
} catch (err) {
|
|
477
455
|
this._bgErr = err;
|
|
478
456
|
}
|
|
@@ -589,6 +567,7 @@ class ThinPoolImpl extends PoolImpl {
|
|
|
589
567
|
|
|
590
568
|
// connection has passed health checks, return it immediately
|
|
591
569
|
this._usedConnectionList.add(conn);
|
|
570
|
+
this._eventCallback("onPoolConnectionHit");
|
|
592
571
|
return conn;
|
|
593
572
|
|
|
594
573
|
}
|
|
@@ -619,6 +598,7 @@ class ThinPoolImpl extends PoolImpl {
|
|
|
619
598
|
}
|
|
620
599
|
// return a connection from the ones that were just built
|
|
621
600
|
const conn = this._freeConnectionList.pop();
|
|
601
|
+
this._eventCallback("onPoolConnectionMiss");
|
|
622
602
|
this._usedConnectionList.add(conn);
|
|
623
603
|
return conn;
|
|
624
604
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright (c) 2022,
|
|
1
|
+
// Copyright (c) 2022, 2026, Oracle and/or its affiliates.
|
|
2
2
|
|
|
3
3
|
//-----------------------------------------------------------------------------
|
|
4
4
|
//
|
|
@@ -42,11 +42,13 @@ class Capabilities {
|
|
|
42
42
|
this.supports12cLogon = true;
|
|
43
43
|
this.supportsOob = false;
|
|
44
44
|
this.nCharsetId = constants.TNS_CHARSET_UTF16;
|
|
45
|
+
this.charsetId = constants.TNS_CHARSET_UTF8;
|
|
45
46
|
this.compileCaps = Buffer.alloc(constants.TNS_CCAP_MAX);
|
|
46
47
|
this.runtimeCaps = Buffer.alloc(constants.TNS_RCAP_MAX);
|
|
47
48
|
this.initCompileCaps(nscon);
|
|
48
49
|
this.initRuntimeCaps();
|
|
49
50
|
this.maxStringSize = 0;
|
|
51
|
+
this.supportsEndUserSecurityContext = false;
|
|
50
52
|
}
|
|
51
53
|
|
|
52
54
|
adjustForServerCompileCaps(serverCaps, nscon) {
|
|
@@ -62,6 +64,11 @@ class Capabilities {
|
|
|
62
64
|
^= constants.TNS_CCAP_END_OF_REQUEST;
|
|
63
65
|
nscon.endOfRequestSupport = false;
|
|
64
66
|
}
|
|
67
|
+
const bpIndex = constants.TNS_CCAP_FEATURE_BACKPORT2;
|
|
68
|
+
if (bpIndex < serverCaps.length &&
|
|
69
|
+
(serverCaps[bpIndex] & constants.TNS_CCAP_END_USER_SEC_CTX_PIGGYBACK)) {
|
|
70
|
+
this.supportsEndUserSecurityContext = true;
|
|
71
|
+
}
|
|
65
72
|
}
|
|
66
73
|
|
|
67
74
|
adjustForServerRuntimeCaps(serverCaps) {
|
|
@@ -123,9 +130,13 @@ class Capabilities {
|
|
|
123
130
|
constants.TNS_CCAP_CTB_OAUTH_MSG_ON_ERR;
|
|
124
131
|
this.compileCaps[constants.TNS_CCAP_TTC5] =
|
|
125
132
|
constants.TNS_CCAP_VECTOR_SUPPORT |
|
|
133
|
+
constants.TNS_CCAP_TOKEN_SUPPORTED |
|
|
134
|
+
constants.TNS_CCAP_PIPELINING_SUPPORT |
|
|
135
|
+
constants.TNS_CCAP_PIPELINING_BREAK |
|
|
126
136
|
constants.TNS_CCAP_TTC5_SESSIONLESS_TXNS;
|
|
127
137
|
this.compileCaps[constants.TNS_CCAP_VECTOR_FEATURES] =
|
|
128
138
|
constants.TNS_CCAP_VECTOR_FEATURE_BINARY | constants.TNS_CCAP_VECTOR_FEATURE_SPARSE;
|
|
139
|
+
this.compileCaps[constants.TNS_CCAP_FEATURE_BACKPORT2] = constants.TNS_CCAP_END_USER_SEC_CTX_PIGGYBACK;
|
|
129
140
|
}
|
|
130
141
|
|
|
131
142
|
initRuntimeCaps() {
|
|
@@ -135,9 +146,13 @@ class Capabilities {
|
|
|
135
146
|
}
|
|
136
147
|
|
|
137
148
|
checkNCharsetId() {
|
|
138
|
-
if (this.nCharsetId !== constants.TNS_CHARSET_UTF16)
|
|
149
|
+
if (this.nCharsetId !== constants.TNS_CHARSET_UTF16)
|
|
139
150
|
errors.throwErr(errors.ERR_NCHAR_CS_NOT_SUPPORTED, this.nCharsetId);
|
|
140
|
-
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
checkCharsetId() {
|
|
154
|
+
if (this.charsetId !== constants.TNS_CHARSET_UTF8)
|
|
155
|
+
errors.throwErr(errors.ERR_CHAR_CS_NOT_SUPPORTED, this.charsetId);
|
|
141
156
|
}
|
|
142
157
|
|
|
143
158
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright (c) 2022,
|
|
1
|
+
// Copyright (c) 2022, 2026, Oracle and/or its affiliates.
|
|
2
2
|
|
|
3
3
|
//-----------------------------------------------------------------------------
|
|
4
4
|
//
|
|
@@ -407,7 +407,12 @@ module.exports = {
|
|
|
407
407
|
TNS_DATA_TYPE_OAC: 646,
|
|
408
408
|
TNS_DATA_TYPE_SESSSIGN: 647,
|
|
409
409
|
TNS_DATA_TYPE_OER: 652,
|
|
410
|
+
TNS_DATA_TYPE_PLEND: 660,
|
|
411
|
+
TNS_DATA_TYPE_PLBGN: 661,
|
|
410
412
|
TNS_DATA_TYPE_UDS: 663,
|
|
413
|
+
TNS_DATA_TYPE_PLOP: 665,
|
|
414
|
+
TNS_DATA_TYPE_KVE: 669,
|
|
415
|
+
TNS_DATA_TYPE_EUSC: 670,
|
|
411
416
|
|
|
412
417
|
// data type representations
|
|
413
418
|
TNS_TYPE_REP_NATIVE: 0,
|
|
@@ -435,12 +440,15 @@ module.exports = {
|
|
|
435
440
|
TNS_MSG_TYPE_IMPLICIT_RESULTSET: 27,
|
|
436
441
|
TNS_MSG_TYPE_RENEGOTIATE: 28,
|
|
437
442
|
TNS_MSG_TYPE_END_OF_REQUEST: 29,
|
|
443
|
+
TNS_MSG_TYPE_TOKEN: 33,
|
|
438
444
|
TNS_MSG_TYPE_FAST_AUTH: 34,
|
|
439
445
|
|
|
440
446
|
// parameter keyword numbers,
|
|
441
447
|
TNS_KEYWORD_NUM_CURRENT_SCHEMA: 168,
|
|
442
448
|
TNS_KEYWORD_NUM_EDITION: 172,
|
|
443
449
|
TNS_KEYWORD_NUM_TRANSACTION_ID: 201,
|
|
450
|
+
TNS_KEYWORD_PDBNAME: 197, // Container Name
|
|
451
|
+
TNS_KEYWORD_DBNAME: 179, // Global DB Name
|
|
444
452
|
|
|
445
453
|
// bind flags
|
|
446
454
|
TNS_BIND_USE_INDICATORS: 0x0001,
|
|
@@ -541,13 +549,20 @@ module.exports = {
|
|
|
541
549
|
// TTC functions
|
|
542
550
|
TNS_FUNC_AUTH_PHASE_ONE: 118,
|
|
543
551
|
TNS_FUNC_AUTH_PHASE_TWO: 115,
|
|
552
|
+
TNS_FUNC_APP_CONTEXT: 154,
|
|
544
553
|
TNS_FUNC_CLOSE_CURSORS: 105,
|
|
545
554
|
TNS_FUNC_COMMIT: 14,
|
|
555
|
+
TNS_FUNC_DIRECT_PATH_LOAD_STREAM: 129,
|
|
556
|
+
TNS_FUNC_DIRECT_PATH_OP: 130,
|
|
557
|
+
TNS_FUNC_DIRECT_PATH_PREPARE: 128,
|
|
558
|
+
TNS_FUNC_END_USER_SECURITY_CTX: 205,
|
|
546
559
|
TNS_FUNC_EXECUTE: 94,
|
|
547
560
|
TNS_FUNC_FETCH: 5,
|
|
548
561
|
TNS_FUNC_LOB_OP: 96,
|
|
549
562
|
TNS_FUNC_LOGOFF: 9,
|
|
550
563
|
TNS_FUNC_PING: 147,
|
|
564
|
+
TNS_FUNC_PIPELINE_BEGIN: 199,
|
|
565
|
+
TNS_FUNC_PIPELINE_END: 200,
|
|
551
566
|
TNS_FUNC_ROLLBACK: 15,
|
|
552
567
|
TNS_FUNC_SET_END_TO_END_ATTR: 135,
|
|
553
568
|
TNS_FUNC_REEXECUTE: 4,
|
|
@@ -595,6 +610,7 @@ module.exports = {
|
|
|
595
610
|
TNS_CCAP_TTC4: 40,
|
|
596
611
|
TNS_CCAP_LOB2: 42,
|
|
597
612
|
TNS_CCAP_TTC5: 44,
|
|
613
|
+
TNS_CCAP_FEATURE_BACKPORT2: 45,
|
|
598
614
|
TNS_CCAP_VECTOR_FEATURES: 52,
|
|
599
615
|
TNS_CCAP_MAX: 53,
|
|
600
616
|
|
|
@@ -654,10 +670,14 @@ module.exports = {
|
|
|
654
670
|
TNS_CCAP_CTB_IMPLICIT_POOL: 0x08,
|
|
655
671
|
TNS_CCAP_CTB_OAUTH_MSG_ON_ERR: 0x10,
|
|
656
672
|
TNS_CCAP_VECTOR_SUPPORT: 0x08,
|
|
673
|
+
TNS_CCAP_TOKEN_SUPPORTED: 0x02,
|
|
674
|
+
TNS_CCAP_PIPELINING_SUPPORT: 0x04,
|
|
675
|
+
TNS_CCAP_PIPELINING_BREAK: 0x10,
|
|
657
676
|
TNS_CCAP_VECTOR_FEATURE_BINARY: 0x01,
|
|
658
677
|
TNS_CCAP_VECTOR_FEATURE_SPARSE: 0x02,
|
|
659
678
|
TNS_CCAP_TTC5_SESSIONLESS_TXNS: 0x20,
|
|
660
679
|
TNS_CCAP_OCI3_OCSSYNC: 0x20,
|
|
680
|
+
TNS_CCAP_END_USER_SEC_CTX_PIGGYBACK: 0x02,
|
|
661
681
|
|
|
662
682
|
// runtime capability indices
|
|
663
683
|
TNS_RCAP_COMPAT: 0,
|
|
@@ -776,6 +796,58 @@ module.exports = {
|
|
|
776
796
|
TNS_AQ_EXT_KEYWORD_AGENT_PROTOCOL: 66,
|
|
777
797
|
TNS_AQ_EXT_KEYWORD_ORIGINAL_MSGID: 69,
|
|
778
798
|
|
|
799
|
+
// direct path constants
|
|
800
|
+
TNS_DP_INTERFACE_VERSION: 400,
|
|
801
|
+
TNS_DP_STREAM_VERSION: 400,
|
|
802
|
+
|
|
803
|
+
// direct path op codes
|
|
804
|
+
TNS_DPP_OP_CODE_LOAD: 1,
|
|
805
|
+
TNS_DPP_OP_CODE_UNLOAD: 2,
|
|
806
|
+
TNS_DPP_OP_CODE_CONVERT: 3,
|
|
807
|
+
|
|
808
|
+
// direct path prepare input indexes
|
|
809
|
+
TNS_DPP_IN_INDEX_INTERFACE_VERSION: 0,
|
|
810
|
+
TNS_DPP_IN_INDEX_STREAM_VERSION: 1,
|
|
811
|
+
TNS_DPP_IN_INDEX_LOCK_WAIT: 14,
|
|
812
|
+
TNS_DPP_IN_MAX_PARAMS: 36,
|
|
813
|
+
|
|
814
|
+
// direct path prepare keyword indexes
|
|
815
|
+
TNS_DPP_KW_INDEX_OBJECT_NAME: 1,
|
|
816
|
+
TNS_DPP_KW_INDEX_SUBOBJECT_NAME: 2,
|
|
817
|
+
TNS_DPP_KW_INDEX_SCHEMA_NAME: 3,
|
|
818
|
+
TNS_DPP_KW_INDEX_COLUMN_NAME: 4,
|
|
819
|
+
TNS_DPP_KW_INDEX_VARRAY_TABLE: 15,
|
|
820
|
+
TNS_DPP_KW_INDEX_NFOBJ_OID_POS: 11,
|
|
821
|
+
TNS_DPP_KW_INDEX_NFOBJ_SID_POS: 16,
|
|
822
|
+
TNS_DPP_KW_INDEX_NFOBJ_VARRAY_INDEX: 17,
|
|
823
|
+
|
|
824
|
+
// direct path prepare output indexes
|
|
825
|
+
TNS_DPP_OUT_INDEX_CURSOR: 3,
|
|
826
|
+
TNS_DPP_OUT_MAX_PARAMS: 14,
|
|
827
|
+
|
|
828
|
+
// direct path row header flags
|
|
829
|
+
TNS_DPLS_ROW_HEADER_FAST_PIECE: 0x10,
|
|
830
|
+
TNS_DPLS_ROW_HEADER_FAST_ROW: 0x20,
|
|
831
|
+
TNS_DPLS_ROW_HEADER_FIRST: 0x08,
|
|
832
|
+
TNS_DPLS_ROW_HEADER_LAST: 0x04,
|
|
833
|
+
TNS_DPLS_ROW_HEADER_SPLIT_WITH_PREV: 0x02,
|
|
834
|
+
TNS_DPLS_ROW_HEADER_SPLIT_WITH_NEXT: 0x01,
|
|
835
|
+
|
|
836
|
+
// other direct path load stream constants
|
|
837
|
+
TNS_DPLS_MAX_BUFFER_SIZE_FACTOR: 22,
|
|
838
|
+
TNS_DPLS_MAX_SHORT_LENGTH: 0xfa,
|
|
839
|
+
TNS_DPLS_MAX_MESSAGE_SIZE: 1073728895,
|
|
840
|
+
TNS_DPLS_MAX_PIECE_SIZE: 0xfff0,
|
|
841
|
+
TNS_DPLS_FAST_HEADER_SIZE: 4,
|
|
842
|
+
TNS_DPLS_SLOW_HEADER_SIZE: 2,
|
|
843
|
+
|
|
844
|
+
// direct path operation codes
|
|
845
|
+
TNS_DP_OP_ABORT: 1,
|
|
846
|
+
TNS_DP_OP_FINISH: 2,
|
|
847
|
+
|
|
848
|
+
// Security Context constants
|
|
849
|
+
TNS_OSON_SEC_CTX_MAX_FNAME_SIZE: 255,
|
|
850
|
+
TNS_SECURITY_CONTEXT_ATTACH_FLAG: 0x01,
|
|
779
851
|
|
|
780
852
|
// other constants
|
|
781
853
|
TNS_ESCAPE_CHAR: 253,
|
|
@@ -865,8 +937,16 @@ module.exports = {
|
|
|
865
937
|
CHUNKED_BYTES_CHUNK_SIZE: 65536,
|
|
866
938
|
|
|
867
939
|
// Network Header flags for Data packet
|
|
868
|
-
|
|
940
|
+
TNS_DATA_FLAGS_BEGIN_PIPELINE: 0x1000,
|
|
941
|
+
TNS_DATA_FLAGS_END_OF_REQUEST: 0x800,
|
|
942
|
+
TNS_DATA_FLAGS_END_OF_RESPONSE: 0x2000,
|
|
943
|
+
TNS_DATA_FLAGS_OFFSET: 0x8,
|
|
869
944
|
|
|
945
|
+
// pipeline modes
|
|
946
|
+
TNS_PIPELINE_MODE_CONTINUE_ON_ERROR: 1,
|
|
947
|
+
TNS_PIPELINE_MODE_ABORT_ON_ERROR: 2,
|
|
948
|
+
|
|
949
|
+
// base 64 encoding alphabet
|
|
870
950
|
TNS_BASE64_ALPHABET_ARRAY: Buffer.from('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'),
|
|
871
951
|
TNS_EXTENT_OID: Buffer.from('00000000000000000000000000010001', 'hex')
|
|
872
952
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright (c) 2022,
|
|
1
|
+
// Copyright (c) 2022, 2026, Oracle and/or its affiliates.
|
|
2
2
|
|
|
3
3
|
//-----------------------------------------------------------------------------
|
|
4
4
|
//
|
|
@@ -28,8 +28,43 @@
|
|
|
28
28
|
|
|
29
29
|
const { Buffer } = require('buffer');
|
|
30
30
|
const crypto = require('crypto');
|
|
31
|
+
const errors = require('../../errors.js');
|
|
32
|
+
|
|
33
|
+
const MAX_PBKDF2_ITERATIONS = 100_000;
|
|
34
|
+
|
|
35
|
+
function getPBKDF2Iterations(sessionData, key) {
|
|
36
|
+
const iterations = Number(sessionData[key]);
|
|
37
|
+
if (!Number.isInteger(iterations) || iterations < 1 ||
|
|
38
|
+
iterations > MAX_PBKDF2_ITERATIONS) {
|
|
39
|
+
errors.throwErr(errors.ERR_INVALID_SERVER_RESPONSE);
|
|
40
|
+
}
|
|
41
|
+
return iterations;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function resolveCipherKey(key) {
|
|
45
|
+
if (!Buffer.isBuffer(key)) {
|
|
46
|
+
errors.throwErr(errors.ERR_INTERNAL,
|
|
47
|
+
'Encryption key must be a Buffer');
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
let cipherAlg;
|
|
51
|
+
switch (key.length) {
|
|
52
|
+
case 16:
|
|
53
|
+
cipherAlg = 'aes-128-cbc';
|
|
54
|
+
break;
|
|
55
|
+
case 24:
|
|
56
|
+
cipherAlg = 'aes-192-cbc';
|
|
57
|
+
break;
|
|
58
|
+
case 32:
|
|
59
|
+
cipherAlg = 'aes-256-cbc';
|
|
60
|
+
break;
|
|
61
|
+
default:
|
|
62
|
+
errors.throwErr(errors.ERR_UNSUPPORTED_KEY_LENGTH, key.length);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return cipherAlg;
|
|
66
|
+
}
|
|
31
67
|
|
|
32
|
-
let algorithm = 'aes-256-cbc';
|
|
33
68
|
const _appendBuffer = Buffer.from([0x00, 0x01]);
|
|
34
69
|
|
|
35
70
|
/**
|
|
@@ -42,7 +77,8 @@ class EncryptDecrypt {
|
|
|
42
77
|
// 24 bytes (192 bits).
|
|
43
78
|
decrypt(key, val) {
|
|
44
79
|
const iv = Buffer.alloc(16, 0); // Initialization vector, same is used in server
|
|
45
|
-
const
|
|
80
|
+
const cipherAlg = resolveCipherKey(key);
|
|
81
|
+
const decipher = crypto.createDecipheriv(cipherAlg, key, iv);
|
|
46
82
|
decipher.setAutoPadding(false);
|
|
47
83
|
let decrypted = decipher.update(val);
|
|
48
84
|
decrypted = Buffer.concat([decrypted, decipher.final()]);
|
|
@@ -61,7 +97,8 @@ class EncryptDecrypt {
|
|
|
61
97
|
val = Buffer.concat([val, nv]);
|
|
62
98
|
}
|
|
63
99
|
}
|
|
64
|
-
const
|
|
100
|
+
const cipherAlg = resolveCipherKey(key);
|
|
101
|
+
const cipher = crypto.createCipheriv(cipherAlg, key, iv);
|
|
65
102
|
let encrypted = cipher.update(val);
|
|
66
103
|
encrypted = Buffer.concat([encrypted, cipher.final()]);
|
|
67
104
|
if (!padding) {
|
|
@@ -108,13 +145,11 @@ class EncryptDecrypt {
|
|
|
108
145
|
|
|
109
146
|
const verifierData = Buffer.from(sessionData['AUTH_VFR_DATA'], 'hex');
|
|
110
147
|
const encodedServerKey = Buffer.from(sessionData['AUTH_SESSKEY'], 'hex');
|
|
111
|
-
let iterations = Number(sessionData['AUTH_PBKDF2_VGEN_COUNT']);
|
|
112
148
|
const passwordBytes = Buffer.from(password, 'utf8');
|
|
113
149
|
let passwordHash;
|
|
114
150
|
let passwordKey;
|
|
115
151
|
|
|
116
152
|
if (verifier11G) {
|
|
117
|
-
algorithm = 'aes-192-cbc';
|
|
118
153
|
keyLen = 24;
|
|
119
154
|
hashAlg = 'sha1';
|
|
120
155
|
const h = crypto.createHash(hashAlg);
|
|
@@ -124,9 +159,9 @@ class EncryptDecrypt {
|
|
|
124
159
|
passwordHash = Buffer.alloc(ph.length + 4);
|
|
125
160
|
ph.copy(passwordHash, 0, 0, ph.length);
|
|
126
161
|
} else {
|
|
127
|
-
algorithm = 'aes-256-cbc';
|
|
128
162
|
const temp = Buffer.from('AUTH_PBKDF2_SPEEDY_KEY', 'utf8');
|
|
129
163
|
const salt = Buffer.concat([verifierData, temp]);
|
|
164
|
+
const iterations = getPBKDF2Iterations(sessionData, 'AUTH_PBKDF2_VGEN_COUNT');
|
|
130
165
|
passwordKey = crypto.pbkdf2Sync(passwordBytes, salt, iterations, 64, 'sha512');
|
|
131
166
|
const h = crypto.createHash(hashAlg);
|
|
132
167
|
h.update(passwordKey);
|
|
@@ -155,7 +190,7 @@ class EncryptDecrypt {
|
|
|
155
190
|
} else {
|
|
156
191
|
authObj.sessionKey = encodedClientKey.slice().toString('hex').toUpperCase().slice(0, 64);
|
|
157
192
|
const mixingSalt = Buffer.from(sessionData['AUTH_PBKDF2_CSK_SALT'], 'hex');
|
|
158
|
-
iterations =
|
|
193
|
+
const iterations = getPBKDF2Iterations(sessionData, 'AUTH_PBKDF2_SDER_COUNT');
|
|
159
194
|
const partABKey = Buffer.concat([sessionKeyPartb.slice(0, keyLen), sessionKeyParta.slice(0, keyLen)]);
|
|
160
195
|
const partABKeyStr = partABKey.toString('hex').toUpperCase();
|
|
161
196
|
const partABKeyBuffer = Buffer.from(partABKeyStr, 'utf8');
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright (c) 2025, Oracle and/or its affiliates.
|
|
1
|
+
// Copyright (c) 2025, 2026, Oracle and/or its affiliates.
|
|
2
2
|
|
|
3
3
|
//-----------------------------------------------------------------------------
|
|
4
4
|
//
|
|
@@ -78,7 +78,7 @@ class AqArrayMessage extends AqBaseMessage {
|
|
|
78
78
|
}
|
|
79
79
|
temp16 = buf.readUB2(); // extensions len
|
|
80
80
|
if (temp16 > 0) {
|
|
81
|
-
errors.
|
|
81
|
+
errors.throwNotImplemented('AQ extensions');
|
|
82
82
|
}
|
|
83
83
|
buf.skipUB2(); // output ack
|
|
84
84
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright (c) 2025, Oracle and/or its affiliates.
|
|
1
|
+
// Copyright (c) 2025, 2026, Oracle and/or its affiliates.
|
|
2
2
|
|
|
3
3
|
//-----------------------------------------------------------------------------
|
|
4
4
|
//
|
|
@@ -134,7 +134,7 @@ class AqBaseMessage extends BaseMessage {
|
|
|
134
134
|
this._processExtensions(buf, propsImpl);
|
|
135
135
|
const temp32 = buf.readUB4(); // user properties
|
|
136
136
|
if (temp32 > 0) {
|
|
137
|
-
errors.
|
|
137
|
+
errors.throwNotImplemented('AQ User Properties');
|
|
138
138
|
}
|
|
139
139
|
buf.skipUB4(); // csn
|
|
140
140
|
buf.skipUB4(); // dsn
|