1 /* 2 * Copyright 1999-2024 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the Apache License 2.0 (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10 #include <stdio.h> 11 #include "internal/cryptlib.h" 12 #include "crypto/x509.h" 13 #include <openssl/conf.h> 14 #include <openssl/x509v3.h> 15 #include <openssl/bio.h> 16 #include "ext_dat.h" 17 18 static GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method, 19 X509V3_CTX *ctx, 20 STACK_OF(CONF_VALUE) *nval); 21 static GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method, 22 X509V3_CTX *ctx, 23 STACK_OF(CONF_VALUE) *nval); 24 static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p); 25 static int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens); 26 static int do_othername(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx); 27 static int do_dirname(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx); 28 29 const X509V3_EXT_METHOD ossl_v3_alt[3] = { 30 { NID_subject_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES), 31 0, 0, 0, 0, 32 0, 0, 33 (X509V3_EXT_I2V)i2v_GENERAL_NAMES, 34 (X509V3_EXT_V2I)v2i_subject_alt, 35 NULL, NULL, NULL }, 36 37 { NID_issuer_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES), 38 0, 0, 0, 0, 39 0, 0, 40 (X509V3_EXT_I2V)i2v_GENERAL_NAMES, 41 (X509V3_EXT_V2I)v2i_issuer_alt, 42 NULL, NULL, NULL }, 43 44 { NID_certificate_issuer, 0, ASN1_ITEM_ref(GENERAL_NAMES), 45 0, 0, 0, 0, 46 0, 0, 47 (X509V3_EXT_I2V)i2v_GENERAL_NAMES, 48 NULL, NULL, NULL, NULL }, 49 }; 50 51 STACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES(X509V3_EXT_METHOD *method, 52 GENERAL_NAMES *gens, 53 STACK_OF(CONF_VALUE) *ret) 54 { 55 int i; 56 GENERAL_NAME *gen; 57 STACK_OF(CONF_VALUE) *tmpret = NULL, *origret = ret; 58 59 for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) { 60 gen = sk_GENERAL_NAME_value(gens, i); 61 /* 62 * i2v_GENERAL_NAME allocates ret if it is NULL. If something goes 63 * wrong we need to free the stack - but only if it was empty when we 64 * originally entered this function. 65 */ 66 tmpret = i2v_GENERAL_NAME(method, gen, ret); 67 if (tmpret == NULL) { 68 if (origret == NULL) 69 sk_CONF_VALUE_pop_free(ret, X509V3_conf_free); 70 return NULL; 71 } 72 ret = tmpret; 73 } 74 if (ret == NULL) 75 return sk_CONF_VALUE_new_null(); 76 return ret; 77 } 78 79 STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method, 80 GENERAL_NAME *gen, 81 STACK_OF(CONF_VALUE) *ret) 82 { 83 char othername[300]; 84 char oline[256], *tmp; 85 86 switch (gen->type) { 87 case GEN_OTHERNAME: 88 switch (OBJ_obj2nid(gen->d.otherName->type_id)) { 89 case NID_id_on_SmtpUTF8Mailbox: 90 if (gen->d.otherName->value->type != V_ASN1_UTF8STRING 91 || !x509v3_add_len_value_uchar("othername: SmtpUTF8Mailbox", 92 gen->d.otherName->value->value.utf8string->data, 93 gen->d.otherName->value->value.utf8string->length, 94 &ret)) 95 return NULL; 96 break; 97 case NID_XmppAddr: 98 if (gen->d.otherName->value->type != V_ASN1_UTF8STRING 99 || !x509v3_add_len_value_uchar("othername: XmppAddr", 100 gen->d.otherName->value->value.utf8string->data, 101 gen->d.otherName->value->value.utf8string->length, 102 &ret)) 103 return NULL; 104 break; 105 case NID_SRVName: 106 if (gen->d.otherName->value->type != V_ASN1_IA5STRING 107 || !x509v3_add_len_value_uchar("othername: SRVName", 108 gen->d.otherName->value->value.ia5string->data, 109 gen->d.otherName->value->value.ia5string->length, 110 &ret)) 111 return NULL; 112 break; 113 case NID_ms_upn: 114 if (gen->d.otherName->value->type != V_ASN1_UTF8STRING 115 || !x509v3_add_len_value_uchar("othername: UPN", 116 gen->d.otherName->value->value.utf8string->data, 117 gen->d.otherName->value->value.utf8string->length, 118 &ret)) 119 return NULL; 120 break; 121 case NID_NAIRealm: 122 if (gen->d.otherName->value->type != V_ASN1_UTF8STRING 123 || !x509v3_add_len_value_uchar("othername: NAIRealm", 124 gen->d.otherName->value->value.utf8string->data, 125 gen->d.otherName->value->value.utf8string->length, 126 &ret)) 127 return NULL; 128 break; 129 default: 130 if (OBJ_obj2txt(oline, sizeof(oline), gen->d.otherName->type_id, 0) > 0) 131 BIO_snprintf(othername, sizeof(othername), "othername: %s", 132 oline); 133 else 134 OPENSSL_strlcpy(othername, "othername", sizeof(othername)); 135 136 /* check if the value is something printable */ 137 if (gen->d.otherName->value->type == V_ASN1_IA5STRING) { 138 if (x509v3_add_len_value_uchar(othername, 139 gen->d.otherName->value->value.ia5string->data, 140 gen->d.otherName->value->value.ia5string->length, 141 &ret)) 142 return ret; 143 } 144 if (gen->d.otherName->value->type == V_ASN1_UTF8STRING) { 145 if (x509v3_add_len_value_uchar(othername, 146 gen->d.otherName->value->value.utf8string->data, 147 gen->d.otherName->value->value.utf8string->length, 148 &ret)) 149 return ret; 150 } 151 if (!X509V3_add_value(othername, "<unsupported>", &ret)) 152 return NULL; 153 break; 154 } 155 break; 156 157 case GEN_X400: 158 if (!X509V3_add_value("X400Name", "<unsupported>", &ret)) 159 return NULL; 160 break; 161 162 case GEN_EDIPARTY: 163 if (!X509V3_add_value("EdiPartyName", "<unsupported>", &ret)) 164 return NULL; 165 break; 166 167 case GEN_EMAIL: 168 if (!x509v3_add_len_value_uchar("email", gen->d.ia5->data, 169 gen->d.ia5->length, &ret)) 170 return NULL; 171 break; 172 173 case GEN_DNS: 174 if (!x509v3_add_len_value_uchar("DNS", gen->d.ia5->data, 175 gen->d.ia5->length, &ret)) 176 return NULL; 177 break; 178 179 case GEN_URI: 180 if (!x509v3_add_len_value_uchar("URI", gen->d.ia5->data, 181 gen->d.ia5->length, &ret)) 182 return NULL; 183 break; 184 185 case GEN_DIRNAME: 186 if (X509_NAME_oneline(gen->d.dirn, oline, sizeof(oline)) == NULL 187 || !X509V3_add_value("DirName", oline, &ret)) 188 return NULL; 189 break; 190 191 case GEN_IPADD: 192 tmp = ossl_ipaddr_to_asc(gen->d.ip->data, gen->d.ip->length); 193 if (tmp == NULL || !X509V3_add_value("IP Address", tmp, &ret)) 194 ret = NULL; 195 OPENSSL_free(tmp); 196 break; 197 198 case GEN_RID: 199 i2t_ASN1_OBJECT(oline, 256, gen->d.rid); 200 if (!X509V3_add_value("Registered ID", oline, &ret)) 201 return NULL; 202 break; 203 } 204 return ret; 205 } 206 207 int GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen) 208 { 209 char *tmp; 210 int nid; 211 212 switch (gen->type) { 213 case GEN_OTHERNAME: 214 nid = OBJ_obj2nid(gen->d.otherName->type_id); 215 /* Validate the types are as we expect before we use them */ 216 if ((nid == NID_SRVName 217 && gen->d.otherName->value->type != V_ASN1_IA5STRING) 218 || (nid != NID_SRVName 219 && gen->d.otherName->value->type != V_ASN1_UTF8STRING)) { 220 BIO_printf(out, "othername:<unsupported>"); 221 break; 222 } 223 224 switch (nid) { 225 case NID_id_on_SmtpUTF8Mailbox: 226 BIO_printf(out, "othername:SmtpUTF8Mailbox:%.*s", 227 gen->d.otherName->value->value.utf8string->length, 228 gen->d.otherName->value->value.utf8string->data); 229 break; 230 case NID_XmppAddr: 231 BIO_printf(out, "othername:XmppAddr:%.*s", 232 gen->d.otherName->value->value.utf8string->length, 233 gen->d.otherName->value->value.utf8string->data); 234 break; 235 case NID_SRVName: 236 BIO_printf(out, "othername:SRVName:%.*s", 237 gen->d.otherName->value->value.ia5string->length, 238 gen->d.otherName->value->value.ia5string->data); 239 break; 240 case NID_ms_upn: 241 BIO_printf(out, "othername:UPN:%.*s", 242 gen->d.otherName->value->value.utf8string->length, 243 gen->d.otherName->value->value.utf8string->data); 244 break; 245 case NID_NAIRealm: 246 BIO_printf(out, "othername:NAIRealm:%.*s", 247 gen->d.otherName->value->value.utf8string->length, 248 gen->d.otherName->value->value.utf8string->data); 249 break; 250 default: 251 BIO_printf(out, "othername:<unsupported>"); 252 break; 253 } 254 break; 255 256 case GEN_X400: 257 BIO_printf(out, "X400Name:<unsupported>"); 258 break; 259 260 case GEN_EDIPARTY: 261 /* Maybe fix this: it is supported now */ 262 BIO_printf(out, "EdiPartyName:<unsupported>"); 263 break; 264 265 case GEN_EMAIL: 266 BIO_printf(out, "email:"); 267 ASN1_STRING_print(out, gen->d.ia5); 268 break; 269 270 case GEN_DNS: 271 BIO_printf(out, "DNS:"); 272 ASN1_STRING_print(out, gen->d.ia5); 273 break; 274 275 case GEN_URI: 276 BIO_printf(out, "URI:"); 277 ASN1_STRING_print(out, gen->d.ia5); 278 break; 279 280 case GEN_DIRNAME: 281 BIO_printf(out, "DirName:"); 282 X509_NAME_print_ex(out, gen->d.dirn, 0, XN_FLAG_ONELINE); 283 break; 284 285 case GEN_IPADD: 286 tmp = ossl_ipaddr_to_asc(gen->d.ip->data, gen->d.ip->length); 287 if (tmp == NULL) 288 return 0; 289 BIO_printf(out, "IP Address:%s", tmp); 290 OPENSSL_free(tmp); 291 break; 292 293 case GEN_RID: 294 BIO_printf(out, "Registered ID:"); 295 i2a_ASN1_OBJECT(out, gen->d.rid); 296 break; 297 } 298 return 1; 299 } 300 301 static GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method, 302 X509V3_CTX *ctx, 303 STACK_OF(CONF_VALUE) *nval) 304 { 305 const int num = sk_CONF_VALUE_num(nval); 306 GENERAL_NAMES *gens = sk_GENERAL_NAME_new_reserve(NULL, num); 307 int i; 308 309 if (gens == NULL) { 310 ERR_raise(ERR_LIB_X509V3, ERR_R_CRYPTO_LIB); 311 return NULL; 312 } 313 for (i = 0; i < num; i++) { 314 CONF_VALUE *cnf = sk_CONF_VALUE_value(nval, i); 315 316 if (!ossl_v3_name_cmp(cnf->name, "issuer") 317 && cnf->value && strcmp(cnf->value, "copy") == 0) { 318 if (!copy_issuer(ctx, gens)) 319 goto err; 320 } else { 321 GENERAL_NAME *gen = v2i_GENERAL_NAME(method, ctx, cnf); 322 323 if (gen == NULL) 324 goto err; 325 sk_GENERAL_NAME_push(gens, gen); /* no failure as it was reserved */ 326 } 327 } 328 return gens; 329 err: 330 sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); 331 return NULL; 332 } 333 334 /* Append subject altname of issuer to issuer alt name of subject */ 335 336 static int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens) 337 { 338 GENERAL_NAMES *ialt = NULL; 339 GENERAL_NAME *gen; 340 X509_EXTENSION *ext; 341 int i, num; 342 343 if (ctx != NULL && (ctx->flags & X509V3_CTX_TEST) != 0) 344 return 1; 345 if (!ctx || !ctx->issuer_cert) { 346 ERR_raise(ERR_LIB_X509V3, X509V3_R_NO_ISSUER_DETAILS); 347 goto err; 348 } 349 i = X509_get_ext_by_NID(ctx->issuer_cert, NID_subject_alt_name, -1); 350 if (i < 0) 351 return 1; 352 if ((ext = X509_get_ext(ctx->issuer_cert, i)) == NULL 353 || (ialt = X509V3_EXT_d2i(ext)) == NULL) { 354 ERR_raise(ERR_LIB_X509V3, X509V3_R_ISSUER_DECODE_ERROR); 355 goto err; 356 } 357 358 num = sk_GENERAL_NAME_num(ialt); 359 if (!sk_GENERAL_NAME_reserve(gens, num)) { 360 ERR_raise(ERR_LIB_X509V3, ERR_R_CRYPTO_LIB); 361 goto err; 362 } 363 364 for (i = 0; i < num; i++) { 365 gen = sk_GENERAL_NAME_value(ialt, i); 366 sk_GENERAL_NAME_push(gens, gen); /* no failure as it was reserved */ 367 } 368 sk_GENERAL_NAME_free(ialt); 369 370 return 1; 371 372 err: 373 sk_GENERAL_NAME_free(ialt); 374 return 0; 375 } 376 377 static GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method, 378 X509V3_CTX *ctx, 379 STACK_OF(CONF_VALUE) *nval) 380 { 381 GENERAL_NAMES *gens; 382 CONF_VALUE *cnf; 383 const int num = sk_CONF_VALUE_num(nval); 384 int i; 385 386 gens = sk_GENERAL_NAME_new_reserve(NULL, num); 387 if (gens == NULL) { 388 ERR_raise(ERR_LIB_X509V3, ERR_R_CRYPTO_LIB); 389 return NULL; 390 } 391 392 for (i = 0; i < num; i++) { 393 cnf = sk_CONF_VALUE_value(nval, i); 394 if (ossl_v3_name_cmp(cnf->name, "email") == 0 395 && cnf->value && strcmp(cnf->value, "copy") == 0) { 396 if (!copy_email(ctx, gens, 0)) 397 goto err; 398 } else if (ossl_v3_name_cmp(cnf->name, "email") == 0 399 && cnf->value && strcmp(cnf->value, "move") == 0) { 400 if (!copy_email(ctx, gens, 1)) 401 goto err; 402 } else { 403 GENERAL_NAME *gen; 404 if ((gen = v2i_GENERAL_NAME(method, ctx, cnf)) == NULL) 405 goto err; 406 sk_GENERAL_NAME_push(gens, gen); /* no failure as it was reserved */ 407 } 408 } 409 return gens; 410 err: 411 sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); 412 return NULL; 413 } 414 415 /* 416 * Copy any email addresses in a certificate or request to GENERAL_NAMES 417 */ 418 419 static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p) 420 { 421 X509_NAME *nm; 422 ASN1_IA5STRING *email = NULL; 423 X509_NAME_ENTRY *ne; 424 GENERAL_NAME *gen = NULL; 425 int i = -1; 426 427 if (ctx != NULL && (ctx->flags & X509V3_CTX_TEST) != 0) 428 return 1; 429 if (ctx == NULL 430 || (ctx->subject_cert == NULL && ctx->subject_req == NULL)) { 431 ERR_raise(ERR_LIB_X509V3, X509V3_R_NO_SUBJECT_DETAILS); 432 return 0; 433 } 434 /* Find the subject name */ 435 nm = ctx->subject_cert != NULL ? X509_get_subject_name(ctx->subject_cert) : X509_REQ_get_subject_name(ctx->subject_req); 436 437 /* Now add any email address(es) to STACK */ 438 while ((i = X509_NAME_get_index_by_NID(nm, 439 NID_pkcs9_emailAddress, i)) 440 >= 0) { 441 ne = X509_NAME_get_entry(nm, i); 442 email = ASN1_STRING_dup(X509_NAME_ENTRY_get_data(ne)); 443 if (move_p) { 444 X509_NAME_delete_entry(nm, i); 445 X509_NAME_ENTRY_free(ne); 446 i--; 447 } 448 if (email == NULL || (gen = GENERAL_NAME_new()) == NULL) { 449 ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); 450 goto err; 451 } 452 gen->d.ia5 = email; 453 email = NULL; 454 gen->type = GEN_EMAIL; 455 if (!sk_GENERAL_NAME_push(gens, gen)) { 456 ERR_raise(ERR_LIB_X509V3, ERR_R_CRYPTO_LIB); 457 goto err; 458 } 459 gen = NULL; 460 } 461 462 return 1; 463 464 err: 465 GENERAL_NAME_free(gen); 466 ASN1_IA5STRING_free(email); 467 return 0; 468 } 469 470 GENERAL_NAMES *v2i_GENERAL_NAMES(const X509V3_EXT_METHOD *method, 471 X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval) 472 { 473 GENERAL_NAME *gen; 474 GENERAL_NAMES *gens; 475 CONF_VALUE *cnf; 476 const int num = sk_CONF_VALUE_num(nval); 477 int i; 478 479 gens = sk_GENERAL_NAME_new_reserve(NULL, num); 480 if (gens == NULL) { 481 ERR_raise(ERR_LIB_X509V3, ERR_R_CRYPTO_LIB); 482 return NULL; 483 } 484 485 for (i = 0; i < num; i++) { 486 cnf = sk_CONF_VALUE_value(nval, i); 487 if ((gen = v2i_GENERAL_NAME(method, ctx, cnf)) == NULL) 488 goto err; 489 sk_GENERAL_NAME_push(gens, gen); /* no failure as it was reserved */ 490 } 491 return gens; 492 err: 493 sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); 494 return NULL; 495 } 496 497 GENERAL_NAME *v2i_GENERAL_NAME(const X509V3_EXT_METHOD *method, 498 X509V3_CTX *ctx, CONF_VALUE *cnf) 499 { 500 return v2i_GENERAL_NAME_ex(NULL, method, ctx, cnf, 0); 501 } 502 503 GENERAL_NAME *a2i_GENERAL_NAME(GENERAL_NAME *out, 504 const X509V3_EXT_METHOD *method, 505 X509V3_CTX *ctx, int gen_type, const char *value, 506 int is_nc) 507 { 508 char is_string = 0; 509 GENERAL_NAME *gen = NULL; 510 511 if (!value) { 512 ERR_raise(ERR_LIB_X509V3, X509V3_R_MISSING_VALUE); 513 return NULL; 514 } 515 516 if (out) 517 gen = out; 518 else { 519 gen = GENERAL_NAME_new(); 520 if (gen == NULL) { 521 ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); 522 return NULL; 523 } 524 } 525 526 switch (gen_type) { 527 case GEN_URI: 528 case GEN_EMAIL: 529 case GEN_DNS: 530 is_string = 1; 531 break; 532 533 case GEN_RID: { 534 ASN1_OBJECT *obj; 535 if ((obj = OBJ_txt2obj(value, 0)) == NULL) { 536 ERR_raise_data(ERR_LIB_X509V3, X509V3_R_BAD_OBJECT, 537 "value=%s", value); 538 goto err; 539 } 540 gen->d.rid = obj; 541 } break; 542 543 case GEN_IPADD: 544 if (is_nc) 545 gen->d.ip = a2i_IPADDRESS_NC(value); 546 else 547 gen->d.ip = a2i_IPADDRESS(value); 548 if (gen->d.ip == NULL) { 549 ERR_raise_data(ERR_LIB_X509V3, X509V3_R_BAD_IP_ADDRESS, 550 "value=%s", value); 551 goto err; 552 } 553 break; 554 555 case GEN_DIRNAME: 556 if (!do_dirname(gen, value, ctx)) { 557 ERR_raise(ERR_LIB_X509V3, X509V3_R_DIRNAME_ERROR); 558 goto err; 559 } 560 break; 561 562 case GEN_OTHERNAME: 563 if (!do_othername(gen, value, ctx)) { 564 ERR_raise(ERR_LIB_X509V3, X509V3_R_OTHERNAME_ERROR); 565 goto err; 566 } 567 break; 568 default: 569 ERR_raise(ERR_LIB_X509V3, X509V3_R_UNSUPPORTED_TYPE); 570 goto err; 571 } 572 573 if (is_string) { 574 if ((gen->d.ia5 = ASN1_IA5STRING_new()) == NULL || !ASN1_STRING_set(gen->d.ia5, (unsigned char *)value, strlen(value))) { 575 ASN1_IA5STRING_free(gen->d.ia5); 576 gen->d.ia5 = NULL; 577 ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB); 578 goto err; 579 } 580 } 581 582 gen->type = gen_type; 583 584 return gen; 585 586 err: 587 if (!out) 588 GENERAL_NAME_free(gen); 589 return NULL; 590 } 591 592 GENERAL_NAME *v2i_GENERAL_NAME_ex(GENERAL_NAME *out, 593 const X509V3_EXT_METHOD *method, 594 X509V3_CTX *ctx, CONF_VALUE *cnf, int is_nc) 595 { 596 int type; 597 598 char *name, *value; 599 600 name = cnf->name; 601 value = cnf->value; 602 603 if (!value) { 604 ERR_raise(ERR_LIB_X509V3, X509V3_R_MISSING_VALUE); 605 return NULL; 606 } 607 608 if (!ossl_v3_name_cmp(name, "email")) 609 type = GEN_EMAIL; 610 else if (!ossl_v3_name_cmp(name, "URI")) 611 type = GEN_URI; 612 else if (!ossl_v3_name_cmp(name, "DNS")) 613 type = GEN_DNS; 614 else if (!ossl_v3_name_cmp(name, "RID")) 615 type = GEN_RID; 616 else if (!ossl_v3_name_cmp(name, "IP")) 617 type = GEN_IPADD; 618 else if (!ossl_v3_name_cmp(name, "dirName")) 619 type = GEN_DIRNAME; 620 else if (!ossl_v3_name_cmp(name, "otherName")) 621 type = GEN_OTHERNAME; 622 else { 623 ERR_raise_data(ERR_LIB_X509V3, X509V3_R_UNSUPPORTED_OPTION, 624 "name=%s", name); 625 return NULL; 626 } 627 628 return a2i_GENERAL_NAME(out, method, ctx, type, value, is_nc); 629 } 630 631 static int do_othername(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx) 632 { 633 char *objtmp = NULL, *p; 634 int objlen; 635 636 if ((p = strchr(value, ';')) == NULL) 637 return 0; 638 if ((gen->d.otherName = OTHERNAME_new()) == NULL) 639 return 0; 640 /* 641 * Free this up because we will overwrite it. no need to free type_id 642 * because it is static 643 */ 644 ASN1_TYPE_free(gen->d.otherName->value); 645 if ((gen->d.otherName->value = ASN1_generate_v3(p + 1, ctx)) == NULL) 646 goto err; 647 objlen = p - value; 648 objtmp = OPENSSL_strndup(value, objlen); 649 if (objtmp == NULL) 650 goto err; 651 gen->d.otherName->type_id = OBJ_txt2obj(objtmp, 0); 652 OPENSSL_free(objtmp); 653 if (!gen->d.otherName->type_id) 654 goto err; 655 return 1; 656 657 err: 658 OTHERNAME_free(gen->d.otherName); 659 gen->d.otherName = NULL; 660 return 0; 661 } 662 663 static int do_dirname(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx) 664 { 665 int ret = 0; 666 STACK_OF(CONF_VALUE) *sk = NULL; 667 X509_NAME *nm; 668 669 if ((nm = X509_NAME_new()) == NULL) 670 goto err; 671 sk = X509V3_get_section(ctx, value); 672 if (!sk) { 673 ERR_raise_data(ERR_LIB_X509V3, X509V3_R_SECTION_NOT_FOUND, 674 "section=%s", value); 675 goto err; 676 } 677 /* FIXME: should allow other character types... */ 678 ret = X509V3_NAME_from_section(nm, sk, MBSTRING_ASC); 679 if (!ret) 680 goto err; 681 gen->d.dirn = nm; 682 683 err: 684 if (ret == 0) 685 X509_NAME_free(nm); 686 X509V3_section_free(ctx, sk); 687 return ret; 688 } 689