v3_alt.c revision 167612
155714Skris/* v3_alt.c */
255714Skris/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
3160814Ssimon * project.
455714Skris */
555714Skris/* ====================================================================
6160814Ssimon * Copyright (c) 1999-2003 The OpenSSL Project.  All rights reserved.
755714Skris *
855714Skris * Redistribution and use in source and binary forms, with or without
955714Skris * modification, are permitted provided that the following conditions
1055714Skris * are met:
1155714Skris *
1255714Skris * 1. Redistributions of source code must retain the above copyright
1355714Skris *    notice, this list of conditions and the following disclaimer.
1455714Skris *
1555714Skris * 2. Redistributions in binary form must reproduce the above copyright
1655714Skris *    notice, this list of conditions and the following disclaimer in
1755714Skris *    the documentation and/or other materials provided with the
1855714Skris *    distribution.
1955714Skris *
2055714Skris * 3. All advertising materials mentioning features or use of this
2155714Skris *    software must display the following acknowledgment:
2255714Skris *    "This product includes software developed by the OpenSSL Project
2355714Skris *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
2455714Skris *
2555714Skris * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
2655714Skris *    endorse or promote products derived from this software without
2755714Skris *    prior written permission. For written permission, please contact
2855714Skris *    licensing@OpenSSL.org.
2955714Skris *
3055714Skris * 5. Products derived from this software may not be called "OpenSSL"
3155714Skris *    nor may "OpenSSL" appear in their names without prior written
3255714Skris *    permission of the OpenSSL Project.
3355714Skris *
3455714Skris * 6. Redistributions of any form whatsoever must retain the following
3555714Skris *    acknowledgment:
3655714Skris *    "This product includes software developed by the OpenSSL Project
3755714Skris *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
3855714Skris *
3955714Skris * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
4055714Skris * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4155714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
4255714Skris * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
4355714Skris * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
4455714Skris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
4555714Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
4655714Skris * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4755714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
4855714Skris * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
4955714Skris * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
5055714Skris * OF THE POSSIBILITY OF SUCH DAMAGE.
5155714Skris * ====================================================================
5255714Skris *
5355714Skris * This product includes cryptographic software written by Eric Young
5455714Skris * (eay@cryptsoft.com).  This product includes software written by Tim
5555714Skris * Hudson (tjh@cryptsoft.com).
5655714Skris *
5755714Skris */
5855714Skris
5955714Skris#include <stdio.h>
6055714Skris#include "cryptlib.h"
6155714Skris#include <openssl/conf.h>
6255714Skris#include <openssl/x509v3.h>
6355714Skris
64109998Smarkmstatic GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval);
65109998Smarkmstatic GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval);
66109998Smarkmstatic int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p);
67109998Smarkmstatic int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens);
68160814Ssimonstatic int do_othername(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx);
69160814Ssimonstatic int do_dirname(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx);
70160814Ssimon
71167612Ssimonconst X509V3_EXT_METHOD v3_alt[] = {
72109998Smarkm{ NID_subject_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES),
73109998Smarkm0,0,0,0,
74109998Smarkm0,0,
7555714Skris(X509V3_EXT_I2V)i2v_GENERAL_NAMES,
7655714Skris(X509V3_EXT_V2I)v2i_subject_alt,
7755714SkrisNULL, NULL, NULL},
78109998Smarkm
79109998Smarkm{ NID_issuer_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES),
80109998Smarkm0,0,0,0,
81109998Smarkm0,0,
8255714Skris(X509V3_EXT_I2V)i2v_GENERAL_NAMES,
8355714Skris(X509V3_EXT_V2I)v2i_issuer_alt,
8455714SkrisNULL, NULL, NULL},
8555714Skris};
8655714Skris
8755714SkrisSTACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES(X509V3_EXT_METHOD *method,
88109998Smarkm		GENERAL_NAMES *gens, STACK_OF(CONF_VALUE) *ret)
8955714Skris{
9055714Skris	int i;
9155714Skris	GENERAL_NAME *gen;
9255714Skris	for(i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
9355714Skris		gen = sk_GENERAL_NAME_value(gens, i);
9455714Skris		ret = i2v_GENERAL_NAME(method, gen, ret);
9555714Skris	}
9655714Skris	if(!ret) return sk_CONF_VALUE_new_null();
9755714Skris	return ret;
9855714Skris}
9955714Skris
10055714SkrisSTACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method,
10155714Skris				GENERAL_NAME *gen, STACK_OF(CONF_VALUE) *ret)
10255714Skris{
103109998Smarkm	unsigned char *p;
104160814Ssimon	char oline[256], htmp[5];
105160814Ssimon	int i;
10655714Skris	switch (gen->type)
10755714Skris	{
10855714Skris		case GEN_OTHERNAME:
10955714Skris		X509V3_add_value("othername","<unsupported>", &ret);
11055714Skris		break;
11155714Skris
11255714Skris		case GEN_X400:
11355714Skris		X509V3_add_value("X400Name","<unsupported>", &ret);
11455714Skris		break;
11555714Skris
11655714Skris		case GEN_EDIPARTY:
11755714Skris		X509V3_add_value("EdiPartyName","<unsupported>", &ret);
11855714Skris		break;
11955714Skris
12055714Skris		case GEN_EMAIL:
12155714Skris		X509V3_add_value_uchar("email",gen->d.ia5->data, &ret);
12255714Skris		break;
12355714Skris
12455714Skris		case GEN_DNS:
12555714Skris		X509V3_add_value_uchar("DNS",gen->d.ia5->data, &ret);
12655714Skris		break;
12755714Skris
12855714Skris		case GEN_URI:
12955714Skris		X509V3_add_value_uchar("URI",gen->d.ia5->data, &ret);
13055714Skris		break;
13155714Skris
13255714Skris		case GEN_DIRNAME:
13355714Skris		X509_NAME_oneline(gen->d.dirn, oline, 256);
13455714Skris		X509V3_add_value("DirName",oline, &ret);
13555714Skris		break;
13655714Skris
13755714Skris		case GEN_IPADD:
13855714Skris		p = gen->d.ip->data;
139160814Ssimon		if(gen->d.ip->length == 4)
140160814Ssimon			BIO_snprintf(oline, sizeof oline,
141160814Ssimon				     "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
142160814Ssimon		else if(gen->d.ip->length == 16)
143160814Ssimon			{
144160814Ssimon			oline[0] = 0;
145160814Ssimon			for (i = 0; i < 8; i++)
146160814Ssimon				{
147160814Ssimon				BIO_snprintf(htmp, sizeof htmp,
148160814Ssimon					     "%X", p[0] << 8 | p[1]);
149160814Ssimon				p += 2;
150160814Ssimon				strcat(oline, htmp);
151160814Ssimon				if (i != 7)
152160814Ssimon					strcat(oline, ":");
153160814Ssimon				}
154160814Ssimon			}
155160814Ssimon		else
156160814Ssimon			{
15755714Skris			X509V3_add_value("IP Address","<invalid>", &ret);
15855714Skris			break;
159160814Ssimon			}
16055714Skris		X509V3_add_value("IP Address",oline, &ret);
16155714Skris		break;
16255714Skris
16355714Skris		case GEN_RID:
16455714Skris		i2t_ASN1_OBJECT(oline, 256, gen->d.rid);
16555714Skris		X509V3_add_value("Registered ID",oline, &ret);
16655714Skris		break;
16755714Skris	}
16855714Skris	return ret;
16955714Skris}
17055714Skris
171109998Smarkmint GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen)
172109998Smarkm{
173109998Smarkm	unsigned char *p;
174160814Ssimon	int i;
175109998Smarkm	switch (gen->type)
176109998Smarkm	{
177109998Smarkm		case GEN_OTHERNAME:
178109998Smarkm		BIO_printf(out, "othername:<unsupported>");
179109998Smarkm		break;
180109998Smarkm
181109998Smarkm		case GEN_X400:
182109998Smarkm		BIO_printf(out, "X400Name:<unsupported>");
183109998Smarkm		break;
184109998Smarkm
185109998Smarkm		case GEN_EDIPARTY:
186109998Smarkm		/* Maybe fix this: it is supported now */
187109998Smarkm		BIO_printf(out, "EdiPartyName:<unsupported>");
188109998Smarkm		break;
189109998Smarkm
190109998Smarkm		case GEN_EMAIL:
191109998Smarkm		BIO_printf(out, "email:%s",gen->d.ia5->data);
192109998Smarkm		break;
193109998Smarkm
194109998Smarkm		case GEN_DNS:
195109998Smarkm		BIO_printf(out, "DNS:%s",gen->d.ia5->data);
196109998Smarkm		break;
197109998Smarkm
198109998Smarkm		case GEN_URI:
199109998Smarkm		BIO_printf(out, "URI:%s",gen->d.ia5->data);
200109998Smarkm		break;
201109998Smarkm
202109998Smarkm		case GEN_DIRNAME:
203109998Smarkm		BIO_printf(out, "DirName: ");
204109998Smarkm		X509_NAME_print_ex(out, gen->d.dirn, 0, XN_FLAG_ONELINE);
205109998Smarkm		break;
206109998Smarkm
207109998Smarkm		case GEN_IPADD:
208109998Smarkm		p = gen->d.ip->data;
209160814Ssimon		if(gen->d.ip->length == 4)
210160814Ssimon			BIO_printf(out, "IP Address:%d.%d.%d.%d",
211160814Ssimon						p[0], p[1], p[2], p[3]);
212160814Ssimon		else if(gen->d.ip->length == 16)
213160814Ssimon			{
214160814Ssimon			BIO_printf(out, "IP Address");
215160814Ssimon			for (i = 0; i < 8; i++)
216160814Ssimon				{
217160814Ssimon				BIO_printf(out, ":%X", p[0] << 8 | p[1]);
218160814Ssimon				p += 2;
219160814Ssimon				}
220160814Ssimon			BIO_puts(out, "\n");
221160814Ssimon			}
222160814Ssimon		else
223160814Ssimon			{
224109998Smarkm			BIO_printf(out,"IP Address:<invalid>");
225109998Smarkm			break;
226160814Ssimon			}
227109998Smarkm		break;
228109998Smarkm
229109998Smarkm		case GEN_RID:
230109998Smarkm		BIO_printf(out, "Registered ID");
231109998Smarkm		i2a_ASN1_OBJECT(out, gen->d.rid);
232109998Smarkm		break;
233109998Smarkm	}
234109998Smarkm	return 1;
235109998Smarkm}
236109998Smarkm
237109998Smarkmstatic GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method,
23855714Skris				 X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
23955714Skris{
240109998Smarkm	GENERAL_NAMES *gens = NULL;
24155714Skris	CONF_VALUE *cnf;
24255714Skris	int i;
24368651Skris	if(!(gens = sk_GENERAL_NAME_new_null())) {
244160814Ssimon		X509V3err(X509V3_F_V2I_ISSUER_ALT,ERR_R_MALLOC_FAILURE);
24555714Skris		return NULL;
24655714Skris	}
24755714Skris	for(i = 0; i < sk_CONF_VALUE_num(nval); i++) {
24855714Skris		cnf = sk_CONF_VALUE_value(nval, i);
24955714Skris		if(!name_cmp(cnf->name, "issuer") && cnf->value &&
25055714Skris						!strcmp(cnf->value, "copy")) {
25155714Skris			if(!copy_issuer(ctx, gens)) goto err;
25255714Skris		} else {
25355714Skris			GENERAL_NAME *gen;
25455714Skris			if(!(gen = v2i_GENERAL_NAME(method, ctx, cnf)))
25555714Skris								 goto err;
25655714Skris			sk_GENERAL_NAME_push(gens, gen);
25755714Skris		}
25855714Skris	}
25955714Skris	return gens;
26055714Skris	err:
26155714Skris	sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
26255714Skris	return NULL;
26355714Skris}
26455714Skris
26555714Skris/* Append subject altname of issuer to issuer alt name of subject */
26655714Skris
267109998Smarkmstatic int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens)
26855714Skris{
269109998Smarkm	GENERAL_NAMES *ialt;
27055714Skris	GENERAL_NAME *gen;
27155714Skris	X509_EXTENSION *ext;
27255714Skris	int i;
27355714Skris	if(ctx && (ctx->flags == CTX_TEST)) return 1;
27455714Skris	if(!ctx || !ctx->issuer_cert) {
27555714Skris		X509V3err(X509V3_F_COPY_ISSUER,X509V3_R_NO_ISSUER_DETAILS);
27655714Skris		goto err;
27755714Skris	}
27855714Skris        i = X509_get_ext_by_NID(ctx->issuer_cert, NID_subject_alt_name, -1);
27955714Skris	if(i < 0) return 1;
28055714Skris        if(!(ext = X509_get_ext(ctx->issuer_cert, i)) ||
28155714Skris                        !(ialt = X509V3_EXT_d2i(ext)) ) {
28255714Skris		X509V3err(X509V3_F_COPY_ISSUER,X509V3_R_ISSUER_DECODE_ERROR);
28355714Skris		goto err;
28455714Skris	}
28555714Skris
28655714Skris	for(i = 0; i < sk_GENERAL_NAME_num(ialt); i++) {
28755714Skris		gen = sk_GENERAL_NAME_value(ialt, i);
28855714Skris		if(!sk_GENERAL_NAME_push(gens, gen)) {
28955714Skris			X509V3err(X509V3_F_COPY_ISSUER,ERR_R_MALLOC_FAILURE);
29055714Skris			goto err;
29155714Skris		}
29255714Skris	}
29355714Skris	sk_GENERAL_NAME_free(ialt);
29455714Skris
29555714Skris	return 1;
29655714Skris
29755714Skris	err:
29855714Skris	return 0;
29955714Skris
30055714Skris}
30155714Skris
302109998Smarkmstatic GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method,
30355714Skris				 X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
30455714Skris{
305109998Smarkm	GENERAL_NAMES *gens = NULL;
30655714Skris	CONF_VALUE *cnf;
30755714Skris	int i;
30868651Skris	if(!(gens = sk_GENERAL_NAME_new_null())) {
309160814Ssimon		X509V3err(X509V3_F_V2I_SUBJECT_ALT,ERR_R_MALLOC_FAILURE);
31055714Skris		return NULL;
31155714Skris	}
31255714Skris	for(i = 0; i < sk_CONF_VALUE_num(nval); i++) {
31355714Skris		cnf = sk_CONF_VALUE_value(nval, i);
31455714Skris		if(!name_cmp(cnf->name, "email") && cnf->value &&
31555714Skris						!strcmp(cnf->value, "copy")) {
316109998Smarkm			if(!copy_email(ctx, gens, 0)) goto err;
317109998Smarkm		} else if(!name_cmp(cnf->name, "email") && cnf->value &&
318109998Smarkm						!strcmp(cnf->value, "move")) {
319109998Smarkm			if(!copy_email(ctx, gens, 1)) goto err;
32055714Skris		} else {
32155714Skris			GENERAL_NAME *gen;
32255714Skris			if(!(gen = v2i_GENERAL_NAME(method, ctx, cnf)))
32355714Skris								 goto err;
32455714Skris			sk_GENERAL_NAME_push(gens, gen);
32555714Skris		}
32655714Skris	}
32755714Skris	return gens;
32855714Skris	err:
32955714Skris	sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
33055714Skris	return NULL;
33155714Skris}
33255714Skris
33355714Skris/* Copy any email addresses in a certificate or request to
33455714Skris * GENERAL_NAMES
33555714Skris */
33655714Skris
337109998Smarkmstatic int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p)
33855714Skris{
33955714Skris	X509_NAME *nm;
34055714Skris	ASN1_IA5STRING *email = NULL;
34155714Skris	X509_NAME_ENTRY *ne;
34255714Skris	GENERAL_NAME *gen = NULL;
34355714Skris	int i;
344160814Ssimon	if(ctx != NULL && ctx->flags == CTX_TEST)
345160814Ssimon		return 1;
34655714Skris	if(!ctx || (!ctx->subject_cert && !ctx->subject_req)) {
34755714Skris		X509V3err(X509V3_F_COPY_EMAIL,X509V3_R_NO_SUBJECT_DETAILS);
34855714Skris		goto err;
34955714Skris	}
35055714Skris	/* Find the subject name */
35155714Skris	if(ctx->subject_cert) nm = X509_get_subject_name(ctx->subject_cert);
35255714Skris	else nm = X509_REQ_get_subject_name(ctx->subject_req);
35355714Skris
35455714Skris	/* Now add any email address(es) to STACK */
35555714Skris	i = -1;
35655714Skris	while((i = X509_NAME_get_index_by_NID(nm,
35776866Skris					 NID_pkcs9_emailAddress, i)) >= 0) {
35855714Skris		ne = X509_NAME_get_entry(nm, i);
35959191Skris		email = M_ASN1_IA5STRING_dup(X509_NAME_ENTRY_get_data(ne));
360109998Smarkm                if (move_p)
361109998Smarkm                        {
362109998Smarkm                        X509_NAME_delete_entry(nm, i);
363109998Smarkm                        i--;
364109998Smarkm                        }
36555714Skris		if(!email || !(gen = GENERAL_NAME_new())) {
36655714Skris			X509V3err(X509V3_F_COPY_EMAIL,ERR_R_MALLOC_FAILURE);
36755714Skris			goto err;
36855714Skris		}
36955714Skris		gen->d.ia5 = email;
37055714Skris		email = NULL;
37155714Skris		gen->type = GEN_EMAIL;
37255714Skris		if(!sk_GENERAL_NAME_push(gens, gen)) {
37355714Skris			X509V3err(X509V3_F_COPY_EMAIL,ERR_R_MALLOC_FAILURE);
37455714Skris			goto err;
37555714Skris		}
37655714Skris		gen = NULL;
37755714Skris	}
37855714Skris
37955714Skris
38055714Skris	return 1;
38155714Skris
38255714Skris	err:
38355714Skris	GENERAL_NAME_free(gen);
38459191Skris	M_ASN1_IA5STRING_free(email);
38555714Skris	return 0;
38655714Skris
38755714Skris}
38855714Skris
389109998SmarkmGENERAL_NAMES *v2i_GENERAL_NAMES(X509V3_EXT_METHOD *method,
39055714Skris				X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
39155714Skris{
39255714Skris	GENERAL_NAME *gen;
393109998Smarkm	GENERAL_NAMES *gens = NULL;
39455714Skris	CONF_VALUE *cnf;
39555714Skris	int i;
39668651Skris	if(!(gens = sk_GENERAL_NAME_new_null())) {
39755714Skris		X509V3err(X509V3_F_V2I_GENERAL_NAMES,ERR_R_MALLOC_FAILURE);
39855714Skris		return NULL;
39955714Skris	}
40055714Skris	for(i = 0; i < sk_CONF_VALUE_num(nval); i++) {
40155714Skris		cnf = sk_CONF_VALUE_value(nval, i);
40255714Skris		if(!(gen = v2i_GENERAL_NAME(method, ctx, cnf))) goto err;
40355714Skris		sk_GENERAL_NAME_push(gens, gen);
40455714Skris	}
40555714Skris	return gens;
40655714Skris	err:
40755714Skris	sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
40855714Skris	return NULL;
40955714Skris}
41055714Skris
41155714SkrisGENERAL_NAME *v2i_GENERAL_NAME(X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
41255714Skris							 CONF_VALUE *cnf)
413160814Ssimon	{
414160814Ssimon	return v2i_GENERAL_NAME_ex(NULL, method, ctx, cnf, 0);
415160814Ssimon	}
41655714Skris
417160814SsimonGENERAL_NAME *v2i_GENERAL_NAME_ex(GENERAL_NAME *out,
418160814Ssimon				X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
419160814Ssimon						 CONF_VALUE *cnf, int is_nc)
420160814Ssimon	{
421160814Ssimon	char is_string = 0;
422160814Ssimon	int type;
423160814Ssimon	GENERAL_NAME *gen = NULL;
42455714Skris
425160814Ssimon	char *name, *value;
42655714Skris
427160814Ssimon	name = cnf->name;
428160814Ssimon	value = cnf->value;
42955714Skris
430160814Ssimon	if(!value)
431160814Ssimon		{
432160814Ssimon		X509V3err(X509V3_F_V2I_GENERAL_NAME_EX,X509V3_R_MISSING_VALUE);
433160814Ssimon		return NULL;
434160814Ssimon		}
43555714Skris
436160814Ssimon	if (out)
437160814Ssimon		gen = out;
438160814Ssimon	else
439160814Ssimon		{
440160814Ssimon		gen = GENERAL_NAME_new();
441160814Ssimon		if(gen == NULL)
442160814Ssimon			{
443160814Ssimon			X509V3err(X509V3_F_V2I_GENERAL_NAME_EX,ERR_R_MALLOC_FAILURE);
444160814Ssimon			return NULL;
445160814Ssimon			}
446160814Ssimon		}
447160814Ssimon
448160814Ssimon	if(!name_cmp(name, "email"))
449160814Ssimon		{
450160814Ssimon		is_string = 1;
451160814Ssimon		type = GEN_EMAIL;
452160814Ssimon		}
453160814Ssimon	else if(!name_cmp(name, "URI"))
454160814Ssimon		{
455160814Ssimon		is_string = 1;
456160814Ssimon		type = GEN_URI;
457160814Ssimon		}
458160814Ssimon	else if(!name_cmp(name, "DNS"))
459160814Ssimon		{
460160814Ssimon		is_string = 1;
461160814Ssimon		type = GEN_DNS;
462160814Ssimon		}
463160814Ssimon	else if(!name_cmp(name, "RID"))
464160814Ssimon		{
465160814Ssimon		ASN1_OBJECT *obj;
466160814Ssimon		if(!(obj = OBJ_txt2obj(value,0)))
467160814Ssimon			{
468160814Ssimon			X509V3err(X509V3_F_V2I_GENERAL_NAME_EX,X509V3_R_BAD_OBJECT);
469160814Ssimon			ERR_add_error_data(2, "value=", value);
470160814Ssimon			goto err;
471160814Ssimon			}
472160814Ssimon		gen->d.rid = obj;
473160814Ssimon		type = GEN_RID;
474160814Ssimon		}
475160814Ssimon	else if(!name_cmp(name, "IP"))
476160814Ssimon		{
477160814Ssimon		if (is_nc)
478160814Ssimon			gen->d.ip = a2i_IPADDRESS_NC(value);
479160814Ssimon		else
480160814Ssimon			gen->d.ip = a2i_IPADDRESS(value);
481160814Ssimon		if(gen->d.ip == NULL)
482160814Ssimon			{
483160814Ssimon			X509V3err(X509V3_F_V2I_GENERAL_NAME_EX,X509V3_R_BAD_IP_ADDRESS);
484160814Ssimon			ERR_add_error_data(2, "value=", value);
485160814Ssimon			goto err;
486160814Ssimon			}
487160814Ssimon		type = GEN_IPADD;
488160814Ssimon		}
489160814Ssimon	else if(!name_cmp(name, "dirName"))
490160814Ssimon		{
491160814Ssimon		type = GEN_DIRNAME;
492160814Ssimon		if (!do_dirname(gen, value, ctx))
493160814Ssimon			{
494160814Ssimon			X509V3err(X509V3_F_V2I_GENERAL_NAME_EX,X509V3_R_DIRNAME_ERROR);
495160814Ssimon			goto err;
496160814Ssimon			}
497160814Ssimon		}
498160814Ssimon	else if(!name_cmp(name, "otherName"))
499160814Ssimon		{
500160814Ssimon		if (!do_othername(gen, value, ctx))
501160814Ssimon			{
502160814Ssimon			X509V3err(X509V3_F_V2I_GENERAL_NAME_EX,X509V3_R_OTHERNAME_ERROR);
503160814Ssimon			goto err;
504160814Ssimon			}
505160814Ssimon		type = GEN_OTHERNAME;
506160814Ssimon		}
507160814Ssimon	else
508160814Ssimon		{
509160814Ssimon		X509V3err(X509V3_F_V2I_GENERAL_NAME_EX,X509V3_R_UNSUPPORTED_OPTION);
510160814Ssimon		ERR_add_error_data(2, "name=", name);
51155714Skris		goto err;
512160814Ssimon		}
513160814Ssimon
514160814Ssimon	if(is_string)
515160814Ssimon		{
516160814Ssimon		if(!(gen->d.ia5 = M_ASN1_IA5STRING_new()) ||
517160814Ssimon			      !ASN1_STRING_set(gen->d.ia5, (unsigned char*)value,
518160814Ssimon					       strlen(value)))
519160814Ssimon			{
520160814Ssimon			X509V3err(X509V3_F_V2I_GENERAL_NAME_EX,ERR_R_MALLOC_FAILURE);
52155714Skris			goto err;
522160814Ssimon			}
523160814Ssimon		}
524160814Ssimon
525160814Ssimon	gen->type = type;
526160814Ssimon
527160814Ssimon	return gen;
528160814Ssimon
529160814Ssimon	err:
530160814Ssimon	GENERAL_NAME_free(gen);
531160814Ssimon	return NULL;
53255714Skris	}
53355714Skris
534160814Ssimonstatic int do_othername(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx)
535160814Ssimon	{
536160814Ssimon	char *objtmp = NULL, *p;
537160814Ssimon	int objlen;
538160814Ssimon	if (!(p = strchr(value, ';')))
539160814Ssimon		return 0;
540160814Ssimon	if (!(gen->d.otherName = OTHERNAME_new()))
541160814Ssimon		return 0;
542160814Ssimon	/* Free this up because we will overwrite it.
543160814Ssimon	 * no need to free type_id because it is static
544160814Ssimon	 */
545160814Ssimon	ASN1_TYPE_free(gen->d.otherName->value);
546160814Ssimon	if (!(gen->d.otherName->value = ASN1_generate_v3(p + 1, ctx)))
547160814Ssimon		return 0;
548160814Ssimon	objlen = p - value;
549160814Ssimon	objtmp = OPENSSL_malloc(objlen + 1);
550160814Ssimon	strncpy(objtmp, value, objlen);
551160814Ssimon	objtmp[objlen] = 0;
552160814Ssimon	gen->d.otherName->type_id = OBJ_txt2obj(objtmp, 0);
553160814Ssimon	OPENSSL_free(objtmp);
554160814Ssimon	if (!gen->d.otherName->type_id)
555160814Ssimon		return 0;
556160814Ssimon	return 1;
55755714Skris	}
55855714Skris
559160814Ssimonstatic int do_dirname(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx)
560160814Ssimon	{
561160814Ssimon	int ret;
562160814Ssimon	STACK_OF(CONF_VALUE) *sk;
563160814Ssimon	X509_NAME *nm;
564160814Ssimon	if (!(nm = X509_NAME_new()))
565160814Ssimon		return 0;
566160814Ssimon	sk = X509V3_get_section(ctx, value);
567160814Ssimon	if (!sk)
568160814Ssimon		{
569160814Ssimon		X509V3err(X509V3_F_DO_DIRNAME,X509V3_R_SECTION_NOT_FOUND);
570160814Ssimon		ERR_add_error_data(2, "section=", value);
571160814Ssimon		X509_NAME_free(nm);
572160814Ssimon		return 0;
573160814Ssimon		}
574160814Ssimon	/* FIXME: should allow other character types... */
575160814Ssimon	ret = X509V3_NAME_from_section(nm, sk, MBSTRING_ASC);
576160814Ssimon	if (!ret)
577160814Ssimon		X509_NAME_free(nm);
578160814Ssimon	gen->d.dirn = nm;
579160814Ssimon
580160814Ssimon	return ret;
581160814Ssimon	}
582