You need to sign in or sign up before continuing.
v3_alt.c 16.1 KB
Newer Older
1
/*
R
Rich Salz 已提交
2
 * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
3
 *
R
Rich Salz 已提交
4 5 6 7
 * Licensed under the OpenSSL license (the "License").  You may not use
 * this file except in compliance with the License.  You can obtain a copy
 * in the file LICENSE in the source distribution or at
 * https://www.openssl.org/source/license.html
8 9 10
 */

#include <stdio.h>
11
#include "internal/cryptlib.h"
12 13
#include <openssl/conf.h>
#include <openssl/x509v3.h>
14
#include "ext_dat.h"
15

16 17 18 19 20 21
static GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method,
                                      X509V3_CTX *ctx,
                                      STACK_OF(CONF_VALUE) *nval);
static GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method,
                                     X509V3_CTX *ctx,
                                     STACK_OF(CONF_VALUE) *nval);
22
static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p);
D
 
Dr. Stephen Henson 已提交
23
static int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens);
24 25
static int do_othername(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx);
static int do_dirname(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx);
D
 
Dr. Stephen Henson 已提交
26

K
Kurt Roeckx 已提交
27
const X509V3_EXT_METHOD v3_alt[3] = {
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
    {NID_subject_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES),
     0, 0, 0, 0,
     0, 0,
     (X509V3_EXT_I2V) i2v_GENERAL_NAMES,
     (X509V3_EXT_V2I)v2i_subject_alt,
     NULL, NULL, NULL},

    {NID_issuer_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES),
     0, 0, 0, 0,
     0, 0,
     (X509V3_EXT_I2V) i2v_GENERAL_NAMES,
     (X509V3_EXT_V2I)v2i_issuer_alt,
     NULL, NULL, NULL},

    {NID_certificate_issuer, 0, ASN1_ITEM_ref(GENERAL_NAMES),
     0, 0, 0, 0,
     0, 0,
     (X509V3_EXT_I2V) i2v_GENERAL_NAMES,
     NULL, NULL, NULL, NULL},
47 48
};

49
STACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES(X509V3_EXT_METHOD *method,
50 51
                                        GENERAL_NAMES *gens,
                                        STACK_OF(CONF_VALUE) *ret)
52
{
53 54 55 56 57 58 59 60 61
    int i;
    GENERAL_NAME *gen;
    for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
        gen = sk_GENERAL_NAME_value(gens, i);
        ret = i2v_GENERAL_NAME(method, gen, ret);
    }
    if (!ret)
        return sk_CONF_VALUE_new_null();
    return ret;
62 63
}

64
STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method,
65 66
                                       GENERAL_NAME *gen,
                                       STACK_OF(CONF_VALUE) *ret)
67
{
68 69 70 71 72
    unsigned char *p;
    char oline[256], htmp[5];
    int i;
    switch (gen->type) {
    case GEN_OTHERNAME:
73 74
        if (!X509V3_add_value("othername", "<unsupported>", &ret))
            return NULL;
75 76 77
        break;

    case GEN_X400:
78 79
        if (!X509V3_add_value("X400Name", "<unsupported>", &ret))
            return NULL;
80 81 82
        break;

    case GEN_EDIPARTY:
83 84
        if (!X509V3_add_value("EdiPartyName", "<unsupported>", &ret))
            return NULL;
85 86 87
        break;

    case GEN_EMAIL:
88 89
        if (!X509V3_add_value_uchar("email", gen->d.ia5->data, &ret))
            return NULL;
90 91 92
        break;

    case GEN_DNS:
93 94
        if (!X509V3_add_value_uchar("DNS", gen->d.ia5->data, &ret))
            return NULL;
95 96 97
        break;

    case GEN_URI:
98 99
        if (!X509V3_add_value_uchar("URI", gen->d.ia5->data, &ret))
            return NULL;
100 101 102
        break;

    case GEN_DIRNAME:
103 104 105
        if (X509_NAME_oneline(gen->d.dirn, oline, 256) == NULL
                || !X509V3_add_value("DirName", oline, &ret))
            return NULL;
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
        break;

    case GEN_IPADD:
        p = gen->d.ip->data;
        if (gen->d.ip->length == 4)
            BIO_snprintf(oline, sizeof oline,
                         "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
        else if (gen->d.ip->length == 16) {
            oline[0] = 0;
            for (i = 0; i < 8; i++) {
                BIO_snprintf(htmp, sizeof htmp, "%X", p[0] << 8 | p[1]);
                p += 2;
                strcat(oline, htmp);
                if (i != 7)
                    strcat(oline, ":");
            }
        } else {
123 124
            if (!X509V3_add_value("IP Address", "<invalid>", &ret))
                return NULL;
125 126
            break;
        }
127 128
        if (!X509V3_add_value("IP Address", oline, &ret))
            return NULL;
129 130 131 132
        break;

    case GEN_RID:
        i2t_ASN1_OBJECT(oline, 256, gen->d.rid);
133 134
        if (!X509V3_add_value("Registered ID", oline, &ret))
            return NULL;
135 136 137
        break;
    }
    return ret;
138 139 140 141
}

int GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen)
{
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
    unsigned char *p;
    int i;
    switch (gen->type) {
    case GEN_OTHERNAME:
        BIO_printf(out, "othername:<unsupported>");
        break;

    case GEN_X400:
        BIO_printf(out, "X400Name:<unsupported>");
        break;

    case GEN_EDIPARTY:
        /* Maybe fix this: it is supported now */
        BIO_printf(out, "EdiPartyName:<unsupported>");
        break;

    case GEN_EMAIL:
        BIO_printf(out, "email:%s", gen->d.ia5->data);
        break;

    case GEN_DNS:
        BIO_printf(out, "DNS:%s", gen->d.ia5->data);
        break;

    case GEN_URI:
        BIO_printf(out, "URI:%s", gen->d.ia5->data);
        break;

    case GEN_DIRNAME:
171
        BIO_printf(out, "DirName:");
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
        X509_NAME_print_ex(out, gen->d.dirn, 0, XN_FLAG_ONELINE);
        break;

    case GEN_IPADD:
        p = gen->d.ip->data;
        if (gen->d.ip->length == 4)
            BIO_printf(out, "IP Address:%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
        else if (gen->d.ip->length == 16) {
            BIO_printf(out, "IP Address");
            for (i = 0; i < 8; i++) {
                BIO_printf(out, ":%X", p[0] << 8 | p[1]);
                p += 2;
            }
            BIO_puts(out, "\n");
        } else {
            BIO_printf(out, "IP Address:<invalid>");
            break;
        }
        break;

    case GEN_RID:
193
        BIO_printf(out, "Registered ID:");
194 195 196 197
        i2a_ASN1_OBJECT(out, gen->d.rid);
        break;
    }
    return 1;
198 199
}

D
 
Dr. Stephen Henson 已提交
200
static GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method,
201 202
                                     X509V3_CTX *ctx,
                                     STACK_OF(CONF_VALUE) *nval)
203
{
204 205 206
    GENERAL_NAMES *gens = NULL;
    CONF_VALUE *cnf;
    int i;
207 208

    if ((gens = sk_GENERAL_NAME_new_null()) == NULL) {
209 210 211 212 213
        X509V3err(X509V3_F_V2I_ISSUER_ALT, ERR_R_MALLOC_FAILURE);
        return NULL;
    }
    for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
        cnf = sk_CONF_VALUE_value(nval, i);
R
Rich Salz 已提交
214 215
        if (!name_cmp(cnf->name, "issuer")
            && cnf->value && strcmp(cnf->value, "copy") == 0) {
216 217 218 219
            if (!copy_issuer(ctx, gens))
                goto err;
        } else {
            GENERAL_NAME *gen;
220
            if ((gen = v2i_GENERAL_NAME(method, ctx, cnf)) == NULL)
221 222 223 224 225 226 227 228
                goto err;
            sk_GENERAL_NAME_push(gens, gen);
        }
    }
    return gens;
 err:
    sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
    return NULL;
229 230 231 232
}

/* Append subject altname of issuer to issuer alt name of subject */

D
 
Dr. Stephen Henson 已提交
233
static int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens)
234
{
235 236 237 238
    GENERAL_NAMES *ialt;
    GENERAL_NAME *gen;
    X509_EXTENSION *ext;
    int i;
239

240 241 242 243 244 245 246 247 248
    if (ctx && (ctx->flags == CTX_TEST))
        return 1;
    if (!ctx || !ctx->issuer_cert) {
        X509V3err(X509V3_F_COPY_ISSUER, X509V3_R_NO_ISSUER_DETAILS);
        goto err;
    }
    i = X509_get_ext_by_NID(ctx->issuer_cert, NID_subject_alt_name, -1);
    if (i < 0)
        return 1;
249 250
    if ((ext = X509_get_ext(ctx->issuer_cert, i)) == NULL
        || (ialt = X509V3_EXT_d2i(ext)) == NULL) {
251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268
        X509V3err(X509V3_F_COPY_ISSUER, X509V3_R_ISSUER_DECODE_ERROR);
        goto err;
    }

    for (i = 0; i < sk_GENERAL_NAME_num(ialt); i++) {
        gen = sk_GENERAL_NAME_value(ialt, i);
        if (!sk_GENERAL_NAME_push(gens, gen)) {
            X509V3err(X509V3_F_COPY_ISSUER, ERR_R_MALLOC_FAILURE);
            goto err;
        }
    }
    sk_GENERAL_NAME_free(ialt);

    return 1;

 err:
    return 0;

269 270
}

D
 
Dr. Stephen Henson 已提交
271
static GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method,
272 273
                                      X509V3_CTX *ctx,
                                      STACK_OF(CONF_VALUE) *nval)
274
{
275 276 277
    GENERAL_NAMES *gens = NULL;
    CONF_VALUE *cnf;
    int i;
278 279

    if ((gens = sk_GENERAL_NAME_new_null()) == NULL) {
280 281 282 283 284
        X509V3err(X509V3_F_V2I_SUBJECT_ALT, ERR_R_MALLOC_FAILURE);
        return NULL;
    }
    for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
        cnf = sk_CONF_VALUE_value(nval, i);
R
Rich Salz 已提交
285 286
        if (!name_cmp(cnf->name, "email")
            && cnf->value && strcmp(cnf->value, "copy") == 0) {
287 288
            if (!copy_email(ctx, gens, 0))
                goto err;
R
Rich Salz 已提交
289 290
        } else if (!name_cmp(cnf->name, "email")
                   && cnf->value && strcmp(cnf->value, "move") == 0) {
291 292 293 294
            if (!copy_email(ctx, gens, 1))
                goto err;
        } else {
            GENERAL_NAME *gen;
295
            if ((gen = v2i_GENERAL_NAME(method, ctx, cnf)) == NULL)
296 297 298 299 300 301 302 303
                goto err;
            sk_GENERAL_NAME_push(gens, gen);
        }
    }
    return gens;
 err:
    sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
    return NULL;
304 305
}

306 307
/*
 * Copy any email addresses in a certificate or request to GENERAL_NAMES
308 309
 */

310
static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p)
311
{
312 313 314 315
    X509_NAME *nm;
    ASN1_IA5STRING *email = NULL;
    X509_NAME_ENTRY *ne;
    GENERAL_NAME *gen = NULL;
F
FdaSilvaYY 已提交
316 317
    int i = -1;

318 319
    if (ctx != NULL && ctx->flags == CTX_TEST)
        return 1;
F
FdaSilvaYY 已提交
320 321
    if (ctx == NULL 
        || (ctx->subject_cert == NULL && ctx->subject_req == NULL)) {
322 323 324 325 326 327 328 329 330 331 332 333 334
        X509V3err(X509V3_F_COPY_EMAIL, X509V3_R_NO_SUBJECT_DETAILS);
        goto err;
    }
    /* Find the subject name */
    if (ctx->subject_cert)
        nm = X509_get_subject_name(ctx->subject_cert);
    else
        nm = X509_REQ_get_subject_name(ctx->subject_req);

    /* Now add any email address(es) to STACK */
    while ((i = X509_NAME_get_index_by_NID(nm,
                                           NID_pkcs9_emailAddress, i)) >= 0) {
        ne = X509_NAME_get_entry(nm, i);
D
Dr. Stephen Henson 已提交
335
        email = ASN1_STRING_dup(X509_NAME_ENTRY_get_data(ne));
336 337 338 339 340
        if (move_p) {
            X509_NAME_delete_entry(nm, i);
            X509_NAME_ENTRY_free(ne);
            i--;
        }
341
        if (email == NULL || (gen = GENERAL_NAME_new()) == NULL) {
342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358
            X509V3err(X509V3_F_COPY_EMAIL, ERR_R_MALLOC_FAILURE);
            goto err;
        }
        gen->d.ia5 = email;
        email = NULL;
        gen->type = GEN_EMAIL;
        if (!sk_GENERAL_NAME_push(gens, gen)) {
            X509V3err(X509V3_F_COPY_EMAIL, ERR_R_MALLOC_FAILURE);
            goto err;
        }
        gen = NULL;
    }

    return 1;

 err:
    GENERAL_NAME_free(gen);
D
Dr. Stephen Henson 已提交
359
    ASN1_IA5STRING_free(email);
360 361
    return 0;

362 363
}

364
GENERAL_NAMES *v2i_GENERAL_NAMES(const X509V3_EXT_METHOD *method,
365
                                 X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
366
{
367 368 369 370
    GENERAL_NAME *gen;
    GENERAL_NAMES *gens = NULL;
    CONF_VALUE *cnf;
    int i;
371 372

    if ((gens = sk_GENERAL_NAME_new_null()) == NULL) {
373 374 375 376 377
        X509V3err(X509V3_F_V2I_GENERAL_NAMES, ERR_R_MALLOC_FAILURE);
        return NULL;
    }
    for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
        cnf = sk_CONF_VALUE_value(nval, i);
378
        if ((gen = v2i_GENERAL_NAME(method, ctx, cnf)) == NULL)
379 380 381 382 383 384 385
            goto err;
        sk_GENERAL_NAME_push(gens, gen);
    }
    return gens;
 err:
    sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
    return NULL;
386 387
}

388 389 390 391 392
GENERAL_NAME *v2i_GENERAL_NAME(const X509V3_EXT_METHOD *method,
                               X509V3_CTX *ctx, CONF_VALUE *cnf)
{
    return v2i_GENERAL_NAME_ex(NULL, method, ctx, cnf, 0);
}
393

394
GENERAL_NAME *a2i_GENERAL_NAME(GENERAL_NAME *out,
395
                               const X509V3_EXT_METHOD *method,
396
                               X509V3_CTX *ctx, int gen_type, const char *value,
397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426
                               int is_nc)
{
    char is_string = 0;
    GENERAL_NAME *gen = NULL;

    if (!value) {
        X509V3err(X509V3_F_A2I_GENERAL_NAME, X509V3_R_MISSING_VALUE);
        return NULL;
    }

    if (out)
        gen = out;
    else {
        gen = GENERAL_NAME_new();
        if (gen == NULL) {
            X509V3err(X509V3_F_A2I_GENERAL_NAME, ERR_R_MALLOC_FAILURE);
            return NULL;
        }
    }

    switch (gen_type) {
    case GEN_URI:
    case GEN_EMAIL:
    case GEN_DNS:
        is_string = 1;
        break;

    case GEN_RID:
        {
            ASN1_OBJECT *obj;
427
            if ((obj = OBJ_txt2obj(value, 0)) == NULL) {
428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466
                X509V3err(X509V3_F_A2I_GENERAL_NAME, X509V3_R_BAD_OBJECT);
                ERR_add_error_data(2, "value=", value);
                goto err;
            }
            gen->d.rid = obj;
        }
        break;

    case GEN_IPADD:
        if (is_nc)
            gen->d.ip = a2i_IPADDRESS_NC(value);
        else
            gen->d.ip = a2i_IPADDRESS(value);
        if (gen->d.ip == NULL) {
            X509V3err(X509V3_F_A2I_GENERAL_NAME, X509V3_R_BAD_IP_ADDRESS);
            ERR_add_error_data(2, "value=", value);
            goto err;
        }
        break;

    case GEN_DIRNAME:
        if (!do_dirname(gen, value, ctx)) {
            X509V3err(X509V3_F_A2I_GENERAL_NAME, X509V3_R_DIRNAME_ERROR);
            goto err;
        }
        break;

    case GEN_OTHERNAME:
        if (!do_othername(gen, value, ctx)) {
            X509V3err(X509V3_F_A2I_GENERAL_NAME, X509V3_R_OTHERNAME_ERROR);
            goto err;
        }
        break;
    default:
        X509V3err(X509V3_F_A2I_GENERAL_NAME, X509V3_R_UNSUPPORTED_TYPE);
        goto err;
    }

    if (is_string) {
467
        if ((gen->d.ia5 = ASN1_IA5STRING_new()) == NULL ||
468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483
            !ASN1_STRING_set(gen->d.ia5, (unsigned char *)value,
                             strlen(value))) {
            X509V3err(X509V3_F_A2I_GENERAL_NAME, ERR_R_MALLOC_FAILURE);
            goto err;
        }
    }

    gen->type = gen_type;

    return gen;

 err:
    if (!out)
        GENERAL_NAME_free(gen);
    return NULL;
}
D
 
Dr. Stephen Henson 已提交
484

485
GENERAL_NAME *v2i_GENERAL_NAME_ex(GENERAL_NAME *out,
486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523
                                  const X509V3_EXT_METHOD *method,
                                  X509V3_CTX *ctx, CONF_VALUE *cnf, int is_nc)
{
    int type;

    char *name, *value;

    name = cnf->name;
    value = cnf->value;

    if (!value) {
        X509V3err(X509V3_F_V2I_GENERAL_NAME_EX, X509V3_R_MISSING_VALUE);
        return NULL;
    }

    if (!name_cmp(name, "email"))
        type = GEN_EMAIL;
    else if (!name_cmp(name, "URI"))
        type = GEN_URI;
    else if (!name_cmp(name, "DNS"))
        type = GEN_DNS;
    else if (!name_cmp(name, "RID"))
        type = GEN_RID;
    else if (!name_cmp(name, "IP"))
        type = GEN_IPADD;
    else if (!name_cmp(name, "dirName"))
        type = GEN_DIRNAME;
    else if (!name_cmp(name, "otherName"))
        type = GEN_OTHERNAME;
    else {
        X509V3err(X509V3_F_V2I_GENERAL_NAME_EX, X509V3_R_UNSUPPORTED_OPTION);
        ERR_add_error_data(2, "name=", name);
        return NULL;
    }

    return a2i_GENERAL_NAME(out, method, ctx, type, value, is_nc);

}
524

525
static int do_othername(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx)
526 527 528
{
    char *objtmp = NULL, *p;
    int objlen;
529 530

    if ((p = strchr(value, ';')) == NULL)
531
        return 0;
532
    if ((gen->d.otherName = OTHERNAME_new()) == NULL)
533 534 535 536 537 538
        return 0;
    /*
     * Free this up because we will overwrite it. no need to free type_id
     * because it is static
     */
    ASN1_TYPE_free(gen->d.otherName->value);
539
    if ((gen->d.otherName->value = ASN1_generate_v3(p + 1, ctx)) == NULL)
540 541
        return 0;
    objlen = p - value;
D
Dmitry-Me 已提交
542
    objtmp = OPENSSL_strndup(value, objlen);
543 544 545 546 547 548 549 550
    if (objtmp == NULL)
        return 0;
    gen->d.otherName->type_id = OBJ_txt2obj(objtmp, 0);
    OPENSSL_free(objtmp);
    if (!gen->d.otherName->type_id)
        return 0;
    return 1;
}
551

552
static int do_dirname(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx)
553
{
554 555
    int ret = 0;
    STACK_OF(CONF_VALUE) *sk = NULL;
556 557 558
    X509_NAME *nm;

    if ((nm = X509_NAME_new()) == NULL)
559
        goto err;
560 561 562 563
    sk = X509V3_get_section(ctx, value);
    if (!sk) {
        X509V3err(X509V3_F_DO_DIRNAME, X509V3_R_SECTION_NOT_FOUND);
        ERR_add_error_data(2, "section=", value);
564
        goto err;
565 566 567 568
    }
    /* FIXME: should allow other character types... */
    ret = X509V3_NAME_from_section(nm, sk, MBSTRING_ASC);
    if (!ret)
569
        goto err;
570 571
    gen->d.dirn = nm;

572 573 574 575
err:
    if (ret == 0)
        X509_NAME_free(nm);
    X509V3_section_free(ctx, sk);
576 577
    return ret;
}