xref: /onnv-gate/usr/src/common/openssl/crypto/x509v3/v3_alt.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /* v3_alt.c */
2*0Sstevel@tonic-gate /* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
3*0Sstevel@tonic-gate  * project 1999.
4*0Sstevel@tonic-gate  */
5*0Sstevel@tonic-gate /* ====================================================================
6*0Sstevel@tonic-gate  * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
7*0Sstevel@tonic-gate  *
8*0Sstevel@tonic-gate  * Redistribution and use in source and binary forms, with or without
9*0Sstevel@tonic-gate  * modification, are permitted provided that the following conditions
10*0Sstevel@tonic-gate  * are met:
11*0Sstevel@tonic-gate  *
12*0Sstevel@tonic-gate  * 1. Redistributions of source code must retain the above copyright
13*0Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer.
14*0Sstevel@tonic-gate  *
15*0Sstevel@tonic-gate  * 2. Redistributions in binary form must reproduce the above copyright
16*0Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer in
17*0Sstevel@tonic-gate  *    the documentation and/or other materials provided with the
18*0Sstevel@tonic-gate  *    distribution.
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * 3. All advertising materials mentioning features or use of this
21*0Sstevel@tonic-gate  *    software must display the following acknowledgment:
22*0Sstevel@tonic-gate  *    "This product includes software developed by the OpenSSL Project
23*0Sstevel@tonic-gate  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24*0Sstevel@tonic-gate  *
25*0Sstevel@tonic-gate  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26*0Sstevel@tonic-gate  *    endorse or promote products derived from this software without
27*0Sstevel@tonic-gate  *    prior written permission. For written permission, please contact
28*0Sstevel@tonic-gate  *    licensing@OpenSSL.org.
29*0Sstevel@tonic-gate  *
30*0Sstevel@tonic-gate  * 5. Products derived from this software may not be called "OpenSSL"
31*0Sstevel@tonic-gate  *    nor may "OpenSSL" appear in their names without prior written
32*0Sstevel@tonic-gate  *    permission of the OpenSSL Project.
33*0Sstevel@tonic-gate  *
34*0Sstevel@tonic-gate  * 6. Redistributions of any form whatsoever must retain the following
35*0Sstevel@tonic-gate  *    acknowledgment:
36*0Sstevel@tonic-gate  *    "This product includes software developed by the OpenSSL Project
37*0Sstevel@tonic-gate  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38*0Sstevel@tonic-gate  *
39*0Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40*0Sstevel@tonic-gate  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41*0Sstevel@tonic-gate  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42*0Sstevel@tonic-gate  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43*0Sstevel@tonic-gate  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44*0Sstevel@tonic-gate  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45*0Sstevel@tonic-gate  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46*0Sstevel@tonic-gate  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47*0Sstevel@tonic-gate  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48*0Sstevel@tonic-gate  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49*0Sstevel@tonic-gate  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50*0Sstevel@tonic-gate  * OF THE POSSIBILITY OF SUCH DAMAGE.
51*0Sstevel@tonic-gate  * ====================================================================
52*0Sstevel@tonic-gate  *
53*0Sstevel@tonic-gate  * This product includes cryptographic software written by Eric Young
54*0Sstevel@tonic-gate  * (eay@cryptsoft.com).  This product includes software written by Tim
55*0Sstevel@tonic-gate  * Hudson (tjh@cryptsoft.com).
56*0Sstevel@tonic-gate  *
57*0Sstevel@tonic-gate  */
58*0Sstevel@tonic-gate 
59*0Sstevel@tonic-gate #include <stdio.h>
60*0Sstevel@tonic-gate #include "cryptlib.h"
61*0Sstevel@tonic-gate #include <openssl/conf.h>
62*0Sstevel@tonic-gate #include <openssl/x509v3.h>
63*0Sstevel@tonic-gate 
64*0Sstevel@tonic-gate static GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval);
65*0Sstevel@tonic-gate static GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval);
66*0Sstevel@tonic-gate static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p);
67*0Sstevel@tonic-gate static int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens);
68*0Sstevel@tonic-gate X509V3_EXT_METHOD v3_alt[] = {
69*0Sstevel@tonic-gate { NID_subject_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES),
70*0Sstevel@tonic-gate 0,0,0,0,
71*0Sstevel@tonic-gate 0,0,
72*0Sstevel@tonic-gate (X509V3_EXT_I2V)i2v_GENERAL_NAMES,
73*0Sstevel@tonic-gate (X509V3_EXT_V2I)v2i_subject_alt,
74*0Sstevel@tonic-gate NULL, NULL, NULL},
75*0Sstevel@tonic-gate 
76*0Sstevel@tonic-gate { NID_issuer_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES),
77*0Sstevel@tonic-gate 0,0,0,0,
78*0Sstevel@tonic-gate 0,0,
79*0Sstevel@tonic-gate (X509V3_EXT_I2V)i2v_GENERAL_NAMES,
80*0Sstevel@tonic-gate (X509V3_EXT_V2I)v2i_issuer_alt,
81*0Sstevel@tonic-gate NULL, NULL, NULL},
82*0Sstevel@tonic-gate };
83*0Sstevel@tonic-gate 
84*0Sstevel@tonic-gate STACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES(X509V3_EXT_METHOD *method,
85*0Sstevel@tonic-gate 		GENERAL_NAMES *gens, STACK_OF(CONF_VALUE) *ret)
86*0Sstevel@tonic-gate {
87*0Sstevel@tonic-gate 	int i;
88*0Sstevel@tonic-gate 	GENERAL_NAME *gen;
89*0Sstevel@tonic-gate 	for(i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
90*0Sstevel@tonic-gate 		gen = sk_GENERAL_NAME_value(gens, i);
91*0Sstevel@tonic-gate 		ret = i2v_GENERAL_NAME(method, gen, ret);
92*0Sstevel@tonic-gate 	}
93*0Sstevel@tonic-gate 	if(!ret) return sk_CONF_VALUE_new_null();
94*0Sstevel@tonic-gate 	return ret;
95*0Sstevel@tonic-gate }
96*0Sstevel@tonic-gate 
97*0Sstevel@tonic-gate STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method,
98*0Sstevel@tonic-gate 				GENERAL_NAME *gen, STACK_OF(CONF_VALUE) *ret)
99*0Sstevel@tonic-gate {
100*0Sstevel@tonic-gate 	unsigned char *p;
101*0Sstevel@tonic-gate 	char oline[256];
102*0Sstevel@tonic-gate 	switch (gen->type)
103*0Sstevel@tonic-gate 	{
104*0Sstevel@tonic-gate 		case GEN_OTHERNAME:
105*0Sstevel@tonic-gate 		X509V3_add_value("othername","<unsupported>", &ret);
106*0Sstevel@tonic-gate 		break;
107*0Sstevel@tonic-gate 
108*0Sstevel@tonic-gate 		case GEN_X400:
109*0Sstevel@tonic-gate 		X509V3_add_value("X400Name","<unsupported>", &ret);
110*0Sstevel@tonic-gate 		break;
111*0Sstevel@tonic-gate 
112*0Sstevel@tonic-gate 		case GEN_EDIPARTY:
113*0Sstevel@tonic-gate 		X509V3_add_value("EdiPartyName","<unsupported>", &ret);
114*0Sstevel@tonic-gate 		break;
115*0Sstevel@tonic-gate 
116*0Sstevel@tonic-gate 		case GEN_EMAIL:
117*0Sstevel@tonic-gate 		X509V3_add_value_uchar("email",gen->d.ia5->data, &ret);
118*0Sstevel@tonic-gate 		break;
119*0Sstevel@tonic-gate 
120*0Sstevel@tonic-gate 		case GEN_DNS:
121*0Sstevel@tonic-gate 		X509V3_add_value_uchar("DNS",gen->d.ia5->data, &ret);
122*0Sstevel@tonic-gate 		break;
123*0Sstevel@tonic-gate 
124*0Sstevel@tonic-gate 		case GEN_URI:
125*0Sstevel@tonic-gate 		X509V3_add_value_uchar("URI",gen->d.ia5->data, &ret);
126*0Sstevel@tonic-gate 		break;
127*0Sstevel@tonic-gate 
128*0Sstevel@tonic-gate 		case GEN_DIRNAME:
129*0Sstevel@tonic-gate 		X509_NAME_oneline(gen->d.dirn, oline, 256);
130*0Sstevel@tonic-gate 		X509V3_add_value("DirName",oline, &ret);
131*0Sstevel@tonic-gate 		break;
132*0Sstevel@tonic-gate 
133*0Sstevel@tonic-gate 		case GEN_IPADD:
134*0Sstevel@tonic-gate 		p = gen->d.ip->data;
135*0Sstevel@tonic-gate 		/* BUG: doesn't support IPV6 */
136*0Sstevel@tonic-gate 		if(gen->d.ip->length != 4) {
137*0Sstevel@tonic-gate 			X509V3_add_value("IP Address","<invalid>", &ret);
138*0Sstevel@tonic-gate 			break;
139*0Sstevel@tonic-gate 		}
140*0Sstevel@tonic-gate 		BIO_snprintf(oline, sizeof oline,
141*0Sstevel@tonic-gate 			     "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
142*0Sstevel@tonic-gate 		X509V3_add_value("IP Address",oline, &ret);
143*0Sstevel@tonic-gate 		break;
144*0Sstevel@tonic-gate 
145*0Sstevel@tonic-gate 		case GEN_RID:
146*0Sstevel@tonic-gate 		i2t_ASN1_OBJECT(oline, 256, gen->d.rid);
147*0Sstevel@tonic-gate 		X509V3_add_value("Registered ID",oline, &ret);
148*0Sstevel@tonic-gate 		break;
149*0Sstevel@tonic-gate 	}
150*0Sstevel@tonic-gate 	return ret;
151*0Sstevel@tonic-gate }
152*0Sstevel@tonic-gate 
153*0Sstevel@tonic-gate int GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen)
154*0Sstevel@tonic-gate {
155*0Sstevel@tonic-gate 	unsigned char *p;
156*0Sstevel@tonic-gate 	switch (gen->type)
157*0Sstevel@tonic-gate 	{
158*0Sstevel@tonic-gate 		case GEN_OTHERNAME:
159*0Sstevel@tonic-gate 		BIO_printf(out, "othername:<unsupported>");
160*0Sstevel@tonic-gate 		break;
161*0Sstevel@tonic-gate 
162*0Sstevel@tonic-gate 		case GEN_X400:
163*0Sstevel@tonic-gate 		BIO_printf(out, "X400Name:<unsupported>");
164*0Sstevel@tonic-gate 		break;
165*0Sstevel@tonic-gate 
166*0Sstevel@tonic-gate 		case GEN_EDIPARTY:
167*0Sstevel@tonic-gate 		/* Maybe fix this: it is supported now */
168*0Sstevel@tonic-gate 		BIO_printf(out, "EdiPartyName:<unsupported>");
169*0Sstevel@tonic-gate 		break;
170*0Sstevel@tonic-gate 
171*0Sstevel@tonic-gate 		case GEN_EMAIL:
172*0Sstevel@tonic-gate 		BIO_printf(out, "email:%s",gen->d.ia5->data);
173*0Sstevel@tonic-gate 		break;
174*0Sstevel@tonic-gate 
175*0Sstevel@tonic-gate 		case GEN_DNS:
176*0Sstevel@tonic-gate 		BIO_printf(out, "DNS:%s",gen->d.ia5->data);
177*0Sstevel@tonic-gate 		break;
178*0Sstevel@tonic-gate 
179*0Sstevel@tonic-gate 		case GEN_URI:
180*0Sstevel@tonic-gate 		BIO_printf(out, "URI:%s",gen->d.ia5->data);
181*0Sstevel@tonic-gate 		break;
182*0Sstevel@tonic-gate 
183*0Sstevel@tonic-gate 		case GEN_DIRNAME:
184*0Sstevel@tonic-gate 		BIO_printf(out, "DirName: ");
185*0Sstevel@tonic-gate 		X509_NAME_print_ex(out, gen->d.dirn, 0, XN_FLAG_ONELINE);
186*0Sstevel@tonic-gate 		break;
187*0Sstevel@tonic-gate 
188*0Sstevel@tonic-gate 		case GEN_IPADD:
189*0Sstevel@tonic-gate 		p = gen->d.ip->data;
190*0Sstevel@tonic-gate 		/* BUG: doesn't support IPV6 */
191*0Sstevel@tonic-gate 		if(gen->d.ip->length != 4) {
192*0Sstevel@tonic-gate 			BIO_printf(out,"IP Address:<invalid>");
193*0Sstevel@tonic-gate 			break;
194*0Sstevel@tonic-gate 		}
195*0Sstevel@tonic-gate 		BIO_printf(out, "IP Address:%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
196*0Sstevel@tonic-gate 		break;
197*0Sstevel@tonic-gate 
198*0Sstevel@tonic-gate 		case GEN_RID:
199*0Sstevel@tonic-gate 		BIO_printf(out, "Registered ID");
200*0Sstevel@tonic-gate 		i2a_ASN1_OBJECT(out, gen->d.rid);
201*0Sstevel@tonic-gate 		break;
202*0Sstevel@tonic-gate 	}
203*0Sstevel@tonic-gate 	return 1;
204*0Sstevel@tonic-gate }
205*0Sstevel@tonic-gate 
206*0Sstevel@tonic-gate static GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method,
207*0Sstevel@tonic-gate 				 X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
208*0Sstevel@tonic-gate {
209*0Sstevel@tonic-gate 	GENERAL_NAMES *gens = NULL;
210*0Sstevel@tonic-gate 	CONF_VALUE *cnf;
211*0Sstevel@tonic-gate 	int i;
212*0Sstevel@tonic-gate 	if(!(gens = sk_GENERAL_NAME_new_null())) {
213*0Sstevel@tonic-gate 		X509V3err(X509V3_F_V2I_GENERAL_NAMES,ERR_R_MALLOC_FAILURE);
214*0Sstevel@tonic-gate 		return NULL;
215*0Sstevel@tonic-gate 	}
216*0Sstevel@tonic-gate 	for(i = 0; i < sk_CONF_VALUE_num(nval); i++) {
217*0Sstevel@tonic-gate 		cnf = sk_CONF_VALUE_value(nval, i);
218*0Sstevel@tonic-gate 		if(!name_cmp(cnf->name, "issuer") && cnf->value &&
219*0Sstevel@tonic-gate 						!strcmp(cnf->value, "copy")) {
220*0Sstevel@tonic-gate 			if(!copy_issuer(ctx, gens)) goto err;
221*0Sstevel@tonic-gate 		} else {
222*0Sstevel@tonic-gate 			GENERAL_NAME *gen;
223*0Sstevel@tonic-gate 			if(!(gen = v2i_GENERAL_NAME(method, ctx, cnf)))
224*0Sstevel@tonic-gate 								 goto err;
225*0Sstevel@tonic-gate 			sk_GENERAL_NAME_push(gens, gen);
226*0Sstevel@tonic-gate 		}
227*0Sstevel@tonic-gate 	}
228*0Sstevel@tonic-gate 	return gens;
229*0Sstevel@tonic-gate 	err:
230*0Sstevel@tonic-gate 	sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
231*0Sstevel@tonic-gate 	return NULL;
232*0Sstevel@tonic-gate }
233*0Sstevel@tonic-gate 
234*0Sstevel@tonic-gate /* Append subject altname of issuer to issuer alt name of subject */
235*0Sstevel@tonic-gate 
236*0Sstevel@tonic-gate static int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens)
237*0Sstevel@tonic-gate {
238*0Sstevel@tonic-gate 	GENERAL_NAMES *ialt;
239*0Sstevel@tonic-gate 	GENERAL_NAME *gen;
240*0Sstevel@tonic-gate 	X509_EXTENSION *ext;
241*0Sstevel@tonic-gate 	int i;
242*0Sstevel@tonic-gate 	if(ctx && (ctx->flags == CTX_TEST)) return 1;
243*0Sstevel@tonic-gate 	if(!ctx || !ctx->issuer_cert) {
244*0Sstevel@tonic-gate 		X509V3err(X509V3_F_COPY_ISSUER,X509V3_R_NO_ISSUER_DETAILS);
245*0Sstevel@tonic-gate 		goto err;
246*0Sstevel@tonic-gate 	}
247*0Sstevel@tonic-gate         i = X509_get_ext_by_NID(ctx->issuer_cert, NID_subject_alt_name, -1);
248*0Sstevel@tonic-gate 	if(i < 0) return 1;
249*0Sstevel@tonic-gate         if(!(ext = X509_get_ext(ctx->issuer_cert, i)) ||
250*0Sstevel@tonic-gate                         !(ialt = X509V3_EXT_d2i(ext)) ) {
251*0Sstevel@tonic-gate 		X509V3err(X509V3_F_COPY_ISSUER,X509V3_R_ISSUER_DECODE_ERROR);
252*0Sstevel@tonic-gate 		goto err;
253*0Sstevel@tonic-gate 	}
254*0Sstevel@tonic-gate 
255*0Sstevel@tonic-gate 	for(i = 0; i < sk_GENERAL_NAME_num(ialt); i++) {
256*0Sstevel@tonic-gate 		gen = sk_GENERAL_NAME_value(ialt, i);
257*0Sstevel@tonic-gate 		if(!sk_GENERAL_NAME_push(gens, gen)) {
258*0Sstevel@tonic-gate 			X509V3err(X509V3_F_COPY_ISSUER,ERR_R_MALLOC_FAILURE);
259*0Sstevel@tonic-gate 			goto err;
260*0Sstevel@tonic-gate 		}
261*0Sstevel@tonic-gate 	}
262*0Sstevel@tonic-gate 	sk_GENERAL_NAME_free(ialt);
263*0Sstevel@tonic-gate 
264*0Sstevel@tonic-gate 	return 1;
265*0Sstevel@tonic-gate 
266*0Sstevel@tonic-gate 	err:
267*0Sstevel@tonic-gate 	return 0;
268*0Sstevel@tonic-gate 
269*0Sstevel@tonic-gate }
270*0Sstevel@tonic-gate 
271*0Sstevel@tonic-gate static GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method,
272*0Sstevel@tonic-gate 				 X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
273*0Sstevel@tonic-gate {
274*0Sstevel@tonic-gate 	GENERAL_NAMES *gens = NULL;
275*0Sstevel@tonic-gate 	CONF_VALUE *cnf;
276*0Sstevel@tonic-gate 	int i;
277*0Sstevel@tonic-gate 	if(!(gens = sk_GENERAL_NAME_new_null())) {
278*0Sstevel@tonic-gate 		X509V3err(X509V3_F_V2I_GENERAL_NAMES,ERR_R_MALLOC_FAILURE);
279*0Sstevel@tonic-gate 		return NULL;
280*0Sstevel@tonic-gate 	}
281*0Sstevel@tonic-gate 	for(i = 0; i < sk_CONF_VALUE_num(nval); i++) {
282*0Sstevel@tonic-gate 		cnf = sk_CONF_VALUE_value(nval, i);
283*0Sstevel@tonic-gate 		if(!name_cmp(cnf->name, "email") && cnf->value &&
284*0Sstevel@tonic-gate 						!strcmp(cnf->value, "copy")) {
285*0Sstevel@tonic-gate 			if(!copy_email(ctx, gens, 0)) goto err;
286*0Sstevel@tonic-gate 		} else if(!name_cmp(cnf->name, "email") && cnf->value &&
287*0Sstevel@tonic-gate 						!strcmp(cnf->value, "move")) {
288*0Sstevel@tonic-gate 			if(!copy_email(ctx, gens, 1)) goto err;
289*0Sstevel@tonic-gate 		} else {
290*0Sstevel@tonic-gate 			GENERAL_NAME *gen;
291*0Sstevel@tonic-gate 			if(!(gen = v2i_GENERAL_NAME(method, ctx, cnf)))
292*0Sstevel@tonic-gate 								 goto err;
293*0Sstevel@tonic-gate 			sk_GENERAL_NAME_push(gens, gen);
294*0Sstevel@tonic-gate 		}
295*0Sstevel@tonic-gate 	}
296*0Sstevel@tonic-gate 	return gens;
297*0Sstevel@tonic-gate 	err:
298*0Sstevel@tonic-gate 	sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
299*0Sstevel@tonic-gate 	return NULL;
300*0Sstevel@tonic-gate }
301*0Sstevel@tonic-gate 
302*0Sstevel@tonic-gate /* Copy any email addresses in a certificate or request to
303*0Sstevel@tonic-gate  * GENERAL_NAMES
304*0Sstevel@tonic-gate  */
305*0Sstevel@tonic-gate 
306*0Sstevel@tonic-gate static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p)
307*0Sstevel@tonic-gate {
308*0Sstevel@tonic-gate 	X509_NAME *nm;
309*0Sstevel@tonic-gate 	ASN1_IA5STRING *email = NULL;
310*0Sstevel@tonic-gate 	X509_NAME_ENTRY *ne;
311*0Sstevel@tonic-gate 	GENERAL_NAME *gen = NULL;
312*0Sstevel@tonic-gate 	int i;
313*0Sstevel@tonic-gate 	if(ctx->flags == CTX_TEST) return 1;
314*0Sstevel@tonic-gate 	if(!ctx || (!ctx->subject_cert && !ctx->subject_req)) {
315*0Sstevel@tonic-gate 		X509V3err(X509V3_F_COPY_EMAIL,X509V3_R_NO_SUBJECT_DETAILS);
316*0Sstevel@tonic-gate 		goto err;
317*0Sstevel@tonic-gate 	}
318*0Sstevel@tonic-gate 	/* Find the subject name */
319*0Sstevel@tonic-gate 	if(ctx->subject_cert) nm = X509_get_subject_name(ctx->subject_cert);
320*0Sstevel@tonic-gate 	else nm = X509_REQ_get_subject_name(ctx->subject_req);
321*0Sstevel@tonic-gate 
322*0Sstevel@tonic-gate 	/* Now add any email address(es) to STACK */
323*0Sstevel@tonic-gate 	i = -1;
324*0Sstevel@tonic-gate 	while((i = X509_NAME_get_index_by_NID(nm,
325*0Sstevel@tonic-gate 					 NID_pkcs9_emailAddress, i)) >= 0) {
326*0Sstevel@tonic-gate 		ne = X509_NAME_get_entry(nm, i);
327*0Sstevel@tonic-gate 		email = M_ASN1_IA5STRING_dup(X509_NAME_ENTRY_get_data(ne));
328*0Sstevel@tonic-gate                 if (move_p)
329*0Sstevel@tonic-gate                         {
330*0Sstevel@tonic-gate                         X509_NAME_delete_entry(nm, i);
331*0Sstevel@tonic-gate                         i--;
332*0Sstevel@tonic-gate                         }
333*0Sstevel@tonic-gate 		if(!email || !(gen = GENERAL_NAME_new())) {
334*0Sstevel@tonic-gate 			X509V3err(X509V3_F_COPY_EMAIL,ERR_R_MALLOC_FAILURE);
335*0Sstevel@tonic-gate 			goto err;
336*0Sstevel@tonic-gate 		}
337*0Sstevel@tonic-gate 		gen->d.ia5 = email;
338*0Sstevel@tonic-gate 		email = NULL;
339*0Sstevel@tonic-gate 		gen->type = GEN_EMAIL;
340*0Sstevel@tonic-gate 		if(!sk_GENERAL_NAME_push(gens, gen)) {
341*0Sstevel@tonic-gate 			X509V3err(X509V3_F_COPY_EMAIL,ERR_R_MALLOC_FAILURE);
342*0Sstevel@tonic-gate 			goto err;
343*0Sstevel@tonic-gate 		}
344*0Sstevel@tonic-gate 		gen = NULL;
345*0Sstevel@tonic-gate 	}
346*0Sstevel@tonic-gate 
347*0Sstevel@tonic-gate 
348*0Sstevel@tonic-gate 	return 1;
349*0Sstevel@tonic-gate 
350*0Sstevel@tonic-gate 	err:
351*0Sstevel@tonic-gate 	GENERAL_NAME_free(gen);
352*0Sstevel@tonic-gate 	M_ASN1_IA5STRING_free(email);
353*0Sstevel@tonic-gate 	return 0;
354*0Sstevel@tonic-gate 
355*0Sstevel@tonic-gate }
356*0Sstevel@tonic-gate 
357*0Sstevel@tonic-gate GENERAL_NAMES *v2i_GENERAL_NAMES(X509V3_EXT_METHOD *method,
358*0Sstevel@tonic-gate 				X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
359*0Sstevel@tonic-gate {
360*0Sstevel@tonic-gate 	GENERAL_NAME *gen;
361*0Sstevel@tonic-gate 	GENERAL_NAMES *gens = NULL;
362*0Sstevel@tonic-gate 	CONF_VALUE *cnf;
363*0Sstevel@tonic-gate 	int i;
364*0Sstevel@tonic-gate 	if(!(gens = sk_GENERAL_NAME_new_null())) {
365*0Sstevel@tonic-gate 		X509V3err(X509V3_F_V2I_GENERAL_NAMES,ERR_R_MALLOC_FAILURE);
366*0Sstevel@tonic-gate 		return NULL;
367*0Sstevel@tonic-gate 	}
368*0Sstevel@tonic-gate 	for(i = 0; i < sk_CONF_VALUE_num(nval); i++) {
369*0Sstevel@tonic-gate 		cnf = sk_CONF_VALUE_value(nval, i);
370*0Sstevel@tonic-gate 		if(!(gen = v2i_GENERAL_NAME(method, ctx, cnf))) goto err;
371*0Sstevel@tonic-gate 		sk_GENERAL_NAME_push(gens, gen);
372*0Sstevel@tonic-gate 	}
373*0Sstevel@tonic-gate 	return gens;
374*0Sstevel@tonic-gate 	err:
375*0Sstevel@tonic-gate 	sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
376*0Sstevel@tonic-gate 	return NULL;
377*0Sstevel@tonic-gate }
378*0Sstevel@tonic-gate 
379*0Sstevel@tonic-gate #if	defined(_BOOT)
380*0Sstevel@tonic-gate /* stolen from bio/b_sock.c  - XXXX - why steal it? */
381*0Sstevel@tonic-gate /* The reason I have implemented this instead of using sscanf is because
382*0Sstevel@tonic-gate  * Visual C 1.52c gives an unresolved external when linking a DLL :-( */
383*0Sstevel@tonic-gate static int get_ip(const char *str, unsigned char ip[4])
384*0Sstevel@tonic-gate 	{
385*0Sstevel@tonic-gate 	unsigned int tmp[4];
386*0Sstevel@tonic-gate 	int num=0,c,ok=0;
387*0Sstevel@tonic-gate 
388*0Sstevel@tonic-gate 	tmp[0]=tmp[1]=tmp[2]=tmp[3]=0;
389*0Sstevel@tonic-gate 
390*0Sstevel@tonic-gate 	for (;;)
391*0Sstevel@tonic-gate 		{
392*0Sstevel@tonic-gate 		c= *(str++);
393*0Sstevel@tonic-gate 		if ((c >= '0') && (c <= '9'))
394*0Sstevel@tonic-gate 			{
395*0Sstevel@tonic-gate 			ok=1;
396*0Sstevel@tonic-gate 			tmp[num]=tmp[num]*10+c-'0';
397*0Sstevel@tonic-gate 			if (tmp[num] > 255) return(0);
398*0Sstevel@tonic-gate 			}
399*0Sstevel@tonic-gate 		else if (c == '.')
400*0Sstevel@tonic-gate 			{
401*0Sstevel@tonic-gate 			if (!ok) return(-1);
402*0Sstevel@tonic-gate 			if (num == 3) return(0);
403*0Sstevel@tonic-gate 			num++;
404*0Sstevel@tonic-gate 			ok=0;
405*0Sstevel@tonic-gate 			}
406*0Sstevel@tonic-gate 		else if (c == '\0' && (num == 3) && ok)
407*0Sstevel@tonic-gate 			break;
408*0Sstevel@tonic-gate 		else
409*0Sstevel@tonic-gate 			return(0);
410*0Sstevel@tonic-gate 		}
411*0Sstevel@tonic-gate 	ip[0]=tmp[0];
412*0Sstevel@tonic-gate 	ip[1]=tmp[1];
413*0Sstevel@tonic-gate 	ip[2]=tmp[2];
414*0Sstevel@tonic-gate 	ip[3]=tmp[3];
415*0Sstevel@tonic-gate 	return(1);
416*0Sstevel@tonic-gate 	}
417*0Sstevel@tonic-gate #endif /* _BOOT */
418*0Sstevel@tonic-gate 
419*0Sstevel@tonic-gate GENERAL_NAME *v2i_GENERAL_NAME(X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
420*0Sstevel@tonic-gate 							 CONF_VALUE *cnf)
421*0Sstevel@tonic-gate {
422*0Sstevel@tonic-gate char is_string = 0;
423*0Sstevel@tonic-gate int type;
424*0Sstevel@tonic-gate GENERAL_NAME *gen = NULL;
425*0Sstevel@tonic-gate 
426*0Sstevel@tonic-gate char *name, *value;
427*0Sstevel@tonic-gate 
428*0Sstevel@tonic-gate name = cnf->name;
429*0Sstevel@tonic-gate value = cnf->value;
430*0Sstevel@tonic-gate 
431*0Sstevel@tonic-gate if(!value) {
432*0Sstevel@tonic-gate 	X509V3err(X509V3_F_V2I_GENERAL_NAME,X509V3_R_MISSING_VALUE);
433*0Sstevel@tonic-gate 	return NULL;
434*0Sstevel@tonic-gate }
435*0Sstevel@tonic-gate 
436*0Sstevel@tonic-gate if(!(gen = GENERAL_NAME_new())) {
437*0Sstevel@tonic-gate 	X509V3err(X509V3_F_V2I_GENERAL_NAME,ERR_R_MALLOC_FAILURE);
438*0Sstevel@tonic-gate 	return NULL;
439*0Sstevel@tonic-gate }
440*0Sstevel@tonic-gate 
441*0Sstevel@tonic-gate if(!name_cmp(name, "email")) {
442*0Sstevel@tonic-gate 	is_string = 1;
443*0Sstevel@tonic-gate 	type = GEN_EMAIL;
444*0Sstevel@tonic-gate } else if(!name_cmp(name, "URI")) {
445*0Sstevel@tonic-gate 	is_string = 1;
446*0Sstevel@tonic-gate 	type = GEN_URI;
447*0Sstevel@tonic-gate } else if(!name_cmp(name, "DNS")) {
448*0Sstevel@tonic-gate 	is_string = 1;
449*0Sstevel@tonic-gate 	type = GEN_DNS;
450*0Sstevel@tonic-gate } else if(!name_cmp(name, "RID")) {
451*0Sstevel@tonic-gate 	ASN1_OBJECT *obj;
452*0Sstevel@tonic-gate 	if(!(obj = OBJ_txt2obj(value,0))) {
453*0Sstevel@tonic-gate 		X509V3err(X509V3_F_V2I_GENERAL_NAME,X509V3_R_BAD_OBJECT);
454*0Sstevel@tonic-gate 		ERR_add_error_data(2, "value=", value);
455*0Sstevel@tonic-gate 		goto err;
456*0Sstevel@tonic-gate 	}
457*0Sstevel@tonic-gate 	gen->d.rid = obj;
458*0Sstevel@tonic-gate 	type = GEN_RID;
459*0Sstevel@tonic-gate } else if(!name_cmp(name, "IP")) {
460*0Sstevel@tonic-gate 	int i1,i2,i3,i4;
461*0Sstevel@tonic-gate 	unsigned char ip[4];
462*0Sstevel@tonic-gate 
463*0Sstevel@tonic-gate #if	defined(_BOOT)
464*0Sstevel@tonic-gate 	if (get_ip(value, ip) != 1) {
465*0Sstevel@tonic-gate #else	/* _BOOT */
466*0Sstevel@tonic-gate 	    if ((sscanf(value, "%d.%d.%d.%d",&i1,&i2,&i3,&i4) != 4) ||
467*0Sstevel@tonic-gate 	    (i1 < 0) || (i1 > 255) || (i2 < 0) || (i2 > 255) ||
468*0Sstevel@tonic-gate 	    (i3 < 0) || (i3 > 255) || (i4 < 0) || (i4 > 255) ) {
469*0Sstevel@tonic-gate #endif	/* _BOOT */
470*0Sstevel@tonic-gate 		X509V3err(X509V3_F_V2I_GENERAL_NAME,X509V3_R_BAD_IP_ADDRESS);
471*0Sstevel@tonic-gate 		ERR_add_error_data(2, "value=", value);
472*0Sstevel@tonic-gate 		goto err;
473*0Sstevel@tonic-gate 	}
474*0Sstevel@tonic-gate 	ip[0] = i1; ip[1] = i2 ; ip[2] = i3 ; ip[3] = i4;
475*0Sstevel@tonic-gate 	if(!(gen->d.ip = M_ASN1_OCTET_STRING_new()) ||
476*0Sstevel@tonic-gate 		!ASN1_STRING_set(gen->d.ip, ip, 4)) {
477*0Sstevel@tonic-gate 			X509V3err(X509V3_F_V2I_GENERAL_NAME,ERR_R_MALLOC_FAILURE);
478*0Sstevel@tonic-gate 			goto err;
479*0Sstevel@tonic-gate 	}
480*0Sstevel@tonic-gate 	type = GEN_IPADD;
481*0Sstevel@tonic-gate } else {
482*0Sstevel@tonic-gate 	X509V3err(X509V3_F_V2I_GENERAL_NAME,X509V3_R_UNSUPPORTED_OPTION);
483*0Sstevel@tonic-gate 	ERR_add_error_data(2, "name=", name);
484*0Sstevel@tonic-gate 	goto err;
485*0Sstevel@tonic-gate }
486*0Sstevel@tonic-gate 
487*0Sstevel@tonic-gate if(is_string) {
488*0Sstevel@tonic-gate 	if(!(gen->d.ia5 = M_ASN1_IA5STRING_new()) ||
489*0Sstevel@tonic-gate 		      !ASN1_STRING_set(gen->d.ia5, (unsigned char*)value,
490*0Sstevel@tonic-gate 				       strlen(value))) {
491*0Sstevel@tonic-gate 		X509V3err(X509V3_F_V2I_GENERAL_NAME,ERR_R_MALLOC_FAILURE);
492*0Sstevel@tonic-gate 		goto err;
493*0Sstevel@tonic-gate 	}
494*0Sstevel@tonic-gate }
495*0Sstevel@tonic-gate 
496*0Sstevel@tonic-gate gen->type = type;
497*0Sstevel@tonic-gate 
498*0Sstevel@tonic-gate return gen;
499*0Sstevel@tonic-gate 
500*0Sstevel@tonic-gate err:
501*0Sstevel@tonic-gate GENERAL_NAME_free(gen);
502*0Sstevel@tonic-gate return NULL;
503*0Sstevel@tonic-gate }
504