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