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