xref: /openbsd-src/lib/libcrypto/x509/x509_alt.c (revision 8b5faa7170599a10b7304ec693b84d6d6fd0697f)
1*8b5faa71Stb /* $OpenBSD: x509_alt.c,v 1.17 2024/07/13 15:08:58 tb Exp $ */
2e500e238Sjsing /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3e500e238Sjsing  * project.
4e500e238Sjsing  */
5e500e238Sjsing /* ====================================================================
6e500e238Sjsing  * Copyright (c) 1999-2003 The OpenSSL Project.  All rights reserved.
7e500e238Sjsing  *
8e500e238Sjsing  * Redistribution and use in source and binary forms, with or without
9e500e238Sjsing  * modification, are permitted provided that the following conditions
10e500e238Sjsing  * are met:
11e500e238Sjsing  *
12e500e238Sjsing  * 1. Redistributions of source code must retain the above copyright
13e500e238Sjsing  *    notice, this list of conditions and the following disclaimer.
14e500e238Sjsing  *
15e500e238Sjsing  * 2. Redistributions in binary form must reproduce the above copyright
16e500e238Sjsing  *    notice, this list of conditions and the following disclaimer in
17e500e238Sjsing  *    the documentation and/or other materials provided with the
18e500e238Sjsing  *    distribution.
19e500e238Sjsing  *
20e500e238Sjsing  * 3. All advertising materials mentioning features or use of this
21e500e238Sjsing  *    software must display the following acknowledgment:
22e500e238Sjsing  *    "This product includes software developed by the OpenSSL Project
23e500e238Sjsing  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24e500e238Sjsing  *
25e500e238Sjsing  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26e500e238Sjsing  *    endorse or promote products derived from this software without
27e500e238Sjsing  *    prior written permission. For written permission, please contact
28e500e238Sjsing  *    licensing@OpenSSL.org.
29e500e238Sjsing  *
30e500e238Sjsing  * 5. Products derived from this software may not be called "OpenSSL"
31e500e238Sjsing  *    nor may "OpenSSL" appear in their names without prior written
32e500e238Sjsing  *    permission of the OpenSSL Project.
33e500e238Sjsing  *
34e500e238Sjsing  * 6. Redistributions of any form whatsoever must retain the following
35e500e238Sjsing  *    acknowledgment:
36e500e238Sjsing  *    "This product includes software developed by the OpenSSL Project
37e500e238Sjsing  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38e500e238Sjsing  *
39e500e238Sjsing  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40e500e238Sjsing  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41e500e238Sjsing  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42e500e238Sjsing  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43e500e238Sjsing  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44e500e238Sjsing  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45e500e238Sjsing  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46e500e238Sjsing  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47e500e238Sjsing  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48e500e238Sjsing  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49e500e238Sjsing  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50e500e238Sjsing  * OF THE POSSIBILITY OF SUCH DAMAGE.
51e500e238Sjsing  * ====================================================================
52e500e238Sjsing  *
53e500e238Sjsing  * This product includes cryptographic software written by Eric Young
54e500e238Sjsing  * (eay@cryptsoft.com).  This product includes software written by Tim
55e500e238Sjsing  * Hudson (tjh@cryptsoft.com).
56e500e238Sjsing  *
57e500e238Sjsing  */
58e500e238Sjsing 
59e500e238Sjsing #include <stdio.h>
60e500e238Sjsing #include <string.h>
61e500e238Sjsing 
62e500e238Sjsing #include <openssl/conf.h>
63e500e238Sjsing #include <openssl/err.h>
64e500e238Sjsing #include <openssl/x509v3.h>
65e500e238Sjsing 
66e35ec605Stb #include "x509_internal.h"
67e35ec605Stb 
68e500e238Sjsing static GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method,
69e500e238Sjsing     X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval);
70e500e238Sjsing static GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method,
71e500e238Sjsing     X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval);
72e500e238Sjsing static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p);
73e500e238Sjsing static int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens);
74e500e238Sjsing static int do_othername(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx);
75e500e238Sjsing static int do_dirname(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx);
76e500e238Sjsing 
77*8b5faa71Stb static const X509V3_EXT_METHOD x509v3_ext_subject_alt_name = {
78e500e238Sjsing 	.ext_nid = NID_subject_alt_name,
79e500e238Sjsing 	.ext_flags = 0,
80e500e238Sjsing 	.it = &GENERAL_NAMES_it,
81e500e238Sjsing 	.ext_new = NULL,
82e500e238Sjsing 	.ext_free = NULL,
83e500e238Sjsing 	.d2i = NULL,
84e500e238Sjsing 	.i2d = NULL,
85e500e238Sjsing 	.i2s = NULL,
86e500e238Sjsing 	.s2i = NULL,
87e500e238Sjsing 	.i2v = (X509V3_EXT_I2V)i2v_GENERAL_NAMES,
88e500e238Sjsing 	.v2i = (X509V3_EXT_V2I)v2i_subject_alt,
89e500e238Sjsing 	.i2r = NULL,
90e500e238Sjsing 	.r2i = NULL,
91e500e238Sjsing 	.usr_data = NULL,
92*8b5faa71Stb };
93*8b5faa71Stb 
94*8b5faa71Stb const X509V3_EXT_METHOD *
x509v3_ext_method_subject_alt_name(void)95*8b5faa71Stb x509v3_ext_method_subject_alt_name(void)
96e500e238Sjsing {
97*8b5faa71Stb 	return &x509v3_ext_subject_alt_name;
98*8b5faa71Stb }
99*8b5faa71Stb 
100*8b5faa71Stb static const X509V3_EXT_METHOD x509v3_ext_issuer_alt_name = {
101e500e238Sjsing 	.ext_nid = NID_issuer_alt_name,
102e500e238Sjsing 	.ext_flags = 0,
103e500e238Sjsing 	.it = &GENERAL_NAMES_it,
104e500e238Sjsing 	.ext_new = NULL,
105e500e238Sjsing 	.ext_free = NULL,
106e500e238Sjsing 	.d2i = NULL,
107e500e238Sjsing 	.i2d = NULL,
108e500e238Sjsing 	.i2s = NULL,
109e500e238Sjsing 	.s2i = NULL,
110e500e238Sjsing 	.i2v = (X509V3_EXT_I2V)i2v_GENERAL_NAMES,
111e500e238Sjsing 	.v2i = (X509V3_EXT_V2I)v2i_issuer_alt,
112e500e238Sjsing 	.i2r = NULL,
113e500e238Sjsing 	.r2i = NULL,
114e500e238Sjsing 	.usr_data = NULL,
115*8b5faa71Stb };
116*8b5faa71Stb 
117*8b5faa71Stb const X509V3_EXT_METHOD *
x509v3_ext_method_issuer_alt_name(void)118*8b5faa71Stb x509v3_ext_method_issuer_alt_name(void)
119e500e238Sjsing {
120*8b5faa71Stb 	return &x509v3_ext_issuer_alt_name;
121*8b5faa71Stb }
122*8b5faa71Stb 
123*8b5faa71Stb static const X509V3_EXT_METHOD x509v3_ext_certificate_issuer = {
124e500e238Sjsing 	.ext_nid = NID_certificate_issuer,
125e500e238Sjsing 	.ext_flags = 0,
126e500e238Sjsing 	.it = &GENERAL_NAMES_it,
127e500e238Sjsing 	.ext_new = NULL,
128e500e238Sjsing 	.ext_free = NULL,
129e500e238Sjsing 	.d2i = NULL,
130e500e238Sjsing 	.i2d = NULL,
131e500e238Sjsing 	.i2s = NULL,
132e500e238Sjsing 	.s2i = NULL,
133e500e238Sjsing 	.i2v = (X509V3_EXT_I2V)i2v_GENERAL_NAMES,
134e500e238Sjsing 	.v2i = NULL,
135e500e238Sjsing 	.i2r = NULL,
136e500e238Sjsing 	.r2i = NULL,
137e500e238Sjsing 	.usr_data = NULL,
138e500e238Sjsing };
139e500e238Sjsing 
140*8b5faa71Stb const X509V3_EXT_METHOD *
x509v3_ext_method_certificate_issuer(void)141*8b5faa71Stb x509v3_ext_method_certificate_issuer(void)
142*8b5faa71Stb {
143*8b5faa71Stb 	return &x509v3_ext_certificate_issuer;
144*8b5faa71Stb }
145*8b5faa71Stb 
STACK_OF(CONF_VALUE)146e500e238Sjsing STACK_OF(CONF_VALUE) *
147e500e238Sjsing i2v_GENERAL_NAMES(X509V3_EXT_METHOD *method, GENERAL_NAMES *gens,
148e500e238Sjsing     STACK_OF(CONF_VALUE) *ret)
149e500e238Sjsing {
150e500e238Sjsing 	STACK_OF(CONF_VALUE) *free_ret = NULL;
151e500e238Sjsing 	GENERAL_NAME *gen;
152e500e238Sjsing 	int i;
153e500e238Sjsing 
154e500e238Sjsing 	if (ret == NULL) {
155e500e238Sjsing 		if ((free_ret = ret = sk_CONF_VALUE_new_null()) == NULL)
156e500e238Sjsing 			return NULL;
157e500e238Sjsing 	}
158e500e238Sjsing 
159e500e238Sjsing 	for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
160e500e238Sjsing 		if ((gen = sk_GENERAL_NAME_value(gens, i)) == NULL)
161e500e238Sjsing 			goto err;
162e500e238Sjsing 		if ((ret = i2v_GENERAL_NAME(method, gen, ret)) == NULL)
163e500e238Sjsing 			goto err;
164e500e238Sjsing 	}
165e500e238Sjsing 
166e500e238Sjsing 	return ret;
167e500e238Sjsing 
168e500e238Sjsing  err:
169e500e238Sjsing 	sk_CONF_VALUE_pop_free(free_ret, X509V3_conf_free);
170e500e238Sjsing 
171e500e238Sjsing 	return NULL;
172e500e238Sjsing }
173cedac418Stb LCRYPTO_ALIAS(i2v_GENERAL_NAMES);
174e500e238Sjsing 
STACK_OF(CONF_VALUE)175e500e238Sjsing STACK_OF(CONF_VALUE) *
176e500e238Sjsing i2v_GENERAL_NAME(X509V3_EXT_METHOD *method, GENERAL_NAME *gen,
177e500e238Sjsing     STACK_OF(CONF_VALUE) *ret)
178e500e238Sjsing {
179e500e238Sjsing 	STACK_OF(CONF_VALUE) *free_ret = NULL;
180e500e238Sjsing 	unsigned char *p;
181e500e238Sjsing 	char oline[256], htmp[5];
182e500e238Sjsing 	int i;
183e500e238Sjsing 
184e500e238Sjsing 	if (ret == NULL) {
185e500e238Sjsing 		if ((free_ret = ret = sk_CONF_VALUE_new_null()) == NULL)
186e500e238Sjsing 			return NULL;
187e500e238Sjsing 	}
188e500e238Sjsing 
189e500e238Sjsing 	switch (gen->type) {
190e500e238Sjsing 	case GEN_OTHERNAME:
191e500e238Sjsing 		if (!X509V3_add_value("othername", "<unsupported>", &ret))
192e500e238Sjsing 			goto err;
193e500e238Sjsing 		break;
194e500e238Sjsing 
195e500e238Sjsing 	case GEN_X400:
196e500e238Sjsing 		if (!X509V3_add_value("X400Name", "<unsupported>", &ret))
197e500e238Sjsing 			goto err;
198e500e238Sjsing 		break;
199e500e238Sjsing 
200e500e238Sjsing 	case GEN_EDIPARTY:
201e500e238Sjsing 		if (!X509V3_add_value("EdiPartyName", "<unsupported>", &ret))
202e500e238Sjsing 			goto err;
203e500e238Sjsing 		break;
204e500e238Sjsing 
205e500e238Sjsing 	case GEN_EMAIL:
206e500e238Sjsing 		if (!X509V3_add_value_uchar("email", gen->d.ia5->data, &ret))
207e500e238Sjsing 			goto err;
208e500e238Sjsing 		break;
209e500e238Sjsing 
210e500e238Sjsing 	case GEN_DNS:
211e500e238Sjsing 		if (!X509V3_add_value_uchar("DNS", gen->d.ia5->data, &ret))
212e500e238Sjsing 			goto err;
213e500e238Sjsing 		break;
214e500e238Sjsing 
215e500e238Sjsing 	case GEN_URI:
216e500e238Sjsing 		if (!X509V3_add_value_uchar("URI", gen->d.ia5->data, &ret))
217e500e238Sjsing 			goto err;
218e500e238Sjsing 		break;
219e500e238Sjsing 
220e500e238Sjsing 	case GEN_DIRNAME:
221e500e238Sjsing 		if (X509_NAME_oneline(gen->d.dirn, oline, 256) == NULL)
222e500e238Sjsing 			goto err;
223e500e238Sjsing 		if (!X509V3_add_value("DirName", oline, &ret))
224e500e238Sjsing 			goto err;
225e500e238Sjsing 		break;
226e500e238Sjsing 
227e500e238Sjsing 	case GEN_IPADD: /* XXX */
228e500e238Sjsing 		p = gen->d.ip->data;
229e500e238Sjsing 		if (gen->d.ip->length == 4)
230e500e238Sjsing 			(void) snprintf(oline, sizeof oline,
231e500e238Sjsing 			    "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
232e500e238Sjsing 		else if (gen->d.ip->length == 16) {
233e500e238Sjsing 			oline[0] = 0;
234e500e238Sjsing 			for (i = 0; i < 8; i++) {
235e500e238Sjsing 				(void) snprintf(htmp, sizeof htmp,
236e500e238Sjsing 				    "%X", p[0] << 8 | p[1]);
237e500e238Sjsing 				p += 2;
238e500e238Sjsing 				strlcat(oline, htmp, sizeof(oline));
239e500e238Sjsing 				if (i != 7)
240e500e238Sjsing 					strlcat(oline, ":", sizeof(oline));
241e500e238Sjsing 			}
242e500e238Sjsing 		} else {
243e500e238Sjsing 			if (!X509V3_add_value("IP Address", "<invalid>", &ret))
244e500e238Sjsing 				goto err;
245e500e238Sjsing 			break;
246e500e238Sjsing 		}
247e500e238Sjsing 		if (!X509V3_add_value("IP Address", oline, &ret))
248e500e238Sjsing 			goto err;
249e500e238Sjsing 		break;
250e500e238Sjsing 
251e500e238Sjsing 	case GEN_RID:
252e500e238Sjsing 		if (!i2t_ASN1_OBJECT(oline, 256, gen->d.rid))
253e500e238Sjsing 			goto err;
254e500e238Sjsing 		if (!X509V3_add_value("Registered ID", oline, &ret))
255e500e238Sjsing 			goto err;
256e500e238Sjsing 		break;
257e500e238Sjsing 	}
258e500e238Sjsing 
259e500e238Sjsing 	return ret;
260e500e238Sjsing 
261e500e238Sjsing  err:
262e500e238Sjsing 	sk_CONF_VALUE_pop_free(free_ret, X509V3_conf_free);
263e500e238Sjsing 
264e500e238Sjsing 	return NULL;
265e500e238Sjsing }
266cedac418Stb LCRYPTO_ALIAS(i2v_GENERAL_NAME);
267e500e238Sjsing 
268e500e238Sjsing int
GENERAL_NAME_print(BIO * out,GENERAL_NAME * gen)269e500e238Sjsing GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen)
270e500e238Sjsing {
271e500e238Sjsing 	unsigned char *p;
272e500e238Sjsing 	int i;
273e500e238Sjsing 
274e500e238Sjsing 	switch (gen->type) {
275e500e238Sjsing 	case GEN_OTHERNAME:
276e500e238Sjsing 		BIO_printf(out, "othername:<unsupported>");
277e500e238Sjsing 		break;
278e500e238Sjsing 
279e500e238Sjsing 	case GEN_X400:
280e500e238Sjsing 		BIO_printf(out, "X400Name:<unsupported>");
281e500e238Sjsing 		break;
282e500e238Sjsing 
283e500e238Sjsing 	case GEN_EDIPARTY:
284e500e238Sjsing 		/* Maybe fix this: it is supported now */
285e500e238Sjsing 		BIO_printf(out, "EdiPartyName:<unsupported>");
286e500e238Sjsing 		break;
287e500e238Sjsing 
288e500e238Sjsing 	case GEN_EMAIL:
2893d508f29Stb 		BIO_printf(out, "email:%.*s", gen->d.ia5->length,
2903d508f29Stb 		    gen->d.ia5->data);
291e500e238Sjsing 		break;
292e500e238Sjsing 
293e500e238Sjsing 	case GEN_DNS:
2943d508f29Stb 		BIO_printf(out, "DNS:%.*s", gen->d.ia5->length,
2953d508f29Stb 		    gen->d.ia5->data);
296e500e238Sjsing 		break;
297e500e238Sjsing 
298e500e238Sjsing 	case GEN_URI:
2993d508f29Stb 		BIO_printf(out, "URI:%.*s", gen->d.ia5->length,
3003d508f29Stb 		    gen->d.ia5->data);
301e500e238Sjsing 		break;
302e500e238Sjsing 
303e500e238Sjsing 	case GEN_DIRNAME:
304e500e238Sjsing 		BIO_printf(out, "DirName: ");
305e500e238Sjsing 		X509_NAME_print_ex(out, gen->d.dirn, 0, XN_FLAG_ONELINE);
306e500e238Sjsing 		break;
307e500e238Sjsing 
308e500e238Sjsing 	case GEN_IPADD:
309e500e238Sjsing 		p = gen->d.ip->data;
310e500e238Sjsing 		if (gen->d.ip->length == 4)
311e500e238Sjsing 			BIO_printf(out, "IP Address:%d.%d.%d.%d",
312e500e238Sjsing 			    p[0], p[1], p[2], p[3]);
313e500e238Sjsing 		else if (gen->d.ip->length == 16) {
314e500e238Sjsing 			BIO_printf(out, "IP Address");
315e500e238Sjsing 			for (i = 0; i < 8; i++) {
316e500e238Sjsing 				BIO_printf(out, ":%X", p[0] << 8 | p[1]);
317e500e238Sjsing 				p += 2;
318e500e238Sjsing 			}
319e500e238Sjsing 			BIO_puts(out, "\n");
320e500e238Sjsing 		} else {
321e500e238Sjsing 			BIO_printf(out, "IP Address:<invalid>");
322e500e238Sjsing 			break;
323e500e238Sjsing 		}
324e500e238Sjsing 		break;
325e500e238Sjsing 
326e500e238Sjsing 	case GEN_RID:
327e500e238Sjsing 		BIO_printf(out, "Registered ID");
328e500e238Sjsing 		i2a_ASN1_OBJECT(out, gen->d.rid);
329e500e238Sjsing 		break;
330e500e238Sjsing 	}
331e500e238Sjsing 	return 1;
332e500e238Sjsing }
333cedac418Stb LCRYPTO_ALIAS(GENERAL_NAME_print);
334e500e238Sjsing 
335e500e238Sjsing static GENERAL_NAMES *
v2i_issuer_alt(X509V3_EXT_METHOD * method,X509V3_CTX * ctx,STACK_OF (CONF_VALUE)* nval)336e500e238Sjsing v2i_issuer_alt(X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
337e500e238Sjsing     STACK_OF(CONF_VALUE) *nval)
338e500e238Sjsing {
339e500e238Sjsing 	GENERAL_NAMES *gens = NULL;
340e500e238Sjsing 	CONF_VALUE *cnf;
341e500e238Sjsing 	int i;
342e500e238Sjsing 
343e500e238Sjsing 	if ((gens = sk_GENERAL_NAME_new_null()) == NULL) {
344e500e238Sjsing 		X509V3error(ERR_R_MALLOC_FAILURE);
345e500e238Sjsing 		return NULL;
346e500e238Sjsing 	}
347e500e238Sjsing 	for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
348e500e238Sjsing 		cnf = sk_CONF_VALUE_value(nval, i);
349e500e238Sjsing 		if (name_cmp(cnf->name, "issuer") == 0 && cnf->value != NULL &&
350e500e238Sjsing 		    strcmp(cnf->value, "copy") == 0) {
351e500e238Sjsing 			if (!copy_issuer(ctx, gens))
352e500e238Sjsing 				goto err;
353e500e238Sjsing 		} else {
354e500e238Sjsing 			GENERAL_NAME *gen;
355e500e238Sjsing 			if ((gen = v2i_GENERAL_NAME(method, ctx, cnf)) == NULL)
356e500e238Sjsing 				goto err;
357e500e238Sjsing 			if (sk_GENERAL_NAME_push(gens, gen) == 0) {
358e500e238Sjsing 				GENERAL_NAME_free(gen);
359e500e238Sjsing 				goto err;
360e500e238Sjsing 			}
361e500e238Sjsing 		}
362e500e238Sjsing 	}
363e500e238Sjsing 	return gens;
364e500e238Sjsing 
365e500e238Sjsing err:
366e500e238Sjsing 	sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
367e500e238Sjsing 	return NULL;
368e500e238Sjsing }
369e500e238Sjsing 
370e500e238Sjsing /* Append subject altname of issuer to issuer alt name of subject */
371e500e238Sjsing 
372e500e238Sjsing static int
copy_issuer(X509V3_CTX * ctx,GENERAL_NAMES * gens)373e500e238Sjsing copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens)
374e500e238Sjsing {
375c44a4196Stb 	GENERAL_NAMES *ialt = NULL;
376c44a4196Stb 	GENERAL_NAME *gen = NULL;
377e500e238Sjsing 	X509_EXTENSION *ext;
378e500e238Sjsing 	int i;
379c44a4196Stb 	int ret = 0;
380e500e238Sjsing 
381e500e238Sjsing 	if (ctx && (ctx->flags == CTX_TEST))
382e500e238Sjsing 		return 1;
383e500e238Sjsing 	if (!ctx || !ctx->issuer_cert) {
384e500e238Sjsing 		X509V3error(X509V3_R_NO_ISSUER_DETAILS);
385e500e238Sjsing 		goto err;
386e500e238Sjsing 	}
387e500e238Sjsing 	i = X509_get_ext_by_NID(ctx->issuer_cert, NID_subject_alt_name, -1);
388e500e238Sjsing 	if (i < 0)
389e500e238Sjsing 		return 1;
390e500e238Sjsing 	if (!(ext = X509_get_ext(ctx->issuer_cert, i)) ||
391e500e238Sjsing 	    !(ialt = X509V3_EXT_d2i(ext))) {
392e500e238Sjsing 		X509V3error(X509V3_R_ISSUER_DECODE_ERROR);
393e500e238Sjsing 		goto err;
394e500e238Sjsing 	}
395e500e238Sjsing 
396e500e238Sjsing 	for (i = 0; i < sk_GENERAL_NAME_num(ialt); i++) {
397c44a4196Stb 		GENERAL_NAME *val = sk_GENERAL_NAME_value(ialt, i);
398c44a4196Stb 
399c44a4196Stb 		if ((gen = GENERAL_NAME_dup(val)) == NULL)
400c44a4196Stb 			goto err;
401e500e238Sjsing 		if (!sk_GENERAL_NAME_push(gens, gen)) {
402e500e238Sjsing 			X509V3error(ERR_R_MALLOC_FAILURE);
403e500e238Sjsing 			goto err;
404e500e238Sjsing 		}
405c44a4196Stb 		gen = NULL;
406e500e238Sjsing 	}
407e500e238Sjsing 
408c44a4196Stb 	ret = 1;
409e500e238Sjsing 
410e500e238Sjsing  err:
411c44a4196Stb 	sk_GENERAL_NAME_pop_free(ialt, GENERAL_NAME_free);
412c44a4196Stb 	GENERAL_NAME_free(gen);
413e500e238Sjsing 
414c44a4196Stb 	return ret;
415e500e238Sjsing }
416e500e238Sjsing 
417e500e238Sjsing static GENERAL_NAMES *
v2i_subject_alt(X509V3_EXT_METHOD * method,X509V3_CTX * ctx,STACK_OF (CONF_VALUE)* nval)418e500e238Sjsing v2i_subject_alt(X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
419e500e238Sjsing     STACK_OF(CONF_VALUE) *nval)
420e500e238Sjsing {
421e500e238Sjsing 	GENERAL_NAMES *gens = NULL;
422e500e238Sjsing 	CONF_VALUE *cnf;
423e500e238Sjsing 	int i;
424e500e238Sjsing 
425e500e238Sjsing 	if (!(gens = sk_GENERAL_NAME_new_null())) {
426e500e238Sjsing 		X509V3error(ERR_R_MALLOC_FAILURE);
427e500e238Sjsing 		return NULL;
428e500e238Sjsing 	}
429e500e238Sjsing 	for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
430e500e238Sjsing 		cnf = sk_CONF_VALUE_value(nval, i);
431e500e238Sjsing 		if (!name_cmp(cnf->name, "email") && cnf->value &&
432e500e238Sjsing 		    !strcmp(cnf->value, "copy")) {
433e500e238Sjsing 			if (!copy_email(ctx, gens, 0))
434e500e238Sjsing 				goto err;
435e500e238Sjsing 		} else if (!name_cmp(cnf->name, "email") && cnf->value &&
436e500e238Sjsing 		    !strcmp(cnf->value, "move")) {
437e500e238Sjsing 			if (!copy_email(ctx, gens, 1))
438e500e238Sjsing 				goto err;
439e500e238Sjsing 		} else {
440e500e238Sjsing 			GENERAL_NAME *gen;
441e500e238Sjsing 			if (!(gen = v2i_GENERAL_NAME(method, ctx, cnf)))
442e500e238Sjsing 				goto err;
443e500e238Sjsing 			if (sk_GENERAL_NAME_push(gens, gen) == 0) {
444e500e238Sjsing 				GENERAL_NAME_free(gen);
445e500e238Sjsing 				goto err;
446e500e238Sjsing 			}
447e500e238Sjsing 		}
448e500e238Sjsing 	}
449e500e238Sjsing 	return gens;
450e500e238Sjsing 
451e500e238Sjsing err:
452e500e238Sjsing 	sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
453e500e238Sjsing 	return NULL;
454e500e238Sjsing }
455e500e238Sjsing 
456e500e238Sjsing /* Copy any email addresses in a certificate or request to
457e500e238Sjsing  * GENERAL_NAMES
458e500e238Sjsing  */
459e500e238Sjsing 
460e500e238Sjsing static int
copy_email(X509V3_CTX * ctx,GENERAL_NAMES * gens,int move_p)461e500e238Sjsing copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p)
462e500e238Sjsing {
463e500e238Sjsing 	X509_NAME *nm;
464e500e238Sjsing 	ASN1_IA5STRING *email = NULL;
465e500e238Sjsing 	X509_NAME_ENTRY *ne;
466e500e238Sjsing 	GENERAL_NAME *gen = NULL;
467e500e238Sjsing 	int i;
468e500e238Sjsing 
469e500e238Sjsing 	if (ctx != NULL && ctx->flags == CTX_TEST)
470e500e238Sjsing 		return 1;
471e500e238Sjsing 	if (!ctx || (!ctx->subject_cert && !ctx->subject_req)) {
472e500e238Sjsing 		X509V3error(X509V3_R_NO_SUBJECT_DETAILS);
473e500e238Sjsing 		goto err;
474e500e238Sjsing 	}
475e500e238Sjsing 	/* Find the subject name */
476e500e238Sjsing 	if (ctx->subject_cert)
477e500e238Sjsing 		nm = X509_get_subject_name(ctx->subject_cert);
478e500e238Sjsing 	else
479e500e238Sjsing 		nm = X509_REQ_get_subject_name(ctx->subject_req);
480e500e238Sjsing 
481e500e238Sjsing 	/* Now add any email address(es) to STACK */
482e500e238Sjsing 	i = -1;
483e500e238Sjsing 	while ((i = X509_NAME_get_index_by_NID(nm,
484e500e238Sjsing 	    NID_pkcs9_emailAddress, i)) >= 0) {
485e500e238Sjsing 		ne = X509_NAME_get_entry(nm, i);
486e500e238Sjsing 		email = ASN1_STRING_dup(X509_NAME_ENTRY_get_data(ne));
487e500e238Sjsing 		if (move_p) {
488e500e238Sjsing 			X509_NAME_delete_entry(nm, i);
489e500e238Sjsing 			X509_NAME_ENTRY_free(ne);
490e500e238Sjsing 			i--;
491e500e238Sjsing 		}
492e500e238Sjsing 		if (!email || !(gen = GENERAL_NAME_new())) {
493e500e238Sjsing 			X509V3error(ERR_R_MALLOC_FAILURE);
494e500e238Sjsing 			goto err;
495e500e238Sjsing 		}
496e500e238Sjsing 		gen->d.ia5 = email;
497e500e238Sjsing 		email = NULL;
498e500e238Sjsing 		gen->type = GEN_EMAIL;
499e500e238Sjsing 		if (!sk_GENERAL_NAME_push(gens, gen)) {
500e500e238Sjsing 			X509V3error(ERR_R_MALLOC_FAILURE);
501e500e238Sjsing 			goto err;
502e500e238Sjsing 		}
503e500e238Sjsing 		gen = NULL;
504e500e238Sjsing 	}
505e500e238Sjsing 
506e500e238Sjsing 	return 1;
507e500e238Sjsing 
508e500e238Sjsing err:
509e500e238Sjsing 	GENERAL_NAME_free(gen);
510e500e238Sjsing 	ASN1_IA5STRING_free(email);
511e500e238Sjsing 	return 0;
512e500e238Sjsing }
513e500e238Sjsing 
514e500e238Sjsing GENERAL_NAMES *
v2i_GENERAL_NAMES(const X509V3_EXT_METHOD * method,X509V3_CTX * ctx,STACK_OF (CONF_VALUE)* nval)515e500e238Sjsing v2i_GENERAL_NAMES(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
516e500e238Sjsing     STACK_OF(CONF_VALUE) *nval)
517e500e238Sjsing {
518e500e238Sjsing 	GENERAL_NAME *gen;
519e500e238Sjsing 	GENERAL_NAMES *gens = NULL;
520e500e238Sjsing 	CONF_VALUE *cnf;
521e500e238Sjsing 	int i;
522e500e238Sjsing 
523e500e238Sjsing 	if (!(gens = sk_GENERAL_NAME_new_null())) {
524e500e238Sjsing 		X509V3error(ERR_R_MALLOC_FAILURE);
525e500e238Sjsing 		return NULL;
526e500e238Sjsing 	}
527e500e238Sjsing 	for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
528e500e238Sjsing 		cnf = sk_CONF_VALUE_value(nval, i);
529e500e238Sjsing 		if (!(gen = v2i_GENERAL_NAME(method, ctx, cnf)))
530e500e238Sjsing 			goto err;
531e500e238Sjsing 		if (sk_GENERAL_NAME_push(gens, gen) == 0) {
532e500e238Sjsing 			GENERAL_NAME_free(gen);
533e500e238Sjsing 			goto err;
534e500e238Sjsing 		}
535e500e238Sjsing 	}
536e500e238Sjsing 	return gens;
537e500e238Sjsing 
538e500e238Sjsing err:
539e500e238Sjsing 	sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
540e500e238Sjsing 	return NULL;
541e500e238Sjsing }
542cedac418Stb LCRYPTO_ALIAS(v2i_GENERAL_NAMES);
543e500e238Sjsing 
544e500e238Sjsing GENERAL_NAME *
v2i_GENERAL_NAME(const X509V3_EXT_METHOD * method,X509V3_CTX * ctx,CONF_VALUE * cnf)545e500e238Sjsing v2i_GENERAL_NAME(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
546e500e238Sjsing     CONF_VALUE *cnf)
547e500e238Sjsing {
548e500e238Sjsing 	return v2i_GENERAL_NAME_ex(NULL, method, ctx, cnf, 0);
549e500e238Sjsing }
550cedac418Stb LCRYPTO_ALIAS(v2i_GENERAL_NAME);
551e500e238Sjsing 
552e500e238Sjsing GENERAL_NAME *
a2i_GENERAL_NAME(GENERAL_NAME * out,const X509V3_EXT_METHOD * method,X509V3_CTX * ctx,int gen_type,const char * value,int is_nc)553e500e238Sjsing a2i_GENERAL_NAME(GENERAL_NAME *out, const X509V3_EXT_METHOD *method,
554e500e238Sjsing     X509V3_CTX *ctx, int gen_type, const char *value, int is_nc)
555e500e238Sjsing {
556e500e238Sjsing 	char is_string = 0;
557e500e238Sjsing 	GENERAL_NAME *gen = NULL;
558e500e238Sjsing 
559e500e238Sjsing 	if (!value) {
560e500e238Sjsing 		X509V3error(X509V3_R_MISSING_VALUE);
561e500e238Sjsing 		return NULL;
562e500e238Sjsing 	}
563e500e238Sjsing 
564e500e238Sjsing 	if (out)
565e500e238Sjsing 		gen = out;
566e500e238Sjsing 	else {
567e500e238Sjsing 		gen = GENERAL_NAME_new();
568e500e238Sjsing 		if (gen == NULL) {
569e500e238Sjsing 			X509V3error(ERR_R_MALLOC_FAILURE);
570e500e238Sjsing 			return NULL;
571e500e238Sjsing 		}
572e500e238Sjsing 	}
573e500e238Sjsing 
574e500e238Sjsing 	switch (gen_type) {
575e500e238Sjsing 	case GEN_URI:
576e500e238Sjsing 	case GEN_EMAIL:
577e500e238Sjsing 	case GEN_DNS:
578e500e238Sjsing 		is_string = 1;
579e500e238Sjsing 		break;
580e500e238Sjsing 
581e500e238Sjsing 	case GEN_RID:
582e500e238Sjsing 		{
583e500e238Sjsing 			ASN1_OBJECT *obj;
584e500e238Sjsing 			if (!(obj = OBJ_txt2obj(value, 0))) {
585e500e238Sjsing 				X509V3error(X509V3_R_BAD_OBJECT);
586e500e238Sjsing 				ERR_asprintf_error_data("value=%s", value);
587e500e238Sjsing 				goto err;
588e500e238Sjsing 			}
589e500e238Sjsing 			gen->d.rid = obj;
590e500e238Sjsing 		}
591e500e238Sjsing 		break;
592e500e238Sjsing 
593e500e238Sjsing 	case GEN_IPADD:
594e500e238Sjsing 		if (is_nc)
595e500e238Sjsing 			gen->d.ip = a2i_IPADDRESS_NC(value);
596e500e238Sjsing 		else
597e500e238Sjsing 			gen->d.ip = a2i_IPADDRESS(value);
598e500e238Sjsing 		if (gen->d.ip == NULL) {
599e500e238Sjsing 			X509V3error(X509V3_R_BAD_IP_ADDRESS);
600e500e238Sjsing 			ERR_asprintf_error_data("value=%s", value);
601e500e238Sjsing 			goto err;
602e500e238Sjsing 		}
603e500e238Sjsing 		break;
604e500e238Sjsing 
605e500e238Sjsing 	case GEN_DIRNAME:
606e500e238Sjsing 		if (!do_dirname(gen, value, ctx)) {
607e500e238Sjsing 			X509V3error(X509V3_R_DIRNAME_ERROR);
608e500e238Sjsing 			goto err;
609e500e238Sjsing 		}
610e500e238Sjsing 		break;
611e500e238Sjsing 
612e500e238Sjsing 	case GEN_OTHERNAME:
613e500e238Sjsing 		if (!do_othername(gen, value, ctx)) {
614e500e238Sjsing 			X509V3error(X509V3_R_OTHERNAME_ERROR);
615e500e238Sjsing 			goto err;
616e500e238Sjsing 		}
617e500e238Sjsing 		break;
618e500e238Sjsing 
619e500e238Sjsing 	default:
620e500e238Sjsing 		X509V3error(X509V3_R_UNSUPPORTED_TYPE);
621e500e238Sjsing 		goto err;
622e500e238Sjsing 	}
623e500e238Sjsing 
624e500e238Sjsing 	if (is_string) {
625e500e238Sjsing 		if (!(gen->d.ia5 = ASN1_IA5STRING_new()) ||
626e500e238Sjsing 		    !ASN1_STRING_set(gen->d.ia5, value, strlen(value))) {
627e500e238Sjsing 			X509V3error(ERR_R_MALLOC_FAILURE);
628e500e238Sjsing 			goto err;
629e500e238Sjsing 		}
630e500e238Sjsing 	}
631e500e238Sjsing 
632e500e238Sjsing 	gen->type = gen_type;
633e500e238Sjsing 
634e500e238Sjsing 	return gen;
635e500e238Sjsing 
636e500e238Sjsing err:
637e500e238Sjsing 	if (out == NULL)
638e500e238Sjsing 		GENERAL_NAME_free(gen);
639e500e238Sjsing 	return NULL;
640e500e238Sjsing }
641cedac418Stb LCRYPTO_ALIAS(a2i_GENERAL_NAME);
642e500e238Sjsing 
643e500e238Sjsing GENERAL_NAME *
v2i_GENERAL_NAME_ex(GENERAL_NAME * out,const X509V3_EXT_METHOD * method,X509V3_CTX * ctx,CONF_VALUE * cnf,int is_nc)644e500e238Sjsing v2i_GENERAL_NAME_ex(GENERAL_NAME *out, const X509V3_EXT_METHOD *method,
645e500e238Sjsing     X509V3_CTX *ctx, CONF_VALUE *cnf, int is_nc)
646e500e238Sjsing {
647e35ec605Stb 	uint8_t *bytes = NULL;
648d6e0e7c7Sbeck 	char *name, *value;
649e35ec605Stb 	GENERAL_NAME *ret;
650e35ec605Stb 	size_t len = 0;
651e35ec605Stb 	int type;
652f06436f8Sbeck 	CBS cbs;
653e500e238Sjsing 
654e500e238Sjsing 	name = cnf->name;
655e500e238Sjsing 	value = cnf->value;
656e500e238Sjsing 
657e500e238Sjsing 	if (!value) {
658e500e238Sjsing 		X509V3error(X509V3_R_MISSING_VALUE);
659e500e238Sjsing 		return NULL;
660e500e238Sjsing 	}
661e500e238Sjsing 
662e500e238Sjsing 	if (!name_cmp(name, "email"))
663e500e238Sjsing 		type = GEN_EMAIL;
664e500e238Sjsing 	else if (!name_cmp(name, "URI"))
665e500e238Sjsing 		type = GEN_URI;
666e500e238Sjsing 	else if (!name_cmp(name, "DNS"))
667e500e238Sjsing 		type = GEN_DNS;
668e500e238Sjsing 	else if (!name_cmp(name, "RID"))
669e500e238Sjsing 		type = GEN_RID;
670e500e238Sjsing 	else if (!name_cmp(name, "IP"))
671e500e238Sjsing 		type = GEN_IPADD;
672e500e238Sjsing 	else if (!name_cmp(name, "dirName"))
673e500e238Sjsing 		type = GEN_DIRNAME;
674e500e238Sjsing 	else if (!name_cmp(name, "otherName"))
675e500e238Sjsing 		type = GEN_OTHERNAME;
676e500e238Sjsing 	else {
677e500e238Sjsing 		X509V3error(X509V3_R_UNSUPPORTED_OPTION);
678e500e238Sjsing 		ERR_asprintf_error_data("name=%s", name);
679e500e238Sjsing 		return NULL;
680e500e238Sjsing 	}
681e500e238Sjsing 
682e35ec605Stb 	ret = a2i_GENERAL_NAME(out, method, ctx, type, value, is_nc);
683b6505d5cStb 	if (ret == NULL)
684b6505d5cStb 		return NULL;
685e35ec605Stb 
686b7c79982Stb 	/*
687b7c79982Stb 	 * Validate what we have for sanity.
688b7c79982Stb 	 */
689b7c79982Stb 
690b7c79982Stb 	if (is_nc) {
691a7f2167bStb 		struct x509_constraints_name *constraints_name = NULL;
692b7c79982Stb 
693a7f2167bStb 		if (!x509_constraints_validate(ret, &constraints_name, NULL)) {
694b7c79982Stb 			X509V3error(X509V3_R_BAD_OBJECT);
695b7c79982Stb 			ERR_asprintf_error_data("name=%s", name);
696b7c79982Stb 			goto err;
697b7c79982Stb 		}
698a7f2167bStb 		x509_constraints_name_free(constraints_name);
699b7c79982Stb 		return ret;
700b7c79982Stb 	}
701b7c79982Stb 
702e35ec605Stb 	type = x509_constraints_general_to_bytes(ret, &bytes, &len);
703f06436f8Sbeck 	CBS_init(&cbs, bytes, len);
704e35ec605Stb 	switch (type) {
705e35ec605Stb 	case GEN_DNS:
706f06436f8Sbeck 		if (!x509_constraints_valid_sandns(&cbs)) {
707e35ec605Stb 			X509V3error(X509V3_R_BAD_OBJECT);
708a8034bb6Stb 			ERR_asprintf_error_data("name=%s value='%.*s'", name,
709a8034bb6Stb 			    (int)len, bytes);
710e35ec605Stb 			goto err;
711e35ec605Stb 		}
712e35ec605Stb 		break;
713e35ec605Stb 	case GEN_URI:
714e35ec605Stb 		if (!x509_constraints_uri_host(bytes, len, NULL)) {
715e35ec605Stb 			X509V3error(X509V3_R_BAD_OBJECT);
716a8034bb6Stb 			ERR_asprintf_error_data("name=%s value='%.*s'", name,
717a8034bb6Stb 			    (int)len, bytes);
718e35ec605Stb 			goto err;
719e35ec605Stb 		}
720e35ec605Stb 		break;
721e35ec605Stb 	case GEN_EMAIL:
722f06436f8Sbeck 		if (!x509_constraints_parse_mailbox(&cbs, NULL)) {
723e35ec605Stb 			X509V3error(X509V3_R_BAD_OBJECT);
724a8034bb6Stb 			ERR_asprintf_error_data("name=%s value='%.*s'", name,
725a8034bb6Stb 			    (int)len, bytes);
726e35ec605Stb 			goto err;
727e35ec605Stb 		}
728e35ec605Stb 		break;
729e35ec605Stb 	case GEN_IPADD:
730b7c79982Stb 		if (len != 4 && len != 16) {
731e35ec605Stb 			X509V3error(X509V3_R_BAD_IP_ADDRESS);
732e35ec605Stb 			ERR_asprintf_error_data("name=%s len=%zu", name, len);
733e35ec605Stb 			goto err;
734e35ec605Stb 		}
735e35ec605Stb 		break;
736e35ec605Stb 	default:
737e35ec605Stb 		break;
738e35ec605Stb 	}
739e35ec605Stb 	return ret;
740e35ec605Stb  err:
741fdcc2361Stb 	if (out == NULL)
742e35ec605Stb 		GENERAL_NAME_free(ret);
743e35ec605Stb 	return NULL;
744e500e238Sjsing }
745cedac418Stb LCRYPTO_ALIAS(v2i_GENERAL_NAME_ex);
746e500e238Sjsing 
747e500e238Sjsing static int
do_othername(GENERAL_NAME * gen,const char * value,X509V3_CTX * ctx)748e500e238Sjsing do_othername(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx)
749e500e238Sjsing {
750e500e238Sjsing 	char *objtmp = NULL, *p;
751e500e238Sjsing 	int objlen;
752e500e238Sjsing 
753e500e238Sjsing 	if (!(p = strchr(value, ';')))
754e500e238Sjsing 		return 0;
755e500e238Sjsing 	if (!(gen->d.otherName = OTHERNAME_new()))
756e500e238Sjsing 		return 0;
757e500e238Sjsing 	/* Free this up because we will overwrite it.
758e500e238Sjsing 	 * no need to free type_id because it is static
759e500e238Sjsing 	 */
760e500e238Sjsing 	ASN1_TYPE_free(gen->d.otherName->value);
761e500e238Sjsing 	if (!(gen->d.otherName->value = ASN1_generate_v3(p + 1, ctx)))
762e500e238Sjsing 		return 0;
763e500e238Sjsing 	objlen = p - value;
764e500e238Sjsing 	objtmp = malloc(objlen + 1);
765e500e238Sjsing 	if (objtmp) {
766e500e238Sjsing 		strlcpy(objtmp, value, objlen + 1);
767e500e238Sjsing 		gen->d.otherName->type_id = OBJ_txt2obj(objtmp, 0);
768e500e238Sjsing 		free(objtmp);
769e500e238Sjsing 	} else
770e500e238Sjsing 		gen->d.otherName->type_id = NULL;
771e500e238Sjsing 	if (!gen->d.otherName->type_id)
772e500e238Sjsing 		return 0;
773e500e238Sjsing 	return 1;
774e500e238Sjsing }
775e500e238Sjsing 
776e500e238Sjsing static int
do_dirname(GENERAL_NAME * gen,const char * value,X509V3_CTX * ctx)777e500e238Sjsing do_dirname(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx)
778e500e238Sjsing {
779e500e238Sjsing 	int ret;
780e500e238Sjsing 	STACK_OF(CONF_VALUE) *sk;
781e500e238Sjsing 	X509_NAME *nm;
782e500e238Sjsing 
783e500e238Sjsing 	if (!(nm = X509_NAME_new()))
784e500e238Sjsing 		return 0;
785e500e238Sjsing 	sk = X509V3_get_section(ctx, value);
786e500e238Sjsing 	if (!sk) {
787e500e238Sjsing 		X509V3error(X509V3_R_SECTION_NOT_FOUND);
788e500e238Sjsing 		ERR_asprintf_error_data("section=%s", value);
789e500e238Sjsing 		X509_NAME_free(nm);
790e500e238Sjsing 		return 0;
791e500e238Sjsing 	}
792e500e238Sjsing 	/* FIXME: should allow other character types... */
793e500e238Sjsing 	ret = X509V3_NAME_from_section(nm, sk, MBSTRING_ASC);
794e500e238Sjsing 	if (!ret)
795e500e238Sjsing 		X509_NAME_free(nm);
796e500e238Sjsing 	gen->d.dirn = nm;
797e500e238Sjsing 	X509V3_section_free(ctx, sk);
798e500e238Sjsing 
799e500e238Sjsing 	return ret;
800e500e238Sjsing }
801