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