OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "net/cert/internal/name_constraints.h" |
| 6 |
| 7 #include "base/strings/string_util.h" |
| 8 #include "net/cert/internal/verify_name_match.h" |
| 9 #include "net/der/input.h" |
| 10 #include "net/der/parser.h" |
| 11 #include "net/der/tag.h" |
| 12 |
| 13 namespace net { |
| 14 |
| 15 namespace { |
| 16 |
| 17 // The name types of GeneralName that are fully supported in name constraints. |
| 18 // |
| 19 // (The other types will have the minimal checking described by RFC 5280 |
| 20 // section 4.2.1.10: If a name constraints extension that is marked as critical |
| 21 // imposes constraints on a particular name form, and an instance of |
| 22 // that name form appears in the subject field or subjectAltName |
| 23 // extension of a subsequent certificate, then the application MUST |
| 24 // either process the constraint or reject the certificate.) |
| 25 const int kSupportedNameTypes = GENERAL_NAME_DNS_NAME | |
| 26 GENERAL_NAME_DIRECTORY_NAME | |
| 27 GENERAL_NAME_IP_ADDRESS; |
| 28 |
| 29 // Controls wildcard handling of DNSNameMatches. |
| 30 // If WildcardMatchType is WILDCARD_PARTIAL_MATCH "*.bar.com" is considered to |
| 31 // match the constraint "foo.bar.com". If it is WILDCARD_FULL_MATCH, "*.bar.com" |
| 32 // will match "bar.com" but not "foo.bar.com". |
| 33 enum WildcardMatchType { WILDCARD_PARTIAL_MATCH, WILDCARD_FULL_MATCH }; |
| 34 |
| 35 // Returns true if |name| falls in the subtree defined by |dns_constraint|. |
| 36 // RFC 5280 section 4.2.1.10: |
| 37 // DNS name restrictions are expressed as host.example.com. Any DNS |
| 38 // name that can be constructed by simply adding zero or more labels |
| 39 // to the left-hand side of the name satisfies the name constraint. For |
| 40 // example, www.host.example.com would satisfy the constraint but |
| 41 // host1.example.com would not. |
| 42 // |
| 43 // |wildcard_matching| controls handling of wildcard names (|name| starts with |
| 44 // "*."). Wildcard handling is not specified by RFC 5280, but certificate |
| 45 // verification allows it, name constraints must check it similarly. |
| 46 bool DNSNameMatches(base::StringPiece name, |
| 47 base::StringPiece dns_constraint, |
| 48 WildcardMatchType wildcard_matching) { |
| 49 // Everything matches the empty DNS name constraint. |
| 50 if (dns_constraint.empty()) |
| 51 return true; |
| 52 |
| 53 // Normalize absolute DNS names by removing the trailing dot, if any. |
| 54 if (!name.empty() && *name.rbegin() == '.') |
| 55 name.remove_suffix(1); |
| 56 if (!dns_constraint.empty() && *dns_constraint.rbegin() == '.') |
| 57 dns_constraint.remove_suffix(1); |
| 58 |
| 59 // Wildcard partial-match handling ("*.bar.com" matching name constraint |
| 60 // "foo.bar.com"). This only handles the case where the the dnsname and the |
| 61 // constraint match after removing the leftmost label, otherwise it is handled |
| 62 // by falling through to the check of whether the dnsname is fully within or |
| 63 // fully outside of the constraint. |
| 64 if (wildcard_matching == WILDCARD_PARTIAL_MATCH && name.size() > 2 && |
| 65 name[0] == '*' && name[1] == '.') { |
| 66 size_t dns_constraint_dot_pos = dns_constraint.find('.'); |
| 67 if (dns_constraint_dot_pos != std::string::npos) { |
| 68 base::StringPiece dns_constraint_domain( |
| 69 dns_constraint.begin() + dns_constraint_dot_pos + 1, |
| 70 dns_constraint.size() - dns_constraint_dot_pos - 1); |
| 71 base::StringPiece wildcard_domain(name.begin() + 2, name.size() - 2); |
| 72 if (base::EqualsCaseInsensitiveASCII(wildcard_domain, |
| 73 dns_constraint_domain)) { |
| 74 return true; |
| 75 } |
| 76 } |
| 77 } |
| 78 |
| 79 if (!base::EndsWith(name, dns_constraint, |
| 80 base::CompareCase::INSENSITIVE_ASCII)) { |
| 81 return false; |
| 82 } |
| 83 // Exact match. |
| 84 if (name.size() == dns_constraint.size()) |
| 85 return true; |
| 86 // Subtree match. |
| 87 if (name.size() > dns_constraint.size() && |
| 88 name[name.size() - dns_constraint.size() - 1] == '.') { |
| 89 return true; |
| 90 } |
| 91 // Trailing text matches, but not in a subtree (e.g., "foobar.com" is not a |
| 92 // match for "bar.com"). |
| 93 return false; |
| 94 } |
| 95 |
| 96 // Return true if the bitmask |mask| contains only zeros after the first |
| 97 // |prefix_length| bits. |
| 98 bool IsSuffixZero(const std::vector<uint8_t>& mask, unsigned prefix_length) { |
| 99 size_t zero_bits = mask.size() * CHAR_BIT - prefix_length; |
| 100 size_t zero_bytes = zero_bits / CHAR_BIT; |
| 101 std::vector<uint8_t> zeros(zero_bytes, 0); |
| 102 if (memcmp(zeros.data(), mask.data() + mask.size() - zero_bytes, zero_bytes)) |
| 103 return false; |
| 104 size_t leftover_bits = zero_bits % CHAR_BIT; |
| 105 if (leftover_bits) { |
| 106 uint8_t b = mask[mask.size() - zero_bytes - 1]; |
| 107 for (size_t i = 0; i < leftover_bits; ++i) { |
| 108 if (b & (1 << i)) |
| 109 return false; |
| 110 } |
| 111 } |
| 112 return true; |
| 113 } |
| 114 |
| 115 // Controls handling of unsupported name types in ParseGeneralName. (Unsupported |
| 116 // types are those not in kSupportedNameTypes.) |
| 117 // RECORD_UNSUPPORTED causes unsupported types to be recorded in |
| 118 // |present_name_types|. |
| 119 // IGNORE_UNSUPPORTED causes unsupported types to not be recorded. |
| 120 enum ParseGeneralNameUnsupportedTypeBehavior { |
| 121 RECORD_UNSUPPORTED, |
| 122 IGNORE_UNSUPPORTED, |
| 123 }; |
| 124 |
| 125 // Controls parsing of iPAddress names in ParseGeneralName. |
| 126 // IP_ADDRESS_ONLY parses the iPAddress names as a 4 or 16 byte IP address. |
| 127 // IP_ADDRESS_AND_NETMASK parses the iPAddress names as 8 or 32 bytes containing |
| 128 // an IP address followed by a netmask. |
| 129 enum ParseGeneralNameIPAddressType { |
| 130 IP_ADDRESS_ONLY, |
| 131 IP_ADDRESS_AND_NETMASK, |
| 132 }; |
| 133 |
| 134 // Parses a GeneralName value and adds it to |subtrees|. |
| 135 WARN_UNUSED_RESULT bool ParseGeneralName( |
| 136 const der::Input& input, |
| 137 ParseGeneralNameUnsupportedTypeBehavior unsupported_type_behavior, |
| 138 ParseGeneralNameIPAddressType ip_address_type, |
| 139 NameConstraints::GeneralNames* subtrees) { |
| 140 der::Parser parser(input); |
| 141 der::Tag tag; |
| 142 der::Input value; |
| 143 if (!parser.ReadTagAndValue(&tag, &value)) |
| 144 return false; |
| 145 if (!der::IsContextSpecific(tag)) |
| 146 return false; |
| 147 GeneralNameTypes name_type = GENERAL_NAME_NONE; |
| 148 // GeneralName ::= CHOICE { |
| 149 switch (der::GetTagNumber(tag)) { |
| 150 // otherName [0] OtherName, |
| 151 case 0: |
| 152 if (!der::IsConstructed(tag)) |
| 153 return false; |
| 154 name_type = GENERAL_NAME_OTHER_NAME; |
| 155 break; |
| 156 // rfc822Name [1] IA5String, |
| 157 case 1: |
| 158 if (der::IsConstructed(tag)) |
| 159 return false; |
| 160 name_type = GENERAL_NAME_RFC822_NAME; |
| 161 break; |
| 162 // dNSName [2] IA5String, |
| 163 case 2: { |
| 164 if (der::IsConstructed(tag)) |
| 165 return false; |
| 166 name_type = GENERAL_NAME_DNS_NAME; |
| 167 const std::string s = value.AsString(); |
| 168 if (!base::IsStringASCII(s)) |
| 169 return false; |
| 170 subtrees->dns_names.push_back(s); |
| 171 break; |
| 172 } |
| 173 // x400Address [3] ORAddress, |
| 174 case 3: |
| 175 if (!der::IsConstructed(tag)) |
| 176 return false; |
| 177 name_type = GENERAL_NAME_X400_ADDRESS; |
| 178 break; |
| 179 // directoryName [4] Name, |
| 180 case 4: |
| 181 if (!der::IsConstructed(tag)) |
| 182 return false; |
| 183 name_type = GENERAL_NAME_DIRECTORY_NAME; |
| 184 subtrees->directory_names.push_back(std::vector<uint8_t>( |
| 185 value.UnsafeData(), value.UnsafeData() + value.Length())); |
| 186 break; |
| 187 // ediPartyName [5] EDIPartyName, |
| 188 case 5: |
| 189 if (!der::IsConstructed(tag)) |
| 190 return false; |
| 191 name_type = GENERAL_NAME_EDI_PARTY_NAME; |
| 192 break; |
| 193 // uniformResourceIdentifier [6] IA5String, |
| 194 case 6: |
| 195 if (der::IsConstructed(tag)) |
| 196 return false; |
| 197 name_type = GENERAL_NAME_UNIFORM_RESOURCE_IDENTIFIER; |
| 198 break; |
| 199 // iPAddress [7] OCTET STRING, |
| 200 case 7: |
| 201 if (der::IsConstructed(tag)) |
| 202 return false; |
| 203 name_type = GENERAL_NAME_IP_ADDRESS; |
| 204 if (ip_address_type == IP_ADDRESS_ONLY) { |
| 205 // RFC 5280 section 4.2.1.6: |
| 206 // When the subjectAltName extension contains an iPAddress, the address |
| 207 // MUST be stored in the octet string in "network byte order", as |
| 208 // specified in [RFC791]. The least significant bit (LSB) of each octet |
| 209 // is the LSB of the corresponding byte in the network address. For IP |
| 210 // version 4, as specified in [RFC791], the octet string MUST contain |
| 211 // exactly four octets. For IP version 6, as specified in [RFC2460], |
| 212 // the octet string MUST contain exactly sixteen octets. |
| 213 if ((value.Length() != kIPv4AddressSize && |
| 214 value.Length() != kIPv6AddressSize)) { |
| 215 return false; |
| 216 } |
| 217 subtrees->ip_addresses.push_back(std::vector<uint8_t>( |
| 218 value.UnsafeData(), value.UnsafeData() + value.Length())); |
| 219 } else { |
| 220 DCHECK_EQ(ip_address_type, IP_ADDRESS_AND_NETMASK); |
| 221 // RFC 5280 section 4.2.1.10: |
| 222 // The syntax of iPAddress MUST be as described in Section 4.2.1.6 with |
| 223 // the following additions specifically for name constraints. For IPv4 |
| 224 // addresses, the iPAddress field of GeneralName MUST contain eight (8) |
| 225 // octets, encoded in the style of RFC 4632 (CIDR) to represent an |
| 226 // address range [RFC4632]. For IPv6 addresses, the iPAddress field |
| 227 // MUST contain 32 octets similarly encoded. For example, a name |
| 228 // constraint for "class C" subnet 192.0.2.0 is represented as the |
| 229 // octets C0 00 02 00 FF FF FF 00, representing the CIDR notation |
| 230 // 192.0.2.0/24 (mask 255.255.255.0). |
| 231 if (value.Length() != kIPv4AddressSize * 2 && |
| 232 value.Length() != kIPv6AddressSize * 2) { |
| 233 return false; |
| 234 } |
| 235 const std::vector<uint8_t> mask(value.UnsafeData() + value.Length() / 2, |
| 236 value.UnsafeData() + value.Length()); |
| 237 const unsigned mask_prefix_length = MaskPrefixLength(mask); |
| 238 if (!IsSuffixZero(mask, mask_prefix_length)) |
| 239 return false; |
| 240 subtrees->ip_address_ranges.push_back(std::make_pair( |
| 241 std::vector<uint8_t>(value.UnsafeData(), |
| 242 value.UnsafeData() + value.Length() / 2), |
| 243 mask_prefix_length)); |
| 244 } |
| 245 break; |
| 246 // registeredID [8] OBJECT IDENTIFIER } |
| 247 case 8: |
| 248 if (der::IsConstructed(tag)) |
| 249 return false; |
| 250 name_type = GENERAL_NAME_REGISTERED_ID; |
| 251 break; |
| 252 default: |
| 253 return false; |
| 254 } |
| 255 DCHECK_NE(GENERAL_NAME_NONE, name_type); |
| 256 if ((name_type & kSupportedNameTypes) || |
| 257 unsupported_type_behavior == RECORD_UNSUPPORTED) { |
| 258 subtrees->present_name_types |= name_type; |
| 259 } |
| 260 return true; |
| 261 } |
| 262 |
| 263 // Parses a GeneralSubtrees |value| and store the contents in |subtrees|. |
| 264 // The individual values stored into |subtrees| are not validated by this |
| 265 // function. |
| 266 // NOTE: |subtrees| will be modified regardless of the return. |
| 267 WARN_UNUSED_RESULT bool ParseGeneralSubtrees( |
| 268 const der::Input& value, |
| 269 bool is_critical, |
| 270 NameConstraints::GeneralNames* subtrees) { |
| 271 // GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree |
| 272 // |
| 273 // GeneralSubtree ::= SEQUENCE { |
| 274 // base GeneralName, |
| 275 // minimum [0] BaseDistance DEFAULT 0, |
| 276 // maximum [1] BaseDistance OPTIONAL } |
| 277 // |
| 278 // BaseDistance ::= INTEGER (0..MAX) |
| 279 der::Parser sequence_parser(value); |
| 280 // The GeneralSubtrees sequence should have at least 1 element. |
| 281 if (!sequence_parser.HasMore()) |
| 282 return false; |
| 283 while (sequence_parser.HasMore()) { |
| 284 der::Parser subtree_sequence; |
| 285 if (!sequence_parser.ReadSequence(&subtree_sequence)) |
| 286 return false; |
| 287 |
| 288 der::Input raw_general_name; |
| 289 if (!subtree_sequence.ReadRawTLV(&raw_general_name)) |
| 290 return false; |
| 291 |
| 292 if (!ParseGeneralName(raw_general_name, |
| 293 is_critical ? RECORD_UNSUPPORTED : IGNORE_UNSUPPORTED, |
| 294 IP_ADDRESS_AND_NETMASK, subtrees)) { |
| 295 return false; |
| 296 } |
| 297 |
| 298 // RFC 5280 section 4.2.1.10: |
| 299 // Within this profile, the minimum and maximum fields are not used with any |
| 300 // name forms, thus, the minimum MUST be zero, and maximum MUST be absent. |
| 301 // However, if an application encounters a critical name constraints |
| 302 // extension that specifies other values for minimum or maximum for a name |
| 303 // form that appears in a subsequent certificate, the application MUST |
| 304 // either process these fields or reject the certificate. |
| 305 |
| 306 // Note that technically failing here isn't required: rather only need to |
| 307 // fail if a name of this type actually appears in a subsequent cert and |
| 308 // this extension was marked critical. However the minimum and maximum |
| 309 // fields appear uncommon enough that implementing that isn't useful. |
| 310 if (subtree_sequence.HasMore()) |
| 311 return false; |
| 312 } |
| 313 return true; |
| 314 } |
| 315 |
| 316 } // namespace |
| 317 |
| 318 NameConstraints::GeneralNames::GeneralNames() {} |
| 319 |
| 320 NameConstraints::GeneralNames::~GeneralNames() {} |
| 321 |
| 322 NameConstraints::~NameConstraints() {} |
| 323 |
| 324 // static |
| 325 scoped_ptr<NameConstraints> NameConstraints::CreateFromDer( |
| 326 const der::Input& extension_value, |
| 327 bool is_critical) { |
| 328 scoped_ptr<NameConstraints> name_constraints(new NameConstraints()); |
| 329 if (!name_constraints->Parse(extension_value, is_critical)) |
| 330 return nullptr; |
| 331 return name_constraints; |
| 332 } |
| 333 |
| 334 bool NameConstraints::Parse(const der::Input& extension_value, |
| 335 bool is_critical) { |
| 336 der::Parser extension_parser(extension_value); |
| 337 der::Parser sequence_parser; |
| 338 |
| 339 // NameConstraints ::= SEQUENCE { |
| 340 // permittedSubtrees [0] GeneralSubtrees OPTIONAL, |
| 341 // excludedSubtrees [1] GeneralSubtrees OPTIONAL } |
| 342 if (!extension_parser.ReadSequence(&sequence_parser)) |
| 343 return false; |
| 344 if (extension_parser.HasMore()) |
| 345 return false; |
| 346 |
| 347 bool had_permitted_subtrees = false; |
| 348 der::Input permitted_subtrees_value; |
| 349 if (!sequence_parser.ReadOptionalTag(der::ContextSpecificConstructed(0), |
| 350 &permitted_subtrees_value, |
| 351 &had_permitted_subtrees)) { |
| 352 return false; |
| 353 } |
| 354 if (had_permitted_subtrees && |
| 355 !ParseGeneralSubtrees(permitted_subtrees_value, is_critical, |
| 356 &permitted_subtrees_)) { |
| 357 return false; |
| 358 } |
| 359 |
| 360 bool had_excluded_subtrees = false; |
| 361 der::Input excluded_subtrees_value; |
| 362 if (!sequence_parser.ReadOptionalTag(der::ContextSpecificConstructed(1), |
| 363 &excluded_subtrees_value, |
| 364 &had_excluded_subtrees)) { |
| 365 return false; |
| 366 } |
| 367 if (had_excluded_subtrees && |
| 368 !ParseGeneralSubtrees(excluded_subtrees_value, is_critical, |
| 369 &excluded_subtrees_)) { |
| 370 return false; |
| 371 } |
| 372 |
| 373 // RFC 5280 section 4.2.1.10: |
| 374 // Conforming CAs MUST NOT issue certificates where name constraints is an |
| 375 // empty sequence. That is, either the permittedSubtrees field or the |
| 376 // excludedSubtrees MUST be present. |
| 377 if (!had_permitted_subtrees && !had_excluded_subtrees) |
| 378 return false; |
| 379 |
| 380 if (sequence_parser.HasMore()) |
| 381 return false; |
| 382 |
| 383 return true; |
| 384 } |
| 385 |
| 386 bool NameConstraints::IsPermittedCert( |
| 387 const der::Input& subject_rdn_sequence, |
| 388 const der::Input& subject_alt_name_extnvalue_tlv) const { |
| 389 // Subject Alternative Name handling: |
| 390 // |
| 391 // RFC 5280 section 4.2.1.6: |
| 392 // id-ce-subjectAltName OBJECT IDENTIFIER ::= { id-ce 17 } |
| 393 // |
| 394 // SubjectAltName ::= GeneralNames |
| 395 // |
| 396 // GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName |
| 397 |
| 398 GeneralNames san_names; |
| 399 if (subject_alt_name_extnvalue_tlv.Length()) { |
| 400 der::Parser extnvalue_parser(subject_alt_name_extnvalue_tlv); |
| 401 der::Input subject_alt_name_tlv; |
| 402 if (!extnvalue_parser.ReadTag(der::kOctetString, &subject_alt_name_tlv)) |
| 403 return false; |
| 404 |
| 405 der::Parser subject_alt_name_parser(subject_alt_name_tlv); |
| 406 der::Parser san_sequence_parser; |
| 407 if (!subject_alt_name_parser.ReadSequence(&san_sequence_parser)) |
| 408 return false; |
| 409 // Should not have trailing data after subjectAltName sequence. |
| 410 if (subject_alt_name_parser.HasMore()) |
| 411 return false; |
| 412 // The subjectAltName sequence should have at least 1 element. |
| 413 if (!san_sequence_parser.HasMore()) |
| 414 return false; |
| 415 |
| 416 while (san_sequence_parser.HasMore()) { |
| 417 der::Input raw_general_name; |
| 418 if (!san_sequence_parser.ReadRawTLV(&raw_general_name)) |
| 419 return false; |
| 420 |
| 421 if (!ParseGeneralName(raw_general_name, RECORD_UNSUPPORTED, |
| 422 IP_ADDRESS_ONLY, &san_names)) |
| 423 return false; |
| 424 } |
| 425 |
| 426 // Check unsupported name types: |
| 427 // ConstrainedNameTypes for the unsupported types will only be true if that |
| 428 // type of name was present in a name constraint that was marked critical. |
| 429 // |
| 430 // RFC 5280 section 4.2.1.10: |
| 431 // If a name constraints extension that is marked as critical |
| 432 // imposes constraints on a particular name form, and an instance of |
| 433 // that name form appears in the subject field or subjectAltName |
| 434 // extension of a subsequent certificate, then the application MUST |
| 435 // either process the constraint or reject the certificate. |
| 436 if (ConstrainedNameTypes() & san_names.present_name_types & |
| 437 ~kSupportedNameTypes) { |
| 438 return false; |
| 439 } |
| 440 |
| 441 // Check supported name types: |
| 442 for (const auto& dns_name : san_names.dns_names) { |
| 443 if (!IsPermittedDNSName(dns_name)) |
| 444 return false; |
| 445 } |
| 446 |
| 447 for (const auto& directory_name : san_names.directory_names) { |
| 448 if (!IsPermittedDirectoryName( |
| 449 der::Input(directory_name.data(), directory_name.size()))) { |
| 450 return false; |
| 451 } |
| 452 } |
| 453 |
| 454 for (const auto& ip_address : san_names.ip_addresses) { |
| 455 if (!IsPermittedIP(ip_address)) |
| 456 return false; |
| 457 } |
| 458 } |
| 459 |
| 460 // Subject handling: |
| 461 |
| 462 // RFC 5280 section 4.2.1.10: |
| 463 // Legacy implementations exist where an electronic mail address is embedded |
| 464 // in the subject distinguished name in an attribute of type emailAddress |
| 465 // (Section 4.1.2.6). When constraints are imposed on the rfc822Name name |
| 466 // form, but the certificate does not include a subject alternative name, the |
| 467 // rfc822Name constraint MUST be applied to the attribute of type emailAddress |
| 468 // in the subject distinguished name. |
| 469 if (!subject_alt_name_extnvalue_tlv.Length() && |
| 470 (ConstrainedNameTypes() & GENERAL_NAME_RFC822_NAME)) { |
| 471 bool contained_email_address = false; |
| 472 if (!NameContainsEmailAddress(subject_rdn_sequence, |
| 473 &contained_email_address)) { |
| 474 return false; |
| 475 } |
| 476 if (contained_email_address) |
| 477 return false; |
| 478 } |
| 479 |
| 480 // RFC 5280 4.1.2.6: |
| 481 // If subject naming information is present only in the subjectAltName |
| 482 // extension (e.g., a key bound only to an email address or URI), then the |
| 483 // subject name MUST be an empty sequence and the subjectAltName extension |
| 484 // MUST be critical. |
| 485 // This code assumes that criticality condition is checked by the caller, and |
| 486 // therefore only needs to avoid the IsPermittedDirectoryName check against an |
| 487 // empty subject in such a case. |
| 488 if (subject_alt_name_extnvalue_tlv.Length() && |
| 489 subject_rdn_sequence.Length() == 0) { |
| 490 return true; |
| 491 } |
| 492 |
| 493 return IsPermittedDirectoryName(subject_rdn_sequence); |
| 494 } |
| 495 |
| 496 bool NameConstraints::IsPermittedDNSName(const std::string& name) const { |
| 497 // If there are no name constraints for DNS names, all names are accepted. |
| 498 if (!(ConstrainedNameTypes() & GENERAL_NAME_DNS_NAME)) |
| 499 return true; |
| 500 |
| 501 for (const std::string& excluded_name : excluded_subtrees_.dns_names) { |
| 502 // When matching wildcard hosts against excluded subtrees, consider it a |
| 503 // match if the constraint would match any expansion of the wildcard. Eg, |
| 504 // *.bar.com should match a constraint of foo.bar.com. |
| 505 if (DNSNameMatches(name, excluded_name, WILDCARD_PARTIAL_MATCH)) |
| 506 return false; |
| 507 } |
| 508 for (const std::string& permitted_name : permitted_subtrees_.dns_names) { |
| 509 // When matching wildcard hosts against permitted subtrees, consider it a |
| 510 // match only if the constraint would match all expansions of the wildcard. |
| 511 // Eg, *.bar.com should match a constraint of bar.com, but not foo.bar.com. |
| 512 if (DNSNameMatches(name, permitted_name, WILDCARD_FULL_MATCH)) |
| 513 return true; |
| 514 } |
| 515 |
| 516 return false; |
| 517 } |
| 518 |
| 519 bool NameConstraints::IsPermittedDirectoryName( |
| 520 const der::Input& name_rdn_sequence) const { |
| 521 // If there are no name constraints for directory names, all names are |
| 522 // accepted. |
| 523 if (!(ConstrainedNameTypes() & GENERAL_NAME_DIRECTORY_NAME)) |
| 524 return true; |
| 525 |
| 526 for (const auto& excluded_name : excluded_subtrees_.directory_names) { |
| 527 if (VerifyNameInSubtree( |
| 528 name_rdn_sequence, |
| 529 der::Input(excluded_name.data(), excluded_name.size()))) { |
| 530 return false; |
| 531 } |
| 532 } |
| 533 for (const auto& permitted_name : permitted_subtrees_.directory_names) { |
| 534 if (VerifyNameInSubtree( |
| 535 name_rdn_sequence, |
| 536 der::Input(permitted_name.data(), permitted_name.size()))) { |
| 537 return true; |
| 538 } |
| 539 } |
| 540 |
| 541 return false; |
| 542 } |
| 543 |
| 544 bool NameConstraints::IsPermittedIP(const IPAddressNumber& ip) const { |
| 545 // If there are no name constraints for IP Address names, all names are |
| 546 // accepted. |
| 547 if (!(ConstrainedNameTypes() & GENERAL_NAME_IP_ADDRESS)) |
| 548 return true; |
| 549 |
| 550 for (const auto& excluded_ip : excluded_subtrees_.ip_address_ranges) { |
| 551 if (IPNumberMatchesPrefix(ip, excluded_ip.first, excluded_ip.second)) |
| 552 return false; |
| 553 } |
| 554 for (const auto& permitted_ip : permitted_subtrees_.ip_address_ranges) { |
| 555 if (IPNumberMatchesPrefix(ip, permitted_ip.first, permitted_ip.second)) |
| 556 return true; |
| 557 } |
| 558 |
| 559 return false; |
| 560 } |
| 561 |
| 562 int NameConstraints::ConstrainedNameTypes() const { |
| 563 return (permitted_subtrees_.present_name_types | |
| 564 excluded_subtrees_.present_name_types); |
| 565 } |
| 566 |
| 567 } // namespace net |
OLD | NEW |