xref: /openbsd/lib/libcrypto/x509/x509_alt.c (revision 4bdff4be)
1 /* $OpenBSD: x509_alt.c,v 1.16 2023/08/30 00:49:32 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 const X509V3_EXT_METHOD v3_alt[] = {
78 	{
79 		.ext_nid = NID_subject_alt_name,
80 		.ext_flags = 0,
81 		.it = &GENERAL_NAMES_it,
82 		.ext_new = NULL,
83 		.ext_free = NULL,
84 		.d2i = NULL,
85 		.i2d = NULL,
86 		.i2s = NULL,
87 		.s2i = NULL,
88 		.i2v = (X509V3_EXT_I2V)i2v_GENERAL_NAMES,
89 		.v2i = (X509V3_EXT_V2I)v2i_subject_alt,
90 		.i2r = NULL,
91 		.r2i = NULL,
92 		.usr_data = NULL,
93 	},
94 	{
95 		.ext_nid = NID_issuer_alt_name,
96 		.ext_flags = 0,
97 		.it = &GENERAL_NAMES_it,
98 		.ext_new = NULL,
99 		.ext_free = NULL,
100 		.d2i = NULL,
101 		.i2d = NULL,
102 		.i2s = NULL,
103 		.s2i = NULL,
104 		.i2v = (X509V3_EXT_I2V)i2v_GENERAL_NAMES,
105 		.v2i = (X509V3_EXT_V2I)v2i_issuer_alt,
106 		.i2r = NULL,
107 		.r2i = NULL,
108 		.usr_data = NULL,
109 	},
110 	{
111 		.ext_nid = NID_certificate_issuer,
112 		.ext_flags = 0,
113 		.it = &GENERAL_NAMES_it,
114 		.ext_new = NULL,
115 		.ext_free = NULL,
116 		.d2i = NULL,
117 		.i2d = NULL,
118 		.i2s = NULL,
119 		.s2i = NULL,
120 		.i2v = (X509V3_EXT_I2V)i2v_GENERAL_NAMES,
121 		.v2i = NULL,
122 		.i2r = NULL,
123 		.r2i = NULL,
124 		.usr_data = NULL,
125 	},
126 };
127 
128 STACK_OF(CONF_VALUE) *
129 i2v_GENERAL_NAMES(X509V3_EXT_METHOD *method, GENERAL_NAMES *gens,
130     STACK_OF(CONF_VALUE) *ret)
131 {
132 	STACK_OF(CONF_VALUE) *free_ret = NULL;
133 	GENERAL_NAME *gen;
134 	int i;
135 
136 	if (ret == NULL) {
137 		if ((free_ret = ret = sk_CONF_VALUE_new_null()) == NULL)
138 			return NULL;
139 	}
140 
141 	for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
142 		if ((gen = sk_GENERAL_NAME_value(gens, i)) == NULL)
143 			goto err;
144 		if ((ret = i2v_GENERAL_NAME(method, gen, ret)) == NULL)
145 			goto err;
146 	}
147 
148 	return ret;
149 
150  err:
151 	sk_CONF_VALUE_pop_free(free_ret, X509V3_conf_free);
152 
153 	return NULL;
154 }
155 LCRYPTO_ALIAS(i2v_GENERAL_NAMES);
156 
157 STACK_OF(CONF_VALUE) *
158 i2v_GENERAL_NAME(X509V3_EXT_METHOD *method, GENERAL_NAME *gen,
159     STACK_OF(CONF_VALUE) *ret)
160 {
161 	STACK_OF(CONF_VALUE) *free_ret = NULL;
162 	unsigned char *p;
163 	char oline[256], htmp[5];
164 	int i;
165 
166 	if (ret == NULL) {
167 		if ((free_ret = ret = sk_CONF_VALUE_new_null()) == NULL)
168 			return NULL;
169 	}
170 
171 	switch (gen->type) {
172 	case GEN_OTHERNAME:
173 		if (!X509V3_add_value("othername", "<unsupported>", &ret))
174 			goto err;
175 		break;
176 
177 	case GEN_X400:
178 		if (!X509V3_add_value("X400Name", "<unsupported>", &ret))
179 			goto err;
180 		break;
181 
182 	case GEN_EDIPARTY:
183 		if (!X509V3_add_value("EdiPartyName", "<unsupported>", &ret))
184 			goto err;
185 		break;
186 
187 	case GEN_EMAIL:
188 		if (!X509V3_add_value_uchar("email", gen->d.ia5->data, &ret))
189 			goto err;
190 		break;
191 
192 	case GEN_DNS:
193 		if (!X509V3_add_value_uchar("DNS", gen->d.ia5->data, &ret))
194 			goto err;
195 		break;
196 
197 	case GEN_URI:
198 		if (!X509V3_add_value_uchar("URI", gen->d.ia5->data, &ret))
199 			goto err;
200 		break;
201 
202 	case GEN_DIRNAME:
203 		if (X509_NAME_oneline(gen->d.dirn, oline, 256) == NULL)
204 			goto err;
205 		if (!X509V3_add_value("DirName", oline, &ret))
206 			goto err;
207 		break;
208 
209 	case GEN_IPADD: /* XXX */
210 		p = gen->d.ip->data;
211 		if (gen->d.ip->length == 4)
212 			(void) snprintf(oline, sizeof oline,
213 			    "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
214 		else if (gen->d.ip->length == 16) {
215 			oline[0] = 0;
216 			for (i = 0; i < 8; i++) {
217 				(void) snprintf(htmp, sizeof htmp,
218 				    "%X", p[0] << 8 | p[1]);
219 				p += 2;
220 				strlcat(oline, htmp, sizeof(oline));
221 				if (i != 7)
222 					strlcat(oline, ":", sizeof(oline));
223 			}
224 		} else {
225 			if (!X509V3_add_value("IP Address", "<invalid>", &ret))
226 				goto err;
227 			break;
228 		}
229 		if (!X509V3_add_value("IP Address", oline, &ret))
230 			goto err;
231 		break;
232 
233 	case GEN_RID:
234 		if (!i2t_ASN1_OBJECT(oline, 256, gen->d.rid))
235 			goto err;
236 		if (!X509V3_add_value("Registered ID", oline, &ret))
237 			goto err;
238 		break;
239 	}
240 
241 	return ret;
242 
243  err:
244 	sk_CONF_VALUE_pop_free(free_ret, X509V3_conf_free);
245 
246 	return NULL;
247 }
248 LCRYPTO_ALIAS(i2v_GENERAL_NAME);
249 
250 int
251 GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen)
252 {
253 	unsigned char *p;
254 	int i;
255 
256 	switch (gen->type) {
257 	case GEN_OTHERNAME:
258 		BIO_printf(out, "othername:<unsupported>");
259 		break;
260 
261 	case GEN_X400:
262 		BIO_printf(out, "X400Name:<unsupported>");
263 		break;
264 
265 	case GEN_EDIPARTY:
266 		/* Maybe fix this: it is supported now */
267 		BIO_printf(out, "EdiPartyName:<unsupported>");
268 		break;
269 
270 	case GEN_EMAIL:
271 		BIO_printf(out, "email:%.*s", gen->d.ia5->length,
272 		    gen->d.ia5->data);
273 		break;
274 
275 	case GEN_DNS:
276 		BIO_printf(out, "DNS:%.*s", gen->d.ia5->length,
277 		    gen->d.ia5->data);
278 		break;
279 
280 	case GEN_URI:
281 		BIO_printf(out, "URI:%.*s", gen->d.ia5->length,
282 		    gen->d.ia5->data);
283 		break;
284 
285 	case GEN_DIRNAME:
286 		BIO_printf(out, "DirName: ");
287 		X509_NAME_print_ex(out, gen->d.dirn, 0, XN_FLAG_ONELINE);
288 		break;
289 
290 	case GEN_IPADD:
291 		p = gen->d.ip->data;
292 		if (gen->d.ip->length == 4)
293 			BIO_printf(out, "IP Address:%d.%d.%d.%d",
294 			    p[0], p[1], p[2], p[3]);
295 		else if (gen->d.ip->length == 16) {
296 			BIO_printf(out, "IP Address");
297 			for (i = 0; i < 8; i++) {
298 				BIO_printf(out, ":%X", p[0] << 8 | p[1]);
299 				p += 2;
300 			}
301 			BIO_puts(out, "\n");
302 		} else {
303 			BIO_printf(out, "IP Address:<invalid>");
304 			break;
305 		}
306 		break;
307 
308 	case GEN_RID:
309 		BIO_printf(out, "Registered ID");
310 		i2a_ASN1_OBJECT(out, gen->d.rid);
311 		break;
312 	}
313 	return 1;
314 }
315 LCRYPTO_ALIAS(GENERAL_NAME_print);
316 
317 static GENERAL_NAMES *
318 v2i_issuer_alt(X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
319     STACK_OF(CONF_VALUE) *nval)
320 {
321 	GENERAL_NAMES *gens = NULL;
322 	CONF_VALUE *cnf;
323 	int i;
324 
325 	if ((gens = sk_GENERAL_NAME_new_null()) == NULL) {
326 		X509V3error(ERR_R_MALLOC_FAILURE);
327 		return NULL;
328 	}
329 	for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
330 		cnf = sk_CONF_VALUE_value(nval, i);
331 		if (name_cmp(cnf->name, "issuer") == 0 && cnf->value != NULL &&
332 		    strcmp(cnf->value, "copy") == 0) {
333 			if (!copy_issuer(ctx, gens))
334 				goto err;
335 		} else {
336 			GENERAL_NAME *gen;
337 			if ((gen = v2i_GENERAL_NAME(method, ctx, cnf)) == NULL)
338 				goto err;
339 			if (sk_GENERAL_NAME_push(gens, gen) == 0) {
340 				GENERAL_NAME_free(gen);
341 				goto err;
342 			}
343 		}
344 	}
345 	return gens;
346 
347 err:
348 	sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
349 	return NULL;
350 }
351 
352 /* Append subject altname of issuer to issuer alt name of subject */
353 
354 static int
355 copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens)
356 {
357 	GENERAL_NAMES *ialt = NULL;
358 	GENERAL_NAME *gen = NULL;
359 	X509_EXTENSION *ext;
360 	int i;
361 	int ret = 0;
362 
363 	if (ctx && (ctx->flags == CTX_TEST))
364 		return 1;
365 	if (!ctx || !ctx->issuer_cert) {
366 		X509V3error(X509V3_R_NO_ISSUER_DETAILS);
367 		goto err;
368 	}
369 	i = X509_get_ext_by_NID(ctx->issuer_cert, NID_subject_alt_name, -1);
370 	if (i < 0)
371 		return 1;
372 	if (!(ext = X509_get_ext(ctx->issuer_cert, i)) ||
373 	    !(ialt = X509V3_EXT_d2i(ext))) {
374 		X509V3error(X509V3_R_ISSUER_DECODE_ERROR);
375 		goto err;
376 	}
377 
378 	for (i = 0; i < sk_GENERAL_NAME_num(ialt); i++) {
379 		GENERAL_NAME *val = sk_GENERAL_NAME_value(ialt, i);
380 
381 		if ((gen = GENERAL_NAME_dup(val)) == NULL)
382 			goto err;
383 		if (!sk_GENERAL_NAME_push(gens, gen)) {
384 			X509V3error(ERR_R_MALLOC_FAILURE);
385 			goto err;
386 		}
387 		gen = NULL;
388 	}
389 
390 	ret = 1;
391 
392  err:
393 	sk_GENERAL_NAME_pop_free(ialt, GENERAL_NAME_free);
394 	GENERAL_NAME_free(gen);
395 
396 	return ret;
397 }
398 
399 static GENERAL_NAMES *
400 v2i_subject_alt(X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
401     STACK_OF(CONF_VALUE) *nval)
402 {
403 	GENERAL_NAMES *gens = NULL;
404 	CONF_VALUE *cnf;
405 	int i;
406 
407 	if (!(gens = sk_GENERAL_NAME_new_null())) {
408 		X509V3error(ERR_R_MALLOC_FAILURE);
409 		return NULL;
410 	}
411 	for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
412 		cnf = sk_CONF_VALUE_value(nval, i);
413 		if (!name_cmp(cnf->name, "email") && cnf->value &&
414 		    !strcmp(cnf->value, "copy")) {
415 			if (!copy_email(ctx, gens, 0))
416 				goto err;
417 		} else if (!name_cmp(cnf->name, "email") && cnf->value &&
418 		    !strcmp(cnf->value, "move")) {
419 			if (!copy_email(ctx, gens, 1))
420 				goto err;
421 		} else {
422 			GENERAL_NAME *gen;
423 			if (!(gen = v2i_GENERAL_NAME(method, ctx, cnf)))
424 				goto err;
425 			if (sk_GENERAL_NAME_push(gens, gen) == 0) {
426 				GENERAL_NAME_free(gen);
427 				goto err;
428 			}
429 		}
430 	}
431 	return gens;
432 
433 err:
434 	sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
435 	return NULL;
436 }
437 
438 /* Copy any email addresses in a certificate or request to
439  * GENERAL_NAMES
440  */
441 
442 static int
443 copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p)
444 {
445 	X509_NAME *nm;
446 	ASN1_IA5STRING *email = NULL;
447 	X509_NAME_ENTRY *ne;
448 	GENERAL_NAME *gen = NULL;
449 	int i;
450 
451 	if (ctx != NULL && ctx->flags == CTX_TEST)
452 		return 1;
453 	if (!ctx || (!ctx->subject_cert && !ctx->subject_req)) {
454 		X509V3error(X509V3_R_NO_SUBJECT_DETAILS);
455 		goto err;
456 	}
457 	/* Find the subject name */
458 	if (ctx->subject_cert)
459 		nm = X509_get_subject_name(ctx->subject_cert);
460 	else
461 		nm = X509_REQ_get_subject_name(ctx->subject_req);
462 
463 	/* Now add any email address(es) to STACK */
464 	i = -1;
465 	while ((i = X509_NAME_get_index_by_NID(nm,
466 	    NID_pkcs9_emailAddress, i)) >= 0) {
467 		ne = X509_NAME_get_entry(nm, i);
468 		email = ASN1_STRING_dup(X509_NAME_ENTRY_get_data(ne));
469 		if (move_p) {
470 			X509_NAME_delete_entry(nm, i);
471 			X509_NAME_ENTRY_free(ne);
472 			i--;
473 		}
474 		if (!email || !(gen = GENERAL_NAME_new())) {
475 			X509V3error(ERR_R_MALLOC_FAILURE);
476 			goto err;
477 		}
478 		gen->d.ia5 = email;
479 		email = NULL;
480 		gen->type = GEN_EMAIL;
481 		if (!sk_GENERAL_NAME_push(gens, gen)) {
482 			X509V3error(ERR_R_MALLOC_FAILURE);
483 			goto err;
484 		}
485 		gen = NULL;
486 	}
487 
488 	return 1;
489 
490 err:
491 	GENERAL_NAME_free(gen);
492 	ASN1_IA5STRING_free(email);
493 	return 0;
494 }
495 
496 GENERAL_NAMES *
497 v2i_GENERAL_NAMES(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
498     STACK_OF(CONF_VALUE) *nval)
499 {
500 	GENERAL_NAME *gen;
501 	GENERAL_NAMES *gens = NULL;
502 	CONF_VALUE *cnf;
503 	int i;
504 
505 	if (!(gens = sk_GENERAL_NAME_new_null())) {
506 		X509V3error(ERR_R_MALLOC_FAILURE);
507 		return NULL;
508 	}
509 	for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
510 		cnf = sk_CONF_VALUE_value(nval, i);
511 		if (!(gen = v2i_GENERAL_NAME(method, ctx, cnf)))
512 			goto err;
513 		if (sk_GENERAL_NAME_push(gens, gen) == 0) {
514 			GENERAL_NAME_free(gen);
515 			goto err;
516 		}
517 	}
518 	return gens;
519 
520 err:
521 	sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
522 	return NULL;
523 }
524 LCRYPTO_ALIAS(v2i_GENERAL_NAMES);
525 
526 GENERAL_NAME *
527 v2i_GENERAL_NAME(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
528     CONF_VALUE *cnf)
529 {
530 	return v2i_GENERAL_NAME_ex(NULL, method, ctx, cnf, 0);
531 }
532 LCRYPTO_ALIAS(v2i_GENERAL_NAME);
533 
534 GENERAL_NAME *
535 a2i_GENERAL_NAME(GENERAL_NAME *out, const X509V3_EXT_METHOD *method,
536     X509V3_CTX *ctx, int gen_type, const char *value, int is_nc)
537 {
538 	char is_string = 0;
539 	GENERAL_NAME *gen = NULL;
540 
541 	if (!value) {
542 		X509V3error(X509V3_R_MISSING_VALUE);
543 		return NULL;
544 	}
545 
546 	if (out)
547 		gen = out;
548 	else {
549 		gen = GENERAL_NAME_new();
550 		if (gen == NULL) {
551 			X509V3error(ERR_R_MALLOC_FAILURE);
552 			return NULL;
553 		}
554 	}
555 
556 	switch (gen_type) {
557 	case GEN_URI:
558 	case GEN_EMAIL:
559 	case GEN_DNS:
560 		is_string = 1;
561 		break;
562 
563 	case GEN_RID:
564 		{
565 			ASN1_OBJECT *obj;
566 			if (!(obj = OBJ_txt2obj(value, 0))) {
567 				X509V3error(X509V3_R_BAD_OBJECT);
568 				ERR_asprintf_error_data("value=%s", value);
569 				goto err;
570 			}
571 			gen->d.rid = obj;
572 		}
573 		break;
574 
575 	case GEN_IPADD:
576 		if (is_nc)
577 			gen->d.ip = a2i_IPADDRESS_NC(value);
578 		else
579 			gen->d.ip = a2i_IPADDRESS(value);
580 		if (gen->d.ip == NULL) {
581 			X509V3error(X509V3_R_BAD_IP_ADDRESS);
582 			ERR_asprintf_error_data("value=%s", value);
583 			goto err;
584 		}
585 		break;
586 
587 	case GEN_DIRNAME:
588 		if (!do_dirname(gen, value, ctx)) {
589 			X509V3error(X509V3_R_DIRNAME_ERROR);
590 			goto err;
591 		}
592 		break;
593 
594 	case GEN_OTHERNAME:
595 		if (!do_othername(gen, value, ctx)) {
596 			X509V3error(X509V3_R_OTHERNAME_ERROR);
597 			goto err;
598 		}
599 		break;
600 
601 	default:
602 		X509V3error(X509V3_R_UNSUPPORTED_TYPE);
603 		goto err;
604 	}
605 
606 	if (is_string) {
607 		if (!(gen->d.ia5 = ASN1_IA5STRING_new()) ||
608 		    !ASN1_STRING_set(gen->d.ia5, value, strlen(value))) {
609 			X509V3error(ERR_R_MALLOC_FAILURE);
610 			goto err;
611 		}
612 	}
613 
614 	gen->type = gen_type;
615 
616 	return gen;
617 
618 err:
619 	if (out == NULL)
620 		GENERAL_NAME_free(gen);
621 	return NULL;
622 }
623 LCRYPTO_ALIAS(a2i_GENERAL_NAME);
624 
625 GENERAL_NAME *
626 v2i_GENERAL_NAME_ex(GENERAL_NAME *out, const X509V3_EXT_METHOD *method,
627     X509V3_CTX *ctx, CONF_VALUE *cnf, int is_nc)
628 {
629 	uint8_t *bytes = NULL;
630 	char *name, *value;
631 	GENERAL_NAME *ret;
632 	size_t len = 0;
633 	int type;
634 	CBS cbs;
635 
636 	name = cnf->name;
637 	value = cnf->value;
638 
639 	if (!value) {
640 		X509V3error(X509V3_R_MISSING_VALUE);
641 		return NULL;
642 	}
643 
644 	if (!name_cmp(name, "email"))
645 		type = GEN_EMAIL;
646 	else if (!name_cmp(name, "URI"))
647 		type = GEN_URI;
648 	else if (!name_cmp(name, "DNS"))
649 		type = GEN_DNS;
650 	else if (!name_cmp(name, "RID"))
651 		type = GEN_RID;
652 	else if (!name_cmp(name, "IP"))
653 		type = GEN_IPADD;
654 	else if (!name_cmp(name, "dirName"))
655 		type = GEN_DIRNAME;
656 	else if (!name_cmp(name, "otherName"))
657 		type = GEN_OTHERNAME;
658 	else {
659 		X509V3error(X509V3_R_UNSUPPORTED_OPTION);
660 		ERR_asprintf_error_data("name=%s", name);
661 		return NULL;
662 	}
663 
664 	ret = a2i_GENERAL_NAME(out, method, ctx, type, value, is_nc);
665 	if (ret == NULL)
666 		return NULL;
667 
668 	/*
669 	 * Validate what we have for sanity.
670 	 */
671 
672 	if (is_nc) {
673 		struct x509_constraints_name *constraints_name = NULL;
674 
675 		if (!x509_constraints_validate(ret, &constraints_name, NULL)) {
676 			X509V3error(X509V3_R_BAD_OBJECT);
677 			ERR_asprintf_error_data("name=%s", name);
678 			goto err;
679 		}
680 		x509_constraints_name_free(constraints_name);
681 		return ret;
682 	}
683 
684 	type = x509_constraints_general_to_bytes(ret, &bytes, &len);
685 	CBS_init(&cbs, bytes, len);
686 	switch (type) {
687 	case GEN_DNS:
688 		if (!x509_constraints_valid_sandns(&cbs)) {
689 			X509V3error(X509V3_R_BAD_OBJECT);
690 			ERR_asprintf_error_data("name=%s value='%.*s'", name,
691 			    (int)len, bytes);
692 			goto err;
693 		}
694 		break;
695 	case GEN_URI:
696 		if (!x509_constraints_uri_host(bytes, len, NULL)) {
697 			X509V3error(X509V3_R_BAD_OBJECT);
698 			ERR_asprintf_error_data("name=%s value='%.*s'", name,
699 			    (int)len, bytes);
700 			goto err;
701 		}
702 		break;
703 	case GEN_EMAIL:
704 		if (!x509_constraints_parse_mailbox(&cbs, NULL)) {
705 			X509V3error(X509V3_R_BAD_OBJECT);
706 			ERR_asprintf_error_data("name=%s value='%.*s'", name,
707 			    (int)len, bytes);
708 			goto err;
709 		}
710 		break;
711 	case GEN_IPADD:
712 		if (len != 4 && len != 16) {
713 			X509V3error(X509V3_R_BAD_IP_ADDRESS);
714 			ERR_asprintf_error_data("name=%s len=%zu", name, len);
715 			goto err;
716 		}
717 		break;
718 	default:
719 		break;
720 	}
721 	return ret;
722  err:
723 	if (out == NULL)
724 		GENERAL_NAME_free(ret);
725 	return NULL;
726 }
727 LCRYPTO_ALIAS(v2i_GENERAL_NAME_ex);
728 
729 static int
730 do_othername(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx)
731 {
732 	char *objtmp = NULL, *p;
733 	int objlen;
734 
735 	if (!(p = strchr(value, ';')))
736 		return 0;
737 	if (!(gen->d.otherName = OTHERNAME_new()))
738 		return 0;
739 	/* Free this up because we will overwrite it.
740 	 * no need to free type_id because it is static
741 	 */
742 	ASN1_TYPE_free(gen->d.otherName->value);
743 	if (!(gen->d.otherName->value = ASN1_generate_v3(p + 1, ctx)))
744 		return 0;
745 	objlen = p - value;
746 	objtmp = malloc(objlen + 1);
747 	if (objtmp) {
748 		strlcpy(objtmp, value, objlen + 1);
749 		gen->d.otherName->type_id = OBJ_txt2obj(objtmp, 0);
750 		free(objtmp);
751 	} else
752 		gen->d.otherName->type_id = NULL;
753 	if (!gen->d.otherName->type_id)
754 		return 0;
755 	return 1;
756 }
757 
758 static int
759 do_dirname(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx)
760 {
761 	int ret;
762 	STACK_OF(CONF_VALUE) *sk;
763 	X509_NAME *nm;
764 
765 	if (!(nm = X509_NAME_new()))
766 		return 0;
767 	sk = X509V3_get_section(ctx, value);
768 	if (!sk) {
769 		X509V3error(X509V3_R_SECTION_NOT_FOUND);
770 		ERR_asprintf_error_data("section=%s", value);
771 		X509_NAME_free(nm);
772 		return 0;
773 	}
774 	/* FIXME: should allow other character types... */
775 	ret = X509V3_NAME_from_section(nm, sk, MBSTRING_ASC);
776 	if (!ret)
777 		X509_NAME_free(nm);
778 	gen->d.dirn = nm;
779 	X509V3_section_free(ctx, sk);
780 
781 	return ret;
782 }
783