oracledb 6.10.0 → 7.0.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.
Files changed (84) hide show
  1. package/LICENSE.txt +1 -1
  2. package/NOTICE.txt +1 -1
  3. package/README.md +9 -9
  4. package/build/Release/oracledb-7.0.0-darwin-arm64.node +0 -0
  5. package/build/Release/oracledb-7.0.0-darwin-arm64.node-buildinfo.txt +1 -0
  6. package/build/Release/oracledb-7.0.0-js-buildinfo.txt +1 -0
  7. package/build/Release/oracledb-7.0.0-linux-arm64.node +0 -0
  8. package/build/Release/oracledb-7.0.0-linux-arm64.node-buildinfo.txt +1 -0
  9. package/build/Release/oracledb-7.0.0-linux-x64.node +0 -0
  10. package/build/Release/oracledb-7.0.0-linux-x64.node-buildinfo.txt +1 -0
  11. package/build/Release/oracledb-7.0.0-win32-x64.node +0 -0
  12. package/build/Release/oracledb-7.0.0-win32-x64.node-buildinfo.txt +1 -0
  13. package/eslint.config.js +39 -0
  14. package/lib/connection.js +412 -37
  15. package/lib/endUserSecurityContext.js +176 -0
  16. package/lib/errors.js +86 -5
  17. package/lib/impl/connection.js +76 -2
  18. package/lib/impl/datahandlers/buffer.js +19 -5
  19. package/lib/impl/datahandlers/vector.js +25 -5
  20. package/lib/impl/lob.js +9 -0
  21. package/lib/impl/parserHelpers.js +443 -0
  22. package/lib/impl/resultset.js +1 -1
  23. package/lib/lob.js +27 -14
  24. package/lib/obfuscation.js +97 -0
  25. package/lib/oracledb.js +148 -43
  26. package/lib/parser.js +204 -0
  27. package/lib/pipeline.js +113 -0
  28. package/lib/pool.js +16 -1
  29. package/lib/resultset.js +42 -21
  30. package/lib/settings.js +1 -0
  31. package/lib/thin/connection.js +467 -53
  32. package/lib/thin/dbObject.js +7 -1
  33. package/lib/thin/lob.js +20 -1
  34. package/lib/thin/pool.js +42 -62
  35. package/lib/thin/protocol/capabilities.js +18 -3
  36. package/lib/thin/protocol/constants.js +82 -2
  37. package/lib/thin/protocol/encryptDecrypt.js +43 -8
  38. package/lib/thin/protocol/messages/auth.js +6 -1
  39. package/lib/thin/protocol/messages/base.js +245 -4
  40. package/lib/thin/protocol/messages/dataType.js +8 -3
  41. package/lib/thin/protocol/messages/directPathLoadStream.js +377 -0
  42. package/lib/thin/protocol/messages/directPathOp.js +65 -0
  43. package/lib/thin/protocol/messages/directPathPrepare.js +158 -0
  44. package/lib/thin/protocol/messages/endPipeline.js +56 -0
  45. package/lib/thin/protocol/messages/execute.js +9 -7
  46. package/lib/thin/protocol/messages/index.js +9 -1
  47. package/lib/thin/protocol/messages/protocol.js +2 -2
  48. package/lib/thin/protocol/messages/withData.js +8 -140
  49. package/lib/thin/protocol/packet.js +115 -24
  50. package/lib/thin/protocol/protocol.js +110 -25
  51. package/lib/thin/protocol/utils.js +1 -26
  52. package/lib/thin/resultSet.js +13 -19
  53. package/lib/thin/sqlnet/ezConnectResolver.js +2 -2
  54. package/lib/thin/sqlnet/networkSession.js +62 -40
  55. package/lib/thin/sqlnet/ntTcp.js +24 -0
  56. package/lib/thin/sqlnet/nvStrToNvPair.js +50 -25
  57. package/lib/thin/sqlnet/packet.js +25 -4
  58. package/lib/thin/sqlnet/paramParser.js +10 -7
  59. package/lib/thin/statementCache.js +2 -4
  60. package/lib/traceHandler.js +59 -2
  61. package/lib/transformer.js +8 -3
  62. package/lib/types.js +35 -21
  63. package/lib/util.js +6 -6
  64. package/lib/version.js +3 -3
  65. package/package/install.js +5 -5
  66. package/package/prunebinaries.js +1 -1
  67. package/package.json +1 -1
  68. package/plugins/configProviders/awsCommon.js +125 -0
  69. package/plugins/configProviders/awss3/index.js +138 -0
  70. package/plugins/configProviders/awssecretsmanager/index.js +147 -0
  71. package/plugins/configProviders/azure/index.js +4 -5
  72. package/plugins/token/extensionAzure/index.js +0 -1
  73. package/plugins/token/extensionOci/index.js +0 -1
  74. package/build/Release/oracledb-6.10.0-darwin-arm64.node +0 -0
  75. package/build/Release/oracledb-6.10.0-darwin-arm64.node-buildinfo.txt +0 -1
  76. package/build/Release/oracledb-6.10.0-darwin-x64.node +0 -0
  77. package/build/Release/oracledb-6.10.0-darwin-x64.node-buildinfo.txt +0 -1
  78. package/build/Release/oracledb-6.10.0-js-buildinfo.txt +0 -1
  79. package/build/Release/oracledb-6.10.0-linux-arm64.node +0 -0
  80. package/build/Release/oracledb-6.10.0-linux-arm64.node-buildinfo.txt +0 -1
  81. package/build/Release/oracledb-6.10.0-linux-x64.node +0 -0
  82. package/build/Release/oracledb-6.10.0-linux-x64.node-buildinfo.txt +0 -1
  83. package/build/Release/oracledb-6.10.0-win32-x64.node +0 -0
  84. package/build/Release/oracledb-6.10.0-win32-x64.node-buildinfo.txt +0 -1
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
- this._length += data.length;
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');
@@ -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 = params.password;
69
- this._walletPassword = params.walletPassword;
70
- this._walletContent = params.walletContent;
71
- this._obfuscatedPassword = [];
72
- this._obfuscatedWalletPassword = [];
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 (this._password !== undefined) {
86
- const obj = protocolUtil.setObfuscatedValue(this._password);
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 (this._walletPassword !== undefined) {
93
- const obj = protocolUtil.setObfuscatedValue(this._walletPassword);
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 (this._walletContent !== undefined) {
100
- const obj = protocolUtil.setObfuscatedValue(this._walletContent);
101
- this._walletContent = obj.value;
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 (this._token !== undefined) {
107
- const obj = protocolUtil.setObfuscatedValue(this._token);
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 (this._privateKey !== undefined) {
114
- const obj = protocolUtil.setObfuscatedValue(this._privateKey);
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 = params.token;
154
- const objToken = protocolUtil.setObfuscatedValue(this._token);
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 = params.privateKey;
160
- const objKey = protocolUtil.setObfuscatedValue(this._privateKey);
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 = protocolUtil.getDeobfuscatedValue(this._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
- const obj = protocolUtil.setObfuscatedValue(clonedAttrs.token);
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
- const objToken = protocolUtil.setObfuscatedValue(clonedAttrs.token);
226
- this._token = objToken.value;
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 (err) {
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, 2025, Oracle and/or its affiliates.
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, 2025, Oracle and/or its affiliates.
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
- TNS_DATA_FLAGS_END_OF_REQUEST: 0x2000,
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, 2023, Oracle and/or its affiliates.
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 decipher = crypto.createDecipheriv(algorithm, key, iv);
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 cipher = crypto.createCipheriv(algorithm, key, iv);
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 = Number(sessionData['AUTH_PBKDF2_SDER_COUNT']);
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');
@@ -29,6 +29,7 @@
29
29
  const { Buffer } = require('buffer');
30
30
  const constants = require("../constants.js");
31
31
  const errors = require("../../../errors.js");
32
+ const parser = require("../../../parser.js");
32
33
  const process = require("process");
33
34
  const ED = require("../encryptDecrypt.js");
34
35
  const Message = require("./base.js");
@@ -158,6 +159,10 @@ class AuthMessage extends Message {
158
159
  let sign, tzRepr;
159
160
  if (process.env.ORA_SDTZ) {
160
161
  tzRepr = process.env.ORA_SDTZ;
162
+ // LOCAL and DBTIMEZONE are SQL keywords and must not be quoted.
163
+ if (["LOCAL", "DBTIMEZONE"].includes(tzRepr.toUpperCase())) {
164
+ return `ALTER SESSION SET TIME_ZONE =${tzRepr}\x00`;
165
+ }
161
166
  } else {
162
167
  const date = new Date();
163
168
  const timezoneMinutes = date.getTimezoneOffset();
@@ -172,7 +177,7 @@ class AuthMessage extends Message {
172
177
  tzHour = tzHour.toLocaleString('en-US', {minimumIntegerDigits: 2});
173
178
  tzRepr = `${sign}${tzHour}:${tzMinutes}`;
174
179
  }
175
- return `ALTER SESSION SET TIME_ZONE ='${tzRepr}'\x00`;
180
+ return `ALTER SESSION SET TIME_ZONE =${parser.enquoteLiteral(tzRepr)}\x00`;
176
181
  }
177
182
 
178
183
  encode(buf) {