Home | History | Annotate | Download | only in x509v3
      1 /* v3_alt.c */
      2 /* Written by Dr Stephen N Henson (steve (at) 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 (at) 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 (at) cryptsoft.com).  This product includes software written by Tim
     55  * Hudson (tjh (at) 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 const 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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 			X509_NAME_ENTRY_free(ne);
    364                         i--;
    365                         }
    366 		if(!email || !(gen = GENERAL_NAME_new())) {
    367 			X509V3err(X509V3_F_COPY_EMAIL,ERR_R_MALLOC_FAILURE);
    368 			goto err;
    369 		}
    370 		gen->d.ia5 = email;
    371 		email = NULL;
    372 		gen->type = GEN_EMAIL;
    373 		if(!sk_GENERAL_NAME_push(gens, gen)) {
    374 			X509V3err(X509V3_F_COPY_EMAIL,ERR_R_MALLOC_FAILURE);
    375 			goto err;
    376 		}
    377 		gen = NULL;
    378 	}
    379 
    380 
    381 	return 1;
    382 
    383 	err:
    384 	GENERAL_NAME_free(gen);
    385 	M_ASN1_IA5STRING_free(email);
    386 	return 0;
    387 
    388 }
    389 
    390 GENERAL_NAMES *v2i_GENERAL_NAMES(X509V3_EXT_METHOD *method,
    391 				X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
    392 {
    393 	GENERAL_NAME *gen;
    394 	GENERAL_NAMES *gens = NULL;
    395 	CONF_VALUE *cnf;
    396 	int i;
    397 	if(!(gens = sk_GENERAL_NAME_new_null())) {
    398 		X509V3err(X509V3_F_V2I_GENERAL_NAMES,ERR_R_MALLOC_FAILURE);
    399 		return NULL;
    400 	}
    401 	for(i = 0; i < sk_CONF_VALUE_num(nval); i++) {
    402 		cnf = sk_CONF_VALUE_value(nval, i);
    403 		if(!(gen = v2i_GENERAL_NAME(method, ctx, cnf))) goto err;
    404 		sk_GENERAL_NAME_push(gens, gen);
    405 	}
    406 	return gens;
    407 	err:
    408 	sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
    409 	return NULL;
    410 }
    411 
    412 GENERAL_NAME *v2i_GENERAL_NAME(X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
    413 							 CONF_VALUE *cnf)
    414 	{
    415 	return v2i_GENERAL_NAME_ex(NULL, method, ctx, cnf, 0);
    416 	}
    417 
    418 GENERAL_NAME *v2i_GENERAL_NAME_ex(GENERAL_NAME *out,
    419 				X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
    420 						 CONF_VALUE *cnf, int is_nc)
    421 	{
    422 	char is_string = 0;
    423 	int type;
    424 	GENERAL_NAME *gen = NULL;
    425 
    426 	char *name, *value;
    427 
    428 	name = cnf->name;
    429 	value = cnf->value;
    430 
    431 	if(!value)
    432 		{
    433 		X509V3err(X509V3_F_V2I_GENERAL_NAME_EX,X509V3_R_MISSING_VALUE);
    434 		return NULL;
    435 		}
    436 
    437 	if (out)
    438 		gen = out;
    439 	else
    440 		{
    441 		gen = GENERAL_NAME_new();
    442 		if(gen == NULL)
    443 			{
    444 			X509V3err(X509V3_F_V2I_GENERAL_NAME_EX,ERR_R_MALLOC_FAILURE);
    445 			return NULL;
    446 			}
    447 		}
    448 
    449 	if(!name_cmp(name, "email"))
    450 		{
    451 		is_string = 1;
    452 		type = GEN_EMAIL;
    453 		}
    454 	else if(!name_cmp(name, "URI"))
    455 		{
    456 		is_string = 1;
    457 		type = GEN_URI;
    458 		}
    459 	else if(!name_cmp(name, "DNS"))
    460 		{
    461 		is_string = 1;
    462 		type = GEN_DNS;
    463 		}
    464 	else if(!name_cmp(name, "RID"))
    465 		{
    466 		ASN1_OBJECT *obj;
    467 		if(!(obj = OBJ_txt2obj(value,0)))
    468 			{
    469 			X509V3err(X509V3_F_V2I_GENERAL_NAME_EX,X509V3_R_BAD_OBJECT);
    470 			ERR_add_error_data(2, "value=", value);
    471 			goto err;
    472 			}
    473 		gen->d.rid = obj;
    474 		type = GEN_RID;
    475 		}
    476 	else if(!name_cmp(name, "IP"))
    477 		{
    478 		if (is_nc)
    479 			gen->d.ip = a2i_IPADDRESS_NC(value);
    480 		else
    481 			gen->d.ip = a2i_IPADDRESS(value);
    482 		if(gen->d.ip == NULL)
    483 			{
    484 			X509V3err(X509V3_F_V2I_GENERAL_NAME_EX,X509V3_R_BAD_IP_ADDRESS);
    485 			ERR_add_error_data(2, "value=", value);
    486 			goto err;
    487 			}
    488 		type = GEN_IPADD;
    489 		}
    490 	else if(!name_cmp(name, "dirName"))
    491 		{
    492 		type = GEN_DIRNAME;
    493 		if (!do_dirname(gen, value, ctx))
    494 			{
    495 			X509V3err(X509V3_F_V2I_GENERAL_NAME_EX,X509V3_R_DIRNAME_ERROR);
    496 			goto err;
    497 			}
    498 		}
    499 	else if(!name_cmp(name, "otherName"))
    500 		{
    501 		if (!do_othername(gen, value, ctx))
    502 			{
    503 			X509V3err(X509V3_F_V2I_GENERAL_NAME_EX,X509V3_R_OTHERNAME_ERROR);
    504 			goto err;
    505 			}
    506 		type = GEN_OTHERNAME;
    507 		}
    508 	else
    509 		{
    510 		X509V3err(X509V3_F_V2I_GENERAL_NAME_EX,X509V3_R_UNSUPPORTED_OPTION);
    511 		ERR_add_error_data(2, "name=", name);
    512 		goto err;
    513 		}
    514 
    515 	if(is_string)
    516 		{
    517 		if(!(gen->d.ia5 = M_ASN1_IA5STRING_new()) ||
    518 			      !ASN1_STRING_set(gen->d.ia5, (unsigned char*)value,
    519 					       strlen(value)))
    520 			{
    521 			X509V3err(X509V3_F_V2I_GENERAL_NAME_EX,ERR_R_MALLOC_FAILURE);
    522 			goto err;
    523 			}
    524 		}
    525 
    526 	gen->type = type;
    527 
    528 	return gen;
    529 
    530 	err:
    531 	if (!out)
    532 		GENERAL_NAME_free(gen);
    533 	return NULL;
    534 	}
    535 
    536 static int do_othername(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx)
    537 	{
    538 	char *objtmp = NULL, *p;
    539 	int objlen;
    540 	if (!(p = strchr(value, ';')))
    541 		return 0;
    542 	if (!(gen->d.otherName = OTHERNAME_new()))
    543 		return 0;
    544 	/* Free this up because we will overwrite it.
    545 	 * no need to free type_id because it is static
    546 	 */
    547 	ASN1_TYPE_free(gen->d.otherName->value);
    548 	if (!(gen->d.otherName->value = ASN1_generate_v3(p + 1, ctx)))
    549 		return 0;
    550 	objlen = p - value;
    551 	objtmp = OPENSSL_malloc(objlen + 1);
    552 	strncpy(objtmp, value, objlen);
    553 	objtmp[objlen] = 0;
    554 	gen->d.otherName->type_id = OBJ_txt2obj(objtmp, 0);
    555 	OPENSSL_free(objtmp);
    556 	if (!gen->d.otherName->type_id)
    557 		return 0;
    558 	return 1;
    559 	}
    560 
    561 static int do_dirname(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx)
    562 	{
    563 	int ret;
    564 	STACK_OF(CONF_VALUE) *sk;
    565 	X509_NAME *nm;
    566 	if (!(nm = X509_NAME_new()))
    567 		return 0;
    568 	sk = X509V3_get_section(ctx, value);
    569 	if (!sk)
    570 		{
    571 		X509V3err(X509V3_F_DO_DIRNAME,X509V3_R_SECTION_NOT_FOUND);
    572 		ERR_add_error_data(2, "section=", value);
    573 		X509_NAME_free(nm);
    574 		return 0;
    575 		}
    576 	/* FIXME: should allow other character types... */
    577 	ret = X509V3_NAME_from_section(nm, sk, MBSTRING_ASC);
    578 	if (!ret)
    579 		X509_NAME_free(nm);
    580 	gen->d.dirn = nm;
    581 
    582 	X509V3_section_free(ctx, sk);
    583 
    584 	return ret;
    585 	}
    586