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