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