xref: /freebsd/crypto/openssl/crypto/x509/v3_san.c (revision e0c4386e)
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