• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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