diff --git a/SOURCES/0009-Fix-help-message-for-client-key-file.patch b/SOURCES/0009-Fix-help-message-for-client-key-file.patch index 20e05e4..04e0777 100644 --- a/SOURCES/0009-Fix-help-message-for-client-key-file.patch +++ b/SOURCES/0009-Fix-help-message-for-client-key-file.patch @@ -1,4 +1,4 @@ -From ec20eab0c58bb079c7092183e4893ebc773af9a0 Mon Sep 17 00:00:00 2001 +From fa6be1a9bbc8c5d42a248e398e3aac08078e311e Mon Sep 17 00:00:00 2001 From: Stephen Gallagher Date: Fri, 13 Dec 2019 11:51:43 -0500 Subject: [PATCH 9/9] Fix help message for --client-key-file @@ -6,26 +6,31 @@ Subject: [PATCH 9/9] Fix help message for --client-key-file Resolves: rhbz#1720667 Signed-off-by: Stephen Gallagher + +Further clarify --client-key-file help message + +Resolves: rhbz#1720667 + +Signed-off-by: Stephen Gallagher --- - src/sscg.c | 5 ++--- - 1 file changed, 2 insertions(+), 3 deletions(-) + src/sscg.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/sscg.c b/src/sscg.c -index f34a43b83e562d0bd7da9a77e25911762db83693..87833d266b541f6d0422fdc538d208abd7d81e22 100644 +index f34a43b83e562d0bd7da9a77e25911762db83693..4d009a67488e83c4332f58ee52f7d6ea72a8ddbd 100644 --- a/src/sscg.c +++ b/src/sscg.c -@@ -734,9 +734,8 @@ main (int argc, const char **argv) +@@ -734,9 +734,7 @@ main (int argc, const char **argv) &client_key_file, 0, _ ("Path where the client's private key will be stored. " - "(default is client-file with a .key suffix, if " - "--client-file was passed, otherwise this file will not " - "be generated.)"), -+ "(default is the client-file, if --client-file was passed, " -+ "otherwise this file will not be generated.)"), ++ "(default is the client-file)"), NULL, }, -- -2.23.0 +2.24.1 diff --git a/SOURCES/0010-Better-validation-of-command-line-arguments.patch b/SOURCES/0010-Better-validation-of-command-line-arguments.patch new file mode 100644 index 0000000..7e934e9 --- /dev/null +++ b/SOURCES/0010-Better-validation-of-command-line-arguments.patch @@ -0,0 +1,920 @@ +From 87530e9ebc872761c06506f3cb6a4fa5c494a614 Mon Sep 17 00:00:00 2001 +From: Stephen Gallagher +Date: Tue, 7 Jan 2020 14:32:01 -0500 +Subject: [PATCH 10/10] Better validation of command line arguments + +Check that key passphrases are within 4-1023 characters + +OpenSSL CLI tools cannot handle files with passphrases outside this +range. + +Resolves: rhbz#1784441 + +Signed-off-by: Stephen Gallagher + +Output private keys with 2048 iteration count + +Signed-off-by: Stephen Gallagher + +Rework passphrase handling + +Handle passphrases as part of the sscg_stream for a file. This will +allow us to check for relevance as well as reducing code duplication. + +Resolves: rhbz#1784443 + +Signed-off-by: Stephen Gallagher + +Fix wrong x509 version in CSR + +This was, fortunately, not causing any problems because the signing +process resulted in the certificates being generated with the +correct version. It's best to be correct anyway. + +Signed-off-by: Stephen Gallagher + +Fix memory leaks + +Signed-off-by: Stephen Gallagher + +Fix alignment issue with popt + +The boolean values need to be explicitly defined as int because +a bool may not be aligned properly. It was working prior to some +recent changes by lucky accident. + +Signed-off-by: Stephen Gallagher + +Prevent uninitialized read error + +Signed-off-by: Stephen Gallagher + +Add missing newline for error message + +Signed-off-by: Stephen Gallagher + +Fix OpenSSL 1.0 support + +The symbol UI_F_UI_SET_RESULT changed to UI_F_UI_SET_RESULT_EX in +OpenSSL 1.1, but no other semantics changed that we care about. + +Signed-off-by: Stephen Gallagher + +Fix formatting + +Signed-off-by: Stephen Gallagher + +Fix missing error check + +Signed-off-by: Stephen Gallagher + +Read long password files properly + +Long passphrase files may require more than a single call to BIO_read() +to gather the whole string. + +Signed-off-by: Stephen Gallagher +--- + include/io_utils.h | 37 ++++++- + include/key.h | 6 +- + include/sscg.h | 42 +++++--- + include/x509.h | 6 +- + meson.build | 1 + + src/io_utils.c | 199 ++++++++++++++++++++++++++++++++++++- + src/sscg.c | 239 +++++++-------------------------------------- + src/x509.c | 6 +- + 8 files changed, 310 insertions(+), 226 deletions(-) + +diff --git a/include/io_utils.h b/include/io_utils.h +index 6a89a476b3d982447b6603153c6765835cd67464..907097c7ff1f7ae3c3adf35d0dfba0f5763dc8c0 100644 +--- a/include/io_utils.h ++++ b/include/io_utils.h +@@ -24,6 +24,7 @@ + #include + #include + ++#include "include/key.h" + #include "include/sscg.h" + + +@@ -33,6 +34,9 @@ struct sscg_stream + char *path; + int mode; + int filetypes; ++ ++ bool pass_prompt; ++ char *passphrase; + }; + + +@@ -69,8 +73,6 @@ sscg_io_utils_get_path_by_type (struct sscg_stream **streams, + * @path: The path to the file on disk. + * @mode: The filesystem mode this file should have when written to disk. + * See chmod(1) for the possible values. +- * @overwrite: If true, replace any existing file at @normalized_path. If +- * false, opening will fail if it already exists and return an error. + * + * Prepares all output filenames to be opened. Files are not created until + * sscg_io_utils_open_output_files() is called. +@@ -82,9 +84,40 @@ sscg_io_utils_add_output_file (struct sscg_stream **streams, + int mode); + + ++/** ++ * sscg_io_utils_add_output_key: ++ * @streams: The array of streams from the sscg_options ++ * @filetype: ++ * @path: The path to the file on disk. ++ * @mode: The filesystem mode this file should have when written to disk. ++ * See chmod(1) for the possible values. ++ * @pass_prompt: Whether the user should be prompted to enter a passphrase ++ * interactively. ++ * @passphrase: The passphrase supplied at the command line. ++ * @passfile: The path to a file containing the passphrase. ++ * ++ * Prepares all output filenames to be opened. Files are not created until ++ * sscg_io_utils_open_output_files() is called. ++ */ ++int ++sscg_io_utils_add_output_key (struct sscg_stream **streams, ++ enum sscg_file_type filetype, ++ const char *path, ++ int mode, ++ bool pass_prompt, ++ char *passphrase, ++ char *passfile); ++ ++ + int + sscg_io_utils_open_output_files (struct sscg_stream **streams, bool overwrite); + ++int ++sscg_io_utils_write_privatekey (struct sscg_stream **streams, ++ enum sscg_file_type filetype, ++ struct sscg_evp_pkey *key, ++ struct sscg_options *options); ++ + /* If this function fails, some of the output files may be left as 0400 */ + int + sscg_io_utils_finalize_output_files (struct sscg_stream **streams); +diff --git a/include/key.h b/include/key.h +index ef871d6937e2fc805a445d6686263b023a38eaaa..4c32cad04950ee7fd75ec4144147eb919280c00a 100644 +--- a/include/key.h ++++ b/include/key.h +@@ -17,15 +17,15 @@ + Copyright 2017 by Stephen Gallagher + */ + ++#ifndef _SSCG_KEY_H ++#define _SSCG_KEY_H ++ + #include + #include + + #include "include/sscg.h" + #include "include/bignum.h" + +-#ifndef _SSCG_KEY_H +-#define _SSCG_KEY_H +- + struct sscg_evp_pkey + { + EVP_PKEY *evp_pkey; +diff --git a/include/sscg.h b/include/sscg.h +index 2744404c25c68ed905ca621bb955e0c04b33ca81..96b78152ccc492deafbbc61eb98702562a8fe5e6 100644 +--- a/include/sscg.h ++++ b/include/sscg.h +@@ -20,17 +20,18 @@ + /* This is a master header file that should be included by all + sscg source files. */ + ++ ++#ifndef _SSCG_H ++#define _SSCG_H ++ + #include + #include + #include ++#include + #include + #include + #include + +-#include "include/io_utils.h" +- +-#ifndef _SSCG_H +-#define _SSCG_H + + /* TODO: implement internationalization */ + +@@ -81,15 +82,34 @@ + } \ + while (0) + ++/* The function changed in 1.1, but the library and reason names did not */ ++#ifndef UI_F_UI_SET_RESULT_EX ++#define UI_F_UI_SET_RESULT_EX UI_F_UI_SET_RESULT ++#endif ++ + #define CHECK_SSL(_sslret, _fn) \ + do \ + { \ + if (_sslret != 1) \ + { \ + /* Get information about error from OpenSSL */ \ ++ unsigned long _ssl_error = ERR_get_error (); \ ++ if ((ERR_GET_LIB (_ssl_error) == ERR_LIB_UI) && \ ++ (ERR_GET_FUNC (_ssl_error) == UI_F_UI_SET_RESULT_EX) && \ ++ ((ERR_GET_REASON (_ssl_error) == UI_R_RESULT_TOO_LARGE) || \ ++ (ERR_GET_REASON (_ssl_error) == UI_R_RESULT_TOO_SMALL))) \ ++ { \ ++ fprintf ( \ ++ stderr, \ ++ "Passphrases must be between %d and %d characters. \n", \ ++ SSCG_MIN_KEY_PASS_LEN, \ ++ SSCG_MAX_KEY_PASS_LEN); \ ++ ret = EINVAL; \ ++ goto done; \ ++ } \ + fprintf (stderr, \ + "Error occurred in " #_fn ": [%s].\n", \ +- ERR_error_string (ERR_get_error (), NULL)); \ ++ ERR_error_string (_ssl_error, NULL)); \ + ret = EIO; \ + goto done; \ + } \ +@@ -223,12 +243,9 @@ struct sscg_options + const EVP_CIPHER *cipher; + const EVP_MD *hash_fn; + +- bool ca_key_pass_prompt; +- char *ca_key_pass; +- bool cert_key_pass_prompt; +- char *cert_key_pass; +- bool client_key_pass_prompt; +- char *client_key_pass; ++ int ca_key_pass_prompt; ++ int cert_key_pass_prompt; ++ int client_key_pass_prompt; + + /* Output Files */ + struct sscg_stream **streams; +@@ -251,4 +268,7 @@ enum sscg_cert_type + SSCG_NUM_CERT_TYPES + }; + ++#define SSCG_MIN_KEY_PASS_LEN 4 ++#define SSCG_MAX_KEY_PASS_LEN 1023 ++ + #endif /* _SSCG_H */ +diff --git a/include/x509.h b/include/x509.h +index 865cd0018d3ea77915cd86349e333ae6f4de2af0..cc7e498d06c4d2e503d7d8748dfd5386f9ad0794 100644 +--- a/include/x509.h ++++ b/include/x509.h +@@ -17,6 +17,9 @@ + Copyright 2017 by Stephen Gallagher + */ + ++#ifndef _SSCG_X509_H ++#define _SSCG_X509_H ++ + #include + #include + +@@ -24,9 +27,6 @@ + #include "include/bignum.h" + #include "include/key.h" + +-#ifndef _SSCG_X509_H +-#define _SSCG_X509_H +- + struct sscg_cert_info + { + /* === Input Data === */ +diff --git a/meson.build b/meson.build +index eb339ea8c768adab6d576736fbe476b83529e78d..3d8937ce73dc84f652f6fdad461a1468a532f0f2 100644 +--- a/meson.build ++++ b/meson.build +@@ -76,6 +76,7 @@ sscg_lib_hdrs = [ + 'include/dhparams.h', + 'include/io_utils.h', + 'include/key.h', ++ 'include/sscg.h', + 'include/x509.h', + ] + +diff --git a/src/io_utils.c b/src/io_utils.c +index a2502afb20f4bcb536428f3528900c2bb06997f5..1b8bc41c3849acbe4657ae14dfe55e3010957129 100644 +--- a/src/io_utils.c ++++ b/src/io_utils.c +@@ -24,8 +24,14 @@ + #include + + #include "include/io_utils.h" ++#include "include/key.h" + #include "include/sscg.h" + ++ ++/* Same as OpenSSL CLI */ ++#define MAX_PW_LEN 1024 ++ ++ + int + sscg_normalize_path (TALLOC_CTX *mem_ctx, + const char *path, +@@ -62,6 +68,12 @@ sscg_stream_destructor (TALLOC_CTX *ptr) + + BIO_free (stream->bio); + ++ /* Zero out the memory before freeing it so we don't leak passwords */ ++ if (stream->passphrase) ++ { ++ memset (stream->passphrase, 0, strnlen (stream->passphrase, MAX_PW_LEN)); ++ } ++ + return 0; + } + +@@ -147,11 +159,101 @@ sscg_io_utils_get_path_by_type (struct sscg_stream **streams, + } + + ++/* This function takes a copy of a string into a talloc hierarchy and memsets ++ * the original string to zeroes to avoid leaking it when that memory is freed. ++ */ ++static char * ++sscg_secure_string_steal (TALLOC_CTX *mem_ctx, char *src) ++{ ++ char *dest = talloc_strdup (mem_ctx, src); ++ ++ memset ((void *)src, 0, strlen (src)); ++ ++ return dest; ++} ++ ++ ++static int ++validate_passphrase (struct sscg_stream *stream) ++{ ++ /* Ignore non-key types */ ++ if (!(stream->filetypes & SSCG_FILE_TYPE_KEYS)) ++ return EOK; ++ ++ /* Ignore unset passwords; these will be prompted for when writing out the ++ * key file ++ */ ++ if (!stream->passphrase) ++ return EOK; ++ ++ size_t pass_len = strnlen (stream->passphrase, SSCG_MAX_KEY_PASS_LEN + 1); ++ ++ if ((pass_len < SSCG_MIN_KEY_PASS_LEN) || (pass_len > SSCG_MAX_KEY_PASS_LEN)) ++ { ++ SSCG_ERROR ("Passphrases must be between %d and %d characters. \n", ++ SSCG_MIN_KEY_PASS_LEN, ++ SSCG_MAX_KEY_PASS_LEN); ++ return EINVAL; ++ } ++ return EOK; ++} ++ ++ ++static char * ++sscg_read_pw_file (TALLOC_CTX *mem_ctx, char *path) ++{ ++ int i; ++ BIO *pwdbio = NULL; ++ char tpass[MAX_PW_LEN + 1]; ++ int offset = 0; ++ char *tmp = NULL; ++ char *password = NULL; ++ ++ pwdbio = BIO_new_file (path, "r"); ++ if (pwdbio == NULL) ++ { ++ fprintf (stderr, "Can't open file %s\n", path); ++ return NULL; ++ } ++ ++ /* Read up to one more character than the MAX_PW_LEN */ ++ for (offset = 0; ++ (i = BIO_read (pwdbio, tpass + offset, MAX_PW_LEN + 1 - offset)) > 0 && ++ offset < (MAX_PW_LEN + 1); ++ offset += i) ++ ; ++ ++ tpass[MAX_PW_LEN] = '\0'; ++ ++ BIO_free_all (pwdbio); ++ pwdbio = NULL; ++ ++ if (i < 0) ++ { ++ fprintf (stderr, "Error reading password from BIO\n"); ++ return NULL; ++ } ++ ++ tmp = strchr (tpass, '\n'); ++ if (tmp != NULL) ++ *tmp = 0; ++ ++ password = talloc_strdup (mem_ctx, tpass); ++ ++ memset (tpass, 0, MAX_PW_LEN + 1); ++ ++ return password; ++} ++ ++ + int +-sscg_io_utils_add_output_file (struct sscg_stream **streams, +- enum sscg_file_type filetype, +- const char *path, +- int mode) ++sscg_io_utils_add_output_key (struct sscg_stream **streams, ++ enum sscg_file_type filetype, ++ const char *path, ++ int mode, ++ bool pass_prompt, ++ char *passphrase, ++ char *passfile) + { + int ret, i; + TALLOC_CTX *tmp_ctx = NULL; +@@ -163,6 +265,22 @@ sscg_io_utils_add_output_file (struct sscg_stream **streams, + */ + if (path == NULL) + { ++ if (pass_prompt) ++ { ++ SSCG_ERROR ( ++ "Passphrase prompt requested for %s, but no file path provided.\n", ++ sscg_get_file_type_name (filetype)); ++ return EINVAL; ++ } ++ ++ if (passphrase) ++ { ++ SSCG_ERROR ( ++ "Passphrase provided for %s, but no file path provided.\n", ++ sscg_get_file_type_name (filetype)); ++ return EINVAL; ++ } ++ + SSCG_LOG (SSCG_DEBUG, + "Got a NULL path with filetype: %s\n", + sscg_get_file_type_name (filetype)); +@@ -220,6 +338,31 @@ sscg_io_utils_add_output_file (struct sscg_stream **streams, + /* Add the file type */ + stream->filetypes |= (1 << filetype); + ++ ++ /* Set the password options */ ++ stream->pass_prompt = pass_prompt; ++ ++ if (passphrase) ++ { ++ stream->passphrase = sscg_secure_string_steal (stream, passphrase); ++ ret = validate_passphrase (stream); ++ if (ret != EOK) ++ goto done; ++ } ++ else if (passfile) ++ { ++ stream->passphrase = sscg_read_pw_file (stream, passfile); ++ if (!stream->passphrase) ++ { ++ fprintf (stderr, "Failed to read passphrase from %s", passfile); ++ ret = EIO; ++ goto done; ++ } ++ } ++ ret = validate_passphrase (stream); ++ if (ret != EOK) ++ goto done; ++ + ret = EOK; + + done: +@@ -228,6 +371,17 @@ done: + } + + ++int ++sscg_io_utils_add_output_file (struct sscg_stream **streams, ++ enum sscg_file_type filetype, ++ const char *path, ++ int mode) ++{ ++ return sscg_io_utils_add_output_key ( ++ streams, filetype, path, mode, false, NULL, NULL); ++} ++ ++ + enum io_utils_errors + { + IO_UTILS_OK = 0, +@@ -400,6 +554,43 @@ done: + } + + ++int ++sscg_io_utils_write_privatekey (struct sscg_stream **streams, ++ enum sscg_file_type filetype, ++ struct sscg_evp_pkey *key, ++ struct sscg_options *options) ++{ ++ int ret, sret; ++ ++ struct sscg_stream *stream = ++ sscg_io_utils_get_stream_by_type (streams, filetype); ++ if (stream) ++ { ++ /* This function has a default mechanism for prompting for the ++ * password if it is passed a cipher and gets a NULL password. ++ * ++ * Only pass the cipher if we have a password or were instructed ++ * to prompt for one. ++ */ ++ sret = PEM_write_bio_PKCS8PrivateKey ( ++ stream->bio, ++ key->evp_pkey, ++ stream->pass_prompt || stream->passphrase ? options->cipher : NULL, ++ stream->passphrase, ++ stream->passphrase ? strlen (stream->passphrase) : 0, ++ NULL, ++ NULL); ++ CHECK_SSL (sret, PEM_write_bio_PKCS8PrivateKey); ++ ANNOUNCE_WRITE (filetype); ++ } ++ ++ ret = EOK; ++ ++done: ++ return ret; ++} ++ ++ + int + sscg_io_utils_finalize_output_files (struct sscg_stream **streams) + { +diff --git a/src/sscg.c b/src/sscg.c +index 4d009a67488e83c4332f58ee52f7d6ea72a8ddbd..96a9be1232d890590e97c126f8f4a78d571d7247 100644 +--- a/src/sscg.c ++++ b/src/sscg.c +@@ -18,6 +18,7 @@ + */ + + #define _GNU_SOURCE ++#include + #include + #include + #include +@@ -40,9 +41,6 @@ + int verbosity; + + +-/* Same as OpenSSL CLI */ +-#define MAX_PW_LEN 1024 +- + static int + get_security_level (void) + { +@@ -140,79 +138,6 @@ print_options (struct sscg_options *opts) + } + + +-/* This function takes a copy of a string into a talloc hierarchy and memsets +- * the original string to zeroes to avoid leaking it when that memory is freed. +- */ +-static char * +-sscg_secure_string_steal (TALLOC_CTX *mem_ctx, char *src) +-{ +- char *dest = talloc_strdup (mem_ctx, src); +- +- memset (src, 0, strlen (src)); +- +- return dest; +-} +- +- +-static int +-sscg_options_destructor (TALLOC_CTX *opts) +-{ +- struct sscg_options *options = +- talloc_get_type_abort (opts, struct sscg_options); +- +- /* Zero out the memory before freeing it so we don't leak passwords */ +- if (options->ca_key_pass) +- { +- memset (options->ca_key_pass, 0, strlen (options->ca_key_pass)); +- } +- +- if (options->cert_key_pass) +- { +- memset (options->cert_key_pass, 0, strlen (options->cert_key_pass)); +- } +- +- return 0; +-} +- +- +-static char * +-sscg_read_pw_file (TALLOC_CTX *mem_ctx, char *path) +-{ +- int i; +- BIO *pwdbio = NULL; +- char tpass[MAX_PW_LEN]; +- char *tmp = NULL; +- char *password = NULL; +- +- pwdbio = BIO_new_file (path, "r"); +- if (pwdbio == NULL) +- { +- fprintf (stderr, "Can't open file %s\n", path); +- return NULL; +- } +- +- i = BIO_gets (pwdbio, tpass, MAX_PW_LEN); +- BIO_free_all (pwdbio); +- pwdbio = NULL; +- +- if (i <= 0) +- { +- fprintf (stderr, "Error reading password from BIO\n"); +- return NULL; +- } +- +- tmp = strchr (tpass, '\n'); +- if (tmp != NULL) +- *tmp = 0; +- +- password = talloc_strdup (mem_ctx, tpass); +- +- memset (tpass, 0, MAX_PW_LEN); +- +- return password; +-} +- +- + const char * + sscg_get_verbosity_name (enum sscg_verbosity type) + { +@@ -310,12 +235,14 @@ main (int argc, const char **argv) + struct sscg_evp_pkey *cakey; + struct sscg_x509_cert *svc_cert; + struct sscg_evp_pkey *svc_key; +- struct sscg_x509_cert *client_cert; +- struct sscg_evp_pkey *client_key; ++ struct sscg_x509_cert *client_cert = NULL; ++ struct sscg_evp_pkey *client_key = NULL; + + int dhparams_mode = SSCG_CERT_DEFAULT_MODE; + struct sscg_dhparams *dhparams = NULL; + ++ struct sscg_stream *stream = NULL; ++ + /* Always use umask 0577 for generating certificates and keys + This means that it's opened as write-only by the effective + user. */ +@@ -335,7 +262,6 @@ main (int argc, const char **argv) + + options = talloc_zero (main_ctx, struct sscg_options); + CHECK_MEM (options); +- talloc_set_destructor ((TALLOC_CTX *)options, sscg_options_destructor); + + options->streams = + talloc_zero_array (options, struct sscg_stream *, SSCG_NUM_FILE_TYPES); +@@ -965,56 +891,6 @@ main (int argc, const char **argv) + } + } + +- /* Password handling */ +- if (ca_key_password) +- { +- options->ca_key_pass = +- sscg_secure_string_steal (options, ca_key_password); +- } +- else if (ca_key_passfile) +- { +- options->ca_key_pass = sscg_read_pw_file (options, ca_key_passfile); +- if (!options->ca_key_pass) +- { +- fprintf ( +- stderr, "Failed to read passphrase from %s", ca_key_passfile); +- goto done; +- } +- } +- +- if (cert_key_password) +- { +- options->cert_key_pass = +- sscg_secure_string_steal (options, cert_key_password); +- } +- else if (cert_key_passfile) +- { +- options->cert_key_pass = sscg_read_pw_file (options, cert_key_passfile); +- if (!options->cert_key_pass) +- { +- fprintf ( +- stderr, "Failed to read passphrase from %s", cert_key_passfile); +- goto done; +- } +- } +- +- if (client_key_password) +- { +- options->client_key_pass = +- sscg_secure_string_steal (options, client_key_password); +- } +- else if (client_key_passfile) +- { +- options->client_key_pass = +- sscg_read_pw_file (options, client_key_passfile); +- if (!options->client_key_pass) +- { +- fprintf ( +- stderr, "Failed to read passphrase from %s", client_key_passfile); +- goto done; +- } +- } +- + if (options->key_strength < options->minimum_key_strength) + { + fprintf (stderr, +@@ -1055,8 +931,13 @@ main (int argc, const char **argv) + ca_mode); + CHECK_OK (ret); + +- ret = sscg_io_utils_add_output_file ( +- options->streams, SSCG_FILE_TYPE_CA_KEY, ca_key_file, ca_key_mode); ++ ret = sscg_io_utils_add_output_key (options->streams, ++ SSCG_FILE_TYPE_CA_KEY, ++ ca_key_file, ++ ca_key_mode, ++ options->ca_key_pass_prompt, ++ ca_key_password, ++ ca_key_passfile); + CHECK_OK (ret); + + ret = sscg_io_utils_add_output_file (options->streams, +@@ -1065,11 +946,14 @@ main (int argc, const char **argv) + cert_mode); + CHECK_OK (ret); + +- ret = sscg_io_utils_add_output_file (options->streams, +- SSCG_FILE_TYPE_SVC_KEY, +- cert_key_file ? cert_key_file : +- "./service-key.pem", +- cert_key_mode); ++ ret = sscg_io_utils_add_output_key (options->streams, ++ SSCG_FILE_TYPE_SVC_KEY, ++ cert_key_file ? cert_key_file : ++ "./service-key.pem", ++ cert_key_mode, ++ options->cert_key_pass_prompt, ++ cert_key_password, ++ cert_key_passfile); + CHECK_OK (ret); + + +@@ -1078,11 +962,14 @@ main (int argc, const char **argv) + CHECK_OK (ret); + + +- ret = sscg_io_utils_add_output_file (options->streams, +- SSCG_FILE_TYPE_CLIENT_KEY, +- client_key_file ? client_key_file : +- client_file, +- client_key_mode); ++ ret = sscg_io_utils_add_output_key (options->streams, ++ SSCG_FILE_TYPE_CLIENT_KEY, ++ client_key_file ? client_key_file : ++ client_file, ++ client_key_mode, ++ options->client_key_pass_prompt, ++ client_key_password, ++ client_key_passfile); + CHECK_OK (ret); + + ret = sscg_io_utils_add_output_file ( +@@ -1136,67 +1023,17 @@ main (int argc, const char **argv) + + /* Write private keys first */ + +- if (build_client_cert) +- { +- /* This function has a default mechanism for prompting for the +- * password if it is passed a cipher and gets a NULL password. +- * +- * Only pass the cipher if we have a password or were instructed +- * to prompt for one. +- */ +- sret = PEM_write_bio_PrivateKey ( +- GET_BIO (SSCG_FILE_TYPE_CLIENT_KEY), +- client_key->evp_pkey, +- options->client_key_pass_prompt || options->client_key_pass ? +- options->cipher : +- NULL, +- (unsigned char *)options->client_key_pass, +- options->client_key_pass ? strlen (options->client_key_pass) : 0, +- NULL, +- NULL); +- CHECK_SSL (sret, PEM_write_bio_PrivateKey (svc)); +- ANNOUNCE_WRITE (SSCG_FILE_TYPE_SVC_KEY); +- } ++ ret = sscg_io_utils_write_privatekey ( ++ options->streams, SSCG_FILE_TYPE_CLIENT_KEY, client_key, options); ++ CHECK_OK (ret); + +- /* This function has a default mechanism for prompting for the +- * password if it is passed a cipher and gets a NULL password. +- * +- * Only pass the cipher if we have a password or were instructed +- * to prompt for one. +- */ +- sret = PEM_write_bio_PrivateKey ( +- GET_BIO (SSCG_FILE_TYPE_SVC_KEY), +- svc_key->evp_pkey, +- options->cert_key_pass_prompt || options->cert_key_pass ? options->cipher : +- NULL, +- (unsigned char *)options->cert_key_pass, +- options->cert_key_pass ? strlen (options->cert_key_pass) : 0, +- NULL, +- NULL); +- CHECK_SSL (sret, PEM_write_bio_PrivateKey (svc)); +- ANNOUNCE_WRITE (SSCG_FILE_TYPE_SVC_KEY); ++ ret = sscg_io_utils_write_privatekey ( ++ options->streams, SSCG_FILE_TYPE_SVC_KEY, svc_key, options); ++ CHECK_OK (ret); + +- /* Create CA private key, if requested */ +- if (GET_BIO (SSCG_FILE_TYPE_CA_KEY)) +- { +- /* This function has a default mechanism for prompting for the +- * password if it is passed a cipher and gets a NULL password. +- * +- * Only pass the cipher if we have a password or were instructed +- * to prompt for one. +- */ +- sret = PEM_write_bio_PrivateKey ( +- GET_BIO (SSCG_FILE_TYPE_CA_KEY), +- cakey->evp_pkey, +- options->ca_key_pass_prompt || options->ca_key_pass ? options->cipher : +- NULL, +- (unsigned char *)options->ca_key_pass, +- options->ca_key_pass ? strlen (options->ca_key_pass) : 0, +- NULL, +- NULL); +- CHECK_SSL (sret, PEM_write_bio_PrivateKey (CA)); +- ANNOUNCE_WRITE (SSCG_FILE_TYPE_CA_KEY); +- } ++ ret = sscg_io_utils_write_privatekey ( ++ options->streams, SSCG_FILE_TYPE_CA_KEY, cakey, options); ++ CHECK_OK (ret); + + /* Public keys come next, in chain order */ + +@@ -1217,7 +1054,7 @@ main (int argc, const char **argv) + + + /* Create CA public certificate */ +- struct sscg_stream *stream = ++ stream = + sscg_io_utils_get_stream_by_type (options->streams, SSCG_FILE_TYPE_CA); + sret = PEM_write_bio_X509 (stream->bio, cacert->certificate); + CHECK_SSL (sret, PEM_write_bio_X509 (CA)); +diff --git a/src/x509.c b/src/x509.c +index c173f539791fbbc51e52e6b121e587dca43924d4..42315d42d1e03460a8121e1592d8e7fcc0fef1df 100644 +--- a/src/x509.c ++++ b/src/x509.c +@@ -72,7 +72,7 @@ _sscg_certinfo_destructor (TALLOC_CTX *ctx) + struct sscg_cert_info *certinfo = + talloc_get_type_abort (ctx, struct sscg_cert_info); + +- sk_X509_EXTENSION_free (certinfo->extensions); ++ sk_X509_EXTENSION_pop_free (certinfo->extensions, X509_EXTENSION_free); + + return 0; + } +@@ -155,7 +155,7 @@ sscg_x509v3_csr_new (TALLOC_CTX *mem_ctx, + talloc_set_destructor ((TALLOC_CTX *)csr, _sscg_csr_destructor); + + /* We will generate only x509v3 certificates */ +- sslret = X509_REQ_set_version (csr->x509_req, 3); ++ sslret = X509_REQ_set_version (csr->x509_req, 2); + CHECK_SSL (sslret, X509_REQ_set_version); + + subject = X509_REQ_get_subject_name (csr->x509_req); +@@ -461,6 +461,8 @@ sscg_sign_x509_csr (TALLOC_CTX *mem_ctx, + } + sslret = X509_add_ext (cert, ext, -1); + CHECK_SSL (sslret, X509_add_ext); ++ ++ X509_EXTENSION_free (ext); + } + + /* Sign the new certificate */ +-- +2.24.1 + diff --git a/SPECS/sscg.spec b/SPECS/sscg.spec index f56a7a8..235e7fb 100644 --- a/SPECS/sscg.spec +++ b/SPECS/sscg.spec @@ -9,7 +9,7 @@ Name: sscg Version: 2.3.3 -Release: 10%{?dist} +Release: 14%{?dist} Summary: Simple SSL certificate generator License: BSD @@ -43,6 +43,9 @@ Patch0007: 0007-Add-support-for-client-certificates-and-dhparams.patch Patch0008: 0008-Fix-client-cert-issues-found-by-CI-tests.patch Patch0009: 0009-Fix-help-message-for-client-key-file.patch +# RHBZ #1784441 and 1784443 +Patch0010: 0010-Better-validation-of-command-line-arguments.patch + %description A utility to aid in the creation of more secure "self-signed" certificates. The certificates created by this tool are generated in a @@ -76,6 +79,21 @@ false signatures from the service certificate. %{_mandir}/man8/%{name}.8* %changelog +* Tue Jan 21 2020 Stephen Gallagher - 2.3.3-14 +- Properly handling reading long passphrase files. + +* Tue Jan 21 2020 Stephen Gallagher - 2.3.3-13 +- Fix missing error check for --*-key-passfile + +* Thu Jan 09 2020 Stephen Gallagher - 2.3.3-12 +- Improve validation of command-line arguments +- Resolves: rhbz#1784441 +- Resolves: rhbz#1784443 + +* Tue Jan 07 2020 Stephen Gallagher - 2.3.3-11 +- Further improve --client-key-file help message +- Resolves: rhbz#1720667 + * Fri Dec 13 2019 Stephen Gallagher - 2.3.3-10 - Fix incorrect help message - Resolves: rhbz#1720667