v3_utl.c revision 296465
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 <stdio.h> 62#include <ctype.h> 63#include "cryptlib.h" 64#include <openssl/conf.h> 65#include <openssl/x509v3.h> 66#include <openssl/bn.h> 67 68static char *strip_spaces(char *name); 69static int sk_strcmp(const char *const *a, const char *const *b); 70static STACK *get_email(X509_NAME *name, GENERAL_NAMES *gens); 71static void str_free(void *str); 72static int append_ia5(STACK ** sk, ASN1_IA5STRING *email); 73 74static int ipv4_from_asc(unsigned char *v4, const char *in); 75static int ipv6_from_asc(unsigned char *v6, const char *in); 76static int ipv6_cb(const char *elem, int len, void *usr); 77static int ipv6_hex(unsigned char *out, const char *in, int inlen); 78 79/* Add a CONF_VALUE name value pair to stack */ 80 81int X509V3_add_value(const char *name, const char *value, 82 STACK_OF(CONF_VALUE) **extlist) 83{ 84 CONF_VALUE *vtmp = NULL; 85 char *tname = NULL, *tvalue = NULL; 86 if (name && !(tname = BUF_strdup(name))) 87 goto err; 88 if (value && !(tvalue = BUF_strdup(value))) 89 goto err; 90 if (!(vtmp = (CONF_VALUE *)OPENSSL_malloc(sizeof(CONF_VALUE)))) 91 goto err; 92 if (!*extlist && !(*extlist = sk_CONF_VALUE_new_null())) 93 goto err; 94 vtmp->section = NULL; 95 vtmp->name = tname; 96 vtmp->value = tvalue; 97 if (!sk_CONF_VALUE_push(*extlist, vtmp)) 98 goto err; 99 return 1; 100 err: 101 X509V3err(X509V3_F_X509V3_ADD_VALUE, ERR_R_MALLOC_FAILURE); 102 if (vtmp) 103 OPENSSL_free(vtmp); 104 if (tname) 105 OPENSSL_free(tname); 106 if (tvalue) 107 OPENSSL_free(tvalue); 108 return 0; 109} 110 111int X509V3_add_value_uchar(const char *name, const unsigned char *value, 112 STACK_OF(CONF_VALUE) **extlist) 113{ 114 return X509V3_add_value(name, (const char *)value, extlist); 115} 116 117/* Free function for STACK_OF(CONF_VALUE) */ 118 119void X509V3_conf_free(CONF_VALUE *conf) 120{ 121 if (!conf) 122 return; 123 if (conf->name) 124 OPENSSL_free(conf->name); 125 if (conf->value) 126 OPENSSL_free(conf->value); 127 if (conf->section) 128 OPENSSL_free(conf->section); 129 OPENSSL_free(conf); 130} 131 132int X509V3_add_value_bool(const char *name, int asn1_bool, 133 STACK_OF(CONF_VALUE) **extlist) 134{ 135 if (asn1_bool) 136 return X509V3_add_value(name, "TRUE", extlist); 137 return X509V3_add_value(name, "FALSE", extlist); 138} 139 140int X509V3_add_value_bool_nf(char *name, int asn1_bool, 141 STACK_OF(CONF_VALUE) **extlist) 142{ 143 if (asn1_bool) 144 return X509V3_add_value(name, "TRUE", extlist); 145 return 1; 146} 147 148char *i2s_ASN1_ENUMERATED(X509V3_EXT_METHOD *method, ASN1_ENUMERATED *a) 149{ 150 BIGNUM *bntmp = NULL; 151 char *strtmp = NULL; 152 if (!a) 153 return NULL; 154 if (!(bntmp = ASN1_ENUMERATED_to_BN(a, NULL)) || 155 !(strtmp = BN_bn2dec(bntmp))) 156 X509V3err(X509V3_F_I2S_ASN1_ENUMERATED, ERR_R_MALLOC_FAILURE); 157 BN_free(bntmp); 158 return strtmp; 159} 160 161char *i2s_ASN1_INTEGER(X509V3_EXT_METHOD *method, ASN1_INTEGER *a) 162{ 163 BIGNUM *bntmp = NULL; 164 char *strtmp = NULL; 165 if (!a) 166 return NULL; 167 if (!(bntmp = ASN1_INTEGER_to_BN(a, NULL)) || 168 !(strtmp = BN_bn2dec(bntmp))) 169 X509V3err(X509V3_F_I2S_ASN1_INTEGER, ERR_R_MALLOC_FAILURE); 170 BN_free(bntmp); 171 return strtmp; 172} 173 174ASN1_INTEGER *s2i_ASN1_INTEGER(X509V3_EXT_METHOD *method, char *value) 175{ 176 BIGNUM *bn = NULL; 177 ASN1_INTEGER *aint; 178 int isneg, ishex; 179 int ret; 180 if (!value) { 181 X509V3err(X509V3_F_S2I_ASN1_INTEGER, X509V3_R_INVALID_NULL_VALUE); 182 return 0; 183 } 184 bn = BN_new(); 185 if (value[0] == '-') { 186 value++; 187 isneg = 1; 188 } else 189 isneg = 0; 190 191 if (value[0] == '0' && ((value[1] == 'x') || (value[1] == 'X'))) { 192 value += 2; 193 ishex = 1; 194 } else 195 ishex = 0; 196 197 if (ishex) 198 ret = BN_hex2bn(&bn, value); 199 else 200 ret = BN_dec2bn(&bn, value); 201 202 if (!ret || value[ret]) { 203 BN_free(bn); 204 X509V3err(X509V3_F_S2I_ASN1_INTEGER, X509V3_R_BN_DEC2BN_ERROR); 205 return 0; 206 } 207 208 if (isneg && BN_is_zero(bn)) 209 isneg = 0; 210 211 aint = BN_to_ASN1_INTEGER(bn, NULL); 212 BN_free(bn); 213 if (!aint) { 214 X509V3err(X509V3_F_S2I_ASN1_INTEGER, 215 X509V3_R_BN_TO_ASN1_INTEGER_ERROR); 216 return 0; 217 } 218 if (isneg) 219 aint->type |= V_ASN1_NEG; 220 return aint; 221} 222 223int X509V3_add_value_int(const char *name, ASN1_INTEGER *aint, 224 STACK_OF(CONF_VALUE) **extlist) 225{ 226 char *strtmp; 227 int ret; 228 if (!aint) 229 return 1; 230 if (!(strtmp = i2s_ASN1_INTEGER(NULL, aint))) 231 return 0; 232 ret = X509V3_add_value(name, strtmp, extlist); 233 OPENSSL_free(strtmp); 234 return ret; 235} 236 237int X509V3_get_value_bool(CONF_VALUE *value, int *asn1_bool) 238{ 239 char *btmp; 240 if (!(btmp = value->value)) 241 goto err; 242 if (!strcmp(btmp, "TRUE") || !strcmp(btmp, "true") 243 || !strcmp(btmp, "Y") || !strcmp(btmp, "y") 244 || !strcmp(btmp, "YES") || !strcmp(btmp, "yes")) { 245 *asn1_bool = 0xff; 246 return 1; 247 } else if (!strcmp(btmp, "FALSE") || !strcmp(btmp, "false") 248 || !strcmp(btmp, "N") || !strcmp(btmp, "n") 249 || !strcmp(btmp, "NO") || !strcmp(btmp, "no")) { 250 *asn1_bool = 0; 251 return 1; 252 } 253 err: 254 X509V3err(X509V3_F_X509V3_GET_VALUE_BOOL, 255 X509V3_R_INVALID_BOOLEAN_STRING); 256 X509V3_conf_err(value); 257 return 0; 258} 259 260int X509V3_get_value_int(CONF_VALUE *value, ASN1_INTEGER **aint) 261{ 262 ASN1_INTEGER *itmp; 263 if (!(itmp = s2i_ASN1_INTEGER(NULL, value->value))) { 264 X509V3_conf_err(value); 265 return 0; 266 } 267 *aint = itmp; 268 return 1; 269} 270 271#define HDR_NAME 1 272#define HDR_VALUE 2 273 274/* 275 * #define DEBUG 276 */ 277 278STACK_OF(CONF_VALUE) *X509V3_parse_list(const char *line) 279{ 280 char *p, *q, c; 281 char *ntmp, *vtmp; 282 STACK_OF(CONF_VALUE) *values = NULL; 283 char *linebuf; 284 int state; 285 /* We are going to modify the line so copy it first */ 286 linebuf = BUF_strdup(line); 287 state = HDR_NAME; 288 ntmp = NULL; 289 /* Go through all characters */ 290 for (p = linebuf, q = linebuf; (c = *p) && (c != '\r') && (c != '\n'); 291 p++) { 292 293 switch (state) { 294 case HDR_NAME: 295 if (c == ':') { 296 state = HDR_VALUE; 297 *p = 0; 298 ntmp = strip_spaces(q); 299 if (!ntmp) { 300 X509V3err(X509V3_F_X509V3_PARSE_LIST, 301 X509V3_R_INVALID_NULL_NAME); 302 goto err; 303 } 304 q = p + 1; 305 } else if (c == ',') { 306 *p = 0; 307 ntmp = strip_spaces(q); 308 q = p + 1; 309#if 0 310 printf("%s\n", ntmp); 311#endif 312 if (!ntmp) { 313 X509V3err(X509V3_F_X509V3_PARSE_LIST, 314 X509V3_R_INVALID_NULL_NAME); 315 goto err; 316 } 317 X509V3_add_value(ntmp, NULL, &values); 318 } 319 break; 320 321 case HDR_VALUE: 322 if (c == ',') { 323 state = HDR_NAME; 324 *p = 0; 325 vtmp = strip_spaces(q); 326#if 0 327 printf("%s\n", ntmp); 328#endif 329 if (!vtmp) { 330 X509V3err(X509V3_F_X509V3_PARSE_LIST, 331 X509V3_R_INVALID_NULL_VALUE); 332 goto err; 333 } 334 X509V3_add_value(ntmp, vtmp, &values); 335 ntmp = NULL; 336 q = p + 1; 337 } 338 339 } 340 } 341 342 if (state == HDR_VALUE) { 343 vtmp = strip_spaces(q); 344#if 0 345 printf("%s=%s\n", ntmp, vtmp); 346#endif 347 if (!vtmp) { 348 X509V3err(X509V3_F_X509V3_PARSE_LIST, 349 X509V3_R_INVALID_NULL_VALUE); 350 goto err; 351 } 352 X509V3_add_value(ntmp, vtmp, &values); 353 } else { 354 ntmp = strip_spaces(q); 355#if 0 356 printf("%s\n", ntmp); 357#endif 358 if (!ntmp) { 359 X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_NAME); 360 goto err; 361 } 362 X509V3_add_value(ntmp, NULL, &values); 363 } 364 OPENSSL_free(linebuf); 365 return values; 366 367 err: 368 OPENSSL_free(linebuf); 369 sk_CONF_VALUE_pop_free(values, X509V3_conf_free); 370 return NULL; 371 372} 373 374/* Delete leading and trailing spaces from a string */ 375static char *strip_spaces(char *name) 376{ 377 char *p, *q; 378 /* Skip over leading spaces */ 379 p = name; 380 while (*p && isspace((unsigned char)*p)) 381 p++; 382 if (!*p) 383 return NULL; 384 q = p + strlen(p) - 1; 385 while ((q != p) && isspace((unsigned char)*q)) 386 q--; 387 if (p != q) 388 q[1] = 0; 389 if (!*p) 390 return NULL; 391 return p; 392} 393 394/* hex string utilities */ 395 396/* 397 * Given a buffer of length 'len' return a OPENSSL_malloc'ed string with its 398 * hex representation @@@ (Contents of buffer are always kept in ASCII, also 399 * on EBCDIC machines) 400 */ 401 402char *hex_to_string(unsigned char *buffer, long len) 403{ 404 char *tmp, *q; 405 unsigned char *p; 406 int i; 407 const static char hexdig[] = "0123456789ABCDEF"; 408 if (!buffer || !len) 409 return NULL; 410 if (!(tmp = OPENSSL_malloc(len * 3 + 1))) { 411 X509V3err(X509V3_F_HEX_TO_STRING, ERR_R_MALLOC_FAILURE); 412 return NULL; 413 } 414 q = tmp; 415 for (i = 0, p = buffer; i < len; i++, p++) { 416 *q++ = hexdig[(*p >> 4) & 0xf]; 417 *q++ = hexdig[*p & 0xf]; 418 *q++ = ':'; 419 } 420 q[-1] = 0; 421#ifdef CHARSET_EBCDIC 422 ebcdic2ascii(tmp, tmp, q - tmp - 1); 423#endif 424 425 return tmp; 426} 427 428/* 429 * Give a string of hex digits convert to a buffer 430 */ 431 432unsigned char *string_to_hex(char *str, long *len) 433{ 434 unsigned char *hexbuf, *q; 435 unsigned char ch, cl, *p; 436 if (!str) { 437 X509V3err(X509V3_F_STRING_TO_HEX, X509V3_R_INVALID_NULL_ARGUMENT); 438 return NULL; 439 } 440 if (!(hexbuf = OPENSSL_malloc(strlen(str) >> 1))) 441 goto err; 442 for (p = (unsigned char *)str, q = hexbuf; *p;) { 443 ch = *p++; 444#ifdef CHARSET_EBCDIC 445 ch = os_toebcdic[ch]; 446#endif 447 if (ch == ':') 448 continue; 449 cl = *p++; 450#ifdef CHARSET_EBCDIC 451 cl = os_toebcdic[cl]; 452#endif 453 if (!cl) { 454 X509V3err(X509V3_F_STRING_TO_HEX, X509V3_R_ODD_NUMBER_OF_DIGITS); 455 OPENSSL_free(hexbuf); 456 return NULL; 457 } 458 if (isupper(ch)) 459 ch = tolower(ch); 460 if (isupper(cl)) 461 cl = tolower(cl); 462 463 if ((ch >= '0') && (ch <= '9')) 464 ch -= '0'; 465 else if ((ch >= 'a') && (ch <= 'f')) 466 ch -= 'a' - 10; 467 else 468 goto badhex; 469 470 if ((cl >= '0') && (cl <= '9')) 471 cl -= '0'; 472 else if ((cl >= 'a') && (cl <= 'f')) 473 cl -= 'a' - 10; 474 else 475 goto badhex; 476 477 *q++ = (ch << 4) | cl; 478 } 479 480 if (len) 481 *len = q - hexbuf; 482 483 return hexbuf; 484 485 err: 486 if (hexbuf) 487 OPENSSL_free(hexbuf); 488 X509V3err(X509V3_F_STRING_TO_HEX, ERR_R_MALLOC_FAILURE); 489 return NULL; 490 491 badhex: 492 OPENSSL_free(hexbuf); 493 X509V3err(X509V3_F_STRING_TO_HEX, X509V3_R_ILLEGAL_HEX_DIGIT); 494 return NULL; 495 496} 497 498/* 499 * V2I name comparison function: returns zero if 'name' matches cmp or cmp.* 500 */ 501 502int name_cmp(const char *name, const char *cmp) 503{ 504 int len, ret; 505 char c; 506 len = strlen(cmp); 507 if ((ret = strncmp(name, cmp, len))) 508 return ret; 509 c = name[len]; 510 if (!c || (c == '.')) 511 return 0; 512 return 1; 513} 514 515static int sk_strcmp(const char *const *a, const char *const *b) 516{ 517 return strcmp(*a, *b); 518} 519 520STACK *X509_get1_email(X509 *x) 521{ 522 GENERAL_NAMES *gens; 523 STACK *ret; 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 *X509_get1_ocsp(X509 *x) 531{ 532 AUTHORITY_INFO_ACCESS *info; 533 STACK *ret = NULL; 534 int i; 535 info = X509_get_ext_d2i(x, NID_info_access, NULL, NULL); 536 if (!info) 537 return NULL; 538 for (i = 0; i < sk_ACCESS_DESCRIPTION_num(info); i++) { 539 ACCESS_DESCRIPTION *ad = sk_ACCESS_DESCRIPTION_value(info, i); 540 if (OBJ_obj2nid(ad->method) == NID_ad_OCSP) { 541 if (ad->location->type == GEN_URI) { 542 if (!append_ia5 543 (&ret, ad->location->d.uniformResourceIdentifier)) 544 break; 545 } 546 } 547 } 548 AUTHORITY_INFO_ACCESS_free(info); 549 return ret; 550} 551 552STACK *X509_REQ_get1_email(X509_REQ *x) 553{ 554 GENERAL_NAMES *gens; 555 STACK_OF(X509_EXTENSION) *exts; 556 STACK *ret; 557 exts = X509_REQ_get_extensions(x); 558 gens = X509V3_get_d2i(exts, NID_subject_alt_name, NULL, NULL); 559 ret = get_email(X509_REQ_get_subject_name(x), gens); 560 sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); 561 sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free); 562 return ret; 563} 564 565static STACK *get_email(X509_NAME *name, GENERAL_NAMES *gens) 566{ 567 STACK *ret = NULL; 568 X509_NAME_ENTRY *ne; 569 ASN1_IA5STRING *email; 570 GENERAL_NAME *gen; 571 int i; 572 /* Now add any email address(es) to STACK */ 573 i = -1; 574 /* First supplied X509_NAME */ 575 while ((i = X509_NAME_get_index_by_NID(name, 576 NID_pkcs9_emailAddress, i)) >= 0) { 577 ne = X509_NAME_get_entry(name, i); 578 email = X509_NAME_ENTRY_get_data(ne); 579 if (!append_ia5(&ret, email)) 580 return NULL; 581 } 582 for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) { 583 gen = sk_GENERAL_NAME_value(gens, i); 584 if (gen->type != GEN_EMAIL) 585 continue; 586 if (!append_ia5(&ret, gen->d.ia5)) 587 return NULL; 588 } 589 return ret; 590} 591 592static void str_free(void *str) 593{ 594 OPENSSL_free(str); 595} 596 597static int append_ia5(STACK ** sk, ASN1_IA5STRING *email) 598{ 599 char *emtmp; 600 /* First some sanity checks */ 601 if (email->type != V_ASN1_IA5STRING) 602 return 1; 603 if (!email->data || !email->length) 604 return 1; 605 if (!*sk) 606 *sk = sk_new(sk_strcmp); 607 if (!*sk) 608 return 0; 609 /* Don't add duplicates */ 610 if (sk_find(*sk, (char *)email->data) != -1) 611 return 1; 612 emtmp = BUF_strdup((char *)email->data); 613 if (!emtmp || !sk_push(*sk, emtmp)) { 614 X509_email_free(*sk); 615 *sk = NULL; 616 return 0; 617 } 618 return 1; 619} 620 621void X509_email_free(STACK * sk) 622{ 623 sk_pop_free(sk, str_free); 624} 625 626/* 627 * Convert IP addresses both IPv4 and IPv6 into an OCTET STRING compatible 628 * with RFC3280. 629 */ 630 631ASN1_OCTET_STRING *a2i_IPADDRESS(const char *ipasc) 632{ 633 unsigned char ipout[16]; 634 ASN1_OCTET_STRING *ret; 635 int iplen; 636 637 /* If string contains a ':' assume IPv6 */ 638 639 iplen = a2i_ipadd(ipout, ipasc); 640 641 if (!iplen) 642 return NULL; 643 644 ret = ASN1_OCTET_STRING_new(); 645 if (!ret) 646 return NULL; 647 if (!ASN1_OCTET_STRING_set(ret, ipout, iplen)) { 648 ASN1_OCTET_STRING_free(ret); 649 return NULL; 650 } 651 return ret; 652} 653 654ASN1_OCTET_STRING *a2i_IPADDRESS_NC(const char *ipasc) 655{ 656 ASN1_OCTET_STRING *ret = NULL; 657 unsigned char ipout[32]; 658 char *iptmp = NULL, *p; 659 int iplen1, iplen2; 660 p = strchr(ipasc, '/'); 661 if (!p) 662 return NULL; 663 iptmp = BUF_strdup(ipasc); 664 if (!iptmp) 665 return NULL; 666 p = iptmp + (p - ipasc); 667 *p++ = 0; 668 669 iplen1 = a2i_ipadd(ipout, iptmp); 670 671 if (!iplen1) 672 goto err; 673 674 iplen2 = a2i_ipadd(ipout + iplen1, p); 675 676 OPENSSL_free(iptmp); 677 iptmp = NULL; 678 679 if (!iplen2 || (iplen1 != iplen2)) 680 goto err; 681 682 ret = ASN1_OCTET_STRING_new(); 683 if (!ret) 684 goto err; 685 if (!ASN1_OCTET_STRING_set(ret, ipout, iplen1 + iplen2)) 686 goto err; 687 688 return ret; 689 690 err: 691 if (iptmp) 692 OPENSSL_free(iptmp); 693 if (ret) 694 ASN1_OCTET_STRING_free(ret); 695 return NULL; 696} 697 698int a2i_ipadd(unsigned char *ipout, const char *ipasc) 699{ 700 /* If string contains a ':' assume IPv6 */ 701 702 if (strchr(ipasc, ':')) { 703 if (!ipv6_from_asc(ipout, ipasc)) 704 return 0; 705 return 16; 706 } else { 707 if (!ipv4_from_asc(ipout, ipasc)) 708 return 0; 709 return 4; 710 } 711} 712 713static int ipv4_from_asc(unsigned char *v4, const char *in) 714{ 715 int a0, a1, a2, a3; 716 if (sscanf(in, "%d.%d.%d.%d", &a0, &a1, &a2, &a3) != 4) 717 return 0; 718 if ((a0 < 0) || (a0 > 255) || (a1 < 0) || (a1 > 255) 719 || (a2 < 0) || (a2 > 255) || (a3 < 0) || (a3 > 255)) 720 return 0; 721 v4[0] = a0; 722 v4[1] = a1; 723 v4[2] = a2; 724 v4[3] = a3; 725 return 1; 726} 727 728typedef struct { 729 /* Temporary store for IPV6 output */ 730 unsigned char tmp[16]; 731 /* Total number of bytes in tmp */ 732 int total; 733 /* The position of a zero (corresponding to '::') */ 734 int zero_pos; 735 /* Number of zeroes */ 736 int zero_cnt; 737} IPV6_STAT; 738 739static int ipv6_from_asc(unsigned char *v6, const char *in) 740{ 741 IPV6_STAT v6stat; 742 v6stat.total = 0; 743 v6stat.zero_pos = -1; 744 v6stat.zero_cnt = 0; 745 /* 746 * Treat the IPv6 representation as a list of values separated by ':'. 747 * The presence of a '::' will parse as one, two or three zero length 748 * elements. 749 */ 750 if (!CONF_parse_list(in, ':', 0, ipv6_cb, &v6stat)) 751 return 0; 752 753 /* Now for some sanity checks */ 754 755 if (v6stat.zero_pos == -1) { 756 /* If no '::' must have exactly 16 bytes */ 757 if (v6stat.total != 16) 758 return 0; 759 } else { 760 /* If '::' must have less than 16 bytes */ 761 if (v6stat.total == 16) 762 return 0; 763 /* More than three zeroes is an error */ 764 if (v6stat.zero_cnt > 3) 765 return 0; 766 /* Can only have three zeroes if nothing else present */ 767 else if (v6stat.zero_cnt == 3) { 768 if (v6stat.total > 0) 769 return 0; 770 } 771 /* Can only have two zeroes if at start or end */ 772 else if (v6stat.zero_cnt == 2) { 773 if ((v6stat.zero_pos != 0) 774 && (v6stat.zero_pos != v6stat.total)) 775 return 0; 776 } else 777 /* Can only have one zero if *not* start or end */ 778 { 779 if ((v6stat.zero_pos == 0) 780 || (v6stat.zero_pos == v6stat.total)) 781 return 0; 782 } 783 } 784 785 /* Format result */ 786 787 if (v6stat.zero_pos >= 0) { 788 /* Copy initial part */ 789 memcpy(v6, v6stat.tmp, v6stat.zero_pos); 790 /* Zero middle */ 791 memset(v6 + v6stat.zero_pos, 0, 16 - v6stat.total); 792 /* Copy final part */ 793 if (v6stat.total != v6stat.zero_pos) 794 memcpy(v6 + v6stat.zero_pos + 16 - v6stat.total, 795 v6stat.tmp + v6stat.zero_pos, 796 v6stat.total - v6stat.zero_pos); 797 } else 798 memcpy(v6, v6stat.tmp, 16); 799 800 return 1; 801} 802 803static int ipv6_cb(const char *elem, int len, void *usr) 804{ 805 IPV6_STAT *s = usr; 806 /* Error if 16 bytes written */ 807 if (s->total == 16) 808 return 0; 809 if (len == 0) { 810 /* Zero length element, corresponds to '::' */ 811 if (s->zero_pos == -1) 812 s->zero_pos = s->total; 813 /* If we've already got a :: its an error */ 814 else if (s->zero_pos != s->total) 815 return 0; 816 s->zero_cnt++; 817 } else { 818 /* If more than 4 characters could be final a.b.c.d form */ 819 if (len > 4) { 820 /* Need at least 4 bytes left */ 821 if (s->total > 12) 822 return 0; 823 /* Must be end of string */ 824 if (elem[len]) 825 return 0; 826 if (!ipv4_from_asc(s->tmp + s->total, elem)) 827 return 0; 828 s->total += 4; 829 } else { 830 if (!ipv6_hex(s->tmp + s->total, elem, len)) 831 return 0; 832 s->total += 2; 833 } 834 } 835 return 1; 836} 837 838/* 839 * Convert a string of up to 4 hex digits into the corresponding IPv6 form. 840 */ 841 842static int ipv6_hex(unsigned char *out, const char *in, int inlen) 843{ 844 unsigned char c; 845 unsigned int num = 0; 846 if (inlen > 4) 847 return 0; 848 while (inlen--) { 849 c = *in++; 850 num <<= 4; 851 if ((c >= '0') && (c <= '9')) 852 num |= c - '0'; 853 else if ((c >= 'A') && (c <= 'F')) 854 num |= c - 'A' + 10; 855 else if ((c >= 'a') && (c <= 'f')) 856 num |= c - 'a' + 10; 857 else 858 return 0; 859 } 860 out[0] = num >> 8; 861 out[1] = num & 0xff; 862 return 1; 863} 864 865int X509V3_NAME_from_section(X509_NAME *nm, STACK_OF(CONF_VALUE) *dn_sk, 866 unsigned long chtype) 867{ 868 CONF_VALUE *v; 869 int i, mval; 870 char *p, *type; 871 if (!nm) 872 return 0; 873 874 for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++) { 875 v = sk_CONF_VALUE_value(dn_sk, i); 876 type = v->name; 877 /* 878 * Skip past any leading X. X: X, etc to allow for multiple instances 879 */ 880 for (p = type; *p; p++) 881#ifndef CHARSET_EBCDIC 882 if ((*p == ':') || (*p == ',') || (*p == '.')) 883#else 884 if ((*p == os_toascii[':']) || (*p == os_toascii[',']) 885 || (*p == os_toascii['.'])) 886#endif 887 { 888 p++; 889 if (*p) 890 type = p; 891 break; 892 } 893#ifndef CHARSET_EBCDIC 894 if (*type == '+') 895#else 896 if (*type == os_toascii['+']) 897#endif 898 { 899 mval = -1; 900 type++; 901 } else 902 mval = 0; 903 if (!X509_NAME_add_entry_by_txt(nm, type, chtype, 904 (unsigned char *)v->value, -1, -1, 905 mval)) 906 return 0; 907 908 } 909 return 1; 910} 911