1 /* $OpenBSD: x509_alt.c,v 1.17 2024/07/13 15:08:58 tb Exp $ */
2 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3 * project.
4 */
5 /* ====================================================================
6 * Copyright (c) 1999-2003 The OpenSSL Project. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
18 * distribution.
19 *
20 * 3. All advertising materials mentioning features or use of this
21 * software must display the following acknowledgment:
22 * "This product includes software developed by the OpenSSL Project
23 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24 *
25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26 * endorse or promote products derived from this software without
27 * prior written permission. For written permission, please contact
28 * licensing@OpenSSL.org.
29 *
30 * 5. Products derived from this software may not be called "OpenSSL"
31 * nor may "OpenSSL" appear in their names without prior written
32 * permission of the OpenSSL Project.
33 *
34 * 6. Redistributions of any form whatsoever must retain the following
35 * acknowledgment:
36 * "This product includes software developed by the OpenSSL Project
37 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38 *
39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50 * OF THE POSSIBILITY OF SUCH DAMAGE.
51 * ====================================================================
52 *
53 * This product includes cryptographic software written by Eric Young
54 * (eay@cryptsoft.com). This product includes software written by Tim
55 * Hudson (tjh@cryptsoft.com).
56 *
57 */
58
59 #include <stdio.h>
60 #include <string.h>
61
62 #include <openssl/conf.h>
63 #include <openssl/err.h>
64 #include <openssl/x509v3.h>
65
66 #include "x509_internal.h"
67
68 static GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method,
69 X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval);
70 static GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method,
71 X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval);
72 static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p);
73 static int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens);
74 static int do_othername(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx);
75 static int do_dirname(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx);
76
77 static const X509V3_EXT_METHOD x509v3_ext_subject_alt_name = {
78 .ext_nid = NID_subject_alt_name,
79 .ext_flags = 0,
80 .it = &GENERAL_NAMES_it,
81 .ext_new = NULL,
82 .ext_free = NULL,
83 .d2i = NULL,
84 .i2d = NULL,
85 .i2s = NULL,
86 .s2i = NULL,
87 .i2v = (X509V3_EXT_I2V)i2v_GENERAL_NAMES,
88 .v2i = (X509V3_EXT_V2I)v2i_subject_alt,
89 .i2r = NULL,
90 .r2i = NULL,
91 .usr_data = NULL,
92 };
93
94 const X509V3_EXT_METHOD *
x509v3_ext_method_subject_alt_name(void)95 x509v3_ext_method_subject_alt_name(void)
96 {
97 return &x509v3_ext_subject_alt_name;
98 }
99
100 static const X509V3_EXT_METHOD x509v3_ext_issuer_alt_name = {
101 .ext_nid = NID_issuer_alt_name,
102 .ext_flags = 0,
103 .it = &GENERAL_NAMES_it,
104 .ext_new = NULL,
105 .ext_free = NULL,
106 .d2i = NULL,
107 .i2d = NULL,
108 .i2s = NULL,
109 .s2i = NULL,
110 .i2v = (X509V3_EXT_I2V)i2v_GENERAL_NAMES,
111 .v2i = (X509V3_EXT_V2I)v2i_issuer_alt,
112 .i2r = NULL,
113 .r2i = NULL,
114 .usr_data = NULL,
115 };
116
117 const X509V3_EXT_METHOD *
x509v3_ext_method_issuer_alt_name(void)118 x509v3_ext_method_issuer_alt_name(void)
119 {
120 return &x509v3_ext_issuer_alt_name;
121 }
122
123 static const X509V3_EXT_METHOD x509v3_ext_certificate_issuer = {
124 .ext_nid = NID_certificate_issuer,
125 .ext_flags = 0,
126 .it = &GENERAL_NAMES_it,
127 .ext_new = NULL,
128 .ext_free = NULL,
129 .d2i = NULL,
130 .i2d = NULL,
131 .i2s = NULL,
132 .s2i = NULL,
133 .i2v = (X509V3_EXT_I2V)i2v_GENERAL_NAMES,
134 .v2i = NULL,
135 .i2r = NULL,
136 .r2i = NULL,
137 .usr_data = NULL,
138 };
139
140 const X509V3_EXT_METHOD *
x509v3_ext_method_certificate_issuer(void)141 x509v3_ext_method_certificate_issuer(void)
142 {
143 return &x509v3_ext_certificate_issuer;
144 }
145
STACK_OF(CONF_VALUE)146 STACK_OF(CONF_VALUE) *
147 i2v_GENERAL_NAMES(X509V3_EXT_METHOD *method, GENERAL_NAMES *gens,
148 STACK_OF(CONF_VALUE) *ret)
149 {
150 STACK_OF(CONF_VALUE) *free_ret = NULL;
151 GENERAL_NAME *gen;
152 int i;
153
154 if (ret == NULL) {
155 if ((free_ret = ret = sk_CONF_VALUE_new_null()) == NULL)
156 return NULL;
157 }
158
159 for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
160 if ((gen = sk_GENERAL_NAME_value(gens, i)) == NULL)
161 goto err;
162 if ((ret = i2v_GENERAL_NAME(method, gen, ret)) == NULL)
163 goto err;
164 }
165
166 return ret;
167
168 err:
169 sk_CONF_VALUE_pop_free(free_ret, X509V3_conf_free);
170
171 return NULL;
172 }
173 LCRYPTO_ALIAS(i2v_GENERAL_NAMES);
174
STACK_OF(CONF_VALUE)175 STACK_OF(CONF_VALUE) *
176 i2v_GENERAL_NAME(X509V3_EXT_METHOD *method, GENERAL_NAME *gen,
177 STACK_OF(CONF_VALUE) *ret)
178 {
179 STACK_OF(CONF_VALUE) *free_ret = NULL;
180 unsigned char *p;
181 char oline[256], htmp[5];
182 int i;
183
184 if (ret == NULL) {
185 if ((free_ret = ret = sk_CONF_VALUE_new_null()) == NULL)
186 return NULL;
187 }
188
189 switch (gen->type) {
190 case GEN_OTHERNAME:
191 if (!X509V3_add_value("othername", "<unsupported>", &ret))
192 goto err;
193 break;
194
195 case GEN_X400:
196 if (!X509V3_add_value("X400Name", "<unsupported>", &ret))
197 goto err;
198 break;
199
200 case GEN_EDIPARTY:
201 if (!X509V3_add_value("EdiPartyName", "<unsupported>", &ret))
202 goto err;
203 break;
204
205 case GEN_EMAIL:
206 if (!X509V3_add_value_uchar("email", gen->d.ia5->data, &ret))
207 goto err;
208 break;
209
210 case GEN_DNS:
211 if (!X509V3_add_value_uchar("DNS", gen->d.ia5->data, &ret))
212 goto err;
213 break;
214
215 case GEN_URI:
216 if (!X509V3_add_value_uchar("URI", gen->d.ia5->data, &ret))
217 goto err;
218 break;
219
220 case GEN_DIRNAME:
221 if (X509_NAME_oneline(gen->d.dirn, oline, 256) == NULL)
222 goto err;
223 if (!X509V3_add_value("DirName", oline, &ret))
224 goto err;
225 break;
226
227 case GEN_IPADD: /* XXX */
228 p = gen->d.ip->data;
229 if (gen->d.ip->length == 4)
230 (void) snprintf(oline, sizeof oline,
231 "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
232 else if (gen->d.ip->length == 16) {
233 oline[0] = 0;
234 for (i = 0; i < 8; i++) {
235 (void) snprintf(htmp, sizeof htmp,
236 "%X", p[0] << 8 | p[1]);
237 p += 2;
238 strlcat(oline, htmp, sizeof(oline));
239 if (i != 7)
240 strlcat(oline, ":", sizeof(oline));
241 }
242 } else {
243 if (!X509V3_add_value("IP Address", "<invalid>", &ret))
244 goto err;
245 break;
246 }
247 if (!X509V3_add_value("IP Address", oline, &ret))
248 goto err;
249 break;
250
251 case GEN_RID:
252 if (!i2t_ASN1_OBJECT(oline, 256, gen->d.rid))
253 goto err;
254 if (!X509V3_add_value("Registered ID", oline, &ret))
255 goto err;
256 break;
257 }
258
259 return ret;
260
261 err:
262 sk_CONF_VALUE_pop_free(free_ret, X509V3_conf_free);
263
264 return NULL;
265 }
266 LCRYPTO_ALIAS(i2v_GENERAL_NAME);
267
268 int
GENERAL_NAME_print(BIO * out,GENERAL_NAME * gen)269 GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen)
270 {
271 unsigned char *p;
272 int i;
273
274 switch (gen->type) {
275 case GEN_OTHERNAME:
276 BIO_printf(out, "othername:<unsupported>");
277 break;
278
279 case GEN_X400:
280 BIO_printf(out, "X400Name:<unsupported>");
281 break;
282
283 case GEN_EDIPARTY:
284 /* Maybe fix this: it is supported now */
285 BIO_printf(out, "EdiPartyName:<unsupported>");
286 break;
287
288 case GEN_EMAIL:
289 BIO_printf(out, "email:%.*s", gen->d.ia5->length,
290 gen->d.ia5->data);
291 break;
292
293 case GEN_DNS:
294 BIO_printf(out, "DNS:%.*s", gen->d.ia5->length,
295 gen->d.ia5->data);
296 break;
297
298 case GEN_URI:
299 BIO_printf(out, "URI:%.*s", gen->d.ia5->length,
300 gen->d.ia5->data);
301 break;
302
303 case GEN_DIRNAME:
304 BIO_printf(out, "DirName: ");
305 X509_NAME_print_ex(out, gen->d.dirn, 0, XN_FLAG_ONELINE);
306 break;
307
308 case GEN_IPADD:
309 p = gen->d.ip->data;
310 if (gen->d.ip->length == 4)
311 BIO_printf(out, "IP Address:%d.%d.%d.%d",
312 p[0], p[1], p[2], p[3]);
313 else if (gen->d.ip->length == 16) {
314 BIO_printf(out, "IP Address");
315 for (i = 0; i < 8; i++) {
316 BIO_printf(out, ":%X", p[0] << 8 | p[1]);
317 p += 2;
318 }
319 BIO_puts(out, "\n");
320 } else {
321 BIO_printf(out, "IP Address:<invalid>");
322 break;
323 }
324 break;
325
326 case GEN_RID:
327 BIO_printf(out, "Registered ID");
328 i2a_ASN1_OBJECT(out, gen->d.rid);
329 break;
330 }
331 return 1;
332 }
333 LCRYPTO_ALIAS(GENERAL_NAME_print);
334
335 static GENERAL_NAMES *
v2i_issuer_alt(X509V3_EXT_METHOD * method,X509V3_CTX * ctx,STACK_OF (CONF_VALUE)* nval)336 v2i_issuer_alt(X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
337 STACK_OF(CONF_VALUE) *nval)
338 {
339 GENERAL_NAMES *gens = NULL;
340 CONF_VALUE *cnf;
341 int i;
342
343 if ((gens = sk_GENERAL_NAME_new_null()) == NULL) {
344 X509V3error(ERR_R_MALLOC_FAILURE);
345 return NULL;
346 }
347 for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
348 cnf = sk_CONF_VALUE_value(nval, i);
349 if (name_cmp(cnf->name, "issuer") == 0 && cnf->value != NULL &&
350 strcmp(cnf->value, "copy") == 0) {
351 if (!copy_issuer(ctx, gens))
352 goto err;
353 } else {
354 GENERAL_NAME *gen;
355 if ((gen = v2i_GENERAL_NAME(method, ctx, cnf)) == NULL)
356 goto err;
357 if (sk_GENERAL_NAME_push(gens, gen) == 0) {
358 GENERAL_NAME_free(gen);
359 goto err;
360 }
361 }
362 }
363 return gens;
364
365 err:
366 sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
367 return NULL;
368 }
369
370 /* Append subject altname of issuer to issuer alt name of subject */
371
372 static int
copy_issuer(X509V3_CTX * ctx,GENERAL_NAMES * gens)373 copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens)
374 {
375 GENERAL_NAMES *ialt = NULL;
376 GENERAL_NAME *gen = NULL;
377 X509_EXTENSION *ext;
378 int i;
379 int ret = 0;
380
381 if (ctx && (ctx->flags == CTX_TEST))
382 return 1;
383 if (!ctx || !ctx->issuer_cert) {
384 X509V3error(X509V3_R_NO_ISSUER_DETAILS);
385 goto err;
386 }
387 i = X509_get_ext_by_NID(ctx->issuer_cert, NID_subject_alt_name, -1);
388 if (i < 0)
389 return 1;
390 if (!(ext = X509_get_ext(ctx->issuer_cert, i)) ||
391 !(ialt = X509V3_EXT_d2i(ext))) {
392 X509V3error(X509V3_R_ISSUER_DECODE_ERROR);
393 goto err;
394 }
395
396 for (i = 0; i < sk_GENERAL_NAME_num(ialt); i++) {
397 GENERAL_NAME *val = sk_GENERAL_NAME_value(ialt, i);
398
399 if ((gen = GENERAL_NAME_dup(val)) == NULL)
400 goto err;
401 if (!sk_GENERAL_NAME_push(gens, gen)) {
402 X509V3error(ERR_R_MALLOC_FAILURE);
403 goto err;
404 }
405 gen = NULL;
406 }
407
408 ret = 1;
409
410 err:
411 sk_GENERAL_NAME_pop_free(ialt, GENERAL_NAME_free);
412 GENERAL_NAME_free(gen);
413
414 return ret;
415 }
416
417 static GENERAL_NAMES *
v2i_subject_alt(X509V3_EXT_METHOD * method,X509V3_CTX * ctx,STACK_OF (CONF_VALUE)* nval)418 v2i_subject_alt(X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
419 STACK_OF(CONF_VALUE) *nval)
420 {
421 GENERAL_NAMES *gens = NULL;
422 CONF_VALUE *cnf;
423 int i;
424
425 if (!(gens = sk_GENERAL_NAME_new_null())) {
426 X509V3error(ERR_R_MALLOC_FAILURE);
427 return NULL;
428 }
429 for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
430 cnf = sk_CONF_VALUE_value(nval, i);
431 if (!name_cmp(cnf->name, "email") && cnf->value &&
432 !strcmp(cnf->value, "copy")) {
433 if (!copy_email(ctx, gens, 0))
434 goto err;
435 } else if (!name_cmp(cnf->name, "email") && cnf->value &&
436 !strcmp(cnf->value, "move")) {
437 if (!copy_email(ctx, gens, 1))
438 goto err;
439 } else {
440 GENERAL_NAME *gen;
441 if (!(gen = v2i_GENERAL_NAME(method, ctx, cnf)))
442 goto err;
443 if (sk_GENERAL_NAME_push(gens, gen) == 0) {
444 GENERAL_NAME_free(gen);
445 goto err;
446 }
447 }
448 }
449 return gens;
450
451 err:
452 sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
453 return NULL;
454 }
455
456 /* Copy any email addresses in a certificate or request to
457 * GENERAL_NAMES
458 */
459
460 static int
copy_email(X509V3_CTX * ctx,GENERAL_NAMES * gens,int move_p)461 copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p)
462 {
463 X509_NAME *nm;
464 ASN1_IA5STRING *email = NULL;
465 X509_NAME_ENTRY *ne;
466 GENERAL_NAME *gen = NULL;
467 int i;
468
469 if (ctx != NULL && ctx->flags == CTX_TEST)
470 return 1;
471 if (!ctx || (!ctx->subject_cert && !ctx->subject_req)) {
472 X509V3error(X509V3_R_NO_SUBJECT_DETAILS);
473 goto err;
474 }
475 /* Find the subject name */
476 if (ctx->subject_cert)
477 nm = X509_get_subject_name(ctx->subject_cert);
478 else
479 nm = X509_REQ_get_subject_name(ctx->subject_req);
480
481 /* Now add any email address(es) to STACK */
482 i = -1;
483 while ((i = X509_NAME_get_index_by_NID(nm,
484 NID_pkcs9_emailAddress, i)) >= 0) {
485 ne = X509_NAME_get_entry(nm, i);
486 email = ASN1_STRING_dup(X509_NAME_ENTRY_get_data(ne));
487 if (move_p) {
488 X509_NAME_delete_entry(nm, i);
489 X509_NAME_ENTRY_free(ne);
490 i--;
491 }
492 if (!email || !(gen = GENERAL_NAME_new())) {
493 X509V3error(ERR_R_MALLOC_FAILURE);
494 goto err;
495 }
496 gen->d.ia5 = email;
497 email = NULL;
498 gen->type = GEN_EMAIL;
499 if (!sk_GENERAL_NAME_push(gens, gen)) {
500 X509V3error(ERR_R_MALLOC_FAILURE);
501 goto err;
502 }
503 gen = NULL;
504 }
505
506 return 1;
507
508 err:
509 GENERAL_NAME_free(gen);
510 ASN1_IA5STRING_free(email);
511 return 0;
512 }
513
514 GENERAL_NAMES *
v2i_GENERAL_NAMES(const X509V3_EXT_METHOD * method,X509V3_CTX * ctx,STACK_OF (CONF_VALUE)* nval)515 v2i_GENERAL_NAMES(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
516 STACK_OF(CONF_VALUE) *nval)
517 {
518 GENERAL_NAME *gen;
519 GENERAL_NAMES *gens = NULL;
520 CONF_VALUE *cnf;
521 int i;
522
523 if (!(gens = sk_GENERAL_NAME_new_null())) {
524 X509V3error(ERR_R_MALLOC_FAILURE);
525 return NULL;
526 }
527 for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
528 cnf = sk_CONF_VALUE_value(nval, i);
529 if (!(gen = v2i_GENERAL_NAME(method, ctx, cnf)))
530 goto err;
531 if (sk_GENERAL_NAME_push(gens, gen) == 0) {
532 GENERAL_NAME_free(gen);
533 goto err;
534 }
535 }
536 return gens;
537
538 err:
539 sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
540 return NULL;
541 }
542 LCRYPTO_ALIAS(v2i_GENERAL_NAMES);
543
544 GENERAL_NAME *
v2i_GENERAL_NAME(const X509V3_EXT_METHOD * method,X509V3_CTX * ctx,CONF_VALUE * cnf)545 v2i_GENERAL_NAME(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
546 CONF_VALUE *cnf)
547 {
548 return v2i_GENERAL_NAME_ex(NULL, method, ctx, cnf, 0);
549 }
550 LCRYPTO_ALIAS(v2i_GENERAL_NAME);
551
552 GENERAL_NAME *
a2i_GENERAL_NAME(GENERAL_NAME * out,const X509V3_EXT_METHOD * method,X509V3_CTX * ctx,int gen_type,const char * value,int is_nc)553 a2i_GENERAL_NAME(GENERAL_NAME *out, const X509V3_EXT_METHOD *method,
554 X509V3_CTX *ctx, int gen_type, const char *value, int is_nc)
555 {
556 char is_string = 0;
557 GENERAL_NAME *gen = NULL;
558
559 if (!value) {
560 X509V3error(X509V3_R_MISSING_VALUE);
561 return NULL;
562 }
563
564 if (out)
565 gen = out;
566 else {
567 gen = GENERAL_NAME_new();
568 if (gen == NULL) {
569 X509V3error(ERR_R_MALLOC_FAILURE);
570 return NULL;
571 }
572 }
573
574 switch (gen_type) {
575 case GEN_URI:
576 case GEN_EMAIL:
577 case GEN_DNS:
578 is_string = 1;
579 break;
580
581 case GEN_RID:
582 {
583 ASN1_OBJECT *obj;
584 if (!(obj = OBJ_txt2obj(value, 0))) {
585 X509V3error(X509V3_R_BAD_OBJECT);
586 ERR_asprintf_error_data("value=%s", value);
587 goto err;
588 }
589 gen->d.rid = obj;
590 }
591 break;
592
593 case GEN_IPADD:
594 if (is_nc)
595 gen->d.ip = a2i_IPADDRESS_NC(value);
596 else
597 gen->d.ip = a2i_IPADDRESS(value);
598 if (gen->d.ip == NULL) {
599 X509V3error(X509V3_R_BAD_IP_ADDRESS);
600 ERR_asprintf_error_data("value=%s", value);
601 goto err;
602 }
603 break;
604
605 case GEN_DIRNAME:
606 if (!do_dirname(gen, value, ctx)) {
607 X509V3error(X509V3_R_DIRNAME_ERROR);
608 goto err;
609 }
610 break;
611
612 case GEN_OTHERNAME:
613 if (!do_othername(gen, value, ctx)) {
614 X509V3error(X509V3_R_OTHERNAME_ERROR);
615 goto err;
616 }
617 break;
618
619 default:
620 X509V3error(X509V3_R_UNSUPPORTED_TYPE);
621 goto err;
622 }
623
624 if (is_string) {
625 if (!(gen->d.ia5 = ASN1_IA5STRING_new()) ||
626 !ASN1_STRING_set(gen->d.ia5, value, strlen(value))) {
627 X509V3error(ERR_R_MALLOC_FAILURE);
628 goto err;
629 }
630 }
631
632 gen->type = gen_type;
633
634 return gen;
635
636 err:
637 if (out == NULL)
638 GENERAL_NAME_free(gen);
639 return NULL;
640 }
641 LCRYPTO_ALIAS(a2i_GENERAL_NAME);
642
643 GENERAL_NAME *
v2i_GENERAL_NAME_ex(GENERAL_NAME * out,const X509V3_EXT_METHOD * method,X509V3_CTX * ctx,CONF_VALUE * cnf,int is_nc)644 v2i_GENERAL_NAME_ex(GENERAL_NAME *out, const X509V3_EXT_METHOD *method,
645 X509V3_CTX *ctx, CONF_VALUE *cnf, int is_nc)
646 {
647 uint8_t *bytes = NULL;
648 char *name, *value;
649 GENERAL_NAME *ret;
650 size_t len = 0;
651 int type;
652 CBS cbs;
653
654 name = cnf->name;
655 value = cnf->value;
656
657 if (!value) {
658 X509V3error(X509V3_R_MISSING_VALUE);
659 return NULL;
660 }
661
662 if (!name_cmp(name, "email"))
663 type = GEN_EMAIL;
664 else if (!name_cmp(name, "URI"))
665 type = GEN_URI;
666 else if (!name_cmp(name, "DNS"))
667 type = GEN_DNS;
668 else if (!name_cmp(name, "RID"))
669 type = GEN_RID;
670 else if (!name_cmp(name, "IP"))
671 type = GEN_IPADD;
672 else if (!name_cmp(name, "dirName"))
673 type = GEN_DIRNAME;
674 else if (!name_cmp(name, "otherName"))
675 type = GEN_OTHERNAME;
676 else {
677 X509V3error(X509V3_R_UNSUPPORTED_OPTION);
678 ERR_asprintf_error_data("name=%s", name);
679 return NULL;
680 }
681
682 ret = a2i_GENERAL_NAME(out, method, ctx, type, value, is_nc);
683 if (ret == NULL)
684 return NULL;
685
686 /*
687 * Validate what we have for sanity.
688 */
689
690 if (is_nc) {
691 struct x509_constraints_name *constraints_name = NULL;
692
693 if (!x509_constraints_validate(ret, &constraints_name, NULL)) {
694 X509V3error(X509V3_R_BAD_OBJECT);
695 ERR_asprintf_error_data("name=%s", name);
696 goto err;
697 }
698 x509_constraints_name_free(constraints_name);
699 return ret;
700 }
701
702 type = x509_constraints_general_to_bytes(ret, &bytes, &len);
703 CBS_init(&cbs, bytes, len);
704 switch (type) {
705 case GEN_DNS:
706 if (!x509_constraints_valid_sandns(&cbs)) {
707 X509V3error(X509V3_R_BAD_OBJECT);
708 ERR_asprintf_error_data("name=%s value='%.*s'", name,
709 (int)len, bytes);
710 goto err;
711 }
712 break;
713 case GEN_URI:
714 if (!x509_constraints_uri_host(bytes, len, NULL)) {
715 X509V3error(X509V3_R_BAD_OBJECT);
716 ERR_asprintf_error_data("name=%s value='%.*s'", name,
717 (int)len, bytes);
718 goto err;
719 }
720 break;
721 case GEN_EMAIL:
722 if (!x509_constraints_parse_mailbox(&cbs, NULL)) {
723 X509V3error(X509V3_R_BAD_OBJECT);
724 ERR_asprintf_error_data("name=%s value='%.*s'", name,
725 (int)len, bytes);
726 goto err;
727 }
728 break;
729 case GEN_IPADD:
730 if (len != 4 && len != 16) {
731 X509V3error(X509V3_R_BAD_IP_ADDRESS);
732 ERR_asprintf_error_data("name=%s len=%zu", name, len);
733 goto err;
734 }
735 break;
736 default:
737 break;
738 }
739 return ret;
740 err:
741 if (out == NULL)
742 GENERAL_NAME_free(ret);
743 return NULL;
744 }
745 LCRYPTO_ALIAS(v2i_GENERAL_NAME_ex);
746
747 static int
do_othername(GENERAL_NAME * gen,const char * value,X509V3_CTX * ctx)748 do_othername(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx)
749 {
750 char *objtmp = NULL, *p;
751 int objlen;
752
753 if (!(p = strchr(value, ';')))
754 return 0;
755 if (!(gen->d.otherName = OTHERNAME_new()))
756 return 0;
757 /* Free this up because we will overwrite it.
758 * no need to free type_id because it is static
759 */
760 ASN1_TYPE_free(gen->d.otherName->value);
761 if (!(gen->d.otherName->value = ASN1_generate_v3(p + 1, ctx)))
762 return 0;
763 objlen = p - value;
764 objtmp = malloc(objlen + 1);
765 if (objtmp) {
766 strlcpy(objtmp, value, objlen + 1);
767 gen->d.otherName->type_id = OBJ_txt2obj(objtmp, 0);
768 free(objtmp);
769 } else
770 gen->d.otherName->type_id = NULL;
771 if (!gen->d.otherName->type_id)
772 return 0;
773 return 1;
774 }
775
776 static int
do_dirname(GENERAL_NAME * gen,const char * value,X509V3_CTX * ctx)777 do_dirname(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx)
778 {
779 int ret;
780 STACK_OF(CONF_VALUE) *sk;
781 X509_NAME *nm;
782
783 if (!(nm = X509_NAME_new()))
784 return 0;
785 sk = X509V3_get_section(ctx, value);
786 if (!sk) {
787 X509V3error(X509V3_R_SECTION_NOT_FOUND);
788 ERR_asprintf_error_data("section=%s", value);
789 X509_NAME_free(nm);
790 return 0;
791 }
792 /* FIXME: should allow other character types... */
793 ret = X509V3_NAME_from_section(nm, sk, MBSTRING_ASC);
794 if (!ret)
795 X509_NAME_free(nm);
796 gen->d.dirn = nm;
797 X509V3_section_free(ctx, sk);
798
799 return ret;
800 }
801