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