v3_alt.c revision 296465
15455Sdg/* v3_alt.c */
21541Srgrimes/*
31541Srgrimes * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
41549Srgrimes * project.
51549Srgrimes */
61549Srgrimes/* ====================================================================
71549Srgrimes * Copyright (c) 1999-2003 The OpenSSL Project.  All rights reserved.
81541Srgrimes *
91549Srgrimes * Redistribution and use in source and binary forms, with or without
101541Srgrimes * modification, are permitted provided that the following conditions
111541Srgrimes * are met:
121541Srgrimes *
131541Srgrimes * 1. Redistributions of source code must retain the above copyright
141541Srgrimes *    notice, this list of conditions and the following disclaimer.
151541Srgrimes *
161541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
171541Srgrimes *    notice, this list of conditions and the following disclaimer in
181541Srgrimes *    the documentation and/or other materials provided with the
191541Srgrimes *    distribution.
201541Srgrimes *
211541Srgrimes * 3. All advertising materials mentioning features or use of this
2258705Scharnier *    software must display the following acknowledgment:
231541Srgrimes *    "This product includes software developed by the OpenSSL Project
241541Srgrimes *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
251541Srgrimes *
261541Srgrimes * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
271541Srgrimes *    endorse or promote products derived from this software without
281541Srgrimes *    prior written permission. For written permission, please contact
291541Srgrimes *    licensing@OpenSSL.org.
301541Srgrimes *
311541Srgrimes * 5. Products derived from this software may not be called "OpenSSL"
321541Srgrimes *    nor may "OpenSSL" appear in their names without prior written
331541Srgrimes *    permission of the OpenSSL Project.
341541Srgrimes *
351541Srgrimes * 6. Redistributions of any form whatsoever must retain the following
361541Srgrimes *    acknowledgment:
371541Srgrimes *    "This product includes software developed by the OpenSSL Project
381541Srgrimes *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
391541Srgrimes *
401541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
411817Sdg * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
421541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
431541Srgrimes * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
441541Srgrimes * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
451541Srgrimes * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
461541Srgrimes * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
471541Srgrimes * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
485455Sdg * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
491541Srgrimes * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
501541Srgrimes * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
511541Srgrimes * OF THE POSSIBILITY OF SUCH DAMAGE.
521541Srgrimes * ====================================================================
531541Srgrimes *
545455Sdg * This product includes cryptographic software written by Eric Young
555455Sdg * (eay@cryptsoft.com).  This product includes software written by Tim
565455Sdg * Hudson (tjh@cryptsoft.com).
571541Srgrimes *
585455Sdg */
591541Srgrimes
601541Srgrimes#include <stdio.h>
611541Srgrimes#include "cryptlib.h"
621541Srgrimes#include <openssl/conf.h>
631541Srgrimes#include <openssl/x509v3.h>
641541Srgrimes
651541Srgrimesstatic GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method,
661541Srgrimes                                      X509V3_CTX *ctx,
671541Srgrimes                                      STACK_OF(CONF_VALUE) *nval);
681541Srgrimesstatic GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method,
691541Srgrimes                                     X509V3_CTX *ctx,
701541Srgrimes                                     STACK_OF(CONF_VALUE) *nval);
711541Srgrimesstatic int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p);
721541Srgrimesstatic int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens);
73116226Sobrienstatic int do_othername(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx);
74116226Sobrienstatic int do_dirname(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx);
75116226Sobrien
76116226Sobrienconst X509V3_EXT_METHOD v3_alt[] = {
771541Srgrimes    {NID_subject_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES),
781541Srgrimes     0, 0, 0, 0,
7976949Sjhb     0, 0,
8076166Smarkm     (X509V3_EXT_I2V) i2v_GENERAL_NAMES,
8176166Smarkm     (X509V3_EXT_V2I)v2i_subject_alt,
821549Srgrimes     NULL, NULL, NULL},
831549Srgrimes
8476949Sjhb    {NID_issuer_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES),
8512662Sdg     0, 0, 0, 0,
8676949Sjhb     0, 0,
871541Srgrimes     (X509V3_EXT_I2V) i2v_GENERAL_NAMES,
881541Srgrimes     (X509V3_EXT_V2I)v2i_issuer_alt,
8912662Sdg     NULL, NULL, NULL},
9012662Sdg};
9112662Sdg
9212662SdgSTACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES(X509V3_EXT_METHOD *method,
931541Srgrimes                                        GENERAL_NAMES *gens,
941541Srgrimes                                        STACK_OF(CONF_VALUE) *ret)
954207Sdg{
969507Sdg    int i;
979507Sdg    GENERAL_NAME *gen;
9812662Sdg    for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
991541Srgrimes        gen = sk_GENERAL_NAME_value(gens, i);
10092727Salfred        ret = i2v_GENERAL_NAME(method, gen, ret);
1011549Srgrimes    }
10232585Sdyson    if (!ret)
10332585Sdyson        return sk_CONF_VALUE_new_null();
1041549Srgrimes    return ret;
1051549Srgrimes}
10634202Sdyson
10734202SdysonSTACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method,
10834202Sdyson                                       GENERAL_NAME *gen,
10934202Sdyson                                       STACK_OF(CONF_VALUE) *ret)
11034202Sdyson{
11134202Sdyson    unsigned char *p;
11234202Sdyson    char oline[256], htmp[5];
11334202Sdyson    int i;
11434202Sdyson    switch (gen->type) {
11592588Sgreen    case GEN_OTHERNAME:
11634202Sdyson        X509V3_add_value("othername", "<unsupported>", &ret);
11734202Sdyson        break;
11834202Sdyson
11942957Sdillon    case GEN_X400:
12034202Sdyson        X509V3_add_value("X400Name", "<unsupported>", &ret);
12134202Sdyson        break;
122100456Salc
12338799Sdfr    case GEN_EDIPARTY:
12434202Sdyson        X509V3_add_value("EdiPartyName", "<unsupported>", &ret);
125100456Salc        break;
12634202Sdyson
12734202Sdyson    case GEN_EMAIL:
12834202Sdyson        X509V3_add_value_uchar("email", gen->d.ia5->data, &ret);
12942957Sdillon        break;
13034202Sdyson
13134202Sdyson    case GEN_DNS:
13292588Sgreen        X509V3_add_value_uchar("DNS", gen->d.ia5->data, &ret);
13334202Sdyson        break;
13492588Sgreen
13534202Sdyson    case GEN_URI:
13634202Sdyson        X509V3_add_value_uchar("URI", gen->d.ia5->data, &ret);
13734202Sdyson        break;
13834202Sdyson
13934202Sdyson    case GEN_DIRNAME:
14034202Sdyson        X509_NAME_oneline(gen->d.dirn, oline, 256);
14179224Sdillon        X509V3_add_value("DirName", oline, &ret);
142113761Salc        break;
14334202Sdyson
144113761Salc    case GEN_IPADD:
14534202Sdyson        p = gen->d.ip->data;
146113761Salc        if (gen->d.ip->length == 4)
147100456Salc            BIO_snprintf(oline, sizeof oline,
14834202Sdyson                         "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
149100456Salc        else if (gen->d.ip->length == 16) {
15034202Sdyson            oline[0] = 0;
151113761Salc            for (i = 0; i < 8; i++) {
15234202Sdyson                BIO_snprintf(htmp, sizeof htmp, "%X", p[0] << 8 | p[1]);
15334202Sdyson                p += 2;
15434202Sdyson                strcat(oline, htmp);
15534202Sdyson                if (i != 7)
15634202Sdyson                    strcat(oline, ":");
15734202Sdyson            }
15834202Sdyson        } else {
15979224Sdillon            X509V3_add_value("IP Address", "<invalid>", &ret);
16034202Sdyson            break;
16134202Sdyson        }
16234202Sdyson        X509V3_add_value("IP Address", oline, &ret);
16334202Sdyson        break;
16434202Sdyson
16534202Sdyson    case GEN_RID:
16634202Sdyson        i2t_ASN1_OBJECT(oline, 256, gen->d.rid);
1671541Srgrimes        X509V3_add_value("Registered ID", oline, &ret);
16851488Sdillon        break;
16951488Sdillon    }
17051488Sdillon    return ret;
17151488Sdillon}
17251488Sdillon
17351488Sdillonint GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen)
17451488Sdillon{
17551488Sdillon    unsigned char *p;
17651488Sdillon    int i;
1771541Srgrimes    switch (gen->type) {
1781541Srgrimes    case GEN_OTHERNAME:
17958634Scharnier        BIO_printf(out, "othername:<unsupported>");
1801541Srgrimes        break;
1811541Srgrimes
1821541Srgrimes    case GEN_X400:
1831541Srgrimes        BIO_printf(out, "X400Name:<unsupported>");
1841541Srgrimes        break;
1851541Srgrimes
1861541Srgrimes    case GEN_EDIPARTY:
1871541Srgrimes        /* Maybe fix this: it is supported now */
1881541Srgrimes        BIO_printf(out, "EdiPartyName:<unsupported>");
1891541Srgrimes        break;
1901541Srgrimes
1911541Srgrimes    case GEN_EMAIL:
19279224Sdillon        BIO_printf(out, "email:%s", gen->d.ia5->data);
1931541Srgrimes        break;
1941541Srgrimes
19576827Salfred    case GEN_DNS:
19676827Salfred        BIO_printf(out, "DNS:%s", gen->d.ia5->data);
1971541Srgrimes        break;
1985455Sdg
199116650Salc    case GEN_URI:
20094977Salc        BIO_printf(out, "URI:%s", gen->d.ia5->data);
20132702Sdyson        break;
2025455Sdg
2035455Sdg    case GEN_DIRNAME:
20434202Sdyson        BIO_printf(out, "DirName: ");
20532702Sdyson        X509_NAME_print_ex(out, gen->d.dirn, 0, XN_FLAG_ONELINE);
20634202Sdyson        break;
2071541Srgrimes
20834202Sdyson    case GEN_IPADD:
20994977Salc        p = gen->d.ip->data;
21095021Salc        if (gen->d.ip->length == 4)
2111541Srgrimes            BIO_printf(out, "IP Address:%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
21295021Salc        else if (gen->d.ip->length == 16) {
2135455Sdg            BIO_printf(out, "IP Address");
2141541Srgrimes            for (i = 0; i < 8; i++) {
2151541Srgrimes                BIO_printf(out, ":%X", p[0] << 8 | p[1]);
2165455Sdg                p += 2;
2175455Sdg            }
2181541Srgrimes            BIO_puts(out, "\n");
21951488Sdillon        } else {
22095021Salc            BIO_printf(out, "IP Address:<invalid>");
22195021Salc            break;
22295021Salc        }
22395021Salc        break;
22495021Salc
22594977Salc    case GEN_RID:
22694977Salc        BIO_printf(out, "Registered ID");
22794977Salc        i2a_ASN1_OBJECT(out, gen->d.rid);
22895764Salc        break;
22995764Salc    }
23094977Salc    return 1;
23195764Salc}
23294977Salc
23394977Salcstatic GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method,
23494977Salc                                     X509V3_CTX *ctx,
23595764Salc                                     STACK_OF(CONF_VALUE) *nval)
23695021Salc{
23732585Sdyson    GENERAL_NAMES *gens = NULL;
23832585Sdyson    CONF_VALUE *cnf;
23932585Sdyson    int i;
24032585Sdyson    if (!(gens = sk_GENERAL_NAME_new_null())) {
24132585Sdyson        X509V3err(X509V3_F_V2I_ISSUER_ALT, ERR_R_MALLOC_FAILURE);
24232585Sdyson        return NULL;
24332585Sdyson    }
24432585Sdyson    for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
24532585Sdyson        cnf = sk_CONF_VALUE_value(nval, i);
24634202Sdyson        if (!name_cmp(cnf->name, "issuer") && cnf->value &&
24732585Sdyson            !strcmp(cnf->value, "copy")) {
24834202Sdyson            if (!copy_issuer(ctx, gens))
24932585Sdyson                goto err;
25095764Salc        } else {
25195764Salc            GENERAL_NAME *gen;
25232585Sdyson            if (!(gen = v2i_GENERAL_NAME(method, ctx, cnf)))
25332585Sdyson                goto err;
25432585Sdyson            sk_GENERAL_NAME_push(gens, gen);
25532585Sdyson        }
25632585Sdyson    }
25732585Sdyson    return gens;
25894981Salc err:
25994981Salc    sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
26094981Salc    return NULL;
26132585Sdyson}
26234202Sdyson
26334202Sdyson/* Append subject altname of issuer to issuer alt name of subject */
2641541Srgrimes
2657695Sdgstatic int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens)
26634202Sdyson{
26732702Sdyson    GENERAL_NAMES *ialt;
26834202Sdyson    GENERAL_NAME *gen;
26920054Sdyson    X509_EXTENSION *ext;
27037563Sbde    int i;
27120054Sdyson    if (ctx && (ctx->flags == CTX_TEST))
27220054Sdyson        return 1;
27320449Sdyson    if (!ctx || !ctx->issuer_cert) {
27432286Sdyson        X509V3err(X509V3_F_COPY_ISSUER, X509V3_R_NO_ISSUER_DETAILS);
27532286Sdyson        goto err;
27632286Sdyson    }
27732286Sdyson    i = X509_get_ext_by_NID(ctx->issuer_cert, NID_subject_alt_name, -1);
27886236Sdillon    if (i < 0)
27986236Sdillon        return 1;
28086236Sdillon    if (!(ext = X509_get_ext(ctx->issuer_cert, i)) ||
28186236Sdillon        !(ialt = X509V3_EXT_d2i(ext))) {
28295701Salc        X509V3err(X509V3_F_COPY_ISSUER, X509V3_R_ISSUER_DECODE_ERROR);
28395701Salc        goto err;
28432286Sdyson    }
28534202Sdyson
28686236Sdillon    for (i = 0; i < sk_GENERAL_NAME_num(ialt); i++) {
287113739Salc        gen = sk_GENERAL_NAME_value(ialt, i);
28838135Sdfr        if (!sk_GENERAL_NAME_push(gens, gen)) {
289113739Salc            X509V3err(X509V3_F_COPY_ISSUER, ERR_R_MALLOC_FAILURE);
29032286Sdyson            goto err;
29192588Sgreen        }
2921541Srgrimes    }
2931541Srgrimes    sk_GENERAL_NAME_free(ialt);
2941541Srgrimes
2951541Srgrimes    return 1;
29634202Sdyson
2971541Srgrimes err:
2985455Sdg    return 0;
2995455Sdg
3001541Srgrimes}
30134202Sdyson
30234202Sdysonstatic GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method,
3031541Srgrimes                                      X509V3_CTX *ctx,
30442957Sdillon                                      STACK_OF(CONF_VALUE) *nval)
30542957Sdillon{
30642957Sdillon    GENERAL_NAMES *gens = NULL;
30734202Sdyson    CONF_VALUE *cnf;
30834202Sdyson    int i;
30995764Salc    if (!(gens = sk_GENERAL_NAME_new_null())) {
31032585Sdyson        X509V3err(X509V3_F_V2I_SUBJECT_ALT, ERR_R_MALLOC_FAILURE);
31132585Sdyson        return NULL;
31242957Sdillon    }
31342957Sdillon    for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
31442957Sdillon        cnf = sk_CONF_VALUE_value(nval, i);
31542957Sdillon        if (!name_cmp(cnf->name, "email") && cnf->value &&
31634202Sdyson            !strcmp(cnf->value, "copy")) {
31734202Sdyson            if (!copy_email(ctx, gens, 0))
31841322Sdg                goto err;
31998849Sken        } else if (!name_cmp(cnf->name, "email") && cnf->value &&
32098849Sken                   !strcmp(cnf->value, "move")) {
321111977Sken            if (!copy_email(ctx, gens, 1))
322111977Sken                goto err;
323111977Sken        } else {
324111977Sken            GENERAL_NAME *gen;
325111977Sken            if (!(gen = v2i_GENERAL_NAME(method, ctx, cnf)))
326111977Sken                goto err;
327111977Sken            sk_GENERAL_NAME_push(gens, gen);
32898849Sken        }
329105466Salc    }
33098849Sken    return gens;
331111977Sken err:
332111977Sken    sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
33398849Sken    return NULL;
33498849Sken}
33598849Sken
336105466Salc/*
337116552Salc * Copy any email addresses in a certificate or request to GENERAL_NAMES
33898849Sken */
33998849Sken
34098849Skenstatic int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p)
3411541Srgrimes{
34242957Sdillon    X509_NAME *nm;
34342957Sdillon    ASN1_IA5STRING *email = NULL;
34442957Sdillon    X509_NAME_ENTRY *ne;
34542957Sdillon    GENERAL_NAME *gen = NULL;
34642957Sdillon    int i;
34758634Scharnier    if (ctx != NULL && ctx->flags == CTX_TEST)
34842957Sdillon        return 1;
34942957Sdillon    if (!ctx || (!ctx->subject_cert && !ctx->subject_req)) {
35042957Sdillon        X509V3err(X509V3_F_COPY_EMAIL, X509V3_R_NO_SUBJECT_DETAILS);
35142957Sdillon        goto err;
35242957Sdillon    }
35342957Sdillon    /* Find the subject name */
35442957Sdillon    if (ctx->subject_cert)
35542957Sdillon        nm = X509_get_subject_name(ctx->subject_cert);
3561541Srgrimes    else
35742957Sdillon        nm = X509_REQ_get_subject_name(ctx->subject_req);
358100742Salc
35934202Sdyson    /* Now add any email address(es) to STACK */
360108068Salc    i = -1;
361108068Salc    while ((i = X509_NAME_get_index_by_NID(nm,
362108068Salc                                           NID_pkcs9_emailAddress, i)) >= 0) {
36342957Sdillon        ne = X509_NAME_get_entry(nm, i);
36434202Sdyson        email = M_ASN1_IA5STRING_dup(X509_NAME_ENTRY_get_data(ne));
3651541Srgrimes        if (move_p) {
3661541Srgrimes            X509_NAME_delete_entry(nm, i);
36792029Seivind            X509_NAME_ENTRY_free(ne);
3687695Sdg            i--;
36941322Sdg        }
37079263Sdillon        if (!email || !(gen = GENERAL_NAME_new())) {
37141322Sdg            X509V3err(X509V3_F_COPY_EMAIL, ERR_R_MALLOC_FAILURE);
37216268Sdyson            goto err;
37351488Sdillon        }
37434202Sdyson        gen->d.ia5 = email;
375100742Salc        email = NULL;
37634202Sdyson        gen->type = GEN_EMAIL;
37790935Ssilby        if (!sk_GENERAL_NAME_push(gens, gen)) {
3785455Sdg            X509V3err(X509V3_F_COPY_EMAIL, ERR_R_MALLOC_FAILURE);
3795455Sdg            goto err;
38043086Sdillon        }
38142957Sdillon        gen = NULL;
38242957Sdillon    }
38342957Sdillon
38442957Sdillon    return 1;
38542957Sdillon
38642957Sdillon err:
38738799Sdfr    GENERAL_NAME_free(gen);
388100742Salc    M_ASN1_IA5STRING_free(email);
38934202Sdyson    return 0;
39034202Sdyson
3915455Sdg}
3925455Sdg
39333936SdysonGENERAL_NAMES *v2i_GENERAL_NAMES(X509V3_EXT_METHOD *method,
3941541Srgrimes                                 X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
3951541Srgrimes{
39642957Sdillon    GENERAL_NAME *gen;
39742957Sdillon    GENERAL_NAMES *gens = NULL;
39851488Sdillon    CONF_VALUE *cnf;
39951488Sdillon    int i;
40042957Sdillon    if (!(gens = sk_GENERAL_NAME_new_null())) {
40151488Sdillon        X509V3err(X509V3_F_V2I_GENERAL_NAMES, ERR_R_MALLOC_FAILURE);
40234202Sdyson        return NULL;
40334202Sdyson    }
40495764Salc    for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
4058585Sdg        cnf = sk_CONF_VALUE_value(nval, i);
4068585Sdg        if (!(gen = v2i_GENERAL_NAME(method, ctx, cnf)))
40710988Sdyson            goto err;
4081541Srgrimes        sk_GENERAL_NAME_push(gens, gen);
4095455Sdg    }
4101541Srgrimes    return gens;
41151488Sdillon err:
41251488Sdillon    sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
41351488Sdillon    return NULL;
41451488Sdillon}
41551488Sdillon
41634202SdysonGENERAL_NAME *v2i_GENERAL_NAME(X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
41734202Sdyson                               CONF_VALUE *cnf)
41890935Ssilby{
4191541Srgrimes    return v2i_GENERAL_NAME_ex(NULL, method, ctx, cnf, 0);
4201541Srgrimes}
4211541Srgrimes
42232585SdysonGENERAL_NAME *v2i_GENERAL_NAME_ex(GENERAL_NAME *out,
4235455Sdg                                  X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
42442957Sdillon                                  CONF_VALUE *cnf, int is_nc)
42551488Sdillon{
42651488Sdillon    char is_string = 0;
42751488Sdillon    int type;
42851488Sdillon    GENERAL_NAME *gen = NULL;
42951488Sdillon
43051488Sdillon    char *name, *value;
43151488Sdillon
43242957Sdillon    name = cnf->name;
43351488Sdillon    value = cnf->value;
4341541Srgrimes
4351549Srgrimes    if (!value) {
43615819Sdyson        X509V3err(X509V3_F_V2I_GENERAL_NAME_EX, X509V3_R_MISSING_VALUE);
43749338Salc        return NULL;
4381541Srgrimes    }
43949338Salc
44015819Sdyson    if (out)
44115819Sdyson        gen = out;
44232702Sdyson    else {
44334202Sdyson        gen = GENERAL_NAME_new();
44432702Sdyson        if (gen == NULL) {
44532702Sdyson            X509V3err(X509V3_F_V2I_GENERAL_NAME_EX, ERR_R_MALLOC_FAILURE);
44632702Sdyson            return NULL;
44734202Sdyson        }
44832702Sdyson    }
44932702Sdyson
45015819Sdyson    if (!name_cmp(name, "email")) {
45115819Sdyson        is_string = 1;
45234202Sdyson        type = GEN_EMAIL;
45351488Sdillon    } else if (!name_cmp(name, "URI")) {
45451488Sdillon        is_string = 1;
45551488Sdillon        type = GEN_URI;
45651488Sdillon    } else if (!name_cmp(name, "DNS")) {
45751488Sdillon        is_string = 1;
45815819Sdyson        type = GEN_DNS;
45951488Sdillon    } else if (!name_cmp(name, "RID")) {
46051488Sdillon        ASN1_OBJECT *obj;
46115819Sdyson        if (!(obj = OBJ_txt2obj(value, 0))) {
46215819Sdyson            X509V3err(X509V3_F_V2I_GENERAL_NAME_EX, X509V3_R_BAD_OBJECT);
46351488Sdillon            ERR_add_error_data(2, "value=", value);
46415819Sdyson            goto err;
465100413Salc        }
46646349Salc        gen->d.rid = obj;
46746349Salc        type = GEN_RID;
46846349Salc    } else if (!name_cmp(name, "IP")) {
46946349Salc        if (is_nc)
47046349Salc            gen->d.ip = a2i_IPADDRESS_NC(value);
47192029Seivind        else
47224678Speter            gen->d.ip = a2i_IPADDRESS(value);
47315819Sdyson        if (gen->d.ip == NULL) {
47415819Sdyson            X509V3err(X509V3_F_V2I_GENERAL_NAME_EX, X509V3_R_BAD_IP_ADDRESS);
47592029Seivind            ERR_add_error_data(2, "value=", value);
47692029Seivind            goto err;
47715819Sdyson        }
47815819Sdyson        type = GEN_IPADD;
47916058Sdyson    } else if (!name_cmp(name, "dirName")) {
48061081Sdillon        type = GEN_DIRNAME;
48116058Sdyson        if (!do_dirname(gen, value, ctx)) {
48215819Sdyson            X509V3err(X509V3_F_V2I_GENERAL_NAME_EX, X509V3_R_DIRNAME_ERROR);
48315819Sdyson            goto err;
48415819Sdyson        }
48515819Sdyson    } else if (!name_cmp(name, "otherName")) {
48615819Sdyson        if (!do_othername(gen, value, ctx)) {
487106981Salc            X509V3err(X509V3_F_V2I_GENERAL_NAME_EX, X509V3_R_OTHERNAME_ERROR);
48815819Sdyson            goto err;
48915819Sdyson        }
49015819Sdyson        type = GEN_OTHERNAME;
49115819Sdyson    } else {
49215819Sdyson        X509V3err(X509V3_F_V2I_GENERAL_NAME_EX, X509V3_R_UNSUPPORTED_OPTION);
493100413Salc        ERR_add_error_data(2, "name=", name);
49415819Sdyson        goto err;
49515819Sdyson    }
49615819Sdyson
49715819Sdyson    if (is_string) {
4981541Srgrimes        if (!(gen->d.ia5 = M_ASN1_IA5STRING_new()) ||
4995455Sdg            !ASN1_STRING_set(gen->d.ia5, (unsigned char *)value,
5005455Sdg                             strlen(value))) {
5015455Sdg            X509V3err(X509V3_F_V2I_GENERAL_NAME_EX, ERR_R_MALLOC_FAILURE);
5025455Sdg            goto err;
5035455Sdg        }
5045455Sdg    }
5055455Sdg
5065455Sdg    gen->type = type;
5075455Sdg
5085455Sdg    return gen;
50942957Sdillon
51042957Sdillon err:
51195701Salc    if (!out)
51295701Salc        GENERAL_NAME_free(gen);
51395701Salc    return NULL;
5141549Srgrimes}
5153449Sphk
51634202Sdysonstatic int do_othername(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx)
5171541Srgrimes{
5181541Srgrimes    char *objtmp = NULL, *p;
51951488Sdillon    int objlen;
52051488Sdillon    if (!(p = strchr(value, ';')))
52195701Salc        return 0;
52295701Salc    if (!(gen->d.otherName = OTHERNAME_new()))
52395701Salc        return 0;
52451488Sdillon    /*
52551488Sdillon     * Free this up because we will overwrite it. no need to free type_id
52651488Sdillon     * because it is static
52751488Sdillon     */
5285455Sdg    ASN1_TYPE_free(gen->d.otherName->value);
52942957Sdillon    if (!(gen->d.otherName->value = ASN1_generate_v3(p + 1, ctx)))
53042957Sdillon        return 0;
5311541Srgrimes    objlen = p - value;
53234202Sdyson    objtmp = OPENSSL_malloc(objlen + 1);
5331541Srgrimes    strncpy(objtmp, value, objlen);
5341549Srgrimes    objtmp[objlen] = 0;
53534202Sdyson    gen->d.otherName->type_id = OBJ_txt2obj(objtmp, 0);
5369507Sdg    OPENSSL_free(objtmp);
53710988Sdyson    if (!gen->d.otherName->type_id)
5381541Srgrimes        return 0;
5391541Srgrimes    return 1;
54017312Sdyson}
54117312Sdyson
54217312Sdysonstatic int do_dirname(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx)
54317312Sdyson{
54417312Sdyson    int ret;
5455455Sdg    STACK_OF(CONF_VALUE) *sk;
5465455Sdg    X509_NAME *nm;
5475455Sdg    if (!(nm = X509_NAME_new()))
5481541Srgrimes        return 0;
54934202Sdyson    sk = X509V3_get_section(ctx, value);
55092029Seivind    if (!sk) {
55134202Sdyson        X509V3err(X509V3_F_DO_DIRNAME, X509V3_R_SECTION_NOT_FOUND);
55217312Sdyson        ERR_add_error_data(2, "section=", value);
5537695Sdg        X509_NAME_free(nm);
5548876Srgrimes        return 0;
5551549Srgrimes    }
55642957Sdillon    /* FIXME: should allow other character types... */
5571541Srgrimes    ret = X509V3_NAME_from_section(nm, sk, MBSTRING_ASC);
5581541Srgrimes    if (!ret)
5595455Sdg        X509_NAME_free(nm);
5605455Sdg    gen->d.dirn = nm;
5615455Sdg
5628876Srgrimes    X509V3_section_free(ctx, sk);
5639507Sdg
5645455Sdg    return ret;
5658876Srgrimes}
5665455Sdg