]> git.ipfire.org Git - thirdparty/openssl.git/blame - apps/opt.c
Windows: When installing libraries and executables, install .pdb files as well
[thirdparty/openssl.git] / apps / opt.c
CommitLineData
7e1b7485
RS
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"
7e1b7485
RS
52#include <string.h>
53#if !defined(OPENSSL_SYS_MSDOS)
54# include OPENSSL_UNISTD
55#endif
a3ed492f 56
7e1b7485
RS
57#include <stdlib.h>
58#include <errno.h>
59#include <ctype.h>
bd4850df 60#include <limits.h>
7e1b7485 61#include <openssl/bio.h>
5951e840 62#include <openssl/x509v3.h>
7e1b7485
RS
63
64#define MAX_OPT_HELP_WIDTH 30
65const char OPT_HELP_STR[] = "--";
66const char OPT_MORE_STR[] = "---";
67
68/* Our state */
69static char **argv;
70static int argc;
71static int opt_index;
72static char *arg;
73static char *flag;
74static char *dunno;
75static const OPTIONS *unknown;
76static const OPTIONS *opts;
77static char prog[40];
78
79/*
80 * Return the simple name of the program; removing various platform gunk.
81 */
1fbab1dc 82#if defined(OPENSSL_SYS_WIN32)
7e1b7485
RS
83char *opt_progname(const char *argv0)
84{
45f13518 85 size_t i, n;
7e1b7485
RS
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 &&
a3ed492f 99 (strcmp(&p[n - 4], ".exe") == 0 || strcmp(&p[n - 4], ".EXE") == 0))
7e1b7485 100 n -= 4;
7e1b7485
RS
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++)
a3ed492f 106 *q++ = isupper(*p) ? tolower(*p) : *p;
7e1b7485
RS
107 *q = '\0';
108 return prog;
109}
110
111#elif defined(OPENSSL_SYS_VMS)
112
113char *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';
211a68b4 127 if (q != NULL && q - p < sizeof prog)
7e1b7485
RS
128 prog[q - p] = '\0';
129 return prog;
130}
131
132#else
133
134char *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
150char *opt_getprog(void)
151{
152 return prog;
153}
154
155/* Set up the arg parsing. */
156char *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) {
7e1b7485 167#ifndef NDEBUG
b286cb8e 168 const OPTIONS *next;
88806cfc 169 int duplicated, i;
7e1b7485
RS
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);
03f887ca 180 switch (i) {
0c20802c
VD
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':
03f887ca
VD
184 break;
185 default:
186 assert(0);
187 }
7e1b7485
RS
188
189 /* Make sure there are no duplicates. */
88806cfc 190 for (next = o + 1; next->name; ++next) {
7e1b7485 191 /*
88806cfc 192 * Some compilers inline strcmp and the assert string is too long.
7e1b7485 193 */
88806cfc
RS
194 duplicated = strcmp(o->name, next->name) == 0;
195 assert(!duplicated);
7e1b7485
RS
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
207static 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. */
222int 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. */
240int 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':
0bc2f365
RS
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;
7e1b7485
RS
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. */
317int 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 */
329int 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. */
339int 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
7e1b7485
RS
354/* Parse an int, put it into *result; return 0 on failure, else 1. */
355int opt_int(const char *value, int *result)
356{
bd4850df
RS
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",
7e1b7485
RS
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. */
371int opt_long(const char *value, long *result)
372{
bd4850df
RS
373 int oerrno = errno;
374 long l;
375 char *endp;
376
c3a7e0c5 377 errno = 0;
bd4850df
RS
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;
7e1b7485
RS
386 return 0;
387 }
bd4850df
RS
388 *result = l;
389 errno = oerrno;
7e1b7485
RS
390 return 1;
391}
392
d94a1a70
VD
393#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L && \
394 defined(INTMAX_MAX) && defined(UINTMAX_MAX)
03f887ca
VD
395
396/* Parse an intmax_t, put it into *result; return 0 on failure, else 1. */
397int opt_imax(const char *value, intmax_t *result)
398{
399 int oerrno = errno;
400 intmax_t m;
401 char *endp;
402
c3a7e0c5 403 errno = 0;
03f887ca
VD
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. */
420int opt_umax(const char *value, uintmax_t *result)
421{
422 int oerrno = errno;
423 uintmax_t m;
424 char *endp;
425
c3a7e0c5 426 errno = 0;
03f887ca
VD
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
7e1b7485
RS
443/*
444 * Parse an unsigned long, put it into *result; return 0 on failure, else 1.
445 */
446int opt_ulong(const char *value, unsigned long *result)
447{
bd4850df 448 int oerrno = errno;
7e1b7485 449 char *endptr;
bd4850df
RS
450 unsigned long l;
451
c3a7e0c5 452 errno = 0;
bd4850df
RS
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;
7e1b7485
RS
461 return 0;
462 }
bd4850df
RS
463 *result = l;
464 errno = oerrno;
7e1b7485
RS
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 */
473enum range { OPT_V_ENUM };
474
475int opt_verify(int opt, X509_VERIFY_PARAM *vpm)
476{
7e1b7485 477 int i;
03f887ca 478 ossl_intmax_t t = 0;
7e1b7485
RS
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:
0daccd4d 500 /* purpose name -> purpose index */
7e1b7485
RS
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 }
0daccd4d
VD
506
507 /* purpose index -> purpose object */
7e1b7485 508 xptmp = X509_PURPOSE_get0(i);
0daccd4d
VD
509
510 /* purpose object -> purpose value */
7e1b7485 511 i = X509_PURPOSE_get_id(xptmp);
0daccd4d
VD
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 }
7e1b7485
RS
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;
fbb82a60
VD
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;
7e1b7485 539 case OPT_V_ATTIME:
03f887ca
VD
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);
7e1b7485
RS
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:
d33def66 565 /* NOP, deprecated */
7e1b7485
RS
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);
dccd20d1 619 break;
d35ff2c0
DW
620 case OPT_V_NO_CHECK_TIME:
621 X509_VERIFY_PARAM_set_flags(vpm, X509_V_FLAG_NO_CHECK_TIME);
dccd20d1 622 break;
7e1b7485
RS
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 */
632int opt_next(void)
633{
634 char *p;
7e1b7485 635 const OPTIONS *o;
bd4850df 636 int ival;
03f887ca
VD
637 long lval;
638 unsigned long ulval;
639 ossl_intmax_t imval;
640 ossl_uintmax_t umval;
7e1b7485
RS
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. */
7e1b7485
RS
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':
bd4850df
RS
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;
7e1b7485 725 }
bd4850df 726 break;
03f887ca
VD
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;
0c20802c 743 case 'l':
03f887ca
VD
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;
7e1b7485 751 case 'u':
03f887ca 752 if (!opt_ulong(arg, &ulval)) {
bd4850df
RS
753 BIO_printf(bio_err,
754 "%s: Invalid number \"%s\" for -%s\n",
755 prog, arg, o->name);
756 return -1;
757 }
758 break;
0c20802c 759 case 'E':
7e1b7485 760 case 'F':
0c20802c 761 case 'f':
7e1b7485 762 if (opt_format(arg,
0c20802c 763 o->valtype == 'E' ? OPT_FMT_PDE :
7e1b7485 764 o->valtype == 'F' ? OPT_FMT_PEMDER
bd4850df 765 : OPT_FMT_ANY, &ival))
7e1b7485
RS
766 break;
767 BIO_printf(bio_err,
768 "%s: Invalid format \"%s\" for -%s\n",
769 prog, arg, o->name);
770 return -1;
771 }
772
773 /* Return the flag value. */
774 return o->retval;
775 }
776 if (unknown != NULL) {
777 dunno = p;
778 return unknown->retval;
779 }
780 BIO_printf(bio_err, "%s: Option unknown option -%s\n", prog, p);
781 return -1;
782}
783
784/* Return the most recent flag parameter. */
785char *opt_arg(void)
786{
787 return arg;
788}
789
790/* Return the most recent flag. */
791char *opt_flag(void)
792{
793 return flag;
794}
795
796/* Return the unknown option. */
797char *opt_unknown(void)
798{
799 return dunno;
800}
801
802/* Return the rest of the arguments after parsing flags. */
803char **opt_rest(void)
804{
805 return &argv[opt_index];
806}
807
808/* How many items in remaining args? */
809int opt_num_rest(void)
810{
811 int i = 0;
812 char **pp;
813
814 for (pp = opt_rest(); *pp; pp++, i++)
815 continue;
816 return i;
817}
818
819/* Return a string describing the parameter type. */
820static const char *valtype2param(const OPTIONS *o)
821{
822 switch (o->valtype) {
6755ff11 823 case 0:
7e1b7485
RS
824 case '-':
825 return "";
826 case 's':
827 return "val";
828 case '/':
829 return "dir";
830 case '<':
831 return "infile";
832 case '>':
833 return "outfile";
834 case 'p':
0c20802c 835 return "+int";
7e1b7485 836 case 'n':
0c20802c
VD
837 return "int";
838 case 'l':
839 return "long";
7e1b7485 840 case 'u':
0c20802c
VD
841 return "ulong";
842 case 'E':
843 return "PEM|DER|ENGINE";
7e1b7485 844 case 'F':
0c20802c 845 return "PEM|DER";
7e1b7485
RS
846 case 'f':
847 return "format";
0c20802c
VD
848 case 'M':
849 return "intmax";
850 case 'U':
851 return "uintmax";
7e1b7485
RS
852 }
853 return "parm";
854}
855
856void opt_help(const OPTIONS *list)
857{
858 const OPTIONS *o;
859 int i;
860 int standard_prolog;
861 int width = 5;
862 char start[80 + 1];
863 char *p;
864 const char *help;
865
866 /* Starts with its own help message? */
867 standard_prolog = list[0].name != OPT_HELP_STR;
868
869 /* Find the widest help. */
870 for (o = list; o->name; o++) {
871 if (o->name == OPT_MORE_STR)
872 continue;
873 i = 2 + (int)strlen(o->name);
874 if (o->valtype != '-')
875 i += 1 + strlen(valtype2param(o));
876 if (i < MAX_OPT_HELP_WIDTH && i > width)
877 width = i;
878 assert(i < (int)sizeof start);
879 }
880
881 if (standard_prolog)
882 BIO_printf(bio_err, "Usage: %s [options]\nValid options are:\n",
883 prog);
884
885 /* Now let's print. */
886 for (o = list; o->name; o++) {
887 help = o->helpstr ? o->helpstr : "(No additional info)";
888 if (o->name == OPT_HELP_STR) {
889 BIO_printf(bio_err, help, prog);
890 continue;
891 }
892
893 /* Pad out prefix */
16f8d4eb 894 memset(start, ' ', sizeof(start) - 1);
7e1b7485
RS
895 start[sizeof start - 1] = '\0';
896
897 if (o->name == OPT_MORE_STR) {
898 /* Continuation of previous line; padd and print. */
899 start[width] = '\0';
900 BIO_printf(bio_err, "%s %s\n", start, help);
901 continue;
902 }
903
904 /* Build up the "-flag [param]" part. */
905 p = start;
906 *p++ = ' ';
907 *p++ = '-';
908 if (o->name[0])
909 p += strlen(strcpy(p, o->name));
910 else
911 *p++ = '*';
912 if (o->valtype != '-') {
913 *p++ = ' ';
914 p += strlen(strcpy(p, valtype2param(o)));
915 }
916 *p = ' ';
917 if ((int)(p - start) >= MAX_OPT_HELP_WIDTH) {
918 *p = '\0';
919 BIO_printf(bio_err, "%s\n", start);
16f8d4eb 920 memset(start, ' ', sizeof(start));
7e1b7485
RS
921 }
922 start[width] = '\0';
923 BIO_printf(bio_err, "%s %s\n", start, help);
924 }
925}
926
927#ifdef COMPILE_STANDALONE_TEST_DRIVER
928# include <sys/stat.h>
929
930typedef enum OPTION_choice {
931 OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
932 OPT_IN, OPT_INFORM, OPT_OUT, OPT_COUNT, OPT_U, OPT_FLAG,
933 OPT_STR, OPT_NOTUSED
934} OPTION_CHOICE;
935
936static OPTIONS options[] = {
937 {OPT_HELP_STR, 1, '-', "Usage: %s flags\n"},
938 {OPT_HELP_STR, 1, '-', "Valid options are:\n"},
939 {"help", OPT_HELP, '-', "Display this summary"},
940 {"in", OPT_IN, '<', "input file"},
941 {OPT_MORE_STR, 1, '-', "more detail about input"},
942 {"inform", OPT_INFORM, 'f', "input file format; defaults to pem"},
943 {"out", OPT_OUT, '>', "output file"},
944 {"count", OPT_COUNT, 'p', "a counter greater than zero"},
945 {"u", OPT_U, 'u', "an unsigned number"},
946 {"flag", OPT_FLAG, 0, "just some flag"},
947 {"str", OPT_STR, 's', "the magic word"},
948 {"areallyverylongoption", OPT_HELP, '-', "long way for help"},
949 {NULL}
950};
951
952BIO *bio_err;
953
954int app_isdir(const char *name)
955{
956 struct stat sb;
957
958 return name != NULL && stat(name, &sb) >= 0 && S_ISDIR(sb.st_mode);
959}
960
961int main(int ac, char **av)
962{
963 OPTION_CHOICE o;
964 char **rest;
965 char *prog;
966
967 bio_err = BIO_new_fp(stderr, BIO_NOCLOSE | BIO_FP_TEXT);
968
969 prog = opt_init(ac, av, options);
970 while ((o = opt_next()) != OPT_EOF) {
971 switch (c) {
972 case OPT_NOTUSED:
973 case OPT_EOF:
974 case OPT_ERR:
975 printf("%s: Usage error; try -help.\n", prog);
976 return 1;
977 case OPT_HELP:
978 opt_help(options);
979 return 0;
980 case OPT_IN:
981 printf("in %s\n", opt_arg());
982 break;
983 case OPT_INFORM:
984 printf("inform %s\n", opt_arg());
985 break;
986 case OPT_OUT:
987 printf("out %s\n", opt_arg());
988 break;
989 case OPT_COUNT:
990 printf("count %s\n", opt_arg());
991 break;
992 case OPT_U:
993 printf("u %s\n", opt_arg());
994 break;
995 case OPT_FLAG:
996 printf("flag\n");
997 break;
998 case OPT_STR:
999 printf("str %s\n", opt_arg());
1000 break;
1001 }
1002 }
1003 argc = opt_num_rest();
1004 argv = opt_rest();
1005
1006 printf("args = %d\n", argc);
1007 if (argc)
1008 while (*argv)
1009 printf(" %s\n", *argv++);
1010 return 0;
1011}
1012#endif