From 2c2724476ef50b8926b033f009bdfc85ac3f1816 Mon Sep 17 00:00:00 2001 From: "Dr. David von Oheimb" Date: Tue, 24 Aug 2021 12:03:12 +0200 Subject: [PATCH] APPS: Add check for multiple 'unknown' options Reviewed-by: Dmitry Belyavskiy (Merged from https://github.com/openssl/openssl/pull/16416) --- apps/cms.c | 1 + apps/crl.c | 1 + apps/dgst.c | 1 + apps/dsa.c | 1 + apps/ec.c | 1 + apps/enc.c | 1 + apps/gendsa.c | 1 + apps/genpkey.c | 1 + apps/genrsa.c | 1 + apps/include/opt.h | 2 ++ apps/lib/opt.c | 19 ++++++++++++++++++- apps/ocsp.c | 9 +++++++-- apps/pkcs12.c | 1 + apps/pkey.c | 1 + apps/req.c | 1 + apps/rsa.c | 1 + apps/smime.c | 1 + apps/storeutl.c | 4 +++- apps/ts.c | 1 + apps/x509.c | 2 +- doc/man1/openssl-ocsp.pod.in | 11 ++++++----- 21 files changed, 52 insertions(+), 10 deletions(-) diff --git a/apps/cms.c b/apps/cms.c index b49d1e3a68..575f8b3625 100644 --- a/apps/cms.c +++ b/apps/cms.c @@ -314,6 +314,7 @@ int cms_main(int argc, char **argv) if (encerts == NULL || vpm == NULL) goto end; + opt_set_unknown_name("cipher"); prog = opt_init(argc, argv, cms_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { diff --git a/apps/crl.c b/apps/crl.c index 8d353ff2af..c8f0981ee7 100644 --- a/apps/crl.c +++ b/apps/crl.c @@ -98,6 +98,7 @@ int crl_main(int argc, char **argv) int hash_old = 0; #endif + opt_set_unknown_name("digest"); prog = opt_init(argc, argv, crl_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { diff --git a/apps/dgst.c b/apps/dgst.c index e75dd72521..18ba3d41c5 100644 --- a/apps/dgst.c +++ b/apps/dgst.c @@ -115,6 +115,7 @@ int dgst_main(int argc, char **argv) buf = app_malloc(BUFSIZE, "I/O buffer"); md = (EVP_MD *)EVP_get_digestbyname(argv[0]); + opt_set_unknown_name("digest"); prog = opt_init(argc, argv, dgst_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { diff --git a/apps/dsa.c b/apps/dsa.c index 9605ed81e7..fae277b8a2 100644 --- a/apps/dsa.c +++ b/apps/dsa.c @@ -92,6 +92,7 @@ int dsa_main(int argc, char **argv) int selection = 0; OSSL_ENCODER_CTX *ectx = NULL; + opt_set_unknown_name("cipher"); prog = opt_init(argc, argv, dsa_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { diff --git a/apps/ec.c b/apps/ec.c index 4573300a5e..2c350ff0b4 100644 --- a/apps/ec.c +++ b/apps/ec.c @@ -80,6 +80,7 @@ int ec_main(int argc, char **argv) char *point_format = NULL; int no_public = 0; + opt_set_unknown_name("cipher"); prog = opt_init(argc, argv, ec_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { diff --git a/apps/enc.c b/apps/enc.c index e71453c3c4..b14129d9b0 100644 --- a/apps/enc.c +++ b/apps/enc.c @@ -143,6 +143,7 @@ int enc_main(int argc, char **argv) else if (strcmp(argv[0], "enc") != 0) ciphername = argv[0]; + opt_set_unknown_name("cipher"); prog = opt_init(argc, argv, enc_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { diff --git a/apps/gendsa.c b/apps/gendsa.c index b9bc2f502b..c4070c9e1a 100644 --- a/apps/gendsa.c +++ b/apps/gendsa.c @@ -62,6 +62,7 @@ int gendsa_main(int argc, char **argv) OPTION_CHOICE o; int ret = 1, private = 0, verbose = 0, nbits; + opt_set_unknown_name("cipher"); prog = opt_init(argc, argv, gendsa_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { diff --git a/apps/genpkey.c b/apps/genpkey.c index 7f70a6baa2..f4c8f92c34 100644 --- a/apps/genpkey.c +++ b/apps/genpkey.c @@ -74,6 +74,7 @@ int genpkey_main(int argc, char **argv) OSSL_LIB_CTX *libctx = app_get0_libctx(); STACK_OF(OPENSSL_STRING) *keyopt = NULL; + opt_set_unknown_name("cipher"); prog = opt_init(argc, argv, genpkey_options); keyopt = sk_OPENSSL_STRING_new_null(); if (keyopt == NULL) diff --git a/apps/genrsa.c b/apps/genrsa.c index 1a6c67380f..9d0fea7646 100644 --- a/apps/genrsa.c +++ b/apps/genrsa.c @@ -93,6 +93,7 @@ int genrsa_main(int argc, char **argv) if (bn == NULL || cb == NULL) goto end; + opt_set_unknown_name("cipher"); prog = opt_init(argc, argv, genrsa_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { diff --git a/apps/include/opt.h b/apps/include/opt.h index 9493901c44..365eae5bc8 100644 --- a/apps/include/opt.h +++ b/apps/include/opt.h @@ -365,6 +365,7 @@ int opt_next(void); char *opt_flag(void); char *opt_arg(void); char *opt_unknown(void); +void reset_unknown(void); int opt_cipher(const char *name, EVP_CIPHER **cipherp); int opt_cipher_any(const char *name, EVP_CIPHER **cipherp); int opt_cipher_silent(const char *name, EVP_CIPHER **cipherp); @@ -373,6 +374,7 @@ int opt_md(const char *name, EVP_MD **mdp); int opt_md_silent(const char *name, EVP_MD **mdp); int opt_int(const char *arg, int *result); +void opt_set_unknown_name(const char *name); int opt_int_arg(void); int opt_long(const char *arg, long *result); int opt_ulong(const char *arg, unsigned long *result); diff --git a/apps/lib/opt.c b/apps/lib/opt.c index 7967fa7956..2865a1eefb 100644 --- a/apps/lib/opt.c +++ b/apps/lib/opt.c @@ -41,6 +41,7 @@ static int opt_index; static char *arg; static char *flag; static char *dunno; +static const char *unknown_name; static const OPTIONS *unknown; static const OPTIONS *opts; static char prog[40]; @@ -166,7 +167,6 @@ char *opt_init(int ac, char **av, const OPTIONS *o) opt_begin(); opts = o; unknown = NULL; - /* Make sure prog name is set for usage output */ (void)opt_progname(argv[0]); @@ -215,6 +215,7 @@ char *opt_init(int ac, char **av, const OPTIONS *o) } #endif if (o->name[0] == '\0') { + OPENSSL_assert(unknown_name != NULL); OPENSSL_assert(unknown == NULL); unknown = o; OPENSSL_assert(unknown->valtype == 0 || unknown->valtype == '-'); @@ -236,6 +237,11 @@ static OPT_PAIR formats[] = { {NULL} }; +void opt_set_unknown_name(const char *name) +{ + unknown_name = name; +} + /* Print an error message about a failed format parse. */ static int opt_format_error(const char *s, unsigned long flags) { @@ -985,6 +991,11 @@ int opt_next(void) return o->retval; } if (unknown != NULL) { + if (dunno != NULL) { + opt_printf_stderr("%s: Multiple %s or unknown options: -%s and -%s\n", + prog, unknown_name, dunno, p); + return -1; + } dunno = p; return unknown->retval; } @@ -1010,6 +1021,12 @@ char *opt_unknown(void) return dunno; } +/* Reset the unknown option; needed by ocsp to allow multiple digest options. */ +void reset_unknown(void) +{ + dunno = NULL; +} + /* Return the rest of the arguments after parsing flags. */ char **opt_rest(void) { diff --git a/apps/ocsp.c b/apps/ocsp.c index d8e45ccd43..18e7c44191 100644 --- a/apps/ocsp.c +++ b/apps/ocsp.c @@ -196,8 +196,10 @@ const OPTIONS ocsp_options[] = { {"VAfile", OPT_VAFILE, '<', "Validator certificates file"}, {"verify_other", OPT_VERIFY_OTHER, '<', "Additional certificates to search for signer"}, - {"cert", OPT_CERT, '<', "Certificate to check"}, - {"serial", OPT_SERIAL, 's', "Serial number to check"}, + {"cert", OPT_CERT, '<', + "Certificate to check; may be given multiple times"}, + {"serial", OPT_SERIAL, 's', + "Serial number to check; may be given multiple times"}, {"validity_period", OPT_VALIDITY_PERIOD, 'u', "Maximum validity discrepancy in seconds"}, {"signkey", OPT_SIGNKEY, 's', "Private key to sign OCSP request with"}, @@ -261,6 +263,7 @@ int ocsp_main(int argc, char **argv) || (vpm = X509_VERIFY_PARAM_new()) == NULL) goto end; + opt_set_unknown_name("digest"); prog = opt_init(argc, argv, ocsp_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { @@ -436,6 +439,7 @@ int ocsp_main(int argc, char **argv) goto end; break; case OPT_CERT: + reset_unknown(); X509_free(cert); cert = load_cert(opt_arg(), FORMAT_UNDEF, "certificate"); if (cert == NULL) @@ -449,6 +453,7 @@ int ocsp_main(int argc, char **argv) trailing_md = 0; break; case OPT_SERIAL: + reset_unknown(); if (cert_id_md == NULL) cert_id_md = (EVP_MD *)EVP_sha1(); if (!add_ocsp_serial(&req, opt_arg(), cert_id_md, issuer, ids)) diff --git a/apps/pkcs12.c b/apps/pkcs12.c index 08af7bf3d2..754994e6a9 100644 --- a/apps/pkcs12.c +++ b/apps/pkcs12.c @@ -182,6 +182,7 @@ int pkcs12_main(int argc, char **argv) EVP_CIPHER *enc = (EVP_CIPHER *)default_enc; OPTION_CHOICE o; + opt_set_unknown_name("cipher"); prog = opt_init(argc, argv, pkcs12_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { diff --git a/apps/pkey.c b/apps/pkey.c index 41a4c29897..cfef85ec0e 100644 --- a/apps/pkey.c +++ b/apps/pkey.c @@ -83,6 +83,7 @@ int pkey_main(int argc, char **argv) char *point_format = NULL; #endif + opt_set_unknown_name("cipher"); prog = opt_init(argc, argv, pkey_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { diff --git a/apps/req.c b/apps/req.c index 36ac493807..eaff69faa4 100644 --- a/apps/req.c +++ b/apps/req.c @@ -266,6 +266,7 @@ int req_main(int argc, char **argv) cipher = (EVP_CIPHER *)EVP_des_ede3_cbc(); #endif + opt_set_unknown_name("digest"); prog = opt_init(argc, argv, req_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { diff --git a/apps/rsa.c b/apps/rsa.c index fb73173428..08527f6347 100644 --- a/apps/rsa.c +++ b/apps/rsa.c @@ -139,6 +139,7 @@ int rsa_main(int argc, char **argv) int selection = 0; OSSL_ENCODER_CTX *ectx = NULL; + opt_set_unknown_name("cipher"); prog = opt_init(argc, argv, rsa_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { diff --git a/apps/smime.c b/apps/smime.c index 9677f056ed..6001d444ff 100644 --- a/apps/smime.c +++ b/apps/smime.c @@ -160,6 +160,7 @@ int smime_main(int argc, char **argv) if ((vpm = X509_VERIFY_PARAM_new()) == NULL) return 1; + opt_set_unknown_name("cipher"); prog = opt_init(argc, argv, smime_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { diff --git a/apps/storeutl.c b/apps/storeutl.c index 8d1ce3cea3..65444fc53e 100644 --- a/apps/storeutl.c +++ b/apps/storeutl.c @@ -74,7 +74,7 @@ int storeutl_main(int argc, char *argv[]) BIO *out = NULL; ENGINE *e = NULL; OPTION_CHOICE o; - char *prog = opt_init(argc, argv, storeutl_options); + char *prog; PW_CB_DATA pw_cb_data; int expected = 0; int criterion = 0; @@ -87,6 +87,8 @@ int storeutl_main(int argc, char *argv[]) EVP_MD *digest = NULL; OSSL_LIB_CTX *libctx = app_get0_libctx(); + opt_set_unknown_name("digest"); + prog = opt_init(argc, argv, storeutl_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { case OPT_EOF: diff --git a/apps/ts.c b/apps/ts.c index 8e58ef00b4..2497c3b32a 100644 --- a/apps/ts.c +++ b/apps/ts.c @@ -181,6 +181,7 @@ int ts_main(int argc, char **argv) if ((vpm = X509_VERIFY_PARAM_new()) == NULL) goto end; + opt_set_unknown_name("digest"); prog = opt_init(argc, argv, ts_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { diff --git a/apps/x509.c b/apps/x509.c index 188bc17a09..29dc74ca9e 100644 --- a/apps/x509.c +++ b/apps/x509.c @@ -302,6 +302,7 @@ int x509_main(int argc, char **argv) goto err; X509_STORE_set_verify_cb(ctx, callb); + opt_set_unknown_name("digest"); prog = opt_init(argc, argv, x509_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { @@ -592,7 +593,6 @@ int x509_main(int argc, char **argv) break; } } - /* No extra arguments. */ if (!opt_check_rest_arg(NULL)) goto opthelp; diff --git a/doc/man1/openssl-ocsp.pod.in b/doc/man1/openssl-ocsp.pod.in index fbad5079af..37c7aeb915 100644 --- a/doc/man1/openssl-ocsp.pod.in +++ b/doc/man1/openssl-ocsp.pod.in @@ -102,15 +102,16 @@ specify output filename, default is standard output. =item B<-issuer> I -This specifies the current issuer certificate. This option can be used -multiple times. +This specifies the current issuer certificate. +This option can be used multiple times. This option B come before any B<-cert> options. =item B<-cert> I -Add the certificate I to the request. The issuer certificate -is taken from the previous B<-issuer> option, or an error occurs if no -issuer certificate is specified. +Add the certificate I to the request. +This option can be used multiple times. +The issuer certificate is taken from the previous B<-issuer> option, +or an error occurs if no issuer certificate is specified. =item B<-no_certs> -- 2.34.1