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