diff options
-rw-r--r-- | src/usr.bin/openssl/req.c | 136 |
1 files changed, 133 insertions, 3 deletions
diff --git a/src/usr.bin/openssl/req.c b/src/usr.bin/openssl/req.c index 6b7dfb98b9..29a47cbfed 100644 --- a/src/usr.bin/openssl/req.c +++ b/src/usr.bin/openssl/req.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: req.c,v 1.16 2019/07/03 03:24:02 deraadt Exp $ */ | 1 | /* $OpenBSD: req.c,v 1.17 2019/11/06 10:35:40 inoguchi Exp $ */ |
2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) | 2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
3 | * All rights reserved. | 3 | * All rights reserved. |
4 | * | 4 | * |
@@ -62,9 +62,10 @@ | |||
62 | #undef OPENSSL_NO_DEPRECATED | 62 | #undef OPENSSL_NO_DEPRECATED |
63 | #endif | 63 | #endif |
64 | 64 | ||
65 | #include <ctype.h> | ||
66 | #include <limits.h> | ||
65 | #include <stdio.h> | 67 | #include <stdio.h> |
66 | #include <stdlib.h> | 68 | #include <stdlib.h> |
67 | #include <limits.h> | ||
68 | #include <string.h> | 69 | #include <string.h> |
69 | #include <time.h> | 70 | #include <time.h> |
70 | 71 | ||
@@ -141,7 +142,12 @@ static int req_check_len(int len, int n_min, int n_max); | |||
141 | static int check_end(const char *str, const char *end); | 142 | static int check_end(const char *str, const char *end); |
142 | static EVP_PKEY_CTX *set_keygen_ctx(BIO * err, const char *gstr, int *pkey_type, | 143 | static EVP_PKEY_CTX *set_keygen_ctx(BIO * err, const char *gstr, int *pkey_type, |
143 | long *pkeylen, char **palgnam); | 144 | long *pkeylen, char **palgnam); |
145 | static unsigned long ext_name_hash(const OPENSSL_STRING *a); | ||
146 | static int ext_name_cmp(const OPENSSL_STRING *a, const OPENSSL_STRING *b); | ||
147 | static void exts_cleanup(OPENSSL_STRING *x); | ||
148 | static int duplicated(LHASH_OF(OPENSSL_STRING) *addexts, char *kv); | ||
144 | static CONF *req_conf = NULL; | 149 | static CONF *req_conf = NULL; |
150 | static CONF *addext_conf = NULL; | ||
145 | static int batch = 0; | 151 | static int batch = 0; |
146 | 152 | ||
147 | int | 153 | int |
@@ -155,6 +161,7 @@ req_main(int argc, char **argv) | |||
155 | const char *keyalg = NULL; | 161 | const char *keyalg = NULL; |
156 | char *keyalgstr = NULL; | 162 | char *keyalgstr = NULL; |
157 | STACK_OF(OPENSSL_STRING) * pkeyopts = NULL, *sigopts = NULL; | 163 | STACK_OF(OPENSSL_STRING) * pkeyopts = NULL, *sigopts = NULL; |
164 | LHASH_OF(OPENSSL_STRING) *addexts = NULL; | ||
158 | EVP_PKEY *pkey = NULL; | 165 | EVP_PKEY *pkey = NULL; |
159 | int i = 0, badops = 0, newreq = 0, verbose = 0, pkey_type = -1; | 166 | int i = 0, badops = 0, newreq = 0, verbose = 0, pkey_type = -1; |
160 | long newkey = -1; | 167 | long newkey = -1; |
@@ -163,6 +170,7 @@ req_main(int argc, char **argv) | |||
163 | int nodes = 0, kludge = 0, newhdr = 0, subject = 0, pubkey = 0; | 170 | int nodes = 0, kludge = 0, newhdr = 0, subject = 0, pubkey = 0; |
164 | char *infile, *outfile, *prog, *keyfile = NULL, *template = NULL, | 171 | char *infile, *outfile, *prog, *keyfile = NULL, *template = NULL, |
165 | *keyout = NULL; | 172 | *keyout = NULL; |
173 | BIO *addext_bio = NULL; | ||
166 | char *extensions = NULL; | 174 | char *extensions = NULL; |
167 | char *req_exts = NULL; | 175 | char *req_exts = NULL; |
168 | const EVP_CIPHER *cipher = NULL; | 176 | const EVP_CIPHER *cipher = NULL; |
@@ -319,6 +327,23 @@ req_main(int argc, char **argv) | |||
319 | serial = s2i_ASN1_INTEGER(NULL, *(++argv)); | 327 | serial = s2i_ASN1_INTEGER(NULL, *(++argv)); |
320 | if (!serial) | 328 | if (!serial) |
321 | goto bad; | 329 | goto bad; |
330 | } else if (strcmp(*argv, "-addext") == 0) { | ||
331 | if (--argc < 1) | ||
332 | goto bad; | ||
333 | p = *(++argv); | ||
334 | if (addexts == NULL) { | ||
335 | addexts = (LHASH_OF(OPENSSL_STRING) *)lh_new( | ||
336 | (LHASH_HASH_FN_TYPE)ext_name_hash, | ||
337 | (LHASH_COMP_FN_TYPE)ext_name_cmp); | ||
338 | addext_bio = BIO_new(BIO_s_mem()); | ||
339 | if (addexts == NULL || addext_bio == NULL) | ||
340 | goto bad; | ||
341 | } | ||
342 | i = duplicated(addexts, p); | ||
343 | if (i == 1) | ||
344 | goto bad; | ||
345 | if (i < 0 || BIO_printf(addext_bio, "%s\n", p) < 0) | ||
346 | goto bad; | ||
322 | } else if (strcmp(*argv, "-extensions") == 0) { | 347 | } else if (strcmp(*argv, "-extensions") == 0) { |
323 | if (--argc < 1) | 348 | if (--argc < 1) |
324 | goto bad; | 349 | goto bad; |
@@ -373,6 +398,7 @@ req_main(int argc, char **argv) | |||
373 | BIO_printf(bio_err, " -newhdr output \"NEW\" in the header lines\n"); | 398 | BIO_printf(bio_err, " -newhdr output \"NEW\" in the header lines\n"); |
374 | BIO_printf(bio_err, " -asn1-kludge Output the 'request' in a format that is wrong but some CA's\n"); | 399 | BIO_printf(bio_err, " -asn1-kludge Output the 'request' in a format that is wrong but some CA's\n"); |
375 | BIO_printf(bio_err, " have been reported as requiring\n"); | 400 | BIO_printf(bio_err, " have been reported as requiring\n"); |
401 | BIO_printf(bio_err, " -addext .. additional cert extension key=value pair (may be given more than once)\n"); | ||
376 | BIO_printf(bio_err, " -extensions .. specify certificate extension section (override value in config file)\n"); | 402 | BIO_printf(bio_err, " -extensions .. specify certificate extension section (override value in config file)\n"); |
377 | BIO_printf(bio_err, " -reqexts .. specify request extension section (override value in config file)\n"); | 403 | BIO_printf(bio_err, " -reqexts .. specify request extension section (override value in config file)\n"); |
378 | BIO_printf(bio_err, " -utf8 input characters are UTF8 (default ASCII)\n"); | 404 | BIO_printf(bio_err, " -utf8 input characters are UTF8 (default ASCII)\n"); |
@@ -408,6 +434,21 @@ req_main(int argc, char **argv) | |||
408 | default_config_file); | 434 | default_config_file); |
409 | } | 435 | } |
410 | 436 | ||
437 | if (addext_bio != NULL) { | ||
438 | long errline = -1; | ||
439 | if (verbose) | ||
440 | BIO_printf(bio_err, | ||
441 | "Using additional configuration from command line\n"); | ||
442 | addext_conf = NCONF_new(NULL); | ||
443 | i = NCONF_load_bio(addext_conf, addext_bio, &errline); | ||
444 | if (i == 0) { | ||
445 | BIO_printf(bio_err, | ||
446 | "req: Error on line %ld of config input\n", | ||
447 | errline); | ||
448 | goto end; | ||
449 | } | ||
450 | } | ||
451 | |||
411 | if (req_conf != NULL) { | 452 | if (req_conf != NULL) { |
412 | if (!load_config(bio_err, req_conf)) | 453 | if (!load_config(bio_err, req_conf)) |
413 | goto end; | 454 | goto end; |
@@ -457,6 +498,17 @@ req_main(int argc, char **argv) | |||
457 | goto end; | 498 | goto end; |
458 | } | 499 | } |
459 | } | 500 | } |
501 | if (addext_conf != NULL) { | ||
502 | /* Check syntax of command line extensions */ | ||
503 | X509V3_CTX ctx; | ||
504 | X509V3_set_ctx_test(&ctx); | ||
505 | X509V3_set_nconf(&ctx, addext_conf); | ||
506 | if (!X509V3_EXT_add_nconf(addext_conf, &ctx, "default", NULL)) { | ||
507 | BIO_printf(bio_err, | ||
508 | "Error Loading command line extensions\n"); | ||
509 | goto end; | ||
510 | } | ||
511 | } | ||
460 | if (!passin) { | 512 | if (!passin) { |
461 | passin = NCONF_get_string(req_conf, SECTION, "input_password"); | 513 | passin = NCONF_get_string(req_conf, SECTION, "input_password"); |
462 | if (!passin) | 514 | if (!passin) |
@@ -660,7 +712,8 @@ req_main(int argc, char **argv) | |||
660 | goto end; | 712 | goto end; |
661 | 713 | ||
662 | /* Set version to V3 */ | 714 | /* Set version to V3 */ |
663 | if (extensions && !X509_set_version(x509ss, 2)) | 715 | if ((extensions != NULL || addext_conf != NULL) && |
716 | !X509_set_version(x509ss, 2)) | ||
664 | goto end; | 717 | goto end; |
665 | if (serial) { | 718 | if (serial) { |
666 | if (!X509_set_serialNumber(x509ss, serial)) | 719 | if (!X509_set_serialNumber(x509ss, serial)) |
@@ -697,6 +750,13 @@ req_main(int argc, char **argv) | |||
697 | extensions); | 750 | extensions); |
698 | goto end; | 751 | goto end; |
699 | } | 752 | } |
753 | if (addext_conf != NULL && | ||
754 | !X509V3_EXT_add_nconf(addext_conf, &ext_ctx, | ||
755 | "default", x509ss)) { | ||
756 | BIO_printf(bio_err, | ||
757 | "Error Loading command line extensions\n"); | ||
758 | goto end; | ||
759 | } | ||
700 | i = do_X509_sign(bio_err, x509ss, pkey, digest, sigopts); | 760 | i = do_X509_sign(bio_err, x509ss, pkey, digest, sigopts); |
701 | if (!i) { | 761 | if (!i) { |
702 | ERR_print_errors(bio_err); | 762 | ERR_print_errors(bio_err); |
@@ -718,6 +778,13 @@ req_main(int argc, char **argv) | |||
718 | req_exts); | 778 | req_exts); |
719 | goto end; | 779 | goto end; |
720 | } | 780 | } |
781 | if (addext_conf != NULL && | ||
782 | !X509V3_EXT_REQ_add_nconf(addext_conf, &ext_ctx, | ||
783 | "default", req)) { | ||
784 | BIO_printf(bio_err, | ||
785 | "Error Loading command line extensions\n"); | ||
786 | goto end; | ||
787 | } | ||
721 | i = do_X509_REQ_sign(bio_err, req, pkey, digest, sigopts); | 788 | i = do_X509_REQ_sign(bio_err, req, pkey, digest, sigopts); |
722 | if (!i) { | 789 | if (!i) { |
723 | ERR_print_errors(bio_err); | 790 | ERR_print_errors(bio_err); |
@@ -864,6 +931,8 @@ req_main(int argc, char **argv) | |||
864 | } | 931 | } |
865 | if ((req_conf != NULL) && (req_conf != config)) | 932 | if ((req_conf != NULL) && (req_conf != config)) |
866 | NCONF_free(req_conf); | 933 | NCONF_free(req_conf); |
934 | NCONF_free(addext_conf); | ||
935 | BIO_free(addext_bio); | ||
867 | BIO_free(in); | 936 | BIO_free(in); |
868 | BIO_free_all(out); | 937 | BIO_free_all(out); |
869 | EVP_PKEY_free(pkey); | 938 | EVP_PKEY_free(pkey); |
@@ -873,6 +942,8 @@ req_main(int argc, char **argv) | |||
873 | sk_OPENSSL_STRING_free(pkeyopts); | 942 | sk_OPENSSL_STRING_free(pkeyopts); |
874 | if (sigopts) | 943 | if (sigopts) |
875 | sk_OPENSSL_STRING_free(sigopts); | 944 | sk_OPENSSL_STRING_free(sigopts); |
945 | lh_OPENSSL_STRING_doall(addexts, (LHASH_DOALL_FN_TYPE)exts_cleanup); | ||
946 | lh_OPENSSL_STRING_free(addexts); | ||
876 | free(keyalgstr); | 947 | free(keyalgstr); |
877 | X509_REQ_free(req); | 948 | X509_REQ_free(req); |
878 | X509_free(x509ss); | 949 | X509_free(x509ss); |
@@ -1558,3 +1629,62 @@ do_X509_CRL_sign(BIO * err, X509_CRL * x, EVP_PKEY * pkey, const EVP_MD * md, | |||
1558 | EVP_MD_CTX_cleanup(&mctx); | 1629 | EVP_MD_CTX_cleanup(&mctx); |
1559 | return rv > 0 ? 1 : 0; | 1630 | return rv > 0 ? 1 : 0; |
1560 | } | 1631 | } |
1632 | |||
1633 | static unsigned long | ||
1634 | ext_name_hash(const OPENSSL_STRING *a) | ||
1635 | { | ||
1636 | return lh_strhash((const char *)a); | ||
1637 | } | ||
1638 | |||
1639 | static int | ||
1640 | ext_name_cmp(const OPENSSL_STRING *a, const OPENSSL_STRING *b) | ||
1641 | { | ||
1642 | return strcmp((const char *)a, (const char *)b); | ||
1643 | } | ||
1644 | |||
1645 | static void | ||
1646 | exts_cleanup(OPENSSL_STRING *x) | ||
1647 | { | ||
1648 | free((char *)x); | ||
1649 | } | ||
1650 | |||
1651 | /* | ||
1652 | * Is the |kv| key already duplicated ? This is remarkably tricky to get right. | ||
1653 | * Return 0 if unique, -1 on runtime error; 1 if found or a syntax error. | ||
1654 | */ | ||
1655 | static int | ||
1656 | duplicated(LHASH_OF(OPENSSL_STRING) *addexts, char *kv) | ||
1657 | { | ||
1658 | char *p; | ||
1659 | size_t off; | ||
1660 | |||
1661 | /* Check syntax. */ | ||
1662 | /* Skip leading whitespace, make a copy. */ | ||
1663 | while (*kv && isspace(*kv)) | ||
1664 | if (*++kv == '\0') | ||
1665 | return 1; | ||
1666 | if ((p = strchr(kv, '=')) == NULL) | ||
1667 | return 1; | ||
1668 | off = p - kv; | ||
1669 | if ((kv = strdup(kv)) == NULL) | ||
1670 | return -1; | ||
1671 | |||
1672 | /* Skip trailing space before the equal sign. */ | ||
1673 | for (p = kv + off; p > kv; --p) | ||
1674 | if (!isspace(p[-1])) | ||
1675 | break; | ||
1676 | if (p == kv) { | ||
1677 | free(kv); | ||
1678 | return 1; | ||
1679 | } | ||
1680 | *p = '\0'; | ||
1681 | |||
1682 | /* See if "key" is there by attempting to add it. */ | ||
1683 | if ((p = (char *)lh_OPENSSL_STRING_insert(addexts, (OPENSSL_STRING*)kv)) | ||
1684 | != NULL || lh_OPENSSL_STRING_error(addexts)) { | ||
1685 | free(p != NULL ? p : kv); | ||
1686 | return -1; | ||
1687 | } | ||
1688 | |||
1689 | return 0; | ||
1690 | } | ||