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