opt.c 27 KB

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