xref: /onnv-gate/usr/src/common/openssl/crypto/x509v3/v3_alt.c (revision 2139:6243c3338933)
1 /* v3_alt.c */
2 /* Written by Dr Stephen N Henson (shenson@bigfoot.com) 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 "cryptlib.h"
61 #include <openssl/conf.h>
62 #include <openssl/x509v3.h>
63 
64 static GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval);
65 static GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval);
66 static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p);
67 static int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens);
68 static int do_othername(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx);
69 static int do_dirname(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx);
70 
71 X509V3_EXT_METHOD v3_alt[] = {
72 { NID_subject_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES),
73 0,0,0,0,
74 0,0,
75 (X509V3_EXT_I2V)i2v_GENERAL_NAMES,
76 (X509V3_EXT_V2I)v2i_subject_alt,
77 NULL, NULL, NULL},
78 
79 { NID_issuer_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES),
80 0,0,0,0,
81 0,0,
82 (X509V3_EXT_I2V)i2v_GENERAL_NAMES,
83 (X509V3_EXT_V2I)v2i_issuer_alt,
84 NULL, NULL, NULL},
85 };
86 
STACK_OF(CONF_VALUE)87 STACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES(X509V3_EXT_METHOD *method,
88 		GENERAL_NAMES *gens, STACK_OF(CONF_VALUE) *ret)
89 {
90 	int i;
91 	GENERAL_NAME *gen;
92 	for(i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
93 		gen = sk_GENERAL_NAME_value(gens, i);
94 		ret = i2v_GENERAL_NAME(method, gen, ret);
95 	}
96 	if(!ret) return sk_CONF_VALUE_new_null();
97 	return ret;
98 }
99 
STACK_OF(CONF_VALUE)100 STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method,
101 				GENERAL_NAME *gen, STACK_OF(CONF_VALUE) *ret)
102 {
103 	unsigned char *p;
104 	char oline[256], htmp[5];
105 	int i;
106 	switch (gen->type)
107 	{
108 		case GEN_OTHERNAME:
109 		X509V3_add_value("othername","<unsupported>", &ret);
110 		break;
111 
112 		case GEN_X400:
113 		X509V3_add_value("X400Name","<unsupported>", &ret);
114 		break;
115 
116 		case GEN_EDIPARTY:
117 		X509V3_add_value("EdiPartyName","<unsupported>", &ret);
118 		break;
119 
120 		case GEN_EMAIL:
121 		X509V3_add_value_uchar("email",gen->d.ia5->data, &ret);
122 		break;
123 
124 		case GEN_DNS:
125 		X509V3_add_value_uchar("DNS",gen->d.ia5->data, &ret);
126 		break;
127 
128 		case GEN_URI:
129 		X509V3_add_value_uchar("URI",gen->d.ia5->data, &ret);
130 		break;
131 
132 		case GEN_DIRNAME:
133 		X509_NAME_oneline(gen->d.dirn, oline, 256);
134 		X509V3_add_value("DirName",oline, &ret);
135 		break;
136 
137 		case GEN_IPADD:
138 		p = gen->d.ip->data;
139 		if(gen->d.ip->length == 4)
140 			BIO_snprintf(oline, sizeof oline,
141 				     "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
142 		else if(gen->d.ip->length == 16)
143 			{
144 			oline[0] = 0;
145 			for (i = 0; i < 8; i++)
146 				{
147 				BIO_snprintf(htmp, sizeof htmp,
148 					     "%X", p[0] << 8 | p[1]);
149 				p += 2;
150 				strcat(oline, htmp);
151 				if (i != 7)
152 					strcat(oline, ":");
153 				}
154 			}
155 		else
156 			{
157 			X509V3_add_value("IP Address","<invalid>", &ret);
158 			break;
159 			}
160 		X509V3_add_value("IP Address",oline, &ret);
161 		break;
162 
163 		case GEN_RID:
164 		i2t_ASN1_OBJECT(oline, 256, gen->d.rid);
165 		X509V3_add_value("Registered ID",oline, &ret);
166 		break;
167 	}
168 	return ret;
169 }
170 
GENERAL_NAME_print(BIO * out,GENERAL_NAME * gen)171 int GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen)
172 {
173 	unsigned char *p;
174 	int i;
175 	switch (gen->type)
176 	{
177 		case GEN_OTHERNAME:
178 		BIO_printf(out, "othername:<unsupported>");
179 		break;
180 
181 		case GEN_X400:
182 		BIO_printf(out, "X400Name:<unsupported>");
183 		break;
184 
185 		case GEN_EDIPARTY:
186 		/* Maybe fix this: it is supported now */
187 		BIO_printf(out, "EdiPartyName:<unsupported>");
188 		break;
189 
190 		case GEN_EMAIL:
191 		BIO_printf(out, "email:%s",gen->d.ia5->data);
192 		break;
193 
194 		case GEN_DNS:
195 		BIO_printf(out, "DNS:%s",gen->d.ia5->data);
196 		break;
197 
198 		case GEN_URI:
199 		BIO_printf(out, "URI:%s",gen->d.ia5->data);
200 		break;
201 
202 		case GEN_DIRNAME:
203 		BIO_printf(out, "DirName: ");
204 		X509_NAME_print_ex(out, gen->d.dirn, 0, XN_FLAG_ONELINE);
205 		break;
206 
207 		case GEN_IPADD:
208 		p = gen->d.ip->data;
209 		if(gen->d.ip->length == 4)
210 			BIO_printf(out, "IP Address:%d.%d.%d.%d",
211 						p[0], p[1], p[2], p[3]);
212 		else if(gen->d.ip->length == 16)
213 			{
214 			BIO_printf(out, "IP Address");
215 			for (i = 0; i < 8; i++)
216 				{
217 				BIO_printf(out, ":%X", p[0] << 8 | p[1]);
218 				p += 2;
219 				}
220 			BIO_puts(out, "\n");
221 			}
222 		else
223 			{
224 			BIO_printf(out,"IP Address:<invalid>");
225 			break;
226 			}
227 		break;
228 
229 		case GEN_RID:
230 		BIO_printf(out, "Registered ID");
231 		i2a_ASN1_OBJECT(out, gen->d.rid);
232 		break;
233 	}
234 	return 1;
235 }
236 
v2i_issuer_alt(X509V3_EXT_METHOD * method,X509V3_CTX * ctx,STACK_OF (CONF_VALUE)* nval)237 static GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method,
238 				 X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
239 {
240 	GENERAL_NAMES *gens = NULL;
241 	CONF_VALUE *cnf;
242 	int i;
243 	if(!(gens = sk_GENERAL_NAME_new_null())) {
244 		X509V3err(X509V3_F_V2I_ISSUER_ALT,ERR_R_MALLOC_FAILURE);
245 		return NULL;
246 	}
247 	for(i = 0; i < sk_CONF_VALUE_num(nval); i++) {
248 		cnf = sk_CONF_VALUE_value(nval, i);
249 		if(!name_cmp(cnf->name, "issuer") && cnf->value &&
250 						!strcmp(cnf->value, "copy")) {
251 			if(!copy_issuer(ctx, gens)) goto err;
252 		} else {
253 			GENERAL_NAME *gen;
254 			if(!(gen = v2i_GENERAL_NAME(method, ctx, cnf)))
255 								 goto err;
256 			sk_GENERAL_NAME_push(gens, gen);
257 		}
258 	}
259 	return gens;
260 	err:
261 	sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
262 	return NULL;
263 }
264 
265 /* Append subject altname of issuer to issuer alt name of subject */
266 
copy_issuer(X509V3_CTX * ctx,GENERAL_NAMES * gens)267 static int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens)
268 {
269 	GENERAL_NAMES *ialt;
270 	GENERAL_NAME *gen;
271 	X509_EXTENSION *ext;
272 	int i;
273 	if(ctx && (ctx->flags == CTX_TEST)) return 1;
274 	if(!ctx || !ctx->issuer_cert) {
275 		X509V3err(X509V3_F_COPY_ISSUER,X509V3_R_NO_ISSUER_DETAILS);
276 		goto err;
277 	}
278         i = X509_get_ext_by_NID(ctx->issuer_cert, NID_subject_alt_name, -1);
279 	if(i < 0) return 1;
280         if(!(ext = X509_get_ext(ctx->issuer_cert, i)) ||
281                         !(ialt = X509V3_EXT_d2i(ext)) ) {
282 		X509V3err(X509V3_F_COPY_ISSUER,X509V3_R_ISSUER_DECODE_ERROR);
283 		goto err;
284 	}
285 
286 	for(i = 0; i < sk_GENERAL_NAME_num(ialt); i++) {
287 		gen = sk_GENERAL_NAME_value(ialt, i);
288 		if(!sk_GENERAL_NAME_push(gens, gen)) {
289 			X509V3err(X509V3_F_COPY_ISSUER,ERR_R_MALLOC_FAILURE);
290 			goto err;
291 		}
292 	}
293 	sk_GENERAL_NAME_free(ialt);
294 
295 	return 1;
296 
297 	err:
298 	return 0;
299 
300 }
301 
v2i_subject_alt(X509V3_EXT_METHOD * method,X509V3_CTX * ctx,STACK_OF (CONF_VALUE)* nval)302 static GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method,
303 				 X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
304 {
305 	GENERAL_NAMES *gens = NULL;
306 	CONF_VALUE *cnf;
307 	int i;
308 	if(!(gens = sk_GENERAL_NAME_new_null())) {
309 		X509V3err(X509V3_F_V2I_SUBJECT_ALT,ERR_R_MALLOC_FAILURE);
310 		return NULL;
311 	}
312 	for(i = 0; i < sk_CONF_VALUE_num(nval); i++) {
313 		cnf = sk_CONF_VALUE_value(nval, i);
314 		if(!name_cmp(cnf->name, "email") && cnf->value &&
315 						!strcmp(cnf->value, "copy")) {
316 			if(!copy_email(ctx, gens, 0)) goto err;
317 		} else if(!name_cmp(cnf->name, "email") && cnf->value &&
318 						!strcmp(cnf->value, "move")) {
319 			if(!copy_email(ctx, gens, 1)) goto err;
320 		} else {
321 			GENERAL_NAME *gen;
322 			if(!(gen = v2i_GENERAL_NAME(method, ctx, cnf)))
323 								 goto err;
324 			sk_GENERAL_NAME_push(gens, gen);
325 		}
326 	}
327 	return gens;
328 	err:
329 	sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
330 	return NULL;
331 }
332 
333 /* Copy any email addresses in a certificate or request to
334  * GENERAL_NAMES
335  */
336 
copy_email(X509V3_CTX * ctx,GENERAL_NAMES * gens,int move_p)337 static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p)
338 {
339 	X509_NAME *nm;
340 	ASN1_IA5STRING *email = NULL;
341 	X509_NAME_ENTRY *ne;
342 	GENERAL_NAME *gen = NULL;
343 	int i;
344 	if(ctx != NULL && ctx->flags == CTX_TEST)
345 		return 1;
346 	if(!ctx || (!ctx->subject_cert && !ctx->subject_req)) {
347 		X509V3err(X509V3_F_COPY_EMAIL,X509V3_R_NO_SUBJECT_DETAILS);
348 		goto err;
349 	}
350 	/* Find the subject name */
351 	if(ctx->subject_cert) nm = X509_get_subject_name(ctx->subject_cert);
352 	else nm = X509_REQ_get_subject_name(ctx->subject_req);
353 
354 	/* Now add any email address(es) to STACK */
355 	i = -1;
356 	while((i = X509_NAME_get_index_by_NID(nm,
357 					 NID_pkcs9_emailAddress, i)) >= 0) {
358 		ne = X509_NAME_get_entry(nm, i);
359 		email = M_ASN1_IA5STRING_dup(X509_NAME_ENTRY_get_data(ne));
360                 if (move_p)
361                         {
362                         X509_NAME_delete_entry(nm, i);
363                         i--;
364                         }
365 		if(!email || !(gen = GENERAL_NAME_new())) {
366 			X509V3err(X509V3_F_COPY_EMAIL,ERR_R_MALLOC_FAILURE);
367 			goto err;
368 		}
369 		gen->d.ia5 = email;
370 		email = NULL;
371 		gen->type = GEN_EMAIL;
372 		if(!sk_GENERAL_NAME_push(gens, gen)) {
373 			X509V3err(X509V3_F_COPY_EMAIL,ERR_R_MALLOC_FAILURE);
374 			goto err;
375 		}
376 		gen = NULL;
377 	}
378 
379 
380 	return 1;
381 
382 	err:
383 	GENERAL_NAME_free(gen);
384 	M_ASN1_IA5STRING_free(email);
385 	return 0;
386 
387 }
388 
v2i_GENERAL_NAMES(X509V3_EXT_METHOD * method,X509V3_CTX * ctx,STACK_OF (CONF_VALUE)* nval)389 GENERAL_NAMES *v2i_GENERAL_NAMES(X509V3_EXT_METHOD *method,
390 				X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
391 {
392 	GENERAL_NAME *gen;
393 	GENERAL_NAMES *gens = NULL;
394 	CONF_VALUE *cnf;
395 	int i;
396 	if(!(gens = sk_GENERAL_NAME_new_null())) {
397 		X509V3err(X509V3_F_V2I_GENERAL_NAMES,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(!(gen = v2i_GENERAL_NAME(method, ctx, cnf))) goto err;
403 		sk_GENERAL_NAME_push(gens, gen);
404 	}
405 	return gens;
406 	err:
407 	sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
408 	return NULL;
409 }
410 
v2i_GENERAL_NAME(X509V3_EXT_METHOD * method,X509V3_CTX * ctx,CONF_VALUE * cnf)411 GENERAL_NAME *v2i_GENERAL_NAME(X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
412 							 CONF_VALUE *cnf)
413 	{
414 	return v2i_GENERAL_NAME_ex(NULL, method, ctx, cnf, 0);
415 	}
416 
v2i_GENERAL_NAME_ex(GENERAL_NAME * out,X509V3_EXT_METHOD * method,X509V3_CTX * ctx,CONF_VALUE * cnf,int is_nc)417 GENERAL_NAME *v2i_GENERAL_NAME_ex(GENERAL_NAME *out,
418 				X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
419 						 CONF_VALUE *cnf, int is_nc)
420 	{
421 	char is_string = 0;
422 	int type;
423 	GENERAL_NAME *gen = NULL;
424 
425 	char *name, *value;
426 
427 	name = cnf->name;
428 	value = cnf->value;
429 
430 	if(!value)
431 		{
432 		X509V3err(X509V3_F_V2I_GENERAL_NAME_EX,X509V3_R_MISSING_VALUE);
433 		return NULL;
434 		}
435 
436 	if (out)
437 		gen = out;
438 	else
439 		{
440 		gen = GENERAL_NAME_new();
441 		if(gen == NULL)
442 			{
443 			X509V3err(X509V3_F_V2I_GENERAL_NAME_EX,ERR_R_MALLOC_FAILURE);
444 			return NULL;
445 			}
446 		}
447 
448 	if(!name_cmp(name, "email"))
449 		{
450 		is_string = 1;
451 		type = GEN_EMAIL;
452 		}
453 	else if(!name_cmp(name, "URI"))
454 		{
455 		is_string = 1;
456 		type = GEN_URI;
457 		}
458 	else if(!name_cmp(name, "DNS"))
459 		{
460 		is_string = 1;
461 		type = GEN_DNS;
462 		}
463 	else if(!name_cmp(name, "RID"))
464 		{
465 		ASN1_OBJECT *obj;
466 		if(!(obj = OBJ_txt2obj(value,0)))
467 			{
468 			X509V3err(X509V3_F_V2I_GENERAL_NAME_EX,X509V3_R_BAD_OBJECT);
469 			ERR_add_error_data(2, "value=", value);
470 			goto err;
471 			}
472 		gen->d.rid = obj;
473 		type = GEN_RID;
474 		}
475 	else if(!name_cmp(name, "IP"))
476 		{
477 		if (is_nc)
478 			gen->d.ip = a2i_IPADDRESS_NC(value);
479 		else
480 			gen->d.ip = a2i_IPADDRESS(value);
481 		if(gen->d.ip == NULL)
482 			{
483 			X509V3err(X509V3_F_V2I_GENERAL_NAME_EX,X509V3_R_BAD_IP_ADDRESS);
484 			ERR_add_error_data(2, "value=", value);
485 			goto err;
486 			}
487 		type = GEN_IPADD;
488 		}
489 	else if(!name_cmp(name, "dirName"))
490 		{
491 		type = GEN_DIRNAME;
492 		if (!do_dirname(gen, value, ctx))
493 			{
494 			X509V3err(X509V3_F_V2I_GENERAL_NAME_EX,X509V3_R_DIRNAME_ERROR);
495 			goto err;
496 			}
497 		}
498 	else if(!name_cmp(name, "otherName"))
499 		{
500 		if (!do_othername(gen, value, ctx))
501 			{
502 			X509V3err(X509V3_F_V2I_GENERAL_NAME_EX,X509V3_R_OTHERNAME_ERROR);
503 			goto err;
504 			}
505 		type = GEN_OTHERNAME;
506 		}
507 	else
508 		{
509 		X509V3err(X509V3_F_V2I_GENERAL_NAME_EX,X509V3_R_UNSUPPORTED_OPTION);
510 		ERR_add_error_data(2, "name=", name);
511 		goto err;
512 		}
513 
514 	if(is_string)
515 		{
516 		if(!(gen->d.ia5 = M_ASN1_IA5STRING_new()) ||
517 			      !ASN1_STRING_set(gen->d.ia5, (unsigned char*)value,
518 					       strlen(value)))
519 			{
520 			X509V3err(X509V3_F_V2I_GENERAL_NAME_EX,ERR_R_MALLOC_FAILURE);
521 			goto err;
522 			}
523 		}
524 
525 	gen->type = type;
526 
527 	return gen;
528 
529 	err:
530 	GENERAL_NAME_free(gen);
531 	return NULL;
532 	}
533 
do_othername(GENERAL_NAME * gen,char * value,X509V3_CTX * ctx)534 static int do_othername(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx)
535 	{
536 	char *objtmp = NULL, *p;
537 	int objlen;
538 	if (!(p = strchr(value, ';')))
539 		return 0;
540 	if (!(gen->d.otherName = OTHERNAME_new()))
541 		return 0;
542 	/* Free this up because we will overwrite it.
543 	 * no need to free type_id because it is static
544 	 */
545 	ASN1_TYPE_free(gen->d.otherName->value);
546 	if (!(gen->d.otherName->value = ASN1_generate_v3(p + 1, ctx)))
547 		return 0;
548 	objlen = p - value;
549 	objtmp = OPENSSL_malloc(objlen + 1);
550 	strncpy(objtmp, value, objlen);
551 	objtmp[objlen] = 0;
552 	gen->d.otherName->type_id = OBJ_txt2obj(objtmp, 0);
553 	OPENSSL_free(objtmp);
554 	if (!gen->d.otherName->type_id)
555 		return 0;
556 	return 1;
557 	}
558 
do_dirname(GENERAL_NAME * gen,char * value,X509V3_CTX * ctx)559 static int do_dirname(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx)
560 	{
561 	int ret;
562 	STACK_OF(CONF_VALUE) *sk;
563 	X509_NAME *nm;
564 	if (!(nm = X509_NAME_new()))
565 		return 0;
566 	sk = X509V3_get_section(ctx, value);
567 	if (!sk)
568 		{
569 		X509V3err(X509V3_F_DO_DIRNAME,X509V3_R_SECTION_NOT_FOUND);
570 		ERR_add_error_data(2, "section=", value);
571 		X509_NAME_free(nm);
572 		return 0;
573 		}
574 	/* FIXME: should allow other character types... */
575 	ret = X509V3_NAME_from_section(nm, sk, MBSTRING_ASC);
576 	if (!ret)
577 		X509_NAME_free(nm);
578 	gen->d.dirn = nm;
579 
580 	return ret;
581 	}
582