1 // Copyright 2016 The Chromium Authors
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 "parse_name.h"
6
7 #include <cassert>
8
9 #include "string_util.h"
10 #include "parse_values.h"
11 #include <openssl/bytestring.h>
12 #include <openssl/mem.h>
13
14 namespace bssl {
15
16 namespace {
17
18 // Returns a string containing the dotted numeric form of |oid|, or an empty
19 // string on error.
OidToString(der::Input oid)20 std::string OidToString(der::Input oid) {
21 CBS cbs;
22 CBS_init(&cbs, oid.UnsafeData(), oid.Length());
23 bssl::UniquePtr<char> text(CBS_asn1_oid_to_text(&cbs));
24 if (!text)
25 return std::string();
26 return text.get();
27 }
28
29 } // namespace
30
ValueAsString(std::string * out) const31 bool X509NameAttribute::ValueAsString(std::string* out) const {
32 switch (value_tag) {
33 case der::kTeletexString:
34 return der::ParseTeletexStringAsLatin1(value, out);
35 case der::kIA5String:
36 return der::ParseIA5String(value, out);
37 case der::kPrintableString:
38 return der::ParsePrintableString(value, out);
39 case der::kUtf8String:
40 *out = value.AsString();
41 return true;
42 case der::kUniversalString:
43 return der::ParseUniversalString(value, out);
44 case der::kBmpString:
45 return der::ParseBmpString(value, out);
46 default:
47 return false;
48 }
49 }
50
ValueAsStringWithUnsafeOptions(PrintableStringHandling printable_string_handling,std::string * out) const51 bool X509NameAttribute::ValueAsStringWithUnsafeOptions(
52 PrintableStringHandling printable_string_handling,
53 std::string* out) const {
54 if (printable_string_handling == PrintableStringHandling::kAsUTF8Hack &&
55 value_tag == der::kPrintableString) {
56 *out = value.AsString();
57 return true;
58 }
59 return ValueAsString(out);
60 }
61
ValueAsStringUnsafe(std::string * out) const62 bool X509NameAttribute::ValueAsStringUnsafe(std::string* out) const {
63 switch (value_tag) {
64 case der::kIA5String:
65 case der::kPrintableString:
66 case der::kTeletexString:
67 case der::kUtf8String:
68 *out = value.AsString();
69 return true;
70 case der::kUniversalString:
71 return der::ParseUniversalString(value, out);
72 case der::kBmpString:
73 return der::ParseBmpString(value, out);
74 default:
75 assert(0); // NOTREACHED
76 return false;
77 }
78 }
79
AsRFC2253String(std::string * out) const80 bool X509NameAttribute::AsRFC2253String(std::string* out) const {
81 std::string type_string;
82 std::string value_string;
83 // TODO(mattm): Add streetAddress and domainComponent here?
84 if (type == der::Input(kTypeCommonNameOid)) {
85 type_string = "CN";
86 } else if (type == der::Input(kTypeSurnameOid)) {
87 type_string = "SN";
88 } else if (type == der::Input(kTypeCountryNameOid)) {
89 type_string = "C";
90 } else if (type == der::Input(kTypeLocalityNameOid)) {
91 type_string = "L";
92 } else if (type == der::Input(kTypeStateOrProvinceNameOid)) {
93 type_string = "ST";
94 } else if (type == der::Input(kTypeOrganizationNameOid)) {
95 type_string = "O";
96 } else if (type == der::Input(kTypeOrganizationUnitNameOid)) {
97 type_string = "OU";
98 } else if (type == der::Input(kTypeGivenNameOid)) {
99 type_string = "givenName";
100 } else if (type == der::Input(kTypeEmailAddressOid)) {
101 type_string = "emailAddress";
102 } else {
103 type_string = OidToString(type);
104 if (type_string.empty())
105 return false;
106 value_string =
107 "#" + bssl::string_util::HexEncode(value.UnsafeData(), value.Length());
108 }
109
110 if (value_string.empty()) {
111 std::string unescaped;
112 if (!ValueAsStringUnsafe(&unescaped))
113 return false;
114
115 bool nonprintable = false;
116 for (unsigned int i = 0; i < unescaped.length(); ++i) {
117 unsigned char c = static_cast<unsigned char>(unescaped[i]);
118 if (i == 0 && c == '#') {
119 value_string += "\\#";
120 } else if (i == 0 && c == ' ') {
121 value_string += "\\ ";
122 } else if (i == unescaped.length() - 1 && c == ' ') {
123 value_string += "\\ ";
124 } else if (c == ',' || c == '+' || c == '"' || c == '\\' || c == '<' ||
125 c == '>' || c == ';') {
126 value_string += "\\";
127 value_string += c;
128 } else if (c < 32 || c > 126) {
129 nonprintable = true;
130 std::string h;
131 h += c;
132 value_string +=
133 "\\" + bssl::string_util::HexEncode(
134 reinterpret_cast<const uint8_t*>(h.data()), h.length());
135 } else {
136 value_string += c;
137 }
138 }
139
140 // If we have non-printable characters in a TeletexString, we hex encode
141 // since we don't handle Teletex control codes.
142 if (nonprintable && value_tag == der::kTeletexString)
143 value_string =
144 "#" + bssl::string_util::HexEncode(value.UnsafeData(), value.Length());
145 }
146
147 *out = type_string + "=" + value_string;
148 return true;
149 }
150
ReadRdn(der::Parser * parser,RelativeDistinguishedName * out)151 bool ReadRdn(der::Parser* parser, RelativeDistinguishedName* out) {
152 while (parser->HasMore()) {
153 der::Parser attr_type_and_value;
154 if (!parser->ReadSequence(&attr_type_and_value))
155 return false;
156 // Read the attribute type, which must be an OBJECT IDENTIFIER.
157 der::Input type;
158 if (!attr_type_and_value.ReadTag(der::kOid, &type))
159 return false;
160
161 // Read the attribute value.
162 der::Tag tag;
163 der::Input value;
164 if (!attr_type_and_value.ReadTagAndValue(&tag, &value))
165 return false;
166
167 // There should be no more elements in the sequence after reading the
168 // attribute type and value.
169 if (attr_type_and_value.HasMore())
170 return false;
171
172 out->push_back(X509NameAttribute(type, tag, value));
173 }
174
175 // RFC 5280 section 4.1.2.4
176 // RelativeDistinguishedName ::= SET SIZE (1..MAX) OF AttributeTypeAndValue
177 return out->size() != 0;
178 }
179
ParseName(const der::Input & name_tlv,RDNSequence * out)180 bool ParseName(const der::Input& name_tlv, RDNSequence* out) {
181 der::Parser name_parser(name_tlv);
182 der::Input name_value;
183 if (!name_parser.ReadTag(der::kSequence, &name_value))
184 return false;
185 return ParseNameValue(name_value, out);
186 }
187
ParseNameValue(const der::Input & name_value,RDNSequence * out)188 bool ParseNameValue(const der::Input& name_value, RDNSequence* out) {
189 der::Parser rdn_sequence_parser(name_value);
190 while (rdn_sequence_parser.HasMore()) {
191 der::Parser rdn_parser;
192 if (!rdn_sequence_parser.ReadConstructed(der::kSet, &rdn_parser))
193 return false;
194 RelativeDistinguishedName type_and_values;
195 if (!ReadRdn(&rdn_parser, &type_and_values))
196 return false;
197 out->push_back(type_and_values);
198 }
199
200 return true;
201 }
202
ConvertToRFC2253(const RDNSequence & rdn_sequence,std::string * out)203 bool ConvertToRFC2253(const RDNSequence& rdn_sequence, std::string* out) {
204 std::string rdns_string;
205 size_t size = rdn_sequence.size();
206 for (size_t i = 0; i < size; ++i) {
207 RelativeDistinguishedName rdn = rdn_sequence[size - i - 1];
208 std::string rdn_string;
209 for (const auto& atv : rdn) {
210 if (!rdn_string.empty())
211 rdn_string += "+";
212 std::string atv_string;
213 if (!atv.AsRFC2253String(&atv_string))
214 return false;
215 rdn_string += atv_string;
216 }
217 if (!rdns_string.empty())
218 rdns_string += ",";
219 rdns_string += rdn_string;
220 }
221
222 *out = rdns_string;
223 return true;
224 }
225
226 } // namespace net
227