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