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 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_uintmax_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 if (!X509_VERIFY_PARAM_add0_policy(vpm, otmp)) { 700 ASN1_OBJECT_free(otmp); 701 opt_printf_stderr("%s: Internal error adding Policy %s\n", 702 prog, opt_arg()); 703 return 0; 704 } 705 break; 706 case OPT_V_PURPOSE: 707 /* purpose name -> purpose index */ 708 i = X509_PURPOSE_get_by_sname(opt_arg()); 709 if (i < 0) { 710 opt_printf_stderr("%s: Invalid purpose %s\n", prog, opt_arg()); 711 return 0; 712 } 713 714 /* purpose index -> purpose object */ 715 xptmp = X509_PURPOSE_get0(i); 716 717 /* purpose object -> purpose value */ 718 i = X509_PURPOSE_get_id(xptmp); 719 720 if (!X509_VERIFY_PARAM_set_purpose(vpm, i)) { 721 opt_printf_stderr("%s: Internal error setting purpose %s\n", 722 prog, opt_arg()); 723 return 0; 724 } 725 break; 726 case OPT_V_VERIFY_NAME: 727 vtmp = X509_VERIFY_PARAM_lookup(opt_arg()); 728 if (vtmp == NULL) { 729 opt_printf_stderr("%s: Invalid verify name %s\n", 730 prog, opt_arg()); 731 return 0; 732 } 733 X509_VERIFY_PARAM_set1(vpm, vtmp); 734 break; 735 case OPT_V_VERIFY_DEPTH: 736 i = atoi(opt_arg()); 737 if (i >= 0) 738 X509_VERIFY_PARAM_set_depth(vpm, i); 739 break; 740 case OPT_V_VERIFY_AUTH_LEVEL: 741 i = atoi(opt_arg()); 742 if (i >= 0) 743 X509_VERIFY_PARAM_set_auth_level(vpm, i); 744 break; 745 case OPT_V_ATTIME: 746 if (!opt_intmax(opt_arg(), &t)) 747 return 0; 748 if (t != (time_t)t) { 749 opt_printf_stderr("%s: epoch time out of range %s\n", 750 prog, opt_arg()); 751 return 0; 752 } 753 X509_VERIFY_PARAM_set_time(vpm, (time_t)t); 754 break; 755 case OPT_V_VERIFY_HOSTNAME: 756 if (!X509_VERIFY_PARAM_set1_host(vpm, opt_arg(), 0)) 757 return 0; 758 break; 759 case OPT_V_VERIFY_EMAIL: 760 if (!X509_VERIFY_PARAM_set1_email(vpm, opt_arg(), 0)) 761 return 0; 762 break; 763 case OPT_V_VERIFY_IP: 764 if (!X509_VERIFY_PARAM_set1_ip_asc(vpm, opt_arg())) 765 return 0; 766 break; 767 case OPT_V_IGNORE_CRITICAL: 768 X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_IGNORE_CRITICAL); 769 break; 770 case OPT_V_ISSUER_CHECKS: 771 /* NOP, deprecated */ 772 break; 773 case OPT_V_CRL_CHECK: 774 X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_CRL_CHECK); 775 break; 776 case OPT_V_CRL_CHECK_ALL: 777 X509_VERIFY_PARAM_set_flags(vpm, 778 X509_V_FLAG_CRL_CHECK | 779 X509_V_FLAG_CRL_CHECK_ALL); 780 break; 781 case OPT_V_POLICY_CHECK: 782 X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_POLICY_CHECK); 783 break; 784 case OPT_V_EXPLICIT_POLICY: 785 X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_EXPLICIT_POLICY); 786 break; 787 case OPT_V_INHIBIT_ANY: 788 X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_INHIBIT_ANY); 789 break; 790 case OPT_V_INHIBIT_MAP: 791 X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_INHIBIT_MAP); 792 break; 793 case OPT_V_X509_STRICT: 794 X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_X509_STRICT); 795 break; 796 case OPT_V_EXTENDED_CRL: 797 X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_EXTENDED_CRL_SUPPORT); 798 break; 799 case OPT_V_USE_DELTAS: 800 X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_USE_DELTAS); 801 break; 802 case OPT_V_POLICY_PRINT: 803 X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_NOTIFY_POLICY); 804 break; 805 case OPT_V_CHECK_SS_SIG: 806 X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_CHECK_SS_SIGNATURE); 807 break; 808 case OPT_V_TRUSTED_FIRST: 809 X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_TRUSTED_FIRST); 810 break; 811 case OPT_V_SUITEB_128_ONLY: 812 X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_SUITEB_128_LOS_ONLY); 813 break; 814 case OPT_V_SUITEB_128: 815 X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_SUITEB_128_LOS); 816 break; 817 case OPT_V_SUITEB_192: 818 X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_SUITEB_192_LOS); 819 break; 820 case OPT_V_PARTIAL_CHAIN: 821 X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_PARTIAL_CHAIN); 822 break; 823 case OPT_V_NO_ALT_CHAINS: 824 X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_NO_ALT_CHAINS); 825 break; 826 case OPT_V_NO_CHECK_TIME: 827 X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_NO_CHECK_TIME); 828 break; 829 case OPT_V_ALLOW_PROXY_CERTS: 830 X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_ALLOW_PROXY_CERTS); 831 break; 832 } 833 return 1; 834 835 } 836 837 void opt_begin(void) 838 { 839 opt_index = 1; 840 arg = NULL; 841 flag = NULL; 842 } 843 844 /* 845 * Parse the next flag (and value if specified), return 0 if done, -1 on 846 * error, otherwise the flag's retval. 847 */ 848 int opt_next(void) 849 { 850 char *p; 851 const OPTIONS *o; 852 int ival; 853 long lval; 854 unsigned long ulval; 855 ossl_intmax_t imval; 856 ossl_uintmax_t umval; 857 858 /* Look at current arg; at end of the list? */ 859 arg = NULL; 860 p = argv[opt_index]; 861 if (p == NULL) 862 return 0; 863 864 /* If word doesn't start with a -, we're done. */ 865 if (*p != '-') 866 return 0; 867 868 /* Hit "--" ? We're done. */ 869 opt_index++; 870 if (strcmp(p, "--") == 0) 871 return 0; 872 873 /* Allow -nnn and --nnn */ 874 if (*++p == '-') 875 p++; 876 flag = p - 1; 877 878 /* If we have --flag=foo, snip it off */ 879 if ((arg = strchr(p, '=')) != NULL) 880 *arg++ = '\0'; 881 for (o = opts; o->name; ++o) { 882 /* If not this option, move on to the next one. */ 883 if (!(strcmp(p, "h") == 0 && strcmp(o->name, "help") == 0) 884 && strcmp(p, o->name) != 0) 885 continue; 886 887 /* If it doesn't take a value, make sure none was given. */ 888 if (o->valtype == 0 || o->valtype == '-') { 889 if (arg) { 890 opt_printf_stderr("%s: Option -%s does not take a value\n", 891 prog, p); 892 return -1; 893 } 894 return o->retval; 895 } 896 897 /* Want a value; get the next param if =foo not used. */ 898 if (arg == NULL) { 899 if (argv[opt_index] == NULL) { 900 opt_printf_stderr("%s: Option -%s needs a value\n", 901 prog, o->name); 902 return -1; 903 } 904 arg = argv[opt_index++]; 905 } 906 907 /* Syntax-check value. */ 908 switch (o->valtype) { 909 default: 910 case 's': 911 case ':': 912 /* Just a string. */ 913 break; 914 case '.': 915 /* Parameters */ 916 break; 917 case '/': 918 if (opt_isdir(arg) > 0) 919 break; 920 opt_printf_stderr("%s: Not a directory: %s\n", prog, arg); 921 return -1; 922 case '<': 923 /* Input file. */ 924 break; 925 case '>': 926 /* Output file. */ 927 break; 928 case 'p': 929 case 'n': 930 case 'N': 931 if (!opt_int(arg, &ival)) 932 return -1; 933 if (o->valtype == 'p' && ival <= 0) { 934 opt_printf_stderr("%s: Non-positive number \"%s\" for option -%s\n", 935 prog, arg, o->name); 936 return -1; 937 } 938 if (o->valtype == 'N' && ival < 0) { 939 opt_printf_stderr("%s: Negative number \"%s\" for option -%s\n", 940 prog, arg, o->name); 941 return -1; 942 } 943 break; 944 case 'M': 945 if (!opt_intmax(arg, &imval)) 946 return -1; 947 break; 948 case 'U': 949 if (!opt_uintmax(arg, &umval)) 950 return -1; 951 break; 952 case 'l': 953 if (!opt_long(arg, &lval)) 954 return -1; 955 break; 956 case 'u': 957 if (!opt_ulong(arg, &ulval)) 958 return -1; 959 break; 960 case 'c': 961 case 'E': 962 case 'F': 963 case 'f': 964 if (opt_format(arg, 965 o->valtype == 'c' ? OPT_FMT_PDS : 966 o->valtype == 'E' ? OPT_FMT_PDE : 967 o->valtype == 'F' ? OPT_FMT_PEMDER 968 : OPT_FMT_ANY, &ival)) 969 break; 970 opt_printf_stderr("%s: Invalid format \"%s\" for option -%s\n", 971 prog, arg, o->name); 972 return -1; 973 } 974 975 /* Return the flag value. */ 976 return o->retval; 977 } 978 if (unknown != NULL) { 979 dunno = p; 980 return unknown->retval; 981 } 982 opt_printf_stderr("%s: Unknown option: -%s\n", prog, p); 983 return -1; 984 } 985 986 /* Return the most recent flag parameter. */ 987 char *opt_arg(void) 988 { 989 return arg; 990 } 991 992 /* Return the most recent flag (option name including the preceding '-'). */ 993 char *opt_flag(void) 994 { 995 return flag; 996 } 997 998 /* Return the unknown option. */ 999 char *opt_unknown(void) 1000 { 1001 return dunno; 1002 } 1003 1004 /* Return the rest of the arguments after parsing flags. */ 1005 char **opt_rest(void) 1006 { 1007 return &argv[opt_index]; 1008 } 1009 1010 /* How many items in remaining args? */ 1011 int opt_num_rest(void) 1012 { 1013 int i = 0; 1014 char **pp; 1015 1016 for (pp = opt_rest(); *pp; pp++, i++) 1017 continue; 1018 return i; 1019 } 1020 1021 /* Return a string describing the parameter type. */ 1022 static const char *valtype2param(const OPTIONS *o) 1023 { 1024 switch (o->valtype) { 1025 case 0: 1026 case '-': 1027 return ""; 1028 case ':': 1029 return "uri"; 1030 case 's': 1031 return "val"; 1032 case '/': 1033 return "dir"; 1034 case '<': 1035 return "infile"; 1036 case '>': 1037 return "outfile"; 1038 case 'p': 1039 return "+int"; 1040 case 'n': 1041 return "int"; 1042 case 'l': 1043 return "long"; 1044 case 'u': 1045 return "ulong"; 1046 case 'E': 1047 return "PEM|DER|ENGINE"; 1048 case 'F': 1049 return "PEM|DER"; 1050 case 'f': 1051 return "format"; 1052 case 'M': 1053 return "intmax"; 1054 case 'N': 1055 return "nonneg"; 1056 case 'U': 1057 return "uintmax"; 1058 } 1059 return "parm"; 1060 } 1061 1062 static void opt_print(const OPTIONS *o, int doingparams, int width) 1063 { 1064 const char* help; 1065 char start[80 + 1]; 1066 char *p; 1067 1068 help = o->helpstr ? o->helpstr : "(No additional info)"; 1069 if (o->name == OPT_HELP_STR) { 1070 opt_printf_stderr(help, prog); 1071 return; 1072 } 1073 if (o->name == OPT_SECTION_STR) { 1074 opt_printf_stderr("\n"); 1075 opt_printf_stderr(help, prog); 1076 return; 1077 } 1078 if (o->name == OPT_PARAM_STR) { 1079 opt_printf_stderr("\nParameters:\n"); 1080 return; 1081 } 1082 1083 /* Pad out prefix */ 1084 memset(start, ' ', sizeof(start) - 1); 1085 start[sizeof(start) - 1] = '\0'; 1086 1087 if (o->name == OPT_MORE_STR) { 1088 /* Continuation of previous line; pad and print. */ 1089 start[width] = '\0'; 1090 opt_printf_stderr("%s %s\n", start, help); 1091 return; 1092 } 1093 1094 /* Build up the "-flag [param]" part. */ 1095 p = start; 1096 *p++ = ' '; 1097 if (!doingparams) 1098 *p++ = '-'; 1099 if (o->name[0]) 1100 p += strlen(strcpy(p, o->name)); 1101 else 1102 *p++ = '*'; 1103 if (o->valtype != '-') { 1104 *p++ = ' '; 1105 p += strlen(strcpy(p, valtype2param(o))); 1106 } 1107 *p = ' '; 1108 if ((int)(p - start) >= MAX_OPT_HELP_WIDTH) { 1109 *p = '\0'; 1110 opt_printf_stderr("%s\n", start); 1111 memset(start, ' ', sizeof(start)); 1112 } 1113 start[width] = '\0'; 1114 opt_printf_stderr("%s %s\n", start, help); 1115 } 1116 1117 void opt_help(const OPTIONS *list) 1118 { 1119 const OPTIONS *o; 1120 int i, sawparams = 0, width = 5; 1121 int standard_prolog; 1122 char start[80 + 1]; 1123 1124 /* Starts with its own help message? */ 1125 standard_prolog = list[0].name != OPT_HELP_STR; 1126 1127 /* Find the widest help. */ 1128 for (o = list; o->name; o++) { 1129 if (o->name == OPT_MORE_STR) 1130 continue; 1131 i = 2 + (int)strlen(o->name); 1132 if (o->valtype != '-') 1133 i += 1 + strlen(valtype2param(o)); 1134 if (i < MAX_OPT_HELP_WIDTH && i > width) 1135 width = i; 1136 OPENSSL_assert(i < (int)sizeof(start)); 1137 } 1138 1139 if (standard_prolog) { 1140 opt_printf_stderr("Usage: %s [options]\n", prog); 1141 if (list[0].name != OPT_SECTION_STR) 1142 opt_printf_stderr("Valid options are:\n", prog); 1143 } 1144 1145 /* Now let's print. */ 1146 for (o = list; o->name; o++) { 1147 if (o->name == OPT_PARAM_STR) 1148 sawparams = 1; 1149 opt_print(o, sawparams, width); 1150 } 1151 } 1152 1153 /* opt_isdir section */ 1154 #ifdef _WIN32 1155 # include <windows.h> 1156 int opt_isdir(const char *name) 1157 { 1158 DWORD attr; 1159 # if defined(UNICODE) || defined(_UNICODE) 1160 size_t i, len_0 = strlen(name) + 1; 1161 WCHAR tempname[MAX_PATH]; 1162 1163 if (len_0 > MAX_PATH) 1164 return -1; 1165 1166 # if !defined(_WIN32_WCE) || _WIN32_WCE>=101 1167 if (!MultiByteToWideChar(CP_ACP, 0, name, len_0, tempname, MAX_PATH)) 1168 # endif 1169 for (i = 0; i < len_0; i++) 1170 tempname[i] = (WCHAR)name[i]; 1171 1172 attr = GetFileAttributes(tempname); 1173 # else 1174 attr = GetFileAttributes(name); 1175 # endif 1176 if (attr == INVALID_FILE_ATTRIBUTES) 1177 return -1; 1178 return ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0); 1179 } 1180 #else 1181 # include <sys/stat.h> 1182 # ifndef S_ISDIR 1183 # if defined(_S_IFMT) && defined(_S_IFDIR) 1184 # define S_ISDIR(a) (((a) & _S_IFMT) == _S_IFDIR) 1185 # else 1186 # define S_ISDIR(a) (((a) & S_IFMT) == S_IFDIR) 1187 # endif 1188 # endif 1189 1190 int opt_isdir(const char *name) 1191 { 1192 # if defined(S_ISDIR) 1193 struct stat st; 1194 1195 if (stat(name, &st) == 0) 1196 return S_ISDIR(st.st_mode); 1197 else 1198 return -1; 1199 # else 1200 return -1; 1201 # endif 1202 } 1203 #endif 1204