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