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 static GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method, 68 X509V3_CTX *ctx, 69 STACK_OF(CONF_VALUE) *nval); 70 static GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method, 71 X509V3_CTX *ctx, 72 STACK_OF(CONF_VALUE) *nval); 73 static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p); 74 static int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens); 75 static int do_othername(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx); 76 static int do_dirname(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx); 77 78 const X509V3_EXT_METHOD v3_alt[] = { 79 {NID_subject_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES), 80 0, 0, 0, 0, 81 0, 0, 82 (X509V3_EXT_I2V) i2v_GENERAL_NAMES, 83 (X509V3_EXT_V2I)v2i_subject_alt, 84 NULL, NULL, NULL}, 85 86 {NID_issuer_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES), 87 0, 0, 0, 0, 88 0, 0, 89 (X509V3_EXT_I2V) i2v_GENERAL_NAMES, 90 (X509V3_EXT_V2I)v2i_issuer_alt, 91 NULL, NULL, NULL}, 92 93 {NID_certificate_issuer, 0, ASN1_ITEM_ref(GENERAL_NAMES), 94 0, 0, 0, 0, 95 0, 0, 96 (X509V3_EXT_I2V) i2v_GENERAL_NAMES, 97 NULL, NULL, NULL, NULL}, 98 }; 99 100 STACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES(X509V3_EXT_METHOD *method, 101 GENERAL_NAMES *gens, 102 STACK_OF(CONF_VALUE) *ret) 103 { 104 size_t i; 105 GENERAL_NAME *gen; 106 for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) { 107 gen = sk_GENERAL_NAME_value(gens, i); 108 ret = i2v_GENERAL_NAME(method, gen, ret); 109 } 110 if (!ret) 111 return sk_CONF_VALUE_new_null(); 112 return ret; 113 } 114 115 STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method, 116 GENERAL_NAME *gen, 117 STACK_OF(CONF_VALUE) *ret) 118 { 119 unsigned char *p; 120 char oline[256], htmp[5]; 121 int i; 122 switch (gen->type) { 123 case GEN_OTHERNAME: 124 X509V3_add_value("othername", "<unsupported>", &ret); 125 break; 126 127 case GEN_X400: 128 X509V3_add_value("X400Name", "<unsupported>", &ret); 129 break; 130 131 case GEN_EDIPARTY: 132 X509V3_add_value("EdiPartyName", "<unsupported>", &ret); 133 break; 134 135 case GEN_EMAIL: 136 X509V3_add_value_uchar("email", gen->d.ia5->data, &ret); 137 break; 138 139 case GEN_DNS: 140 X509V3_add_value_uchar("DNS", gen->d.ia5->data, &ret); 141 break; 142 143 case GEN_URI: 144 X509V3_add_value_uchar("URI", gen->d.ia5->data, &ret); 145 break; 146 147 case GEN_DIRNAME: 148 X509_NAME_oneline(gen->d.dirn, oline, 256); 149 X509V3_add_value("DirName", oline, &ret); 150 break; 151 152 case GEN_IPADD: 153 p = gen->d.ip->data; 154 if (gen->d.ip->length == 4) 155 BIO_snprintf(oline, sizeof oline, 156 "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); 157 else if (gen->d.ip->length == 16) { 158 oline[0] = 0; 159 for (i = 0; i < 8; i++) { 160 BIO_snprintf(htmp, sizeof htmp, "%X", p[0] << 8 | p[1]); 161 p += 2; 162 strcat(oline, htmp); 163 if (i != 7) 164 strcat(oline, ":"); 165 } 166 } else { 167 X509V3_add_value("IP Address", "<invalid>", &ret); 168 break; 169 } 170 X509V3_add_value("IP Address", oline, &ret); 171 break; 172 173 case GEN_RID: 174 i2t_ASN1_OBJECT(oline, 256, gen->d.rid); 175 X509V3_add_value("Registered ID", oline, &ret); 176 break; 177 } 178 return ret; 179 } 180 181 int GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen) 182 { 183 unsigned char *p; 184 int i; 185 switch (gen->type) { 186 case GEN_OTHERNAME: 187 BIO_printf(out, "othername:<unsupported>"); 188 break; 189 190 case GEN_X400: 191 BIO_printf(out, "X400Name:<unsupported>"); 192 break; 193 194 case GEN_EDIPARTY: 195 /* Maybe fix this: it is supported now */ 196 BIO_printf(out, "EdiPartyName:<unsupported>"); 197 break; 198 199 case GEN_EMAIL: 200 BIO_printf(out, "email:%s", gen->d.ia5->data); 201 break; 202 203 case GEN_DNS: 204 BIO_printf(out, "DNS:%s", gen->d.ia5->data); 205 break; 206 207 case GEN_URI: 208 BIO_printf(out, "URI:%s", gen->d.ia5->data); 209 break; 210 211 case GEN_DIRNAME: 212 BIO_printf(out, "DirName: "); 213 X509_NAME_print_ex(out, gen->d.dirn, 0, XN_FLAG_ONELINE); 214 break; 215 216 case GEN_IPADD: 217 p = gen->d.ip->data; 218 if (gen->d.ip->length == 4) 219 BIO_printf(out, "IP Address:%d.%d.%d.%d", p[0], p[1], p[2], p[3]); 220 else if (gen->d.ip->length == 16) { 221 BIO_printf(out, "IP Address"); 222 for (i = 0; i < 8; i++) { 223 BIO_printf(out, ":%X", p[0] << 8 | p[1]); 224 p += 2; 225 } 226 BIO_puts(out, "\n"); 227 } else { 228 BIO_printf(out, "IP Address:<invalid>"); 229 break; 230 } 231 break; 232 233 case GEN_RID: 234 BIO_printf(out, "Registered ID"); 235 i2a_ASN1_OBJECT(out, gen->d.rid); 236 break; 237 } 238 return 1; 239 } 240 241 static GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method, 242 X509V3_CTX *ctx, 243 STACK_OF(CONF_VALUE) *nval) 244 { 245 GENERAL_NAMES *gens = NULL; 246 CONF_VALUE *cnf; 247 size_t i; 248 if (!(gens = sk_GENERAL_NAME_new_null())) { 249 OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); 250 return NULL; 251 } 252 for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { 253 cnf = sk_CONF_VALUE_value(nval, i); 254 if (!name_cmp(cnf->name, "issuer") && cnf->value && 255 !strcmp(cnf->value, "copy")) { 256 if (!copy_issuer(ctx, gens)) 257 goto err; 258 } else { 259 GENERAL_NAME *gen; 260 if (!(gen = v2i_GENERAL_NAME(method, ctx, cnf))) 261 goto err; 262 sk_GENERAL_NAME_push(gens, gen); 263 } 264 } 265 return gens; 266 err: 267 sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); 268 return NULL; 269 } 270 271 /* Append subject altname of issuer to issuer alt name of subject */ 272 273 static int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens) 274 { 275 GENERAL_NAMES *ialt; 276 GENERAL_NAME *gen; 277 X509_EXTENSION *ext; 278 int i; 279 size_t j; 280 if (ctx && (ctx->flags == CTX_TEST)) 281 return 1; 282 if (!ctx || !ctx->issuer_cert) { 283 OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_ISSUER_DETAILS); 284 goto err; 285 } 286 i = X509_get_ext_by_NID(ctx->issuer_cert, NID_subject_alt_name, -1); 287 if (i < 0) 288 return 1; 289 if (!(ext = X509_get_ext(ctx->issuer_cert, i)) || 290 !(ialt = X509V3_EXT_d2i(ext))) { 291 OPENSSL_PUT_ERROR(X509V3, X509V3_R_ISSUER_DECODE_ERROR); 292 goto err; 293 } 294 295 for (j = 0; j < sk_GENERAL_NAME_num(ialt); j++) { 296 gen = sk_GENERAL_NAME_value(ialt, j); 297 if (!sk_GENERAL_NAME_push(gens, gen)) { 298 OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); 299 goto err; 300 } 301 } 302 sk_GENERAL_NAME_free(ialt); 303 304 return 1; 305 306 err: 307 return 0; 308 309 } 310 311 static GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method, 312 X509V3_CTX *ctx, 313 STACK_OF(CONF_VALUE) *nval) 314 { 315 GENERAL_NAMES *gens = NULL; 316 CONF_VALUE *cnf; 317 size_t i; 318 if (!(gens = sk_GENERAL_NAME_new_null())) { 319 OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); 320 return NULL; 321 } 322 for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { 323 cnf = sk_CONF_VALUE_value(nval, i); 324 if (!name_cmp(cnf->name, "email") && cnf->value && 325 !strcmp(cnf->value, "copy")) { 326 if (!copy_email(ctx, gens, 0)) 327 goto err; 328 } else if (!name_cmp(cnf->name, "email") && cnf->value && 329 !strcmp(cnf->value, "move")) { 330 if (!copy_email(ctx, gens, 1)) 331 goto err; 332 } else { 333 GENERAL_NAME *gen; 334 if (!(gen = v2i_GENERAL_NAME(method, ctx, cnf))) 335 goto err; 336 sk_GENERAL_NAME_push(gens, gen); 337 } 338 } 339 return gens; 340 err: 341 sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); 342 return NULL; 343 } 344 345 /* 346 * Copy any email addresses in a certificate or request to GENERAL_NAMES 347 */ 348 349 static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p) 350 { 351 X509_NAME *nm; 352 ASN1_IA5STRING *email = NULL; 353 X509_NAME_ENTRY *ne; 354 GENERAL_NAME *gen = NULL; 355 int i; 356 if (ctx != NULL && ctx->flags == CTX_TEST) 357 return 1; 358 if (!ctx || (!ctx->subject_cert && !ctx->subject_req)) { 359 OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_SUBJECT_DETAILS); 360 goto err; 361 } 362 /* Find the subject name */ 363 if (ctx->subject_cert) 364 nm = X509_get_subject_name(ctx->subject_cert); 365 else 366 nm = X509_REQ_get_subject_name(ctx->subject_req); 367 368 /* Now add any email address(es) to STACK */ 369 i = -1; 370 while ((i = X509_NAME_get_index_by_NID(nm, 371 NID_pkcs9_emailAddress, i)) >= 0) { 372 ne = X509_NAME_get_entry(nm, i); 373 email = M_ASN1_IA5STRING_dup(X509_NAME_ENTRY_get_data(ne)); 374 if (move_p) { 375 X509_NAME_delete_entry(nm, i); 376 X509_NAME_ENTRY_free(ne); 377 i--; 378 } 379 if (!email || !(gen = GENERAL_NAME_new())) { 380 OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); 381 goto err; 382 } 383 gen->d.ia5 = email; 384 email = NULL; 385 gen->type = GEN_EMAIL; 386 if (!sk_GENERAL_NAME_push(gens, gen)) { 387 OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); 388 goto err; 389 } 390 gen = NULL; 391 } 392 393 return 1; 394 395 err: 396 GENERAL_NAME_free(gen); 397 M_ASN1_IA5STRING_free(email); 398 return 0; 399 400 } 401 402 GENERAL_NAMES *v2i_GENERAL_NAMES(const X509V3_EXT_METHOD *method, 403 X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval) 404 { 405 GENERAL_NAME *gen; 406 GENERAL_NAMES *gens = NULL; 407 CONF_VALUE *cnf; 408 size_t i; 409 if (!(gens = sk_GENERAL_NAME_new_null())) { 410 OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); 411 return NULL; 412 } 413 for (i = 0; i < sk_CONF_VALUE_num(nval); i++) { 414 cnf = sk_CONF_VALUE_value(nval, i); 415 if (!(gen = v2i_GENERAL_NAME(method, ctx, cnf))) 416 goto err; 417 sk_GENERAL_NAME_push(gens, gen); 418 } 419 return gens; 420 err: 421 sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); 422 return NULL; 423 } 424 425 GENERAL_NAME *v2i_GENERAL_NAME(const X509V3_EXT_METHOD *method, 426 X509V3_CTX *ctx, CONF_VALUE *cnf) 427 { 428 return v2i_GENERAL_NAME_ex(NULL, method, ctx, cnf, 0); 429 } 430 431 GENERAL_NAME *a2i_GENERAL_NAME(GENERAL_NAME *out, 432 const X509V3_EXT_METHOD *method, 433 X509V3_CTX *ctx, int gen_type, char *value, 434 int is_nc) 435 { 436 char is_string = 0; 437 GENERAL_NAME *gen = NULL; 438 439 if (!value) { 440 OPENSSL_PUT_ERROR(X509V3, X509V3_R_MISSING_VALUE); 441 return NULL; 442 } 443 444 if (out) 445 gen = out; 446 else { 447 gen = GENERAL_NAME_new(); 448 if (gen == NULL) { 449 OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); 450 return NULL; 451 } 452 } 453 454 switch (gen_type) { 455 case GEN_URI: 456 case GEN_EMAIL: 457 case GEN_DNS: 458 is_string = 1; 459 break; 460 461 case GEN_RID: 462 { 463 ASN1_OBJECT *obj; 464 if (!(obj = OBJ_txt2obj(value, 0))) { 465 OPENSSL_PUT_ERROR(X509V3, X509V3_R_BAD_OBJECT); 466 ERR_add_error_data(2, "value=", value); 467 goto err; 468 } 469 gen->d.rid = obj; 470 } 471 break; 472 473 case GEN_IPADD: 474 if (is_nc) 475 gen->d.ip = a2i_IPADDRESS_NC(value); 476 else 477 gen->d.ip = a2i_IPADDRESS(value); 478 if (gen->d.ip == NULL) { 479 OPENSSL_PUT_ERROR(X509V3, X509V3_R_BAD_IP_ADDRESS); 480 ERR_add_error_data(2, "value=", value); 481 goto err; 482 } 483 break; 484 485 case GEN_DIRNAME: 486 if (!do_dirname(gen, value, ctx)) { 487 OPENSSL_PUT_ERROR(X509V3, X509V3_R_DIRNAME_ERROR); 488 goto err; 489 } 490 break; 491 492 case GEN_OTHERNAME: 493 if (!do_othername(gen, value, ctx)) { 494 OPENSSL_PUT_ERROR(X509V3, X509V3_R_OTHERNAME_ERROR); 495 goto err; 496 } 497 break; 498 default: 499 OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNSUPPORTED_TYPE); 500 goto err; 501 } 502 503 if (is_string) { 504 if (!(gen->d.ia5 = M_ASN1_IA5STRING_new()) || 505 !ASN1_STRING_set(gen->d.ia5, (unsigned char *)value, 506 strlen(value))) { 507 OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE); 508 goto err; 509 } 510 } 511 512 gen->type = gen_type; 513 514 return gen; 515 516 err: 517 if (!out) 518 GENERAL_NAME_free(gen); 519 return NULL; 520 } 521 522 GENERAL_NAME *v2i_GENERAL_NAME_ex(GENERAL_NAME *out, 523 const X509V3_EXT_METHOD *method, 524 X509V3_CTX *ctx, CONF_VALUE *cnf, int is_nc) 525 { 526 int type; 527 528 char *name, *value; 529 530 name = cnf->name; 531 value = cnf->value; 532 533 if (!value) { 534 OPENSSL_PUT_ERROR(X509V3, X509V3_R_MISSING_VALUE); 535 return NULL; 536 } 537 538 if (!name_cmp(name, "email")) 539 type = GEN_EMAIL; 540 else if (!name_cmp(name, "URI")) 541 type = GEN_URI; 542 else if (!name_cmp(name, "DNS")) 543 type = GEN_DNS; 544 else if (!name_cmp(name, "RID")) 545 type = GEN_RID; 546 else if (!name_cmp(name, "IP")) 547 type = GEN_IPADD; 548 else if (!name_cmp(name, "dirName")) 549 type = GEN_DIRNAME; 550 else if (!name_cmp(name, "otherName")) 551 type = GEN_OTHERNAME; 552 else { 553 OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNSUPPORTED_OPTION); 554 ERR_add_error_data(2, "name=", name); 555 return NULL; 556 } 557 558 return a2i_GENERAL_NAME(out, method, ctx, type, value, is_nc); 559 560 } 561 562 static int do_othername(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx) 563 { 564 char *objtmp = NULL, *p; 565 int objlen; 566 if (!(p = strchr(value, ';'))) 567 return 0; 568 if (!(gen->d.otherName = OTHERNAME_new())) 569 return 0; 570 /* 571 * Free this up because we will overwrite it. no need to free type_id 572 * because it is static 573 */ 574 ASN1_TYPE_free(gen->d.otherName->value); 575 if (!(gen->d.otherName->value = ASN1_generate_v3(p + 1, ctx))) 576 return 0; 577 objlen = p - value; 578 objtmp = OPENSSL_malloc(objlen + 1); 579 if (objtmp == NULL) 580 return 0; 581 strncpy(objtmp, value, objlen); 582 objtmp[objlen] = 0; 583 gen->d.otherName->type_id = OBJ_txt2obj(objtmp, 0); 584 OPENSSL_free(objtmp); 585 if (!gen->d.otherName->type_id) 586 return 0; 587 return 1; 588 } 589 590 static int do_dirname(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx) 591 { 592 int ret = 0; 593 STACK_OF(CONF_VALUE) *sk = NULL; 594 X509_NAME *nm = X509_NAME_new(); 595 if (nm == NULL) 596 goto err; 597 sk = X509V3_get_section(ctx, value); 598 if (sk == NULL) { 599 OPENSSL_PUT_ERROR(X509V3, X509V3_R_SECTION_NOT_FOUND); 600 ERR_add_error_data(2, "section=", value); 601 goto err; 602 } 603 /* FIXME: should allow other character types... */ 604 if (!X509V3_NAME_from_section(nm, sk, MBSTRING_ASC)) 605 goto err; 606 gen->d.dirn = nm; 607 ret = 1; 608 609 err: 610 if (!ret) 611 X509_NAME_free(nm); 612 X509V3_section_free(ctx, sk); 613 return ret; 614 } 615