| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/cert/internal/verify_name_match.h" | 5 #include "net/cert/internal/verify_name_match.h" |
| 6 | 6 |
| 7 #include <string.h> | 7 #include <string.h> |
| 8 | 8 |
| 9 #include "base/stl_util.h" | 9 #include "base/stl_util.h" |
| 10 #include "base/strings/string16.h" | 10 #include "base/strings/string16.h" |
| 11 #include "base/strings/string_util.h" | 11 #include "base/strings/string_util.h" |
| 12 #include "base/strings/utf_string_conversion_utils.h" | 12 #include "base/strings/utf_string_conversion_utils.h" |
| 13 #include "base/strings/utf_string_conversions.h" | 13 #include "base/strings/utf_string_conversions.h" |
| 14 #include "base/sys_byteorder.h" | 14 #include "base/sys_byteorder.h" |
| 15 #include "base/third_party/icu/icu_utf.h" | 15 #include "base/third_party/icu/icu_utf.h" |
| 16 #include "base/tuple.h" | 16 #include "base/tuple.h" |
| 17 #include "net/der/input.h" | 17 #include "net/der/input.h" |
| 18 #include "net/der/parser.h" | 18 #include "net/der/parser.h" |
| 19 #include "net/der/tag.h" | 19 #include "net/der/tag.h" |
| 20 | 20 |
| 21 namespace net { | 21 namespace net { |
| 22 | 22 |
| 23 namespace { | 23 namespace { |
| 24 | 24 |
| 25 // RFC 5280 section A.1: |
| 26 // |
| 27 // pkcs-9 OBJECT IDENTIFIER ::= |
| 28 // { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 9 } |
| 29 // |
| 30 // id-emailAddress AttributeType ::= { pkcs-9 1 } |
| 31 // |
| 32 // In dotted form: 1.2.840.113549.1.9.1 |
| 33 const uint8_t kOidEmailAddress[] = {0x2A, 0x86, 0x48, 0x86, 0xF7, |
| 34 0x0D, 0x01, 0x09, 0x01}; |
| 35 |
| 36 // RFC 5280 section A.1: |
| 37 // |
| 38 // id-at OBJECT IDENTIFIER ::= { joint-iso-ccitt(2) ds(5) 4 } |
| 39 // |
| 40 // id-at-commonName AttributeType ::= { id-at 3 } |
| 41 // |
| 42 // In dotted form: 2.5.4.3 |
| 43 const uint8_t kOidCommonName[] = {0x55, 0x04, 0x03}; |
| 44 |
| 25 // Types of character set checking that NormalizeDirectoryString can perform. | 45 // Types of character set checking that NormalizeDirectoryString can perform. |
| 26 enum CharsetEnforcement { | 46 enum CharsetEnforcement { |
| 27 NO_ENFORCEMENT, | 47 NO_ENFORCEMENT, |
| 28 ENFORCE_PRINTABLE_STRING, | 48 ENFORCE_PRINTABLE_STRING, |
| 29 ENFORCE_ASCII, | 49 ENFORCE_ASCII, |
| 30 }; | 50 }; |
| 31 | 51 |
| 32 // Normalizes |output|, a UTF-8 encoded string, as if it contained | 52 // Normalizes |output|, a UTF-8 encoded string, as if it contained |
| 33 // only ASCII characters. | 53 // only ASCII characters. |
| 34 // | 54 // |
| (...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 377 } | 397 } |
| 378 if (!matched) | 398 if (!matched) |
| 379 return false; | 399 return false; |
| 380 } | 400 } |
| 381 | 401 |
| 382 // Every element in |a_type_and_values| had a matching element in | 402 // Every element in |a_type_and_values| had a matching element in |
| 383 // |b_type_and_values|. | 403 // |b_type_and_values|. |
| 384 return true; | 404 return true; |
| 385 } | 405 } |
| 386 | 406 |
| 387 } // namespace | 407 enum NameMatchType { |
| 388 | 408 EXACT_MATCH, |
| 409 SUBTREE_MATCH, |
| 410 }; |
| 411 // Verify that |a| matches |b|. If |match_type| is EXACT_MATCH, returns true if |
| 412 // they are an exact match as defined by RFC 5280 7.1. If |match_type| is |
| 413 // SUBTREE_MATCH, returns true if |a| is within the subtree defined by |b| as |
| 414 // defined by RFC 5280 7.1. |
| 415 // |
| 389 // |a| and |b| are ASN.1 RDNSequence values (not including the Sequence tag), | 416 // |a| and |b| are ASN.1 RDNSequence values (not including the Sequence tag), |
| 390 // defined in RFC 5280 section 4.1.2.4: | 417 // defined in RFC 5280 section 4.1.2.4: |
| 391 // | 418 // |
| 392 // Name ::= CHOICE { -- only one possibility for now -- | 419 // Name ::= CHOICE { -- only one possibility for now -- |
| 393 // rdnSequence RDNSequence } | 420 // rdnSequence RDNSequence } |
| 394 // | 421 // |
| 395 // RDNSequence ::= SEQUENCE OF RelativeDistinguishedName | 422 // RDNSequence ::= SEQUENCE OF RelativeDistinguishedName |
| 396 // | 423 // |
| 397 // RelativeDistinguishedName ::= | 424 // RelativeDistinguishedName ::= |
| 398 // SET SIZE (1..MAX) OF AttributeTypeAndValue | 425 // SET SIZE (1..MAX) OF AttributeTypeAndValue |
| 399 bool VerifyNameMatch(const der::Input& a, const der::Input& b) { | 426 bool VerifyNameMatchInternal(const der::Input& a, |
| 427 const der::Input& b, |
| 428 NameMatchType match_type) { |
| 400 // Empty Names are allowed. RFC 5280 section 4.1.2.4 requires "The issuer | 429 // Empty Names are allowed. RFC 5280 section 4.1.2.4 requires "The issuer |
| 401 // field MUST contain a non-empty distinguished name (DN)", while section | 430 // field MUST contain a non-empty distinguished name (DN)", while section |
| 402 // 4.1.2.6 allows for the Subject to be empty in certain cases. The caller is | 431 // 4.1.2.6 allows for the Subject to be empty in certain cases. The caller is |
| 403 // assumed to have verified those conditions. | 432 // assumed to have verified those conditions. |
| 404 | 433 |
| 405 // RFC 5280 section 7.1: | 434 // RFC 5280 section 7.1: |
| 406 // Two distinguished names DN1 and DN2 match if they have the same number of | 435 // Two distinguished names DN1 and DN2 match if they have the same number of |
| 407 // RDNs, for each RDN in DN1 there is a matching RDN in DN2, and the matching | 436 // RDNs, for each RDN in DN1 there is a matching RDN in DN2, and the matching |
| 408 // RDNs appear in the same order in both DNs. | 437 // RDNs appear in the same order in both DNs. |
| 409 | 438 |
| 410 // First just check if the inputs have the same number of RDNs: | 439 // First just check if the inputs have the same number of RDNs: |
| 411 der::Parser a_rdn_sequence_counter(a); | 440 der::Parser a_rdn_sequence_counter(a); |
| 412 der::Parser b_rdn_sequence_counter(b); | 441 der::Parser b_rdn_sequence_counter(b); |
| 413 while (a_rdn_sequence_counter.HasMore() && b_rdn_sequence_counter.HasMore()) { | 442 while (a_rdn_sequence_counter.HasMore() && b_rdn_sequence_counter.HasMore()) { |
| 414 if (!a_rdn_sequence_counter.SkipTag(der::kSet) || | 443 if (!a_rdn_sequence_counter.SkipTag(der::kSet) || |
| 415 !b_rdn_sequence_counter.SkipTag(der::kSet)) { | 444 !b_rdn_sequence_counter.SkipTag(der::kSet)) { |
| 416 return false; | 445 return false; |
| 417 } | 446 } |
| 418 } | 447 } |
| 419 if (a_rdn_sequence_counter.HasMore() || b_rdn_sequence_counter.HasMore()) | 448 // If doing exact match and either of the sequences has more elements than the |
| 449 // other, not a match. If doing a subtree match, the first Name may have more |
| 450 // RDNs than the second. |
| 451 if (b_rdn_sequence_counter.HasMore()) |
| 452 return false; |
| 453 if (match_type == EXACT_MATCH && a_rdn_sequence_counter.HasMore()) |
| 420 return false; | 454 return false; |
| 421 | 455 |
| 422 // Same number of RDNs, now check if they match. | 456 // Same number of RDNs, now check if they match. |
| 423 der::Parser a_rdn_sequence(a); | 457 der::Parser a_rdn_sequence(a); |
| 424 der::Parser b_rdn_sequence(b); | 458 der::Parser b_rdn_sequence(b); |
| 425 while (a_rdn_sequence.HasMore() && b_rdn_sequence.HasMore()) { | 459 while (a_rdn_sequence.HasMore() && b_rdn_sequence.HasMore()) { |
| 426 der::Parser a_rdn, b_rdn; | 460 der::Parser a_rdn, b_rdn; |
| 427 if (!a_rdn_sequence.ReadConstructed(der::kSet, &a_rdn) || | 461 if (!a_rdn_sequence.ReadConstructed(der::kSet, &a_rdn) || |
| 428 !b_rdn_sequence.ReadConstructed(der::kSet, &b_rdn)) { | 462 !b_rdn_sequence.ReadConstructed(der::kSet, &b_rdn)) { |
| 429 return false; | 463 return false; |
| 430 } | 464 } |
| 431 if (!VerifyRdnMatch(&a_rdn, &b_rdn)) | 465 if (!VerifyRdnMatch(&a_rdn, &b_rdn)) |
| 432 return false; | 466 return false; |
| 433 } | 467 } |
| 434 | 468 |
| 435 return true; | 469 return true; |
| 436 } | 470 } |
| 437 | 471 |
| 472 } // namespace |
| 473 |
| 474 bool VerifyNameMatch(const der::Input& a_rdn_sequence, |
| 475 const der::Input& b_rdn_sequence) { |
| 476 return VerifyNameMatchInternal(a_rdn_sequence, b_rdn_sequence, EXACT_MATCH); |
| 477 } |
| 478 |
| 479 bool VerifyNameInSubtree(const der::Input& name_rdn_sequence, |
| 480 const der::Input& parent_rdn_sequence) { |
| 481 return VerifyNameMatchInternal(name_rdn_sequence, parent_rdn_sequence, |
| 482 SUBTREE_MATCH); |
| 483 } |
| 484 |
| 485 bool NameContainsEmailAddress(const der::Input& name_rdn_sequence) { |
| 486 der::Parser rdn_sequence_parser(name_rdn_sequence); |
| 487 |
| 488 while (rdn_sequence_parser.HasMore()) { |
| 489 der::Parser rdn_parser; |
| 490 if (!rdn_sequence_parser.ReadConstructed(der::kSet, &rdn_parser)) |
| 491 return false; |
| 492 |
| 493 std::vector<AttributeTypeAndValue> type_and_values; |
| 494 if (!ReadRdn(&rdn_parser, &type_and_values)) |
| 495 return false; |
| 496 |
| 497 for (const auto& type_and_value : type_and_values) { |
| 498 if (type_and_value.type.Equals(der::Input(kOidEmailAddress))) |
| 499 return true; |
| 500 } |
| 501 } |
| 502 |
| 503 return false; |
| 504 } |
| 505 |
| 506 std::string GetNormalizedCommonNameFromName( |
| 507 const der::Input& name_rdn_sequence) { |
| 508 der::Parser rdn_sequence_parser(name_rdn_sequence); |
| 509 |
| 510 while (rdn_sequence_parser.HasMore()) { |
| 511 der::Parser rdn_parser; |
| 512 if (!rdn_sequence_parser.ReadConstructed(der::kSet, &rdn_parser)) |
| 513 return std::string(); |
| 514 |
| 515 std::vector<AttributeTypeAndValue> type_and_values; |
| 516 if (!ReadRdn(&rdn_parser, &type_and_values)) |
| 517 return std::string(); |
| 518 |
| 519 for (const auto& type_and_value : type_and_values) { |
| 520 if (type_and_value.type.Equals(der::Input(kOidCommonName))) { |
| 521 if (!IsNormalizableDirectoryString(type_and_value.value_tag)) |
| 522 return std::string(); |
| 523 std::string normalized; |
| 524 bool ok = NormalizeValue(type_and_value.value_tag, type_and_value.value, |
| 525 &normalized); |
| 526 if (!ok) |
| 527 return std::string(); |
| 528 return normalized; |
| 529 } |
| 530 } |
| 531 } |
| 532 |
| 533 return std::string(); |
| 534 } |
| 535 |
| 438 } // namespace net | 536 } // namespace net |
| OLD | NEW |