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