155714Skris/* v3_alt.c */
2280297Sjkim/*
3280297Sjkim * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
4160814Ssimon * project.
555714Skris */
655714Skris/* ====================================================================
7352193Sjkim * Copyright (c) 1999-2019 The OpenSSL Project.  All rights reserved.
855714Skris *
955714Skris * Redistribution and use in source and binary forms, with or without
1055714Skris * modification, are permitted provided that the following conditions
1155714Skris * are met:
1255714Skris *
1355714Skris * 1. Redistributions of source code must retain the above copyright
14280297Sjkim *    notice, this list of conditions and the following disclaimer.
1555714Skris *
1655714Skris * 2. Redistributions in binary form must reproduce the above copyright
1755714Skris *    notice, this list of conditions and the following disclaimer in
1855714Skris *    the documentation and/or other materials provided with the
1955714Skris *    distribution.
2055714Skris *
2155714Skris * 3. All advertising materials mentioning features or use of this
2255714Skris *    software must display the following acknowledgment:
2355714Skris *    "This product includes software developed by the OpenSSL Project
2455714Skris *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
2555714Skris *
2655714Skris * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
2755714Skris *    endorse or promote products derived from this software without
2855714Skris *    prior written permission. For written permission, please contact
2955714Skris *    licensing@OpenSSL.org.
3055714Skris *
3155714Skris * 5. Products derived from this software may not be called "OpenSSL"
3255714Skris *    nor may "OpenSSL" appear in their names without prior written
3355714Skris *    permission of the OpenSSL Project.
3455714Skris *
3555714Skris * 6. Redistributions of any form whatsoever must retain the following
3655714Skris *    acknowledgment:
3755714Skris *    "This product includes software developed by the OpenSSL Project
3855714Skris *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
3955714Skris *
4055714Skris * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
4155714Skris * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4255714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
4355714Skris * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
4455714Skris * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
4555714Skris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
4655714Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
4755714Skris * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
4955714Skris * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
5055714Skris * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
5155714Skris * OF THE POSSIBILITY OF SUCH DAMAGE.
5255714Skris * ====================================================================
5355714Skris *
5455714Skris * This product includes cryptographic software written by Eric Young
5555714Skris * (eay@cryptsoft.com).  This product includes software written by Tim
5655714Skris * Hudson (tjh@cryptsoft.com).
5755714Skris *
5855714Skris */
5955714Skris
6055714Skris#include <stdio.h>
6155714Skris#include "cryptlib.h"
6255714Skris#include <openssl/conf.h>
6355714Skris#include <openssl/x509v3.h>
6455714Skris
65280297Sjkimstatic GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method,
66280297Sjkim                                      X509V3_CTX *ctx,
67280297Sjkim                                      STACK_OF(CONF_VALUE) *nval);
68280297Sjkimstatic GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method,
69280297Sjkim                                     X509V3_CTX *ctx,
70280297Sjkim                                     STACK_OF(CONF_VALUE) *nval);
71109998Smarkmstatic int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p);
72109998Smarkmstatic int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens);
73160814Ssimonstatic int do_othername(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx);
74160814Ssimonstatic int do_dirname(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx);
75160814Ssimon
76167612Ssimonconst X509V3_EXT_METHOD v3_alt[] = {
77280297Sjkim    {NID_subject_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES),
78280297Sjkim     0, 0, 0, 0,
79280297Sjkim     0, 0,
80280297Sjkim     (X509V3_EXT_I2V) i2v_GENERAL_NAMES,
81280297Sjkim     (X509V3_EXT_V2I)v2i_subject_alt,
82280297Sjkim     NULL, NULL, NULL},
83109998Smarkm
84280297Sjkim    {NID_issuer_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES),
85280297Sjkim     0, 0, 0, 0,
86280297Sjkim     0, 0,
87280297Sjkim     (X509V3_EXT_I2V) i2v_GENERAL_NAMES,
88280297Sjkim     (X509V3_EXT_V2I)v2i_issuer_alt,
89280297Sjkim     NULL, NULL, NULL},
90238405Sjkim
91280297Sjkim    {NID_certificate_issuer, 0, ASN1_ITEM_ref(GENERAL_NAMES),
92280297Sjkim     0, 0, 0, 0,
93280297Sjkim     0, 0,
94280297Sjkim     (X509V3_EXT_I2V) i2v_GENERAL_NAMES,
95280297Sjkim     NULL, NULL, NULL, NULL},
9655714Skris};
9755714Skris
9855714SkrisSTACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES(X509V3_EXT_METHOD *method,
99280297Sjkim                                        GENERAL_NAMES *gens,
100280297Sjkim                                        STACK_OF(CONF_VALUE) *ret)
10155714Skris{
102280297Sjkim    int i;
103280297Sjkim    GENERAL_NAME *gen;
104280297Sjkim    for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
105280297Sjkim        gen = sk_GENERAL_NAME_value(gens, i);
106280297Sjkim        ret = i2v_GENERAL_NAME(method, gen, ret);
107280297Sjkim    }
108280297Sjkim    if (!ret)
109280297Sjkim        return sk_CONF_VALUE_new_null();
110280297Sjkim    return ret;
11155714Skris}
11255714Skris
11355714SkrisSTACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method,
114280297Sjkim                                       GENERAL_NAME *gen,
115280297Sjkim                                       STACK_OF(CONF_VALUE) *ret)
11655714Skris{
117280297Sjkim    unsigned char *p;
118280297Sjkim    char oline[256], htmp[5];
119280297Sjkim    int i;
120280297Sjkim    switch (gen->type) {
121280297Sjkim    case GEN_OTHERNAME:
122325335Sjkim        if (!X509V3_add_value("othername", "<unsupported>", &ret))
123325335Sjkim            return NULL;
124280297Sjkim        break;
12555714Skris
126280297Sjkim    case GEN_X400:
127325335Sjkim        if (!X509V3_add_value("X400Name", "<unsupported>", &ret))
128325335Sjkim            return NULL;
129280297Sjkim        break;
13055714Skris
131280297Sjkim    case GEN_EDIPARTY:
132325335Sjkim        if (!X509V3_add_value("EdiPartyName", "<unsupported>", &ret))
133325335Sjkim            return NULL;
134280297Sjkim        break;
13555714Skris
136280297Sjkim    case GEN_EMAIL:
137325335Sjkim        if (!X509V3_add_value_uchar("email", gen->d.ia5->data, &ret))
138325335Sjkim            return NULL;
139280297Sjkim        break;
14055714Skris
141280297Sjkim    case GEN_DNS:
142325335Sjkim        if (!X509V3_add_value_uchar("DNS", gen->d.ia5->data, &ret))
143325335Sjkim            return NULL;
144280297Sjkim        break;
14555714Skris
146280297Sjkim    case GEN_URI:
147325335Sjkim        if (!X509V3_add_value_uchar("URI", gen->d.ia5->data, &ret))
148325335Sjkim            return NULL;
149280297Sjkim        break;
15055714Skris
151280297Sjkim    case GEN_DIRNAME:
152325335Sjkim        if (X509_NAME_oneline(gen->d.dirn, oline, 256) == NULL
153325335Sjkim                || !X509V3_add_value("DirName", oline, &ret))
154325335Sjkim            return NULL;
155280297Sjkim        break;
15655714Skris
157280297Sjkim    case GEN_IPADD:
158280297Sjkim        p = gen->d.ip->data;
159280297Sjkim        if (gen->d.ip->length == 4)
160331638Sjkim            BIO_snprintf(oline, sizeof(oline),
161280297Sjkim                         "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
162280297Sjkim        else if (gen->d.ip->length == 16) {
163280297Sjkim            oline[0] = 0;
164280297Sjkim            for (i = 0; i < 8; i++) {
165331638Sjkim                BIO_snprintf(htmp, sizeof(htmp), "%X", p[0] << 8 | p[1]);
166280297Sjkim                p += 2;
167280297Sjkim                strcat(oline, htmp);
168280297Sjkim                if (i != 7)
169280297Sjkim                    strcat(oline, ":");
170280297Sjkim            }
171280297Sjkim        } else {
172325335Sjkim            if (!X509V3_add_value("IP Address", "<invalid>", &ret))
173325335Sjkim                return NULL;
174280297Sjkim            break;
175280297Sjkim        }
176325335Sjkim        if (!X509V3_add_value("IP Address", oline, &ret))
177325335Sjkim            return NULL;
178280297Sjkim        break;
17955714Skris
180280297Sjkim    case GEN_RID:
181280297Sjkim        i2t_ASN1_OBJECT(oline, 256, gen->d.rid);
182325335Sjkim        if (!X509V3_add_value("Registered ID", oline, &ret))
183325335Sjkim            return NULL;
184280297Sjkim        break;
185280297Sjkim    }
186280297Sjkim    return ret;
18755714Skris}
18855714Skris
189109998Smarkmint GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen)
190109998Smarkm{
191280297Sjkim    unsigned char *p;
192280297Sjkim    int i;
193280297Sjkim    switch (gen->type) {
194280297Sjkim    case GEN_OTHERNAME:
195280297Sjkim        BIO_printf(out, "othername:<unsupported>");
196280297Sjkim        break;
197109998Smarkm
198280297Sjkim    case GEN_X400:
199280297Sjkim        BIO_printf(out, "X400Name:<unsupported>");
200280297Sjkim        break;
201109998Smarkm
202280297Sjkim    case GEN_EDIPARTY:
203280297Sjkim        /* Maybe fix this: it is supported now */
204280297Sjkim        BIO_printf(out, "EdiPartyName:<unsupported>");
205280297Sjkim        break;
206109998Smarkm
207280297Sjkim    case GEN_EMAIL:
208352193Sjkim        BIO_printf(out, "email:");
209352193Sjkim        ASN1_STRING_print(out, gen->d.ia5);
210280297Sjkim        break;
211109998Smarkm
212280297Sjkim    case GEN_DNS:
213352193Sjkim        BIO_printf(out, "DNS:");
214352193Sjkim        ASN1_STRING_print(out, gen->d.ia5);
215280297Sjkim        break;
216109998Smarkm
217280297Sjkim    case GEN_URI:
218352193Sjkim        BIO_printf(out, "URI:");
219352193Sjkim        ASN1_STRING_print(out, gen->d.ia5);
220280297Sjkim        break;
221109998Smarkm
222280297Sjkim    case GEN_DIRNAME:
223280297Sjkim        BIO_printf(out, "DirName: ");
224280297Sjkim        X509_NAME_print_ex(out, gen->d.dirn, 0, XN_FLAG_ONELINE);
225280297Sjkim        break;
226109998Smarkm
227280297Sjkim    case GEN_IPADD:
228280297Sjkim        p = gen->d.ip->data;
229280297Sjkim        if (gen->d.ip->length == 4)
230280297Sjkim            BIO_printf(out, "IP Address:%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
231280297Sjkim        else if (gen->d.ip->length == 16) {
232280297Sjkim            BIO_printf(out, "IP Address");
233280297Sjkim            for (i = 0; i < 8; i++) {
234280297Sjkim                BIO_printf(out, ":%X", p[0] << 8 | p[1]);
235280297Sjkim                p += 2;
236280297Sjkim            }
237280297Sjkim            BIO_puts(out, "\n");
238280297Sjkim        } else {
239280297Sjkim            BIO_printf(out, "IP Address:<invalid>");
240280297Sjkim            break;
241280297Sjkim        }
242280297Sjkim        break;
243109998Smarkm
244280297Sjkim    case GEN_RID:
245280297Sjkim        BIO_printf(out, "Registered ID");
246280297Sjkim        i2a_ASN1_OBJECT(out, gen->d.rid);
247280297Sjkim        break;
248280297Sjkim    }
249280297Sjkim    return 1;
250109998Smarkm}
251109998Smarkm
252109998Smarkmstatic GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method,
253280297Sjkim                                     X509V3_CTX *ctx,
254280297Sjkim                                     STACK_OF(CONF_VALUE) *nval)
25555714Skris{
256280297Sjkim    GENERAL_NAMES *gens = NULL;
257280297Sjkim    CONF_VALUE *cnf;
258280297Sjkim    int i;
259280297Sjkim    if (!(gens = sk_GENERAL_NAME_new_null())) {
260280297Sjkim        X509V3err(X509V3_F_V2I_ISSUER_ALT, ERR_R_MALLOC_FAILURE);
261280297Sjkim        return NULL;
262280297Sjkim    }
263280297Sjkim    for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
264280297Sjkim        cnf = sk_CONF_VALUE_value(nval, i);
265280297Sjkim        if (!name_cmp(cnf->name, "issuer") && cnf->value &&
266280297Sjkim            !strcmp(cnf->value, "copy")) {
267280297Sjkim            if (!copy_issuer(ctx, gens))
268280297Sjkim                goto err;
269280297Sjkim        } else {
270280297Sjkim            GENERAL_NAME *gen;
271280297Sjkim            if (!(gen = v2i_GENERAL_NAME(method, ctx, cnf)))
272280297Sjkim                goto err;
273280297Sjkim            sk_GENERAL_NAME_push(gens, gen);
274280297Sjkim        }
275280297Sjkim    }
276280297Sjkim    return gens;
277280297Sjkim err:
278280297Sjkim    sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
279280297Sjkim    return NULL;
28055714Skris}
28155714Skris
28255714Skris/* Append subject altname of issuer to issuer alt name of subject */
28355714Skris
284109998Smarkmstatic int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens)
28555714Skris{
286280297Sjkim    GENERAL_NAMES *ialt;
287280297Sjkim    GENERAL_NAME *gen;
288280297Sjkim    X509_EXTENSION *ext;
289280297Sjkim    int i;
290280297Sjkim    if (ctx && (ctx->flags == CTX_TEST))
291280297Sjkim        return 1;
292280297Sjkim    if (!ctx || !ctx->issuer_cert) {
293280297Sjkim        X509V3err(X509V3_F_COPY_ISSUER, X509V3_R_NO_ISSUER_DETAILS);
294280297Sjkim        goto err;
295280297Sjkim    }
296280297Sjkim    i = X509_get_ext_by_NID(ctx->issuer_cert, NID_subject_alt_name, -1);
297280297Sjkim    if (i < 0)
298280297Sjkim        return 1;
299280297Sjkim    if (!(ext = X509_get_ext(ctx->issuer_cert, i)) ||
300280297Sjkim        !(ialt = X509V3_EXT_d2i(ext))) {
301280297Sjkim        X509V3err(X509V3_F_COPY_ISSUER, X509V3_R_ISSUER_DECODE_ERROR);
302280297Sjkim        goto err;
303280297Sjkim    }
30455714Skris
305280297Sjkim    for (i = 0; i < sk_GENERAL_NAME_num(ialt); i++) {
306280297Sjkim        gen = sk_GENERAL_NAME_value(ialt, i);
307280297Sjkim        if (!sk_GENERAL_NAME_push(gens, gen)) {
308280297Sjkim            X509V3err(X509V3_F_COPY_ISSUER, ERR_R_MALLOC_FAILURE);
309280297Sjkim            goto err;
310280297Sjkim        }
311280297Sjkim    }
312280297Sjkim    sk_GENERAL_NAME_free(ialt);
31355714Skris
314280297Sjkim    return 1;
315280297Sjkim
316280297Sjkim err:
317280297Sjkim    return 0;
318280297Sjkim
31955714Skris}
32055714Skris
321109998Smarkmstatic GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method,
322280297Sjkim                                      X509V3_CTX *ctx,
323280297Sjkim                                      STACK_OF(CONF_VALUE) *nval)
32455714Skris{
325280297Sjkim    GENERAL_NAMES *gens = NULL;
326280297Sjkim    CONF_VALUE *cnf;
327280297Sjkim    int i;
328280297Sjkim    if (!(gens = sk_GENERAL_NAME_new_null())) {
329280297Sjkim        X509V3err(X509V3_F_V2I_SUBJECT_ALT, ERR_R_MALLOC_FAILURE);
330280297Sjkim        return NULL;
331280297Sjkim    }
332280297Sjkim    for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
333280297Sjkim        cnf = sk_CONF_VALUE_value(nval, i);
334280297Sjkim        if (!name_cmp(cnf->name, "email") && cnf->value &&
335280297Sjkim            !strcmp(cnf->value, "copy")) {
336280297Sjkim            if (!copy_email(ctx, gens, 0))
337280297Sjkim                goto err;
338280297Sjkim        } else if (!name_cmp(cnf->name, "email") && cnf->value &&
339280297Sjkim                   !strcmp(cnf->value, "move")) {
340280297Sjkim            if (!copy_email(ctx, gens, 1))
341280297Sjkim                goto err;
342280297Sjkim        } else {
343280297Sjkim            GENERAL_NAME *gen;
344280297Sjkim            if (!(gen = v2i_GENERAL_NAME(method, ctx, cnf)))
345280297Sjkim                goto err;
346280297Sjkim            sk_GENERAL_NAME_push(gens, gen);
347280297Sjkim        }
348280297Sjkim    }
349280297Sjkim    return gens;
350280297Sjkim err:
351280297Sjkim    sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
352280297Sjkim    return NULL;
35355714Skris}
35455714Skris
355280297Sjkim/*
356280297Sjkim * Copy any email addresses in a certificate or request to GENERAL_NAMES
35755714Skris */
35855714Skris
359109998Smarkmstatic int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p)
36055714Skris{
361280297Sjkim    X509_NAME *nm;
362280297Sjkim    ASN1_IA5STRING *email = NULL;
363280297Sjkim    X509_NAME_ENTRY *ne;
364280297Sjkim    GENERAL_NAME *gen = NULL;
365280297Sjkim    int i;
366280297Sjkim    if (ctx != NULL && ctx->flags == CTX_TEST)
367280297Sjkim        return 1;
368280297Sjkim    if (!ctx || (!ctx->subject_cert && !ctx->subject_req)) {
369280297Sjkim        X509V3err(X509V3_F_COPY_EMAIL, X509V3_R_NO_SUBJECT_DETAILS);
370280297Sjkim        goto err;
371280297Sjkim    }
372280297Sjkim    /* Find the subject name */
373280297Sjkim    if (ctx->subject_cert)
374280297Sjkim        nm = X509_get_subject_name(ctx->subject_cert);
375280297Sjkim    else
376280297Sjkim        nm = X509_REQ_get_subject_name(ctx->subject_req);
37755714Skris
378280297Sjkim    /* Now add any email address(es) to STACK */
379280297Sjkim    i = -1;
380280297Sjkim    while ((i = X509_NAME_get_index_by_NID(nm,
381280297Sjkim                                           NID_pkcs9_emailAddress, i)) >= 0) {
382280297Sjkim        ne = X509_NAME_get_entry(nm, i);
383280297Sjkim        email = M_ASN1_IA5STRING_dup(X509_NAME_ENTRY_get_data(ne));
384280297Sjkim        if (move_p) {
385280297Sjkim            X509_NAME_delete_entry(nm, i);
386280297Sjkim            X509_NAME_ENTRY_free(ne);
387280297Sjkim            i--;
388280297Sjkim        }
389280297Sjkim        if (!email || !(gen = GENERAL_NAME_new())) {
390280297Sjkim            X509V3err(X509V3_F_COPY_EMAIL, ERR_R_MALLOC_FAILURE);
391280297Sjkim            goto err;
392280297Sjkim        }
393280297Sjkim        gen->d.ia5 = email;
394280297Sjkim        email = NULL;
395280297Sjkim        gen->type = GEN_EMAIL;
396280297Sjkim        if (!sk_GENERAL_NAME_push(gens, gen)) {
397280297Sjkim            X509V3err(X509V3_F_COPY_EMAIL, ERR_R_MALLOC_FAILURE);
398280297Sjkim            goto err;
399280297Sjkim        }
400280297Sjkim        gen = NULL;
401280297Sjkim    }
40255714Skris
403280297Sjkim    return 1;
404280297Sjkim
405280297Sjkim err:
406280297Sjkim    GENERAL_NAME_free(gen);
407280297Sjkim    M_ASN1_IA5STRING_free(email);
408280297Sjkim    return 0;
409280297Sjkim
41055714Skris}
41155714Skris
412238405SjkimGENERAL_NAMES *v2i_GENERAL_NAMES(const X509V3_EXT_METHOD *method,
413280297Sjkim                                 X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
41455714Skris{
415280297Sjkim    GENERAL_NAME *gen;
416280297Sjkim    GENERAL_NAMES *gens = NULL;
417280297Sjkim    CONF_VALUE *cnf;
418280297Sjkim    int i;
419280297Sjkim    if (!(gens = sk_GENERAL_NAME_new_null())) {
420280297Sjkim        X509V3err(X509V3_F_V2I_GENERAL_NAMES, ERR_R_MALLOC_FAILURE);
421280297Sjkim        return NULL;
422280297Sjkim    }
423280297Sjkim    for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
424280297Sjkim        cnf = sk_CONF_VALUE_value(nval, i);
425280297Sjkim        if (!(gen = v2i_GENERAL_NAME(method, ctx, cnf)))
426280297Sjkim            goto err;
427280297Sjkim        sk_GENERAL_NAME_push(gens, gen);
428280297Sjkim    }
429280297Sjkim    return gens;
430280297Sjkim err:
431280297Sjkim    sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
432280297Sjkim    return NULL;
43355714Skris}
43455714Skris
435280297SjkimGENERAL_NAME *v2i_GENERAL_NAME(const X509V3_EXT_METHOD *method,
436280297Sjkim                               X509V3_CTX *ctx, CONF_VALUE *cnf)
437280297Sjkim{
438280297Sjkim    return v2i_GENERAL_NAME_ex(NULL, method, ctx, cnf, 0);
439280297Sjkim}
44055714Skris
441238405SjkimGENERAL_NAME *a2i_GENERAL_NAME(GENERAL_NAME *out,
442280297Sjkim                               const X509V3_EXT_METHOD *method,
443280297Sjkim                               X509V3_CTX *ctx, int gen_type, char *value,
444280297Sjkim                               int is_nc)
445280297Sjkim{
446280297Sjkim    char is_string = 0;
447280297Sjkim    GENERAL_NAME *gen = NULL;
44855714Skris
449280297Sjkim    if (!value) {
450280297Sjkim        X509V3err(X509V3_F_A2I_GENERAL_NAME, X509V3_R_MISSING_VALUE);
451280297Sjkim        return NULL;
452280297Sjkim    }
45355714Skris
454280297Sjkim    if (out)
455280297Sjkim        gen = out;
456280297Sjkim    else {
457280297Sjkim        gen = GENERAL_NAME_new();
458280297Sjkim        if (gen == NULL) {
459280297Sjkim            X509V3err(X509V3_F_A2I_GENERAL_NAME, ERR_R_MALLOC_FAILURE);
460280297Sjkim            return NULL;
461280297Sjkim        }
462280297Sjkim    }
463160814Ssimon
464280297Sjkim    switch (gen_type) {
465280297Sjkim    case GEN_URI:
466280297Sjkim    case GEN_EMAIL:
467280297Sjkim    case GEN_DNS:
468280297Sjkim        is_string = 1;
469280297Sjkim        break;
470238405Sjkim
471280297Sjkim    case GEN_RID:
472280297Sjkim        {
473280297Sjkim            ASN1_OBJECT *obj;
474280297Sjkim            if (!(obj = OBJ_txt2obj(value, 0))) {
475280297Sjkim                X509V3err(X509V3_F_A2I_GENERAL_NAME, X509V3_R_BAD_OBJECT);
476280297Sjkim                ERR_add_error_data(2, "value=", value);
477280297Sjkim                goto err;
478280297Sjkim            }
479280297Sjkim            gen->d.rid = obj;
480280297Sjkim        }
481280297Sjkim        break;
482238405Sjkim
483280297Sjkim    case GEN_IPADD:
484280297Sjkim        if (is_nc)
485280297Sjkim            gen->d.ip = a2i_IPADDRESS_NC(value);
486280297Sjkim        else
487280297Sjkim            gen->d.ip = a2i_IPADDRESS(value);
488280297Sjkim        if (gen->d.ip == NULL) {
489280297Sjkim            X509V3err(X509V3_F_A2I_GENERAL_NAME, X509V3_R_BAD_IP_ADDRESS);
490280297Sjkim            ERR_add_error_data(2, "value=", value);
491280297Sjkim            goto err;
492280297Sjkim        }
493280297Sjkim        break;
494238405Sjkim
495280297Sjkim    case GEN_DIRNAME:
496280297Sjkim        if (!do_dirname(gen, value, ctx)) {
497280297Sjkim            X509V3err(X509V3_F_A2I_GENERAL_NAME, X509V3_R_DIRNAME_ERROR);
498280297Sjkim            goto err;
499280297Sjkim        }
500280297Sjkim        break;
501160814Ssimon
502280297Sjkim    case GEN_OTHERNAME:
503280297Sjkim        if (!do_othername(gen, value, ctx)) {
504280297Sjkim            X509V3err(X509V3_F_A2I_GENERAL_NAME, X509V3_R_OTHERNAME_ERROR);
505280297Sjkim            goto err;
506280297Sjkim        }
507280297Sjkim        break;
508280297Sjkim    default:
509280297Sjkim        X509V3err(X509V3_F_A2I_GENERAL_NAME, X509V3_R_UNSUPPORTED_TYPE);
510280297Sjkim        goto err;
511280297Sjkim    }
512160814Ssimon
513280297Sjkim    if (is_string) {
514280297Sjkim        if (!(gen->d.ia5 = M_ASN1_IA5STRING_new()) ||
515280297Sjkim            !ASN1_STRING_set(gen->d.ia5, (unsigned char *)value,
516280297Sjkim                             strlen(value))) {
517280297Sjkim            X509V3err(X509V3_F_A2I_GENERAL_NAME, ERR_R_MALLOC_FAILURE);
518280297Sjkim            goto err;
519280297Sjkim        }
520280297Sjkim    }
521160814Ssimon
522280297Sjkim    gen->type = gen_type;
523160814Ssimon
524280297Sjkim    return gen;
52555714Skris
526280297Sjkim err:
527280297Sjkim    if (!out)
528280297Sjkim        GENERAL_NAME_free(gen);
529280297Sjkim    return NULL;
530280297Sjkim}
531280297Sjkim
532238405SjkimGENERAL_NAME *v2i_GENERAL_NAME_ex(GENERAL_NAME *out,
533280297Sjkim                                  const X509V3_EXT_METHOD *method,
534280297Sjkim                                  X509V3_CTX *ctx, CONF_VALUE *cnf, int is_nc)
535280297Sjkim{
536280297Sjkim    int type;
537238405Sjkim
538280297Sjkim    char *name, *value;
539238405Sjkim
540280297Sjkim    name = cnf->name;
541280297Sjkim    value = cnf->value;
542238405Sjkim
543280297Sjkim    if (!value) {
544280297Sjkim        X509V3err(X509V3_F_V2I_GENERAL_NAME_EX, X509V3_R_MISSING_VALUE);
545280297Sjkim        return NULL;
546280297Sjkim    }
547238405Sjkim
548280297Sjkim    if (!name_cmp(name, "email"))
549280297Sjkim        type = GEN_EMAIL;
550280297Sjkim    else if (!name_cmp(name, "URI"))
551280297Sjkim        type = GEN_URI;
552280297Sjkim    else if (!name_cmp(name, "DNS"))
553280297Sjkim        type = GEN_DNS;
554280297Sjkim    else if (!name_cmp(name, "RID"))
555280297Sjkim        type = GEN_RID;
556280297Sjkim    else if (!name_cmp(name, "IP"))
557280297Sjkim        type = GEN_IPADD;
558280297Sjkim    else if (!name_cmp(name, "dirName"))
559280297Sjkim        type = GEN_DIRNAME;
560280297Sjkim    else if (!name_cmp(name, "otherName"))
561280297Sjkim        type = GEN_OTHERNAME;
562280297Sjkim    else {
563280297Sjkim        X509V3err(X509V3_F_V2I_GENERAL_NAME_EX, X509V3_R_UNSUPPORTED_OPTION);
564280297Sjkim        ERR_add_error_data(2, "name=", name);
565280297Sjkim        return NULL;
566280297Sjkim    }
567238405Sjkim
568280297Sjkim    return a2i_GENERAL_NAME(out, method, ctx, type, value, is_nc);
569238405Sjkim
570280297Sjkim}
571238405Sjkim
572160814Ssimonstatic int do_othername(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx)
573280297Sjkim{
574280297Sjkim    char *objtmp = NULL, *p;
575280297Sjkim    int objlen;
576280297Sjkim    if (!(p = strchr(value, ';')))
577280297Sjkim        return 0;
578280297Sjkim    if (!(gen->d.otherName = OTHERNAME_new()))
579280297Sjkim        return 0;
580280297Sjkim    /*
581280297Sjkim     * Free this up because we will overwrite it. no need to free type_id
582280297Sjkim     * because it is static
583280297Sjkim     */
584280297Sjkim    ASN1_TYPE_free(gen->d.otherName->value);
585280297Sjkim    if (!(gen->d.otherName->value = ASN1_generate_v3(p + 1, ctx)))
586280297Sjkim        return 0;
587280297Sjkim    objlen = p - value;
588280297Sjkim    objtmp = OPENSSL_malloc(objlen + 1);
589306195Sjkim    if (objtmp == NULL)
590306195Sjkim        return 0;
591280297Sjkim    strncpy(objtmp, value, objlen);
592280297Sjkim    objtmp[objlen] = 0;
593280297Sjkim    gen->d.otherName->type_id = OBJ_txt2obj(objtmp, 0);
594280297Sjkim    OPENSSL_free(objtmp);
595280297Sjkim    if (!gen->d.otherName->type_id)
596280297Sjkim        return 0;
597280297Sjkim    return 1;
598280297Sjkim}
59955714Skris
600160814Ssimonstatic int do_dirname(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx)
601280297Sjkim{
602284283Sjkim    int ret = 0;
603284283Sjkim    STACK_OF(CONF_VALUE) *sk = NULL;
604284283Sjkim    X509_NAME *nm = NULL;
605280297Sjkim    if (!(nm = X509_NAME_new()))
606284283Sjkim        goto err;
607280297Sjkim    sk = X509V3_get_section(ctx, value);
608280297Sjkim    if (!sk) {
609280297Sjkim        X509V3err(X509V3_F_DO_DIRNAME, X509V3_R_SECTION_NOT_FOUND);
610280297Sjkim        ERR_add_error_data(2, "section=", value);
611284283Sjkim        goto err;
612280297Sjkim    }
613280297Sjkim    /* FIXME: should allow other character types... */
614280297Sjkim    ret = X509V3_NAME_from_section(nm, sk, MBSTRING_ASC);
615280297Sjkim    if (!ret)
616284283Sjkim        goto err;
617284283Sjkim    gen->d.dirn = nm;
618284283Sjkim
619284283Sjkimerr:
620284283Sjkim    if (ret == 0)
621280297Sjkim        X509_NAME_free(nm);
622280297Sjkim    X509V3_section_free(ctx, sk);
623280297Sjkim    return ret;
624280297Sjkim}
625