1 /* $OpenBSD: x509_utl.c,v 1.14 2023/04/23 11:52:14 tb 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 /* X509 v3 extension utilities */ 59 60 #include <ctype.h> 61 #include <stdio.h> 62 #include <string.h> 63 64 #include <openssl/asn1.h> 65 #include <openssl/bn.h> 66 #include <openssl/conf.h> 67 #include <openssl/err.h> 68 #include <openssl/x509v3.h> 69 70 static char *bn_to_string(const BIGNUM *bn); 71 static char *strip_spaces(char *name); 72 static int sk_strcmp(const char * const *a, const char * const *b); 73 static STACK_OF(OPENSSL_STRING) *get_email(X509_NAME *name, 74 GENERAL_NAMES *gens); 75 static void str_free(OPENSSL_STRING str); 76 static int append_ia5(STACK_OF(OPENSSL_STRING) **sk, ASN1_IA5STRING *email); 77 78 static int ipv4_from_asc(unsigned char *v4, const char *in); 79 static int ipv6_from_asc(unsigned char *v6, const char *in); 80 static int ipv6_cb(const char *elem, int len, void *usr); 81 static int ipv6_hex(unsigned char *out, const char *in, int inlen); 82 83 /* Add a CONF_VALUE name-value pair to stack. */ 84 int 85 X509V3_add_value(const char *name, const char *value, 86 STACK_OF(CONF_VALUE) **extlist) 87 { 88 CONF_VALUE *vtmp = NULL; 89 STACK_OF(CONF_VALUE) *free_exts = NULL; 90 91 if ((vtmp = calloc(1, sizeof(CONF_VALUE))) == NULL) 92 goto err; 93 if (name != NULL) { 94 if ((vtmp->name = strdup(name)) == NULL) 95 goto err; 96 } 97 if (value != NULL) { 98 if ((vtmp->value = strdup(value)) == NULL) 99 goto err; 100 } 101 102 if (*extlist == NULL) { 103 if ((free_exts = *extlist = sk_CONF_VALUE_new_null()) == NULL) 104 goto err; 105 } 106 107 if (!sk_CONF_VALUE_push(*extlist, vtmp)) 108 goto err; 109 110 return 1; 111 112 err: 113 X509V3error(ERR_R_MALLOC_FAILURE); 114 X509V3_conf_free(vtmp); 115 if (free_exts != NULL) { 116 sk_CONF_VALUE_free(*extlist); 117 *extlist = NULL; 118 } 119 return 0; 120 } 121 LCRYPTO_ALIAS(X509V3_add_value); 122 123 int 124 X509V3_add_value_uchar(const char *name, const unsigned char *value, 125 STACK_OF(CONF_VALUE) **extlist) 126 { 127 return X509V3_add_value(name, (const char *)value, extlist); 128 } 129 LCRYPTO_ALIAS(X509V3_add_value_uchar); 130 131 /* Free function for STACK_OF(CONF_VALUE) */ 132 133 void 134 X509V3_conf_free(CONF_VALUE *conf) 135 { 136 if (!conf) 137 return; 138 free(conf->name); 139 free(conf->value); 140 free(conf->section); 141 free(conf); 142 } 143 LCRYPTO_ALIAS(X509V3_conf_free); 144 145 int 146 X509V3_add_value_bool(const char *name, int asn1_bool, 147 STACK_OF(CONF_VALUE) **extlist) 148 { 149 if (asn1_bool) 150 return X509V3_add_value(name, "TRUE", extlist); 151 return X509V3_add_value(name, "FALSE", extlist); 152 } 153 LCRYPTO_ALIAS(X509V3_add_value_bool); 154 155 int 156 X509V3_add_value_bool_nf(const char *name, int asn1_bool, 157 STACK_OF(CONF_VALUE) **extlist) 158 { 159 if (asn1_bool) 160 return X509V3_add_value(name, "TRUE", extlist); 161 return 1; 162 } 163 LCRYPTO_ALIAS(X509V3_add_value_bool_nf); 164 165 static char * 166 bn_to_string(const BIGNUM *bn) 167 { 168 const char *sign = ""; 169 char *bnstr, *hex; 170 char *ret = NULL; 171 172 /* Only display small numbers in decimal, as conversion is quadratic. */ 173 if (BN_num_bits(bn) < 128) 174 return BN_bn2dec(bn); 175 176 if ((hex = bnstr = BN_bn2hex(bn)) == NULL) 177 goto err; 178 179 if (BN_is_negative(bn)) { 180 sign = "-"; 181 hex++; 182 } 183 184 if (asprintf(&ret, "%s0x%s", sign, hex) == -1) 185 ret = NULL; 186 187 err: 188 free(bnstr); 189 return ret; 190 } 191 192 char * 193 i2s_ASN1_ENUMERATED(X509V3_EXT_METHOD *method, const ASN1_ENUMERATED *a) 194 { 195 BIGNUM *bntmp; 196 char *strtmp = NULL; 197 198 if (a == NULL) 199 return NULL; 200 if ((bntmp = ASN1_ENUMERATED_to_BN(a, NULL)) == NULL || 201 (strtmp = bn_to_string(bntmp)) == NULL) 202 X509V3error(ERR_R_MALLOC_FAILURE); 203 BN_free(bntmp); 204 return strtmp; 205 } 206 LCRYPTO_ALIAS(i2s_ASN1_ENUMERATED); 207 208 char * 209 i2s_ASN1_ENUMERATED_TABLE(X509V3_EXT_METHOD *method, const ASN1_ENUMERATED *e) 210 { 211 BIT_STRING_BITNAME *enam; 212 long strval; 213 214 strval = ASN1_ENUMERATED_get(e); 215 for (enam = method->usr_data; enam->lname; enam++) { 216 if (strval == enam->bitnum) 217 return strdup(enam->lname); 218 } 219 return i2s_ASN1_ENUMERATED(method, e); 220 } 221 LCRYPTO_ALIAS(i2s_ASN1_ENUMERATED_TABLE); 222 223 char * 224 i2s_ASN1_INTEGER(X509V3_EXT_METHOD *method, const ASN1_INTEGER *a) 225 { 226 BIGNUM *bntmp; 227 char *strtmp = NULL; 228 229 if (a == NULL) 230 return NULL; 231 if ((bntmp = ASN1_INTEGER_to_BN(a, NULL)) == NULL || 232 (strtmp = bn_to_string(bntmp)) == NULL) 233 X509V3error(ERR_R_MALLOC_FAILURE); 234 BN_free(bntmp); 235 return strtmp; 236 } 237 LCRYPTO_ALIAS(i2s_ASN1_INTEGER); 238 239 ASN1_INTEGER * 240 s2i_ASN1_INTEGER(X509V3_EXT_METHOD *method, const char *value) 241 { 242 BIGNUM *bn = NULL; 243 ASN1_INTEGER *aint; 244 int isneg = 0, ishex = 0; 245 int ret; 246 247 if (!value) { 248 X509V3error(X509V3_R_INVALID_NULL_VALUE); 249 return NULL; 250 } 251 if ((bn = BN_new()) == NULL) { 252 X509V3error(ERR_R_MALLOC_FAILURE); 253 return NULL; 254 } 255 if (value[0] == '-') { 256 value++; 257 isneg = 1; 258 } 259 260 if (value[0] == '0' && (value[1] == 'x' || value[1] == 'X')) { 261 value += 2; 262 ishex = 1; 263 } 264 265 if (ishex) 266 ret = BN_hex2bn(&bn, value); 267 else 268 ret = BN_dec2bn(&bn, value); 269 270 if (!ret || value[ret]) { 271 BN_free(bn); 272 X509V3error(X509V3_R_BN_DEC2BN_ERROR); 273 return NULL; 274 } 275 276 if (BN_is_zero(bn)) 277 isneg = 0; 278 279 aint = BN_to_ASN1_INTEGER(bn, NULL); 280 BN_free(bn); 281 if (!aint) { 282 X509V3error(X509V3_R_BN_TO_ASN1_INTEGER_ERROR); 283 return NULL; 284 } 285 if (isneg) 286 aint->type |= V_ASN1_NEG; 287 return aint; 288 } 289 LCRYPTO_ALIAS(s2i_ASN1_INTEGER); 290 291 int 292 X509V3_add_value_int(const char *name, const ASN1_INTEGER *aint, 293 STACK_OF(CONF_VALUE) **extlist) 294 { 295 char *strtmp; 296 int ret; 297 298 if (!aint) 299 return 1; 300 if (!(strtmp = i2s_ASN1_INTEGER(NULL, aint))) 301 return 0; 302 ret = X509V3_add_value(name, strtmp, extlist); 303 free(strtmp); 304 return ret; 305 } 306 LCRYPTO_ALIAS(X509V3_add_value_int); 307 308 int 309 X509V3_get_value_bool(const CONF_VALUE *value, int *asn1_bool) 310 { 311 char *btmp; 312 313 if (!(btmp = value->value)) 314 goto err; 315 if (!strcmp(btmp, "TRUE") || !strcmp(btmp, "true") || 316 !strcmp(btmp, "Y") || !strcmp(btmp, "y") || 317 !strcmp(btmp, "YES") || !strcmp(btmp, "yes")) { 318 *asn1_bool = 0xff; 319 return 1; 320 } else if (!strcmp(btmp, "FALSE") || !strcmp(btmp, "false") || 321 !strcmp(btmp, "N") || !strcmp(btmp, "n") || 322 !strcmp(btmp, "NO") || !strcmp(btmp, "no")) { 323 *asn1_bool = 0; 324 return 1; 325 } 326 327 err: 328 X509V3error(X509V3_R_INVALID_BOOLEAN_STRING); 329 X509V3_conf_err(value); 330 return 0; 331 } 332 LCRYPTO_ALIAS(X509V3_get_value_bool); 333 334 int 335 X509V3_get_value_int(const CONF_VALUE *value, ASN1_INTEGER **aint) 336 { 337 ASN1_INTEGER *itmp; 338 339 if (!(itmp = s2i_ASN1_INTEGER(NULL, value->value))) { 340 X509V3_conf_err(value); 341 return 0; 342 } 343 *aint = itmp; 344 return 1; 345 } 346 LCRYPTO_ALIAS(X509V3_get_value_int); 347 348 #define HDR_NAME 1 349 #define HDR_VALUE 2 350 351 /*#define DEBUG*/ 352 353 STACK_OF(CONF_VALUE) * 354 X509V3_parse_list(const char *line) 355 { 356 char *p, *q, c; 357 char *ntmp, *vtmp; 358 STACK_OF(CONF_VALUE) *values = NULL; 359 char *linebuf; 360 int state; 361 362 /* We are going to modify the line so copy it first */ 363 if ((linebuf = strdup(line)) == NULL) { 364 X509V3error(ERR_R_MALLOC_FAILURE); 365 goto err; 366 } 367 state = HDR_NAME; 368 ntmp = NULL; 369 370 /* Go through all characters */ 371 for (p = linebuf, q = linebuf; (c = *p) && (c != '\r') && 372 (c != '\n'); p++) { 373 374 switch (state) { 375 case HDR_NAME: 376 if (c == ':') { 377 state = HDR_VALUE; 378 *p = 0; 379 ntmp = strip_spaces(q); 380 if (!ntmp) { 381 X509V3error(X509V3_R_INVALID_NULL_NAME); 382 goto err; 383 } 384 q = p + 1; 385 } else if (c == ',') { 386 *p = 0; 387 ntmp = strip_spaces(q); 388 q = p + 1; 389 if (!ntmp) { 390 X509V3error(X509V3_R_INVALID_NULL_NAME); 391 goto err; 392 } 393 X509V3_add_value(ntmp, NULL, &values); 394 } 395 break; 396 397 case HDR_VALUE: 398 if (c == ',') { 399 state = HDR_NAME; 400 *p = 0; 401 vtmp = strip_spaces(q); 402 if (!vtmp) { 403 X509V3error(X509V3_R_INVALID_NULL_VALUE); 404 goto err; 405 } 406 X509V3_add_value(ntmp, vtmp, &values); 407 ntmp = NULL; 408 q = p + 1; 409 } 410 411 } 412 } 413 414 if (state == HDR_VALUE) { 415 vtmp = strip_spaces(q); 416 if (!vtmp) { 417 X509V3error(X509V3_R_INVALID_NULL_VALUE); 418 goto err; 419 } 420 X509V3_add_value(ntmp, vtmp, &values); 421 } else { 422 ntmp = strip_spaces(q); 423 if (!ntmp) { 424 X509V3error(X509V3_R_INVALID_NULL_NAME); 425 goto err; 426 } 427 X509V3_add_value(ntmp, NULL, &values); 428 } 429 free(linebuf); 430 return values; 431 432 err: 433 free(linebuf); 434 sk_CONF_VALUE_pop_free(values, X509V3_conf_free); 435 return NULL; 436 437 } 438 LCRYPTO_ALIAS(X509V3_parse_list); 439 440 /* Delete leading and trailing spaces from a string */ 441 static char * 442 strip_spaces(char *name) 443 { 444 char *p, *q; 445 446 /* Skip over leading spaces */ 447 p = name; 448 while (*p && isspace((unsigned char)*p)) 449 p++; 450 if (!*p) 451 return NULL; 452 q = p + strlen(p) - 1; 453 while ((q != p) && isspace((unsigned char)*q)) 454 q--; 455 if (p != q) 456 q[1] = 0; 457 if (!*p) 458 return NULL; 459 return p; 460 } 461 462 /* hex string utilities */ 463 464 /* Given a buffer of length 'len' return a malloc'ed string with its 465 * hex representation 466 */ 467 char * 468 hex_to_string(const unsigned char *buffer, long len) 469 { 470 char *tmp, *q; 471 const unsigned char *p; 472 int i; 473 static const char hexdig[] = "0123456789ABCDEF"; 474 475 if (len < 0) 476 return NULL; 477 if (len == 0) 478 return calloc(1, 1); 479 if ((tmp = calloc(len, 3)) == NULL) { 480 X509V3error(ERR_R_MALLOC_FAILURE); 481 return NULL; 482 } 483 q = tmp; 484 for (i = 0, p = buffer; i < len; i++, p++) { 485 *q++ = hexdig[(*p >> 4) & 0xf]; 486 *q++ = hexdig[*p & 0xf]; 487 *q++ = ':'; 488 } 489 q[-1] = 0; 490 return tmp; 491 } 492 LCRYPTO_ALIAS(hex_to_string); 493 494 /* Give a string of hex digits convert to 495 * a buffer 496 */ 497 498 unsigned char * 499 string_to_hex(const char *str, long *len) 500 { 501 unsigned char *hexbuf, *q; 502 unsigned char ch, cl, *p; 503 if (!str) { 504 X509V3error(X509V3_R_INVALID_NULL_ARGUMENT); 505 return NULL; 506 } 507 if (!(hexbuf = malloc(strlen(str) >> 1))) 508 goto err; 509 for (p = (unsigned char *)str, q = hexbuf; *p; ) { 510 ch = *p++; 511 if (ch == ':') 512 continue; 513 cl = *p++; 514 if (!cl) { 515 X509V3error(X509V3_R_ODD_NUMBER_OF_DIGITS); 516 free(hexbuf); 517 return NULL; 518 } 519 ch = tolower(ch); 520 cl = tolower(cl); 521 522 if ((ch >= '0') && (ch <= '9')) 523 ch -= '0'; 524 else if ((ch >= 'a') && (ch <= 'f')) 525 ch -= 'a' - 10; 526 else 527 goto badhex; 528 529 if ((cl >= '0') && (cl <= '9')) 530 cl -= '0'; 531 else if ((cl >= 'a') && (cl <= 'f')) 532 cl -= 'a' - 10; 533 else 534 goto badhex; 535 536 *q++ = (ch << 4) | cl; 537 } 538 539 if (len) 540 *len = q - hexbuf; 541 542 return hexbuf; 543 544 err: 545 free(hexbuf); 546 X509V3error(ERR_R_MALLOC_FAILURE); 547 return NULL; 548 549 badhex: 550 free(hexbuf); 551 X509V3error(X509V3_R_ILLEGAL_HEX_DIGIT); 552 return NULL; 553 } 554 LCRYPTO_ALIAS(string_to_hex); 555 556 /* V2I name comparison function: returns zero if 'name' matches 557 * cmp or cmp.* 558 */ 559 560 int 561 name_cmp(const char *name, const char *cmp) 562 { 563 int len, ret; 564 char c; 565 566 len = strlen(cmp); 567 if ((ret = strncmp(name, cmp, len))) 568 return ret; 569 c = name[len]; 570 if (!c || (c=='.')) 571 return 0; 572 return 1; 573 } 574 575 static int 576 sk_strcmp(const char * const *a, const char * const *b) 577 { 578 return strcmp(*a, *b); 579 } 580 581 STACK_OF(OPENSSL_STRING) * 582 X509_get1_email(X509 *x) 583 { 584 GENERAL_NAMES *gens; 585 STACK_OF(OPENSSL_STRING) *ret; 586 587 gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL); 588 ret = get_email(X509_get_subject_name(x), gens); 589 sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); 590 return ret; 591 } 592 LCRYPTO_ALIAS(X509_get1_email); 593 594 STACK_OF(OPENSSL_STRING) * 595 X509_get1_ocsp(X509 *x) 596 { 597 AUTHORITY_INFO_ACCESS *info; 598 STACK_OF(OPENSSL_STRING) *ret = NULL; 599 int i; 600 601 info = X509_get_ext_d2i(x, NID_info_access, NULL, NULL); 602 if (!info) 603 return NULL; 604 for (i = 0; i < sk_ACCESS_DESCRIPTION_num(info); i++) { 605 ACCESS_DESCRIPTION *ad = sk_ACCESS_DESCRIPTION_value(info, i); 606 if (OBJ_obj2nid(ad->method) == NID_ad_OCSP) { 607 if (ad->location->type == GEN_URI) { 608 if (!append_ia5(&ret, 609 ad->location->d.uniformResourceIdentifier)) 610 break; 611 } 612 } 613 } 614 AUTHORITY_INFO_ACCESS_free(info); 615 return ret; 616 } 617 LCRYPTO_ALIAS(X509_get1_ocsp); 618 619 STACK_OF(OPENSSL_STRING) * 620 X509_REQ_get1_email(X509_REQ *x) 621 { 622 GENERAL_NAMES *gens; 623 STACK_OF(X509_EXTENSION) *exts; 624 STACK_OF(OPENSSL_STRING) *ret; 625 626 exts = X509_REQ_get_extensions(x); 627 gens = X509V3_get_d2i(exts, NID_subject_alt_name, NULL, NULL); 628 ret = get_email(X509_REQ_get_subject_name(x), gens); 629 sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); 630 sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free); 631 return ret; 632 } 633 LCRYPTO_ALIAS(X509_REQ_get1_email); 634 635 636 static STACK_OF(OPENSSL_STRING) * 637 get_email(X509_NAME *name, GENERAL_NAMES *gens) 638 { 639 STACK_OF(OPENSSL_STRING) *ret = NULL; 640 X509_NAME_ENTRY *ne; 641 ASN1_IA5STRING *email; 642 GENERAL_NAME *gen; 643 int i; 644 645 /* Now add any email address(es) to STACK */ 646 i = -1; 647 648 /* First supplied X509_NAME */ 649 while ((i = X509_NAME_get_index_by_NID(name, 650 NID_pkcs9_emailAddress, i)) >= 0) { 651 ne = X509_NAME_get_entry(name, i); 652 email = X509_NAME_ENTRY_get_data(ne); 653 if (!append_ia5(&ret, email)) 654 return NULL; 655 } 656 for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) { 657 gen = sk_GENERAL_NAME_value(gens, i); 658 if (gen->type != GEN_EMAIL) 659 continue; 660 if (!append_ia5(&ret, gen->d.ia5)) 661 return NULL; 662 } 663 return ret; 664 } 665 666 static void 667 str_free(OPENSSL_STRING str) 668 { 669 free(str); 670 } 671 672 static int 673 append_ia5(STACK_OF(OPENSSL_STRING) **sk, ASN1_IA5STRING *email) 674 { 675 char *emtmp; 676 677 /* First some sanity checks */ 678 if (email->type != V_ASN1_IA5STRING) 679 return 1; 680 if (!email->data || !email->length) 681 return 1; 682 if (!*sk) 683 *sk = sk_OPENSSL_STRING_new(sk_strcmp); 684 if (!*sk) 685 return 0; 686 /* Don't add duplicates */ 687 if (sk_OPENSSL_STRING_find(*sk, (char *)email->data) != -1) 688 return 1; 689 emtmp = strdup((char *)email->data); 690 if (!emtmp || !sk_OPENSSL_STRING_push(*sk, emtmp)) { 691 X509_email_free(*sk); 692 *sk = NULL; 693 return 0; 694 } 695 return 1; 696 } 697 698 void 699 X509_email_free(STACK_OF(OPENSSL_STRING) *sk) 700 { 701 sk_OPENSSL_STRING_pop_free(sk, str_free); 702 } 703 LCRYPTO_ALIAS(X509_email_free); 704 705 typedef int (*equal_fn)(const unsigned char *pattern, size_t pattern_len, 706 const unsigned char *subject, size_t subject_len, unsigned int flags); 707 708 /* Skip pattern prefix to match "wildcard" subject */ 709 static void 710 skip_prefix(const unsigned char **p, size_t *plen, const unsigned char *subject, 711 size_t subject_len, unsigned int flags) 712 { 713 const unsigned char *pattern = *p; 714 size_t pattern_len = *plen; 715 716 /* 717 * If subject starts with a leading '.' followed by more octets, and 718 * pattern is longer, compare just an equal-length suffix with the 719 * full subject (starting at the '.'), provided the prefix contains 720 * no NULs. 721 */ 722 if ((flags & _X509_CHECK_FLAG_DOT_SUBDOMAINS) == 0) 723 return; 724 725 while (pattern_len > subject_len && *pattern) { 726 if ((flags & X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS) && 727 *pattern == '.') 728 break; 729 ++pattern; 730 --pattern_len; 731 } 732 733 /* Skip if entire prefix acceptable */ 734 if (pattern_len == subject_len) { 735 *p = pattern; 736 *plen = pattern_len; 737 } 738 } 739 740 /* 741 * Open/BoringSSL uses memcmp for "equal_case" while their 742 * "equal_nocase" function is a hand-rolled strncasecmp that does not 743 * allow \0 in the pattern. Since an embedded \0 is likely a sign of 744 * problems, we simply don't allow it in either case, and then we use 745 * standard libc functions. 746 */ 747 748 /* Compare using strncasecmp */ 749 static int 750 equal_nocase(const unsigned char *pattern, size_t pattern_len, 751 const unsigned char *subject, size_t subject_len, unsigned int flags) 752 { 753 if (memchr(pattern, '\0', pattern_len) != NULL) 754 return 0; 755 if (memchr(subject, '\0', subject_len) != NULL) 756 return 0; 757 skip_prefix(&pattern, &pattern_len, subject, subject_len, flags); 758 if (pattern_len != subject_len) 759 return 0; 760 return (strncasecmp(pattern, subject, pattern_len) == 0); 761 } 762 763 /* Compare using strncmp. */ 764 static int 765 equal_case(const unsigned char *pattern, size_t pattern_len, 766 const unsigned char *subject, size_t subject_len, unsigned int flags) 767 { 768 if (memchr(pattern, 0, pattern_len) != NULL) 769 return 0; 770 if (memchr(subject, 0, subject_len) != NULL) 771 return 0; 772 skip_prefix(&pattern, &pattern_len, subject, subject_len, flags); 773 if (pattern_len != subject_len) 774 return 0; 775 return (strncmp(pattern, subject, pattern_len) == 0); 776 } 777 778 /* 779 * RFC 5280, section 7.5, requires that only the domain is compared in a 780 * case-insensitive manner. 781 */ 782 static int 783 equal_email(const unsigned char *a, size_t a_len, const unsigned char *b, 784 size_t b_len, unsigned int unused_flags) 785 { 786 size_t pos = a_len; 787 if (a_len != b_len) 788 return 0; 789 /* 790 * We search backwards for the '@' character, so that we do not have to 791 * deal with quoted local-parts. The domain part is compared in a 792 * case-insensitive manner. 793 */ 794 while (pos > 0) { 795 pos--; 796 if (a[pos] == '@' || b[pos] == '@') { 797 if (!equal_nocase(a + pos, a_len - pos, b + pos, 798 a_len - pos, 0)) 799 return 0; 800 break; 801 } 802 } 803 if (pos == 0) 804 pos = a_len; 805 return equal_case(a, pos, b, pos, 0); 806 } 807 808 /* 809 * Compare the prefix and suffix with the subject, and check that the 810 * characters in-between are valid. 811 */ 812 static int 813 wildcard_match(const unsigned char *prefix, size_t prefix_len, 814 const unsigned char *suffix, size_t suffix_len, 815 const unsigned char *subject, size_t subject_len, unsigned int flags) 816 { 817 const unsigned char *wildcard_start; 818 const unsigned char *wildcard_end; 819 const unsigned char *p; 820 int allow_multi = 0; 821 int allow_idna = 0; 822 823 if (subject_len < prefix_len + suffix_len) 824 return 0; 825 if (!equal_nocase(prefix, prefix_len, subject, prefix_len, flags)) 826 return 0; 827 wildcard_start = subject + prefix_len; 828 wildcard_end = subject + (subject_len - suffix_len); 829 if (!equal_nocase(wildcard_end, suffix_len, suffix, suffix_len, flags)) 830 return 0; 831 /* 832 * If the wildcard makes up the entire first label, it must match at 833 * least one character. 834 */ 835 if (prefix_len == 0 && *suffix == '.') { 836 if (wildcard_start == wildcard_end) 837 return 0; 838 allow_idna = 1; 839 if (flags & X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS) 840 allow_multi = 1; 841 } 842 /* IDNA labels cannot match partial wildcards */ 843 if (!allow_idna && 844 subject_len >= 4 845 && strncasecmp((char *)subject, "xn--", 4) == 0) 846 return 0; 847 /* The wildcard may match a literal '*' */ 848 if (wildcard_end == wildcard_start + 1 && *wildcard_start == '*') 849 return 1; 850 /* 851 * Check that the part matched by the wildcard contains only 852 * permitted characters and only matches a single label unless 853 * allow_multi is set. 854 */ 855 for (p = wildcard_start; p != wildcard_end; ++p) 856 if (!(('0' <= *p && *p <= '9') || ('A' <= *p && *p <= 'Z') || 857 ('a' <= *p && *p <= 'z') || *p == '-' || 858 (allow_multi && *p == '.'))) 859 return 0; 860 return 1; 861 } 862 863 #define LABEL_START (1 << 0) 864 #define LABEL_END (1 << 1) 865 #define LABEL_HYPHEN (1 << 2) 866 #define LABEL_IDNA (1 << 3) 867 868 static const unsigned char * 869 valid_star(const unsigned char *p, size_t len, unsigned int flags) 870 { 871 const unsigned char *star = 0; 872 size_t i; 873 int state = LABEL_START; 874 int dots = 0; 875 for (i = 0; i < len; ++i) { 876 /* 877 * Locate first and only legal wildcard, either at the start 878 * or end of a non-IDNA first and not final label. 879 */ 880 if (p[i] == '*') { 881 int atstart = (state & LABEL_START); 882 int atend = (i == len - 1 || p[i + 1] == '.'); 883 /* 884 * At most one wildcard per pattern. 885 * No wildcards in IDNA labels. 886 * No wildcards after the first label. 887 */ 888 if (star != NULL || (state & LABEL_IDNA) != 0 || dots) 889 return NULL; 890 /* Only full-label '*.example.com' wildcards? */ 891 if ((flags & X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS) 892 && (!atstart || !atend)) 893 return NULL; 894 /* No 'foo*bar' wildcards */ 895 if (!atstart && !atend) 896 return NULL; 897 star = &p[i]; 898 state &= ~LABEL_START; 899 } else if ((state & LABEL_START) != 0) { 900 /* 901 * At the start of a label, skip any "xn--" and 902 * remain in the LABEL_START state, but set the 903 * IDNA label state 904 */ 905 if ((state & LABEL_IDNA) == 0 && len - i >= 4 906 && strncasecmp((char *)&p[i], "xn--", 4) == 0) { 907 i += 3; 908 state |= LABEL_IDNA; 909 continue; 910 } 911 /* Labels must start with a letter or digit */ 912 state &= ~LABEL_START; 913 if (('a' <= p[i] && p[i] <= 'z') 914 || ('A' <= p[i] && p[i] <= 'Z') 915 || ('0' <= p[i] && p[i] <= '9')) 916 continue; 917 return NULL; 918 } else if (('a' <= p[i] && p[i] <= 'z') 919 || ('A' <= p[i] && p[i] <= 'Z') 920 || ('0' <= p[i] && p[i] <= '9')) { 921 state &= LABEL_IDNA; 922 continue; 923 } else if (p[i] == '.') { 924 if (state & (LABEL_HYPHEN | LABEL_START)) 925 return NULL; 926 state = LABEL_START; 927 ++dots; 928 } else if (p[i] == '-') { 929 /* no domain/subdomain starts with '-' */ 930 if ((state & LABEL_START) != 0) 931 return NULL; 932 state |= LABEL_HYPHEN; 933 } else 934 return NULL; 935 } 936 937 /* 938 * The final label must not end in a hyphen or ".", and 939 * there must be at least two dots after the star. 940 */ 941 if ((state & (LABEL_START | LABEL_HYPHEN)) != 0 || dots < 2) 942 return NULL; 943 return star; 944 } 945 946 /* Compare using wildcards. */ 947 static int 948 equal_wildcard(const unsigned char *pattern, size_t pattern_len, 949 const unsigned char *subject, size_t subject_len, unsigned int flags) 950 { 951 const unsigned char *star = NULL; 952 953 /* 954 * Subject names starting with '.' can only match a wildcard pattern 955 * via a subject sub-domain pattern suffix match. 956 */ 957 if (!(subject_len > 1 && subject[0] == '.')) 958 star = valid_star(pattern, pattern_len, flags); 959 if (star == NULL) 960 return equal_nocase(pattern, pattern_len, 961 subject, subject_len, flags); 962 return wildcard_match(pattern, star - pattern, 963 star + 1, (pattern + pattern_len) - star - 1, 964 subject, subject_len, flags); 965 } 966 967 /* 968 * Compare an ASN1_STRING to a supplied string. If they match return 1. If 969 * cmp_type > 0 only compare if string matches the type, otherwise convert it 970 * to UTF8. 971 */ 972 973 static int 974 do_check_string(ASN1_STRING *a, int cmp_type, equal_fn equal, 975 unsigned int flags, const char *b, size_t blen, char **peername) 976 { 977 int rv = 0; 978 979 if (!a->data || !a->length) 980 return 0; 981 if (cmp_type > 0) { 982 if (cmp_type != a->type) 983 return 0; 984 if (cmp_type == V_ASN1_IA5STRING) 985 rv = equal(a->data, a->length, (unsigned char *)b, 986 blen, flags); 987 else if (a->length == (int)blen && !memcmp(a->data, b, blen)) 988 rv = 1; 989 if (rv > 0 && peername && 990 (*peername = strndup((char *)a->data, a->length)) == NULL) 991 rv = -1; 992 } else { 993 int astrlen; 994 unsigned char *astr = NULL; 995 astrlen = ASN1_STRING_to_UTF8(&astr, a); 996 if (astrlen < 0) 997 return -1; 998 rv = equal(astr, astrlen, (unsigned char *)b, blen, flags); 999 if (rv > 0 && peername && 1000 (*peername = strndup((char *)astr, astrlen)) == NULL) 1001 rv = -1; 1002 free(astr); 1003 } 1004 return rv; 1005 } 1006 1007 static int 1008 do_x509_check(X509 *x, const char *chk, size_t chklen, unsigned int flags, 1009 int check_type, char **peername) 1010 { 1011 GENERAL_NAMES *gens = NULL; 1012 X509_NAME *name = NULL; 1013 size_t i; 1014 int j; 1015 int cnid = NID_undef; 1016 int alt_type; 1017 int san_present = 0; 1018 int rv = 0; 1019 equal_fn equal; 1020 1021 /* See below, this flag is internal-only */ 1022 flags &= ~_X509_CHECK_FLAG_DOT_SUBDOMAINS; 1023 if (check_type == GEN_EMAIL) { 1024 cnid = NID_pkcs9_emailAddress; 1025 alt_type = V_ASN1_IA5STRING; 1026 equal = equal_email; 1027 } else if (check_type == GEN_DNS) { 1028 if (!(flags & X509_CHECK_FLAG_NEVER_CHECK_SUBJECT)) 1029 cnid = NID_commonName; 1030 /* Implicit client-side DNS sub-domain pattern */ 1031 if (chklen > 1 && chk[0] == '.') 1032 flags |= _X509_CHECK_FLAG_DOT_SUBDOMAINS; 1033 alt_type = V_ASN1_IA5STRING; 1034 if (flags & X509_CHECK_FLAG_NO_WILDCARDS) 1035 equal = equal_nocase; 1036 else 1037 equal = equal_wildcard; 1038 } else { 1039 alt_type = V_ASN1_OCTET_STRING; 1040 equal = equal_case; 1041 } 1042 1043 gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL); 1044 if (gens != NULL) { 1045 for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) { 1046 GENERAL_NAME *gen; 1047 ASN1_STRING *cstr; 1048 gen = sk_GENERAL_NAME_value(gens, i); 1049 if (gen->type != check_type) 1050 continue; 1051 san_present = 1; 1052 if (check_type == GEN_EMAIL) 1053 cstr = gen->d.rfc822Name; 1054 else if (check_type == GEN_DNS) 1055 cstr = gen->d.dNSName; 1056 else 1057 cstr = gen->d.iPAddress; 1058 /* Positive on success, negative on error! */ 1059 if ((rv = do_check_string(cstr, alt_type, equal, flags, 1060 chk, chklen, peername)) != 0) 1061 break; 1062 } 1063 GENERAL_NAMES_free(gens); 1064 if (rv != 0) 1065 return rv; 1066 if (cnid == NID_undef || 1067 (san_present && 1068 !(flags & X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT))) 1069 return 0; 1070 } 1071 1072 /* We're done if CN-ID is not pertinent */ 1073 if (cnid == NID_undef) 1074 return 0; 1075 1076 j = -1; 1077 name = X509_get_subject_name(x); 1078 while ((j = X509_NAME_get_index_by_NID(name, cnid, j)) >= 0) { 1079 X509_NAME_ENTRY *ne; 1080 ASN1_STRING *str; 1081 if ((ne = X509_NAME_get_entry(name, j)) == NULL) 1082 return -1; 1083 if ((str = X509_NAME_ENTRY_get_data(ne)) == NULL) 1084 return -1; 1085 /* Positive on success, negative on error! */ 1086 if ((rv = do_check_string(str, -1, equal, flags, 1087 chk, chklen, peername)) != 0) 1088 return rv; 1089 } 1090 return 0; 1091 } 1092 1093 int 1094 X509_check_host(X509 *x, const char *chk, size_t chklen, unsigned int flags, 1095 char **peername) 1096 { 1097 if (chk == NULL) 1098 return -2; 1099 if (chklen == 0) 1100 chklen = strlen(chk); 1101 else if (memchr(chk, '\0', chklen)) 1102 return -2; 1103 return do_x509_check(x, chk, chklen, flags, GEN_DNS, peername); 1104 } 1105 LCRYPTO_ALIAS(X509_check_host); 1106 1107 int 1108 X509_check_email(X509 *x, const char *chk, size_t chklen, unsigned int flags) 1109 { 1110 if (chk == NULL) 1111 return -2; 1112 if (chklen == 0) 1113 chklen = strlen(chk); 1114 else if (memchr(chk, '\0', chklen)) 1115 return -2; 1116 return do_x509_check(x, chk, chklen, flags, GEN_EMAIL, NULL); 1117 } 1118 LCRYPTO_ALIAS(X509_check_email); 1119 1120 int 1121 X509_check_ip(X509 *x, const unsigned char *chk, size_t chklen, 1122 unsigned int flags) 1123 { 1124 if (chk == NULL) 1125 return -2; 1126 return do_x509_check(x, (char *)chk, chklen, flags, GEN_IPADD, NULL); 1127 } 1128 LCRYPTO_ALIAS(X509_check_ip); 1129 1130 int 1131 X509_check_ip_asc(X509 *x, const char *ipasc, unsigned int flags) 1132 { 1133 unsigned char ipout[16]; 1134 size_t iplen; 1135 1136 if (ipasc == NULL) 1137 return -2; 1138 iplen = (size_t)a2i_ipadd(ipout, ipasc); 1139 if (iplen == 0) 1140 return -2; 1141 return do_x509_check(x, (char *)ipout, iplen, flags, GEN_IPADD, NULL); 1142 } 1143 LCRYPTO_ALIAS(X509_check_ip_asc); 1144 1145 /* Convert IP addresses both IPv4 and IPv6 into an 1146 * OCTET STRING compatible with RFC3280. 1147 */ 1148 1149 ASN1_OCTET_STRING * 1150 a2i_IPADDRESS(const char *ipasc) 1151 { 1152 unsigned char ipout[16]; 1153 ASN1_OCTET_STRING *ret; 1154 int iplen; 1155 1156 /* If string contains a ':' assume IPv6 */ 1157 1158 iplen = a2i_ipadd(ipout, ipasc); 1159 1160 if (!iplen) 1161 return NULL; 1162 1163 ret = ASN1_OCTET_STRING_new(); 1164 if (!ret) 1165 return NULL; 1166 if (!ASN1_OCTET_STRING_set(ret, ipout, iplen)) { 1167 ASN1_OCTET_STRING_free(ret); 1168 return NULL; 1169 } 1170 return ret; 1171 } 1172 LCRYPTO_ALIAS(a2i_IPADDRESS); 1173 1174 ASN1_OCTET_STRING * 1175 a2i_IPADDRESS_NC(const char *ipasc) 1176 { 1177 ASN1_OCTET_STRING *ret = NULL; 1178 unsigned char ipout[32]; 1179 char *iptmp = NULL, *p; 1180 int iplen1, iplen2; 1181 1182 p = strchr(ipasc, '/'); 1183 if (!p) 1184 return NULL; 1185 iptmp = strdup(ipasc); 1186 if (!iptmp) 1187 return NULL; 1188 p = iptmp + (p - ipasc); 1189 *p++ = 0; 1190 1191 iplen1 = a2i_ipadd(ipout, iptmp); 1192 1193 if (!iplen1) 1194 goto err; 1195 1196 iplen2 = a2i_ipadd(ipout + iplen1, p); 1197 1198 free(iptmp); 1199 iptmp = NULL; 1200 1201 if (!iplen2 || (iplen1 != iplen2)) 1202 goto err; 1203 1204 ret = ASN1_OCTET_STRING_new(); 1205 if (!ret) 1206 goto err; 1207 if (!ASN1_OCTET_STRING_set(ret, ipout, iplen1 + iplen2)) 1208 goto err; 1209 1210 return ret; 1211 1212 err: 1213 free(iptmp); 1214 if (ret) 1215 ASN1_OCTET_STRING_free(ret); 1216 return NULL; 1217 } 1218 LCRYPTO_ALIAS(a2i_IPADDRESS_NC); 1219 1220 1221 int 1222 a2i_ipadd(unsigned char *ipout, const char *ipasc) 1223 { 1224 /* If string contains a ':' assume IPv6 */ 1225 1226 if (strchr(ipasc, ':')) { 1227 if (!ipv6_from_asc(ipout, ipasc)) 1228 return 0; 1229 return 16; 1230 } else { 1231 if (!ipv4_from_asc(ipout, ipasc)) 1232 return 0; 1233 return 4; 1234 } 1235 } 1236 LCRYPTO_ALIAS(a2i_ipadd); 1237 1238 static int 1239 ipv4_from_asc(unsigned char *v4, const char *in) 1240 { 1241 int a0, a1, a2, a3; 1242 if (sscanf(in, "%d.%d.%d.%d", &a0, &a1, &a2, &a3) != 4) 1243 return 0; 1244 if ((a0 < 0) || (a0 > 255) || (a1 < 0) || (a1 > 255) || 1245 (a2 < 0) || (a2 > 255) || (a3 < 0) || (a3 > 255)) 1246 return 0; 1247 v4[0] = a0; 1248 v4[1] = a1; 1249 v4[2] = a2; 1250 v4[3] = a3; 1251 return 1; 1252 } 1253 1254 typedef struct { 1255 /* Temporary store for IPV6 output */ 1256 unsigned char tmp[16]; 1257 /* Total number of bytes in tmp */ 1258 int total; 1259 /* The position of a zero (corresponding to '::') */ 1260 int zero_pos; 1261 /* Number of zeroes */ 1262 int zero_cnt; 1263 } IPV6_STAT; 1264 1265 1266 static int 1267 ipv6_from_asc(unsigned char *v6, const char *in) 1268 { 1269 IPV6_STAT v6stat; 1270 1271 v6stat.total = 0; 1272 v6stat.zero_pos = -1; 1273 v6stat.zero_cnt = 0; 1274 1275 /* Treat the IPv6 representation as a list of values 1276 * separated by ':'. The presence of a '::' will parse 1277 * as one, two or three zero length elements. 1278 */ 1279 if (!CONF_parse_list(in, ':', 0, ipv6_cb, &v6stat)) 1280 return 0; 1281 1282 /* Now for some sanity checks */ 1283 1284 if (v6stat.zero_pos == -1) { 1285 /* If no '::' must have exactly 16 bytes */ 1286 if (v6stat.total != 16) 1287 return 0; 1288 } else { 1289 /* If '::' must have less than 16 bytes */ 1290 if (v6stat.total == 16) 1291 return 0; 1292 /* More than three zeroes is an error */ 1293 if (v6stat.zero_cnt > 3) 1294 return 0; 1295 /* Can only have three zeroes if nothing else present */ 1296 else if (v6stat.zero_cnt == 3) { 1297 if (v6stat.total > 0) 1298 return 0; 1299 } 1300 /* Can only have two zeroes if at start or end */ 1301 else if (v6stat.zero_cnt == 2) { 1302 if ((v6stat.zero_pos != 0) && 1303 (v6stat.zero_pos != v6stat.total)) 1304 return 0; 1305 } else 1306 /* Can only have one zero if *not* start or end */ 1307 { 1308 if ((v6stat.zero_pos == 0) || 1309 (v6stat.zero_pos == v6stat.total)) 1310 return 0; 1311 } 1312 } 1313 1314 /* Format result */ 1315 1316 if (v6stat.zero_pos >= 0) { 1317 /* Copy initial part */ 1318 memcpy(v6, v6stat.tmp, v6stat.zero_pos); 1319 /* Zero middle */ 1320 memset(v6 + v6stat.zero_pos, 0, 16 - v6stat.total); 1321 /* Copy final part */ 1322 if (v6stat.total != v6stat.zero_pos) 1323 memcpy(v6 + v6stat.zero_pos + 16 - v6stat.total, 1324 v6stat.tmp + v6stat.zero_pos, 1325 v6stat.total - v6stat.zero_pos); 1326 } else 1327 memcpy(v6, v6stat.tmp, 16); 1328 1329 return 1; 1330 } 1331 1332 static int 1333 ipv6_cb(const char *elem, int len, void *usr) 1334 { 1335 IPV6_STAT *s = usr; 1336 1337 /* Error if 16 bytes written */ 1338 if (s->total == 16) 1339 return 0; 1340 if (len == 0) { 1341 /* Zero length element, corresponds to '::' */ 1342 if (s->zero_pos == -1) 1343 s->zero_pos = s->total; 1344 /* If we've already got a :: its an error */ 1345 else if (s->zero_pos != s->total) 1346 return 0; 1347 s->zero_cnt++; 1348 } else { 1349 /* If more than 4 characters could be final a.b.c.d form */ 1350 if (len > 4) { 1351 /* Need at least 4 bytes left */ 1352 if (s->total > 12) 1353 return 0; 1354 /* Must be end of string */ 1355 if (elem[len]) 1356 return 0; 1357 if (!ipv4_from_asc(s->tmp + s->total, elem)) 1358 return 0; 1359 s->total += 4; 1360 } else { 1361 if (!ipv6_hex(s->tmp + s->total, elem, len)) 1362 return 0; 1363 s->total += 2; 1364 } 1365 } 1366 return 1; 1367 } 1368 1369 /* Convert a string of up to 4 hex digits into the corresponding 1370 * IPv6 form. 1371 */ 1372 1373 static int 1374 ipv6_hex(unsigned char *out, const char *in, int inlen) 1375 { 1376 unsigned char c; 1377 unsigned int num = 0; 1378 1379 if (inlen > 4) 1380 return 0; 1381 while (inlen--) { 1382 c = *in++; 1383 num <<= 4; 1384 if ((c >= '0') && (c <= '9')) 1385 num |= c - '0'; 1386 else if ((c >= 'A') && (c <= 'F')) 1387 num |= c - 'A' + 10; 1388 else if ((c >= 'a') && (c <= 'f')) 1389 num |= c - 'a' + 10; 1390 else 1391 return 0; 1392 } 1393 out[0] = num >> 8; 1394 out[1] = num & 0xff; 1395 return 1; 1396 } 1397 1398 int 1399 X509V3_NAME_from_section(X509_NAME *nm, STACK_OF(CONF_VALUE)*dn_sk, 1400 unsigned long chtype) 1401 { 1402 CONF_VALUE *v; 1403 int i, mval; 1404 char *p, *type; 1405 1406 if (!nm) 1407 return 0; 1408 1409 for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++) { 1410 v = sk_CONF_VALUE_value(dn_sk, i); 1411 type = v->name; 1412 /* Skip past any leading X. X: X, etc to allow for 1413 * multiple instances 1414 */ 1415 for (p = type; *p; p++) 1416 if ((*p == ':') || (*p == ',') || (*p == '.')) { 1417 p++; 1418 if (*p) 1419 type = p; 1420 break; 1421 } 1422 if (*type == '+') { 1423 mval = -1; 1424 type++; 1425 } else 1426 mval = 0; 1427 if (!X509_NAME_add_entry_by_txt(nm, type, chtype, 1428 (unsigned char *) v->value, -1, -1, mval)) 1429 return 0; 1430 } 1431 return 1; 1432 } 1433 LCRYPTO_ALIAS(X509V3_NAME_from_section); 1434