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