11590Srgrimes/*
21590Srgrimes * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
31590Srgrimes *
41590Srgrimes * Licensed under the Apache License 2.0 (the "License").  You may not use
51590Srgrimes * this file except in compliance with the License.  You can obtain a copy
61590Srgrimes * in the file LICENSE in the source distribution or at
71590Srgrimes * https://www.openssl.org/source/license.html
81590Srgrimes */
91590Srgrimes
101590Srgrimes/*
111590Srgrimes * This file is also used by the test suite. Do not #include "apps.h".
121590Srgrimes */
131590Srgrimes#include "opt.h"
141590Srgrimes#include "fmt.h"
151590Srgrimes#include "app_libctx.h"
161590Srgrimes#include "internal/nelem.h"
171590Srgrimes#include "internal/numbers.h"
181590Srgrimes#include <string.h>
191590Srgrimes#if !defined(OPENSSL_SYS_MSDOS)
201590Srgrimes# include <unistd.h>
211590Srgrimes#endif
221590Srgrimes
231590Srgrimes#include <stdlib.h>
241590Srgrimes#include <errno.h>
251590Srgrimes#include <ctype.h>
261590Srgrimes#include <limits.h>
271590Srgrimes#include <openssl/err.h>
281590Srgrimes#include <openssl/bio.h>
291590Srgrimes#include <openssl/x509v3.h>
301590Srgrimes
311590Srgrimes#define MAX_OPT_HELP_WIDTH 30
321590Srgrimesconst char OPT_HELP_STR[] = "-H";
331590Srgrimesconst char OPT_MORE_STR[] = "-M";
341590Srgrimesconst char OPT_SECTION_STR[] = "-S";
3541568Sarchieconst char OPT_PARAM_STR[] = "-P";
361590Srgrimes
371590Srgrimes/* Our state */
381590Srgrimesstatic char **argv;
391590Srgrimesstatic int argc;
401590Srgrimesstatic int opt_index;
4141568Sarchiestatic char *arg;
421590Srgrimesstatic char *flag;
4399112Sobrienstatic char *dunno;
4499112Sobrienstatic const OPTIONS *unknown;
451590Srgrimesstatic const OPTIONS *opts;
4665508Sdesstatic char prog[40];
4765414Sdes
481590Srgrimes/*
4978717Sdd * Return the simple name of the program; removing various platform gunk.
5023693Speter */
511590Srgrimes#if defined(OPENSSL_SYS_WIN32)
5292920Simp
531590Srgrimesconst char *opt_path_end(const char *filename)
541590Srgrimes{
55100822Sdwmalone    const char *p;
561590Srgrimes
5765508Sdes    /* find the last '/', '\' or ':' */
581590Srgrimes    for (p = filename + strlen(filename); --p > filename; )
591590Srgrimes        if (*p == '/' || *p == '\\' || *p == ':') {
6024360Simp            p++;
611590Srgrimes            break;
621590Srgrimes        }
631590Srgrimes    return p;
641590Srgrimes}
651590Srgrimes
661590Srgrimeschar *opt_progname(const char *argv0)
671590Srgrimes{
681590Srgrimes    size_t i, n;
69188006Srwatson    const char *p;
701590Srgrimes    char *q;
711590Srgrimes
72188006Srwatson    p = opt_path_end(argv0);
73188006Srwatson
74188006Srwatson    /* Strip off trailing nonsense. */
75188006Srwatson    n = strlen(p);
76188006Srwatson    if (n > 4 &&
77188006Srwatson        (strcmp(&p[n - 4], ".exe") == 0 || strcmp(&p[n - 4], ".EXE") == 0))
781590Srgrimes        n -= 4;
791590Srgrimes
801590Srgrimes    /* Copy over the name, in lowercase. */
811590Srgrimes    if (n > sizeof(prog) - 1)
82100822Sdwmalone        n = sizeof(prog) - 1;
831590Srgrimes    for (q = prog, i = 0; i < n; i++, p++)
841590Srgrimes        *q++ = tolower((unsigned char)*p);
85188006Srwatson    *q = '\0';
861590Srgrimes    return prog;
871590Srgrimes}
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 *)(intptr_t)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 *)(intptr_t)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        const char *prefix;
523        const 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        if (!X509_VERIFY_PARAM_add0_policy(vpm, otmp)) {
700            ASN1_OBJECT_free(otmp);
701            opt_printf_stderr("%s: Internal error adding Policy %s\n",
702                              prog, opt_arg());
703            return 0;
704        }
705        break;
706    case OPT_V_PURPOSE:
707        /* purpose name -> purpose index */
708        i = X509_PURPOSE_get_by_sname(opt_arg());
709        if (i < 0) {
710            opt_printf_stderr("%s: Invalid purpose %s\n", prog, opt_arg());
711            return 0;
712        }
713
714        /* purpose index -> purpose object */
715        xptmp = X509_PURPOSE_get0(i);
716
717        /* purpose object -> purpose value */
718        i = X509_PURPOSE_get_id(xptmp);
719
720        if (!X509_VERIFY_PARAM_set_purpose(vpm, i)) {
721            opt_printf_stderr("%s: Internal error setting purpose %s\n",
722                              prog, opt_arg());
723            return 0;
724        }
725        break;
726    case OPT_V_VERIFY_NAME:
727        vtmp = X509_VERIFY_PARAM_lookup(opt_arg());
728        if (vtmp == NULL) {
729            opt_printf_stderr("%s: Invalid verify name %s\n",
730                              prog, opt_arg());
731            return 0;
732        }
733        X509_VERIFY_PARAM_set1(vpm, vtmp);
734        break;
735    case OPT_V_VERIFY_DEPTH:
736        i = atoi(opt_arg());
737        if (i >= 0)
738            X509_VERIFY_PARAM_set_depth(vpm, i);
739        break;
740    case OPT_V_VERIFY_AUTH_LEVEL:
741        i = atoi(opt_arg());
742        if (i >= 0)
743            X509_VERIFY_PARAM_set_auth_level(vpm, i);
744        break;
745    case OPT_V_ATTIME:
746        if (!opt_intmax(opt_arg(), &t))
747            return 0;
748        if (t != (time_t)t) {
749            opt_printf_stderr("%s: epoch time out of range %s\n",
750                              prog, opt_arg());
751            return 0;
752        }
753        X509_VERIFY_PARAM_set_time(vpm, (time_t)t);
754        break;
755    case OPT_V_VERIFY_HOSTNAME:
756        if (!X509_VERIFY_PARAM_set1_host(vpm, opt_arg(), 0))
757            return 0;
758        break;
759    case OPT_V_VERIFY_EMAIL:
760        if (!X509_VERIFY_PARAM_set1_email(vpm, opt_arg(), 0))
761            return 0;
762        break;
763    case OPT_V_VERIFY_IP:
764        if (!X509_VERIFY_PARAM_set1_ip_asc(vpm, opt_arg()))
765            return 0;
766        break;
767    case OPT_V_IGNORE_CRITICAL:
768        X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_IGNORE_CRITICAL);
769        break;
770    case OPT_V_ISSUER_CHECKS:
771        /* NOP, deprecated */
772        break;
773    case OPT_V_CRL_CHECK:
774        X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_CRL_CHECK);
775        break;
776    case OPT_V_CRL_CHECK_ALL:
777        X509_VERIFY_PARAM_set_flags(vpm,
778                                    X509_V_FLAG_CRL_CHECK |
779                                    X509_V_FLAG_CRL_CHECK_ALL);
780        break;
781    case OPT_V_POLICY_CHECK:
782        X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_POLICY_CHECK);
783        break;
784    case OPT_V_EXPLICIT_POLICY:
785        X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_EXPLICIT_POLICY);
786        break;
787    case OPT_V_INHIBIT_ANY:
788        X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_INHIBIT_ANY);
789        break;
790    case OPT_V_INHIBIT_MAP:
791        X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_INHIBIT_MAP);
792        break;
793    case OPT_V_X509_STRICT:
794        X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_X509_STRICT);
795        break;
796    case OPT_V_EXTENDED_CRL:
797        X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_EXTENDED_CRL_SUPPORT);
798        break;
799    case OPT_V_USE_DELTAS:
800        X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_USE_DELTAS);
801        break;
802    case OPT_V_POLICY_PRINT:
803        X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_NOTIFY_POLICY);
804        break;
805    case OPT_V_CHECK_SS_SIG:
806        X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_CHECK_SS_SIGNATURE);
807        break;
808    case OPT_V_TRUSTED_FIRST:
809        X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_TRUSTED_FIRST);
810        break;
811    case OPT_V_SUITEB_128_ONLY:
812        X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_SUITEB_128_LOS_ONLY);
813        break;
814    case OPT_V_SUITEB_128:
815        X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_SUITEB_128_LOS);
816        break;
817    case OPT_V_SUITEB_192:
818        X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_SUITEB_192_LOS);
819        break;
820    case OPT_V_PARTIAL_CHAIN:
821        X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_PARTIAL_CHAIN);
822        break;
823    case OPT_V_NO_ALT_CHAINS:
824        X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_NO_ALT_CHAINS);
825        break;
826    case OPT_V_NO_CHECK_TIME:
827        X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_NO_CHECK_TIME);
828        break;
829    case OPT_V_ALLOW_PROXY_CERTS:
830        X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_ALLOW_PROXY_CERTS);
831        break;
832    }
833    return 1;
834
835}
836
837void opt_begin(void)
838{
839    opt_index = 1;
840    arg = NULL;
841    flag = NULL;
842}
843
844/*
845 * Parse the next flag (and value if specified), return 0 if done, -1 on
846 * error, otherwise the flag's retval.
847 */
848int opt_next(void)
849{
850    char *p;
851    const OPTIONS *o;
852    int ival;
853    long lval;
854    unsigned long ulval;
855    ossl_intmax_t imval;
856    ossl_uintmax_t umval;
857
858    /* Look at current arg; at end of the list? */
859    arg = NULL;
860    p = argv[opt_index];
861    if (p == NULL)
862        return 0;
863
864    /* If word doesn't start with a -, we're done. */
865    if (*p != '-')
866        return 0;
867
868    /* Hit "--" ? We're done. */
869    opt_index++;
870    if (strcmp(p, "--") == 0)
871        return 0;
872
873    /* Allow -nnn and --nnn */
874    if (*++p == '-')
875        p++;
876    flag = p - 1;
877
878    /* If we have --flag=foo, snip it off */
879    if ((arg = strchr(p, '=')) != NULL)
880        *arg++ = '\0';
881    for (o = opts; o->name; ++o) {
882        /* If not this option, move on to the next one. */
883        if (!(strcmp(p, "h") == 0 && strcmp(o->name, "help") == 0)
884                && strcmp(p, o->name) != 0)
885            continue;
886
887        /* If it doesn't take a value, make sure none was given. */
888        if (o->valtype == 0 || o->valtype == '-') {
889            if (arg) {
890                opt_printf_stderr("%s: Option -%s does not take a value\n",
891                                  prog, p);
892                return -1;
893            }
894            return o->retval;
895        }
896
897        /* Want a value; get the next param if =foo not used. */
898        if (arg == NULL) {
899            if (argv[opt_index] == NULL) {
900                opt_printf_stderr("%s: Option -%s needs a value\n",
901                                  prog, o->name);
902                return -1;
903            }
904            arg = argv[opt_index++];
905        }
906
907        /* Syntax-check value. */
908        switch (o->valtype) {
909        default:
910        case 's':
911        case ':':
912            /* Just a string. */
913            break;
914        case '.':
915            /* Parameters */
916            break;
917        case '/':
918            if (opt_isdir(arg) > 0)
919                break;
920            opt_printf_stderr("%s: Not a directory: %s\n", prog, arg);
921            return -1;
922        case '<':
923            /* Input file. */
924            break;
925        case '>':
926            /* Output file. */
927            break;
928        case 'p':
929        case 'n':
930        case 'N':
931            if (!opt_int(arg, &ival))
932                return -1;
933            if (o->valtype == 'p' && ival <= 0) {
934                opt_printf_stderr("%s: Non-positive number \"%s\" for option -%s\n",
935                                  prog, arg, o->name);
936                return -1;
937            }
938            if (o->valtype == 'N' && ival < 0) {
939                opt_printf_stderr("%s: Negative number \"%s\" for option -%s\n",
940                                  prog, arg, o->name);
941                return -1;
942            }
943            break;
944        case 'M':
945            if (!opt_intmax(arg, &imval))
946                return -1;
947            break;
948        case 'U':
949            if (!opt_uintmax(arg, &umval))
950                return -1;
951            break;
952        case 'l':
953            if (!opt_long(arg, &lval))
954                return -1;
955            break;
956        case 'u':
957            if (!opt_ulong(arg, &ulval))
958                return -1;
959            break;
960        case 'c':
961        case 'E':
962        case 'F':
963        case 'f':
964            if (opt_format(arg,
965                           o->valtype == 'c' ? OPT_FMT_PDS :
966                           o->valtype == 'E' ? OPT_FMT_PDE :
967                           o->valtype == 'F' ? OPT_FMT_PEMDER
968                           : OPT_FMT_ANY, &ival))
969                break;
970            opt_printf_stderr("%s: Invalid format \"%s\" for option -%s\n",
971                              prog, arg, o->name);
972            return -1;
973        }
974
975        /* Return the flag value. */
976        return o->retval;
977    }
978    if (unknown != NULL) {
979        dunno = p;
980        return unknown->retval;
981    }
982    opt_printf_stderr("%s: Unknown option: -%s\n", prog, p);
983    return -1;
984}
985
986/* Return the most recent flag parameter. */
987char *opt_arg(void)
988{
989    return arg;
990}
991
992/* Return the most recent flag (option name including the preceding '-'). */
993char *opt_flag(void)
994{
995    return flag;
996}
997
998/* Return the unknown option. */
999char *opt_unknown(void)
1000{
1001    return dunno;
1002}
1003
1004/* Return the rest of the arguments after parsing flags. */
1005char **opt_rest(void)
1006{
1007    return &argv[opt_index];
1008}
1009
1010/* How many items in remaining args? */
1011int opt_num_rest(void)
1012{
1013    int i = 0;
1014    char **pp;
1015
1016    for (pp = opt_rest(); *pp; pp++, i++)
1017        continue;
1018    return i;
1019}
1020
1021/* Return a string describing the parameter type. */
1022static const char *valtype2param(const OPTIONS *o)
1023{
1024    switch (o->valtype) {
1025    case 0:
1026    case '-':
1027        return "";
1028    case ':':
1029        return "uri";
1030    case 's':
1031        return "val";
1032    case '/':
1033        return "dir";
1034    case '<':
1035        return "infile";
1036    case '>':
1037        return "outfile";
1038    case 'p':
1039        return "+int";
1040    case 'n':
1041        return "int";
1042    case 'l':
1043        return "long";
1044    case 'u':
1045        return "ulong";
1046    case 'E':
1047        return "PEM|DER|ENGINE";
1048    case 'F':
1049        return "PEM|DER";
1050    case 'f':
1051        return "format";
1052    case 'M':
1053        return "intmax";
1054    case 'N':
1055        return "nonneg";
1056    case 'U':
1057        return "uintmax";
1058    }
1059    return "parm";
1060}
1061
1062static void opt_print(const OPTIONS *o, int doingparams, int width)
1063{
1064    const char* help;
1065    char start[80 + 1];
1066    char *p;
1067
1068        help = o->helpstr ? o->helpstr : "(No additional info)";
1069        if (o->name == OPT_HELP_STR) {
1070            opt_printf_stderr(help, prog);
1071            return;
1072        }
1073        if (o->name == OPT_SECTION_STR) {
1074            opt_printf_stderr("\n");
1075            opt_printf_stderr(help, prog);
1076            return;
1077        }
1078        if (o->name == OPT_PARAM_STR) {
1079            opt_printf_stderr("\nParameters:\n");
1080            return;
1081        }
1082
1083        /* Pad out prefix */
1084        memset(start, ' ', sizeof(start) - 1);
1085        start[sizeof(start) - 1] = '\0';
1086
1087        if (o->name == OPT_MORE_STR) {
1088            /* Continuation of previous line; pad and print. */
1089            start[width] = '\0';
1090            opt_printf_stderr("%s  %s\n", start, help);
1091            return;
1092        }
1093
1094        /* Build up the "-flag [param]" part. */
1095        p = start;
1096        *p++ = ' ';
1097        if (!doingparams)
1098            *p++ = '-';
1099        if (o->name[0])
1100            p += strlen(strcpy(p, o->name));
1101        else
1102            *p++ = '*';
1103        if (o->valtype != '-') {
1104            *p++ = ' ';
1105            p += strlen(strcpy(p, valtype2param(o)));
1106        }
1107        *p = ' ';
1108        if ((int)(p - start) >= MAX_OPT_HELP_WIDTH) {
1109            *p = '\0';
1110            opt_printf_stderr("%s\n", start);
1111            memset(start, ' ', sizeof(start));
1112        }
1113        start[width] = '\0';
1114        opt_printf_stderr("%s  %s\n", start, help);
1115}
1116
1117void opt_help(const OPTIONS *list)
1118{
1119    const OPTIONS *o;
1120    int i, sawparams = 0, width = 5;
1121    int standard_prolog;
1122    char start[80 + 1];
1123
1124    /* Starts with its own help message? */
1125    standard_prolog = list[0].name != OPT_HELP_STR;
1126
1127    /* Find the widest help. */
1128    for (o = list; o->name; o++) {
1129        if (o->name == OPT_MORE_STR)
1130            continue;
1131        i = 2 + (int)strlen(o->name);
1132        if (o->valtype != '-')
1133            i += 1 + strlen(valtype2param(o));
1134        if (i < MAX_OPT_HELP_WIDTH && i > width)
1135            width = i;
1136        OPENSSL_assert(i < (int)sizeof(start));
1137    }
1138
1139    if (standard_prolog) {
1140        opt_printf_stderr("Usage: %s [options]\n", prog);
1141        if (list[0].name != OPT_SECTION_STR)
1142            opt_printf_stderr("Valid options are:\n", prog);
1143    }
1144
1145    /* Now let's print. */
1146    for (o = list; o->name; o++) {
1147        if (o->name == OPT_PARAM_STR)
1148            sawparams = 1;
1149        opt_print(o, sawparams, width);
1150    }
1151}
1152
1153/* opt_isdir section */
1154#ifdef _WIN32
1155# include <windows.h>
1156int opt_isdir(const char *name)
1157{
1158    DWORD attr;
1159# if defined(UNICODE) || defined(_UNICODE)
1160    size_t i, len_0 = strlen(name) + 1;
1161    WCHAR tempname[MAX_PATH];
1162
1163    if (len_0 > MAX_PATH)
1164        return -1;
1165
1166#  if !defined(_WIN32_WCE) || _WIN32_WCE>=101
1167    if (!MultiByteToWideChar(CP_ACP, 0, name, len_0, tempname, MAX_PATH))
1168#  endif
1169        for (i = 0; i < len_0; i++)
1170            tempname[i] = (WCHAR)name[i];
1171
1172    attr = GetFileAttributes(tempname);
1173# else
1174    attr = GetFileAttributes(name);
1175# endif
1176    if (attr == INVALID_FILE_ATTRIBUTES)
1177        return -1;
1178    return ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0);
1179}
1180#else
1181# include <sys/stat.h>
1182# ifndef S_ISDIR
1183#  if defined(_S_IFMT) && defined(_S_IFDIR)
1184#   define S_ISDIR(a)   (((a) & _S_IFMT) == _S_IFDIR)
1185#  else
1186#   define S_ISDIR(a)   (((a) & S_IFMT) == S_IFDIR)
1187#  endif
1188# endif
1189
1190int opt_isdir(const char *name)
1191{
1192# if defined(S_ISDIR)
1193    struct stat st;
1194
1195    if (stat(name, &st) == 0)
1196        return S_ISDIR(st.st_mode);
1197    else
1198        return -1;
1199# else
1200    return -1;
1201# endif
1202}
1203#endif
1204