| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1533,6 +1533,20 @@ When running as the server, the socket will be destroyed with an error after | |||
| 1533 | 1533 | For TLSv1.3, renegotiation cannot be initiated, it is not supported by the | |
| 1534 | 1534 | protocol. | |
| 1535 | 1535 | ||
| 1536 | + ### `tlsSocket.setKeyCert(context)` | ||
| 1537 | + | ||
| 1538 | + <!-- YAML | ||
| 1539 | + added: REPLACEME | ||
| 1540 | + --> | ||
| 1541 | + | ||
| 1542 | + * `context` {Object|tls.SecureContext} An object containing at least `key` and | ||
| 1543 | + `cert` properties from the [`tls.createSecureContext()`][] `options`, or a | ||
| 1544 | + TLS context object created with [`tls.createSecureContext()`][] itself. | ||
| 1545 | + | ||
| 1546 | + The `tlsSocket.setKeyCert()` method sets the private key and certificate to use | ||
| 1547 | + for the socket. This is mainly useful if you wish to select a server certificate | ||
| 1548 | + from a TLS server's `ALPNCallback`. | ||
| 1549 | + | ||
| 1536 | 1550 | ### `tlsSocket.setMaxSendFragment(size)` | |
| 1537 | 1551 | ||
| 1538 | 1552 | <!-- YAML | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1151,6 +1151,17 @@ TLSSocket.prototype.getX509Certificate = function() { | |||
| 1151 | 1151 | return cert ? new InternalX509Certificate(cert) : undefined; | |
| 1152 | 1152 | }; | |
| 1153 | 1153 | ||
| 1154 | + TLSSocket.prototype.setKeyCert = function(context) { | ||
| 1155 | + if (this._handle) { | ||
| 1156 | + let secureContext; | ||
| 1157 | + if (context instanceof common.SecureContext) | ||
| 1158 | + secureContext = context; | ||
| 1159 | + else | ||
| 1160 | + secureContext = tls.createSecureContext(context); | ||
| 1161 | + this._handle.setKeyCert(secureContext.context); | ||
| 1162 | + } | ||
| 1163 | + }; | ||
| 1164 | + | ||
| 1154 | 1165 | // Proxy TLSSocket handle methods | |
| 1155 | 1166 | function makeSocketMethodProxy(name) { | |
| 1156 | 1167 | return function socketMethodProxy(...args) { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1595,6 +1595,33 @@ void TLSWrap::SetALPNProtocols(const FunctionCallbackInfo<Value>& args) { | |||
| 1595 | 1595 | } | |
| 1596 | 1596 | } | |
| 1597 | 1597 | ||
| 1598 | + void TLSWrap::SetKeyCert(const FunctionCallbackInfo<Value>& args) { | ||
| 1599 | + TLSWrap* w; | ||
| 1600 | + ASSIGN_OR_RETURN_UNWRAP(&w, args.This()); | ||
| 1601 | + Environment* env = w->env(); | ||
| 1602 | + | ||
| 1603 | + if (w->is_client()) return; | ||
| 1604 | + | ||
| 1605 | + if (args.Length() < 1 || !args[0]->IsObject()) | ||
| 1606 | + return env->ThrowTypeError("Must give a SecureContext as first argument"); | ||
| 1607 | + | ||
| 1608 | + Local<Value> ctx = args[0]; | ||
| 1609 | + if (UNLIKELY(ctx.IsEmpty())) return; | ||
| 1610 | + | ||
| 1611 | + Local<FunctionTemplate> cons = env->secure_context_constructor_template(); | ||
| 1612 | + if (cons->HasInstance(ctx)) { | ||
| 1613 | + SecureContext* sc = Unwrap<SecureContext>(ctx.As<Object>()); | ||
| 1614 | + CHECK_NOT_NULL(sc); | ||
| 1615 | + if (!UseSNIContext(w->ssl_, BaseObjectPtr<SecureContext>(sc)) || | ||
| 1616 | + !w->SetCACerts(sc)) { | ||
| 1617 | + unsigned long err = ERR_get_error(); // NOLINT(runtime/int) | ||
| 1618 | + return ThrowCryptoError(env, err, "SetKeyCert"); | ||
| 1619 | + } | ||
| 1620 | + } else { | ||
| 1621 | + return env->ThrowTypeError("Must give a SecureContext as first argument"); | ||
| 1622 | + } | ||
| 1623 | + } | ||
| 1624 | + | ||
| 1598 | 1625 | void TLSWrap::GetPeerCertificate(const FunctionCallbackInfo<Value>& args) { | |
| 1599 | 1626 | TLSWrap* w; | |
| 1600 | 1627 | ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder()); | |
@@ -2130,6 +2157,7 @@ void TLSWrap::Initialize( | |||
| 2130 | 2157 | SetProtoMethod(isolate, t, "renegotiate", Renegotiate); | |
| 2131 | 2158 | SetProtoMethod(isolate, t, "requestOCSP", RequestOCSP); | |
| 2132 | 2159 | SetProtoMethod(isolate, t, "setALPNProtocols", SetALPNProtocols); | |
| 2160 | + SetProtoMethod(isolate, t, "setKeyCert", SetKeyCert); | ||
| 2133 | 2161 | SetProtoMethod(isolate, t, "setOCSPResponse", SetOCSPResponse); | |
| 2134 | 2162 | SetProtoMethod(isolate, t, "setServername", SetServername); | |
| 2135 | 2163 | SetProtoMethod(isolate, t, "setSession", SetSession); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -213,6 +213,7 @@ class TLSWrap : public AsyncWrap, | |||
| 213 | 213 | static void Renegotiate(const v8::FunctionCallbackInfo<v8::Value>& args); | |
| 214 | 214 | static void RequestOCSP(const v8::FunctionCallbackInfo<v8::Value>& args); | |
| 215 | 215 | static void SetALPNProtocols(const v8::FunctionCallbackInfo<v8::Value>& args); | |
| 216 | + static void SetKeyCert(const v8::FunctionCallbackInfo<v8::Value>& args); | ||
| 216 | 217 | static void SetOCSPResponse(const v8::FunctionCallbackInfo<v8::Value>& args); | |
| 217 | 218 | static void SetServername(const v8::FunctionCallbackInfo<v8::Value>& args); | |
| 218 | 219 | static void SetSession(const v8::FunctionCallbackInfo<v8::Value>& args); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,56 @@ | |||
| 1 | + 'use strict'; | ||
| 2 | + const common = require('../common'); | ||
| 3 | + | ||
| 4 | + if (!common.hasCrypto) | ||
| 5 | + common.skip('missing crypto'); | ||
| 6 | + | ||
| 7 | + const assert = require('assert'); | ||
| 8 | + const { X509Certificate } = require('crypto'); | ||
| 9 | + const tls = require('tls'); | ||
| 10 | + const fixtures = require('../common/fixtures'); | ||
| 11 | + | ||
| 12 | + const altKeyCert = { | ||
| 13 | + key: fixtures.readKey('agent2-key.pem'), | ||
| 14 | + cert: fixtures.readKey('agent2-cert.pem'), | ||
| 15 | + minVersion: 'TLSv1.2', | ||
| 16 | + }; | ||
| 17 | + | ||
| 18 | + const altKeyCertVals = [ | ||
| 19 | + altKeyCert, | ||
| 20 | + tls.createSecureContext(altKeyCert), | ||
| 21 | + ]; | ||
| 22 | + | ||
| 23 | + (function next() { | ||
| 24 | + if (!altKeyCertVals.length) | ||
| 25 | + return; | ||
| 26 | + const altKeyCertVal = altKeyCertVals.shift(); | ||
| 27 | + const options = { | ||
| 28 | + key: fixtures.readKey('agent1-key.pem'), | ||
| 29 | + cert: fixtures.readKey('agent1-cert.pem'), | ||
| 30 | + minVersion: 'TLSv1.3', | ||
| 31 | + ALPNCallback: common.mustCall(function({ servername, protocols }) { | ||
| 32 | + this.setKeyCert(altKeyCertVal); | ||
| 33 | + assert.deepStrictEqual(protocols, ['acme-tls/1']); | ||
| 34 | + return protocols[0]; | ||
| 35 | + }), | ||
| 36 | + }; | ||
| 37 | + | ||
| 38 | + tls.createServer(options, (s) => s.end()).listen(0, function() { | ||
| 39 | + this.on('connection', common.mustCall((socket) => this.close())); | ||
| 40 | + | ||
| 41 | + tls.connect({ | ||
| 42 | + port: this.address().port, | ||
| 43 | + rejectUnauthorized: false, | ||
| 44 | + ALPNProtocols: ['acme-tls/1'], | ||
| 45 | + }, common.mustCall(function() { | ||
| 46 | + assert.strictEqual(this.getProtocol(), 'TLSv1.3'); | ||
| 47 | + const altCert = new X509Certificate(altKeyCert.cert); | ||
| 48 | + assert.strictEqual( | ||
| 49 | + this.getPeerX509Certificate().raw.equals(altCert.raw), | ||
| 50 | + true | ||
| 51 | + ); | ||
| 52 | + this.end(); | ||
| 53 | + next(); | ||
| 54 | + })); | ||
| 55 | + }); | ||
| 56 | + })(); | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments