summaryrefslogtreecommitdiffstats
path: root/apps/req.c
diff options
context:
space:
mode:
authorRich Salz <rsalz@openssl.org>2018-07-06 01:57:22 +0200
committerRich Salz <rsalz@openssl.org>2018-07-06 01:57:22 +0200
commit2ddee136ec4157598b0679f9d5a5097ed77c4c01 (patch)
tree6115e7b9bbf3747efb164a3402e61eef31ebfc2d /apps/req.c
parentAdd missing include file to doc (diff)
downloadopenssl-2ddee136ec4157598b0679f9d5a5097ed77c4c01.tar.xz
openssl-2ddee136ec4157598b0679f9d5a5097ed77c4c01.zip
Reject duplicate -addext parameters
Reviewed-by: Paul Dale <paul.dale@oracle.com> (Merged from https://github.com/openssl/openssl/pull/6636)
Diffstat (limited to 'apps/req.c')
-rw-r--r--apps/req.c80
1 files changed, 77 insertions, 3 deletions
diff --git a/apps/req.c b/apps/req.c
index 7e7b994f0d..3d89f2000c 100644
--- a/apps/req.c
+++ b/apps/req.c
@@ -11,6 +11,7 @@
#include <stdlib.h>
#include <time.h>
#include <string.h>
+#include <ctype.h>
#include "apps.h"
#include "progs.h"
#include <openssl/bio.h>
@@ -23,6 +24,8 @@
#include <openssl/objects.h>
#include <openssl/pem.h>
#include <openssl/bn.h>
+#include <openssl/bn.h>
+#include <openssl/lhash.h>
#ifndef OPENSSL_NO_RSA
# include <openssl/rsa.h>
#endif
@@ -147,6 +150,68 @@ const OPTIONS req_options[] = {
{NULL}
};
+
+/*
+ * An LHASH of strings, where each string is an extension name.
+ */
+static unsigned long ext_name_hash(const OPENSSL_STRING *a)
+{
+ return OPENSSL_LH_strhash((const char *)a);
+}
+
+static int ext_name_cmp(const OPENSSL_STRING *a, const OPENSSL_STRING *b)
+{
+ return strcmp((const char *)a, (const char *)b);
+}
+
+static void exts_cleanup(OPENSSL_STRING *x)
+{
+ OPENSSL_free((char *)x);
+}
+
+/*
+ * Is the |kv| key already duplicated? This is remarkably tricky to get
+ * right. Return 0 if unique, -1 on runtime error; 1 if found or a syntax
+ * error.
+ */
+static int duplicated(LHASH_OF(OPENSSL_STRING) *addexts, char *kv)
+{
+ char *p;
+
+ /* Check syntax. */
+ if (strchr(kv, '=') == NULL)
+ return 1;
+
+ /* Skip leading whitespace, make a copy. */
+ while (*kv && isspace(*kv))
+ if (*++kv == '\0')
+ return 1;
+ if ((kv = OPENSSL_strdup(kv)) == NULL)
+ return -1;
+
+ /* Skip trailing space before the equal sign. */
+ for (p = strchr(kv, '='); p > kv; --p)
+ if (p[-1] != ' ' && p[-1] != '\t')
+ break;
+ if (p == kv) {
+ OPENSSL_free(kv);
+ return 1;
+ }
+ *p = '\0';
+
+ /* Finally have a clean "key"; see if it's there. */
+ if (lh_OPENSSL_STRING_retrieve(addexts, (OPENSSL_STRING*)kv) != NULL) {
+ BIO_printf(bio_err, "Extension \"%s\" repeated\n", kv);
+ OPENSSL_free(kv);
+ return 1;
+ }
+
+ /* Not found; add it. */
+ if (lh_OPENSSL_STRING_insert(addexts, (OPENSSL_STRING*)kv) == NULL)
+ return -1;
+ return 0;
+}
+
int req_main(int argc, char **argv)
{
ASN1_INTEGER *serial = NULL;
@@ -155,6 +220,7 @@ int req_main(int argc, char **argv)
EVP_PKEY *pkey = NULL;
EVP_PKEY_CTX *genctx = NULL;
STACK_OF(OPENSSL_STRING) *pkeyopts = NULL, *sigopts = NULL;
+ LHASH_OF(OPENSSL_STRING) *addexts = NULL;
X509 *x509ss = NULL;
X509_REQ *req = NULL;
const EVP_CIPHER *cipher = NULL;
@@ -324,11 +390,17 @@ int req_main(int argc, char **argv)
multirdn = 1;
break;
case OPT_ADDEXT:
- if (addext_bio == NULL) {
+ p = opt_arg();
+ if (addexts == NULL) {
+ addexts = lh_OPENSSL_STRING_new(ext_name_hash, ext_name_cmp);
addext_bio = BIO_new(BIO_s_mem());
+ if (addexts == NULL || addext_bio == NULL)
+ goto end;
}
- if (addext_bio == NULL
- || BIO_printf(addext_bio, "%s\n", opt_arg()) < 0)
+ i = duplicated(addexts, p);
+ if (i == 1)
+ goto opthelp;
+ if (i < 0 || BIO_printf(addext_bio, "%s\n", opt_arg()) < 0)
goto end;
break;
case OPT_EXTENSIONS:
@@ -885,6 +957,8 @@ int req_main(int argc, char **argv)
EVP_PKEY_CTX_free(genctx);
sk_OPENSSL_STRING_free(pkeyopts);
sk_OPENSSL_STRING_free(sigopts);
+ lh_OPENSSL_STRING_doall(addexts, exts_cleanup);
+ lh_OPENSSL_STRING_free(addexts);
#ifndef OPENSSL_NO_ENGINE
ENGINE_free(gen_eng);
#endif