1 /* v3_alt.c */ 2 /* 3 * Written by Dr Stephen N Henson (steve (at) openssl.org) for the OpenSSL 4 * project. 5 */ 6 /* ==================================================================== 7 * Copyright (c) 1999-2003 The OpenSSL Project. All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in 18 * the documentation and/or other materials provided with the 19 * distribution. 20 * 21 * 3. All advertising materials mentioning features or use of this 22 * software must display the following acknowledgment: 23 * "This product includes software developed by the OpenSSL Project 24 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 25 * 26 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 27 * endorse or promote products derived from this software without 28 * prior written permission. For written permission, please contact 29 * licensing (at) OpenSSL.org. 30 * 31 * 5. Products derived from this software may not be called "OpenSSL" 32 * nor may "OpenSSL" appear in their names without prior written 33 * permission of the OpenSSL Project. 34 * 35 * 6. Redistributions of any form whatsoever must retain the following 36 * acknowledgment: 37 * "This product includes software developed by the OpenSSL Project 38 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 39 * 40 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 41 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 43 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 44 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 46 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 47 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 49 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 50 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 51 * OF THE POSSIBILITY OF SUCH DAMAGE. 52 * ==================================================================== 53 * 54 * This product includes cryptographic software written by Eric Young 55 * (eay (at) cryptsoft.com). This product includes software written by Tim 56 * Hudson (tjh (at) cryptsoft.com). */ 57 58 #include <stdio.h> 59 #include <string.h> 60 61 #include <openssl/conf.h> 62 #include <openssl/err.h> 63 #include <openssl/mem.h> 64 #include <openssl/obj.h> 65 #include <openssl/x509v3.h> 66 67 #include "internal.h" 68 69 70 static GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method, 71 X509V3_CTX *ctx, 72 STACK_OF(CONF_VALUE) *nval); 73 static GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method, 74 X509V3_CTX *ctx, 75 STACK_OF(CONF_VALUE) *nval); 76 static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p); 77 static int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens); 78 static int do_othername(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx); 79 static int do_dirname(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx); 80 81 const X509V3_EXT_METHOD v3_alt[] = { 82 {NID_subject_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES), 83 0, 0, 0, 0, 84 0, 0, 85 (X509V3_EXT_I2V) i2v_GENERAL_NAMES, 86 (X509V3_EXT_V2I)v2i_subject_alt, 87 NULL, NULL, NULL}, 88 89 {NID_issuer_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES), 90 0, 0, 0, 0, 91 0, 0, 92 (X509V3_EXT_I2V) i2v_GENERAL_NAMES, 93 (X509V3_EXT_V2I)v2i_issuer_alt, 94 NULL, NULL, NULL}, 95 96 {NID_certificate_issuer, 0, ASN1_ITEM_ref(GENERAL_NAMES), 97 0, 0, 0, 0, 98 0, 0, 99 (X509V3_EXT_I2V) i2v_GENERAL_NAMES, 100 NULL, NULL, NULL, NULL}, 101 }; 102 103 STACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES(X509V3_EXT_METHOD *method, 104 GENERAL_NAMES *gens, 105 STACK_OF(CONF_VALUE) *ret) 106 { 107 size_t i; 108 GENERAL_NAME *gen; 109 for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) { 110 gen = sk_GENERAL_NAME_value(gens, i); 111 ret = i2v_GENERAL_NAME(method, gen, ret); 112 } 113 if (!ret) 114 return sk_CONF_VALUE_new_null(); 115 return ret; 116 } 117 118 STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method, 119 GENERAL_NAME *gen, 120 STACK_OF(CONF_VALUE) *ret) 121 { 122 unsigned char *p; 123 char oline[256], htmp[5]; 124 int i; 125 switch (gen->type) { 126 case GEN_OTHERNAME: 127 if (!X509V3_add_value("othername", "<unsupported>", &ret)) 128 return NULL; 129 break; 130 131 case GEN_X400: 132 if (!X509V3_add_value("X400Name", "<unsupported>", &ret)) 133 return NULL; 134 break; 135 136 case GEN_EDIPARTY: 137 if (!X509V3_add_value("EdiPartyName", "<unsupported>", &ret)) 138 return NULL; 139 break; 140 141 case GEN_EMAIL: 142 if (!X509V3_add_value_uchar("email", gen->d.ia5->data, &ret)) 143 return NULL; 144 break; 145 146 case GEN_DNS: 147 if (!X509V3_add_value_uchar("DNS", gen->d.ia5->data, &ret)) 148 return NULL; 149 break; 150 151 case GEN_URI: 152 if (!X509V3_add_value_uchar("URI", gen->d.ia5->data, &ret)) 153 return NULL; 154 break; 155 156 case GEN_DIRNAME: 157 if (X509_NAME_oneline(gen->d.dirn, oline, 256) == NULL 158 || !X509V3_add_value("DirName", oline, &ret)) 159 return NULL; 160 break; 161 162 case GEN_IPADD: 163 p = gen->d.ip->data; 164 if (gen->d.ip->length == 4) 165 BIO_snprintf(oline, sizeof oline, 166 "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); 167 else if (gen->d.ip->length == 16) { 168 oline[0] = 0; 169 for (i = 0; i < 8; i++) { 170 BIO_snprintf(htmp, sizeof htmp, "%X", p[0] << 8 | p[1]); 171 p += 2; 172 BUF_strlcat(oline, htmp, sizeof(oline)); 173 if (i != 7) 174 BUF_strlcat(oline, ":", sizeof(oline)); 175 } 176 } else { 177 if (!X509V3_add_value("IP Address", "<invalid>", &ret)) 178 return NULL; 179 break; 180 } 181 if (!X509V3_add_value("IP Address", oline, &ret)) 182 return NULL; 183 break; 184 185 case GEN_RID: 186 i2t_ASN1_OBJECT(oline, 256, gen->d.rid); 187 if (!X509V3_add_value("Registered ID", oline, &ret)) 188 return NULL; 189 break; 190 } 191 return ret; 192 } 193 194 int GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen) 195 { 196 unsigned char *p; 197 int i; 198 switch (gen->type) { 199 case GEN_OTHERNAME: 200 BIO_printf(out, "othername:<unsupported>"); 201 break; 202 203 case GEN_X400: 204 BIO_printf(out, "X400Name:<unsupported>"); 205 break; 206 207 case GEN_EDIPARTY: 208 /* Maybe fix this: it is supported now */ 209 BIO_printf(out, "EdiPartyName:<unsupported>"); 210 break; 211 212 case GEN_EMAIL: 213 BIO_printf(out, "email:%s", gen->d.ia5->data); 214 break; 215 216 case GEN_DNS: 217 BIO_printf(out, "DNS:%s", gen->d.ia5->data); 218 break; 219 220 case GEN_URI: 221 BIO_printf(out, "URI:%s", gen->d.ia5->data); 222 break; 223 224 case GEN_DIRNAME: 225 BIO_printf(out, "DirName: "); 226 X509_NAME_print_ex(out, gen->d.dirn, 0, XN_FLAG_ONELINE); 227 break; 228 229 case GEN_IPADD: 230 p = gen->d.ip->data; 231 if (gen->d.ip->length == 4) 232 BIO_printf(out, "IP Address:%d.%d.%d.%d", p[0], p[1], p[2], p[3]); 233 else if (gen->d.ip->length == 16) { 234 BIO_printf(out, "IP Address"); 235 for (i = 0; i < 8; i++) { 236 BIO_printf(out, ":%X", p[0] << 8 | p[1]); 237 p += 2; 238 } 239 BIO_puts(out, "\n"); 240 } else { 241 BIO_printf(out, "IP Address:<invalid>"); 242 break; 243 } 244 break; 245 246 case GEN_RID: 247 BIO_printf(out, "Registered ID"); 248 i2a_ASN1_OBJECT(out, gen->d.rid); 249 break; 250 } 251 return 1; 252 } 253 254 static GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method, 255 X509V3_CTX *ctx, 256 STACK_OF(CONF_VALUE) *nval) 257 { 258 GENERAL_NAMES *gens = NULL; 259 CONF_VALUE *cnf; 260 size_t i; 261 if (!(gens = sk_GENERAL_NAME_new_null())) { 262 OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); 263 return NULL; 264 } 265 for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { 266 cnf = sk_CONF_VALUE_value(nval, i); 267 if (!x509v3_name_cmp(cnf->name, "issuer") && cnf->value && 268 !strcmp(cnf->value, "copy")) { 269 if (!copy_issuer(ctx, gens)) 270 goto err; 271 } else { 272 GENERAL_NAME *gen; 273 if (!(gen = v2i_GENERAL_NAME(method, ctx, cnf))) 274 goto err; 275 sk_GENERAL_NAME_push(gens, gen); 276 } 277 } 278 return gens; 279 err: 280 sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); 281 return NULL; 282 } 283 284 /* Append subject altname of issuer to issuer alt name of subject */ 285 286 static int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens) 287 { 288 GENERAL_NAMES *ialt; 289 GENERAL_NAME *gen; 290 X509_EXTENSION *ext; 291 int i; 292 size_t j; 293 if (ctx && (ctx->flags == CTX_TEST)) 294 return 1; 295 if (!ctx || !ctx->issuer_cert) { 296 OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_ISSUER_DETAILS); 297 goto err; 298 } 299 i = X509_get_ext_by_NID(ctx->issuer_cert, NID_subject_alt_name, -1); 300 if (i < 0) 301 return 1; 302 if (!(ext = X509_get_ext(ctx->issuer_cert, i)) || 303 !(ialt = X509V3_EXT_d2i(ext))) { 304 OPENSSL_PUT_ERROR(X509V3, X509V3_R_ISSUER_DECODE_ERROR); 305 goto err; 306 } 307 308 for (j = 0; j < sk_GENERAL_NAME_num(ialt); j++) { 309 gen = sk_GENERAL_NAME_value(ialt, j); 310 if (!sk_GENERAL_NAME_push(gens, gen)) { 311 OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); 312 goto err; 313 } 314 } 315 sk_GENERAL_NAME_free(ialt); 316 317 return 1; 318 319 err: 320 return 0; 321 322 } 323 324 static GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method, 325 X509V3_CTX *ctx, 326 STACK_OF(CONF_VALUE) *nval) 327 { 328 GENERAL_NAMES *gens = NULL; 329 CONF_VALUE *cnf; 330 size_t i; 331 if (!(gens = sk_GENERAL_NAME_new_null())) { 332 OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); 333 return NULL; 334 } 335 for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { 336 cnf = sk_CONF_VALUE_value(nval, i); 337 if (!x509v3_name_cmp(cnf->name, "email") && cnf->value && 338 !strcmp(cnf->value, "copy")) { 339 if (!copy_email(ctx, gens, 0)) 340 goto err; 341 } else if (!x509v3_name_cmp(cnf->name, "email") && cnf->value && 342 !strcmp(cnf->value, "move")) { 343 if (!copy_email(ctx, gens, 1)) 344 goto err; 345 } else { 346 GENERAL_NAME *gen; 347 if (!(gen = v2i_GENERAL_NAME(method, ctx, cnf))) 348 goto err; 349 sk_GENERAL_NAME_push(gens, gen); 350 } 351 } 352 return gens; 353 err: 354 sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); 355 return NULL; 356 } 357 358 /* 359 * Copy any email addresses in a certificate or request to GENERAL_NAMES 360 */ 361 362 static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p) 363 { 364 X509_NAME *nm; 365 ASN1_IA5STRING *email = NULL; 366 X509_NAME_ENTRY *ne; 367 GENERAL_NAME *gen = NULL; 368 int i; 369 if (ctx != NULL && ctx->flags == CTX_TEST) 370 return 1; 371 if (!ctx || (!ctx->subject_cert && !ctx->subject_req)) { 372 OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_SUBJECT_DETAILS); 373 goto err; 374 } 375 /* Find the subject name */ 376 if (ctx->subject_cert) 377 nm = X509_get_subject_name(ctx->subject_cert); 378 else 379 nm = X509_REQ_get_subject_name(ctx->subject_req); 380 381 /* Now add any email address(es) to STACK */ 382 i = -1; 383 while ((i = X509_NAME_get_index_by_NID(nm, 384 NID_pkcs9_emailAddress, i)) >= 0) { 385 ne = X509_NAME_get_entry(nm, i); 386 email = M_ASN1_IA5STRING_dup(X509_NAME_ENTRY_get_data(ne)); 387 if (move_p) { 388 X509_NAME_delete_entry(nm, i); 389 X509_NAME_ENTRY_free(ne); 390 i--; 391 } 392 if (!email || !(gen = GENERAL_NAME_new())) { 393 OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); 394 goto err; 395 } 396 gen->d.ia5 = email; 397 email = NULL; 398 gen->type = GEN_EMAIL; 399 if (!sk_GENERAL_NAME_push(gens, gen)) { 400 OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); 401 goto err; 402 } 403 gen = NULL; 404 } 405 406 return 1; 407 408 err: 409 GENERAL_NAME_free(gen); 410 M_ASN1_IA5STRING_free(email); 411 return 0; 412 413 } 414 415 GENERAL_NAMES *v2i_GENERAL_NAMES(const X509V3_EXT_METHOD *method, 416 X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval) 417 { 418 GENERAL_NAME *gen; 419 GENERAL_NAMES *gens = NULL; 420 CONF_VALUE *cnf; 421 size_t i; 422 if (!(gens = sk_GENERAL_NAME_new_null())) { 423 OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); 424 return NULL; 425 } 426 for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { 427 cnf = sk_CONF_VALUE_value(nval, i); 428 if (!(gen = v2i_GENERAL_NAME(method, ctx, cnf))) 429 goto err; 430 sk_GENERAL_NAME_push(gens, gen); 431 } 432 return gens; 433 err: 434 sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); 435 return NULL; 436 } 437 438 GENERAL_NAME *v2i_GENERAL_NAME(const X509V3_EXT_METHOD *method, 439 X509V3_CTX *ctx, CONF_VALUE *cnf) 440 { 441 return v2i_GENERAL_NAME_ex(NULL, method, ctx, cnf, 0); 442 } 443 444 GENERAL_NAME *a2i_GENERAL_NAME(GENERAL_NAME *out, 445 const X509V3_EXT_METHOD *method, 446 X509V3_CTX *ctx, int gen_type, char *value, 447 int is_nc) 448 { 449 char is_string = 0; 450 GENERAL_NAME *gen = NULL; 451 452 if (!value) { 453 OPENSSL_PUT_ERROR(X509V3, X509V3_R_MISSING_VALUE); 454 return NULL; 455 } 456 457 if (out) 458 gen = out; 459 else { 460 gen = GENERAL_NAME_new(); 461 if (gen == NULL) { 462 OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); 463 return NULL; 464 } 465 } 466 467 switch (gen_type) { 468 case GEN_URI: 469 case GEN_EMAIL: 470 case GEN_DNS: 471 is_string = 1; 472 break; 473 474 case GEN_RID: 475 { 476 ASN1_OBJECT *obj; 477 if (!(obj = OBJ_txt2obj(value, 0))) { 478 OPENSSL_PUT_ERROR(X509V3, X509V3_R_BAD_OBJECT); 479 ERR_add_error_data(2, "value=", value); 480 goto err; 481 } 482 gen->d.rid = obj; 483 } 484 break; 485 486 case GEN_IPADD: 487 if (is_nc) 488 gen->d.ip = a2i_IPADDRESS_NC(value); 489 else 490 gen->d.ip = a2i_IPADDRESS(value); 491 if (gen->d.ip == NULL) { 492 OPENSSL_PUT_ERROR(X509V3, X509V3_R_BAD_IP_ADDRESS); 493 ERR_add_error_data(2, "value=", value); 494 goto err; 495 } 496 break; 497 498 case GEN_DIRNAME: 499 if (!do_dirname(gen, value, ctx)) { 500 OPENSSL_PUT_ERROR(X509V3, X509V3_R_DIRNAME_ERROR); 501 goto err; 502 } 503 break; 504 505 case GEN_OTHERNAME: 506 if (!do_othername(gen, value, ctx)) { 507 OPENSSL_PUT_ERROR(X509V3, X509V3_R_OTHERNAME_ERROR); 508 goto err; 509 } 510 break; 511 default: 512 OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNSUPPORTED_TYPE); 513 goto err; 514 } 515 516 if (is_string) { 517 if (!(gen->d.ia5 = M_ASN1_IA5STRING_new()) || 518 !ASN1_STRING_set(gen->d.ia5, (unsigned char *)value, 519 strlen(value))) { 520 OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); 521 goto err; 522 } 523 } 524 525 gen->type = gen_type; 526 527 return gen; 528 529 err: 530 if (!out) 531 GENERAL_NAME_free(gen); 532 return NULL; 533 } 534 535 GENERAL_NAME *v2i_GENERAL_NAME_ex(GENERAL_NAME *out, 536 const X509V3_EXT_METHOD *method, 537 X509V3_CTX *ctx, CONF_VALUE *cnf, int is_nc) 538 { 539 int type; 540 541 char *name, *value; 542 543 name = cnf->name; 544 value = cnf->value; 545 546 if (!value) { 547 OPENSSL_PUT_ERROR(X509V3, X509V3_R_MISSING_VALUE); 548 return NULL; 549 } 550 551 if (!x509v3_name_cmp(name, "email")) 552 type = GEN_EMAIL; 553 else if (!x509v3_name_cmp(name, "URI")) 554 type = GEN_URI; 555 else if (!x509v3_name_cmp(name, "DNS")) 556 type = GEN_DNS; 557 else if (!x509v3_name_cmp(name, "RID")) 558 type = GEN_RID; 559 else if (!x509v3_name_cmp(name, "IP")) 560 type = GEN_IPADD; 561 else if (!x509v3_name_cmp(name, "dirName")) 562 type = GEN_DIRNAME; 563 else if (!x509v3_name_cmp(name, "otherName")) 564 type = GEN_OTHERNAME; 565 else { 566 OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNSUPPORTED_OPTION); 567 ERR_add_error_data(2, "name=", name); 568 return NULL; 569 } 570 571 return a2i_GENERAL_NAME(out, method, ctx, type, value, is_nc); 572 573 } 574 575 static int do_othername(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx) 576 { 577 char *objtmp = NULL, *p; 578 int objlen; 579 if (!(p = strchr(value, ';'))) 580 return 0; 581 if (!(gen->d.otherName = OTHERNAME_new())) 582 return 0; 583 /* 584 * Free this up because we will overwrite it. no need to free type_id 585 * because it is static 586 */ 587 ASN1_TYPE_free(gen->d.otherName->value); 588 if (!(gen->d.otherName->value = ASN1_generate_v3(p + 1, ctx))) 589 return 0; 590 objlen = p - value; 591 objtmp = OPENSSL_malloc(objlen + 1); 592 if (objtmp == NULL) 593 return 0; 594 BUF_strlcpy(objtmp, value, objlen + 1); 595 gen->d.otherName->type_id = OBJ_txt2obj(objtmp, 0); 596 OPENSSL_free(objtmp); 597 if (!gen->d.otherName->type_id) 598 return 0; 599 return 1; 600 } 601 602 static int do_dirname(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx) 603 { 604 int ret = 0; 605 STACK_OF(CONF_VALUE) *sk = NULL; 606 X509_NAME *nm = X509_NAME_new(); 607 if (nm == NULL) 608 goto err; 609 sk = X509V3_get_section(ctx, value); 610 if (sk == NULL) { 611 OPENSSL_PUT_ERROR(X509V3, X509V3_R_SECTION_NOT_FOUND); 612 ERR_add_error_data(2, "section=", value); 613 goto err; 614 } 615 /* FIXME: should allow other character types... */ 616 if (!X509V3_NAME_from_section(nm, sk, MBSTRING_ASC)) 617 goto err; 618 gen->d.dirn = nm; 619 ret = 1; 620 621 err: 622 if (!ret) 623 X509_NAME_free(nm); 624 X509V3_section_free(ctx, sk); 625 return ret; 626 } 627