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