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