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