Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(16)

Side by Side Diff: net/cert/internal/verify_name_match.cc

Issue 1214933009: Class for parsing and evaluating RFC 5280 NameConstraints. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@compare_DN2
Patch Set: changes for comment #16 Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/cert/internal/verify_name_match.h ('k') | net/cert/internal/verify_name_match_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
25 // Types of character set checking that NormalizeDirectoryString can perform. 36 // Types of character set checking that NormalizeDirectoryString can perform.
26 enum CharsetEnforcement { 37 enum CharsetEnforcement {
27 NO_ENFORCEMENT, 38 NO_ENFORCEMENT,
28 ENFORCE_PRINTABLE_STRING, 39 ENFORCE_PRINTABLE_STRING,
29 ENFORCE_ASCII, 40 ENFORCE_ASCII,
30 }; 41 };
31 42
32 // Normalizes |output|, a UTF-8 encoded string, as if it contained 43 // Normalizes |output|, a UTF-8 encoded string, as if it contained
33 // only ASCII characters. 44 // only ASCII characters.
34 // 45 //
(...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after
382 // elements in a_type_and_values can't match the same element in 393 // elements in a_type_and_values can't match the same element in
383 // b_type_and_values multiple times. 394 // b_type_and_values multiple times.
384 b_type_and_values.erase(b_iter); 395 b_type_and_values.erase(b_iter);
385 } 396 }
386 397
387 // Every element in |a_type_and_values| had a matching element in 398 // Every element in |a_type_and_values| had a matching element in
388 // |b_type_and_values|. 399 // |b_type_and_values|.
389 return true; 400 return true;
390 } 401 }
391 402
392 } // namespace 403 enum NameMatchType {
404 EXACT_MATCH,
405 SUBTREE_MATCH,
406 };
393 407
408 // Verify that |a| matches |b|. If |match_type| is EXACT_MATCH, returns true if
409 // they are an exact match as defined by RFC 5280 7.1. If |match_type| is
410 // SUBTREE_MATCH, returns true if |a| is within the subtree defined by |b| as
411 // defined by RFC 5280 7.1.
412 //
394 // |a| and |b| are ASN.1 RDNSequence values (not including the Sequence tag), 413 // |a| and |b| are ASN.1 RDNSequence values (not including the Sequence tag),
395 // defined in RFC 5280 section 4.1.2.4: 414 // defined in RFC 5280 section 4.1.2.4:
396 // 415 //
397 // Name ::= CHOICE { -- only one possibility for now -- 416 // Name ::= CHOICE { -- only one possibility for now --
398 // rdnSequence RDNSequence } 417 // rdnSequence RDNSequence }
399 // 418 //
400 // RDNSequence ::= SEQUENCE OF RelativeDistinguishedName 419 // RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
401 // 420 //
402 // RelativeDistinguishedName ::= 421 // RelativeDistinguishedName ::=
403 // SET SIZE (1..MAX) OF AttributeTypeAndValue 422 // SET SIZE (1..MAX) OF AttributeTypeAndValue
404 bool VerifyNameMatch(const der::Input& a, const der::Input& b) { 423 bool VerifyNameMatchInternal(const der::Input& a,
424 const der::Input& b,
425 NameMatchType match_type) {
405 // Empty Names are allowed. RFC 5280 section 4.1.2.4 requires "The issuer 426 // Empty Names are allowed. RFC 5280 section 4.1.2.4 requires "The issuer
406 // field MUST contain a non-empty distinguished name (DN)", while section 427 // field MUST contain a non-empty distinguished name (DN)", while section
407 // 4.1.2.6 allows for the Subject to be empty in certain cases. The caller is 428 // 4.1.2.6 allows for the Subject to be empty in certain cases. The caller is
408 // assumed to have verified those conditions. 429 // assumed to have verified those conditions.
409 430
410 // RFC 5280 section 7.1: 431 // RFC 5280 section 7.1:
411 // Two distinguished names DN1 and DN2 match if they have the same number of 432 // Two distinguished names DN1 and DN2 match if they have the same number of
412 // RDNs, for each RDN in DN1 there is a matching RDN in DN2, and the matching 433 // RDNs, for each RDN in DN1 there is a matching RDN in DN2, and the matching
413 // RDNs appear in the same order in both DNs. 434 // RDNs appear in the same order in both DNs.
414 435
415 // First just check if the inputs have the same number of RDNs: 436 // First just check if the inputs have the same number of RDNs:
416 der::Parser a_rdn_sequence_counter(a); 437 der::Parser a_rdn_sequence_counter(a);
417 der::Parser b_rdn_sequence_counter(b); 438 der::Parser b_rdn_sequence_counter(b);
418 while (a_rdn_sequence_counter.HasMore() && b_rdn_sequence_counter.HasMore()) { 439 while (a_rdn_sequence_counter.HasMore() && b_rdn_sequence_counter.HasMore()) {
419 if (!a_rdn_sequence_counter.SkipTag(der::kSet) || 440 if (!a_rdn_sequence_counter.SkipTag(der::kSet) ||
420 !b_rdn_sequence_counter.SkipTag(der::kSet)) { 441 !b_rdn_sequence_counter.SkipTag(der::kSet)) {
421 return false; 442 return false;
422 } 443 }
423 } 444 }
424 if (a_rdn_sequence_counter.HasMore() || b_rdn_sequence_counter.HasMore()) 445 // If doing exact match and either of the sequences has more elements than the
446 // other, not a match. If doing a subtree match, the first Name may have more
447 // RDNs than the second.
448 if (b_rdn_sequence_counter.HasMore())
449 return false;
450 if (match_type == EXACT_MATCH && a_rdn_sequence_counter.HasMore())
425 return false; 451 return false;
426 452
427 // Same number of RDNs, now check if they match. 453 // Same number of RDNs, now check if they match.
428 der::Parser a_rdn_sequence(a); 454 der::Parser a_rdn_sequence(a);
429 der::Parser b_rdn_sequence(b); 455 der::Parser b_rdn_sequence(b);
430 while (a_rdn_sequence.HasMore() && b_rdn_sequence.HasMore()) { 456 while (a_rdn_sequence.HasMore() && b_rdn_sequence.HasMore()) {
431 der::Parser a_rdn, b_rdn; 457 der::Parser a_rdn, b_rdn;
432 if (!a_rdn_sequence.ReadConstructed(der::kSet, &a_rdn) || 458 if (!a_rdn_sequence.ReadConstructed(der::kSet, &a_rdn) ||
433 !b_rdn_sequence.ReadConstructed(der::kSet, &b_rdn)) { 459 !b_rdn_sequence.ReadConstructed(der::kSet, &b_rdn)) {
434 return false; 460 return false;
435 } 461 }
436 if (!VerifyRdnMatch(&a_rdn, &b_rdn)) 462 if (!VerifyRdnMatch(&a_rdn, &b_rdn))
437 return false; 463 return false;
438 } 464 }
439 465
440 return true; 466 return true;
441 } 467 }
442 468
469 } // namespace
470
471 bool VerifyNameMatch(const der::Input& a_rdn_sequence,
472 const der::Input& b_rdn_sequence) {
473 return VerifyNameMatchInternal(a_rdn_sequence, b_rdn_sequence, EXACT_MATCH);
474 }
475
476 bool VerifyNameInSubtree(const der::Input& name_rdn_sequence,
477 const der::Input& parent_rdn_sequence) {
478 return VerifyNameMatchInternal(name_rdn_sequence, parent_rdn_sequence,
479 SUBTREE_MATCH);
480 }
481
482 bool NameContainsEmailAddress(const der::Input& name_rdn_sequence,
483 bool* contained_email_address) {
484 der::Parser rdn_sequence_parser(name_rdn_sequence);
485
486 while (rdn_sequence_parser.HasMore()) {
487 der::Parser rdn_parser;
488 if (!rdn_sequence_parser.ReadConstructed(der::kSet, &rdn_parser))
489 return false;
490
491 std::vector<AttributeTypeAndValue> type_and_values;
492 if (!ReadRdn(&rdn_parser, &type_and_values))
493 return false;
494
495 for (const auto& type_and_value : type_and_values) {
496 if (type_and_value.type.Equals(der::Input(kOidEmailAddress))) {
497 *contained_email_address = true;
498 return true;
499 }
500 }
501 }
502
503 *contained_email_address = false;
504 return true;
505 }
506
443 } // namespace net 507 } // namespace net
OLDNEW
« no previous file with comments | « net/cert/internal/verify_name_match.h ('k') | net/cert/internal/verify_name_match_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698