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