1b077aed3SPierre Pronchery /*
2b077aed3SPierre Pronchery * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
3b077aed3SPierre Pronchery *
4b077aed3SPierre Pronchery * Licensed under the Apache License 2.0 (the "License"). You may not use
5b077aed3SPierre Pronchery * this file except in compliance with the License. You can obtain a copy
6b077aed3SPierre Pronchery * in the file LICENSE in the source distribution or at
7b077aed3SPierre Pronchery * https://www.openssl.org/source/license.html
8b077aed3SPierre Pronchery */
9b077aed3SPierre Pronchery
10b077aed3SPierre Pronchery #include <stdio.h>
11b077aed3SPierre Pronchery #include "internal/cryptlib.h"
12b077aed3SPierre Pronchery #include "crypto/x509.h"
13b077aed3SPierre Pronchery #include <openssl/conf.h>
14b077aed3SPierre Pronchery #include <openssl/x509v3.h>
15b077aed3SPierre Pronchery #include <openssl/bio.h>
16b077aed3SPierre Pronchery #include "ext_dat.h"
17b077aed3SPierre Pronchery
18b077aed3SPierre Pronchery static GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method,
19b077aed3SPierre Pronchery X509V3_CTX *ctx,
20b077aed3SPierre Pronchery STACK_OF(CONF_VALUE) *nval);
21b077aed3SPierre Pronchery static GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method,
22b077aed3SPierre Pronchery X509V3_CTX *ctx,
23b077aed3SPierre Pronchery STACK_OF(CONF_VALUE) *nval);
24b077aed3SPierre Pronchery static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p);
25b077aed3SPierre Pronchery static int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens);
26b077aed3SPierre Pronchery static int do_othername(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx);
27b077aed3SPierre Pronchery static int do_dirname(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx);
28b077aed3SPierre Pronchery
29b077aed3SPierre Pronchery const X509V3_EXT_METHOD ossl_v3_alt[3] = {
30b077aed3SPierre Pronchery {NID_subject_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES),
31b077aed3SPierre Pronchery 0, 0, 0, 0,
32b077aed3SPierre Pronchery 0, 0,
33b077aed3SPierre Pronchery (X509V3_EXT_I2V) i2v_GENERAL_NAMES,
34b077aed3SPierre Pronchery (X509V3_EXT_V2I)v2i_subject_alt,
35b077aed3SPierre Pronchery NULL, NULL, NULL},
36b077aed3SPierre Pronchery
37b077aed3SPierre Pronchery {NID_issuer_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES),
38b077aed3SPierre Pronchery 0, 0, 0, 0,
39b077aed3SPierre Pronchery 0, 0,
40b077aed3SPierre Pronchery (X509V3_EXT_I2V) i2v_GENERAL_NAMES,
41b077aed3SPierre Pronchery (X509V3_EXT_V2I)v2i_issuer_alt,
42b077aed3SPierre Pronchery NULL, NULL, NULL},
43b077aed3SPierre Pronchery
44b077aed3SPierre Pronchery {NID_certificate_issuer, 0, ASN1_ITEM_ref(GENERAL_NAMES),
45b077aed3SPierre Pronchery 0, 0, 0, 0,
46b077aed3SPierre Pronchery 0, 0,
47b077aed3SPierre Pronchery (X509V3_EXT_I2V) i2v_GENERAL_NAMES,
48b077aed3SPierre Pronchery NULL, NULL, NULL, NULL},
49b077aed3SPierre Pronchery };
50b077aed3SPierre Pronchery
STACK_OF(CONF_VALUE)51b077aed3SPierre Pronchery STACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES(X509V3_EXT_METHOD *method,
52b077aed3SPierre Pronchery GENERAL_NAMES *gens,
53b077aed3SPierre Pronchery STACK_OF(CONF_VALUE) *ret)
54b077aed3SPierre Pronchery {
55b077aed3SPierre Pronchery int i;
56b077aed3SPierre Pronchery GENERAL_NAME *gen;
57b077aed3SPierre Pronchery STACK_OF(CONF_VALUE) *tmpret = NULL, *origret = ret;
58b077aed3SPierre Pronchery
59b077aed3SPierre Pronchery for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
60b077aed3SPierre Pronchery gen = sk_GENERAL_NAME_value(gens, i);
61b077aed3SPierre Pronchery /*
62b077aed3SPierre Pronchery * i2v_GENERAL_NAME allocates ret if it is NULL. If something goes
63b077aed3SPierre Pronchery * wrong we need to free the stack - but only if it was empty when we
64b077aed3SPierre Pronchery * originally entered this function.
65b077aed3SPierre Pronchery */
66b077aed3SPierre Pronchery tmpret = i2v_GENERAL_NAME(method, gen, ret);
67b077aed3SPierre Pronchery if (tmpret == NULL) {
68b077aed3SPierre Pronchery if (origret == NULL)
69b077aed3SPierre Pronchery sk_CONF_VALUE_pop_free(ret, X509V3_conf_free);
70b077aed3SPierre Pronchery return NULL;
71b077aed3SPierre Pronchery }
72b077aed3SPierre Pronchery ret = tmpret;
73b077aed3SPierre Pronchery }
74b077aed3SPierre Pronchery if (ret == NULL)
75b077aed3SPierre Pronchery return sk_CONF_VALUE_new_null();
76b077aed3SPierre Pronchery return ret;
77b077aed3SPierre Pronchery }
78b077aed3SPierre Pronchery
STACK_OF(CONF_VALUE)79b077aed3SPierre Pronchery STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method,
80b077aed3SPierre Pronchery GENERAL_NAME *gen,
81b077aed3SPierre Pronchery STACK_OF(CONF_VALUE) *ret)
82b077aed3SPierre Pronchery {
83b077aed3SPierre Pronchery char othername[300];
84b077aed3SPierre Pronchery char oline[256], *tmp;
85b077aed3SPierre Pronchery
86b077aed3SPierre Pronchery switch (gen->type) {
87b077aed3SPierre Pronchery case GEN_OTHERNAME:
88b077aed3SPierre Pronchery switch (OBJ_obj2nid(gen->d.otherName->type_id)) {
89b077aed3SPierre Pronchery case NID_id_on_SmtpUTF8Mailbox:
90b077aed3SPierre Pronchery if (gen->d.otherName->value->type != V_ASN1_UTF8STRING
91b077aed3SPierre Pronchery || !x509v3_add_len_value_uchar("othername: SmtpUTF8Mailbox:",
92b077aed3SPierre Pronchery gen->d.otherName->value->value.utf8string->data,
93b077aed3SPierre Pronchery gen->d.otherName->value->value.utf8string->length,
94b077aed3SPierre Pronchery &ret))
95b077aed3SPierre Pronchery return NULL;
96b077aed3SPierre Pronchery break;
97b077aed3SPierre Pronchery case NID_XmppAddr:
98b077aed3SPierre Pronchery if (gen->d.otherName->value->type != V_ASN1_UTF8STRING
99b077aed3SPierre Pronchery || !x509v3_add_len_value_uchar("othername: XmppAddr:",
100b077aed3SPierre Pronchery gen->d.otherName->value->value.utf8string->data,
101b077aed3SPierre Pronchery gen->d.otherName->value->value.utf8string->length,
102b077aed3SPierre Pronchery &ret))
103b077aed3SPierre Pronchery return NULL;
104b077aed3SPierre Pronchery break;
105b077aed3SPierre Pronchery case NID_SRVName:
106b077aed3SPierre Pronchery if (gen->d.otherName->value->type != V_ASN1_IA5STRING
107b077aed3SPierre Pronchery || !x509v3_add_len_value_uchar("othername: SRVName:",
108b077aed3SPierre Pronchery gen->d.otherName->value->value.ia5string->data,
109b077aed3SPierre Pronchery gen->d.otherName->value->value.ia5string->length,
110b077aed3SPierre Pronchery &ret))
111b077aed3SPierre Pronchery return NULL;
112b077aed3SPierre Pronchery break;
113b077aed3SPierre Pronchery case NID_ms_upn:
114b077aed3SPierre Pronchery if (gen->d.otherName->value->type != V_ASN1_UTF8STRING
115b077aed3SPierre Pronchery || !x509v3_add_len_value_uchar("othername: UPN:",
116b077aed3SPierre Pronchery gen->d.otherName->value->value.utf8string->data,
117b077aed3SPierre Pronchery gen->d.otherName->value->value.utf8string->length,
118b077aed3SPierre Pronchery &ret))
119b077aed3SPierre Pronchery return NULL;
120b077aed3SPierre Pronchery break;
121b077aed3SPierre Pronchery case NID_NAIRealm:
122b077aed3SPierre Pronchery if (gen->d.otherName->value->type != V_ASN1_UTF8STRING
123b077aed3SPierre Pronchery || !x509v3_add_len_value_uchar("othername: NAIRealm:",
124b077aed3SPierre Pronchery gen->d.otherName->value->value.utf8string->data,
125b077aed3SPierre Pronchery gen->d.otherName->value->value.utf8string->length,
126b077aed3SPierre Pronchery &ret))
127b077aed3SPierre Pronchery return NULL;
128b077aed3SPierre Pronchery break;
129b077aed3SPierre Pronchery default:
130b077aed3SPierre Pronchery if (OBJ_obj2txt(oline, sizeof(oline), gen->d.otherName->type_id, 0) > 0)
131b077aed3SPierre Pronchery BIO_snprintf(othername, sizeof(othername), "othername: %s:",
132b077aed3SPierre Pronchery oline);
133b077aed3SPierre Pronchery else
134b077aed3SPierre Pronchery OPENSSL_strlcpy(othername, "othername:", sizeof(othername));
135b077aed3SPierre Pronchery
136b077aed3SPierre Pronchery /* check if the value is something printable */
137b077aed3SPierre Pronchery if (gen->d.otherName->value->type == V_ASN1_IA5STRING) {
138b077aed3SPierre Pronchery if (x509v3_add_len_value_uchar(othername,
139b077aed3SPierre Pronchery gen->d.otherName->value->value.ia5string->data,
140b077aed3SPierre Pronchery gen->d.otherName->value->value.ia5string->length,
141b077aed3SPierre Pronchery &ret))
142b077aed3SPierre Pronchery return ret;
143b077aed3SPierre Pronchery }
144b077aed3SPierre Pronchery if (gen->d.otherName->value->type == V_ASN1_UTF8STRING) {
145b077aed3SPierre Pronchery if (x509v3_add_len_value_uchar(othername,
146b077aed3SPierre Pronchery gen->d.otherName->value->value.utf8string->data,
147b077aed3SPierre Pronchery gen->d.otherName->value->value.utf8string->length,
148b077aed3SPierre Pronchery &ret))
149b077aed3SPierre Pronchery return ret;
150b077aed3SPierre Pronchery }
151b077aed3SPierre Pronchery if (!X509V3_add_value(othername, "<unsupported>", &ret))
152b077aed3SPierre Pronchery return NULL;
153b077aed3SPierre Pronchery break;
154b077aed3SPierre Pronchery }
155b077aed3SPierre Pronchery break;
156b077aed3SPierre Pronchery
157b077aed3SPierre Pronchery case GEN_X400:
158b077aed3SPierre Pronchery if (!X509V3_add_value("X400Name", "<unsupported>", &ret))
159b077aed3SPierre Pronchery return NULL;
160b077aed3SPierre Pronchery break;
161b077aed3SPierre Pronchery
162b077aed3SPierre Pronchery case GEN_EDIPARTY:
163b077aed3SPierre Pronchery if (!X509V3_add_value("EdiPartyName", "<unsupported>", &ret))
164b077aed3SPierre Pronchery return NULL;
165b077aed3SPierre Pronchery break;
166b077aed3SPierre Pronchery
167b077aed3SPierre Pronchery case GEN_EMAIL:
168b077aed3SPierre Pronchery if (!x509v3_add_len_value_uchar("email", gen->d.ia5->data,
169b077aed3SPierre Pronchery gen->d.ia5->length, &ret))
170b077aed3SPierre Pronchery return NULL;
171b077aed3SPierre Pronchery break;
172b077aed3SPierre Pronchery
173b077aed3SPierre Pronchery case GEN_DNS:
174b077aed3SPierre Pronchery if (!x509v3_add_len_value_uchar("DNS", gen->d.ia5->data,
175b077aed3SPierre Pronchery gen->d.ia5->length, &ret))
176b077aed3SPierre Pronchery return NULL;
177b077aed3SPierre Pronchery break;
178b077aed3SPierre Pronchery
179b077aed3SPierre Pronchery case GEN_URI:
180b077aed3SPierre Pronchery if (!x509v3_add_len_value_uchar("URI", gen->d.ia5->data,
181b077aed3SPierre Pronchery gen->d.ia5->length, &ret))
182b077aed3SPierre Pronchery return NULL;
183b077aed3SPierre Pronchery break;
184b077aed3SPierre Pronchery
185b077aed3SPierre Pronchery case GEN_DIRNAME:
186b077aed3SPierre Pronchery if (X509_NAME_oneline(gen->d.dirn, oline, sizeof(oline)) == NULL
187b077aed3SPierre Pronchery || !X509V3_add_value("DirName", oline, &ret))
188b077aed3SPierre Pronchery return NULL;
189b077aed3SPierre Pronchery break;
190b077aed3SPierre Pronchery
191b077aed3SPierre Pronchery case GEN_IPADD:
192b077aed3SPierre Pronchery tmp = ossl_ipaddr_to_asc(gen->d.ip->data, gen->d.ip->length);
193b077aed3SPierre Pronchery if (tmp == NULL || !X509V3_add_value("IP Address", tmp, &ret))
194b077aed3SPierre Pronchery ret = NULL;
195b077aed3SPierre Pronchery OPENSSL_free(tmp);
196b077aed3SPierre Pronchery break;
197b077aed3SPierre Pronchery
198b077aed3SPierre Pronchery case GEN_RID:
199b077aed3SPierre Pronchery i2t_ASN1_OBJECT(oline, 256, gen->d.rid);
200b077aed3SPierre Pronchery if (!X509V3_add_value("Registered ID", oline, &ret))
201b077aed3SPierre Pronchery return NULL;
202b077aed3SPierre Pronchery break;
203b077aed3SPierre Pronchery }
204b077aed3SPierre Pronchery return ret;
205b077aed3SPierre Pronchery }
206b077aed3SPierre Pronchery
GENERAL_NAME_print(BIO * out,GENERAL_NAME * gen)207b077aed3SPierre Pronchery int GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen)
208b077aed3SPierre Pronchery {
209b077aed3SPierre Pronchery char *tmp;
210b077aed3SPierre Pronchery int nid;
211b077aed3SPierre Pronchery
212b077aed3SPierre Pronchery switch (gen->type) {
213b077aed3SPierre Pronchery case GEN_OTHERNAME:
214b077aed3SPierre Pronchery nid = OBJ_obj2nid(gen->d.otherName->type_id);
215b077aed3SPierre Pronchery /* Validate the types are as we expect before we use them */
216b077aed3SPierre Pronchery if ((nid == NID_SRVName
217b077aed3SPierre Pronchery && gen->d.otherName->value->type != V_ASN1_IA5STRING)
218b077aed3SPierre Pronchery || (nid != NID_SRVName
219b077aed3SPierre Pronchery && gen->d.otherName->value->type != V_ASN1_UTF8STRING)) {
220b077aed3SPierre Pronchery BIO_printf(out, "othername:<unsupported>");
221b077aed3SPierre Pronchery break;
222b077aed3SPierre Pronchery }
223b077aed3SPierre Pronchery
224b077aed3SPierre Pronchery switch (nid) {
225b077aed3SPierre Pronchery case NID_id_on_SmtpUTF8Mailbox:
226b077aed3SPierre Pronchery BIO_printf(out, "othername:SmtpUTF8Mailbox:%.*s",
227b077aed3SPierre Pronchery gen->d.otherName->value->value.utf8string->length,
228b077aed3SPierre Pronchery gen->d.otherName->value->value.utf8string->data);
229b077aed3SPierre Pronchery break;
230b077aed3SPierre Pronchery case NID_XmppAddr:
231b077aed3SPierre Pronchery BIO_printf(out, "othername:XmppAddr:%.*s",
232b077aed3SPierre Pronchery gen->d.otherName->value->value.utf8string->length,
233b077aed3SPierre Pronchery gen->d.otherName->value->value.utf8string->data);
234b077aed3SPierre Pronchery break;
235b077aed3SPierre Pronchery case NID_SRVName:
236b077aed3SPierre Pronchery BIO_printf(out, "othername:SRVName:%.*s",
237b077aed3SPierre Pronchery gen->d.otherName->value->value.ia5string->length,
238b077aed3SPierre Pronchery gen->d.otherName->value->value.ia5string->data);
239b077aed3SPierre Pronchery break;
240b077aed3SPierre Pronchery case NID_ms_upn:
241b077aed3SPierre Pronchery BIO_printf(out, "othername:UPN:%.*s",
242b077aed3SPierre Pronchery gen->d.otherName->value->value.utf8string->length,
243b077aed3SPierre Pronchery gen->d.otherName->value->value.utf8string->data);
244b077aed3SPierre Pronchery break;
245b077aed3SPierre Pronchery case NID_NAIRealm:
246b077aed3SPierre Pronchery BIO_printf(out, "othername:NAIRealm:%.*s",
247b077aed3SPierre Pronchery gen->d.otherName->value->value.utf8string->length,
248b077aed3SPierre Pronchery gen->d.otherName->value->value.utf8string->data);
249b077aed3SPierre Pronchery break;
250b077aed3SPierre Pronchery default:
251b077aed3SPierre Pronchery BIO_printf(out, "othername:<unsupported>");
252b077aed3SPierre Pronchery break;
253b077aed3SPierre Pronchery }
254b077aed3SPierre Pronchery break;
255b077aed3SPierre Pronchery
256b077aed3SPierre Pronchery case GEN_X400:
257b077aed3SPierre Pronchery BIO_printf(out, "X400Name:<unsupported>");
258b077aed3SPierre Pronchery break;
259b077aed3SPierre Pronchery
260b077aed3SPierre Pronchery case GEN_EDIPARTY:
261b077aed3SPierre Pronchery /* Maybe fix this: it is supported now */
262b077aed3SPierre Pronchery BIO_printf(out, "EdiPartyName:<unsupported>");
263b077aed3SPierre Pronchery break;
264b077aed3SPierre Pronchery
265b077aed3SPierre Pronchery case GEN_EMAIL:
266b077aed3SPierre Pronchery BIO_printf(out, "email:");
267b077aed3SPierre Pronchery ASN1_STRING_print(out, gen->d.ia5);
268b077aed3SPierre Pronchery break;
269b077aed3SPierre Pronchery
270b077aed3SPierre Pronchery case GEN_DNS:
271b077aed3SPierre Pronchery BIO_printf(out, "DNS:");
272b077aed3SPierre Pronchery ASN1_STRING_print(out, gen->d.ia5);
273b077aed3SPierre Pronchery break;
274b077aed3SPierre Pronchery
275b077aed3SPierre Pronchery case GEN_URI:
276b077aed3SPierre Pronchery BIO_printf(out, "URI:");
277b077aed3SPierre Pronchery ASN1_STRING_print(out, gen->d.ia5);
278b077aed3SPierre Pronchery break;
279b077aed3SPierre Pronchery
280b077aed3SPierre Pronchery case GEN_DIRNAME:
281b077aed3SPierre Pronchery BIO_printf(out, "DirName:");
282b077aed3SPierre Pronchery X509_NAME_print_ex(out, gen->d.dirn, 0, XN_FLAG_ONELINE);
283b077aed3SPierre Pronchery break;
284b077aed3SPierre Pronchery
285b077aed3SPierre Pronchery case GEN_IPADD:
286b077aed3SPierre Pronchery tmp = ossl_ipaddr_to_asc(gen->d.ip->data, gen->d.ip->length);
287b077aed3SPierre Pronchery if (tmp == NULL)
288b077aed3SPierre Pronchery return 0;
289b077aed3SPierre Pronchery BIO_printf(out, "IP Address:%s", tmp);
290b077aed3SPierre Pronchery OPENSSL_free(tmp);
291b077aed3SPierre Pronchery break;
292b077aed3SPierre Pronchery
293b077aed3SPierre Pronchery case GEN_RID:
294b077aed3SPierre Pronchery BIO_printf(out, "Registered ID:");
295b077aed3SPierre Pronchery i2a_ASN1_OBJECT(out, gen->d.rid);
296b077aed3SPierre Pronchery break;
297b077aed3SPierre Pronchery }
298b077aed3SPierre Pronchery return 1;
299b077aed3SPierre Pronchery }
300b077aed3SPierre Pronchery
v2i_issuer_alt(X509V3_EXT_METHOD * method,X509V3_CTX * ctx,STACK_OF (CONF_VALUE)* nval)301b077aed3SPierre Pronchery static GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method,
302b077aed3SPierre Pronchery X509V3_CTX *ctx,
303b077aed3SPierre Pronchery STACK_OF(CONF_VALUE) *nval)
304b077aed3SPierre Pronchery {
305b077aed3SPierre Pronchery const int num = sk_CONF_VALUE_num(nval);
306b077aed3SPierre Pronchery GENERAL_NAMES *gens = sk_GENERAL_NAME_new_reserve(NULL, num);
307b077aed3SPierre Pronchery int i;
308b077aed3SPierre Pronchery
309b077aed3SPierre Pronchery if (gens == NULL) {
310b077aed3SPierre Pronchery ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
311b077aed3SPierre Pronchery sk_GENERAL_NAME_free(gens);
312b077aed3SPierre Pronchery return NULL;
313b077aed3SPierre Pronchery }
314b077aed3SPierre Pronchery for (i = 0; i < num; i++) {
315b077aed3SPierre Pronchery CONF_VALUE *cnf = sk_CONF_VALUE_value(nval, i);
316b077aed3SPierre Pronchery
317b077aed3SPierre Pronchery if (!ossl_v3_name_cmp(cnf->name, "issuer")
318b077aed3SPierre Pronchery && cnf->value && strcmp(cnf->value, "copy") == 0) {
319b077aed3SPierre Pronchery if (!copy_issuer(ctx, gens))
320b077aed3SPierre Pronchery goto err;
321b077aed3SPierre Pronchery } else {
322b077aed3SPierre Pronchery GENERAL_NAME *gen = v2i_GENERAL_NAME(method, ctx, cnf);
323b077aed3SPierre Pronchery
324b077aed3SPierre Pronchery if (gen == NULL)
325b077aed3SPierre Pronchery goto err;
326b077aed3SPierre Pronchery sk_GENERAL_NAME_push(gens, gen); /* no failure as it was reserved */
327b077aed3SPierre Pronchery }
328b077aed3SPierre Pronchery }
329b077aed3SPierre Pronchery return gens;
330b077aed3SPierre Pronchery err:
331b077aed3SPierre Pronchery sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
332b077aed3SPierre Pronchery return NULL;
333b077aed3SPierre Pronchery }
334b077aed3SPierre Pronchery
335b077aed3SPierre Pronchery /* Append subject altname of issuer to issuer alt name of subject */
336b077aed3SPierre Pronchery
copy_issuer(X509V3_CTX * ctx,GENERAL_NAMES * gens)337b077aed3SPierre Pronchery static int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens)
338b077aed3SPierre Pronchery {
339b077aed3SPierre Pronchery GENERAL_NAMES *ialt;
340b077aed3SPierre Pronchery GENERAL_NAME *gen;
341b077aed3SPierre Pronchery X509_EXTENSION *ext;
342b077aed3SPierre Pronchery int i, num;
343b077aed3SPierre Pronchery
344b077aed3SPierre Pronchery if (ctx != NULL && (ctx->flags & X509V3_CTX_TEST) != 0)
345b077aed3SPierre Pronchery return 1;
346b077aed3SPierre Pronchery if (!ctx || !ctx->issuer_cert) {
347b077aed3SPierre Pronchery ERR_raise(ERR_LIB_X509V3, X509V3_R_NO_ISSUER_DETAILS);
348b077aed3SPierre Pronchery goto err;
349b077aed3SPierre Pronchery }
350b077aed3SPierre Pronchery i = X509_get_ext_by_NID(ctx->issuer_cert, NID_subject_alt_name, -1);
351b077aed3SPierre Pronchery if (i < 0)
352b077aed3SPierre Pronchery return 1;
353b077aed3SPierre Pronchery if ((ext = X509_get_ext(ctx->issuer_cert, i)) == NULL
354b077aed3SPierre Pronchery || (ialt = X509V3_EXT_d2i(ext)) == NULL) {
355b077aed3SPierre Pronchery ERR_raise(ERR_LIB_X509V3, X509V3_R_ISSUER_DECODE_ERROR);
356b077aed3SPierre Pronchery goto err;
357b077aed3SPierre Pronchery }
358b077aed3SPierre Pronchery
359b077aed3SPierre Pronchery num = sk_GENERAL_NAME_num(ialt);
360b077aed3SPierre Pronchery if (!sk_GENERAL_NAME_reserve(gens, num)) {
361b077aed3SPierre Pronchery ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
362b077aed3SPierre Pronchery goto err;
363b077aed3SPierre Pronchery }
364b077aed3SPierre Pronchery
365b077aed3SPierre Pronchery for (i = 0; i < num; i++) {
366b077aed3SPierre Pronchery gen = sk_GENERAL_NAME_value(ialt, i);
367b077aed3SPierre Pronchery sk_GENERAL_NAME_push(gens, gen); /* no failure as it was reserved */
368b077aed3SPierre Pronchery }
369b077aed3SPierre Pronchery sk_GENERAL_NAME_free(ialt);
370b077aed3SPierre Pronchery
371b077aed3SPierre Pronchery return 1;
372b077aed3SPierre Pronchery
373b077aed3SPierre Pronchery err:
374b077aed3SPierre Pronchery return 0;
375b077aed3SPierre Pronchery
376b077aed3SPierre Pronchery }
377b077aed3SPierre Pronchery
v2i_subject_alt(X509V3_EXT_METHOD * method,X509V3_CTX * ctx,STACK_OF (CONF_VALUE)* nval)378b077aed3SPierre Pronchery static GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method,
379b077aed3SPierre Pronchery X509V3_CTX *ctx,
380b077aed3SPierre Pronchery STACK_OF(CONF_VALUE) *nval)
381b077aed3SPierre Pronchery {
382b077aed3SPierre Pronchery GENERAL_NAMES *gens;
383b077aed3SPierre Pronchery CONF_VALUE *cnf;
384b077aed3SPierre Pronchery const int num = sk_CONF_VALUE_num(nval);
385b077aed3SPierre Pronchery int i;
386b077aed3SPierre Pronchery
387b077aed3SPierre Pronchery gens = sk_GENERAL_NAME_new_reserve(NULL, num);
388b077aed3SPierre Pronchery if (gens == NULL) {
389b077aed3SPierre Pronchery ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
390b077aed3SPierre Pronchery sk_GENERAL_NAME_free(gens);
391b077aed3SPierre Pronchery return NULL;
392b077aed3SPierre Pronchery }
393b077aed3SPierre Pronchery
394b077aed3SPierre Pronchery for (i = 0; i < num; i++) {
395b077aed3SPierre Pronchery cnf = sk_CONF_VALUE_value(nval, i);
396b077aed3SPierre Pronchery if (ossl_v3_name_cmp(cnf->name, "email") == 0
397b077aed3SPierre Pronchery && cnf->value && strcmp(cnf->value, "copy") == 0) {
398b077aed3SPierre Pronchery if (!copy_email(ctx, gens, 0))
399b077aed3SPierre Pronchery goto err;
400b077aed3SPierre Pronchery } else if (ossl_v3_name_cmp(cnf->name, "email") == 0
401b077aed3SPierre Pronchery && cnf->value && strcmp(cnf->value, "move") == 0) {
402b077aed3SPierre Pronchery if (!copy_email(ctx, gens, 1))
403b077aed3SPierre Pronchery goto err;
404b077aed3SPierre Pronchery } else {
405b077aed3SPierre Pronchery GENERAL_NAME *gen;
406b077aed3SPierre Pronchery if ((gen = v2i_GENERAL_NAME(method, ctx, cnf)) == NULL)
407b077aed3SPierre Pronchery goto err;
408b077aed3SPierre Pronchery sk_GENERAL_NAME_push(gens, gen); /* no failure as it was reserved */
409b077aed3SPierre Pronchery }
410b077aed3SPierre Pronchery }
411b077aed3SPierre Pronchery return gens;
412b077aed3SPierre Pronchery err:
413b077aed3SPierre Pronchery sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
414b077aed3SPierre Pronchery return NULL;
415b077aed3SPierre Pronchery }
416b077aed3SPierre Pronchery
417b077aed3SPierre Pronchery /*
418b077aed3SPierre Pronchery * Copy any email addresses in a certificate or request to GENERAL_NAMES
419b077aed3SPierre Pronchery */
420b077aed3SPierre Pronchery
copy_email(X509V3_CTX * ctx,GENERAL_NAMES * gens,int move_p)421b077aed3SPierre Pronchery static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p)
422b077aed3SPierre Pronchery {
423b077aed3SPierre Pronchery X509_NAME *nm;
424b077aed3SPierre Pronchery ASN1_IA5STRING *email = NULL;
425b077aed3SPierre Pronchery X509_NAME_ENTRY *ne;
426b077aed3SPierre Pronchery GENERAL_NAME *gen = NULL;
427b077aed3SPierre Pronchery int i = -1;
428b077aed3SPierre Pronchery
429b077aed3SPierre Pronchery if (ctx != NULL && (ctx->flags & X509V3_CTX_TEST) != 0)
430b077aed3SPierre Pronchery return 1;
431b077aed3SPierre Pronchery if (ctx == NULL
432b077aed3SPierre Pronchery || (ctx->subject_cert == NULL && ctx->subject_req == NULL)) {
433b077aed3SPierre Pronchery ERR_raise(ERR_LIB_X509V3, X509V3_R_NO_SUBJECT_DETAILS);
434b077aed3SPierre Pronchery return 0;
435b077aed3SPierre Pronchery }
436b077aed3SPierre Pronchery /* Find the subject name */
437b077aed3SPierre Pronchery nm = ctx->subject_cert != NULL ?
438b077aed3SPierre Pronchery X509_get_subject_name(ctx->subject_cert) :
439b077aed3SPierre Pronchery X509_REQ_get_subject_name(ctx->subject_req);
440b077aed3SPierre Pronchery
441b077aed3SPierre Pronchery /* Now add any email address(es) to STACK */
442b077aed3SPierre Pronchery while ((i = X509_NAME_get_index_by_NID(nm,
443b077aed3SPierre Pronchery NID_pkcs9_emailAddress, i)) >= 0) {
444b077aed3SPierre Pronchery ne = X509_NAME_get_entry(nm, i);
445b077aed3SPierre Pronchery email = ASN1_STRING_dup(X509_NAME_ENTRY_get_data(ne));
446b077aed3SPierre Pronchery if (move_p) {
447b077aed3SPierre Pronchery X509_NAME_delete_entry(nm, i);
448b077aed3SPierre Pronchery X509_NAME_ENTRY_free(ne);
449b077aed3SPierre Pronchery i--;
450b077aed3SPierre Pronchery }
451b077aed3SPierre Pronchery if (email == NULL || (gen = GENERAL_NAME_new()) == NULL) {
452b077aed3SPierre Pronchery ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
453b077aed3SPierre Pronchery goto err;
454b077aed3SPierre Pronchery }
455b077aed3SPierre Pronchery gen->d.ia5 = email;
456b077aed3SPierre Pronchery email = NULL;
457b077aed3SPierre Pronchery gen->type = GEN_EMAIL;
458b077aed3SPierre Pronchery if (!sk_GENERAL_NAME_push(gens, gen)) {
459b077aed3SPierre Pronchery ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
460b077aed3SPierre Pronchery goto err;
461b077aed3SPierre Pronchery }
462b077aed3SPierre Pronchery gen = NULL;
463b077aed3SPierre Pronchery }
464b077aed3SPierre Pronchery
465b077aed3SPierre Pronchery return 1;
466b077aed3SPierre Pronchery
467b077aed3SPierre Pronchery err:
468b077aed3SPierre Pronchery GENERAL_NAME_free(gen);
469b077aed3SPierre Pronchery ASN1_IA5STRING_free(email);
470b077aed3SPierre Pronchery return 0;
471b077aed3SPierre Pronchery
472b077aed3SPierre Pronchery }
473b077aed3SPierre Pronchery
v2i_GENERAL_NAMES(const X509V3_EXT_METHOD * method,X509V3_CTX * ctx,STACK_OF (CONF_VALUE)* nval)474b077aed3SPierre Pronchery GENERAL_NAMES *v2i_GENERAL_NAMES(const X509V3_EXT_METHOD *method,
475b077aed3SPierre Pronchery X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
476b077aed3SPierre Pronchery {
477b077aed3SPierre Pronchery GENERAL_NAME *gen;
478b077aed3SPierre Pronchery GENERAL_NAMES *gens;
479b077aed3SPierre Pronchery CONF_VALUE *cnf;
480b077aed3SPierre Pronchery const int num = sk_CONF_VALUE_num(nval);
481b077aed3SPierre Pronchery int i;
482b077aed3SPierre Pronchery
483b077aed3SPierre Pronchery gens = sk_GENERAL_NAME_new_reserve(NULL, num);
484b077aed3SPierre Pronchery if (gens == NULL) {
485b077aed3SPierre Pronchery ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
486b077aed3SPierre Pronchery sk_GENERAL_NAME_free(gens);
487b077aed3SPierre Pronchery return NULL;
488b077aed3SPierre Pronchery }
489b077aed3SPierre Pronchery
490b077aed3SPierre Pronchery for (i = 0; i < num; i++) {
491b077aed3SPierre Pronchery cnf = sk_CONF_VALUE_value(nval, i);
492b077aed3SPierre Pronchery if ((gen = v2i_GENERAL_NAME(method, ctx, cnf)) == NULL)
493b077aed3SPierre Pronchery goto err;
494b077aed3SPierre Pronchery sk_GENERAL_NAME_push(gens, gen); /* no failure as it was reserved */
495b077aed3SPierre Pronchery }
496b077aed3SPierre Pronchery return gens;
497b077aed3SPierre Pronchery err:
498b077aed3SPierre Pronchery sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
499b077aed3SPierre Pronchery return NULL;
500b077aed3SPierre Pronchery }
501b077aed3SPierre Pronchery
v2i_GENERAL_NAME(const X509V3_EXT_METHOD * method,X509V3_CTX * ctx,CONF_VALUE * cnf)502b077aed3SPierre Pronchery GENERAL_NAME *v2i_GENERAL_NAME(const X509V3_EXT_METHOD *method,
503b077aed3SPierre Pronchery X509V3_CTX *ctx, CONF_VALUE *cnf)
504b077aed3SPierre Pronchery {
505b077aed3SPierre Pronchery return v2i_GENERAL_NAME_ex(NULL, method, ctx, cnf, 0);
506b077aed3SPierre Pronchery }
507b077aed3SPierre Pronchery
a2i_GENERAL_NAME(GENERAL_NAME * out,const X509V3_EXT_METHOD * method,X509V3_CTX * ctx,int gen_type,const char * value,int is_nc)508b077aed3SPierre Pronchery GENERAL_NAME *a2i_GENERAL_NAME(GENERAL_NAME *out,
509b077aed3SPierre Pronchery const X509V3_EXT_METHOD *method,
510b077aed3SPierre Pronchery X509V3_CTX *ctx, int gen_type, const char *value,
511b077aed3SPierre Pronchery int is_nc)
512b077aed3SPierre Pronchery {
513b077aed3SPierre Pronchery char is_string = 0;
514b077aed3SPierre Pronchery GENERAL_NAME *gen = NULL;
515b077aed3SPierre Pronchery
516b077aed3SPierre Pronchery if (!value) {
517b077aed3SPierre Pronchery ERR_raise(ERR_LIB_X509V3, X509V3_R_MISSING_VALUE);
518b077aed3SPierre Pronchery return NULL;
519b077aed3SPierre Pronchery }
520b077aed3SPierre Pronchery
521b077aed3SPierre Pronchery if (out)
522b077aed3SPierre Pronchery gen = out;
523b077aed3SPierre Pronchery else {
524b077aed3SPierre Pronchery gen = GENERAL_NAME_new();
525b077aed3SPierre Pronchery if (gen == NULL) {
526b077aed3SPierre Pronchery ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
527b077aed3SPierre Pronchery return NULL;
528b077aed3SPierre Pronchery }
529b077aed3SPierre Pronchery }
530b077aed3SPierre Pronchery
531b077aed3SPierre Pronchery switch (gen_type) {
532b077aed3SPierre Pronchery case GEN_URI:
533b077aed3SPierre Pronchery case GEN_EMAIL:
534b077aed3SPierre Pronchery case GEN_DNS:
535b077aed3SPierre Pronchery is_string = 1;
536b077aed3SPierre Pronchery break;
537b077aed3SPierre Pronchery
538b077aed3SPierre Pronchery case GEN_RID:
539b077aed3SPierre Pronchery {
540b077aed3SPierre Pronchery ASN1_OBJECT *obj;
541b077aed3SPierre Pronchery if ((obj = OBJ_txt2obj(value, 0)) == NULL) {
542b077aed3SPierre Pronchery ERR_raise_data(ERR_LIB_X509V3, X509V3_R_BAD_OBJECT,
543b077aed3SPierre Pronchery "value=%s", value);
544b077aed3SPierre Pronchery goto err;
545b077aed3SPierre Pronchery }
546b077aed3SPierre Pronchery gen->d.rid = obj;
547b077aed3SPierre Pronchery }
548b077aed3SPierre Pronchery break;
549b077aed3SPierre Pronchery
550b077aed3SPierre Pronchery case GEN_IPADD:
551b077aed3SPierre Pronchery if (is_nc)
552b077aed3SPierre Pronchery gen->d.ip = a2i_IPADDRESS_NC(value);
553b077aed3SPierre Pronchery else
554b077aed3SPierre Pronchery gen->d.ip = a2i_IPADDRESS(value);
555b077aed3SPierre Pronchery if (gen->d.ip == NULL) {
556b077aed3SPierre Pronchery ERR_raise_data(ERR_LIB_X509V3, X509V3_R_BAD_IP_ADDRESS,
557b077aed3SPierre Pronchery "value=%s", value);
558b077aed3SPierre Pronchery goto err;
559b077aed3SPierre Pronchery }
560b077aed3SPierre Pronchery break;
561b077aed3SPierre Pronchery
562b077aed3SPierre Pronchery case GEN_DIRNAME:
563b077aed3SPierre Pronchery if (!do_dirname(gen, value, ctx)) {
564b077aed3SPierre Pronchery ERR_raise(ERR_LIB_X509V3, X509V3_R_DIRNAME_ERROR);
565b077aed3SPierre Pronchery goto err;
566b077aed3SPierre Pronchery }
567b077aed3SPierre Pronchery break;
568b077aed3SPierre Pronchery
569b077aed3SPierre Pronchery case GEN_OTHERNAME:
570b077aed3SPierre Pronchery if (!do_othername(gen, value, ctx)) {
571b077aed3SPierre Pronchery ERR_raise(ERR_LIB_X509V3, X509V3_R_OTHERNAME_ERROR);
572b077aed3SPierre Pronchery goto err;
573b077aed3SPierre Pronchery }
574b077aed3SPierre Pronchery break;
575b077aed3SPierre Pronchery default:
576b077aed3SPierre Pronchery ERR_raise(ERR_LIB_X509V3, X509V3_R_UNSUPPORTED_TYPE);
577b077aed3SPierre Pronchery goto err;
578b077aed3SPierre Pronchery }
579b077aed3SPierre Pronchery
580b077aed3SPierre Pronchery if (is_string) {
581b077aed3SPierre Pronchery if ((gen->d.ia5 = ASN1_IA5STRING_new()) == NULL ||
582b077aed3SPierre Pronchery !ASN1_STRING_set(gen->d.ia5, (unsigned char *)value,
583b077aed3SPierre Pronchery strlen(value))) {
584*e0c4386eSCy Schubert ASN1_IA5STRING_free(gen->d.ia5);
585*e0c4386eSCy Schubert gen->d.ia5 = NULL;
586b077aed3SPierre Pronchery ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
587b077aed3SPierre Pronchery goto err;
588b077aed3SPierre Pronchery }
589b077aed3SPierre Pronchery }
590b077aed3SPierre Pronchery
591b077aed3SPierre Pronchery gen->type = gen_type;
592b077aed3SPierre Pronchery
593b077aed3SPierre Pronchery return gen;
594b077aed3SPierre Pronchery
595b077aed3SPierre Pronchery err:
596b077aed3SPierre Pronchery if (!out)
597b077aed3SPierre Pronchery GENERAL_NAME_free(gen);
598b077aed3SPierre Pronchery return NULL;
599b077aed3SPierre Pronchery }
600b077aed3SPierre Pronchery
v2i_GENERAL_NAME_ex(GENERAL_NAME * out,const X509V3_EXT_METHOD * method,X509V3_CTX * ctx,CONF_VALUE * cnf,int is_nc)601b077aed3SPierre Pronchery GENERAL_NAME *v2i_GENERAL_NAME_ex(GENERAL_NAME *out,
602b077aed3SPierre Pronchery const X509V3_EXT_METHOD *method,
603b077aed3SPierre Pronchery X509V3_CTX *ctx, CONF_VALUE *cnf, int is_nc)
604b077aed3SPierre Pronchery {
605b077aed3SPierre Pronchery int type;
606b077aed3SPierre Pronchery
607b077aed3SPierre Pronchery char *name, *value;
608b077aed3SPierre Pronchery
609b077aed3SPierre Pronchery name = cnf->name;
610b077aed3SPierre Pronchery value = cnf->value;
611b077aed3SPierre Pronchery
612b077aed3SPierre Pronchery if (!value) {
613b077aed3SPierre Pronchery ERR_raise(ERR_LIB_X509V3, X509V3_R_MISSING_VALUE);
614b077aed3SPierre Pronchery return NULL;
615b077aed3SPierre Pronchery }
616b077aed3SPierre Pronchery
617b077aed3SPierre Pronchery if (!ossl_v3_name_cmp(name, "email"))
618b077aed3SPierre Pronchery type = GEN_EMAIL;
619b077aed3SPierre Pronchery else if (!ossl_v3_name_cmp(name, "URI"))
620b077aed3SPierre Pronchery type = GEN_URI;
621b077aed3SPierre Pronchery else if (!ossl_v3_name_cmp(name, "DNS"))
622b077aed3SPierre Pronchery type = GEN_DNS;
623b077aed3SPierre Pronchery else if (!ossl_v3_name_cmp(name, "RID"))
624b077aed3SPierre Pronchery type = GEN_RID;
625b077aed3SPierre Pronchery else if (!ossl_v3_name_cmp(name, "IP"))
626b077aed3SPierre Pronchery type = GEN_IPADD;
627b077aed3SPierre Pronchery else if (!ossl_v3_name_cmp(name, "dirName"))
628b077aed3SPierre Pronchery type = GEN_DIRNAME;
629b077aed3SPierre Pronchery else if (!ossl_v3_name_cmp(name, "otherName"))
630b077aed3SPierre Pronchery type = GEN_OTHERNAME;
631b077aed3SPierre Pronchery else {
632b077aed3SPierre Pronchery ERR_raise_data(ERR_LIB_X509V3, X509V3_R_UNSUPPORTED_OPTION,
633b077aed3SPierre Pronchery "name=%s", name);
634b077aed3SPierre Pronchery return NULL;
635b077aed3SPierre Pronchery }
636b077aed3SPierre Pronchery
637b077aed3SPierre Pronchery return a2i_GENERAL_NAME(out, method, ctx, type, value, is_nc);
638b077aed3SPierre Pronchery
639b077aed3SPierre Pronchery }
640b077aed3SPierre Pronchery
do_othername(GENERAL_NAME * gen,const char * value,X509V3_CTX * ctx)641b077aed3SPierre Pronchery static int do_othername(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx)
642b077aed3SPierre Pronchery {
643b077aed3SPierre Pronchery char *objtmp = NULL, *p;
644b077aed3SPierre Pronchery int objlen;
645b077aed3SPierre Pronchery
646b077aed3SPierre Pronchery if ((p = strchr(value, ';')) == NULL)
647b077aed3SPierre Pronchery return 0;
648b077aed3SPierre Pronchery if ((gen->d.otherName = OTHERNAME_new()) == NULL)
649b077aed3SPierre Pronchery return 0;
650b077aed3SPierre Pronchery /*
651b077aed3SPierre Pronchery * Free this up because we will overwrite it. no need to free type_id
652b077aed3SPierre Pronchery * because it is static
653b077aed3SPierre Pronchery */
654b077aed3SPierre Pronchery ASN1_TYPE_free(gen->d.otherName->value);
655b077aed3SPierre Pronchery if ((gen->d.otherName->value = ASN1_generate_v3(p + 1, ctx)) == NULL)
656*e0c4386eSCy Schubert goto err;
657b077aed3SPierre Pronchery objlen = p - value;
658b077aed3SPierre Pronchery objtmp = OPENSSL_strndup(value, objlen);
659b077aed3SPierre Pronchery if (objtmp == NULL)
660*e0c4386eSCy Schubert goto err;
661b077aed3SPierre Pronchery gen->d.otherName->type_id = OBJ_txt2obj(objtmp, 0);
662b077aed3SPierre Pronchery OPENSSL_free(objtmp);
663b077aed3SPierre Pronchery if (!gen->d.otherName->type_id)
664*e0c4386eSCy Schubert goto err;
665b077aed3SPierre Pronchery return 1;
666*e0c4386eSCy Schubert
667*e0c4386eSCy Schubert err:
668*e0c4386eSCy Schubert OTHERNAME_free(gen->d.otherName);
669*e0c4386eSCy Schubert gen->d.otherName = NULL;
670*e0c4386eSCy Schubert return 0;
671b077aed3SPierre Pronchery }
672b077aed3SPierre Pronchery
do_dirname(GENERAL_NAME * gen,const char * value,X509V3_CTX * ctx)673b077aed3SPierre Pronchery static int do_dirname(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx)
674b077aed3SPierre Pronchery {
675b077aed3SPierre Pronchery int ret = 0;
676b077aed3SPierre Pronchery STACK_OF(CONF_VALUE) *sk = NULL;
677b077aed3SPierre Pronchery X509_NAME *nm;
678b077aed3SPierre Pronchery
679b077aed3SPierre Pronchery if ((nm = X509_NAME_new()) == NULL)
680b077aed3SPierre Pronchery goto err;
681b077aed3SPierre Pronchery sk = X509V3_get_section(ctx, value);
682b077aed3SPierre Pronchery if (!sk) {
683b077aed3SPierre Pronchery ERR_raise_data(ERR_LIB_X509V3, X509V3_R_SECTION_NOT_FOUND,
684b077aed3SPierre Pronchery "section=%s", value);
685b077aed3SPierre Pronchery goto err;
686b077aed3SPierre Pronchery }
687b077aed3SPierre Pronchery /* FIXME: should allow other character types... */
688b077aed3SPierre Pronchery ret = X509V3_NAME_from_section(nm, sk, MBSTRING_ASC);
689b077aed3SPierre Pronchery if (!ret)
690b077aed3SPierre Pronchery goto err;
691b077aed3SPierre Pronchery gen->d.dirn = nm;
692b077aed3SPierre Pronchery
693b077aed3SPierre Pronchery err:
694b077aed3SPierre Pronchery if (ret == 0)
695b077aed3SPierre Pronchery X509_NAME_free(nm);
696b077aed3SPierre Pronchery X509V3_section_free(ctx, sk);
697b077aed3SPierre Pronchery return ret;
698b077aed3SPierre Pronchery }
699