| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 5823fc7 commit eb20447
3 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -21,45 +21,39 @@ | |||
| 21 | 21 | ||
| 22 | 22 | 'use strict'; | |
| 23 | 23 | ||
| 24 | + const tls = require('tls'); | ||
| 25 | + | ||
| 24 | 26 | const { | |
| 25 | - ArrayIsArray, | ||
| 26 | - ArrayPrototypeFilter, | ||
| 27 | - ArrayPrototypeForEach, | ||
| 28 | - ArrayPrototypeJoin, | ||
| 29 | 27 | ArrayPrototypePush, | |
| 30 | 28 | ObjectCreate, | |
| 31 | 29 | StringPrototypeReplace, | |
| 32 | - StringPrototypeSplit, | ||
| 33 | - StringPrototypeStartsWith, | ||
| 34 | 30 | } = primordials; | |
| 35 | 31 | ||
| 36 | - const { parseCertString } = require('internal/tls'); | ||
| 37 | - const { isArrayBufferView } = require('internal/util/types'); | ||
| 38 | - const tls = require('tls'); | ||
| 39 | 32 | const { | |
| 40 | - ERR_CRYPTO_CUSTOM_ENGINE_NOT_SUPPORTED, | ||
| 41 | - ERR_INVALID_ARG_TYPE, | ||
| 42 | - ERR_INVALID_ARG_VALUE, | ||
| 43 | - ERR_TLS_INVALID_PROTOCOL_VERSION, | ||
| 44 | - ERR_TLS_PROTOCOL_VERSION_CONFLICT, | ||
| 45 | - } = require('internal/errors').codes; | ||
| 33 | + codes: { | ||
| 34 | + ERR_TLS_INVALID_PROTOCOL_VERSION, | ||
| 35 | + ERR_TLS_PROTOCOL_VERSION_CONFLICT, | ||
| 36 | + }, | ||
| 37 | + } = require('internal/errors'); | ||
| 38 | + | ||
| 46 | 39 | const { | |
| 47 | - SSL_OP_CIPHER_SERVER_PREFERENCE, | ||
| 48 | - TLS1_VERSION, | ||
| 49 | - TLS1_1_VERSION, | ||
| 50 | - TLS1_2_VERSION, | ||
| 51 | - TLS1_3_VERSION, | ||
| 52 | - } = internalBinding('constants').crypto; | ||
| 40 | + crypto: { | ||
| 41 | + SSL_OP_CIPHER_SERVER_PREFERENCE, | ||
| 42 | + TLS1_VERSION, | ||
| 43 | + TLS1_1_VERSION, | ||
| 44 | + TLS1_2_VERSION, | ||
| 45 | + TLS1_3_VERSION, | ||
| 46 | + }, | ||
| 47 | + } = internalBinding('constants'); | ||
| 53 | 48 | ||
| 54 | 49 | const { | |
| 55 | - validateString, | ||
| 56 | 50 | validateInteger, | |
| 57 | - validateInt32, | ||
| 58 | 51 | } = require('internal/validators'); | |
| 59 | 52 | ||
| 60 | 53 | const { | |
| 61 | - toBuf | ||
| 62 | - } = require('internal/crypto/util'); | ||
| 54 | + configSecureContext, | ||
| 55 | + parseCertString, | ||
| 56 | + } = require('internal/tls'); | ||
| 63 | 57 | ||
| 64 | 58 | function toV(which, v, def) { | |
| 65 | 59 | if (v == null) v = def; | |
@@ -70,7 +64,10 @@ function toV(which, v, def) { | |||
| 70 | 64 | throw new ERR_TLS_INVALID_PROTOCOL_VERSION(v, which); | |
| 71 | 65 | } | |
| 72 | 66 | ||
| 73 | - const { SecureContext: NativeSecureContext } = internalBinding('crypto'); | ||
| 67 | + const { | ||
| 68 | + SecureContext: NativeSecureContext, | ||
| 69 | + } = internalBinding('crypto'); | ||
| 70 | + | ||
| 74 | 71 | function SecureContext(secureProtocol, secureOptions, minVersion, maxVersion) { | |
| 75 | 72 | if (!(this instanceof SecureContext)) { | |
| 76 | 73 | return new SecureContext(secureProtocol, secureOptions, minVersion, | |
@@ -95,93 +92,14 @@ function SecureContext(secureProtocol, secureOptions, minVersion, maxVersion) { | |||
| 95 | 92 | } | |
| 96 | 93 | } | |
| 97 | 94 | ||
| 98 | - function validateKeyOrCertOption(name, value) { | ||
| 99 | - if (typeof value !== 'string' && !isArrayBufferView(value)) { | ||
| 100 | - throw new ERR_INVALID_ARG_TYPE( | ||
| 101 | - `options.${name}`, | ||
| 102 | - ['string', 'Buffer', 'TypedArray', 'DataView'], | ||
| 103 | - value | ||
| 104 | - ); | ||
| 105 | - } | ||
| 106 | - } | ||
| 107 | - | ||
| 108 | - exports.SecureContext = SecureContext; | ||
| 109 | - | ||
| 110 | - function setKey(context, key, passphrase) { | ||
| 111 | - validateKeyOrCertOption('key', key); | ||
| 112 | - if (passphrase != null) | ||
| 113 | - validateString(passphrase, 'options.passphrase'); | ||
| 114 | - context.setKey(key, passphrase); | ||
| 115 | - } | ||
| 116 | - | ||
| 117 | - function processCiphers(ciphers) { | ||
| 118 | - ciphers = StringPrototypeSplit(ciphers || tls.DEFAULT_CIPHERS, ':'); | ||
| 119 | - | ||
| 120 | - const cipherList = | ||
| 121 | - ArrayPrototypeJoin( | ||
| 122 | - ArrayPrototypeFilter( | ||
| 123 | - ciphers, | ||
| 124 | - (cipher) => { | ||
| 125 | - return cipher.length > 0 && | ||
| 126 | - !StringPrototypeStartsWith(cipher, 'TLS_'); | ||
| 127 | - }), ':'); | ||
| 128 | - | ||
| 129 | - const cipherSuites = | ||
| 130 | - ArrayPrototypeJoin( | ||
| 131 | - ArrayPrototypeFilter( | ||
| 132 | - ciphers, | ||
| 133 | - (cipher) => { | ||
| 134 | - return cipher.length > 0 && | ||
| 135 | - StringPrototypeStartsWith(cipher, 'TLS_'); | ||
| 136 | - }), ':'); | ||
| 137 | - | ||
| 138 | - // Specifying empty cipher suites for both TLS1.2 and TLS1.3 is invalid, its | ||
| 139 | - // not possible to handshake with no suites. | ||
| 140 | - if (cipherSuites === '' && cipherList === '') | ||
| 141 | - throw new ERR_INVALID_ARG_VALUE('options.ciphers', ciphers); | ||
| 142 | - | ||
| 143 | - return { cipherList, cipherSuites }; | ||
| 144 | - } | ||
| 145 | - | ||
| 146 | - function addCACerts(context, certs) { | ||
| 147 | - ArrayPrototypeForEach(certs, (cert) => { | ||
| 148 | - validateKeyOrCertOption('ca', cert); | ||
| 149 | - context.addCACert(cert); | ||
| 150 | - }); | ||
| 151 | - } | ||
| 152 | - | ||
| 153 | - function setCerts(context, certs) { | ||
| 154 | - ArrayPrototypeForEach(certs, (cert) => { | ||
| 155 | - validateKeyOrCertOption('cert', cert); | ||
| 156 | - context.setCert(cert); | ||
| 157 | - }); | ||
| 158 | - } | ||
| 159 | - | ||
| 160 | - exports.createSecureContext = function createSecureContext(options) { | ||
| 95 | + function createSecureContext(options) { | ||
| 161 | 96 | if (!options) options = {}; | |
| 162 | 97 | ||
| 163 | 98 | const { | |
| 164 | - ca, | ||
| 165 | - cert, | ||
| 166 | - ciphers, | ||
| 167 | - clientCertEngine, | ||
| 168 | - crl, | ||
| 169 | - dhparam, | ||
| 170 | - ecdhCurve = tls.DEFAULT_ECDH_CURVE, | ||
| 171 | 99 | honorCipherOrder, | |
| 172 | - key, | ||
| 173 | 100 | minVersion, | |
| 174 | 101 | maxVersion, | |
| 175 | - passphrase, | ||
| 176 | - pfx, | ||
| 177 | - privateKeyIdentifier, | ||
| 178 | - privateKeyEngine, | ||
| 179 | 102 | secureProtocol, | |
| 180 | - sessionIdContext, | ||
| 181 | - sessionTimeout, | ||
| 182 | - sigalgs, | ||
| 183 | - singleUse, | ||
| 184 | - ticketKeys, | ||
| 185 | 103 | } = options; | |
| 186 | 104 | ||
| 187 | 105 | let { secureOptions } = options; | |
@@ -192,196 +110,15 @@ exports.createSecureContext = function createSecureContext(options) { | |||
| 192 | 110 | const c = new SecureContext(secureProtocol, secureOptions, | |
| 193 | 111 | minVersion, maxVersion); | |
| 194 | 112 | ||
| 195 | - // Add CA before the cert to be able to load cert's issuer in C++ code. | ||
| 196 | - // NOTE(@jasnell): ca, cert, and key are permitted to be falsy, so do not | ||
| 197 | - // change the checks to !== undefined checks. | ||
| 198 | - if (ca) { | ||
| 199 | - if (ArrayIsArray(ca)) | ||
| 200 | - addCACerts(c.context, ca); | ||
| 201 | - else | ||
| 202 | - addCACerts(c.context, [ca]); | ||
| 203 | - } else { | ||
| 204 | - c.context.addRootCerts(); | ||
| 205 | - } | ||
| 206 | - | ||
| 207 | - if (cert) { | ||
| 208 | - if (ArrayIsArray(cert)) | ||
| 209 | - setCerts(c.context, cert); | ||
| 210 | - else | ||
| 211 | - setCerts(c.context, [cert]); | ||
| 212 | - } | ||
| 213 | - | ||
| 214 | - // Set the key after the cert. | ||
| 215 | - // `ssl_set_pkey` returns `0` when the key does not match the cert, but | ||
| 216 | - // `ssl_set_cert` returns `1` and nullifies the key in the SSL structure | ||
| 217 | - // which leads to the crash later on. | ||
| 218 | - if (key) { | ||
| 219 | - if (ArrayIsArray(key)) { | ||
| 220 | - for (let i = 0; i < key.length; ++i) { | ||
| 221 | - const val = key[i]; | ||
| 222 | - // eslint-disable-next-line eqeqeq | ||
| 223 | - const pem = (val != undefined && val.pem !== undefined ? val.pem : val); | ||
| 224 | - setKey(c.context, pem, val.passphrase || passphrase); | ||
| 225 | - } | ||
| 226 | - } else { | ||
| 227 | - setKey(c.context, key, passphrase); | ||
| 228 | - } | ||
| 229 | - } | ||
| 230 | - | ||
| 231 | - if (sigalgs !== undefined) { | ||
| 232 | - validateString(sigalgs, 'options.sigalgs'); | ||
| 233 | - | ||
| 234 | - if (sigalgs === '') | ||
| 235 | - throw new ERR_INVALID_ARG_VALUE('options.sigalgs', sigalgs); | ||
| 236 | - | ||
| 237 | - c.context.setSigalgs(sigalgs); | ||
| 238 | - } | ||
| 239 | - | ||
| 240 | - if (privateKeyIdentifier !== undefined) { | ||
| 241 | - if (privateKeyEngine === undefined) { | ||
| 242 | - // Engine is required when privateKeyIdentifier is present | ||
| 243 | - throw new ERR_INVALID_ARG_VALUE('options.privateKeyEngine', | ||
| 244 | - privateKeyEngine); | ||
| 245 | - } | ||
| 246 | - if (key) { | ||
| 247 | - // Both data key and engine key can't be set at the same time | ||
| 248 | - throw new ERR_INVALID_ARG_VALUE('options.privateKeyIdentifier', | ||
| 249 | - privateKeyIdentifier); | ||
| 250 | - } | ||
| 251 | - | ||
| 252 | - if (typeof privateKeyIdentifier === 'string' && | ||
| 253 | - typeof privateKeyEngine === 'string') { | ||
| 254 | - if (c.context.setEngineKey) | ||
| 255 | - c.context.setEngineKey(privateKeyIdentifier, privateKeyEngine); | ||
| 256 | - else | ||
| 257 | - throw new ERR_CRYPTO_CUSTOM_ENGINE_NOT_SUPPORTED(); | ||
| 258 | - } else if (typeof privateKeyIdentifier !== 'string') { | ||
| 259 | - throw new ERR_INVALID_ARG_TYPE('options.privateKeyIdentifier', | ||
| 260 | - ['string', 'undefined'], | ||
| 261 | - privateKeyIdentifier); | ||
| 262 | - } else { | ||
| 263 | - throw new ERR_INVALID_ARG_TYPE('options.privateKeyEngine', | ||
| 264 | - ['string', 'undefined'], | ||
| 265 | - privateKeyEngine); | ||
| 266 | - } | ||
| 267 | - } | ||
| 268 | - | ||
| 269 | - if (ciphers != null) | ||
| 270 | - validateString(ciphers, 'options.ciphers'); | ||
| 271 | - | ||
| 272 | - // Work around an OpenSSL API quirk. cipherList is for TLSv1.2 and below, | ||
| 273 | - // cipherSuites is for TLSv1.3 (and presumably any later versions). TLSv1.3 | ||
| 274 | - // cipher suites all have a standard name format beginning with TLS_, so split | ||
| 275 | - // the ciphers and pass them to the appropriate API. | ||
| 276 | - const { cipherList, cipherSuites } = processCiphers(ciphers); | ||
| 277 | - | ||
| 278 | - c.context.setCipherSuites(cipherSuites); | ||
| 279 | - c.context.setCiphers(cipherList); | ||
| 280 | - | ||
| 281 | - if (cipherSuites === '' && | ||
| 282 | - c.context.getMaxProto() > TLS1_2_VERSION && | ||
| 283 | - c.context.getMinProto() < TLS1_3_VERSION) { | ||
| 284 | - c.context.setMaxProto(TLS1_2_VERSION); | ||
| 285 | - } | ||
| 286 | - | ||
| 287 | - if (cipherList === '' && | ||
| 288 | - c.context.getMinProto() < TLS1_3_VERSION && | ||
| 289 | - c.context.getMaxProto() > TLS1_2_VERSION) { | ||
| 290 | - c.context.setMinProto(TLS1_3_VERSION); | ||
| 291 | - } | ||
| 292 | - | ||
| 293 | - validateString(ecdhCurve, 'options.ecdhCurve'); | ||
| 294 | - c.context.setECDHCurve(ecdhCurve); | ||
| 295 | - | ||
| 296 | - if (dhparam !== undefined) { | ||
| 297 | - validateKeyOrCertOption('dhparam', dhparam); | ||
| 298 | - const warning = c.context.setDHParam(dhparam); | ||
| 299 | - if (warning) | ||
| 300 | - process.emitWarning(warning, 'SecurityWarning'); | ||
| 301 | - } | ||
| 302 | - | ||
| 303 | - if (crl !== undefined) { | ||
| 304 | - if (ArrayIsArray(crl)) { | ||
| 305 | - for (const val of crl) { | ||
| 306 | - validateKeyOrCertOption('crl', val); | ||
| 307 | - c.context.addCRL(val); | ||
| 308 | - } | ||
| 309 | - } else { | ||
| 310 | - validateKeyOrCertOption('crl', crl); | ||
| 311 | - c.context.addCRL(crl); | ||
| 312 | - } | ||
| 313 | - } | ||
| 314 | - | ||
| 315 | - if (sessionIdContext !== undefined) { | ||
| 316 | - validateString(sessionIdContext, 'options.sessionIdContext'); | ||
| 317 | - c.context.setSessionIdContext(sessionIdContext); | ||
| 318 | - } | ||
| 319 | - | ||
| 320 | - if (pfx !== undefined) { | ||
| 321 | - if (ArrayIsArray(pfx)) { | ||
| 322 | - ArrayPrototypeForEach(pfx, (val) => { | ||
| 323 | - const raw = val.buf ? val.buf : val; | ||
| 324 | - const pass = val.passphrase || passphrase; | ||
| 325 | - if (pass !== undefined) { | ||
| 326 | - c.context.loadPKCS12(toBuf(raw), toBuf(pass)); | ||
| 327 | - } else { | ||
| 328 | - c.context.loadPKCS12(toBuf(raw)); | ||
| 329 | - } | ||
| 330 | - }); | ||
| 331 | - } else if (passphrase) { | ||
| 332 | - c.context.loadPKCS12(toBuf(pfx), toBuf(passphrase)); | ||
| 333 | - } else { | ||
| 334 | - c.context.loadPKCS12(toBuf(pfx)); | ||
| 335 | - } | ||
| 336 | - } | ||
| 337 | - | ||
| 338 | - // Do not keep read/write buffers in free list for OpenSSL < 1.1.0. (For | ||
| 339 | - // OpenSSL 1.1.0, buffers are malloced and freed without the use of a | ||
| 340 | - // freelist.) | ||
| 341 | - if (singleUse) { | ||
| 342 | - c.singleUse = true; | ||
| 343 | - c.context.setFreeListLength(0); | ||
| 344 | - } | ||
| 345 | - | ||
| 346 | - if (clientCertEngine !== undefined) { | ||
| 347 | - if (typeof c.context.setClientCertEngine !== 'function') | ||
| 348 | - throw new ERR_CRYPTO_CUSTOM_ENGINE_NOT_SUPPORTED(); | ||
| 349 | - if (typeof clientCertEngine !== 'string') { | ||
| 350 | - throw new ERR_INVALID_ARG_TYPE('options.clientCertEngine', | ||
| 351 | - ['string', 'null', 'undefined'], | ||
| 352 | - clientCertEngine); | ||
| 353 | - } | ||
| 354 | - c.context.setClientCertEngine(clientCertEngine); | ||
| 355 | - } | ||
| 356 | - | ||
| 357 | - if (ticketKeys !== undefined) { | ||
| 358 | - if (!isArrayBufferView(ticketKeys)) { | ||
| 359 | - throw new ERR_INVALID_ARG_TYPE( | ||
| 360 | - 'options.ticketKeys', | ||
| 361 | - ['Buffer', 'TypedArray', 'DataView'], | ||
| 362 | - ticketKeys); | ||
| 363 | - } | ||
| 364 | - if (ticketKeys.byteLength !== 48) { | ||
| 365 | - throw new ERR_INVALID_ARG_VALUE( | ||
| 366 | - 'options.ticketKeys', | ||
| 367 | - ticketKeys.byteLength, | ||
| 368 | - 'must be exactly 48 bytes'); | ||
| 369 | - } | ||
| 370 | - c.context.setTicketKeys(ticketKeys); | ||
| 371 | - } | ||
| 372 | - | ||
| 373 | - if (sessionTimeout !== undefined) { | ||
| 374 | - validateInt32(sessionTimeout, 'options.sessionTimeout'); | ||
| 375 | - c.context.setSessionTimeout(sessionTimeout); | ||
| 376 | - } | ||
| 113 | + configSecureContext(c.context, options); | ||
| 377 | 114 | ||
| 378 | 115 | return c; | |
| 379 | - }; | ||
| 116 | + } | ||
| 380 | 117 | ||
| 381 | 118 | // Translate some fields from the handle's C-friendly format into more idiomatic | |
| 382 | 119 | // javascript object representations before passing them back to the user. Can | |
| 383 | 120 | // be used on any cert object, but changing the name would be semver-major. | |
| 384 | - exports.translatePeerCertificate = function translatePeerCertificate(c) { | ||
| 121 | + function translatePeerCertificate(c) { | ||
| 385 | 122 | if (!c) | |
| 386 | 123 | return null; | |
| 387 | 124 | ||
@@ -404,4 +141,10 @@ exports.translatePeerCertificate = function translatePeerCertificate(c) { | |||
| 404 | 141 | }); | |
| 405 | 142 | } | |
| 406 | 143 | return c; | |
| 144 | + } | ||
| 145 | + | ||
| 146 | + module.exports = { | ||
| 147 | + SecureContext, | ||
| 148 | + createSecureContext, | ||
| 149 | + translatePeerCertificate, | ||
| 407 | 150 | }; | |
| Back | FazBrowse Home | New Git URL |
0 commit comments