1'use strict'; 2 3const common = require('../common'); 4const fixtures = require('../common/fixtures'); 5 6const { 7 assert, connect, keys, tls 8} = require(fixtures.path('tls-connect')); 9 10// Use ec10 and agent10, they are the only identities with intermediate CAs. 11const client = keys.ec10; 12const server = keys.agent10; 13 14// The certificates aren't for "localhost", so override the identity check. 15function checkServerIdentity(hostname, cert) { 16 assert.strictEqual(hostname, 'localhost'); 17 assert.strictEqual(cert.subject.CN, 'agent10.example.com'); 18} 19 20// Split out the single end-entity cert and the subordinate CA for later use. 21split(client.cert, client); 22split(server.cert, server); 23 24function split(file, into) { 25 const certs = /([^]*END CERTIFICATE-----\r?\n)(-----BEGIN[^]*)/.exec(file); 26 assert.strictEqual(certs.length, 3); 27 into.single = certs[1]; 28 into.subca = certs[2]; 29} 30 31// Typical setup, nothing special, complete cert chains sent to peer. 32connect({ 33 client: { 34 key: client.key, 35 cert: client.cert, 36 ca: server.ca, 37 checkServerIdentity, 38 }, 39 server: { 40 key: server.key, 41 cert: server.cert, 42 ca: client.ca, 43 requestCert: true, 44 }, 45}, function(err, pair, cleanup) { 46 assert.ifError(err); 47 return cleanup(); 48}); 49 50// As above, but without requesting client's cert. 51connect({ 52 client: { 53 ca: server.ca, 54 checkServerIdentity, 55 }, 56 server: { 57 key: server.key, 58 cert: server.cert, 59 ca: client.ca, 60 }, 61}, function(err, pair, cleanup) { 62 assert.ifError(err); 63 return cleanup(); 64}); 65 66// Request cert from TLS1.2 client that doesn't have one. 67connect({ 68 client: { 69 maxVersion: 'TLSv1.2', 70 ca: server.ca, 71 checkServerIdentity, 72 }, 73 server: { 74 key: server.key, 75 cert: server.cert, 76 ca: client.ca, 77 requestCert: true, 78 }, 79}, function(err, pair, cleanup) { 80 assert.strictEqual(pair.server.err.code, 81 'ERR_SSL_PEER_DID_NOT_RETURN_A_CERTIFICATE'); 82 assert.strictEqual(pair.client.err.code, 'ECONNRESET'); 83 return cleanup(); 84}); 85 86// Request cert from TLS1.3 client that doesn't have one. 87if (tls.DEFAULT_MAX_VERSION === 'TLSv1.3') connect({ 88 client: { 89 ca: server.ca, 90 checkServerIdentity, 91 }, 92 server: { 93 key: server.key, 94 cert: server.cert, 95 ca: client.ca, 96 requestCert: true, 97 }, 98}, function(err, pair, cleanup) { 99 assert.strictEqual(pair.server.err.code, 100 'ERR_SSL_PEER_DID_NOT_RETURN_A_CERTIFICATE'); 101 102 // TLS1.3 client completes handshake before server, and its only after the 103 // server handshakes, requests certs, gets back a zero-length list of certs, 104 // and sends a fatal Alert to the client that the client discovers there has 105 // been a fatal error. 106 pair.client.conn.once('error', common.mustCall((err) => { 107 assert.strictEqual(err.code, 'ERR_SSL_TLSV13_ALERT_CERTIFICATE_REQUIRED'); 108 cleanup(); 109 })); 110}); 111 112// Typical configuration error, incomplete cert chains sent, we have to know the 113// peer's subordinate CAs in order to verify the peer. 114connect({ 115 client: { 116 key: client.key, 117 cert: client.single, 118 ca: [server.ca, server.subca], 119 checkServerIdentity, 120 }, 121 server: { 122 key: server.key, 123 cert: server.single, 124 ca: [client.ca, client.subca], 125 requestCert: true, 126 }, 127}, function(err, pair, cleanup) { 128 assert.ifError(err); 129 return cleanup(); 130}); 131 132// Like above, but provide root CA and subordinate CA as multi-PEM. 133connect({ 134 client: { 135 key: client.key, 136 cert: client.single, 137 ca: server.ca + '\n' + server.subca, 138 checkServerIdentity, 139 }, 140 server: { 141 key: server.key, 142 cert: server.single, 143 ca: client.ca + '\n' + client.subca, 144 requestCert: true, 145 }, 146}, function(err, pair, cleanup) { 147 assert.ifError(err); 148 return cleanup(); 149}); 150 151// Like above, but provide multi-PEM in an array. 152connect({ 153 client: { 154 key: client.key, 155 cert: client.single, 156 ca: [server.ca + '\n' + server.subca], 157 checkServerIdentity, 158 }, 159 server: { 160 key: server.key, 161 cert: server.single, 162 ca: [client.ca + '\n' + client.subca], 163 requestCert: true, 164 }, 165}, function(err, pair, cleanup) { 166 assert.ifError(err); 167 return cleanup(); 168}); 169 170// Fail to complete server's chain 171connect({ 172 client: { 173 ca: server.ca, 174 checkServerIdentity, 175 }, 176 server: { 177 key: server.key, 178 cert: server.single, 179 }, 180}, function(err, pair, cleanup) { 181 assert.strictEqual(err.code, 'UNABLE_TO_VERIFY_LEAF_SIGNATURE'); 182 return cleanup(); 183}); 184 185// Fail to complete client's chain. 186connect({ 187 client: { 188 key: client.key, 189 cert: client.single, 190 ca: server.ca, 191 checkServerIdentity, 192 }, 193 server: { 194 key: server.key, 195 cert: server.cert, 196 ca: client.ca, 197 requestCert: true, 198 }, 199}, function(err, pair, cleanup) { 200 assert.ifError(pair.client.error); 201 assert.ifError(pair.server.error); 202 assert.strictEqual(err.code, 'ECONNRESET'); 203 return cleanup(); 204}); 205 206// Fail to find CA for server. 207connect({ 208 client: { 209 checkServerIdentity, 210 }, 211 server: { 212 key: server.key, 213 cert: server.cert, 214 }, 215}, function(err, pair, cleanup) { 216 assert.strictEqual(err.code, 'UNABLE_TO_GET_ISSUER_CERT_LOCALLY'); 217 return cleanup(); 218}); 219 220// Server sent their CA, but CA cannot be trusted if it is not locally known. 221connect({ 222 client: { 223 checkServerIdentity, 224 }, 225 server: { 226 key: server.key, 227 cert: server.cert + '\n' + server.ca, 228 }, 229}, function(err, pair, cleanup) { 230 assert.strictEqual(err.code, 'SELF_SIGNED_CERT_IN_CHAIN'); 231 return cleanup(); 232}); 233 234// Server sent their CA, wrongly, but its OK since we know the CA locally. 235connect({ 236 client: { 237 checkServerIdentity, 238 ca: server.ca, 239 }, 240 server: { 241 key: server.key, 242 cert: server.cert + '\n' + server.ca, 243 }, 244}, function(err, pair, cleanup) { 245 assert.ifError(err); 246 return cleanup(); 247}); 248 249// Fail to complete client's chain. 250connect({ 251 client: { 252 key: client.key, 253 cert: client.single, 254 ca: server.ca, 255 checkServerIdentity, 256 }, 257 server: { 258 key: server.key, 259 cert: server.cert, 260 ca: client.ca, 261 requestCert: true, 262 }, 263}, function(err, pair, cleanup) { 264 assert.strictEqual(err.code, 'ECONNRESET'); 265 return cleanup(); 266}); 267 268// Fail to find CA for client. 269connect({ 270 client: { 271 key: client.key, 272 cert: client.cert, 273 ca: server.ca, 274 checkServerIdentity, 275 }, 276 server: { 277 key: server.key, 278 cert: server.cert, 279 requestCert: true, 280 }, 281}, function(err, pair, cleanup) { 282 assert.strictEqual(err.code, 'ECONNRESET'); 283 return cleanup(); 284}); 285 286// Confirm support for "BEGIN TRUSTED CERTIFICATE". 287connect({ 288 client: { 289 key: client.key, 290 cert: client.cert, 291 ca: server.ca.replace(/CERTIFICATE/g, 'TRUSTED CERTIFICATE'), 292 checkServerIdentity, 293 }, 294 server: { 295 key: server.key, 296 cert: server.cert, 297 ca: client.ca, 298 requestCert: true, 299 }, 300}, function(err, pair, cleanup) { 301 assert.ifError(err); 302 return cleanup(); 303}); 304 305// Confirm support for "BEGIN TRUSTED CERTIFICATE". 306connect({ 307 client: { 308 key: client.key, 309 cert: client.cert, 310 ca: server.ca, 311 checkServerIdentity, 312 }, 313 server: { 314 key: server.key, 315 cert: server.cert, 316 ca: client.ca.replace(/CERTIFICATE/g, 'TRUSTED CERTIFICATE'), 317 requestCert: true, 318 }, 319}, function(err, pair, cleanup) { 320 assert.ifError(err); 321 return cleanup(); 322}); 323 324// Confirm support for "BEGIN X509 CERTIFICATE". 325connect({ 326 client: { 327 key: client.key, 328 cert: client.cert, 329 ca: server.ca.replace(/CERTIFICATE/g, 'X509 CERTIFICATE'), 330 checkServerIdentity, 331 }, 332 server: { 333 key: server.key, 334 cert: server.cert, 335 ca: client.ca, 336 requestCert: true, 337 }, 338}, function(err, pair, cleanup) { 339 assert.ifError(err); 340 return cleanup(); 341}); 342 343// Confirm support for "BEGIN X509 CERTIFICATE". 344connect({ 345 client: { 346 key: client.key, 347 cert: client.cert, 348 ca: server.ca, 349 checkServerIdentity, 350 }, 351 server: { 352 key: server.key, 353 cert: server.cert, 354 ca: client.ca.replace(/CERTIFICATE/g, 'X509 CERTIFICATE'), 355 requestCert: true, 356 }, 357}, function(err, pair, cleanup) { 358 assert.ifError(err); 359 return cleanup(); 360}); 361