1 /* 2 * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the Apache License 2.0 (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10 /* 11 * This file is also used by the test suite. Do not #include "apps.h". 12 */ 13 #include "opt.h" 14 #include "fmt.h" 15 #include "app_libctx.h" 16 #include "internal/nelem.h" 17 #include "internal/numbers.h" 18 #include <string.h> 19 #if !defined(OPENSSL_SYS_MSDOS) 20 # include <unistd.h> 21 #endif 22 23 #include <stdlib.h> 24 #include <errno.h> 25 #include <ctype.h> 26 #include <limits.h> 27 #include <openssl/err.h> 28 #include <openssl/bio.h> 29 #include <openssl/x509v3.h> 30 31 #define MAX_OPT_HELP_WIDTH 30 32 const char OPT_HELP_STR[] = "-H"; 33 const char OPT_MORE_STR[] = "-M"; 34 const char OPT_SECTION_STR[] = "-S"; 35 const char OPT_PARAM_STR[] = "-P"; 36 37 /* Our state */ 38 static char **argv; 39 static int argc; 40 static int opt_index; 41 static char *arg; 42 static char *flag; 43 static char *dunno; 44 static const OPTIONS *unknown; 45 static const OPTIONS *opts; 46 static char prog[40]; 47 48 /* 49 * Return the simple name of the program; removing various platform gunk. 50 */ 51 #if defined(OPENSSL_SYS_WIN32) 52 53 const char *opt_path_end(const char *filename) 54 { 55 const char *p; 56 57 /* find the last '/', '\' or ':' */ 58 for (p = filename + strlen(filename); --p > filename; ) 59 if (*p == '/' || *p == '\\' || *p == ':') { 60 p++; 61 break; 62 } 63 return p; 64 } 65 66 char *opt_progname(const char *argv0) 67 { 68 size_t i, n; 69 const char *p; 70 char *q; 71 72 p = opt_path_end(argv0); 73 74 /* Strip off trailing nonsense. */ 75 n = strlen(p); 76 if (n > 4 && 77 (strcmp(&p[n - 4], ".exe") == 0 || strcmp(&p[n - 4], ".EXE") == 0)) 78 n -= 4; 79 80 /* Copy over the name, in lowercase. */ 81 if (n > sizeof(prog) - 1) 82 n = sizeof(prog) - 1; 83 for (q = prog, i = 0; i < n; i++, p++) 84 *q++ = tolower((unsigned char)*p); 85 *q = '\0'; 86 return prog; 87 } 88 89 #elif defined(OPENSSL_SYS_VMS) 90 91 const char *opt_path_end(const char *filename) 92 { 93 const char *p; 94 95 /* Find last special character sys:[foo.bar]openssl */ 96 for (p = filename + strlen(filename); --p > filename;) 97 if (*p == ':' || *p == ']' || *p == '>') { 98 p++; 99 break; 100 } 101 return p; 102 } 103 104 char *opt_progname(const char *argv0) 105 { 106 const char *p, *q; 107 108 /* Find last special character sys:[foo.bar]openssl */ 109 p = opt_path_end(argv0); 110 q = strrchr(p, '.'); 111 if (prog != p) 112 strncpy(prog, p, sizeof(prog) - 1); 113 prog[sizeof(prog) - 1] = '\0'; 114 if (q != NULL && q - p < sizeof(prog)) 115 prog[q - p] = '\0'; 116 return prog; 117 } 118 119 #else 120 121 const char *opt_path_end(const char *filename) 122 { 123 const char *p; 124 125 /* Could use strchr, but this is like the ones above. */ 126 for (p = filename + strlen(filename); --p > filename;) 127 if (*p == '/') { 128 p++; 129 break; 130 } 131 return p; 132 } 133 134 char *opt_progname(const char *argv0) 135 { 136 const char *p; 137 138 p = opt_path_end(argv0); 139 if (prog != p) 140 strncpy(prog, p, sizeof(prog) - 1); 141 prog[sizeof(prog) - 1] = '\0'; 142 return prog; 143 } 144 #endif 145 146 char *opt_appname(const char *argv0) 147 { 148 size_t len = strlen(prog); 149 150 if (argv0 != NULL) 151 BIO_snprintf(prog + len, sizeof(prog) - len - 1, " %s", argv0); 152 return prog; 153 } 154 155 char *opt_getprog(void) 156 { 157 return prog; 158 } 159 160 /* Set up the arg parsing. */ 161 char *opt_init(int ac, char **av, const OPTIONS *o) 162 { 163 /* Store state. */ 164 argc = ac; 165 argv = av; 166 opt_begin(); 167 opts = o; 168 unknown = NULL; 169 170 /* Make sure prog name is set for usage output */ 171 (void)opt_progname(argv[0]); 172 173 /* Check all options up until the PARAM marker (if present) */ 174 for (; o->name != NULL && o->name != OPT_PARAM_STR; ++o) { 175 #ifndef NDEBUG 176 const OPTIONS *next; 177 int duplicated, i; 178 #endif 179 180 if (o->name == OPT_HELP_STR 181 || o->name == OPT_MORE_STR 182 || o->name == OPT_SECTION_STR) 183 continue; 184 #ifndef NDEBUG 185 i = o->valtype; 186 187 /* Make sure options are legit. */ 188 OPENSSL_assert(o->name[0] != '-'); 189 if (o->valtype == '.') 190 OPENSSL_assert(o->retval == OPT_PARAM); 191 else 192 OPENSSL_assert(o->retval == OPT_DUP || o->retval > OPT_PARAM); 193 switch (i) { 194 case 0: case '-': case '.': 195 case '/': case '<': case '>': case 'E': case 'F': 196 case 'M': case 'U': case 'f': case 'l': case 'n': case 'p': case 's': 197 case 'u': case 'c': case ':': case 'N': 198 break; 199 default: 200 OPENSSL_assert(0); 201 } 202 203 /* Make sure there are no duplicates. */ 204 for (next = o + 1; next->name; ++next) { 205 /* 206 * Some compilers inline strcmp and the assert string is too long. 207 */ 208 duplicated = next->retval != OPT_DUP 209 && strcmp(o->name, next->name) == 0; 210 if (duplicated) { 211 opt_printf_stderr("%s: Internal error: duplicate option %s\n", 212 prog, o->name); 213 OPENSSL_assert(!duplicated); 214 } 215 } 216 #endif 217 if (o->name[0] == '\0') { 218 OPENSSL_assert(unknown == NULL); 219 unknown = o; 220 OPENSSL_assert(unknown->valtype == 0 || unknown->valtype == '-'); 221 } 222 } 223 return prog; 224 } 225 226 static OPT_PAIR formats[] = { 227 {"PEM/DER", OPT_FMT_PEMDER}, 228 {"pkcs12", OPT_FMT_PKCS12}, 229 {"smime", OPT_FMT_SMIME}, 230 {"engine", OPT_FMT_ENGINE}, 231 {"msblob", OPT_FMT_MSBLOB}, 232 {"nss", OPT_FMT_NSS}, 233 {"text", OPT_FMT_TEXT}, 234 {"http", OPT_FMT_HTTP}, 235 {"pvk", OPT_FMT_PVK}, 236 {NULL} 237 }; 238 239 /* Print an error message about a failed format parse. */ 240 static int opt_format_error(const char *s, unsigned long flags) 241 { 242 OPT_PAIR *ap; 243 244 if (flags == OPT_FMT_PEMDER) { 245 opt_printf_stderr("%s: Bad format \"%s\"; must be pem or der\n", 246 prog, s); 247 } else { 248 opt_printf_stderr("%s: Bad format \"%s\"; must be one of:\n", 249 prog, s); 250 for (ap = formats; ap->name; ap++) 251 if (flags & ap->retval) 252 opt_printf_stderr(" %s\n", ap->name); 253 } 254 return 0; 255 } 256 257 /* Parse a format string, put it into *result; return 0 on failure, else 1. */ 258 int opt_format(const char *s, unsigned long flags, int *result) 259 { 260 switch (*s) { 261 default: 262 opt_printf_stderr("%s: Bad format \"%s\"\n", prog, s); 263 return 0; 264 case 'D': 265 case 'd': 266 if ((flags & OPT_FMT_PEMDER) == 0) 267 return opt_format_error(s, flags); 268 *result = FORMAT_ASN1; 269 break; 270 case 'T': 271 case 't': 272 if ((flags & OPT_FMT_TEXT) == 0) 273 return opt_format_error(s, flags); 274 *result = FORMAT_TEXT; 275 break; 276 case 'N': 277 case 'n': 278 if ((flags & OPT_FMT_NSS) == 0) 279 return opt_format_error(s, flags); 280 if (strcmp(s, "NSS") != 0 && strcmp(s, "nss") != 0) 281 return opt_format_error(s, flags); 282 *result = FORMAT_NSS; 283 break; 284 case 'S': 285 case 's': 286 if ((flags & OPT_FMT_SMIME) == 0) 287 return opt_format_error(s, flags); 288 *result = FORMAT_SMIME; 289 break; 290 case 'M': 291 case 'm': 292 if ((flags & OPT_FMT_MSBLOB) == 0) 293 return opt_format_error(s, flags); 294 *result = FORMAT_MSBLOB; 295 break; 296 case 'E': 297 case 'e': 298 if ((flags & OPT_FMT_ENGINE) == 0) 299 return opt_format_error(s, flags); 300 *result = FORMAT_ENGINE; 301 break; 302 case 'H': 303 case 'h': 304 if ((flags & OPT_FMT_HTTP) == 0) 305 return opt_format_error(s, flags); 306 *result = FORMAT_HTTP; 307 break; 308 case '1': 309 if ((flags & OPT_FMT_PKCS12) == 0) 310 return opt_format_error(s, flags); 311 *result = FORMAT_PKCS12; 312 break; 313 case 'P': 314 case 'p': 315 if (s[1] == '\0' || strcmp(s, "PEM") == 0 || strcmp(s, "pem") == 0) { 316 if ((flags & OPT_FMT_PEMDER) == 0) 317 return opt_format_error(s, flags); 318 *result = FORMAT_PEM; 319 } else if (strcmp(s, "PVK") == 0 || strcmp(s, "pvk") == 0) { 320 if ((flags & OPT_FMT_PVK) == 0) 321 return opt_format_error(s, flags); 322 *result = FORMAT_PVK; 323 } else if (strcmp(s, "P12") == 0 || strcmp(s, "p12") == 0 324 || strcmp(s, "PKCS12") == 0 || strcmp(s, "pkcs12") == 0) { 325 if ((flags & OPT_FMT_PKCS12) == 0) 326 return opt_format_error(s, flags); 327 *result = FORMAT_PKCS12; 328 } else { 329 opt_printf_stderr("%s: Bad format \"%s\"\n", prog, s); 330 return 0; 331 } 332 break; 333 } 334 return 1; 335 } 336 337 /* Return string representing the given format. */ 338 static const char *format2str(int format) 339 { 340 switch (format) { 341 default: 342 return "(undefined)"; 343 case FORMAT_PEM: 344 return "PEM"; 345 case FORMAT_ASN1: 346 return "DER"; 347 case FORMAT_TEXT: 348 return "TEXT"; 349 case FORMAT_NSS: 350 return "NSS"; 351 case FORMAT_SMIME: 352 return "SMIME"; 353 case FORMAT_MSBLOB: 354 return "MSBLOB"; 355 case FORMAT_ENGINE: 356 return "ENGINE"; 357 case FORMAT_HTTP: 358 return "HTTP"; 359 case FORMAT_PKCS12: 360 return "P12"; 361 case FORMAT_PVK: 362 return "PVK"; 363 } 364 } 365 366 /* Print an error message about unsuitable/unsupported format requested. */ 367 void print_format_error(int format, unsigned long flags) 368 { 369 (void)opt_format_error(format2str(format), flags); 370 } 371 372 /* 373 * Parse a cipher name, put it in *cipherp after freeing what was there, if 374 * cipherp is not NULL. Return 0 on failure, else 1. 375 */ 376 int opt_cipher_silent(const char *name, EVP_CIPHER **cipherp) 377 { 378 EVP_CIPHER *c; 379 380 ERR_set_mark(); 381 if ((c = EVP_CIPHER_fetch(app_get0_libctx(), name, 382 app_get0_propq())) != NULL 383 || (opt_legacy_okay() 384 && (c = (EVP_CIPHER *)EVP_get_cipherbyname(name)) != NULL)) { 385 ERR_pop_to_mark(); 386 if (cipherp != NULL) { 387 EVP_CIPHER_free(*cipherp); 388 *cipherp = c; 389 } else { 390 EVP_CIPHER_free(c); 391 } 392 return 1; 393 } 394 ERR_clear_last_mark(); 395 return 0; 396 } 397 398 int opt_cipher_any(const char *name, EVP_CIPHER **cipherp) 399 { 400 int ret; 401 402 if ((ret = opt_cipher_silent(name, cipherp)) == 0) 403 opt_printf_stderr("%s: Unknown cipher: %s\n", prog, name); 404 return ret; 405 } 406 407 int opt_cipher(const char *name, EVP_CIPHER **cipherp) 408 { 409 int mode, ret = 0; 410 unsigned long int flags; 411 EVP_CIPHER *c = NULL; 412 413 if (opt_cipher_any(name, &c)) { 414 mode = EVP_CIPHER_get_mode(c); 415 flags = EVP_CIPHER_get_flags(c); 416 if (mode == EVP_CIPH_XTS_MODE) { 417 opt_printf_stderr("%s XTS ciphers not supported\n", prog); 418 } else if ((flags & EVP_CIPH_FLAG_AEAD_CIPHER) != 0) { 419 opt_printf_stderr("%s: AEAD ciphers not supported\n", prog); 420 } else { 421 ret = 1; 422 if (cipherp != NULL) 423 *cipherp = c; 424 } 425 } 426 return ret; 427 } 428 429 /* 430 * Parse message digest name, put it in *EVP_MD; return 0 on failure, else 1. 431 */ 432 int opt_md_silent(const char *name, EVP_MD **mdp) 433 { 434 EVP_MD *md; 435 436 ERR_set_mark(); 437 if ((md = EVP_MD_fetch(app_get0_libctx(), name, app_get0_propq())) != NULL 438 || (opt_legacy_okay() 439 && (md = (EVP_MD *)EVP_get_digestbyname(name)) != NULL)) { 440 ERR_pop_to_mark(); 441 if (mdp != NULL) { 442 EVP_MD_free(*mdp); 443 *mdp = md; 444 } else { 445 EVP_MD_free(md); 446 } 447 return 1; 448 } 449 ERR_clear_last_mark(); 450 return 0; 451 } 452 453 int opt_md(const char *name, EVP_MD **mdp) 454 { 455 int ret; 456 457 if ((ret = opt_md_silent(name, mdp)) == 0) 458 opt_printf_stderr("%s: Unknown option or message digest: %s\n", prog, 459 name != NULL ? name : "\"\""); 460 return ret; 461 } 462 463 /* Look through a list of name/value pairs. */ 464 int opt_pair(const char *name, const OPT_PAIR* pairs, int *result) 465 { 466 const OPT_PAIR *pp; 467 468 for (pp = pairs; pp->name; pp++) 469 if (strcmp(pp->name, name) == 0) { 470 *result = pp->retval; 471 return 1; 472 } 473 opt_printf_stderr("%s: Value must be one of:\n", prog); 474 for (pp = pairs; pp->name; pp++) 475 opt_printf_stderr("\t%s\n", pp->name); 476 return 0; 477 } 478 479 /* Look through a list of valid names */ 480 int opt_string(const char *name, const char **options) 481 { 482 const char **p; 483 484 for (p = options; *p != NULL; p++) 485 if (strcmp(*p, name) == 0) 486 return 1; 487 opt_printf_stderr("%s: Value must be one of:\n", prog); 488 for (p = options; *p != NULL; p++) 489 opt_printf_stderr("\t%s\n", *p); 490 return 0; 491 } 492 493 /* Parse an int, put it into *result; return 0 on failure, else 1. */ 494 int opt_int(const char *value, int *result) 495 { 496 long l; 497 498 if (!opt_long(value, &l)) 499 return 0; 500 *result = (int)l; 501 if (*result != l) { 502 opt_printf_stderr("%s: Value \"%s\" outside integer range\n", 503 prog, value); 504 return 0; 505 } 506 return 1; 507 } 508 509 /* Parse and return an integer, assuming range has been checked before. */ 510 int opt_int_arg(void) 511 { 512 int result = -1; 513 514 (void)opt_int(arg, &result); 515 return result; 516 } 517 518 static void opt_number_error(const char *v) 519 { 520 size_t i = 0; 521 struct strstr_pair_st { 522 char *prefix; 523 char *name; 524 } b[] = { 525 {"0x", "a hexadecimal"}, 526 {"0X", "a hexadecimal"}, 527 {"0", "an octal"} 528 }; 529 530 for (i = 0; i < OSSL_NELEM(b); i++) { 531 if (strncmp(v, b[i].prefix, strlen(b[i].prefix)) == 0) { 532 opt_printf_stderr("%s: Can't parse \"%s\" as %s number\n", 533 prog, v, b[i].name); 534 return; 535 } 536 } 537 opt_printf_stderr("%s: Can't parse \"%s\" as a number\n", prog, v); 538 return; 539 } 540 541 /* Parse a long, put it into *result; return 0 on failure, else 1. */ 542 int opt_long(const char *value, long *result) 543 { 544 int oerrno = errno; 545 long l; 546 char *endp; 547 548 errno = 0; 549 l = strtol(value, &endp, 0); 550 if (*endp 551 || endp == value 552 || ((l == LONG_MAX || l == LONG_MIN) && errno == ERANGE) 553 || (l == 0 && errno != 0)) { 554 opt_number_error(value); 555 errno = oerrno; 556 return 0; 557 } 558 *result = l; 559 errno = oerrno; 560 return 1; 561 } 562 563 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L && \ 564 defined(INTMAX_MAX) && defined(UINTMAX_MAX) && \ 565 !defined(OPENSSL_NO_INTTYPES_H) 566 567 /* Parse an intmax_t, put it into *result; return 0 on failure, else 1. */ 568 int opt_intmax(const char *value, ossl_intmax_t *result) 569 { 570 int oerrno = errno; 571 intmax_t m; 572 char *endp; 573 574 errno = 0; 575 m = strtoimax(value, &endp, 0); 576 if (*endp 577 || endp == value 578 || ((m == INTMAX_MAX || m == INTMAX_MIN) 579 && errno == ERANGE) 580 || (m == 0 && errno != 0)) { 581 opt_number_error(value); 582 errno = oerrno; 583 return 0; 584 } 585 /* Ensure that the value in |m| is never too big for |*result| */ 586 if (sizeof(m) > sizeof(*result) 587 && (m < OSSL_INTMAX_MIN || m > OSSL_INTMAX_MAX)) { 588 opt_number_error(value); 589 return 0; 590 } 591 *result = (ossl_intmax_t)m; 592 errno = oerrno; 593 return 1; 594 } 595 596 /* Parse a uintmax_t, put it into *result; return 0 on failure, else 1. */ 597 int opt_uintmax(const char *value, ossl_uintmax_t *result) 598 { 599 int oerrno = errno; 600 uintmax_t m; 601 char *endp; 602 603 errno = 0; 604 m = strtoumax(value, &endp, 0); 605 if (*endp 606 || endp == value 607 || (m == UINTMAX_MAX && errno == ERANGE) 608 || (m == 0 && errno != 0)) { 609 opt_number_error(value); 610 errno = oerrno; 611 return 0; 612 } 613 /* Ensure that the value in |m| is never too big for |*result| */ 614 if (sizeof(m) > sizeof(*result) 615 && m > OSSL_UINTMAX_MAX) { 616 opt_number_error(value); 617 return 0; 618 } 619 *result = (ossl_intmax_t)m; 620 errno = oerrno; 621 return 1; 622 } 623 #else 624 /* Fallback implementations based on long */ 625 int opt_intmax(const char *value, ossl_intmax_t *result) 626 { 627 long m; 628 int ret; 629 630 if ((ret = opt_long(value, &m))) 631 *result = m; 632 return ret; 633 } 634 635 int opt_uintmax(const char *value, ossl_uintmax_t *result) 636 { 637 unsigned long m; 638 int ret; 639 640 if ((ret = opt_ulong(value, &m))) 641 *result = m; 642 return ret; 643 } 644 #endif 645 646 /* 647 * Parse an unsigned long, put it into *result; return 0 on failure, else 1. 648 */ 649 int opt_ulong(const char *value, unsigned long *result) 650 { 651 int oerrno = errno; 652 char *endptr; 653 unsigned long l; 654 655 errno = 0; 656 l = strtoul(value, &endptr, 0); 657 if (*endptr 658 || endptr == value 659 || ((l == ULONG_MAX) && errno == ERANGE) 660 || (l == 0 && errno != 0)) { 661 opt_number_error(value); 662 errno = oerrno; 663 return 0; 664 } 665 *result = l; 666 errno = oerrno; 667 return 1; 668 } 669 670 /* 671 * We pass opt as an int but cast it to "enum range" so that all the 672 * items in the OPT_V_ENUM enumeration are caught; this makes -Wswitch 673 * in gcc do the right thing. 674 */ 675 enum range { OPT_V_ENUM }; 676 677 int opt_verify(int opt, X509_VERIFY_PARAM *vpm) 678 { 679 int i; 680 ossl_intmax_t t = 0; 681 ASN1_OBJECT *otmp; 682 X509_PURPOSE *xptmp; 683 const X509_VERIFY_PARAM *vtmp; 684 685 OPENSSL_assert(vpm != NULL); 686 OPENSSL_assert(opt > OPT_V__FIRST); 687 OPENSSL_assert(opt < OPT_V__LAST); 688 689 switch ((enum range)opt) { 690 case OPT_V__FIRST: 691 case OPT_V__LAST: 692 return 0; 693 case OPT_V_POLICY: 694 otmp = OBJ_txt2obj(opt_arg(), 0); 695 if (otmp == NULL) { 696 opt_printf_stderr("%s: Invalid Policy %s\n", prog, opt_arg()); 697 return 0; 698 } 699 X509_VERIFY_PARAM_add0_policy(vpm, otmp); 700 break; 701 case OPT_V_PURPOSE: 702 /* purpose name -> purpose index */ 703 i = X509_PURPOSE_get_by_sname(opt_arg()); 704 if (i < 0) { 705 opt_printf_stderr("%s: Invalid purpose %s\n", prog, opt_arg()); 706 return 0; 707 } 708 709 /* purpose index -> purpose object */ 710 xptmp = X509_PURPOSE_get0(i); 711 712 /* purpose object -> purpose value */ 713 i = X509_PURPOSE_get_id(xptmp); 714 715 if (!X509_VERIFY_PARAM_set_purpose(vpm, i)) { 716 opt_printf_stderr("%s: Internal error setting purpose %s\n", 717 prog, opt_arg()); 718 return 0; 719 } 720 break; 721 case OPT_V_VERIFY_NAME: 722 vtmp = X509_VERIFY_PARAM_lookup(opt_arg()); 723 if (vtmp == NULL) { 724 opt_printf_stderr("%s: Invalid verify name %s\n", 725 prog, opt_arg()); 726 return 0; 727 } 728 X509_VERIFY_PARAM_set1(vpm, vtmp); 729 break; 730 case OPT_V_VERIFY_DEPTH: 731 i = atoi(opt_arg()); 732 if (i >= 0) 733 X509_VERIFY_PARAM_set_depth(vpm, i); 734 break; 735 case OPT_V_VERIFY_AUTH_LEVEL: 736 i = atoi(opt_arg()); 737 if (i >= 0) 738 X509_VERIFY_PARAM_set_auth_level(vpm, i); 739 break; 740 case OPT_V_ATTIME: 741 if (!opt_intmax(opt_arg(), &t)) 742 return 0; 743 if (t != (time_t)t) { 744 opt_printf_stderr("%s: epoch time out of range %s\n", 745 prog, opt_arg()); 746 return 0; 747 } 748 X509_VERIFY_PARAM_set_time(vpm, (time_t)t); 749 break; 750 case OPT_V_VERIFY_HOSTNAME: 751 if (!X509_VERIFY_PARAM_set1_host(vpm, opt_arg(), 0)) 752 return 0; 753 break; 754 case OPT_V_VERIFY_EMAIL: 755 if (!X509_VERIFY_PARAM_set1_email(vpm, opt_arg(), 0)) 756 return 0; 757 break; 758 case OPT_V_VERIFY_IP: 759 if (!X509_VERIFY_PARAM_set1_ip_asc(vpm, opt_arg())) 760 return 0; 761 break; 762 case OPT_V_IGNORE_CRITICAL: 763 X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_IGNORE_CRITICAL); 764 break; 765 case OPT_V_ISSUER_CHECKS: 766 /* NOP, deprecated */ 767 break; 768 case OPT_V_CRL_CHECK: 769 X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_CRL_CHECK); 770 break; 771 case OPT_V_CRL_CHECK_ALL: 772 X509_VERIFY_PARAM_set_flags(vpm, 773 X509_V_FLAG_CRL_CHECK | 774 X509_V_FLAG_CRL_CHECK_ALL); 775 break; 776 case OPT_V_POLICY_CHECK: 777 X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_POLICY_CHECK); 778 break; 779 case OPT_V_EXPLICIT_POLICY: 780 X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_EXPLICIT_POLICY); 781 break; 782 case OPT_V_INHIBIT_ANY: 783 X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_INHIBIT_ANY); 784 break; 785 case OPT_V_INHIBIT_MAP: 786 X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_INHIBIT_MAP); 787 break; 788 case OPT_V_X509_STRICT: 789 X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_X509_STRICT); 790 break; 791 case OPT_V_EXTENDED_CRL: 792 X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_EXTENDED_CRL_SUPPORT); 793 break; 794 case OPT_V_USE_DELTAS: 795 X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_USE_DELTAS); 796 break; 797 case OPT_V_POLICY_PRINT: 798 X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_NOTIFY_POLICY); 799 break; 800 case OPT_V_CHECK_SS_SIG: 801 X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_CHECK_SS_SIGNATURE); 802 break; 803 case OPT_V_TRUSTED_FIRST: 804 X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_TRUSTED_FIRST); 805 break; 806 case OPT_V_SUITEB_128_ONLY: 807 X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_SUITEB_128_LOS_ONLY); 808 break; 809 case OPT_V_SUITEB_128: 810 X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_SUITEB_128_LOS); 811 break; 812 case OPT_V_SUITEB_192: 813 X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_SUITEB_192_LOS); 814 break; 815 case OPT_V_PARTIAL_CHAIN: 816 X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_PARTIAL_CHAIN); 817 break; 818 case OPT_V_NO_ALT_CHAINS: 819 X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_NO_ALT_CHAINS); 820 break; 821 case OPT_V_NO_CHECK_TIME: 822 X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_NO_CHECK_TIME); 823 break; 824 case OPT_V_ALLOW_PROXY_CERTS: 825 X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_ALLOW_PROXY_CERTS); 826 break; 827 } 828 return 1; 829 830 } 831 832 void opt_begin(void) 833 { 834 opt_index = 1; 835 arg = NULL; 836 flag = NULL; 837 } 838 839 /* 840 * Parse the next flag (and value if specified), return 0 if done, -1 on 841 * error, otherwise the flag's retval. 842 */ 843 int opt_next(void) 844 { 845 char *p; 846 const OPTIONS *o; 847 int ival; 848 long lval; 849 unsigned long ulval; 850 ossl_intmax_t imval; 851 ossl_uintmax_t umval; 852 853 /* Look at current arg; at end of the list? */ 854 arg = NULL; 855 p = argv[opt_index]; 856 if (p == NULL) 857 return 0; 858 859 /* If word doesn't start with a -, we're done. */ 860 if (*p != '-') 861 return 0; 862 863 /* Hit "--" ? We're done. */ 864 opt_index++; 865 if (strcmp(p, "--") == 0) 866 return 0; 867 868 /* Allow -nnn and --nnn */ 869 if (*++p == '-') 870 p++; 871 flag = p - 1; 872 873 /* If we have --flag=foo, snip it off */ 874 if ((arg = strchr(p, '=')) != NULL) 875 *arg++ = '\0'; 876 for (o = opts; o->name; ++o) { 877 /* If not this option, move on to the next one. */ 878 if (!(strcmp(p, "h") == 0 && strcmp(o->name, "help") == 0) 879 && strcmp(p, o->name) != 0) 880 continue; 881 882 /* If it doesn't take a value, make sure none was given. */ 883 if (o->valtype == 0 || o->valtype == '-') { 884 if (arg) { 885 opt_printf_stderr("%s: Option -%s does not take a value\n", 886 prog, p); 887 return -1; 888 } 889 return o->retval; 890 } 891 892 /* Want a value; get the next param if =foo not used. */ 893 if (arg == NULL) { 894 if (argv[opt_index] == NULL) { 895 opt_printf_stderr("%s: Option -%s needs a value\n", 896 prog, o->name); 897 return -1; 898 } 899 arg = argv[opt_index++]; 900 } 901 902 /* Syntax-check value. */ 903 switch (o->valtype) { 904 default: 905 case 's': 906 case ':': 907 /* Just a string. */ 908 break; 909 case '.': 910 /* Parameters */ 911 break; 912 case '/': 913 if (opt_isdir(arg) > 0) 914 break; 915 opt_printf_stderr("%s: Not a directory: %s\n", prog, arg); 916 return -1; 917 case '<': 918 /* Input file. */ 919 break; 920 case '>': 921 /* Output file. */ 922 break; 923 case 'p': 924 case 'n': 925 case 'N': 926 if (!opt_int(arg, &ival)) 927 return -1; 928 if (o->valtype == 'p' && ival <= 0) { 929 opt_printf_stderr("%s: Non-positive number \"%s\" for option -%s\n", 930 prog, arg, o->name); 931 return -1; 932 } 933 if (o->valtype == 'N' && ival < 0) { 934 opt_printf_stderr("%s: Negative number \"%s\" for option -%s\n", 935 prog, arg, o->name); 936 return -1; 937 } 938 break; 939 case 'M': 940 if (!opt_intmax(arg, &imval)) 941 return -1; 942 break; 943 case 'U': 944 if (!opt_uintmax(arg, &umval)) 945 return -1; 946 break; 947 case 'l': 948 if (!opt_long(arg, &lval)) 949 return -1; 950 break; 951 case 'u': 952 if (!opt_ulong(arg, &ulval)) 953 return -1; 954 break; 955 case 'c': 956 case 'E': 957 case 'F': 958 case 'f': 959 if (opt_format(arg, 960 o->valtype == 'c' ? OPT_FMT_PDS : 961 o->valtype == 'E' ? OPT_FMT_PDE : 962 o->valtype == 'F' ? OPT_FMT_PEMDER 963 : OPT_FMT_ANY, &ival)) 964 break; 965 opt_printf_stderr("%s: Invalid format \"%s\" for option -%s\n", 966 prog, arg, o->name); 967 return -1; 968 } 969 970 /* Return the flag value. */ 971 return o->retval; 972 } 973 if (unknown != NULL) { 974 dunno = p; 975 return unknown->retval; 976 } 977 opt_printf_stderr("%s: Unknown option: -%s\n", prog, p); 978 return -1; 979 } 980 981 /* Return the most recent flag parameter. */ 982 char *opt_arg(void) 983 { 984 return arg; 985 } 986 987 /* Return the most recent flag (option name including the preceding '-'). */ 988 char *opt_flag(void) 989 { 990 return flag; 991 } 992 993 /* Return the unknown option. */ 994 char *opt_unknown(void) 995 { 996 return dunno; 997 } 998 999 /* Return the rest of the arguments after parsing flags. */ 1000 char **opt_rest(void) 1001 { 1002 return &argv[opt_index]; 1003 } 1004 1005 /* How many items in remaining args? */ 1006 int opt_num_rest(void) 1007 { 1008 int i = 0; 1009 char **pp; 1010 1011 for (pp = opt_rest(); *pp; pp++, i++) 1012 continue; 1013 return i; 1014 } 1015 1016 /* Return a string describing the parameter type. */ 1017 static const char *valtype2param(const OPTIONS *o) 1018 { 1019 switch (o->valtype) { 1020 case 0: 1021 case '-': 1022 return ""; 1023 case ':': 1024 return "uri"; 1025 case 's': 1026 return "val"; 1027 case '/': 1028 return "dir"; 1029 case '<': 1030 return "infile"; 1031 case '>': 1032 return "outfile"; 1033 case 'p': 1034 return "+int"; 1035 case 'n': 1036 return "int"; 1037 case 'l': 1038 return "long"; 1039 case 'u': 1040 return "ulong"; 1041 case 'E': 1042 return "PEM|DER|ENGINE"; 1043 case 'F': 1044 return "PEM|DER"; 1045 case 'f': 1046 return "format"; 1047 case 'M': 1048 return "intmax"; 1049 case 'N': 1050 return "nonneg"; 1051 case 'U': 1052 return "uintmax"; 1053 } 1054 return "parm"; 1055 } 1056 1057 static void opt_print(const OPTIONS *o, int doingparams, int width) 1058 { 1059 const char* help; 1060 char start[80 + 1]; 1061 char *p; 1062 1063 help = o->helpstr ? o->helpstr : "(No additional info)"; 1064 if (o->name == OPT_HELP_STR) { 1065 opt_printf_stderr(help, prog); 1066 return; 1067 } 1068 if (o->name == OPT_SECTION_STR) { 1069 opt_printf_stderr("\n"); 1070 opt_printf_stderr(help, prog); 1071 return; 1072 } 1073 if (o->name == OPT_PARAM_STR) { 1074 opt_printf_stderr("\nParameters:\n"); 1075 return; 1076 } 1077 1078 /* Pad out prefix */ 1079 memset(start, ' ', sizeof(start) - 1); 1080 start[sizeof(start) - 1] = '\0'; 1081 1082 if (o->name == OPT_MORE_STR) { 1083 /* Continuation of previous line; pad and print. */ 1084 start[width] = '\0'; 1085 opt_printf_stderr("%s %s\n", start, help); 1086 return; 1087 } 1088 1089 /* Build up the "-flag [param]" part. */ 1090 p = start; 1091 *p++ = ' '; 1092 if (!doingparams) 1093 *p++ = '-'; 1094 if (o->name[0]) 1095 p += strlen(strcpy(p, o->name)); 1096 else 1097 *p++ = '*'; 1098 if (o->valtype != '-') { 1099 *p++ = ' '; 1100 p += strlen(strcpy(p, valtype2param(o))); 1101 } 1102 *p = ' '; 1103 if ((int)(p - start) >= MAX_OPT_HELP_WIDTH) { 1104 *p = '\0'; 1105 opt_printf_stderr("%s\n", start); 1106 memset(start, ' ', sizeof(start)); 1107 } 1108 start[width] = '\0'; 1109 opt_printf_stderr("%s %s\n", start, help); 1110 } 1111 1112 void opt_help(const OPTIONS *list) 1113 { 1114 const OPTIONS *o; 1115 int i, sawparams = 0, width = 5; 1116 int standard_prolog; 1117 char start[80 + 1]; 1118 1119 /* Starts with its own help message? */ 1120 standard_prolog = list[0].name != OPT_HELP_STR; 1121 1122 /* Find the widest help. */ 1123 for (o = list; o->name; o++) { 1124 if (o->name == OPT_MORE_STR) 1125 continue; 1126 i = 2 + (int)strlen(o->name); 1127 if (o->valtype != '-') 1128 i += 1 + strlen(valtype2param(o)); 1129 if (i < MAX_OPT_HELP_WIDTH && i > width) 1130 width = i; 1131 OPENSSL_assert(i < (int)sizeof(start)); 1132 } 1133 1134 if (standard_prolog) { 1135 opt_printf_stderr("Usage: %s [options]\n", prog); 1136 if (list[0].name != OPT_SECTION_STR) 1137 opt_printf_stderr("Valid options are:\n", prog); 1138 } 1139 1140 /* Now let's print. */ 1141 for (o = list; o->name; o++) { 1142 if (o->name == OPT_PARAM_STR) 1143 sawparams = 1; 1144 opt_print(o, sawparams, width); 1145 } 1146 } 1147 1148 /* opt_isdir section */ 1149 #ifdef _WIN32 1150 # include <windows.h> 1151 int opt_isdir(const char *name) 1152 { 1153 DWORD attr; 1154 # if defined(UNICODE) || defined(_UNICODE) 1155 size_t i, len_0 = strlen(name) + 1; 1156 WCHAR tempname[MAX_PATH]; 1157 1158 if (len_0 > MAX_PATH) 1159 return -1; 1160 1161 # if !defined(_WIN32_WCE) || _WIN32_WCE>=101 1162 if (!MultiByteToWideChar(CP_ACP, 0, name, len_0, tempname, MAX_PATH)) 1163 # endif 1164 for (i = 0; i < len_0; i++) 1165 tempname[i] = (WCHAR)name[i]; 1166 1167 attr = GetFileAttributes(tempname); 1168 # else 1169 attr = GetFileAttributes(name); 1170 # endif 1171 if (attr == INVALID_FILE_ATTRIBUTES) 1172 return -1; 1173 return ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0); 1174 } 1175 #else 1176 # include <sys/stat.h> 1177 # ifndef S_ISDIR 1178 # if defined(_S_IFMT) && defined(_S_IFDIR) 1179 # define S_ISDIR(a) (((a) & _S_IFMT) == _S_IFDIR) 1180 # else 1181 # define S_ISDIR(a) (((a) & S_IFMT) == S_IFDIR) 1182 # endif 1183 # endif 1184 1185 int opt_isdir(const char *name) 1186 { 1187 # if defined(S_ISDIR) 1188 struct stat st; 1189 1190 if (stat(name, &st) == 0) 1191 return S_ISDIR(st.st_mode); 1192 else 1193 return -1; 1194 # else 1195 return -1; 1196 # endif 1197 } 1198 #endif 1199