/src/boringssl/crypto/x509/v3_alt.cc
Line | Count | Source |
1 | | // Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. |
2 | | // |
3 | | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | | // you may not use this file except in compliance with the License. |
5 | | // You may obtain a copy of the License at |
6 | | // |
7 | | // https://www.apache.org/licenses/LICENSE-2.0 |
8 | | // |
9 | | // Unless required by applicable law or agreed to in writing, software |
10 | | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | | // See the License for the specific language governing permissions and |
13 | | // limitations under the License. |
14 | | |
15 | | #include <stdio.h> |
16 | | #include <string.h> |
17 | | |
18 | | #include <openssl/asn1.h> |
19 | | #include <openssl/conf.h> |
20 | | #include <openssl/err.h> |
21 | | #include <openssl/mem.h> |
22 | | #include <openssl/obj.h> |
23 | | #include <openssl/x509.h> |
24 | | |
25 | | #include "internal.h" |
26 | | |
27 | | |
28 | | using namespace bssl; |
29 | | |
30 | | static void *v2i_subject_alt(const X509V3_EXT_METHOD *method, |
31 | | const X509V3_CTX *ctx, |
32 | | const STACK_OF(CONF_VALUE) *nval); |
33 | | static void *v2i_issuer_alt(const X509V3_EXT_METHOD *method, |
34 | | const X509V3_CTX *ctx, |
35 | | const STACK_OF(CONF_VALUE) *nval); |
36 | | static int copy_email(const X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p); |
37 | | static int copy_issuer(const X509V3_CTX *ctx, GENERAL_NAMES *gens); |
38 | | static int do_othername(GENERAL_NAME *gen, const char *value, |
39 | | const X509V3_CTX *ctx); |
40 | | static int do_dirname(GENERAL_NAME *gen, const char *value, |
41 | | const X509V3_CTX *ctx); |
42 | | |
43 | | static STACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES_cb( |
44 | 372 | const X509V3_EXT_METHOD *method, void *ext, STACK_OF(CONF_VALUE) *ret) { |
45 | 372 | return i2v_GENERAL_NAMES(method, reinterpret_cast<GENERAL_NAMES *>(ext), ret); |
46 | 372 | } |
47 | | |
48 | | const X509V3_EXT_METHOD bssl::v3_subject_alt_name = { |
49 | | NID_subject_alt_name, |
50 | | 0, |
51 | | ASN1_ITEM_ref(GENERAL_NAMES), |
52 | | nullptr, |
53 | | nullptr, |
54 | | nullptr, |
55 | | nullptr, |
56 | | nullptr, |
57 | | nullptr, |
58 | | i2v_GENERAL_NAMES_cb, |
59 | | v2i_subject_alt, |
60 | | nullptr, |
61 | | nullptr, |
62 | | nullptr, |
63 | | }; |
64 | | |
65 | | const X509V3_EXT_METHOD bssl::v3_issuer_alt_name = { |
66 | | NID_issuer_alt_name, |
67 | | 0, |
68 | | ASN1_ITEM_ref(GENERAL_NAMES), |
69 | | nullptr, |
70 | | nullptr, |
71 | | nullptr, |
72 | | nullptr, |
73 | | nullptr, |
74 | | nullptr, |
75 | | i2v_GENERAL_NAMES_cb, |
76 | | v2i_issuer_alt, |
77 | | nullptr, |
78 | | nullptr, |
79 | | nullptr, |
80 | | }; |
81 | | |
82 | | const X509V3_EXT_METHOD bssl::v3_certificate_issuer = { |
83 | | NID_certificate_issuer, |
84 | | 0, |
85 | | ASN1_ITEM_ref(GENERAL_NAMES), |
86 | | nullptr, |
87 | | nullptr, |
88 | | nullptr, |
89 | | nullptr, |
90 | | nullptr, |
91 | | nullptr, |
92 | | i2v_GENERAL_NAMES_cb, |
93 | | nullptr, |
94 | | nullptr, |
95 | | nullptr, |
96 | | nullptr, |
97 | | }; |
98 | | |
99 | | STACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES(const X509V3_EXT_METHOD *method, |
100 | | const GENERAL_NAMES *gens, |
101 | 490 | STACK_OF(CONF_VALUE) *ret) { |
102 | 490 | int ret_was_null = ret == nullptr; |
103 | 10.2k | for (size_t i = 0; i < sk_GENERAL_NAME_num(gens); i++) { |
104 | 9.84k | const GENERAL_NAME *gen = sk_GENERAL_NAME_value(gens, i); |
105 | 9.84k | STACK_OF(CONF_VALUE) *tmp = i2v_GENERAL_NAME(method, gen, ret); |
106 | 9.84k | if (tmp == nullptr) { |
107 | 132 | if (ret_was_null) { |
108 | 122 | sk_CONF_VALUE_pop_free(ret, X509V3_conf_free); |
109 | 122 | } |
110 | 132 | return nullptr; |
111 | 132 | } |
112 | 9.71k | ret = tmp; |
113 | 9.71k | } |
114 | 358 | if (!ret) { |
115 | 134 | return sk_CONF_VALUE_new_null(); |
116 | 134 | } |
117 | 224 | return ret; |
118 | 358 | } |
119 | | |
120 | | STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(const X509V3_EXT_METHOD *method, |
121 | | const GENERAL_NAME *gen, |
122 | 9.91k | STACK_OF(CONF_VALUE) *ret) { |
123 | | // Note the error-handling for this function relies on there being at most |
124 | | // one |X509V3_add_value| call. If there were two and the second failed, we |
125 | | // would need to sometimes free the first call's result. |
126 | 9.91k | unsigned char *p; |
127 | 9.91k | char oline[256], htmp[5]; |
128 | 9.91k | int i; |
129 | 9.91k | switch (gen->type) { |
130 | 155 | case GEN_OTHERNAME: |
131 | 155 | if (!X509V3_add_value("othername", "<unsupported>", &ret)) { |
132 | 0 | return nullptr; |
133 | 0 | } |
134 | 155 | break; |
135 | | |
136 | 1.46k | case GEN_X400: |
137 | 1.46k | if (!X509V3_add_value("X400Name", "<unsupported>", &ret)) { |
138 | 0 | return nullptr; |
139 | 0 | } |
140 | 1.46k | break; |
141 | | |
142 | 1.46k | case GEN_EDIPARTY: |
143 | 6 | if (!X509V3_add_value("EdiPartyName", "<unsupported>", &ret)) { |
144 | 0 | return nullptr; |
145 | 0 | } |
146 | 6 | break; |
147 | | |
148 | 1.30k | case GEN_EMAIL: |
149 | 1.30k | if (!x509V3_add_value_asn1_string("email", gen->d.ia5, &ret)) { |
150 | 36 | return nullptr; |
151 | 36 | } |
152 | 1.27k | break; |
153 | | |
154 | 1.27k | case GEN_DNS: |
155 | 1.12k | if (!x509V3_add_value_asn1_string("DNS", gen->d.ia5, &ret)) { |
156 | 46 | return nullptr; |
157 | 46 | } |
158 | 1.07k | break; |
159 | | |
160 | 1.82k | case GEN_URI: |
161 | 1.82k | if (!x509V3_add_value_asn1_string("URI", gen->d.ia5, &ret)) { |
162 | 66 | return nullptr; |
163 | 66 | } |
164 | 1.75k | break; |
165 | | |
166 | 1.75k | case GEN_DIRNAME: |
167 | 354 | if (X509_NAME_oneline(gen->d.dirn, oline, 256) == nullptr || |
168 | 354 | !X509V3_add_value("DirName", oline, &ret)) { |
169 | 0 | return nullptr; |
170 | 0 | } |
171 | 354 | break; |
172 | | |
173 | 1.74k | case GEN_IPADD: |
174 | 1.74k | p = gen->d.ip->data; |
175 | 1.74k | if (gen->d.ip->length == 4) { |
176 | 555 | snprintf(oline, sizeof(oline), "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); |
177 | 1.18k | } else if (gen->d.ip->length == 16) { |
178 | 249 | oline[0] = 0; |
179 | 2.24k | for (i = 0; i < 8; i++) { |
180 | 1.99k | uint16_t v = ((uint16_t)p[0] << 8) | p[1]; |
181 | 1.99k | snprintf(htmp, sizeof(htmp), "%X", v); |
182 | 1.99k | p += 2; |
183 | 1.99k | OPENSSL_strlcat(oline, htmp, sizeof(oline)); |
184 | 1.99k | if (i != 7) { |
185 | 1.74k | OPENSSL_strlcat(oline, ":", sizeof(oline)); |
186 | 1.74k | } |
187 | 1.99k | } |
188 | 936 | } else { |
189 | 936 | if (!X509V3_add_value("IP Address", "<invalid>", &ret)) { |
190 | 0 | return nullptr; |
191 | 0 | } |
192 | 936 | break; |
193 | 936 | } |
194 | 804 | if (!X509V3_add_value("IP Address", oline, &ret)) { |
195 | 0 | return nullptr; |
196 | 0 | } |
197 | 804 | break; |
198 | | |
199 | 1.94k | case GEN_RID: |
200 | 1.94k | i2t_ASN1_OBJECT(oline, 256, gen->d.rid); |
201 | 1.94k | if (!X509V3_add_value("Registered ID", oline, &ret)) { |
202 | 0 | return nullptr; |
203 | 0 | } |
204 | 1.94k | break; |
205 | 9.91k | } |
206 | 9.76k | return ret; |
207 | 9.91k | } |
208 | | |
209 | 2.07k | int GENERAL_NAME_print(BIO *out, const GENERAL_NAME *gen) { |
210 | 2.07k | switch (gen->type) { |
211 | 58 | case GEN_OTHERNAME: |
212 | 58 | BIO_printf(out, "othername:<unsupported>"); |
213 | 58 | break; |
214 | | |
215 | 132 | case GEN_X400: |
216 | 132 | BIO_printf(out, "X400Name:<unsupported>"); |
217 | 132 | break; |
218 | | |
219 | 9 | case GEN_EDIPARTY: |
220 | | // Maybe fix this: it is supported now |
221 | 9 | BIO_printf(out, "EdiPartyName:<unsupported>"); |
222 | 9 | break; |
223 | | |
224 | 371 | case GEN_EMAIL: |
225 | 371 | BIO_printf(out, "email:"); |
226 | 371 | ASN1_STRING_print(out, gen->d.ia5); |
227 | 371 | break; |
228 | | |
229 | 238 | case GEN_DNS: |
230 | 238 | BIO_printf(out, "DNS:"); |
231 | 238 | ASN1_STRING_print(out, gen->d.ia5); |
232 | 238 | break; |
233 | | |
234 | 577 | case GEN_URI: |
235 | 577 | BIO_printf(out, "URI:"); |
236 | 577 | ASN1_STRING_print(out, gen->d.ia5); |
237 | 577 | break; |
238 | | |
239 | 121 | case GEN_DIRNAME: |
240 | 121 | BIO_printf(out, "DirName: "); |
241 | 121 | X509_NAME_print_ex(out, gen->d.dirn, 0, XN_FLAG_ONELINE); |
242 | 121 | break; |
243 | | |
244 | 447 | case GEN_IPADD: { |
245 | 447 | const unsigned char *p = gen->d.ip->data; |
246 | 447 | if (gen->d.ip->length == 4) { |
247 | 124 | BIO_printf(out, "IP Address:%d.%d.%d.%d", p[0], p[1], p[2], p[3]); |
248 | 323 | } else if (gen->d.ip->length == 16) { |
249 | 30 | BIO_printf(out, "IP Address"); |
250 | 270 | for (int i = 0; i < 8; i++) { |
251 | 240 | uint16_t v = ((uint16_t)p[0] << 8) | p[1]; |
252 | 240 | BIO_printf(out, ":%X", v); |
253 | 240 | p += 2; |
254 | 240 | } |
255 | 30 | BIO_puts(out, "\n"); |
256 | 293 | } else { |
257 | 293 | BIO_printf(out, "IP Address:<invalid>"); |
258 | 293 | break; |
259 | 293 | } |
260 | 154 | break; |
261 | 447 | } |
262 | | |
263 | 154 | case GEN_RID: |
264 | 120 | BIO_printf(out, "Registered ID"); |
265 | 120 | i2a_ASN1_OBJECT(out, gen->d.rid); |
266 | 120 | break; |
267 | 2.07k | } |
268 | 2.07k | return 1; |
269 | 2.07k | } |
270 | | |
271 | | static void *v2i_issuer_alt(const X509V3_EXT_METHOD *method, |
272 | | const X509V3_CTX *ctx, |
273 | 982 | const STACK_OF(CONF_VALUE) *nval) { |
274 | 982 | GENERAL_NAMES *gens = sk_GENERAL_NAME_new_null(); |
275 | 982 | if (gens == nullptr) { |
276 | 0 | return nullptr; |
277 | 0 | } |
278 | 4.63k | for (size_t i = 0; i < sk_CONF_VALUE_num(nval); i++) { |
279 | 4.47k | const CONF_VALUE *cnf = sk_CONF_VALUE_value(nval, i); |
280 | 4.47k | if (x509v3_conf_name_matches(cnf->name, "issuer") && cnf->value && |
281 | 3.30k | !strcmp(cnf->value, "copy")) { |
282 | 3.29k | if (!copy_issuer(ctx, gens)) { |
283 | 695 | goto err; |
284 | 695 | } |
285 | 3.29k | } else { |
286 | 1.18k | GENERAL_NAME *gen = v2i_GENERAL_NAME(method, ctx, cnf); |
287 | 1.18k | if (gen == nullptr || !sk_GENERAL_NAME_push(gens, gen)) { |
288 | 132 | GENERAL_NAME_free(gen); |
289 | 132 | goto err; |
290 | 132 | } |
291 | 1.18k | } |
292 | 4.47k | } |
293 | 155 | return gens; |
294 | 827 | err: |
295 | 827 | sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); |
296 | 827 | return nullptr; |
297 | 982 | } |
298 | | |
299 | | // Append subject altname of issuer to issuer alt name of subject |
300 | | |
301 | 3.29k | static int copy_issuer(const X509V3_CTX *ctx, GENERAL_NAMES *gens) { |
302 | 3.29k | if (ctx && (ctx->flags == X509V3_CTX_TEST)) { |
303 | 0 | return 1; |
304 | 0 | } |
305 | 3.29k | if (!ctx || !ctx->issuer_cert) { |
306 | 441 | OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_ISSUER_DETAILS); |
307 | 441 | return 0; |
308 | 441 | } |
309 | 2.85k | int i = X509_get_ext_by_NID(ctx->issuer_cert, NID_subject_alt_name, -1); |
310 | 2.85k | if (i < 0) { |
311 | 594 | return 1; |
312 | 594 | } |
313 | | |
314 | 2.25k | int ret = 0; |
315 | 2.25k | GENERAL_NAMES *ialt = nullptr; |
316 | 2.25k | X509_EXTENSION *ext; |
317 | 2.25k | if (!(ext = X509_get_ext(ctx->issuer_cert, i)) || |
318 | 2.25k | !(ialt = reinterpret_cast<GENERAL_NAMES *>(X509V3_EXT_d2i(ext)))) { |
319 | 254 | OPENSSL_PUT_ERROR(X509V3, X509V3_R_ISSUER_DECODE_ERROR); |
320 | 254 | goto err; |
321 | 254 | } |
322 | | |
323 | 169k | for (size_t j = 0; j < sk_GENERAL_NAME_num(ialt); j++) { |
324 | 167k | GENERAL_NAME *gen = sk_GENERAL_NAME_value(ialt, j); |
325 | 167k | if (!sk_GENERAL_NAME_push(gens, gen)) { |
326 | 0 | goto err; |
327 | 0 | } |
328 | | // Ownership of |gen| has moved from |ialt| to |gens|. |
329 | 167k | sk_GENERAL_NAME_set(ialt, j, nullptr); |
330 | 167k | } |
331 | | |
332 | 2.00k | ret = 1; |
333 | | |
334 | 2.25k | err: |
335 | 2.25k | GENERAL_NAMES_free(ialt); |
336 | 2.25k | return ret; |
337 | 2.00k | } |
338 | | |
339 | | static void *v2i_subject_alt(const X509V3_EXT_METHOD *method, |
340 | | const X509V3_CTX *ctx, |
341 | 422 | const STACK_OF(CONF_VALUE) *nval) { |
342 | 422 | GENERAL_NAMES *gens = sk_GENERAL_NAME_new_null(); |
343 | 422 | if (gens == nullptr) { |
344 | 0 | return nullptr; |
345 | 0 | } |
346 | 10.3k | for (size_t i = 0; i < sk_CONF_VALUE_num(nval); i++) { |
347 | 10.0k | const CONF_VALUE *cnf = sk_CONF_VALUE_value(nval, i); |
348 | 10.0k | if (x509v3_conf_name_matches(cnf->name, "email") && cnf->value && |
349 | 1.49k | !strcmp(cnf->value, "copy")) { |
350 | 261 | if (!copy_email(ctx, gens, 0)) { |
351 | 20 | goto err; |
352 | 20 | } |
353 | 9.74k | } else if (x509v3_conf_name_matches(cnf->name, "email") && cnf->value && |
354 | 1.23k | !strcmp(cnf->value, "move")) { |
355 | 234 | if (!copy_email(ctx, gens, 1)) { |
356 | 17 | goto err; |
357 | 17 | } |
358 | 9.51k | } else { |
359 | 9.51k | GENERAL_NAME *gen = v2i_GENERAL_NAME(method, ctx, cnf); |
360 | 9.51k | if (gen == nullptr || !sk_GENERAL_NAME_push(gens, gen)) { |
361 | 60 | GENERAL_NAME_free(gen); |
362 | 60 | goto err; |
363 | 60 | } |
364 | 9.51k | } |
365 | 10.0k | } |
366 | 325 | return gens; |
367 | 97 | err: |
368 | 97 | sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); |
369 | 97 | return nullptr; |
370 | 422 | } |
371 | | |
372 | | // Copy any email addresses in a certificate or request to GENERAL_NAMES |
373 | | |
374 | 495 | static int copy_email(const X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p) { |
375 | 495 | X509_NAME *nm; |
376 | 495 | ASN1_IA5STRING *email = nullptr; |
377 | 495 | X509_NAME_ENTRY *ne; |
378 | 495 | GENERAL_NAME *gen = nullptr; |
379 | 495 | int i; |
380 | 495 | if (ctx != nullptr && ctx->flags == X509V3_CTX_TEST) { |
381 | 0 | return 1; |
382 | 0 | } |
383 | 495 | if (!ctx || (!ctx->subject_cert && !ctx->subject_req)) { |
384 | 37 | OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_SUBJECT_DETAILS); |
385 | 37 | goto err; |
386 | 37 | } |
387 | | // Find the subject name |
388 | 458 | if (ctx->subject_cert) { |
389 | 458 | nm = X509_get_subject_name(ctx->subject_cert); |
390 | 458 | } else { |
391 | 0 | nm = X509_REQ_get_subject_name(ctx->subject_req); |
392 | 0 | } |
393 | | |
394 | | // Now add any email address(es) to STACK |
395 | 458 | i = -1; |
396 | 458 | while ((i = X509_NAME_get_index_by_NID(nm, NID_pkcs9_emailAddress, i)) >= 0) { |
397 | 0 | ne = X509_NAME_get_entry(nm, i); |
398 | 0 | email = ASN1_STRING_dup(X509_NAME_ENTRY_get_data(ne)); |
399 | 0 | if (move_p) { |
400 | 0 | X509_NAME_delete_entry(nm, i); |
401 | 0 | X509_NAME_ENTRY_free(ne); |
402 | 0 | i--; |
403 | 0 | } |
404 | 0 | if (!email || !(gen = GENERAL_NAME_new())) { |
405 | 0 | goto err; |
406 | 0 | } |
407 | 0 | gen->d.ia5 = email; |
408 | 0 | email = nullptr; |
409 | 0 | gen->type = GEN_EMAIL; |
410 | 0 | if (!sk_GENERAL_NAME_push(gens, gen)) { |
411 | 0 | goto err; |
412 | 0 | } |
413 | 0 | gen = nullptr; |
414 | 0 | } |
415 | | |
416 | 458 | return 1; |
417 | | |
418 | 37 | err: |
419 | 37 | GENERAL_NAME_free(gen); |
420 | 37 | ASN1_IA5STRING_free(email); |
421 | 37 | return 0; |
422 | 458 | } |
423 | | |
424 | | GENERAL_NAMES *bssl::v2i_GENERAL_NAMES(const X509V3_EXT_METHOD *method, |
425 | | const X509V3_CTX *ctx, |
426 | 45.1k | const STACK_OF(CONF_VALUE) *nval) { |
427 | 45.1k | GENERAL_NAMES *gens = sk_GENERAL_NAME_new_null(); |
428 | 45.1k | if (gens == nullptr) { |
429 | 0 | return nullptr; |
430 | 0 | } |
431 | 97.7k | for (size_t i = 0; i < sk_CONF_VALUE_num(nval); i++) { |
432 | 52.6k | const CONF_VALUE *cnf = sk_CONF_VALUE_value(nval, i); |
433 | 52.6k | GENERAL_NAME *gen = v2i_GENERAL_NAME(method, ctx, cnf); |
434 | 52.6k | if (gen == nullptr || !sk_GENERAL_NAME_push(gens, gen)) { |
435 | 16 | GENERAL_NAME_free(gen); |
436 | 16 | goto err; |
437 | 16 | } |
438 | 52.6k | } |
439 | 45.0k | return gens; |
440 | 16 | err: |
441 | 16 | sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); |
442 | 16 | return nullptr; |
443 | 45.1k | } |
444 | | |
445 | | GENERAL_NAME *bssl::v2i_GENERAL_NAME(const X509V3_EXT_METHOD *method, |
446 | | const X509V3_CTX *ctx, |
447 | 65.9k | const CONF_VALUE *cnf) { |
448 | 65.9k | return v2i_GENERAL_NAME_ex(nullptr, method, ctx, cnf, 0); |
449 | 65.9k | } |
450 | | |
451 | | static GENERAL_NAME *a2i_GENERAL_NAME(GENERAL_NAME *out, |
452 | | const X509V3_EXT_METHOD *method, |
453 | | const X509V3_CTX *ctx, int gen_type, |
454 | 67.2k | const char *value, int is_nc) { |
455 | 67.2k | if (!value) { |
456 | 0 | OPENSSL_PUT_ERROR(X509V3, X509V3_R_MISSING_VALUE); |
457 | 0 | return nullptr; |
458 | 0 | } |
459 | | |
460 | 67.2k | GENERAL_NAME *gen = nullptr; |
461 | 67.2k | if (out) { |
462 | 1.63k | gen = out; |
463 | 65.6k | } else { |
464 | 65.6k | gen = GENERAL_NAME_new(); |
465 | 65.6k | if (gen == nullptr) { |
466 | 0 | return nullptr; |
467 | 0 | } |
468 | 65.6k | } |
469 | | |
470 | 67.2k | switch (gen_type) { |
471 | 9.19k | case GEN_URI: |
472 | 10.9k | case GEN_EMAIL: |
473 | 11.9k | case GEN_DNS: { |
474 | 11.9k | ASN1_IA5STRING *str = ASN1_IA5STRING_new(); |
475 | 11.9k | if (str == nullptr || !ASN1_STRING_set(str, value, strlen(value))) { |
476 | 0 | ASN1_STRING_free(str); |
477 | 0 | goto err; |
478 | 0 | } |
479 | 11.9k | gen->type = gen_type; |
480 | 11.9k | gen->d.ia5 = str; |
481 | 11.9k | break; |
482 | 11.9k | } |
483 | | |
484 | 535 | case GEN_RID: { |
485 | 535 | ASN1_OBJECT *obj; |
486 | 535 | if (!(obj = OBJ_txt2obj(value, 0))) { |
487 | 4 | OPENSSL_PUT_ERROR(X509V3, X509V3_R_BAD_OBJECT); |
488 | 4 | ERR_add_error_data(2, "value=", value); |
489 | 4 | goto err; |
490 | 4 | } |
491 | 531 | gen->type = GEN_RID; |
492 | 531 | gen->d.rid = obj; |
493 | 531 | break; |
494 | 535 | } |
495 | | |
496 | 7.46k | case GEN_IPADD: |
497 | 7.46k | gen->type = GEN_IPADD; |
498 | 7.46k | if (is_nc) { |
499 | 496 | gen->d.ip = a2i_IPADDRESS_NC(value); |
500 | 6.96k | } else { |
501 | 6.96k | gen->d.ip = a2i_IPADDRESS(value); |
502 | 6.96k | } |
503 | 7.46k | if (gen->d.ip == nullptr) { |
504 | 312 | OPENSSL_PUT_ERROR(X509V3, X509V3_R_BAD_IP_ADDRESS); |
505 | 312 | ERR_add_error_data(2, "value=", value); |
506 | 312 | goto err; |
507 | 312 | } |
508 | 7.14k | break; |
509 | | |
510 | 7.14k | case GEN_DIRNAME: |
511 | 6.20k | if (!do_dirname(gen, value, ctx)) { |
512 | 283 | OPENSSL_PUT_ERROR(X509V3, X509V3_R_DIRNAME_ERROR); |
513 | 283 | goto err; |
514 | 283 | } |
515 | 5.91k | break; |
516 | | |
517 | 41.0k | case GEN_OTHERNAME: |
518 | 41.0k | if (!do_othername(gen, value, ctx)) { |
519 | 27 | OPENSSL_PUT_ERROR(X509V3, X509V3_R_OTHERNAME_ERROR); |
520 | 27 | goto err; |
521 | 27 | } |
522 | 41.0k | break; |
523 | 41.0k | default: |
524 | 0 | OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNSUPPORTED_TYPE); |
525 | 0 | goto err; |
526 | 67.2k | } |
527 | | |
528 | 66.6k | return gen; |
529 | | |
530 | 626 | err: |
531 | 626 | if (!out) { |
532 | 596 | GENERAL_NAME_free(gen); |
533 | 596 | } |
534 | 626 | return nullptr; |
535 | 67.2k | } |
536 | | |
537 | | GENERAL_NAME *bssl::v2i_GENERAL_NAME_ex(GENERAL_NAME *out, |
538 | | const X509V3_EXT_METHOD *method, |
539 | | const X509V3_CTX *ctx, |
540 | 67.6k | const CONF_VALUE *cnf, int is_nc) { |
541 | 67.6k | const char *name = cnf->name; |
542 | 67.6k | const char *value = cnf->value; |
543 | 67.6k | if (!value) { |
544 | 169 | OPENSSL_PUT_ERROR(X509V3, X509V3_R_MISSING_VALUE); |
545 | 169 | return nullptr; |
546 | 169 | } |
547 | | |
548 | 67.4k | int type; |
549 | 67.4k | if (x509v3_conf_name_matches(name, "email")) { |
550 | 1.70k | type = GEN_EMAIL; |
551 | 65.7k | } else if (x509v3_conf_name_matches(name, "URI")) { |
552 | 9.19k | type = GEN_URI; |
553 | 56.5k | } else if (x509v3_conf_name_matches(name, "DNS")) { |
554 | 1.06k | type = GEN_DNS; |
555 | 55.4k | } else if (x509v3_conf_name_matches(name, "RID")) { |
556 | 535 | type = GEN_RID; |
557 | 54.9k | } else if (x509v3_conf_name_matches(name, "IP")) { |
558 | 7.46k | type = GEN_IPADD; |
559 | 47.4k | } else if (x509v3_conf_name_matches(name, "dirName")) { |
560 | 6.20k | type = GEN_DIRNAME; |
561 | 41.2k | } else if (x509v3_conf_name_matches(name, "otherName")) { |
562 | 41.0k | type = GEN_OTHERNAME; |
563 | 41.0k | } else { |
564 | 183 | OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNSUPPORTED_OPTION); |
565 | 183 | ERR_add_error_data(2, "name=", name); |
566 | 183 | return nullptr; |
567 | 183 | } |
568 | | |
569 | 67.2k | return a2i_GENERAL_NAME(out, method, ctx, type, value, is_nc); |
570 | 67.4k | } |
571 | | |
572 | | static int do_othername(GENERAL_NAME *gen, const char *value, |
573 | 41.0k | const X509V3_CTX *ctx) { |
574 | 41.0k | const char *semicolon = strchr(value, ';'); |
575 | 41.0k | if (semicolon == nullptr) { |
576 | 3 | return 0; |
577 | 3 | } |
578 | | |
579 | 41.0k | OTHERNAME *name = OTHERNAME_new(); |
580 | 41.0k | if (name == nullptr) { |
581 | 0 | return 0; |
582 | 0 | } |
583 | | |
584 | 41.0k | char *objtmp = OPENSSL_strndup(value, semicolon - value); |
585 | 41.0k | if (objtmp == nullptr) { |
586 | 0 | goto err; |
587 | 0 | } |
588 | 41.0k | ASN1_OBJECT_free(name->type_id); |
589 | 41.0k | name->type_id = OBJ_txt2obj(objtmp, /*dont_search_names=*/0); |
590 | 41.0k | OPENSSL_free(objtmp); |
591 | 41.0k | if (name->type_id == nullptr) { |
592 | 9 | goto err; |
593 | 9 | } |
594 | | |
595 | 41.0k | ASN1_TYPE_free(name->value); |
596 | 41.0k | name->value = ASN1_generate_v3(semicolon + 1, ctx); |
597 | 41.0k | if (name->value == nullptr) { |
598 | 15 | goto err; |
599 | 15 | } |
600 | | |
601 | 41.0k | gen->type = GEN_OTHERNAME; |
602 | 41.0k | gen->d.otherName = name; |
603 | 41.0k | return 1; |
604 | | |
605 | 24 | err: |
606 | 24 | OTHERNAME_free(name); |
607 | 24 | return 0; |
608 | 41.0k | } |
609 | | |
610 | | static int do_dirname(GENERAL_NAME *gen, const char *value, |
611 | 6.20k | const X509V3_CTX *ctx) { |
612 | 6.20k | int ret = 0; |
613 | 6.20k | const STACK_OF(CONF_VALUE) *sk = X509V3_get_section(ctx, value); |
614 | 6.20k | X509_NAME *nm = X509_NAME_new(); |
615 | 6.20k | if (nm == nullptr) { |
616 | 0 | goto err; |
617 | 0 | } |
618 | 6.20k | if (sk == nullptr) { |
619 | 228 | OPENSSL_PUT_ERROR(X509V3, X509V3_R_SECTION_NOT_FOUND); |
620 | 228 | ERR_add_error_data(2, "section=", value); |
621 | 228 | goto err; |
622 | 228 | } |
623 | | // FIXME: should allow other character types... |
624 | 5.97k | if (!X509V3_NAME_from_section(nm, sk, MBSTRING_ASC)) { |
625 | 55 | goto err; |
626 | 55 | } |
627 | 5.91k | gen->type = GEN_DIRNAME; |
628 | 5.91k | gen->d.dirn = nm; |
629 | 5.91k | ret = 1; |
630 | | |
631 | 6.20k | err: |
632 | 6.20k | if (!ret) { |
633 | 283 | X509_NAME_free(nm); |
634 | 283 | } |
635 | 6.20k | return ret; |
636 | 5.91k | } |