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