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