Home | History | Annotate | Line # | Download | only in x509
      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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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