1 1.1 christos /* 2 1.1 christos * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. 3 1.1 christos * 4 1.1 christos * Licensed under the OpenSSL license (the "License"). You may not use 5 1.1 christos * this file except in compliance with the License. You can obtain a copy 6 1.1 christos * in the file LICENSE in the source distribution or at 7 1.1 christos * https://www.openssl.org/source/license.html 8 1.1 christos */ 9 1.1 christos #include "apps.h" 10 1.1 christos #include <string.h> 11 1.1 christos #if !defined(OPENSSL_SYS_MSDOS) 12 1.1 christos # include OPENSSL_UNISTD 13 1.1 christos #endif 14 1.1 christos 15 1.1 christos #include <stdlib.h> 16 1.1 christos #include <errno.h> 17 1.1 christos #include <ctype.h> 18 1.1 christos #include <limits.h> 19 1.1 christos #include <openssl/bio.h> 20 1.1 christos #include <openssl/x509v3.h> 21 1.1 christos 22 1.1 christos #define MAX_OPT_HELP_WIDTH 30 23 1.1 christos const char OPT_HELP_STR[] = "--"; 24 1.1 christos const char OPT_MORE_STR[] = "---"; 25 1.1 christos 26 1.1 christos /* Our state */ 27 1.1 christos static char **argv; 28 1.1 christos static int argc; 29 1.1 christos static int opt_index; 30 1.1 christos static char *arg; 31 1.1 christos static char *flag; 32 1.1 christos static char *dunno; 33 1.1 christos static const OPTIONS *unknown; 34 1.1 christos static const OPTIONS *opts; 35 1.1 christos static char prog[40]; 36 1.1 christos 37 1.1 christos /* 38 1.1 christos * Return the simple name of the program; removing various platform gunk. 39 1.1 christos */ 40 1.1 christos #if defined(OPENSSL_SYS_WIN32) 41 1.1 christos char *opt_progname(const char *argv0) 42 1.1 christos { 43 1.1 christos size_t i, n; 44 1.1 christos const char *p; 45 1.1 christos char *q; 46 1.1 christos 47 1.1 christos /* find the last '/', '\' or ':' */ 48 1.1 christos for (p = argv0 + strlen(argv0); --p > argv0;) 49 1.1 christos if (*p == '/' || *p == '\\' || *p == ':') { 50 1.1 christos p++; 51 1.1 christos break; 52 1.1 christos } 53 1.1 christos 54 1.1 christos /* Strip off trailing nonsense. */ 55 1.1 christos n = strlen(p); 56 1.1 christos if (n > 4 && 57 1.1 christos (strcmp(&p[n - 4], ".exe") == 0 || strcmp(&p[n - 4], ".EXE") == 0)) 58 1.1 christos n -= 4; 59 1.1 christos 60 1.1 christos /* Copy over the name, in lowercase. */ 61 1.1 christos if (n > sizeof(prog) - 1) 62 1.1 christos n = sizeof(prog) - 1; 63 1.1 christos for (q = prog, i = 0; i < n; i++, p++) 64 1.1 christos *q++ = tolower((unsigned char)*p); 65 1.1 christos *q = '\0'; 66 1.1 christos return prog; 67 1.1 christos } 68 1.1 christos 69 1.1 christos #elif defined(OPENSSL_SYS_VMS) 70 1.1 christos 71 1.1 christos char *opt_progname(const char *argv0) 72 1.1 christos { 73 1.1 christos const char *p, *q; 74 1.1 christos 75 1.1 christos /* Find last special character sys:[foo.bar]openssl */ 76 1.1 christos for (p = argv0 + strlen(argv0); --p > argv0;) 77 1.1 christos if (*p == ':' || *p == ']' || *p == '>') { 78 1.1 christos p++; 79 1.1 christos break; 80 1.1 christos } 81 1.1 christos 82 1.1 christos q = strrchr(p, '.'); 83 1.1 christos strncpy(prog, p, sizeof(prog) - 1); 84 1.1 christos prog[sizeof(prog) - 1] = '\0'; 85 1.1 christos if (q != NULL && q - p < sizeof(prog)) 86 1.1 christos prog[q - p] = '\0'; 87 1.1 christos return prog; 88 1.1 christos } 89 1.1 christos 90 1.1 christos #else 91 1.1 christos 92 1.1 christos char *opt_progname(const char *argv0) 93 1.1 christos { 94 1.1 christos const char *p; 95 1.1 christos 96 1.1 christos /* Could use strchr, but this is like the ones above. */ 97 1.1 christos for (p = argv0 + strlen(argv0); --p > argv0;) 98 1.1 christos if (*p == '/') { 99 1.1 christos p++; 100 1.1 christos break; 101 1.1 christos } 102 1.1 christos strncpy(prog, p, sizeof(prog) - 1); 103 1.1 christos prog[sizeof(prog) - 1] = '\0'; 104 1.1 christos return prog; 105 1.1 christos } 106 1.1 christos #endif 107 1.1 christos 108 1.1 christos char *opt_getprog(void) 109 1.1 christos { 110 1.1 christos return prog; 111 1.1 christos } 112 1.1 christos 113 1.1 christos /* Set up the arg parsing. */ 114 1.1 christos char *opt_init(int ac, char **av, const OPTIONS *o) 115 1.1 christos { 116 1.1 christos /* Store state. */ 117 1.1 christos argc = ac; 118 1.1 christos argv = av; 119 1.1 christos opt_index = 1; 120 1.1 christos opts = o; 121 1.1 christos opt_progname(av[0]); 122 1.1 christos unknown = NULL; 123 1.1 christos 124 1.1 christos for (; o->name; ++o) { 125 1.1 christos #ifndef NDEBUG 126 1.1 christos const OPTIONS *next; 127 1.1 christos int duplicated, i; 128 1.1 christos #endif 129 1.1 christos 130 1.1 christos if (o->name == OPT_HELP_STR || o->name == OPT_MORE_STR) 131 1.1 christos continue; 132 1.1 christos #ifndef NDEBUG 133 1.1 christos i = o->valtype; 134 1.1 christos 135 1.1 christos /* Make sure options are legit. */ 136 1.1 christos assert(o->name[0] != '-'); 137 1.1 christos assert(o->retval > 0); 138 1.1 christos switch (i) { 139 1.1 christos case 0: case '-': case '/': case '<': case '>': case 'E': case 'F': 140 1.1 christos case 'M': case 'U': case 'f': case 'l': case 'n': case 'p': case 's': 141 1.1 christos case 'u': case 'c': 142 1.1 christos break; 143 1.1 christos default: 144 1.1 christos assert(0); 145 1.1 christos } 146 1.1 christos 147 1.1 christos /* Make sure there are no duplicates. */ 148 1.1 christos for (next = o + 1; next->name; ++next) { 149 1.1 christos /* 150 1.1 christos * Some compilers inline strcmp and the assert string is too long. 151 1.1 christos */ 152 1.1 christos duplicated = strcmp(o->name, next->name) == 0; 153 1.1 christos assert(!duplicated); 154 1.1 christos } 155 1.1 christos #endif 156 1.1 christos if (o->name[0] == '\0') { 157 1.1 christos assert(unknown == NULL); 158 1.1 christos unknown = o; 159 1.1 christos assert(unknown->valtype == 0 || unknown->valtype == '-'); 160 1.1 christos } 161 1.1 christos } 162 1.1 christos return prog; 163 1.1 christos } 164 1.1 christos 165 1.1 christos static OPT_PAIR formats[] = { 166 1.1 christos {"PEM/DER", OPT_FMT_PEMDER}, 167 1.1 christos {"pkcs12", OPT_FMT_PKCS12}, 168 1.1 christos {"smime", OPT_FMT_SMIME}, 169 1.1 christos {"engine", OPT_FMT_ENGINE}, 170 1.1 christos {"msblob", OPT_FMT_MSBLOB}, 171 1.1 christos {"nss", OPT_FMT_NSS}, 172 1.1 christos {"text", OPT_FMT_TEXT}, 173 1.1 christos {"http", OPT_FMT_HTTP}, 174 1.1 christos {"pvk", OPT_FMT_PVK}, 175 1.1 christos {NULL} 176 1.1 christos }; 177 1.1 christos 178 1.1 christos /* Print an error message about a failed format parse. */ 179 1.1 christos int opt_format_error(const char *s, unsigned long flags) 180 1.1 christos { 181 1.1 christos OPT_PAIR *ap; 182 1.1 christos 183 1.1 christos if (flags == OPT_FMT_PEMDER) { 184 1.1 christos BIO_printf(bio_err, "%s: Bad format \"%s\"; must be pem or der\n", 185 1.1 christos prog, s); 186 1.1 christos } else { 187 1.1 christos BIO_printf(bio_err, "%s: Bad format \"%s\"; must be one of:\n", 188 1.1 christos prog, s); 189 1.1 christos for (ap = formats; ap->name; ap++) 190 1.1 christos if (flags & ap->retval) 191 1.1 christos BIO_printf(bio_err, " %s\n", ap->name); 192 1.1 christos } 193 1.1 christos return 0; 194 1.1 christos } 195 1.1 christos 196 1.1 christos /* Parse a format string, put it into *result; return 0 on failure, else 1. */ 197 1.1 christos int opt_format(const char *s, unsigned long flags, int *result) 198 1.1 christos { 199 1.1 christos switch (*s) { 200 1.1 christos default: 201 1.1 christos return 0; 202 1.1 christos case 'D': 203 1.1 christos case 'd': 204 1.1 christos if ((flags & OPT_FMT_PEMDER) == 0) 205 1.1 christos return opt_format_error(s, flags); 206 1.1 christos *result = FORMAT_ASN1; 207 1.1 christos break; 208 1.1 christos case 'T': 209 1.1 christos case 't': 210 1.1 christos if ((flags & OPT_FMT_TEXT) == 0) 211 1.1 christos return opt_format_error(s, flags); 212 1.1 christos *result = FORMAT_TEXT; 213 1.1 christos break; 214 1.1 christos case 'N': 215 1.1 christos case 'n': 216 1.1 christos if ((flags & OPT_FMT_NSS) == 0) 217 1.1 christos return opt_format_error(s, flags); 218 1.1 christos if (strcmp(s, "NSS") != 0 && strcmp(s, "nss") != 0) 219 1.1 christos return opt_format_error(s, flags); 220 1.1 christos *result = FORMAT_NSS; 221 1.1 christos break; 222 1.1 christos case 'S': 223 1.1 christos case 's': 224 1.1 christos if ((flags & OPT_FMT_SMIME) == 0) 225 1.1 christos return opt_format_error(s, flags); 226 1.1 christos *result = FORMAT_SMIME; 227 1.1 christos break; 228 1.1 christos case 'M': 229 1.1 christos case 'm': 230 1.1 christos if ((flags & OPT_FMT_MSBLOB) == 0) 231 1.1 christos return opt_format_error(s, flags); 232 1.1 christos *result = FORMAT_MSBLOB; 233 1.1 christos break; 234 1.1 christos case 'E': 235 1.1 christos case 'e': 236 1.1 christos if ((flags & OPT_FMT_ENGINE) == 0) 237 1.1 christos return opt_format_error(s, flags); 238 1.1 christos *result = FORMAT_ENGINE; 239 1.1 christos break; 240 1.1 christos case 'H': 241 1.1 christos case 'h': 242 1.1 christos if ((flags & OPT_FMT_HTTP) == 0) 243 1.1 christos return opt_format_error(s, flags); 244 1.1 christos *result = FORMAT_HTTP; 245 1.1 christos break; 246 1.1 christos case '1': 247 1.1 christos if ((flags & OPT_FMT_PKCS12) == 0) 248 1.1 christos return opt_format_error(s, flags); 249 1.1 christos *result = FORMAT_PKCS12; 250 1.1 christos break; 251 1.1 christos case 'P': 252 1.1 christos case 'p': 253 1.1 christos if (s[1] == '\0' || strcmp(s, "PEM") == 0 || strcmp(s, "pem") == 0) { 254 1.1 christos if ((flags & OPT_FMT_PEMDER) == 0) 255 1.1 christos return opt_format_error(s, flags); 256 1.1 christos *result = FORMAT_PEM; 257 1.1 christos } else if (strcmp(s, "PVK") == 0 || strcmp(s, "pvk") == 0) { 258 1.1 christos if ((flags & OPT_FMT_PVK) == 0) 259 1.1 christos return opt_format_error(s, flags); 260 1.1 christos *result = FORMAT_PVK; 261 1.1 christos } else if (strcmp(s, "P12") == 0 || strcmp(s, "p12") == 0 262 1.1 christos || strcmp(s, "PKCS12") == 0 || strcmp(s, "pkcs12") == 0) { 263 1.1 christos if ((flags & OPT_FMT_PKCS12) == 0) 264 1.1 christos return opt_format_error(s, flags); 265 1.1 christos *result = FORMAT_PKCS12; 266 1.1 christos } else { 267 1.1 christos return 0; 268 1.1 christos } 269 1.1 christos break; 270 1.1 christos } 271 1.1 christos return 1; 272 1.1 christos } 273 1.1 christos 274 1.1 christos /* Parse a cipher name, put it in *EVP_CIPHER; return 0 on failure, else 1. */ 275 1.1 christos int opt_cipher(const char *name, const EVP_CIPHER **cipherp) 276 1.1 christos { 277 1.1 christos *cipherp = EVP_get_cipherbyname(name); 278 1.1 christos if (*cipherp != NULL) 279 1.1 christos return 1; 280 1.1 christos BIO_printf(bio_err, "%s: Unrecognized flag %s\n", prog, name); 281 1.1 christos return 0; 282 1.1 christos } 283 1.1 christos 284 1.1 christos /* 285 1.1 christos * Parse message digest name, put it in *EVP_MD; return 0 on failure, else 1. 286 1.1 christos */ 287 1.1 christos int opt_md(const char *name, const EVP_MD **mdp) 288 1.1 christos { 289 1.1 christos *mdp = EVP_get_digestbyname(name); 290 1.1 christos if (*mdp != NULL) 291 1.1 christos return 1; 292 1.1 christos BIO_printf(bio_err, "%s: Unrecognized flag %s\n", prog, name); 293 1.1 christos return 0; 294 1.1 christos } 295 1.1 christos 296 1.1 christos /* Look through a list of name/value pairs. */ 297 1.1 christos int opt_pair(const char *name, const OPT_PAIR* pairs, int *result) 298 1.1 christos { 299 1.1 christos const OPT_PAIR *pp; 300 1.1 christos 301 1.1 christos for (pp = pairs; pp->name; pp++) 302 1.1 christos if (strcmp(pp->name, name) == 0) { 303 1.1 christos *result = pp->retval; 304 1.1 christos return 1; 305 1.1 christos } 306 1.1 christos BIO_printf(bio_err, "%s: Value must be one of:\n", prog); 307 1.1 christos for (pp = pairs; pp->name; pp++) 308 1.1 christos BIO_printf(bio_err, "\t%s\n", pp->name); 309 1.1 christos return 0; 310 1.1 christos } 311 1.1 christos 312 1.1 christos /* Parse an int, put it into *result; return 0 on failure, else 1. */ 313 1.1 christos int opt_int(const char *value, int *result) 314 1.1 christos { 315 1.1 christos long l; 316 1.1 christos 317 1.1 christos if (!opt_long(value, &l)) 318 1.1 christos return 0; 319 1.1 christos *result = (int)l; 320 1.1 christos if (*result != l) { 321 1.1 christos BIO_printf(bio_err, "%s: Value \"%s\" outside integer range\n", 322 1.1 christos prog, value); 323 1.1 christos return 0; 324 1.1 christos } 325 1.1 christos return 1; 326 1.1 christos } 327 1.1 christos 328 1.1 christos static void opt_number_error(const char *v) 329 1.1 christos { 330 1.1 christos size_t i = 0; 331 1.1 christos struct strstr_pair_st { 332 1.1 christos char *prefix; 333 1.1 christos char *name; 334 1.1 christos } b[] = { 335 1.1 christos {"0x", "a hexadecimal"}, 336 1.1 christos {"0X", "a hexadecimal"}, 337 1.1 christos {"0", "an octal"} 338 1.1 christos }; 339 1.1 christos 340 1.1 christos for (i = 0; i < OSSL_NELEM(b); i++) { 341 1.1 christos if (strncmp(v, b[i].prefix, strlen(b[i].prefix)) == 0) { 342 1.1 christos BIO_printf(bio_err, 343 1.1 christos "%s: Can't parse \"%s\" as %s number\n", 344 1.1 christos prog, v, b[i].name); 345 1.1 christos return; 346 1.1 christos } 347 1.1 christos } 348 1.1 christos BIO_printf(bio_err, "%s: Can't parse \"%s\" as a number\n", prog, v); 349 1.1 christos return; 350 1.1 christos } 351 1.1 christos 352 1.1 christos /* Parse a long, put it into *result; return 0 on failure, else 1. */ 353 1.1 christos int opt_long(const char *value, long *result) 354 1.1 christos { 355 1.1 christos int oerrno = errno; 356 1.1 christos long l; 357 1.1 christos char *endp; 358 1.1 christos 359 1.1 christos errno = 0; 360 1.1 christos l = strtol(value, &endp, 0); 361 1.1 christos if (*endp 362 1.1 christos || endp == value 363 1.1 christos || ((l == LONG_MAX || l == LONG_MIN) && errno == ERANGE) 364 1.1 christos || (l == 0 && errno != 0)) { 365 1.1 christos opt_number_error(value); 366 1.1 christos errno = oerrno; 367 1.1 christos return 0; 368 1.1 christos } 369 1.1 christos *result = l; 370 1.1 christos errno = oerrno; 371 1.1 christos return 1; 372 1.1 christos } 373 1.1 christos 374 1.1 christos #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L && \ 375 1.1 christos defined(INTMAX_MAX) && defined(UINTMAX_MAX) 376 1.1 christos 377 1.1 christos /* Parse an intmax_t, put it into *result; return 0 on failure, else 1. */ 378 1.1 christos int opt_imax(const char *value, intmax_t *result) 379 1.1 christos { 380 1.1 christos int oerrno = errno; 381 1.1 christos intmax_t m; 382 1.1 christos char *endp; 383 1.1 christos 384 1.1 christos errno = 0; 385 1.1 christos m = strtoimax(value, &endp, 0); 386 1.1 christos if (*endp 387 1.1 christos || endp == value 388 1.1 christos || ((m == INTMAX_MAX || m == INTMAX_MIN) && errno == ERANGE) 389 1.1 christos || (m == 0 && errno != 0)) { 390 1.1 christos opt_number_error(value); 391 1.1 christos errno = oerrno; 392 1.1 christos return 0; 393 1.1 christos } 394 1.1 christos *result = m; 395 1.1 christos errno = oerrno; 396 1.1 christos return 1; 397 1.1 christos } 398 1.1 christos 399 1.1 christos /* Parse a uintmax_t, put it into *result; return 0 on failure, else 1. */ 400 1.1 christos int opt_umax(const char *value, uintmax_t *result) 401 1.1 christos { 402 1.1 christos int oerrno = errno; 403 1.1 christos uintmax_t m; 404 1.1 christos char *endp; 405 1.1 christos 406 1.1 christos errno = 0; 407 1.1 christos m = strtoumax(value, &endp, 0); 408 1.1 christos if (*endp 409 1.1 christos || endp == value 410 1.1 christos || (m == UINTMAX_MAX && errno == ERANGE) 411 1.1 christos || (m == 0 && errno != 0)) { 412 1.1 christos opt_number_error(value); 413 1.1 christos errno = oerrno; 414 1.1 christos return 0; 415 1.1 christos } 416 1.1 christos *result = m; 417 1.1 christos errno = oerrno; 418 1.1 christos return 1; 419 1.1 christos } 420 1.1 christos #endif 421 1.1 christos 422 1.1 christos /* 423 1.1 christos * Parse an unsigned long, put it into *result; return 0 on failure, else 1. 424 1.1 christos */ 425 1.1 christos int opt_ulong(const char *value, unsigned long *result) 426 1.1 christos { 427 1.1 christos int oerrno = errno; 428 1.1 christos char *endptr; 429 1.1 christos unsigned long l; 430 1.1 christos 431 1.1 christos errno = 0; 432 1.1 christos l = strtoul(value, &endptr, 0); 433 1.1 christos if (*endptr 434 1.1 christos || endptr == value 435 1.1 christos || ((l == ULONG_MAX) && errno == ERANGE) 436 1.1 christos || (l == 0 && errno != 0)) { 437 1.1 christos opt_number_error(value); 438 1.1 christos errno = oerrno; 439 1.1 christos return 0; 440 1.1 christos } 441 1.1 christos *result = l; 442 1.1 christos errno = oerrno; 443 1.1 christos return 1; 444 1.1 christos } 445 1.1 christos 446 1.1 christos /* 447 1.1 christos * We pass opt as an int but cast it to "enum range" so that all the 448 1.1 christos * items in the OPT_V_ENUM enumeration are caught; this makes -Wswitch 449 1.1 christos * in gcc do the right thing. 450 1.1 christos */ 451 1.1 christos enum range { OPT_V_ENUM }; 452 1.1 christos 453 1.1 christos int opt_verify(int opt, X509_VERIFY_PARAM *vpm) 454 1.1 christos { 455 1.1 christos int i; 456 1.1 christos ossl_intmax_t t = 0; 457 1.1 christos ASN1_OBJECT *otmp; 458 1.1 christos X509_PURPOSE *xptmp; 459 1.1 christos const X509_VERIFY_PARAM *vtmp; 460 1.1 christos 461 1.1 christos assert(vpm != NULL); 462 1.1 christos assert(opt > OPT_V__FIRST); 463 1.1 christos assert(opt < OPT_V__LAST); 464 1.1 christos 465 1.1 christos switch ((enum range)opt) { 466 1.1 christos case OPT_V__FIRST: 467 1.1 christos case OPT_V__LAST: 468 1.1 christos return 0; 469 1.1 christos case OPT_V_POLICY: 470 1.1 christos otmp = OBJ_txt2obj(opt_arg(), 0); 471 1.1 christos if (otmp == NULL) { 472 1.1 christos BIO_printf(bio_err, "%s: Invalid Policy %s\n", prog, opt_arg()); 473 1.1 christos return 0; 474 1.1 christos } 475 1.1 christos X509_VERIFY_PARAM_add0_policy(vpm, otmp); 476 1.1 christos break; 477 1.1 christos case OPT_V_PURPOSE: 478 1.1 christos /* purpose name -> purpose index */ 479 1.1 christos i = X509_PURPOSE_get_by_sname(opt_arg()); 480 1.1 christos if (i < 0) { 481 1.1 christos BIO_printf(bio_err, "%s: Invalid purpose %s\n", prog, opt_arg()); 482 1.1 christos return 0; 483 1.1 christos } 484 1.1 christos 485 1.1 christos /* purpose index -> purpose object */ 486 1.1 christos xptmp = X509_PURPOSE_get0(i); 487 1.1 christos 488 1.1 christos /* purpose object -> purpose value */ 489 1.1 christos i = X509_PURPOSE_get_id(xptmp); 490 1.1 christos 491 1.1 christos if (!X509_VERIFY_PARAM_set_purpose(vpm, i)) { 492 1.1 christos BIO_printf(bio_err, 493 1.1 christos "%s: Internal error setting purpose %s\n", 494 1.1 christos prog, opt_arg()); 495 1.1 christos return 0; 496 1.1 christos } 497 1.1 christos break; 498 1.1 christos case OPT_V_VERIFY_NAME: 499 1.1 christos vtmp = X509_VERIFY_PARAM_lookup(opt_arg()); 500 1.1 christos if (vtmp == NULL) { 501 1.1 christos BIO_printf(bio_err, "%s: Invalid verify name %s\n", 502 1.1 christos prog, opt_arg()); 503 1.1 christos return 0; 504 1.1 christos } 505 1.1 christos X509_VERIFY_PARAM_set1(vpm, vtmp); 506 1.1 christos break; 507 1.1 christos case OPT_V_VERIFY_DEPTH: 508 1.1 christos i = atoi(opt_arg()); 509 1.1 christos if (i >= 0) 510 1.1 christos X509_VERIFY_PARAM_set_depth(vpm, i); 511 1.1 christos break; 512 1.1 christos case OPT_V_VERIFY_AUTH_LEVEL: 513 1.1 christos i = atoi(opt_arg()); 514 1.1 christos if (i >= 0) 515 1.1 christos X509_VERIFY_PARAM_set_auth_level(vpm, i); 516 1.1 christos break; 517 1.1 christos case OPT_V_ATTIME: 518 1.1 christos if (!opt_imax(opt_arg(), &t)) 519 1.1 christos return 0; 520 1.1 christos if (t != (time_t)t) { 521 1.1 christos BIO_printf(bio_err, "%s: epoch time out of range %s\n", 522 1.1 christos prog, opt_arg()); 523 1.1 christos return 0; 524 1.1 christos } 525 1.1 christos X509_VERIFY_PARAM_set_time(vpm, (time_t)t); 526 1.1 christos break; 527 1.1 christos case OPT_V_VERIFY_HOSTNAME: 528 1.1 christos if (!X509_VERIFY_PARAM_set1_host(vpm, opt_arg(), 0)) 529 1.1 christos return 0; 530 1.1 christos break; 531 1.1 christos case OPT_V_VERIFY_EMAIL: 532 1.1 christos if (!X509_VERIFY_PARAM_set1_email(vpm, opt_arg(), 0)) 533 1.1 christos return 0; 534 1.1 christos break; 535 1.1 christos case OPT_V_VERIFY_IP: 536 1.1 christos if (!X509_VERIFY_PARAM_set1_ip_asc(vpm, opt_arg())) 537 1.1 christos return 0; 538 1.1 christos break; 539 1.1 christos case OPT_V_IGNORE_CRITICAL: 540 1.1 christos X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_IGNORE_CRITICAL); 541 1.1 christos break; 542 1.1 christos case OPT_V_ISSUER_CHECKS: 543 1.1 christos /* NOP, deprecated */ 544 1.1 christos break; 545 1.1 christos case OPT_V_CRL_CHECK: 546 1.1 christos X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_CRL_CHECK); 547 1.1 christos break; 548 1.1 christos case OPT_V_CRL_CHECK_ALL: 549 1.1 christos X509_VERIFY_PARAM_set_flags(vpm, 550 1.1 christos X509_V_FLAG_CRL_CHECK | 551 1.1 christos X509_V_FLAG_CRL_CHECK_ALL); 552 1.1 christos break; 553 1.1 christos case OPT_V_POLICY_CHECK: 554 1.1 christos X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_POLICY_CHECK); 555 1.1 christos break; 556 1.1 christos case OPT_V_EXPLICIT_POLICY: 557 1.1 christos X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_EXPLICIT_POLICY); 558 1.1 christos break; 559 1.1 christos case OPT_V_INHIBIT_ANY: 560 1.1 christos X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_INHIBIT_ANY); 561 1.1 christos break; 562 1.1 christos case OPT_V_INHIBIT_MAP: 563 1.1 christos X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_INHIBIT_MAP); 564 1.1 christos break; 565 1.1 christos case OPT_V_X509_STRICT: 566 1.1 christos X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_X509_STRICT); 567 1.1 christos break; 568 1.1 christos case OPT_V_EXTENDED_CRL: 569 1.1 christos X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_EXTENDED_CRL_SUPPORT); 570 1.1 christos break; 571 1.1 christos case OPT_V_USE_DELTAS: 572 1.1 christos X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_USE_DELTAS); 573 1.1 christos break; 574 1.1 christos case OPT_V_POLICY_PRINT: 575 1.1 christos X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_NOTIFY_POLICY); 576 1.1 christos break; 577 1.1 christos case OPT_V_CHECK_SS_SIG: 578 1.1 christos X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_CHECK_SS_SIGNATURE); 579 1.1 christos break; 580 1.1 christos case OPT_V_TRUSTED_FIRST: 581 1.1 christos X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_TRUSTED_FIRST); 582 1.1 christos break; 583 1.1 christos case OPT_V_SUITEB_128_ONLY: 584 1.1 christos X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_SUITEB_128_LOS_ONLY); 585 1.1 christos break; 586 1.1 christos case OPT_V_SUITEB_128: 587 1.1 christos X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_SUITEB_128_LOS); 588 1.1 christos break; 589 1.1 christos case OPT_V_SUITEB_192: 590 1.1 christos X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_SUITEB_192_LOS); 591 1.1 christos break; 592 1.1 christos case OPT_V_PARTIAL_CHAIN: 593 1.1 christos X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_PARTIAL_CHAIN); 594 1.1 christos break; 595 1.1 christos case OPT_V_NO_ALT_CHAINS: 596 1.1 christos X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_NO_ALT_CHAINS); 597 1.1 christos break; 598 1.1 christos case OPT_V_NO_CHECK_TIME: 599 1.1 christos X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_NO_CHECK_TIME); 600 1.1 christos break; 601 1.1 christos case OPT_V_ALLOW_PROXY_CERTS: 602 1.1 christos X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_ALLOW_PROXY_CERTS); 603 1.1 christos break; 604 1.1 christos } 605 1.1 christos return 1; 606 1.1 christos 607 1.1 christos } 608 1.1 christos 609 1.1 christos /* 610 1.1 christos * Parse the next flag (and value if specified), return 0 if done, -1 on 611 1.1 christos * error, otherwise the flag's retval. 612 1.1 christos */ 613 1.1 christos int opt_next(void) 614 1.1 christos { 615 1.1 christos char *p; 616 1.1 christos const OPTIONS *o; 617 1.1 christos int ival; 618 1.1 christos long lval; 619 1.1 christos unsigned long ulval; 620 1.1 christos ossl_intmax_t imval; 621 1.1 christos ossl_uintmax_t umval; 622 1.1 christos 623 1.1 christos /* Look at current arg; at end of the list? */ 624 1.1 christos arg = NULL; 625 1.1 christos p = argv[opt_index]; 626 1.1 christos if (p == NULL) 627 1.1 christos return 0; 628 1.1 christos 629 1.1 christos /* If word doesn't start with a -, we're done. */ 630 1.1 christos if (*p != '-') 631 1.1 christos return 0; 632 1.1 christos 633 1.1 christos /* Hit "--" ? We're done. */ 634 1.1 christos opt_index++; 635 1.1 christos if (strcmp(p, "--") == 0) 636 1.1 christos return 0; 637 1.1 christos 638 1.1 christos /* Allow -nnn and --nnn */ 639 1.1 christos if (*++p == '-') 640 1.1 christos p++; 641 1.1 christos flag = p - 1; 642 1.1 christos 643 1.1 christos /* If we have --flag=foo, snip it off */ 644 1.1 christos if ((arg = strchr(p, '=')) != NULL) 645 1.1 christos *arg++ = '\0'; 646 1.1 christos for (o = opts; o->name; ++o) { 647 1.1 christos /* If not this option, move on to the next one. */ 648 1.1 christos if (strcmp(p, o->name) != 0) 649 1.1 christos continue; 650 1.1 christos 651 1.1 christos /* If it doesn't take a value, make sure none was given. */ 652 1.1 christos if (o->valtype == 0 || o->valtype == '-') { 653 1.1 christos if (arg) { 654 1.1 christos BIO_printf(bio_err, 655 1.1 christos "%s: Option -%s does not take a value\n", prog, p); 656 1.1 christos return -1; 657 1.1 christos } 658 1.1 christos return o->retval; 659 1.1 christos } 660 1.1 christos 661 1.1 christos /* Want a value; get the next param if =foo not used. */ 662 1.1 christos if (arg == NULL) { 663 1.1 christos if (argv[opt_index] == NULL) { 664 1.1 christos BIO_printf(bio_err, 665 1.1 christos "%s: Option -%s needs a value\n", prog, o->name); 666 1.1 christos return -1; 667 1.1 christos } 668 1.1 christos arg = argv[opt_index++]; 669 1.1 christos } 670 1.1 christos 671 1.1 christos /* Syntax-check value. */ 672 1.1 christos switch (o->valtype) { 673 1.1 christos default: 674 1.1 christos case 's': 675 1.1 christos /* Just a string. */ 676 1.1 christos break; 677 1.1 christos case '/': 678 1.1 christos if (app_isdir(arg) > 0) 679 1.1 christos break; 680 1.1 christos BIO_printf(bio_err, "%s: Not a directory: %s\n", prog, arg); 681 1.1 christos return -1; 682 1.1 christos case '<': 683 1.1 christos /* Input file. */ 684 1.1 christos break; 685 1.1 christos case '>': 686 1.1 christos /* Output file. */ 687 1.1 christos break; 688 1.1 christos case 'p': 689 1.1 christos case 'n': 690 1.1 christos if (!opt_int(arg, &ival) 691 1.1 christos || (o->valtype == 'p' && ival <= 0)) { 692 1.1 christos BIO_printf(bio_err, 693 1.1 christos "%s: Non-positive number \"%s\" for -%s\n", 694 1.1 christos prog, arg, o->name); 695 1.1 christos return -1; 696 1.1 christos } 697 1.1 christos break; 698 1.1 christos case 'M': 699 1.1 christos if (!opt_imax(arg, &imval)) { 700 1.1 christos BIO_printf(bio_err, 701 1.1 christos "%s: Invalid number \"%s\" for -%s\n", 702 1.1 christos prog, arg, o->name); 703 1.1 christos return -1; 704 1.1 christos } 705 1.1 christos break; 706 1.1 christos case 'U': 707 1.1 christos if (!opt_umax(arg, &umval)) { 708 1.1 christos BIO_printf(bio_err, 709 1.1 christos "%s: Invalid number \"%s\" for -%s\n", 710 1.1 christos prog, arg, o->name); 711 1.1 christos return -1; 712 1.1 christos } 713 1.1 christos break; 714 1.1 christos case 'l': 715 1.1 christos if (!opt_long(arg, &lval)) { 716 1.1 christos BIO_printf(bio_err, 717 1.1 christos "%s: Invalid number \"%s\" for -%s\n", 718 1.1 christos prog, arg, o->name); 719 1.1 christos return -1; 720 1.1 christos } 721 1.1 christos break; 722 1.1 christos case 'u': 723 1.1 christos if (!opt_ulong(arg, &ulval)) { 724 1.1 christos BIO_printf(bio_err, 725 1.1 christos "%s: Invalid number \"%s\" for -%s\n", 726 1.1 christos prog, arg, o->name); 727 1.1 christos return -1; 728 1.1 christos } 729 1.1 christos break; 730 1.1 christos case 'c': 731 1.1 christos case 'E': 732 1.1 christos case 'F': 733 1.1 christos case 'f': 734 1.1 christos if (opt_format(arg, 735 1.1 christos o->valtype == 'c' ? OPT_FMT_PDS : 736 1.1 christos o->valtype == 'E' ? OPT_FMT_PDE : 737 1.1 christos o->valtype == 'F' ? OPT_FMT_PEMDER 738 1.1 christos : OPT_FMT_ANY, &ival)) 739 1.1 christos break; 740 1.1 christos BIO_printf(bio_err, 741 1.1 christos "%s: Invalid format \"%s\" for -%s\n", 742 1.1 christos prog, arg, o->name); 743 1.1 christos return -1; 744 1.1 christos } 745 1.1 christos 746 1.1 christos /* Return the flag value. */ 747 1.1 christos return o->retval; 748 1.1 christos } 749 1.1 christos if (unknown != NULL) { 750 1.1 christos dunno = p; 751 1.1 christos return unknown->retval; 752 1.1 christos } 753 1.1 christos BIO_printf(bio_err, "%s: Option unknown option -%s\n", prog, p); 754 1.1 christos return -1; 755 1.1 christos } 756 1.1 christos 757 1.1 christos /* Return the most recent flag parameter. */ 758 1.1 christos char *opt_arg(void) 759 1.1 christos { 760 1.1 christos return arg; 761 1.1 christos } 762 1.1 christos 763 1.1 christos /* Return the most recent flag. */ 764 1.1 christos char *opt_flag(void) 765 1.1 christos { 766 1.1 christos return flag; 767 1.1 christos } 768 1.1 christos 769 1.1 christos /* Return the unknown option. */ 770 1.1 christos char *opt_unknown(void) 771 1.1 christos { 772 1.1 christos return dunno; 773 1.1 christos } 774 1.1 christos 775 1.1 christos /* Return the rest of the arguments after parsing flags. */ 776 1.1 christos char **opt_rest(void) 777 1.1 christos { 778 1.1 christos return &argv[opt_index]; 779 1.1 christos } 780 1.1 christos 781 1.1 christos /* How many items in remaining args? */ 782 1.1 christos int opt_num_rest(void) 783 1.1 christos { 784 1.1 christos int i = 0; 785 1.1 christos char **pp; 786 1.1 christos 787 1.1 christos for (pp = opt_rest(); *pp; pp++, i++) 788 1.1 christos continue; 789 1.1 christos return i; 790 1.1 christos } 791 1.1 christos 792 1.1 christos /* Return a string describing the parameter type. */ 793 1.1 christos static const char *valtype2param(const OPTIONS *o) 794 1.1 christos { 795 1.1 christos switch (o->valtype) { 796 1.1 christos case 0: 797 1.1 christos case '-': 798 1.1 christos return ""; 799 1.1 christos case 's': 800 1.1 christos return "val"; 801 1.1 christos case '/': 802 1.1 christos return "dir"; 803 1.1 christos case '<': 804 1.1 christos return "infile"; 805 1.1 christos case '>': 806 1.1 christos return "outfile"; 807 1.1 christos case 'p': 808 1.1 christos return "+int"; 809 1.1 christos case 'n': 810 1.1 christos return "int"; 811 1.1 christos case 'l': 812 1.1 christos return "long"; 813 1.1 christos case 'u': 814 1.1 christos return "ulong"; 815 1.1 christos case 'E': 816 1.1 christos return "PEM|DER|ENGINE"; 817 1.1 christos case 'F': 818 1.1 christos return "PEM|DER"; 819 1.1 christos case 'f': 820 1.1 christos return "format"; 821 1.1 christos case 'M': 822 1.1 christos return "intmax"; 823 1.1 christos case 'U': 824 1.1 christos return "uintmax"; 825 1.1 christos } 826 1.1 christos return "parm"; 827 1.1 christos } 828 1.1 christos 829 1.1 christos void opt_help(const OPTIONS *list) 830 1.1 christos { 831 1.1 christos const OPTIONS *o; 832 1.1 christos int i; 833 1.1 christos int standard_prolog; 834 1.1 christos int width = 5; 835 1.1 christos char start[80 + 1]; 836 1.1 christos char *p; 837 1.1 christos const char *help; 838 1.1 christos 839 1.1 christos /* Starts with its own help message? */ 840 1.1 christos standard_prolog = list[0].name != OPT_HELP_STR; 841 1.1 christos 842 1.1 christos /* Find the widest help. */ 843 1.1 christos for (o = list; o->name; o++) { 844 1.1 christos if (o->name == OPT_MORE_STR) 845 1.1 christos continue; 846 1.1 christos i = 2 + (int)strlen(o->name); 847 1.1 christos if (o->valtype != '-') 848 1.1 christos i += 1 + strlen(valtype2param(o)); 849 1.1 christos if (i < MAX_OPT_HELP_WIDTH && i > width) 850 1.1 christos width = i; 851 1.1 christos assert(i < (int)sizeof(start)); 852 1.1 christos } 853 1.1 christos 854 1.1 christos if (standard_prolog) 855 1.1 christos BIO_printf(bio_err, "Usage: %s [options]\nValid options are:\n", 856 1.1 christos prog); 857 1.1 christos 858 1.1 christos /* Now let's print. */ 859 1.1 christos for (o = list; o->name; o++) { 860 1.1 christos help = o->helpstr ? o->helpstr : "(No additional info)"; 861 1.1 christos if (o->name == OPT_HELP_STR) { 862 1.1 christos BIO_printf(bio_err, help, prog); 863 1.1 christos continue; 864 1.1 christos } 865 1.1 christos 866 1.1 christos /* Pad out prefix */ 867 1.1 christos memset(start, ' ', sizeof(start) - 1); 868 1.1 christos start[sizeof(start) - 1] = '\0'; 869 1.1 christos 870 1.1 christos if (o->name == OPT_MORE_STR) { 871 1.1 christos /* Continuation of previous line; pad and print. */ 872 1.1 christos start[width] = '\0'; 873 1.1 christos BIO_printf(bio_err, "%s %s\n", start, help); 874 1.1 christos continue; 875 1.1 christos } 876 1.1 christos 877 1.1 christos /* Build up the "-flag [param]" part. */ 878 1.1 christos p = start; 879 1.1 christos *p++ = ' '; 880 1.1 christos *p++ = '-'; 881 1.1 christos if (o->name[0]) 882 1.1 christos p += strlen(strcpy(p, o->name)); 883 1.1 christos else 884 1.1 christos *p++ = '*'; 885 1.1 christos if (o->valtype != '-') { 886 1.1 christos *p++ = ' '; 887 1.1 christos p += strlen(strcpy(p, valtype2param(o))); 888 1.1 christos } 889 1.1 christos *p = ' '; 890 1.1 christos if ((int)(p - start) >= MAX_OPT_HELP_WIDTH) { 891 1.1 christos *p = '\0'; 892 1.1 christos BIO_printf(bio_err, "%s\n", start); 893 1.1 christos memset(start, ' ', sizeof(start)); 894 1.1 christos } 895 1.1 christos start[width] = '\0'; 896 1.1 christos BIO_printf(bio_err, "%s %s\n", start, help); 897 1.1 christos } 898 1.1 christos } 899