• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3  * project.
4  */
5 /* ====================================================================
6  * Copyright (c) 1999-2003 The OpenSSL Project.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in
17  *    the documentation and/or other materials provided with the
18  *    distribution.
19  *
20  * 3. All advertising materials mentioning features or use of this
21  *    software must display the following acknowledgment:
22  *    "This product includes software developed by the OpenSSL Project
23  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24  *
25  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26  *    endorse or promote products derived from this software without
27  *    prior written permission. For written permission, please contact
28  *    licensing@OpenSSL.org.
29  *
30  * 5. Products derived from this software may not be called "OpenSSL"
31  *    nor may "OpenSSL" appear in their names without prior written
32  *    permission of the OpenSSL Project.
33  *
34  * 6. Redistributions of any form whatsoever must retain the following
35  *    acknowledgment:
36  *    "This product includes software developed by the OpenSSL Project
37  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38  *
39  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50  * OF THE POSSIBILITY OF SUCH DAMAGE.
51  * ====================================================================
52  *
53  * This product includes cryptographic software written by Eric Young
54  * (eay@cryptsoft.com).  This product includes software written by Tim
55  * Hudson (tjh@cryptsoft.com). */
56 
57 #include <stdio.h>
58 #include <string.h>
59 
60 #include <openssl/conf.h>
61 #include <openssl/err.h>
62 #include <openssl/mem.h>
63 #include <openssl/obj.h>
64 #include <openssl/x509v3.h>
65 
66 #include "../x509/internal.h"
67 #include "internal.h"
68 
69 
70 static void *v2i_subject_alt(const X509V3_EXT_METHOD *method,
71                              const X509V3_CTX *ctx,
72                              const STACK_OF(CONF_VALUE) *nval);
73 static void *v2i_issuer_alt(const X509V3_EXT_METHOD *method,
74                             const X509V3_CTX *ctx,
75                             const STACK_OF(CONF_VALUE) *nval);
76 static int copy_email(const X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p);
77 static int copy_issuer(const X509V3_CTX *ctx, GENERAL_NAMES *gens);
78 static int do_othername(GENERAL_NAME *gen, const char *value,
79                         const X509V3_CTX *ctx);
80 static int do_dirname(GENERAL_NAME *gen, const char *value,
81                       const X509V3_CTX *ctx);
82 
STACK_OF(CONF_VALUE)83 static STACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES_cb(
84     const X509V3_EXT_METHOD *method, void *ext, STACK_OF(CONF_VALUE) *ret) {
85   return i2v_GENERAL_NAMES(method, ext, ret);
86 }
87 
88 const X509V3_EXT_METHOD v3_alt[] = {
89     {NID_subject_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES), 0, 0, 0, 0, 0, 0,
90      i2v_GENERAL_NAMES_cb, v2i_subject_alt, NULL, NULL, NULL},
91 
92     {NID_issuer_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES), 0, 0, 0, 0, 0, 0,
93      i2v_GENERAL_NAMES_cb, v2i_issuer_alt, NULL, NULL, NULL},
94 
95     {NID_certificate_issuer, 0, ASN1_ITEM_ref(GENERAL_NAMES), 0, 0, 0, 0, 0, 0,
96      i2v_GENERAL_NAMES_cb, NULL, NULL, NULL, NULL},
97 };
98 
STACK_OF(CONF_VALUE)99 STACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES(const X509V3_EXT_METHOD *method,
100                                         const GENERAL_NAMES *gens,
101                                         STACK_OF(CONF_VALUE) *ret) {
102   int ret_was_null = ret == NULL;
103   for (size_t i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
104     const GENERAL_NAME *gen = sk_GENERAL_NAME_value(gens, i);
105     STACK_OF(CONF_VALUE) *tmp = i2v_GENERAL_NAME(method, gen, ret);
106     if (tmp == NULL) {
107       if (ret_was_null) {
108         sk_CONF_VALUE_pop_free(ret, X509V3_conf_free);
109       }
110       return NULL;
111     }
112     ret = tmp;
113   }
114   if (!ret) {
115     return sk_CONF_VALUE_new_null();
116   }
117   return ret;
118 }
119 
STACK_OF(CONF_VALUE)120 STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(const X509V3_EXT_METHOD *method,
121                                        const GENERAL_NAME *gen,
122                                        STACK_OF(CONF_VALUE) *ret) {
123   // Note the error-handling for this function relies on there being at most
124   // one |X509V3_add_value| call. If there were two and the second failed, we
125   // would need to sometimes free the first call's result.
126   unsigned char *p;
127   char oline[256], htmp[5];
128   int i;
129   switch (gen->type) {
130     case GEN_OTHERNAME:
131       if (!X509V3_add_value("othername", "<unsupported>", &ret)) {
132         return NULL;
133       }
134       break;
135 
136     case GEN_X400:
137       if (!X509V3_add_value("X400Name", "<unsupported>", &ret)) {
138         return NULL;
139       }
140       break;
141 
142     case GEN_EDIPARTY:
143       if (!X509V3_add_value("EdiPartyName", "<unsupported>", &ret)) {
144         return NULL;
145       }
146       break;
147 
148     case GEN_EMAIL:
149       if (!x509V3_add_value_asn1_string("email", gen->d.ia5, &ret)) {
150         return NULL;
151       }
152       break;
153 
154     case GEN_DNS:
155       if (!x509V3_add_value_asn1_string("DNS", gen->d.ia5, &ret)) {
156         return NULL;
157       }
158       break;
159 
160     case GEN_URI:
161       if (!x509V3_add_value_asn1_string("URI", gen->d.ia5, &ret)) {
162         return NULL;
163       }
164       break;
165 
166     case GEN_DIRNAME:
167       if (X509_NAME_oneline(gen->d.dirn, oline, 256) == NULL ||
168           !X509V3_add_value("DirName", oline, &ret)) {
169         return NULL;
170       }
171       break;
172 
173     case GEN_IPADD:
174       p = gen->d.ip->data;
175       if (gen->d.ip->length == 4) {
176         snprintf(oline, sizeof(oline), "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
177       } else if (gen->d.ip->length == 16) {
178         oline[0] = 0;
179         for (i = 0; i < 8; i++) {
180           uint16_t v = ((uint16_t)p[0] << 8) | p[1];
181           snprintf(htmp, sizeof(htmp), "%X", v);
182           p += 2;
183           OPENSSL_strlcat(oline, htmp, sizeof(oline));
184           if (i != 7) {
185             OPENSSL_strlcat(oline, ":", sizeof(oline));
186           }
187         }
188       } else {
189         if (!X509V3_add_value("IP Address", "<invalid>", &ret)) {
190           return NULL;
191         }
192         break;
193       }
194       if (!X509V3_add_value("IP Address", oline, &ret)) {
195         return NULL;
196       }
197       break;
198 
199     case GEN_RID:
200       i2t_ASN1_OBJECT(oline, 256, gen->d.rid);
201       if (!X509V3_add_value("Registered ID", oline, &ret)) {
202         return NULL;
203       }
204       break;
205   }
206   return ret;
207 }
208 
GENERAL_NAME_print(BIO * out,const GENERAL_NAME * gen)209 int GENERAL_NAME_print(BIO *out, const GENERAL_NAME *gen) {
210   switch (gen->type) {
211     case GEN_OTHERNAME:
212       BIO_printf(out, "othername:<unsupported>");
213       break;
214 
215     case GEN_X400:
216       BIO_printf(out, "X400Name:<unsupported>");
217       break;
218 
219     case GEN_EDIPARTY:
220       // Maybe fix this: it is supported now
221       BIO_printf(out, "EdiPartyName:<unsupported>");
222       break;
223 
224     case GEN_EMAIL:
225       BIO_printf(out, "email:");
226       ASN1_STRING_print(out, gen->d.ia5);
227       break;
228 
229     case GEN_DNS:
230       BIO_printf(out, "DNS:");
231       ASN1_STRING_print(out, gen->d.ia5);
232       break;
233 
234     case GEN_URI:
235       BIO_printf(out, "URI:");
236       ASN1_STRING_print(out, gen->d.ia5);
237       break;
238 
239     case GEN_DIRNAME:
240       BIO_printf(out, "DirName: ");
241       X509_NAME_print_ex(out, gen->d.dirn, 0, XN_FLAG_ONELINE);
242       break;
243 
244     case GEN_IPADD: {
245       const unsigned char *p = gen->d.ip->data;
246       if (gen->d.ip->length == 4) {
247         BIO_printf(out, "IP Address:%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
248       } else if (gen->d.ip->length == 16) {
249         BIO_printf(out, "IP Address");
250         for (int 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;
254         }
255         BIO_puts(out, "\n");
256       } else {
257         BIO_printf(out, "IP Address:<invalid>");
258         break;
259       }
260       break;
261     }
262 
263     case GEN_RID:
264       BIO_printf(out, "Registered ID");
265       i2a_ASN1_OBJECT(out, gen->d.rid);
266       break;
267   }
268   return 1;
269 }
270 
v2i_issuer_alt(const X509V3_EXT_METHOD * method,const X509V3_CTX * ctx,const STACK_OF (CONF_VALUE)* nval)271 static void *v2i_issuer_alt(const X509V3_EXT_METHOD *method,
272                             const X509V3_CTX *ctx,
273                             const STACK_OF(CONF_VALUE) *nval) {
274   GENERAL_NAMES *gens = sk_GENERAL_NAME_new_null();
275   if (gens == NULL) {
276     return NULL;
277   }
278   for (size_t i = 0; i < sk_CONF_VALUE_num(nval); i++) {
279     const CONF_VALUE *cnf = sk_CONF_VALUE_value(nval, i);
280     if (x509v3_conf_name_matches(cnf->name, "issuer") && cnf->value &&
281         !strcmp(cnf->value, "copy")) {
282       if (!copy_issuer(ctx, gens)) {
283         goto err;
284       }
285     } else {
286       GENERAL_NAME *gen = v2i_GENERAL_NAME(method, ctx, cnf);
287       if (gen == NULL || !sk_GENERAL_NAME_push(gens, gen)) {
288         GENERAL_NAME_free(gen);
289         goto err;
290       }
291     }
292   }
293   return gens;
294 err:
295   sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
296   return NULL;
297 }
298 
299 // Append subject altname of issuer to issuer alt name of subject
300 
copy_issuer(const X509V3_CTX * ctx,GENERAL_NAMES * gens)301 static int copy_issuer(const X509V3_CTX *ctx, GENERAL_NAMES *gens) {
302   if (ctx && (ctx->flags == X509V3_CTX_TEST)) {
303     return 1;
304   }
305   if (!ctx || !ctx->issuer_cert) {
306     OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_ISSUER_DETAILS);
307     return 0;
308   }
309   int i = X509_get_ext_by_NID(ctx->issuer_cert, NID_subject_alt_name, -1);
310   if (i < 0) {
311     return 1;
312   }
313 
314   int ret = 0;
315   GENERAL_NAMES *ialt = NULL;
316   X509_EXTENSION *ext;
317   if (!(ext = X509_get_ext(ctx->issuer_cert, i)) ||
318       !(ialt = X509V3_EXT_d2i(ext))) {
319     OPENSSL_PUT_ERROR(X509V3, X509V3_R_ISSUER_DECODE_ERROR);
320     goto err;
321   }
322 
323   for (size_t j = 0; j < sk_GENERAL_NAME_num(ialt); j++) {
324     GENERAL_NAME *gen = sk_GENERAL_NAME_value(ialt, j);
325     if (!sk_GENERAL_NAME_push(gens, gen)) {
326       goto err;
327     }
328     // Ownership of |gen| has moved from |ialt| to |gens|.
329     sk_GENERAL_NAME_set(ialt, j, NULL);
330   }
331 
332   ret = 1;
333 
334 err:
335   GENERAL_NAMES_free(ialt);
336   return ret;
337 }
338 
v2i_subject_alt(const X509V3_EXT_METHOD * method,const X509V3_CTX * ctx,const STACK_OF (CONF_VALUE)* nval)339 static void *v2i_subject_alt(const X509V3_EXT_METHOD *method,
340                              const X509V3_CTX *ctx,
341                              const STACK_OF(CONF_VALUE) *nval) {
342   GENERAL_NAMES *gens = sk_GENERAL_NAME_new_null();
343   if (gens == NULL) {
344     return NULL;
345   }
346   for (size_t i = 0; i < sk_CONF_VALUE_num(nval); i++) {
347     const CONF_VALUE *cnf = sk_CONF_VALUE_value(nval, i);
348     if (x509v3_conf_name_matches(cnf->name, "email") && cnf->value &&
349         !strcmp(cnf->value, "copy")) {
350       if (!copy_email(ctx, gens, 0)) {
351         goto err;
352       }
353     } else if (x509v3_conf_name_matches(cnf->name, "email") && cnf->value &&
354                !strcmp(cnf->value, "move")) {
355       if (!copy_email(ctx, gens, 1)) {
356         goto err;
357       }
358     } else {
359       GENERAL_NAME *gen = v2i_GENERAL_NAME(method, ctx, cnf);
360       if (gen == NULL || !sk_GENERAL_NAME_push(gens, gen)) {
361         GENERAL_NAME_free(gen);
362         goto err;
363       }
364     }
365   }
366   return gens;
367 err:
368   sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
369   return NULL;
370 }
371 
372 // Copy any email addresses in a certificate or request to GENERAL_NAMES
373 
copy_email(const X509V3_CTX * ctx,GENERAL_NAMES * gens,int move_p)374 static int copy_email(const X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p) {
375   X509_NAME *nm;
376   ASN1_IA5STRING *email = NULL;
377   X509_NAME_ENTRY *ne;
378   GENERAL_NAME *gen = NULL;
379   int i;
380   if (ctx != NULL && ctx->flags == X509V3_CTX_TEST) {
381     return 1;
382   }
383   if (!ctx || (!ctx->subject_cert && !ctx->subject_req)) {
384     OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_SUBJECT_DETAILS);
385     goto err;
386   }
387   // Find the subject name
388   if (ctx->subject_cert) {
389     nm = X509_get_subject_name(ctx->subject_cert);
390   } else {
391     nm = X509_REQ_get_subject_name(ctx->subject_req);
392   }
393 
394   // Now add any email address(es) to STACK
395   i = -1;
396   while ((i = X509_NAME_get_index_by_NID(nm, NID_pkcs9_emailAddress, i)) >= 0) {
397     ne = X509_NAME_get_entry(nm, i);
398     email = ASN1_STRING_dup(X509_NAME_ENTRY_get_data(ne));
399     if (move_p) {
400       X509_NAME_delete_entry(nm, i);
401       X509_NAME_ENTRY_free(ne);
402       i--;
403     }
404     if (!email || !(gen = GENERAL_NAME_new())) {
405       goto err;
406     }
407     gen->d.ia5 = email;
408     email = NULL;
409     gen->type = GEN_EMAIL;
410     if (!sk_GENERAL_NAME_push(gens, gen)) {
411       goto err;
412     }
413     gen = NULL;
414   }
415 
416   return 1;
417 
418 err:
419   GENERAL_NAME_free(gen);
420   ASN1_IA5STRING_free(email);
421   return 0;
422 }
423 
v2i_GENERAL_NAMES(const X509V3_EXT_METHOD * method,const X509V3_CTX * ctx,const STACK_OF (CONF_VALUE)* nval)424 GENERAL_NAMES *v2i_GENERAL_NAMES(const X509V3_EXT_METHOD *method,
425                                  const X509V3_CTX *ctx,
426                                  const STACK_OF(CONF_VALUE) *nval) {
427   GENERAL_NAMES *gens = sk_GENERAL_NAME_new_null();
428   if (gens == NULL) {
429     return NULL;
430   }
431   for (size_t i = 0; i < sk_CONF_VALUE_num(nval); i++) {
432     const CONF_VALUE *cnf = sk_CONF_VALUE_value(nval, i);
433     GENERAL_NAME *gen = v2i_GENERAL_NAME(method, ctx, cnf);
434     if (gen == NULL || !sk_GENERAL_NAME_push(gens, gen)) {
435       GENERAL_NAME_free(gen);
436       goto err;
437     }
438   }
439   return gens;
440 err:
441   sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
442   return NULL;
443 }
444 
v2i_GENERAL_NAME(const X509V3_EXT_METHOD * method,const X509V3_CTX * ctx,const CONF_VALUE * cnf)445 GENERAL_NAME *v2i_GENERAL_NAME(const X509V3_EXT_METHOD *method,
446                                const X509V3_CTX *ctx, const CONF_VALUE *cnf) {
447   return v2i_GENERAL_NAME_ex(NULL, method, ctx, cnf, 0);
448 }
449 
a2i_GENERAL_NAME(GENERAL_NAME * out,const X509V3_EXT_METHOD * method,const X509V3_CTX * ctx,int gen_type,const char * value,int is_nc)450 GENERAL_NAME *a2i_GENERAL_NAME(GENERAL_NAME *out,
451                                const X509V3_EXT_METHOD *method,
452                                const X509V3_CTX *ctx, int gen_type,
453                                const char *value, int is_nc) {
454   if (!value) {
455     OPENSSL_PUT_ERROR(X509V3, X509V3_R_MISSING_VALUE);
456     return NULL;
457   }
458 
459   GENERAL_NAME *gen = NULL;
460   if (out) {
461     gen = out;
462   } else {
463     gen = GENERAL_NAME_new();
464     if (gen == NULL) {
465       return NULL;
466     }
467   }
468 
469   switch (gen_type) {
470     case GEN_URI:
471     case GEN_EMAIL:
472     case GEN_DNS: {
473       ASN1_IA5STRING *str = ASN1_IA5STRING_new();
474       if (str == NULL || !ASN1_STRING_set(str, value, strlen(value))) {
475         ASN1_STRING_free(str);
476         goto err;
477       }
478       gen->type = gen_type;
479       gen->d.ia5 = str;
480       break;
481     }
482 
483     case GEN_RID: {
484       ASN1_OBJECT *obj;
485       if (!(obj = OBJ_txt2obj(value, 0))) {
486         OPENSSL_PUT_ERROR(X509V3, X509V3_R_BAD_OBJECT);
487         ERR_add_error_data(2, "value=", value);
488         goto err;
489       }
490       gen->type = GEN_RID;
491       gen->d.rid = obj;
492       break;
493     }
494 
495     case GEN_IPADD:
496       gen->type = GEN_IPADD;
497       if (is_nc) {
498         gen->d.ip = a2i_IPADDRESS_NC(value);
499       } else {
500         gen->d.ip = a2i_IPADDRESS(value);
501       }
502       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;
508 
509     case GEN_DIRNAME:
510       if (!do_dirname(gen, value, ctx)) {
511         OPENSSL_PUT_ERROR(X509V3, X509V3_R_DIRNAME_ERROR);
512         goto err;
513       }
514       break;
515 
516     case GEN_OTHERNAME:
517       if (!do_othername(gen, value, ctx)) {
518         OPENSSL_PUT_ERROR(X509V3, X509V3_R_OTHERNAME_ERROR);
519         goto err;
520       }
521       break;
522     default:
523       OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNSUPPORTED_TYPE);
524       goto err;
525   }
526 
527   return gen;
528 
529 err:
530   if (!out) {
531     GENERAL_NAME_free(gen);
532   }
533   return NULL;
534 }
535 
v2i_GENERAL_NAME_ex(GENERAL_NAME * out,const X509V3_EXT_METHOD * method,const X509V3_CTX * ctx,const CONF_VALUE * cnf,int is_nc)536 GENERAL_NAME *v2i_GENERAL_NAME_ex(GENERAL_NAME *out,
537                                   const X509V3_EXT_METHOD *method,
538                                   const X509V3_CTX *ctx, const CONF_VALUE *cnf,
539                                   int is_nc) {
540   const char *name = cnf->name;
541   const char *value = cnf->value;
542   if (!value) {
543     OPENSSL_PUT_ERROR(X509V3, X509V3_R_MISSING_VALUE);
544     return NULL;
545   }
546 
547   int type;
548   if (x509v3_conf_name_matches(name, "email")) {
549     type = GEN_EMAIL;
550   } else if (x509v3_conf_name_matches(name, "URI")) {
551     type = GEN_URI;
552   } else if (x509v3_conf_name_matches(name, "DNS")) {
553     type = GEN_DNS;
554   } else if (x509v3_conf_name_matches(name, "RID")) {
555     type = GEN_RID;
556   } else if (x509v3_conf_name_matches(name, "IP")) {
557     type = GEN_IPADD;
558   } else if (x509v3_conf_name_matches(name, "dirName")) {
559     type = GEN_DIRNAME;
560   } else if (x509v3_conf_name_matches(name, "otherName")) {
561     type = GEN_OTHERNAME;
562   } else {
563     OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNSUPPORTED_OPTION);
564     ERR_add_error_data(2, "name=", name);
565     return NULL;
566   }
567 
568   return a2i_GENERAL_NAME(out, method, ctx, type, value, is_nc);
569 }
570 
do_othername(GENERAL_NAME * gen,const char * value,const X509V3_CTX * ctx)571 static int do_othername(GENERAL_NAME *gen, const char *value,
572                         const X509V3_CTX *ctx) {
573   const char *semicolon = strchr(value, ';');
574   if (semicolon == NULL) {
575     return 0;
576   }
577 
578   OTHERNAME *name = OTHERNAME_new();
579   if (name == NULL) {
580     return 0;
581   }
582 
583   char *objtmp = OPENSSL_strndup(value, semicolon - value);
584   if (objtmp == NULL) {
585     goto err;
586   }
587   ASN1_OBJECT_free(name->type_id);
588   name->type_id = OBJ_txt2obj(objtmp, /*dont_search_names=*/0);
589   OPENSSL_free(objtmp);
590   if (name->type_id == NULL) {
591     goto err;
592   }
593 
594   ASN1_TYPE_free(name->value);
595   name->value = ASN1_generate_v3(semicolon + 1, ctx);
596   if (name->value == NULL) {
597     goto err;
598   }
599 
600   gen->type = GEN_OTHERNAME;
601   gen->d.otherName = name;
602   return 1;
603 
604 err:
605   OTHERNAME_free(name);
606   return 0;
607 }
608 
do_dirname(GENERAL_NAME * gen,const char * value,const X509V3_CTX * ctx)609 static int do_dirname(GENERAL_NAME *gen, const char *value,
610                       const X509V3_CTX *ctx) {
611   int ret = 0;
612   X509_NAME *nm = X509_NAME_new();
613   if (nm == NULL) {
614     goto err;
615   }
616   const STACK_OF(CONF_VALUE) *sk = X509V3_get_section(ctx, value);
617   if (sk == NULL) {
618     OPENSSL_PUT_ERROR(X509V3, X509V3_R_SECTION_NOT_FOUND);
619     ERR_add_error_data(2, "section=", value);
620     goto err;
621   }
622   // FIXME: should allow other character types...
623   if (!X509V3_NAME_from_section(nm, sk, MBSTRING_ASC)) {
624     goto err;
625   }
626   gen->type = GEN_DIRNAME;
627   gen->d.dirn = nm;
628   ret = 1;
629 
630 err:
631   if (!ret) {
632     X509_NAME_free(nm);
633   }
634   return ret;
635 }
636