1// Copyright Joyent, Inc. and other Node contributors. 2// 3// Permission is hereby granted, free of charge, to any person obtaining a 4// copy of this software and associated documentation files (the 5// "Software"), to deal in the Software without restriction, including 6// without limitation the rights to use, copy, modify, merge, publish, 7// distribute, sublicense, and/or sell copies of the Software, and to permit 8// persons to whom the Software is furnished to do so, subject to the 9// following conditions: 10// 11// The above copyright notice and this permission notice shall be included 12// in all copies or substantial portions of the Software. 13// 14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 17// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20// USE OR OTHER DEALINGS IN THE SOFTWARE. 21 22'use strict'; 23const common = require('../common'); 24 25if (!common.hasCrypto) 26 common.skip('missing crypto'); 27 28const assert = require('assert'); 29const util = require('util'); 30 31const tls = require('tls'); 32 33const tests = [ 34 // False-y values. 35 { 36 host: false, 37 cert: { subject: { CN: 'a.com' } }, 38 error: 'Host: false. is not cert\'s CN: a.com' 39 }, 40 { 41 host: null, 42 cert: { subject: { CN: 'a.com' } }, 43 error: 'Host: null. is not cert\'s CN: a.com' 44 }, 45 { 46 host: undefined, 47 cert: { subject: { CN: 'a.com' } }, 48 error: 'Host: undefined. is not cert\'s CN: a.com' 49 }, 50 51 // Basic CN handling 52 { host: 'a.com', cert: { subject: { CN: 'a.com' } } }, 53 { host: 'a.com', cert: { subject: { CN: 'A.COM' } } }, 54 { 55 host: 'a.com', 56 cert: { subject: { CN: 'b.com' } }, 57 error: 'Host: a.com. is not cert\'s CN: b.com' 58 }, 59 { host: 'a.com', cert: { subject: { CN: 'a.com.' } } }, 60 { 61 host: 'a.com', 62 cert: { subject: { CN: '.a.com' } }, 63 error: 'Host: a.com. is not cert\'s CN: .a.com' 64 }, 65 66 // IP address in CN. Technically allowed but so rare that we reject 67 // it anyway. If we ever do start allowing them, we should take care 68 // to only allow public (non-internal, non-reserved) IP addresses, 69 // because that's what the spec mandates. 70 { 71 host: '8.8.8.8', 72 cert: { subject: { CN: '8.8.8.8' } }, 73 error: 'IP: 8.8.8.8 is not in the cert\'s list: ' 74 }, 75 76 // The spec suggests that a "DNS:" Subject Alternative Name containing an 77 // IP address is valid but it seems so suspect that we currently reject it. 78 { 79 host: '8.8.8.8', 80 cert: { subject: { CN: '8.8.8.8' }, subjectaltname: 'DNS:8.8.8.8' }, 81 error: 'IP: 8.8.8.8 is not in the cert\'s list: ' 82 }, 83 84 // Likewise for "URI:" Subject Alternative Names. 85 // See also https://github.com/nodejs/node/issues/8108. 86 { 87 host: '8.8.8.8', 88 cert: { subject: { CN: '8.8.8.8' }, subjectaltname: 'URI:http://8.8.8.8/' }, 89 error: 'IP: 8.8.8.8 is not in the cert\'s list: ' 90 }, 91 92 // An "IP Address:" Subject Alternative Name however is acceptable. 93 { 94 host: '8.8.8.8', 95 cert: { subject: { CN: '8.8.8.8' }, subjectaltname: 'IP Address:8.8.8.8' } 96 }, 97 98 // But not when it's a CIDR. 99 { 100 host: '8.8.8.8', 101 cert: { 102 subject: { CN: '8.8.8.8' }, 103 subjectaltname: 'IP Address:8.8.8.0/24' 104 }, 105 error: 'IP: 8.8.8.8 is not in the cert\'s list: ' 106 }, 107 108 // Wildcards in CN 109 { host: 'b.a.com', cert: { subject: { CN: '*.a.com' } } }, 110 { 111 host: 'ba.com', 112 cert: { subject: { CN: '*.a.com' } }, 113 error: 'Host: ba.com. is not cert\'s CN: *.a.com' 114 }, 115 { 116 host: '\n.b.com', 117 cert: { subject: { CN: '*n.b.com' } }, 118 error: 'Host: \n.b.com. is not cert\'s CN: *n.b.com' 119 }, 120 { host: 'b.a.com', 121 cert: { 122 subjectaltname: 'DNS:omg.com', 123 subject: { CN: '*.a.com' }, 124 }, 125 error: 'Host: b.a.com. is not in the cert\'s altnames: ' + 126 'DNS:omg.com' }, 127 { 128 host: 'b.a.com', 129 cert: { subject: { CN: 'b*b.a.com' } }, 130 error: 'Host: b.a.com. is not cert\'s CN: b*b.a.com' 131 }, 132 133 // Empty Cert 134 { 135 host: 'a.com', 136 cert: { }, 137 error: 'Cert does not contain a DNS name' 138 }, 139 140 // Empty Subject w/DNS name 141 { 142 host: 'a.com', cert: { 143 subjectaltname: 'DNS:a.com', 144 } 145 }, 146 147 // Empty Subject w/URI name 148 { 149 host: 'a.b.a.com', cert: { 150 subjectaltname: 'URI:http://a.b.a.com/', 151 }, 152 error: 'Cert does not contain a DNS name' 153 }, 154 155 // Multiple CN fields 156 { 157 host: 'foo.com', cert: { 158 subject: { CN: ['foo.com', 'bar.com'] } // CN=foo.com; CN=bar.com; 159 } 160 }, 161 162 // DNS names and CN 163 { 164 host: 'a.com', cert: { 165 subjectaltname: 'DNS:*', 166 subject: { CN: 'b.com' } 167 }, 168 error: 'Host: a.com. is not in the cert\'s altnames: ' + 169 'DNS:*' 170 }, 171 { 172 host: 'a.com', cert: { 173 subjectaltname: 'DNS:*.com', 174 subject: { CN: 'b.com' } 175 }, 176 error: 'Host: a.com. is not in the cert\'s altnames: ' + 177 'DNS:*.com' 178 }, 179 { 180 host: 'a.co.uk', cert: { 181 subjectaltname: 'DNS:*.co.uk', 182 subject: { CN: 'b.com' } 183 } 184 }, 185 { 186 host: 'a.com', cert: { 187 subjectaltname: 'DNS:*.a.com', 188 subject: { CN: 'a.com' } 189 }, 190 error: 'Host: a.com. is not in the cert\'s altnames: ' + 191 'DNS:*.a.com' 192 }, 193 { 194 host: 'a.com', cert: { 195 subjectaltname: 'DNS:*.a.com', 196 subject: { CN: 'b.com' } 197 }, 198 error: 'Host: a.com. is not in the cert\'s altnames: ' + 199 'DNS:*.a.com' 200 }, 201 { 202 host: 'a.com', cert: { 203 subjectaltname: 'DNS:a.com', 204 subject: { CN: 'b.com' } 205 } 206 }, 207 { 208 host: 'a.com', cert: { 209 subjectaltname: 'DNS:A.COM', 210 subject: { CN: 'b.com' } 211 } 212 }, 213 214 // DNS names 215 { 216 host: 'a.com', cert: { 217 subjectaltname: 'DNS:*.a.com', 218 subject: {} 219 }, 220 error: 'Host: a.com. is not in the cert\'s altnames: ' + 221 'DNS:*.a.com' 222 }, 223 { 224 host: 'b.a.com', cert: { 225 subjectaltname: 'DNS:*.a.com', 226 subject: {} 227 } 228 }, 229 { 230 host: 'c.b.a.com', cert: { 231 subjectaltname: 'DNS:*.a.com', 232 subject: {} 233 }, 234 error: 'Host: c.b.a.com. is not in the cert\'s altnames: ' + 235 'DNS:*.a.com' 236 }, 237 { 238 host: 'b.a.com', cert: { 239 subjectaltname: 'DNS:*b.a.com', 240 subject: {} 241 } 242 }, 243 { 244 host: 'a-cb.a.com', cert: { 245 subjectaltname: 'DNS:*b.a.com', 246 subject: {} 247 } 248 }, 249 { 250 host: 'a.b.a.com', cert: { 251 subjectaltname: 'DNS:*b.a.com', 252 subject: {} 253 }, 254 error: 'Host: a.b.a.com. is not in the cert\'s altnames: ' + 255 'DNS:*b.a.com' 256 }, 257 // Multiple DNS names 258 { 259 host: 'a.b.a.com', cert: { 260 subjectaltname: 'DNS:*b.a.com, DNS:a.b.a.com', 261 subject: {} 262 } 263 }, 264 // URI names 265 { 266 host: 'a.b.a.com', cert: { 267 subjectaltname: 'URI:http://a.b.a.com/', 268 subject: {} 269 }, 270 error: 'Cert does not contain a DNS name' 271 }, 272 { 273 host: 'a.b.a.com', cert: { 274 subjectaltname: 'URI:http://*.b.a.com/', 275 subject: {} 276 }, 277 error: 'Cert does not contain a DNS name' 278 }, 279 // IP addresses 280 { 281 host: 'a.b.a.com', cert: { 282 subjectaltname: 'IP Address:127.0.0.1', 283 subject: {} 284 }, 285 error: 'Cert does not contain a DNS name' 286 }, 287 { 288 host: '127.0.0.1', cert: { 289 subjectaltname: 'IP Address:127.0.0.1', 290 subject: {} 291 } 292 }, 293 { 294 host: '127.0.0.2', cert: { 295 subjectaltname: 'IP Address:127.0.0.1', 296 subject: {} 297 }, 298 error: 'IP: 127.0.0.2 is not in the cert\'s list: ' + 299 '127.0.0.1' 300 }, 301 { 302 host: '127.0.0.1', cert: { 303 subjectaltname: 'DNS:a.com', 304 subject: {} 305 }, 306 error: 'IP: 127.0.0.1 is not in the cert\'s list: ' 307 }, 308 { 309 host: 'localhost', cert: { 310 subjectaltname: 'DNS:a.com', 311 subject: { CN: 'localhost' } 312 }, 313 error: 'Host: localhost. is not in the cert\'s altnames: ' + 314 'DNS:a.com' 315 }, 316 // IDNA 317 { 318 host: 'xn--bcher-kva.example.com', 319 cert: { subject: { CN: '*.example.com' } }, 320 }, 321 // RFC 6125, section 6.4.3: "[...] the client SHOULD NOT attempt to match 322 // a presented identifier where the wildcard character is embedded within 323 // an A-label [...]" 324 { 325 host: 'xn--bcher-kva.example.com', 326 cert: { subject: { CN: 'xn--*.example.com' } }, 327 error: 'Host: xn--bcher-kva.example.com. is not cert\'s CN: ' + 328 'xn--*.example.com', 329 }, 330]; 331 332tests.forEach(function(test, i) { 333 const err = tls.checkServerIdentity(test.host, test.cert); 334 assert.strictEqual(err && err.reason, 335 test.error, 336 `Test# ${i} failed: ${util.inspect(test)} \n` + 337 `${test.error} != ${(err && err.reason)}`); 338}); 339