13345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/x509_cert_types.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <CoreServices/CoreServices.h>
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <Security/Security.h>
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <Security/SecAsn1Coder.h>
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/logging.h"
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/i18n/icu_string_conversions.h"
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/utf_string_conversions.h"
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace net {
16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
17201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochnamespace {
18201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
19201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochconst CSSM_OID* kOIDs[] = {
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    &CSSMOID_CommonName,
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    &CSSMOID_LocalityName,
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    &CSSMOID_StateProvinceName,
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    &CSSMOID_CountryName,
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    &CSSMOID_StreetAddress,
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    &CSSMOID_OrganizationName,
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    &CSSMOID_OrganizationalUnitName,
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    &CSSMOID_DNQualifier      // This should be "DC" but is undoubtedly wrong.
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};                            // TODO(avi): Find the right OID.
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The following structs and templates work with Apple's very arcane and under-
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// documented SecAsn1Parser API, which is apparently the same as NSS's ASN.1
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// decoder:
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// http://www.mozilla.org/projects/security/pki/nss/tech-notes/tn1.html
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// These are used to parse the contents of a raw
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// BER DistinguishedName structure.
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstruct KeyValuePair {
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CSSM_OID key;
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int value_type;
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CSSM_DATA value;
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  enum {
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    kTypeOther = 0,
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    kTypePrintableString,
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    kTypeIA5String,
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    kTypeT61String,
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    kTypeUTF8String,
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    kTypeBMPString,
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    kTypeUniversalString,
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
54201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochconst SecAsn1Template kStringValueTemplate[] = {
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  { SEC_ASN1_CHOICE, offsetof(KeyValuePair, value_type), },
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  { SEC_ASN1_PRINTABLE_STRING,
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    offsetof(KeyValuePair, value), 0, KeyValuePair::kTypePrintableString },
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  { SEC_ASN1_IA5_STRING,
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    offsetof(KeyValuePair, value), 0, KeyValuePair::kTypeIA5String },
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  { SEC_ASN1_T61_STRING,
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    offsetof(KeyValuePair, value), 0, KeyValuePair::kTypeT61String },
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  { SEC_ASN1_UTF8_STRING,
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    offsetof(KeyValuePair, value), 0, KeyValuePair::kTypeUTF8String },
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  { SEC_ASN1_BMP_STRING,
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    offsetof(KeyValuePair, value), 0, KeyValuePair::kTypeBMPString },
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  { SEC_ASN1_UNIVERSAL_STRING,
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    offsetof(KeyValuePair, value), 0, KeyValuePair::kTypeUniversalString },
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  { 0, }
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
71201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochconst SecAsn1Template kKeyValuePairTemplate[] = {
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(KeyValuePair) },
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  { SEC_ASN1_OBJECT_ID, offsetof(KeyValuePair, key), },
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  { SEC_ASN1_INLINE, 0, &kStringValueTemplate, },
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  { 0, }
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstruct KeyValuePairs {
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  KeyValuePair* pairs;
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
82201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochconst SecAsn1Template kKeyValuePairSetTemplate[] = {
83201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  { SEC_ASN1_SET_OF, offsetof(KeyValuePairs, pairs),
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      kKeyValuePairTemplate, sizeof(KeyValuePairs) }
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstruct X509Name {
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  KeyValuePairs** pairs_list;
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
91201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochconst SecAsn1Template kNameTemplate[] = {
92201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  { SEC_ASN1_SEQUENCE_OF, offsetof(X509Name, pairs_list),
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      kKeyValuePairSetTemplate, sizeof(X509Name) }
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
96201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// Converts raw CSSM_DATA to a std::string. (Char encoding is unaltered.)
97201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochstd::string DataToString(CSSM_DATA data) {
98201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  return std::string(
99201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      reinterpret_cast<std::string::value_type*>(data.Data),
100201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      data.Length);
101201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
102201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
103201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// Converts raw CSSM_DATA in ISO-8859-1 to a std::string in UTF-8.
104201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochstd::string Latin1DataToUTF8String(CSSM_DATA data) {
105201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  string16 utf16;
106201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (!CodepageToUTF16(DataToString(data), base::kCodepageLatin1,
107201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                       base::OnStringConversionError::FAIL, &utf16))
108201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    return "";
109201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  return UTF16ToUTF8(utf16);
110201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
111201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
112201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// Converts big-endian UTF-16 to UTF-8 in a std::string.
113201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// Note: The byte-order flipping is done in place on the input buffer!
114201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochbool UTF16BigEndianToUTF8(char16* chars, size_t length,
115201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                          std::string* out_string) {
116201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  for (size_t i = 0; i < length; i++)
117201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    chars[i] = EndianU16_BtoN(chars[i]);
118201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  return UTF16ToUTF8(chars, length, out_string);
119201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
120201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
121201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// Converts big-endian UTF-32 to UTF-8 in a std::string.
122201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// Note: The byte-order flipping is done in place on the input buffer!
123201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochbool UTF32BigEndianToUTF8(char32* chars, size_t length,
124201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                          std::string* out_string) {
125201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  for (size_t i = 0; i < length; ++i)
126201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    chars[i] = EndianS32_BtoN(chars[i]);
127201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#if defined(WCHAR_T_IS_UTF32)
128201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  return WideToUTF8(reinterpret_cast<const wchar_t*>(chars),
129201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                    length, out_string);
130201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#else
131201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#error This code doesn't handle 16-bit wchar_t.
132201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#endif
133201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
134201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
135201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// Adds a type+value pair to the appropriate vector from a C array.
136201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// The array is keyed by the matching OIDs from kOIDS[].
137201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid AddTypeValuePair(const CSSM_OID type,
138201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                      const std::string& value,
139201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                      std::vector<std::string>* values[]) {
140201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  for (size_t oid = 0; oid < arraysize(kOIDs); ++oid) {
141201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    if (CSSMOIDEqual(&type, kOIDs[oid])) {
142201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      values[oid]->push_back(value);
143201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      break;
144201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    }
145201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
146201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
147201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
148201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// Stores the first string of the vector, if any, to *single_value.
149201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid SetSingle(const std::vector<std::string>& values,
150201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch               std::string* single_value) {
151201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // We don't expect to have more than one CN, L, S, and C.
152201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  LOG_IF(WARNING, values.size() > 1) << "Didn't expect multiple values";
153dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (!values.empty())
154201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    *single_value = values[0];
155201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
156201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
157201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochbool match(const std::string& str, const std::string& against) {
158201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // TODO(snej): Use the full matching rules specified in RFC 5280 sec. 7.1
159201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // including trimming and case-folding: <http://www.ietf.org/rfc/rfc5280.txt>.
160201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  return against == str;
161201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
162201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
163201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochbool match(const std::vector<std::string>& rdn1,
164201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch           const std::vector<std::string>& rdn2) {
165201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // "Two relative distinguished names RDN1 and RDN2 match if they have the
166201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // same number of naming attributes and for each naming attribute in RDN1
167201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // there is a matching naming attribute in RDN2." --RFC 5280 sec. 7.1.
168201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (rdn1.size() != rdn2.size())
169201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    return false;
170201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  for (unsigned i1 = 0; i1 < rdn1.size(); ++i1) {
171201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    unsigned i2;
172201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    for (i2 = 0; i2 < rdn2.size(); ++i2) {
173201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      if (match(rdn1[i1], rdn2[i2]))
174201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch          break;
175201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    }
176201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    if (i2 == rdn2.size())
177201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      return false;
178201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
179201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  return true;
180201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
181201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
182201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}  // namespace
183201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool CertPrincipal::ParseDistinguishedName(const void* ber_name_data,
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                           size_t length) {
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(ber_name_data);
187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // First parse the BER |name_data| into the above structs.
189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SecAsn1CoderRef coder = NULL;
190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SecAsn1CoderCreate(&coder);
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(coder);
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  X509Name* name = NULL;
193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  OSStatus err = SecAsn1Decode(coder, ber_name_data, length, kNameTemplate,
194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               &name);
195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (err) {
196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    LOG(ERROR) << "SecAsn1Decode returned " << err << "; name=" << name;
197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    SecAsn1CoderRelease(coder);
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Now scan the structs and add the values to my string vectors.
202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // I don't store multiple common/locality/state/country names, so use
203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // temporary vectors for those.
204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::vector<std::string> common_names, locality_names, state_names,
205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      country_names;
206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::vector<std::string>* values[] = {
207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      &common_names, &locality_names,
208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      &state_names, &country_names,
209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      &this->street_addresses,
210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      &this->organization_names,
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      &this->organization_unit_names,
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      &this->domain_components
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(arraysize(kOIDs) == arraysize(values));
215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
216201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  for (int rdn = 0; name[rdn].pairs_list; ++rdn) {
217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    KeyValuePair *pair;
218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    for (int pair_index = 0;
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch         NULL != (pair = name[rdn].pairs_list[0][pair_index].pairs);
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch         ++pair_index) {
221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      switch (pair->value_type) {
222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        case KeyValuePair::kTypeIA5String:          // ASCII (that means 7-bit!)
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        case KeyValuePair::kTypePrintableString:    // a subset of ASCII
224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        case KeyValuePair::kTypeUTF8String:         // UTF-8
225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          AddTypeValuePair(pair->key, DataToString(pair->value), values);
226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          break;
227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        case KeyValuePair::kTypeT61String:          // T61, pretend it's Latin-1
228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          AddTypeValuePair(pair->key,
229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                           Latin1DataToUTF8String(pair->value),
230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                           values);
231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          break;
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        case KeyValuePair::kTypeBMPString: {        // UTF-16, big-endian
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          std::string value;
234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          UTF16BigEndianToUTF8(reinterpret_cast<char16*>(pair->value.Data),
235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               pair->value.Length / sizeof(char16),
236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               &value);
237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          AddTypeValuePair(pair->key, value, values);
238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          break;
239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        }
240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        case KeyValuePair::kTypeUniversalString: {  // UTF-32, big-endian
241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          std::string value;
242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          UTF32BigEndianToUTF8(reinterpret_cast<char32*>(pair->value.Data),
243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               pair->value.Length / sizeof(char32),
244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               &value);
245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          AddTypeValuePair(pair->key, value, values);
246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          break;
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        }
248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        default:
249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          DCHECK_EQ(pair->value_type, KeyValuePair::kTypeOther);
250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          // We don't know what data type this is, but we'll store it as a blob.
251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          // Displaying the string may not work, but at least it can be compared
252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          // byte-for-byte by a Matches() call.
253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          AddTypeValuePair(pair->key, DataToString(pair->value), values);
254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          break;
255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SetSingle(common_names, &this->common_name);
260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SetSingle(locality_names, &this->locality_name);
261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SetSingle(state_names, &this->state_or_province_name);
262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SetSingle(country_names, &this->country_name);
263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Releasing |coder| frees all the memory pointed to via |name|.
265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SecAsn1CoderRelease(coder);
266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
269201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid CertPrincipal::Parse(const CSSM_X509_NAME* name) {
270201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  std::vector<std::string> common_names, locality_names, state_names,
271201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      country_names;
2723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
273201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  std::vector<std::string>* values[] = {
274201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      &common_names, &locality_names,
275201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      &state_names, &country_names,
276201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      &(this->street_addresses),
277201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      &(this->organization_names),
278201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      &(this->organization_unit_names),
279201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      &(this->domain_components)
280201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  };
281201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  DCHECK(arraysize(kOIDs) == arraysize(values));
282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
283201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  for (size_t rdn = 0; rdn < name->numberOfRDNs; ++rdn) {
284201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    CSSM_X509_RDN rdn_struct = name->RelativeDistinguishedName[rdn];
285201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    for (size_t pair = 0; pair < rdn_struct.numberOfPairs; ++pair) {
286201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      CSSM_X509_TYPE_VALUE_PAIR pair_struct =
287201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch          rdn_struct.AttributeTypeAndValue[pair];
288201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      AddTypeValuePair(pair_struct.type,
289201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                       DataToString(pair_struct.value),
290201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                       values);
291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
293201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
294201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  SetSingle(common_names, &this->common_name);
295201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  SetSingle(locality_names, &this->locality_name);
296201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  SetSingle(state_names, &this->state_or_province_name);
297201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  SetSingle(country_names, &this->country_name);
298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
300201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochbool CertPrincipal::Matches(const CertPrincipal& against) const {
301201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  return match(common_name, against.common_name) &&
302201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      match(locality_name, against.locality_name) &&
303201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      match(state_or_province_name, against.state_or_province_name) &&
304201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      match(country_name, against.country_name) &&
305201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      match(street_addresses, against.street_addresses) &&
306201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      match(organization_names, against.organization_names) &&
307201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      match(organization_unit_names, against.organization_unit_names) &&
308201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      match(domain_components, against.domain_components);
309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace net
312