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