3 const net = require('net');
4 const url = require('url');
5 const binding = process.binding('crypto');
6 const Buffer = require('buffer').Buffer;
7 const constants = require('constants');
9 // Allow {CLIENT_RENEG_LIMIT} client-initiated session renegotiations
10 // every {CLIENT_RENEG_WINDOW} seconds. An error event is emitted if more
11 // renegotations are seen. The settings are applied to all remote client
13 exports.CLIENT_RENEG_LIMIT = 3;
14 exports.CLIENT_RENEG_WINDOW = 600;
16 exports.SLAB_BUFFER_SIZE = 10 * 1024 * 1024;
18 exports.DEFAULT_CIPHERS = constants.defaultCipherList;
20 exports.DEFAULT_ECDH_CURVE = 'prime256v1';
22 exports.getCiphers = function() {
23 const names = binding.getSSLCiphers();
24 // Drop all-caps names in favor of their lowercase aliases,
26 names.forEach(function(name) {
27 if (/^[0-9A-Z\-]+$/.test(name)) name = name.toLowerCase();
30 return Object.getOwnPropertyNames(ctx).sort();
33 // Convert protocols array into valid OpenSSL protocols list
34 // ("\x06spdy/2\x08http/1.1\x08http/1.0")
35 exports.convertNPNProtocols = function convertNPNProtocols(NPNProtocols, out) {
36 // If NPNProtocols is Array - translate it into buffer
37 if (Array.isArray(NPNProtocols)) {
38 var buff = new Buffer(NPNProtocols.reduce(function(p, c) {
39 return p + 1 + Buffer.byteLength(c);
42 NPNProtocols.reduce(function(offset, c) {
43 var clen = Buffer.byteLength(c);
45 buff.write(c, offset + 1);
47 return offset + 1 + clen;
53 // If it's already a Buffer - store it
54 if (NPNProtocols instanceof Buffer) {
55 out.NPNProtocols = NPNProtocols;
59 exports.checkServerIdentity = function checkServerIdentity(host, cert) {
60 // Create regexp to much hostnames
61 function regexpify(host, wildcards) {
62 // Add trailing dot (make hostnames uniform)
63 if (!/\.$/.test(host)) host += '.';
65 // The same applies to hostname with more than one wildcard,
66 // if hostname has wildcard when wildcards are not allowed,
67 // or if there are less than two dots after wildcard (i.e. *.com or *d.com)
71 // "The client SHOULD NOT attempt to match a presented identifier in
72 // which the wildcard character comprises a label other than the
73 // left-most label (e.g., do not match bar.*.example.net)."
75 if (!wildcards && /\*/.test(host) || /[\.\*].*\*/.test(host) ||
76 /\*/.test(host) && !/\*.*\..+\..+/.test(host)) {
80 // Replace wildcard chars with regexp's wildcard and
81 // escape all characters that have special meaning in regexps
82 // (i.e. '.', '[', '{', '*', and others)
83 var re = host.replace(
84 /\*([a-z0-9\\-_\.])|[\.,\-\\\^\$+?*\[\]\(\):!\|{}]/g,
86 if (sub) return '[a-z0-9\\-_]*' + (sub === '-' ? '\\-' : sub);
90 return new RegExp('^' + re + '$', 'i');
98 reason = 'Unknown reason';
100 // There're several names to perform check against:
101 // CN and altnames in certificate extension
102 // (DNS names, IP addresses, and URIs)
104 // Walk through altnames and generate lists of those names
105 if (cert.subjectaltname) {
106 cert.subjectaltname.split(/, /g).forEach(function(altname) {
107 var option = altname.match(/^(DNS|IP Address|URI):(.*)$/);
110 if (option[1] === 'DNS') {
111 dnsNames.push(option[2]);
112 } else if (option[1] === 'IP Address') {
114 } else if (option[1] === 'URI') {
115 var uri = url.parse(option[2]);
116 if (uri) uriNames.push(uri.hostname);
121 // If hostname is an IP address, it should be present in the list of IP
123 if (net.isIP(host)) {
124 valid = ips.some(function(ip) {
128 reason = `IP: ${host} is not in the cert's list: ${ips.join(', ')}`;
130 } else if (cert.subject) {
131 // Transform hostname to canonical form
132 if (!/\.$/.test(host)) host += '.';
134 // Otherwise check all DNS/URI records from certificate
135 // (with allowed wildcards)
136 dnsNames = dnsNames.map(function(name) {
137 return regexpify(name, true);
140 // Wildcards ain't allowed in URI names
141 uriNames = uriNames.map(function(name) {
142 return regexpify(name, false);
145 dnsNames = dnsNames.concat(uriNames);
147 if (dnsNames.length > 0) matchCN = false;
149 // Match against Common Name (CN) only if no supported identifiers are
152 // "As noted, a client MUST NOT seek a match for a reference identifier
153 // of CN-ID if the presented identifiers include a DNS-ID, SRV-ID,
154 // URI-ID, or any application-specific identifier types supported by the
158 var commonNames = cert.subject.CN;
159 if (Array.isArray(commonNames)) {
160 for (var i = 0, k = commonNames.length; i < k; ++i) {
161 dnsNames.push(regexpify(commonNames[i], true));
164 dnsNames.push(regexpify(commonNames, true));
168 valid = dnsNames.some(function(re) {
169 return re.test(host);
173 if (cert.subjectaltname) {
175 `Host: ${host} is not in the cert's altnames: ` +
176 `${cert.subjectaltname}`;
178 reason = `Host: ${host} is not cert's CN: ${cert.subject.CN}`;
182 reason = 'Cert is empty';
187 `Hostname/IP doesn't match certificate's altnames: "${reason}"`);
196 // C=US\nST=CA\nL=SF\nO=Joyent\nOU=Node.js\nCN=ca1\nemailAddress=ry@clouds.org
197 exports.parseCertString = function parseCertString(s) {
199 var parts = s.split('\n');
200 for (var i = 0, len = parts.length; i < len; i++) {
201 var sepIndex = parts[i].indexOf('=');
203 var key = parts[i].slice(0, sepIndex);
204 var value = parts[i].slice(sepIndex + 1);
206 if (!Array.isArray(out[key])) {
207 out[key] = [out[key]];
209 out[key].push(value);
219 exports.createSecureContext = require('_tls_common').createSecureContext;
220 exports.SecureContext = require('_tls_common').SecureContext;
221 exports.TLSSocket = require('_tls_wrap').TLSSocket;
222 exports.Server = require('_tls_wrap').Server;
223 exports.createServer = require('_tls_wrap').createServer;
224 exports.connect = require('_tls_wrap').connect;
225 exports.createSecurePair = require('_tls_legacy').createSecurePair;