blob: 6123ac3e436cfd4aadad65f69080b68538785a89 [file] [log] [blame]
Adam Langley95c29f32014-06-20 12:00:00 -07001/* v3_alt.c */
Adam Langley57707c72016-01-14 11:25:12 -08002/*
3 * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
Adam Langley95c29f32014-06-20 12:00:00 -07004 * project.
5 */
6/* ====================================================================
7 * Copyright (c) 1999-2003 The OpenSSL Project. All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
Adam Langley57707c72016-01-14 11:25:12 -080014 * notice, this list of conditions and the following disclaimer.
Adam Langley95c29f32014-06-20 12:00:00 -070015 *
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in
18 * the documentation and/or other materials provided with the
19 * distribution.
20 *
21 * 3. All advertising materials mentioning features or use of this
22 * software must display the following acknowledgment:
23 * "This product includes software developed by the OpenSSL Project
24 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25 *
26 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27 * endorse or promote products derived from this software without
28 * prior written permission. For written permission, please contact
29 * licensing@OpenSSL.org.
30 *
31 * 5. Products derived from this software may not be called "OpenSSL"
32 * nor may "OpenSSL" appear in their names without prior written
33 * permission of the OpenSSL Project.
34 *
35 * 6. Redistributions of any form whatsoever must retain the following
36 * acknowledgment:
37 * "This product includes software developed by the OpenSSL Project
38 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
39 *
40 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
44 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51 * OF THE POSSIBILITY OF SUCH DAMAGE.
52 * ====================================================================
53 *
54 * This product includes cryptographic software written by Eric Young
55 * (eay@cryptsoft.com). This product includes software written by Tim
56 * Hudson (tjh@cryptsoft.com). */
57
58#include <stdio.h>
Adam Langley2b2d66d2015-01-30 17:08:37 -080059#include <string.h>
Adam Langley95c29f32014-06-20 12:00:00 -070060
61#include <openssl/conf.h>
62#include <openssl/err.h>
63#include <openssl/mem.h>
64#include <openssl/obj.h>
65#include <openssl/x509v3.h>
66
David Benjamin2cbc39a2021-10-21 13:18:33 -040067#include "../x509/internal.h"
David Benjamin045ee412018-11-26 16:46:54 -060068#include "internal.h"
69
70
David Benjamin2d4f1b82022-05-23 14:56:15 -040071static void *v2i_subject_alt(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
72 STACK_OF(CONF_VALUE) *nval);
73static void *v2i_issuer_alt(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
74 STACK_OF(CONF_VALUE) *nval);
Adam Langley95c29f32014-06-20 12:00:00 -070075static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p);
76static int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens);
David Benjamina93545c2020-11-05 12:52:28 -050077static int do_othername(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx);
78static int do_dirname(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx);
Adam Langley95c29f32014-06-20 12:00:00 -070079
David Benjamin2d4f1b82022-05-23 14:56:15 -040080static STACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES_cb(
David Benjamin260a10c2022-06-16 13:58:28 -040081 const X509V3_EXT_METHOD *method, void *ext, STACK_OF(CONF_VALUE) *ret) {
82 return i2v_GENERAL_NAMES(method, ext, ret);
David Benjamin2d4f1b82022-05-23 14:56:15 -040083}
84
Adam Langley95c29f32014-06-20 12:00:00 -070085const X509V3_EXT_METHOD v3_alt[] = {
David Benjamin260a10c2022-06-16 13:58:28 -040086 {NID_subject_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES), 0, 0, 0, 0, 0, 0,
87 i2v_GENERAL_NAMES_cb, v2i_subject_alt, NULL, NULL, NULL},
Adam Langley95c29f32014-06-20 12:00:00 -070088
David Benjamin260a10c2022-06-16 13:58:28 -040089 {NID_issuer_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES), 0, 0, 0, 0, 0, 0,
90 i2v_GENERAL_NAMES_cb, v2i_issuer_alt, NULL, NULL, NULL},
Adam Langley95c29f32014-06-20 12:00:00 -070091
David Benjamin260a10c2022-06-16 13:58:28 -040092 {NID_certificate_issuer, 0, ASN1_ITEM_ref(GENERAL_NAMES), 0, 0, 0, 0, 0, 0,
93 i2v_GENERAL_NAMES_cb, NULL, NULL, NULL, NULL},
Adam Langley95c29f32014-06-20 12:00:00 -070094};
95
David Benjamin2d4f1b82022-05-23 14:56:15 -040096STACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES(const X509V3_EXT_METHOD *method,
Adam Langley57707c72016-01-14 11:25:12 -080097 GENERAL_NAMES *gens,
David Benjamin260a10c2022-06-16 13:58:28 -040098 STACK_OF(CONF_VALUE) *ret) {
99 int ret_was_null = ret == NULL;
100 for (size_t i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
101 GENERAL_NAME *gen = sk_GENERAL_NAME_value(gens, i);
102 STACK_OF(CONF_VALUE) *tmp = i2v_GENERAL_NAME(method, gen, ret);
103 if (tmp == NULL) {
104 if (ret_was_null) {
105 sk_CONF_VALUE_pop_free(ret, X509V3_conf_free);
106 }
107 return NULL;
Adam Langley57707c72016-01-14 11:25:12 -0800108 }
David Benjamin260a10c2022-06-16 13:58:28 -0400109 ret = tmp;
110 }
David Benjaminc0b87a02022-06-16 14:02:15 -0400111 if (!ret) {
David Benjamin260a10c2022-06-16 13:58:28 -0400112 return sk_CONF_VALUE_new_null();
David Benjaminc0b87a02022-06-16 14:02:15 -0400113 }
David Benjamin260a10c2022-06-16 13:58:28 -0400114 return ret;
Adam Langley95c29f32014-06-20 12:00:00 -0700115}
116
David Benjamin2d4f1b82022-05-23 14:56:15 -0400117STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(const X509V3_EXT_METHOD *method,
Adam Langley57707c72016-01-14 11:25:12 -0800118 GENERAL_NAME *gen,
David Benjamin260a10c2022-06-16 13:58:28 -0400119 STACK_OF(CONF_VALUE) *ret) {
David Benjamin46350482022-06-16 14:03:12 -0400120 // Note the error-handling for this function relies on there being at most
121 // one |X509V3_add_value| call. If there were two and the second failed, we
122 // would need to sometimes free the first call's result.
David Benjamin260a10c2022-06-16 13:58:28 -0400123 unsigned char *p;
124 char oline[256], htmp[5];
125 int i;
126 switch (gen->type) {
Adam Langley57707c72016-01-14 11:25:12 -0800127 case GEN_OTHERNAME:
David Benjaminc0b87a02022-06-16 14:02:15 -0400128 if (!X509V3_add_value("othername", "<unsupported>", &ret)) {
David Benjamin260a10c2022-06-16 13:58:28 -0400129 return NULL;
David Benjaminc0b87a02022-06-16 14:02:15 -0400130 }
David Benjamin260a10c2022-06-16 13:58:28 -0400131 break;
Adam Langley95c29f32014-06-20 12:00:00 -0700132
Adam Langley57707c72016-01-14 11:25:12 -0800133 case GEN_X400:
David Benjaminc0b87a02022-06-16 14:02:15 -0400134 if (!X509V3_add_value("X400Name", "<unsupported>", &ret)) {
David Benjamin260a10c2022-06-16 13:58:28 -0400135 return NULL;
David Benjaminc0b87a02022-06-16 14:02:15 -0400136 }
David Benjamin260a10c2022-06-16 13:58:28 -0400137 break;
Adam Langley95c29f32014-06-20 12:00:00 -0700138
Adam Langley57707c72016-01-14 11:25:12 -0800139 case GEN_EDIPARTY:
David Benjaminc0b87a02022-06-16 14:02:15 -0400140 if (!X509V3_add_value("EdiPartyName", "<unsupported>", &ret)) {
David Benjamin260a10c2022-06-16 13:58:28 -0400141 return NULL;
David Benjaminc0b87a02022-06-16 14:02:15 -0400142 }
David Benjamin260a10c2022-06-16 13:58:28 -0400143 break;
Adam Langley95c29f32014-06-20 12:00:00 -0700144
Adam Langley57707c72016-01-14 11:25:12 -0800145 case GEN_EMAIL:
David Benjaminc0b87a02022-06-16 14:02:15 -0400146 if (!x509V3_add_value_asn1_string("email", gen->d.ia5, &ret)) {
David Benjamin260a10c2022-06-16 13:58:28 -0400147 return NULL;
David Benjaminc0b87a02022-06-16 14:02:15 -0400148 }
David Benjamin260a10c2022-06-16 13:58:28 -0400149 break;
Adam Langley95c29f32014-06-20 12:00:00 -0700150
Adam Langley57707c72016-01-14 11:25:12 -0800151 case GEN_DNS:
David Benjaminc0b87a02022-06-16 14:02:15 -0400152 if (!x509V3_add_value_asn1_string("DNS", gen->d.ia5, &ret)) {
David Benjamin260a10c2022-06-16 13:58:28 -0400153 return NULL;
David Benjaminc0b87a02022-06-16 14:02:15 -0400154 }
David Benjamin260a10c2022-06-16 13:58:28 -0400155 break;
Adam Langley95c29f32014-06-20 12:00:00 -0700156
Adam Langley57707c72016-01-14 11:25:12 -0800157 case GEN_URI:
David Benjaminc0b87a02022-06-16 14:02:15 -0400158 if (!x509V3_add_value_asn1_string("URI", gen->d.ia5, &ret)) {
David Benjamin260a10c2022-06-16 13:58:28 -0400159 return NULL;
David Benjaminc0b87a02022-06-16 14:02:15 -0400160 }
David Benjamin260a10c2022-06-16 13:58:28 -0400161 break;
Adam Langley95c29f32014-06-20 12:00:00 -0700162
Adam Langley57707c72016-01-14 11:25:12 -0800163 case GEN_DIRNAME:
David Benjamin260a10c2022-06-16 13:58:28 -0400164 if (X509_NAME_oneline(gen->d.dirn, oline, 256) == NULL ||
David Benjaminc0b87a02022-06-16 14:02:15 -0400165 !X509V3_add_value("DirName", oline, &ret)) {
David Benjamin260a10c2022-06-16 13:58:28 -0400166 return NULL;
David Benjaminc0b87a02022-06-16 14:02:15 -0400167 }
David Benjamin260a10c2022-06-16 13:58:28 -0400168 break;
Adam Langley95c29f32014-06-20 12:00:00 -0700169
Adam Langley57707c72016-01-14 11:25:12 -0800170 case GEN_IPADD:
David Benjamin260a10c2022-06-16 13:58:28 -0400171 p = gen->d.ip->data;
David Benjaminc0b87a02022-06-16 14:02:15 -0400172 if (gen->d.ip->length == 4) {
David Benjamin260a10c2022-06-16 13:58:28 -0400173 BIO_snprintf(oline, sizeof(oline), "%d.%d.%d.%d", p[0], p[1], p[2],
174 p[3]);
David Benjaminc0b87a02022-06-16 14:02:15 -0400175 } else if (gen->d.ip->length == 16) {
David Benjamin260a10c2022-06-16 13:58:28 -0400176 oline[0] = 0;
177 for (i = 0; i < 8; i++) {
178 uint16_t v = ((uint16_t)p[0] << 8) | p[1];
179 BIO_snprintf(htmp, sizeof(htmp), "%X", v);
180 p += 2;
181 OPENSSL_strlcat(oline, htmp, sizeof(oline));
David Benjaminc0b87a02022-06-16 14:02:15 -0400182 if (i != 7) {
David Benjamin260a10c2022-06-16 13:58:28 -0400183 OPENSSL_strlcat(oline, ":", sizeof(oline));
David Benjaminc0b87a02022-06-16 14:02:15 -0400184 }
Adam Langley57707c72016-01-14 11:25:12 -0800185 }
David Benjamin260a10c2022-06-16 13:58:28 -0400186 } else {
David Benjaminc0b87a02022-06-16 14:02:15 -0400187 if (!X509V3_add_value("IP Address", "<invalid>", &ret)) {
David Benjamin260a10c2022-06-16 13:58:28 -0400188 return NULL;
David Benjaminc0b87a02022-06-16 14:02:15 -0400189 }
Adam Langley57707c72016-01-14 11:25:12 -0800190 break;
David Benjamin260a10c2022-06-16 13:58:28 -0400191 }
David Benjaminc0b87a02022-06-16 14:02:15 -0400192 if (!X509V3_add_value("IP Address", oline, &ret)) {
David Benjamin260a10c2022-06-16 13:58:28 -0400193 return NULL;
David Benjaminc0b87a02022-06-16 14:02:15 -0400194 }
David Benjamin260a10c2022-06-16 13:58:28 -0400195 break;
Adam Langley95c29f32014-06-20 12:00:00 -0700196
Adam Langley57707c72016-01-14 11:25:12 -0800197 case GEN_RID:
David Benjamin260a10c2022-06-16 13:58:28 -0400198 i2t_ASN1_OBJECT(oline, 256, gen->d.rid);
David Benjaminc0b87a02022-06-16 14:02:15 -0400199 if (!X509V3_add_value("Registered ID", oline, &ret)) {
David Benjamin260a10c2022-06-16 13:58:28 -0400200 return NULL;
David Benjaminc0b87a02022-06-16 14:02:15 -0400201 }
David Benjamin260a10c2022-06-16 13:58:28 -0400202 break;
203 }
204 return ret;
Adam Langley95c29f32014-06-20 12:00:00 -0700205}
206
David Benjamin260a10c2022-06-16 13:58:28 -0400207int GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen) {
208 unsigned char *p;
209 int i;
210 switch (gen->type) {
Adam Langley57707c72016-01-14 11:25:12 -0800211 case GEN_OTHERNAME:
David Benjamin260a10c2022-06-16 13:58:28 -0400212 BIO_printf(out, "othername:<unsupported>");
213 break;
Adam Langley95c29f32014-06-20 12:00:00 -0700214
Adam Langley57707c72016-01-14 11:25:12 -0800215 case GEN_X400:
David Benjamin260a10c2022-06-16 13:58:28 -0400216 BIO_printf(out, "X400Name:<unsupported>");
217 break;
Adam Langley95c29f32014-06-20 12:00:00 -0700218
Adam Langley57707c72016-01-14 11:25:12 -0800219 case GEN_EDIPARTY:
David Benjamin46350482022-06-16 14:03:12 -0400220 // Maybe fix this: it is supported now
David Benjamin260a10c2022-06-16 13:58:28 -0400221 BIO_printf(out, "EdiPartyName:<unsupported>");
222 break;
Adam Langley95c29f32014-06-20 12:00:00 -0700223
Adam Langley57707c72016-01-14 11:25:12 -0800224 case GEN_EMAIL:
David Benjamin260a10c2022-06-16 13:58:28 -0400225 BIO_printf(out, "email:");
226 ASN1_STRING_print(out, gen->d.ia5);
227 break;
Adam Langley95c29f32014-06-20 12:00:00 -0700228
Adam Langley57707c72016-01-14 11:25:12 -0800229 case GEN_DNS:
David Benjamin260a10c2022-06-16 13:58:28 -0400230 BIO_printf(out, "DNS:");
231 ASN1_STRING_print(out, gen->d.ia5);
232 break;
Adam Langley95c29f32014-06-20 12:00:00 -0700233
Adam Langley57707c72016-01-14 11:25:12 -0800234 case GEN_URI:
David Benjamin260a10c2022-06-16 13:58:28 -0400235 BIO_printf(out, "URI:");
236 ASN1_STRING_print(out, gen->d.ia5);
237 break;
Adam Langley95c29f32014-06-20 12:00:00 -0700238
Adam Langley57707c72016-01-14 11:25:12 -0800239 case GEN_DIRNAME:
David Benjamin260a10c2022-06-16 13:58:28 -0400240 BIO_printf(out, "DirName: ");
241 X509_NAME_print_ex(out, gen->d.dirn, 0, XN_FLAG_ONELINE);
242 break;
Adam Langley95c29f32014-06-20 12:00:00 -0700243
Adam Langley57707c72016-01-14 11:25:12 -0800244 case GEN_IPADD:
David Benjamin260a10c2022-06-16 13:58:28 -0400245 p = gen->d.ip->data;
David Benjaminc0b87a02022-06-16 14:02:15 -0400246 if (gen->d.ip->length == 4) {
David Benjamin260a10c2022-06-16 13:58:28 -0400247 BIO_printf(out, "IP Address:%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
David Benjaminc0b87a02022-06-16 14:02:15 -0400248 } else if (gen->d.ip->length == 16) {
David Benjamin260a10c2022-06-16 13:58:28 -0400249 BIO_printf(out, "IP Address");
250 for (i = 0; i < 8; i++) {
251 uint16_t v = ((uint16_t)p[0] << 8) | p[1];
252 BIO_printf(out, ":%X", v);
253 p += 2;
Adam Langley57707c72016-01-14 11:25:12 -0800254 }
David Benjamin260a10c2022-06-16 13:58:28 -0400255 BIO_puts(out, "\n");
256 } else {
257 BIO_printf(out, "IP Address:<invalid>");
Adam Langley57707c72016-01-14 11:25:12 -0800258 break;
David Benjamin260a10c2022-06-16 13:58:28 -0400259 }
260 break;
Adam Langley95c29f32014-06-20 12:00:00 -0700261
Adam Langley57707c72016-01-14 11:25:12 -0800262 case GEN_RID:
David Benjamin260a10c2022-06-16 13:58:28 -0400263 BIO_printf(out, "Registered ID");
264 i2a_ASN1_OBJECT(out, gen->d.rid);
265 break;
266 }
267 return 1;
Adam Langley95c29f32014-06-20 12:00:00 -0700268}
269
David Benjamin2d4f1b82022-05-23 14:56:15 -0400270static void *v2i_issuer_alt(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
David Benjamin260a10c2022-06-16 13:58:28 -0400271 STACK_OF(CONF_VALUE) *nval) {
272 GENERAL_NAMES *gens = NULL;
273 CONF_VALUE *cnf;
274 size_t i;
275 if (!(gens = sk_GENERAL_NAME_new_null())) {
276 OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
Adam Langley57707c72016-01-14 11:25:12 -0800277 return NULL;
David Benjamin260a10c2022-06-16 13:58:28 -0400278 }
279 for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
280 cnf = sk_CONF_VALUE_value(nval, i);
David Benjaminde5bb392022-11-23 16:32:07 -0500281 if (x509v3_conf_name_matches(cnf->name, "issuer") && cnf->value &&
David Benjamin260a10c2022-06-16 13:58:28 -0400282 !strcmp(cnf->value, "copy")) {
David Benjaminc0b87a02022-06-16 14:02:15 -0400283 if (!copy_issuer(ctx, gens)) {
David Benjamin260a10c2022-06-16 13:58:28 -0400284 goto err;
David Benjaminc0b87a02022-06-16 14:02:15 -0400285 }
David Benjamin260a10c2022-06-16 13:58:28 -0400286 } else {
287 GENERAL_NAME *gen;
David Benjaminc0b87a02022-06-16 14:02:15 -0400288 if (!(gen = v2i_GENERAL_NAME(method, ctx, cnf))) {
David Benjamin260a10c2022-06-16 13:58:28 -0400289 goto err;
David Benjaminc0b87a02022-06-16 14:02:15 -0400290 }
David Benjamin260a10c2022-06-16 13:58:28 -0400291 sk_GENERAL_NAME_push(gens, gen);
292 }
293 }
294 return gens;
295err:
296 sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
297 return NULL;
Adam Langley95c29f32014-06-20 12:00:00 -0700298}
299
David Benjamin46350482022-06-16 14:03:12 -0400300// Append subject altname of issuer to issuer alt name of subject
Adam Langley95c29f32014-06-20 12:00:00 -0700301
David Benjamin260a10c2022-06-16 13:58:28 -0400302static int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens) {
David Benjaminc0b87a02022-06-16 14:02:15 -0400303 if (ctx && (ctx->flags == CTX_TEST)) {
David Benjamin260a10c2022-06-16 13:58:28 -0400304 return 1;
David Benjaminc0b87a02022-06-16 14:02:15 -0400305 }
David Benjamin260a10c2022-06-16 13:58:28 -0400306 if (!ctx || !ctx->issuer_cert) {
307 OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_ISSUER_DETAILS);
308 return 0;
309 }
310 int i = X509_get_ext_by_NID(ctx->issuer_cert, NID_subject_alt_name, -1);
David Benjaminc0b87a02022-06-16 14:02:15 -0400311 if (i < 0) {
David Benjamin260a10c2022-06-16 13:58:28 -0400312 return 1;
David Benjaminc0b87a02022-06-16 14:02:15 -0400313 }
David Benjamin723faad2020-10-02 16:11:10 -0400314
David Benjamin260a10c2022-06-16 13:58:28 -0400315 int ret = 0;
316 GENERAL_NAMES *ialt = NULL;
317 X509_EXTENSION *ext;
318 if (!(ext = X509_get_ext(ctx->issuer_cert, i)) ||
319 !(ialt = X509V3_EXT_d2i(ext))) {
320 OPENSSL_PUT_ERROR(X509V3, X509V3_R_ISSUER_DECODE_ERROR);
321 goto err;
322 }
Adam Langley95c29f32014-06-20 12:00:00 -0700323
David Benjamin260a10c2022-06-16 13:58:28 -0400324 for (size_t j = 0; j < sk_GENERAL_NAME_num(ialt); j++) {
325 GENERAL_NAME *gen = sk_GENERAL_NAME_value(ialt, j);
326 if (!sk_GENERAL_NAME_push(gens, gen)) {
327 OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
328 goto err;
Adam Langley57707c72016-01-14 11:25:12 -0800329 }
David Benjamin46350482022-06-16 14:03:12 -0400330 // Ownership of |gen| has moved from |ialt| to |gens|.
David Benjamin260a10c2022-06-16 13:58:28 -0400331 sk_GENERAL_NAME_set(ialt, j, NULL);
332 }
Adam Langley95c29f32014-06-20 12:00:00 -0700333
David Benjamin260a10c2022-06-16 13:58:28 -0400334 ret = 1;
Adam Langley57707c72016-01-14 11:25:12 -0800335
David Benjamin723faad2020-10-02 16:11:10 -0400336err:
David Benjamin260a10c2022-06-16 13:58:28 -0400337 GENERAL_NAMES_free(ialt);
338 return ret;
Adam Langley95c29f32014-06-20 12:00:00 -0700339}
340
David Benjamin2d4f1b82022-05-23 14:56:15 -0400341static void *v2i_subject_alt(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
David Benjamin260a10c2022-06-16 13:58:28 -0400342 STACK_OF(CONF_VALUE) *nval) {
343 GENERAL_NAMES *gens = NULL;
344 CONF_VALUE *cnf;
345 size_t i;
346 if (!(gens = sk_GENERAL_NAME_new_null())) {
347 OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
Adam Langley57707c72016-01-14 11:25:12 -0800348 return NULL;
David Benjamin260a10c2022-06-16 13:58:28 -0400349 }
350 for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
351 cnf = sk_CONF_VALUE_value(nval, i);
David Benjaminde5bb392022-11-23 16:32:07 -0500352 if (x509v3_conf_name_matches(cnf->name, "email") && cnf->value &&
David Benjamin260a10c2022-06-16 13:58:28 -0400353 !strcmp(cnf->value, "copy")) {
David Benjaminc0b87a02022-06-16 14:02:15 -0400354 if (!copy_email(ctx, gens, 0)) {
David Benjamin260a10c2022-06-16 13:58:28 -0400355 goto err;
David Benjaminc0b87a02022-06-16 14:02:15 -0400356 }
David Benjaminde5bb392022-11-23 16:32:07 -0500357 } else if (x509v3_conf_name_matches(cnf->name, "email") && cnf->value &&
David Benjamin260a10c2022-06-16 13:58:28 -0400358 !strcmp(cnf->value, "move")) {
David Benjaminc0b87a02022-06-16 14:02:15 -0400359 if (!copy_email(ctx, gens, 1)) {
David Benjamin260a10c2022-06-16 13:58:28 -0400360 goto err;
David Benjaminc0b87a02022-06-16 14:02:15 -0400361 }
David Benjamin260a10c2022-06-16 13:58:28 -0400362 } else {
363 GENERAL_NAME *gen;
David Benjaminc0b87a02022-06-16 14:02:15 -0400364 if (!(gen = v2i_GENERAL_NAME(method, ctx, cnf))) {
David Benjamin260a10c2022-06-16 13:58:28 -0400365 goto err;
David Benjaminc0b87a02022-06-16 14:02:15 -0400366 }
David Benjamin260a10c2022-06-16 13:58:28 -0400367 sk_GENERAL_NAME_push(gens, gen);
368 }
369 }
370 return gens;
371err:
372 sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
373 return NULL;
Adam Langley95c29f32014-06-20 12:00:00 -0700374}
375
David Benjamin46350482022-06-16 14:03:12 -0400376// Copy any email addresses in a certificate or request to GENERAL_NAMES
Adam Langley95c29f32014-06-20 12:00:00 -0700377
David Benjamin260a10c2022-06-16 13:58:28 -0400378static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p) {
379 X509_NAME *nm;
380 ASN1_IA5STRING *email = NULL;
381 X509_NAME_ENTRY *ne;
382 GENERAL_NAME *gen = NULL;
383 int i;
David Benjaminc0b87a02022-06-16 14:02:15 -0400384 if (ctx != NULL && ctx->flags == CTX_TEST) {
Adam Langley57707c72016-01-14 11:25:12 -0800385 return 1;
David Benjaminc0b87a02022-06-16 14:02:15 -0400386 }
David Benjamin260a10c2022-06-16 13:58:28 -0400387 if (!ctx || (!ctx->subject_cert && !ctx->subject_req)) {
388 OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_SUBJECT_DETAILS);
389 goto err;
390 }
David Benjamin46350482022-06-16 14:03:12 -0400391 // Find the subject name
David Benjaminc0b87a02022-06-16 14:02:15 -0400392 if (ctx->subject_cert) {
David Benjamin260a10c2022-06-16 13:58:28 -0400393 nm = X509_get_subject_name(ctx->subject_cert);
David Benjaminc0b87a02022-06-16 14:02:15 -0400394 } else {
David Benjamin260a10c2022-06-16 13:58:28 -0400395 nm = X509_REQ_get_subject_name(ctx->subject_req);
David Benjaminc0b87a02022-06-16 14:02:15 -0400396 }
Adam Langley57707c72016-01-14 11:25:12 -0800397
David Benjamin46350482022-06-16 14:03:12 -0400398 // Now add any email address(es) to STACK
David Benjamin260a10c2022-06-16 13:58:28 -0400399 i = -1;
400 while ((i = X509_NAME_get_index_by_NID(nm, NID_pkcs9_emailAddress, i)) >= 0) {
401 ne = X509_NAME_get_entry(nm, i);
402 email = ASN1_STRING_dup(X509_NAME_ENTRY_get_data(ne));
403 if (move_p) {
404 X509_NAME_delete_entry(nm, i);
405 X509_NAME_ENTRY_free(ne);
406 i--;
407 }
408 if (!email || !(gen = GENERAL_NAME_new())) {
409 OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
410 goto err;
411 }
412 gen->d.ia5 = email;
413 email = NULL;
414 gen->type = GEN_EMAIL;
415 if (!sk_GENERAL_NAME_push(gens, gen)) {
416 OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
417 goto err;
418 }
419 gen = NULL;
420 }
Adam Langley57707c72016-01-14 11:25:12 -0800421
David Benjamin260a10c2022-06-16 13:58:28 -0400422 return 1;
423
424err:
425 GENERAL_NAME_free(gen);
426 ASN1_IA5STRING_free(email);
427 return 0;
Adam Langley95c29f32014-06-20 12:00:00 -0700428}
429
430GENERAL_NAMES *v2i_GENERAL_NAMES(const X509V3_EXT_METHOD *method,
David Benjamin260a10c2022-06-16 13:58:28 -0400431 X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval) {
432 GENERAL_NAME *gen;
433 GENERAL_NAMES *gens = NULL;
434 CONF_VALUE *cnf;
435 size_t i;
436 if (!(gens = sk_GENERAL_NAME_new_null())) {
437 OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
Adam Langley57707c72016-01-14 11:25:12 -0800438 return NULL;
David Benjamin260a10c2022-06-16 13:58:28 -0400439 }
440 for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
441 cnf = sk_CONF_VALUE_value(nval, i);
David Benjaminc0b87a02022-06-16 14:02:15 -0400442 if (!(gen = v2i_GENERAL_NAME(method, ctx, cnf))) {
David Benjamin260a10c2022-06-16 13:58:28 -0400443 goto err;
David Benjaminc0b87a02022-06-16 14:02:15 -0400444 }
David Benjamin260a10c2022-06-16 13:58:28 -0400445 sk_GENERAL_NAME_push(gens, gen);
446 }
447 return gens;
448err:
449 sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
450 return NULL;
Adam Langley95c29f32014-06-20 12:00:00 -0700451}
452
David Benjamin260a10c2022-06-16 13:58:28 -0400453GENERAL_NAME *v2i_GENERAL_NAME(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
454 CONF_VALUE *cnf) {
455 return v2i_GENERAL_NAME_ex(NULL, method, ctx, cnf, 0);
Adam Langley57707c72016-01-14 11:25:12 -0800456}
Adam Langley95c29f32014-06-20 12:00:00 -0700457
458GENERAL_NAME *a2i_GENERAL_NAME(GENERAL_NAME *out,
David Benjamin260a10c2022-06-16 13:58:28 -0400459 const X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
460 int gen_type, const char *value, int is_nc) {
461 char is_string = 0;
462 GENERAL_NAME *gen = NULL;
Adam Langley95c29f32014-06-20 12:00:00 -0700463
David Benjamin260a10c2022-06-16 13:58:28 -0400464 if (!value) {
465 OPENSSL_PUT_ERROR(X509V3, X509V3_R_MISSING_VALUE);
466 return NULL;
467 }
468
David Benjaminc0b87a02022-06-16 14:02:15 -0400469 if (out) {
David Benjamin260a10c2022-06-16 13:58:28 -0400470 gen = out;
David Benjaminc0b87a02022-06-16 14:02:15 -0400471 } else {
David Benjamin260a10c2022-06-16 13:58:28 -0400472 gen = GENERAL_NAME_new();
473 if (gen == NULL) {
474 OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
475 return NULL;
Adam Langley57707c72016-01-14 11:25:12 -0800476 }
David Benjamin260a10c2022-06-16 13:58:28 -0400477 }
Adam Langley95c29f32014-06-20 12:00:00 -0700478
David Benjamin260a10c2022-06-16 13:58:28 -0400479 switch (gen_type) {
Adam Langley57707c72016-01-14 11:25:12 -0800480 case GEN_URI:
481 case GEN_EMAIL:
482 case GEN_DNS:
David Benjamin260a10c2022-06-16 13:58:28 -0400483 is_string = 1;
484 break;
Adam Langley95c29f32014-06-20 12:00:00 -0700485
David Benjamin260a10c2022-06-16 13:58:28 -0400486 case GEN_RID: {
487 ASN1_OBJECT *obj;
488 if (!(obj = OBJ_txt2obj(value, 0))) {
489 OPENSSL_PUT_ERROR(X509V3, X509V3_R_BAD_OBJECT);
490 ERR_add_error_data(2, "value=", value);
491 goto err;
492 }
493 gen->d.rid = obj;
494 } break;
Adam Langley95c29f32014-06-20 12:00:00 -0700495
Adam Langley57707c72016-01-14 11:25:12 -0800496 case GEN_IPADD:
David Benjaminc0b87a02022-06-16 14:02:15 -0400497 if (is_nc) {
David Benjamin260a10c2022-06-16 13:58:28 -0400498 gen->d.ip = a2i_IPADDRESS_NC(value);
David Benjaminc0b87a02022-06-16 14:02:15 -0400499 } else {
David Benjamin260a10c2022-06-16 13:58:28 -0400500 gen->d.ip = a2i_IPADDRESS(value);
David Benjaminc0b87a02022-06-16 14:02:15 -0400501 }
David Benjamin260a10c2022-06-16 13:58:28 -0400502 if (gen->d.ip == NULL) {
503 OPENSSL_PUT_ERROR(X509V3, X509V3_R_BAD_IP_ADDRESS);
504 ERR_add_error_data(2, "value=", value);
505 goto err;
506 }
507 break;
Adam Langley95c29f32014-06-20 12:00:00 -0700508
Adam Langley57707c72016-01-14 11:25:12 -0800509 case GEN_DIRNAME:
David Benjamin260a10c2022-06-16 13:58:28 -0400510 if (!do_dirname(gen, value, ctx)) {
511 OPENSSL_PUT_ERROR(X509V3, X509V3_R_DIRNAME_ERROR);
512 goto err;
513 }
514 break;
Adam Langley95c29f32014-06-20 12:00:00 -0700515
Adam Langley57707c72016-01-14 11:25:12 -0800516 case GEN_OTHERNAME:
David Benjamin260a10c2022-06-16 13:58:28 -0400517 if (!do_othername(gen, value, ctx)) {
518 OPENSSL_PUT_ERROR(X509V3, X509V3_R_OTHERNAME_ERROR);
Adam Langley57707c72016-01-14 11:25:12 -0800519 goto err;
David Benjamin260a10c2022-06-16 13:58:28 -0400520 }
521 break;
522 default:
523 OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNSUPPORTED_TYPE);
524 goto err;
525 }
526
527 if (is_string) {
528 if (!(gen->d.ia5 = ASN1_IA5STRING_new()) ||
529 !ASN1_STRING_set(gen->d.ia5, (unsigned char *)value, strlen(value))) {
530 OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
531 goto err;
Adam Langley57707c72016-01-14 11:25:12 -0800532 }
David Benjamin260a10c2022-06-16 13:58:28 -0400533 }
Adam Langley95c29f32014-06-20 12:00:00 -0700534
David Benjamin260a10c2022-06-16 13:58:28 -0400535 gen->type = gen_type;
Adam Langley95c29f32014-06-20 12:00:00 -0700536
David Benjamin260a10c2022-06-16 13:58:28 -0400537 return gen;
Adam Langley95c29f32014-06-20 12:00:00 -0700538
David Benjamin260a10c2022-06-16 13:58:28 -0400539err:
David Benjaminc0b87a02022-06-16 14:02:15 -0400540 if (!out) {
David Benjamin260a10c2022-06-16 13:58:28 -0400541 GENERAL_NAME_free(gen);
David Benjaminc0b87a02022-06-16 14:02:15 -0400542 }
David Benjamin260a10c2022-06-16 13:58:28 -0400543 return NULL;
Adam Langley57707c72016-01-14 11:25:12 -0800544}
Adam Langley95c29f32014-06-20 12:00:00 -0700545
546GENERAL_NAME *v2i_GENERAL_NAME_ex(GENERAL_NAME *out,
Adam Langley57707c72016-01-14 11:25:12 -0800547 const X509V3_EXT_METHOD *method,
David Benjamin260a10c2022-06-16 13:58:28 -0400548 X509V3_CTX *ctx, CONF_VALUE *cnf, int is_nc) {
549 int type;
Adam Langley95c29f32014-06-20 12:00:00 -0700550
David Benjamin260a10c2022-06-16 13:58:28 -0400551 char *name, *value;
Adam Langley95c29f32014-06-20 12:00:00 -0700552
David Benjamin260a10c2022-06-16 13:58:28 -0400553 name = cnf->name;
554 value = cnf->value;
Adam Langley95c29f32014-06-20 12:00:00 -0700555
David Benjamin260a10c2022-06-16 13:58:28 -0400556 if (!value) {
557 OPENSSL_PUT_ERROR(X509V3, X509V3_R_MISSING_VALUE);
558 return NULL;
559 }
Adam Langley95c29f32014-06-20 12:00:00 -0700560
David Benjaminde5bb392022-11-23 16:32:07 -0500561 if (x509v3_conf_name_matches(name, "email")) {
David Benjamin260a10c2022-06-16 13:58:28 -0400562 type = GEN_EMAIL;
David Benjaminde5bb392022-11-23 16:32:07 -0500563 } else if (x509v3_conf_name_matches(name, "URI")) {
David Benjamin260a10c2022-06-16 13:58:28 -0400564 type = GEN_URI;
David Benjaminde5bb392022-11-23 16:32:07 -0500565 } else if (x509v3_conf_name_matches(name, "DNS")) {
David Benjamin260a10c2022-06-16 13:58:28 -0400566 type = GEN_DNS;
David Benjaminde5bb392022-11-23 16:32:07 -0500567 } else if (x509v3_conf_name_matches(name, "RID")) {
David Benjamin260a10c2022-06-16 13:58:28 -0400568 type = GEN_RID;
David Benjaminde5bb392022-11-23 16:32:07 -0500569 } else if (x509v3_conf_name_matches(name, "IP")) {
David Benjamin260a10c2022-06-16 13:58:28 -0400570 type = GEN_IPADD;
David Benjaminde5bb392022-11-23 16:32:07 -0500571 } else if (x509v3_conf_name_matches(name, "dirName")) {
David Benjamin260a10c2022-06-16 13:58:28 -0400572 type = GEN_DIRNAME;
David Benjaminde5bb392022-11-23 16:32:07 -0500573 } else if (x509v3_conf_name_matches(name, "otherName")) {
David Benjamin260a10c2022-06-16 13:58:28 -0400574 type = GEN_OTHERNAME;
David Benjaminc0b87a02022-06-16 14:02:15 -0400575 } else {
David Benjamin260a10c2022-06-16 13:58:28 -0400576 OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNSUPPORTED_OPTION);
577 ERR_add_error_data(2, "name=", name);
578 return NULL;
579 }
Adam Langley95c29f32014-06-20 12:00:00 -0700580
David Benjamin260a10c2022-06-16 13:58:28 -0400581 return a2i_GENERAL_NAME(out, method, ctx, type, value, is_nc);
Adam Langley57707c72016-01-14 11:25:12 -0800582}
Adam Langley95c29f32014-06-20 12:00:00 -0700583
David Benjamin260a10c2022-06-16 13:58:28 -0400584static int do_othername(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx) {
585 char *objtmp = NULL;
586 const char *p;
587 int objlen;
David Benjaminc0b87a02022-06-16 14:02:15 -0400588 if (!(p = strchr(value, ';'))) {
David Benjamin260a10c2022-06-16 13:58:28 -0400589 return 0;
David Benjaminc0b87a02022-06-16 14:02:15 -0400590 }
591 if (!(gen->d.otherName = OTHERNAME_new())) {
David Benjamin260a10c2022-06-16 13:58:28 -0400592 return 0;
David Benjaminc0b87a02022-06-16 14:02:15 -0400593 }
David Benjamin46350482022-06-16 14:03:12 -0400594 // Free this up because we will overwrite it. no need to free type_id
595 // because it is static
David Benjamin260a10c2022-06-16 13:58:28 -0400596 ASN1_TYPE_free(gen->d.otherName->value);
David Benjaminc0b87a02022-06-16 14:02:15 -0400597 if (!(gen->d.otherName->value = ASN1_generate_v3(p + 1, ctx))) {
David Benjamin260a10c2022-06-16 13:58:28 -0400598 return 0;
David Benjaminc0b87a02022-06-16 14:02:15 -0400599 }
David Benjamin260a10c2022-06-16 13:58:28 -0400600 objlen = p - value;
601 objtmp = OPENSSL_malloc(objlen + 1);
David Benjaminc0b87a02022-06-16 14:02:15 -0400602 if (objtmp == NULL) {
David Benjamin260a10c2022-06-16 13:58:28 -0400603 return 0;
David Benjaminc0b87a02022-06-16 14:02:15 -0400604 }
David Benjamin260a10c2022-06-16 13:58:28 -0400605 OPENSSL_strlcpy(objtmp, value, objlen + 1);
606 gen->d.otherName->type_id = OBJ_txt2obj(objtmp, 0);
607 OPENSSL_free(objtmp);
David Benjaminc0b87a02022-06-16 14:02:15 -0400608 if (!gen->d.otherName->type_id) {
David Benjamin260a10c2022-06-16 13:58:28 -0400609 return 0;
David Benjaminc0b87a02022-06-16 14:02:15 -0400610 }
David Benjamin260a10c2022-06-16 13:58:28 -0400611 return 1;
Adam Langley57707c72016-01-14 11:25:12 -0800612}
Adam Langley95c29f32014-06-20 12:00:00 -0700613
David Benjamin260a10c2022-06-16 13:58:28 -0400614static int do_dirname(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx) {
615 int ret = 0;
616 STACK_OF(CONF_VALUE) *sk = NULL;
617 X509_NAME *nm = X509_NAME_new();
David Benjaminc0b87a02022-06-16 14:02:15 -0400618 if (nm == NULL) {
David Benjamin260a10c2022-06-16 13:58:28 -0400619 goto err;
David Benjaminc0b87a02022-06-16 14:02:15 -0400620 }
David Benjamin260a10c2022-06-16 13:58:28 -0400621 sk = X509V3_get_section(ctx, value);
622 if (sk == NULL) {
623 OPENSSL_PUT_ERROR(X509V3, X509V3_R_SECTION_NOT_FOUND);
624 ERR_add_error_data(2, "section=", value);
625 goto err;
626 }
David Benjamin46350482022-06-16 14:03:12 -0400627 // FIXME: should allow other character types...
David Benjaminc0b87a02022-06-16 14:02:15 -0400628 if (!X509V3_NAME_from_section(nm, sk, MBSTRING_ASC)) {
David Benjamin260a10c2022-06-16 13:58:28 -0400629 goto err;
David Benjaminc0b87a02022-06-16 14:02:15 -0400630 }
David Benjamin260a10c2022-06-16 13:58:28 -0400631 gen->d.dirn = nm;
632 ret = 1;
David Benjamin17dd9042015-10-23 19:04:02 -0400633
David Benjamin260a10c2022-06-16 13:58:28 -0400634err:
David Benjaminc0b87a02022-06-16 14:02:15 -0400635 if (!ret) {
David Benjamin260a10c2022-06-16 13:58:28 -0400636 X509_NAME_free(nm);
David Benjaminc0b87a02022-06-16 14:02:15 -0400637 }
David Benjamin260a10c2022-06-16 13:58:28 -0400638 X509V3_section_free(ctx, sk);
639 return ret;
Adam Langley57707c72016-01-14 11:25:12 -0800640}