xref: /openbsd/lib/libcrypto/x509/x509_alt.c (revision 8b5faa71)
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