OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2012 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/base/x509_cert_types.h" | |
6 | |
7 #include <string> | |
wtc
2012/02/15 01:34:41
Nit: <string> is already included by "net/base/x50
| |
8 | |
9 #include "base/logging.h" | |
10 #include "base/memory/scoped_ptr.h" | |
11 #include "base/string_util.h" | |
12 #include "base/utf_string_conversions.h" | |
13 #include "crypto/capi_util.h" | |
14 | |
15 #include <windows.h> | |
16 #include <wincrypt.h> | |
wtc
2012/02/15 01:34:41
Nit: the C system headers should be listed after
"
| |
17 #pragma comment(lib, "crypt32.lib") | |
18 | |
19 namespace net { | |
20 | |
21 namespace { | |
22 | |
23 // A list of OIDs to decode. Any OID not on this list will be ignored for | |
24 // purposes of parsing. | |
25 const char* kOIDs[] = { | |
26 szOID_COMMON_NAME, | |
27 szOID_LOCALITY_NAME, | |
28 szOID_STATE_OR_PROVINCE_NAME, | |
29 szOID_COUNTRY_NAME, | |
30 szOID_STREET_ADDRESS, | |
31 szOID_ORGANIZATION_NAME, | |
32 szOID_ORGANIZATIONAL_UNIT_NAME, | |
33 szOID_DOMAIN_COMPONENT | |
34 }; | |
35 | |
36 // Converts the value for |attribute| to an ASCII string, storing the result | |
wtc
2012/02/15 01:34:41
Typo: ASCII => UTF-8
| |
37 // in |value|. Returns false if the string cannot be converted. | |
38 bool GetAttributeValue(PCERT_RDN_ATTR attribute, | |
39 std::string* value) { | |
40 DWORD chars_needed = CertRDNValueToStrW(attribute->dwValueType, | |
41 &attribute->Value, NULL, 0); | |
42 if (chars_needed == 0) | |
43 return false; | |
44 if (chars_needed == 1) { | |
45 // The value is actually an empty string (chars_needed includes a single | |
46 // char for a NULL value). Don't bother converting - just clear the | |
47 // string. | |
48 value->clear(); | |
49 return true; | |
50 } | |
51 std::wstring wide_name; | |
52 DWORD chars_written = CertRDNValueToStrW( | |
53 attribute->dwValueType, &attribute->Value, | |
54 WriteInto(&wide_name, chars_needed), chars_needed); | |
55 if (chars_written <= 1) | |
56 return false; | |
57 wide_name.resize(chars_written - 1); | |
wtc
2012/02/15 01:34:41
Why isn't the equivalent of this line in the origi
Ryan Sleevi
2012/02/15 02:36:55
Correct. The unit tests correctly pointed out that
| |
58 *value = WideToUTF8(wide_name); | |
59 return true; | |
60 } | |
61 | |
62 // Adds a type+value pair to the appropriate vector from a C array. | |
63 // The array is keyed by the matching OIDs from kOIDS[]. | |
64 bool AddTypeValuePair(PCERT_RDN_ATTR attribute, | |
65 std::vector<std::string>* values[]) { | |
66 for (size_t oid = 0; oid < arraysize(kOIDs); ++oid) { | |
67 if (strcmp(attribute->pszObjId, kOIDs[oid]) == 0) { | |
68 std::string value; | |
69 if (!GetAttributeValue(attribute, &value)) | |
70 return false; | |
71 values[oid]->push_back(value); | |
72 break; | |
73 } | |
74 } | |
75 return true; | |
76 } | |
77 | |
78 // Stores the first string of the vector, if any, to *single_value. | |
79 void SetSingle(const std::vector<std::string>& values, | |
80 std::string* single_value) { | |
81 // We don't expect to have more than one CN, L, S, and C. | |
82 LOG_IF(WARNING, values.size() > 1) << "Didn't expect multiple values"; | |
83 if (!values.empty()) | |
84 *single_value = values[0]; | |
85 } | |
86 | |
87 } | |
wtc
2012/02/15 01:34:41
Nit: add a
// namespace
comment
| |
88 | |
89 bool CertPrincipal::ParseDistinguishedName(const void* ber_name_data, | |
90 size_t length) { | |
91 DCHECK(ber_name_data); | |
92 | |
93 CRYPT_DECODE_PARA decode_para; | |
94 decode_para.cbSize = sizeof(decode_para); | |
95 decode_para.pfnAlloc = crypto::CryptAllocFunction; | |
96 decode_para.pfnFree = crypto::CryptFreeFunction; | |
97 CERT_NAME_INFO* name_info = NULL; | |
98 DWORD name_info_size = 0; | |
99 BOOL rv; | |
100 rv = CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, | |
101 X509_NAME, | |
102 reinterpret_cast<const BYTE*>(ber_name_data), | |
103 length, | |
104 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG, | |
105 &decode_para, | |
106 &name_info, &name_info_size); | |
107 if (!rv) | |
108 return false; | |
109 scoped_ptr_malloc<CERT_NAME_INFO> scoped_name_info(name_info); | |
110 | |
111 std::vector<std::string> common_names, locality_names, state_names, | |
112 country_names; | |
113 | |
114 std::vector<std::string>* values[] = { | |
115 &common_names, &locality_names, | |
116 &state_names, &country_names, | |
117 &(this->street_addresses), | |
118 &(this->organization_names), | |
119 &(this->organization_unit_names), | |
120 &(this->domain_components) | |
wtc
2012/02/15 01:34:41
I assume you use this-> for clarity.
Nit: you can
| |
121 }; | |
122 DCHECK(arraysize(kOIDs) == arraysize(values)); | |
123 | |
124 for (DWORD cur_rdn = 0; cur_rdn < name_info->cRDN; ++cur_rdn) { | |
125 PCERT_RDN rdn = &name_info->rgRDN[cur_rdn]; | |
126 for (DWORD cur_ava = 0; cur_ava < rdn->cRDNAttr; ++cur_ava) { | |
127 PCERT_RDN_ATTR ava = &rdn->rgRDNAttr[cur_ava]; | |
128 if (!AddTypeValuePair(ava, values)) | |
129 return false; | |
130 } | |
131 } | |
132 | |
133 SetSingle(common_names, &this->common_name); | |
134 SetSingle(locality_names, &this->locality_name); | |
135 SetSingle(state_names, &this->state_or_province_name); | |
136 SetSingle(country_names, &this->country_name); | |
137 return true; | |
138 } | |
139 | |
140 } // namespace net | |
OLD | NEW |