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