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