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