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