import sscg-2.3.3-14.el8

This commit is contained in:
CentOS Sources 2020-04-28 04:48:45 -04:00 committed by Andrew Lukoshko
parent 330654936d
commit d2d2ae226a
11 changed files with 4206 additions and 113 deletions

View File

@ -1,7 +1,7 @@
From 71e2451c6ba4d5f17de9e24687b66b93f2e58954 Mon Sep 17 00:00:00 2001
From: Stephen Gallagher <sgallagh@redhat.com>
Date: Mon, 17 Sep 2018 09:58:25 -0400
Subject: [PATCH 1/4] Generate manpage
Subject: [PATCH 1/6] Generate manpage
Signed-off-by: Stephen Gallagher <sgallagh@redhat.com>
---
@ -12,9 +12,7 @@ diff --git a/meson.build b/meson.build
index e6f33475cce6891d17656bcd10e1afabd43bdc07..a2ca4ba1472bfff61fbbd30ba1ddc7ecc89e723c 100644
--- a/meson.build
+++ b/meson.build
@@ -5,11 +5,11 @@ project('sscg', 'c',
'c_std=gnu99',
'warning_level=1',
@@ -7,7 +7,7 @@ project('sscg', 'c',
'b_asneeded=true',
],
license : 'MIT',
@ -23,11 +21,7 @@ index e6f33475cce6891d17656bcd10e1afabd43bdc07..a2ca4ba1472bfff61fbbd30ba1ddc7ec
cc = meson.get_compiler('c')
test_cflags = [
'-Wpointer-arith',
'-Wmissing-declarations',
@@ -139,5 +139,25 @@ cdata.set('version', meson.project_version())
configure_file(
input : 'config.h.in',
@@ -141,3 +141,23 @@ configure_file(
output : 'config.h',
configuration : cdata)
@ -52,5 +46,5 @@ index e6f33475cce6891d17656bcd10e1afabd43bdc07..a2ca4ba1472bfff61fbbd30ba1ddc7ec
+ 'man8'),
+)
--
2.19.1
2.23.0

View File

@ -1,7 +1,7 @@
From 942d9fa4f582a372af3d0bd499f073760dec2335 Mon Sep 17 00:00:00 2001
From: Stephen Gallagher <sgallagh@redhat.com>
Date: Tue, 27 Nov 2018 13:24:37 -0500
Subject: [PATCH 2/4] Adjust defaults based on system security level
Subject: [PATCH 2/6] Adjust defaults based on system security level
Also permit arbitrary keylengths.
@ -29,9 +29,7 @@ diff --git a/include/sscg.h b/include/sscg.h
index 2bd42bbee965c754efb91febd10b6a94af6f508e..3e97cfe49a5cd8fc734ecf43a94156e376227eb7 100644
--- a/include/sscg.h
+++ b/include/sscg.h
@@ -137,10 +137,11 @@ struct sscg_options
const char *hostname;
char **subject_alt_names;
@@ -139,6 +139,7 @@ struct sscg_options
/* Encryption requirements */
int key_strength;
@ -39,15 +37,11 @@ index 2bd42bbee965c754efb91febd10b6a94af6f508e..3e97cfe49a5cd8fc734ecf43a94156e3
const EVP_MD *hash_fn;
/* Output Files */
char *ca_file;
char *ca_key_file;
diff --git a/meson.build b/meson.build
index a2ca4ba1472bfff61fbbd30ba1ddc7ecc89e723c..c7b08ed3d6dff686f08a90ca869ba5881a9e8aaa 100644
--- a/meson.build
+++ b/meson.build
@@ -32,10 +32,11 @@ foreach cflag: test_cflags
endif
endforeach
@@ -34,6 +34,7 @@ endforeach
pkg = import('pkgconfig')
crypto = dependency('libcrypto')
@ -55,11 +49,7 @@ index a2ca4ba1472bfff61fbbd30ba1ddc7ecc89e723c..c7b08ed3d6dff686f08a90ca869ba588
path_utils = dependency('path_utils')
talloc = dependency('talloc')
popt = dependency(
'popt',
@@ -47,10 +48,14 @@ if popt.found()
else
popt = subproject('popt').get_variable('libpopt_a')
@@ -49,6 +50,10 @@ else
popt_incdirs = include_directories('subprojects/popt')
endif
@ -70,11 +60,7 @@ index a2ca4ba1472bfff61fbbd30ba1ddc7ecc89e723c..c7b08ed3d6dff686f08a90ca869ba588
sscg_lib_srcs = [
'src/authority.c',
'src/bignum.c',
'src/key.c',
'src/service.c',
@@ -68,10 +73,11 @@ sscg_lib_hdrs = [
sscg_lib = static_library(
'sscg',
@@ -70,6 +75,7 @@ sscg_lib = static_library(
sources : sscg_lib_srcs,
dependencies : [
crypto,
@ -82,11 +68,7 @@ index a2ca4ba1472bfff61fbbd30ba1ddc7ecc89e723c..c7b08ed3d6dff686f08a90ca869ba588
talloc,
],
install : false,
pic : true,
)
@@ -133,13 +139,13 @@ init_bignum_test = executable(
install : false,
)
@@ -135,9 +141,9 @@ init_bignum_test = executable(
test('init_bignum_test', init_bignum_test)
cdata = configuration_data()
@ -98,15 +80,11 @@ index a2ca4ba1472bfff61fbbd30ba1ddc7ecc89e723c..c7b08ed3d6dff686f08a90ca869ba588
output : 'config.h',
configuration : cdata)
# Generate a manpage from the POPT documentation
help2man = find_program('help2man')
diff --git a/src/sscg.c b/src/sscg.c
index b2c7cbbfd9dc69d9f55a18bc91ed6023c0e64c2e..85a42404aa94524b560755d506b893300a4414cd 100644
--- a/src/sscg.c
+++ b/src/sscg.c
@@ -15,30 +15,80 @@
along with sscg. If not, see <http://www.gnu.org/licenses/>.
@@ -17,6 +17,7 @@
Copyright 2017 by Stephen Gallagher <sgallagh@redhat.com>
*/
@ -114,8 +92,7 @@ index b2c7cbbfd9dc69d9f55a18bc91ed6023c0e64c2e..85a42404aa94524b560755d506b89330
#include <popt.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <talloc.h>
@@ -25,6 +26,7 @@
#include <path_utils.h>
#include <unistd.h>
#include <openssl/evp.h>
@ -123,7 +100,7 @@ index b2c7cbbfd9dc69d9f55a18bc91ed6023c0e64c2e..85a42404aa94524b560755d506b89330
#include <sys/param.h>
#include "config.h"
#include "include/sscg.h"
@@ -32,11 +34,59 @@
#include "include/authority.h"
#include "include/service.h"
@ -184,11 +161,7 @@ index b2c7cbbfd9dc69d9f55a18bc91ed6023c0e64c2e..85a42404aa94524b560755d506b89330
return 0;
}
static void
print_options (struct sscg_options *opts)
@@ -115,10 +165,11 @@ main (int argc, const char **argv)
{
int ret, sret, opt;
@@ -117,6 +167,7 @@ main (int argc, const char **argv)
size_t i;
poptContext pc;
struct sscg_options *options;
@ -196,11 +169,7 @@ index b2c7cbbfd9dc69d9f55a18bc91ed6023c0e64c2e..85a42404aa94524b560755d506b89330
char *country = NULL;
char *state = NULL;
char *locality = NULL;
char *organization = NULL;
@@ -170,10 +221,13 @@ main (int argc, const char **argv)
ret = set_default_options (options);
@@ -172,6 +223,9 @@ main (int argc, const char **argv)
if (ret != EOK)
goto done;
@ -210,11 +179,7 @@ index b2c7cbbfd9dc69d9f55a18bc91ed6023c0e64c2e..85a42404aa94524b560755d506b89330
options->verbosity = SSCG_DEFAULT;
struct poptOption long_options[] = {
POPT_AUTOHELP{ "quiet",
'q',
POPT_ARG_VAL,
@@ -291,11 +345,11 @@ main (int argc, const char **argv)
'\0',
POPT_ARG_INT | POPT_ARGFLAG_SHOW_DEFAULT,
@@ -293,7 +347,7 @@ main (int argc, const char **argv)
&options->key_strength,
0,
_ ("Strength of the certificate private keys in bits."),
@ -223,11 +188,7 @@ index b2c7cbbfd9dc69d9f55a18bc91ed6023c0e64c2e..85a42404aa94524b560755d506b89330
{
"hash-alg",
'\0',
POPT_ARG_STRING,
&hash_alg,
@@ -527,15 +581,15 @@ main (int argc, const char **argv)
options->subject_alt_names[i + 1] = NULL;
i++;
@@ -529,11 +583,11 @@ main (int argc, const char **argv)
}
}
@ -242,8 +203,6 @@ index b2c7cbbfd9dc69d9f55a18bc91ed6023c0e64c2e..85a42404aa94524b560755d506b89330
ret = EINVAL;
goto done;
}
if (!hash_alg)
--
2.19.1
2.23.0

View File

@ -1,7 +1,7 @@
From 298015e8a7cf35cc0de581203b44826d2ae1d406 Mon Sep 17 00:00:00 2001
From: Stephen Gallagher <sgallagh@redhat.com>
Date: Wed, 28 Nov 2018 08:00:08 -0500
Subject: [PATCH 3/4] Adjust hash defaults based on system security level
Subject: [PATCH 3/6] Adjust hash defaults based on system security level
Unlike the key-strength, this does not set a minimum level because
it's not a simple calculation. We will have to rely on libcrypto
@ -17,9 +17,7 @@ diff --git a/include/sscg.h b/include/sscg.h
index 3e97cfe49a5cd8fc734ecf43a94156e376227eb7..fc90b81a0060af28529f3be6922b1b1501559300 100644
--- a/include/sscg.h
+++ b/include/sscg.h
@@ -138,10 +138,11 @@ struct sscg_options
char **subject_alt_names;
@@ -140,6 +140,7 @@ struct sscg_options
/* Encryption requirements */
int key_strength;
int minimum_key_strength;
@ -27,15 +25,11 @@ index 3e97cfe49a5cd8fc734ecf43a94156e376227eb7..fc90b81a0060af28529f3be6922b1b15
const EVP_MD *hash_fn;
/* Output Files */
char *ca_file;
char *ca_key_file;
diff --git a/src/sscg.c b/src/sscg.c
index 85a42404aa94524b560755d506b893300a4414cd..58855f764480d24d6c0f57460b22a3a83281e37e 100644
--- a/src/sscg.c
+++ b/src/sscg.c
@@ -64,28 +64,38 @@ set_default_options (struct sscg_options *opts)
{
case 0:
@@ -66,14 +66,21 @@ set_default_options (struct sscg_options *opts)
case 1:
case 2:
/* Security level 2 and below permits lower key-strengths, but SSCG
@ -60,9 +54,7 @@ index 85a42404aa94524b560755d506b893300a4414cd..58855f764480d24d6c0f57460b22a3a8
default:
/* Unknown security level. Default to the highest we know about */
fprintf (stderr,
"Unknown system security level %d. Defaulting to highest-known "
"level.\n",
@@ -83,7 +90,10 @@ set_default_options (struct sscg_options *opts)
security_level);
/* Fall through */
@ -74,11 +66,7 @@ index 85a42404aa94524b560755d506b893300a4414cd..58855f764480d24d6c0f57460b22a3a8
}
opts->minimum_key_strength = opts->key_strength;
return 0;
}
@@ -175,11 +185,10 @@ main (int argc, const char **argv)
char *organization = NULL;
char *organizational_unit = NULL;
@@ -177,7 +187,6 @@ main (int argc, const char **argv)
char *email = NULL;
char *hostname = NULL;
char *packagename;
@ -86,11 +74,7 @@ index 85a42404aa94524b560755d506b893300a4414cd..58855f764480d24d6c0f57460b22a3a8
char **alternative_names = NULL;
char *ca_file = NULL;
char *ca_key_file = NULL;
char *cert_file = NULL;
@@ -349,14 +358,14 @@ main (int argc, const char **argv)
_ ("Strength of the certificate private keys in bits."),
minimum_key_strength_help },
@@ -351,10 +360,10 @@ main (int argc, const char **argv)
{
"hash-alg",
'\0',
@ -104,11 +88,7 @@ index 85a42404aa94524b560755d506b893300a4414cd..58855f764480d24d6c0f57460b22a3a8
_ ("{sha256,sha384,sha512}"),
},
{
"ca-file",
'\0',
@@ -590,21 +599,14 @@ main (int argc, const char **argv)
options->minimum_key_strength);
ret = EINVAL;
@@ -592,17 +601,10 @@ main (int argc, const char **argv)
goto done;
}
@ -130,8 +110,6 @@ index 85a42404aa94524b560755d506b893300a4414cd..58855f764480d24d6c0f57460b22a3a8
if (!options->hash_fn)
{
fprintf (stderr, "Unsupported hashing algorithm.");
ret = EINVAL;
goto done;
--
2.19.1
2.23.0

View File

@ -1,7 +1,7 @@
From 9e4497d1dd2a337be1f69e0cfb24ce8080690ccf Mon Sep 17 00:00:00 2001
From: Stephen Gallagher <sgallagh@redhat.com>
Date: Wed, 28 Nov 2018 09:16:29 -0500
Subject: [PATCH 4/4] Properly check all return values
Subject: [PATCH 4/6] Properly check all return values
Signed-off-by: Stephen Gallagher <sgallagh@redhat.com>
---
@ -14,9 +14,7 @@ diff --git a/src/authority.c b/src/authority.c
index b735868416b7fb5d016f0854baf0f27cd5f98b26..4e0dccc6c1210beffb38acd9f7dfb6108ca4a4ad 100644
--- a/src/authority.c
+++ b/src/authority.c
@@ -178,10 +178,11 @@ create_private_CA (TALLOC_CTX *mem_ctx,
}
sk_X509_EXTENSION_push (ca_certinfo->extensions, ex);
@@ -180,6 +180,7 @@ create_private_CA (TALLOC_CTX *mem_ctx,
/* Finalize the CSR */
ret = sscg_x509v3_csr_finalize (ca_certinfo, pkey, csr);
@ -24,15 +22,11 @@ index b735868416b7fb5d016f0854baf0f27cd5f98b26..4e0dccc6c1210beffb38acd9f7dfb610
if (options->verbosity >= SSCG_DEBUG)
{
fprintf (stderr, "DEBUG: Writing CA CSR to ./debug-ca.csr\n");
BIO *ca_csr_out = BIO_new_file ("./debug-ca.csr", "w");
diff --git a/src/service.c b/src/service.c
index b292e94063f032fd3c34a8134702063ea46bfa0c..34c976dbe905528000b181c24d1fa95da3cd1377 100644
--- a/src/service.c
+++ b/src/service.c
@@ -124,10 +124,11 @@ create_service_cert (TALLOC_CTX *mem_ctx,
ret = sscg_x509v3_csr_new (tmp_ctx, svc_certinfo, pkey, &csr);
CHECK_OK (ret);
@@ -126,6 +126,7 @@ create_service_cert (TALLOC_CTX *mem_ctx,
/* Finalize the CSR */
ret = sscg_x509v3_csr_finalize (svc_certinfo, pkey, csr);
@ -40,15 +34,11 @@ index b292e94063f032fd3c34a8134702063ea46bfa0c..34c976dbe905528000b181c24d1fa95d
if (options->verbosity >= SSCG_DEBUG)
{
fprintf (stderr,
"DEBUG: Writing service certificate CSR to ./debug-svc.csr\n");
diff --git a/src/x509.c b/src/x509.c
index 6d152fc969d745cc5cf085116c8688866f9d6ab4..18f0627bc64e7cb503a9e81c36dbe726186d1144 100644
--- a/src/x509.c
+++ b/src/x509.c
@@ -39,10 +39,11 @@ sscg_generate_serial (TALLOC_CTX *mem_ctx, struct sscg_bignum **serial)
{
return ENOMEM;
@@ -41,6 +41,7 @@ sscg_generate_serial (TALLOC_CTX *mem_ctx, struct sscg_bignum **serial)
}
ret = sscg_init_bignum (tmp_ctx, 0, &bn);
@ -56,8 +46,6 @@ index 6d152fc969d745cc5cf085116c8688866f9d6ab4..18f0627bc64e7cb503a9e81c36dbe726
/* We'll create a random number of sizeof(unsigned long) - 1 bits
to use as the serial. We use unsigned long to ensure that it
could be printed by BN_get_word() later. We omit the last bit
in order to ensure that we can't randomly get 0xffffffffL, which
--
2.19.1
2.23.0

View File

@ -0,0 +1,273 @@
From 7190d08e1a166455e767769492b8c6b9f41bc0da Mon Sep 17 00:00:00 2001
From: Stephen Gallagher <sgallagh@redhat.com>
Date: Wed, 5 Jun 2019 17:08:23 -0400
Subject: [PATCH 5/6] Add password support for private keys
Fixes: https://github.com/sgallagher/sscg/issues/14
Signed-off-by: Stephen Gallagher <sgallagh@redhat.com>
---
include/sscg.h | 7 +++
src/sscg.c | 152 ++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 157 insertions(+), 2 deletions(-)
diff --git a/include/sscg.h b/include/sscg.h
index fc90b81a0060af28529f3be6922b1b1501559300..ce9a7916e9432d0843d82af61d56ea7238ded682 100644
--- a/include/sscg.h
+++ b/include/sscg.h
@@ -141,8 +141,15 @@ struct sscg_options
int key_strength;
int minimum_key_strength;
char *hash_alg;
+ char *cipher_alg;
+ 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;
+
/* Output Files */
char *ca_file;
char *ca_key_file;
diff --git a/src/sscg.c b/src/sscg.c
index 58855f764480d24d6c0f57460b22a3a83281e37e..9dc926c77038105ca881a612cccd1913bc2d42f1 100644
--- a/src/sscg.c
+++ b/src/sscg.c
@@ -97,6 +97,9 @@ set_default_options (struct sscg_options *opts)
}
opts->minimum_key_strength = opts->key_strength;
+
+ opts->cipher_alg = talloc_strdup (opts, "aes-256-cbc");
+
return 0;
}
@@ -170,6 +173,42 @@ done:
return ret;
}
+
+/* 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;
+}
+
+
int
main (int argc, const char **argv)
{
@@ -196,8 +235,11 @@ main (int argc, const char **argv)
int ca_mode = 0644;
int ca_key_mode = 0600;
+ char *ca_key_password = NULL;
+
int cert_mode = 0644;
int cert_key_mode = 0600;
+ char *cert_key_password = NULL;
char *create_mode = NULL;
@@ -227,6 +269,7 @@ 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);
ret = set_default_options (options);
if (ret != EOK)
@@ -366,6 +409,16 @@ main (int argc, const char **argv)
_ ("Hashing algorithm to use for signing."),
_ ("{sha256,sha384,sha512}"),
},
+ {
+ "cipher-alg",
+ '\0',
+ POPT_ARG_STRING | POPT_ARGFLAG_SHOW_DEFAULT,
+ &options->cipher_alg,
+ 0,
+ _ ("Cipher to use for encrypting key files."),
+ _ ("{des-ede3-cbc,aes-256-cbc}"),
+ },
+
{
"ca-file",
'\0',
@@ -404,6 +457,29 @@ main (int argc, const char **argv)
_ ("File mode of the created CA key. (default: 0600)"),
_ ("0600"),
},
+ {
+ "ca-key-password",
+ '\0',
+ POPT_ARG_STRING,
+ &ca_key_password,
+ 0,
+ _ ("Provide a password for the CA key file. Note that this will be "
+ "visible in the process table for all users, so it should be used "
+ "for testing purposes only. Use --ca-keypassfile or "
+ "--ca-key-password-prompt for secure password entry."),
+ NULL
+ },
+
+ {
+ "ca-key-password-prompt",
+ 'C',
+ POPT_ARG_NONE,
+ &options->ca_key_pass_prompt,
+ 0,
+ _ ("Prompt to enter a password for the CA key file."),
+ NULL
+ },
+
{
"cert-file",
'\0',
@@ -442,6 +518,29 @@ main (int argc, const char **argv)
_ ("File mode of the created certificate key. (default: 0600)"),
_ ("0600"),
},
+ {
+ "cert-key-password",
+ 'p',
+ POPT_ARG_STRING,
+ &cert_key_password,
+ 0,
+ _ ("Provide a password for the service key file. Note that this will be "
+ "visible in the process table for all users, so this flag should be "
+ "used for testing purposes only. Use --cert-keypassfile or "
+ "--cert-key-password-prompt for secure password entry."),
+ NULL
+ },
+
+ {
+ "cert-key-password-prompt",
+ 'P',
+ POPT_ARG_NONE,
+ &options->cert_key_pass_prompt,
+ 0,
+ _ ("Prompt to enter a password for the service key file."),
+ NULL
+ },
+
POPT_TABLEEND
};
@@ -592,6 +691,20 @@ main (int argc, const char **argv)
}
}
+ /* Password handling */
+ if (ca_key_password)
+ {
+ options->ca_key_pass =
+ sscg_secure_string_steal (options, ca_key_password);
+ }
+
+ if (cert_key_password)
+ {
+ options->cert_key_pass =
+ sscg_secure_string_steal (options, cert_key_password);
+ }
+
+
if (options->key_strength < options->minimum_key_strength)
{
fprintf (stderr,
@@ -601,6 +714,15 @@ main (int argc, const char **argv)
goto done;
}
+ /* Make sure we have a valid cipher */
+ options->cipher = EVP_get_cipherbyname (options->cipher_alg);
+ if (!options->cipher)
+ {
+ fprintf (stderr, "Invalid cipher specified: %s\n", options->cipher_alg);
+ ret = EINVAL;
+ goto done;
+ }
+
/* TODO: restrict this to approved hashes.
* For now, we'll only list SHA[256|384|512] in the help */
options->hash_fn = EVP_get_digestbyname (options->hash_alg);
@@ -696,8 +818,21 @@ main (int argc, const char **argv)
cert_key_out = BIO_new_file (options->cert_key_file, create_mode);
CHECK_BIO (cert_key_out, options->cert_key_file);
+ /* 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 (
- cert_key_out, svc_key->evp_pkey, NULL, NULL, 0, NULL, NULL);
+ cert_key_out,
+ 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));
BIO_get_fp (cert_key_out, &fp);
@@ -776,8 +911,21 @@ main (int argc, const char **argv)
}
CHECK_BIO (ca_key_out, options->ca_key_file);
+ /* 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 (
- ca_key_out, cakey->evp_pkey, NULL, NULL, 0, NULL, NULL);
+ ca_key_out,
+ 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));
BIO_get_fp (ca_key_out, &fp);
if (options->verbosity >= SSCG_DEBUG)
--
2.23.0

View File

@ -0,0 +1,153 @@
From 9cb7daa54708dcf5e6500cd20ec7b1cc2f6f6350 Mon Sep 17 00:00:00 2001
From: Stephen Gallagher <sgallagh@redhat.com>
Date: Mon, 10 Jun 2019 10:15:42 -0400
Subject: [PATCH 6/6] Allow specifying keyfile password by file
Signed-off-by: Stephen Gallagher <sgallagh@redhat.com>
---
src/sscg.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 84 insertions(+)
diff --git a/src/sscg.c b/src/sscg.c
index 9dc926c77038105ca881a612cccd1913bc2d42f1..a02e4df66c6cf9ec1865f425b4a15da82fbfdc72 100644
--- a/src/sscg.c
+++ b/src/sscg.c
@@ -34,6 +34,10 @@
#include "include/authority.h"
#include "include/service.h"
+
+/* Same as OpenSSL CLI */
+#define MAX_PW_LEN 1024
+
static int
get_security_level (void)
{
@@ -209,6 +213,44 @@ sscg_options_destructor (TALLOC_CTX *opts)
}
+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;
+}
+
+
int
main (int argc, const char **argv)
{
@@ -236,10 +278,12 @@ main (int argc, const char **argv)
int ca_mode = 0644;
int ca_key_mode = 0600;
char *ca_key_password = NULL;
+ char *ca_key_passfile = NULL;
int cert_mode = 0644;
int cert_key_mode = 0600;
char *cert_key_password = NULL;
+ char *cert_key_passfile = NULL;
char *create_mode = NULL;
@@ -470,6 +514,16 @@ main (int argc, const char **argv)
NULL
},
+ {
+ "ca-key-passfile",
+ '\0',
+ POPT_ARG_STRING,
+ &ca_key_passfile,
+ 0,
+ _ ("A file containing the password to encrypt the CA key file."),
+ NULL
+ },
+
{
"ca-key-password-prompt",
'C',
@@ -531,6 +585,16 @@ main (int argc, const char **argv)
NULL
},
+ {
+ "cert-key-passfile",
+ '\0',
+ POPT_ARG_STRING,
+ &cert_key_passfile,
+ 0,
+ _ ("A file containing the password to encrypt the service key file."),
+ NULL
+ },
+
{
"cert-key-password-prompt",
'P',
@@ -697,12 +761,32 @@ main (int argc, const char **argv)
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 (options->key_strength < options->minimum_key_strength)
--
2.23.0

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,98 @@
From 8afa0ce578ecd5cc3a397707fdb163cc169b9bd1 Mon Sep 17 00:00:00 2001
From: Stephen Gallagher <sgallagh@redhat.com>
Date: Fri, 13 Dec 2019 08:25:01 -0500
Subject: [PATCH 8/8] Fix client-cert issues found by CI tests
Resolves: rhbz#1720667
Better error message for client certs without public key file
Signed-off-by: Stephen Gallagher <sgallagh@redhat.com>
Fix memory leak in sscg_sign_x509_csr()
Signed-off-by: Stephen Gallagher <sgallagh@redhat.com>
Address clang-analyzer warning
clang-analyzer determined that it was possible for the GET_BIO()
return value to have changed between conditional creation of the
client certificate and writing it out. This patch stores the result
of the lookup so it's certain to be consistent.
Signed-off-by: Stephen Gallagher <sgallagh@redhat.com>
---
src/io_utils.c | 4 ++--
src/sscg.c | 8 +++++---
src/x509.c | 1 +
3 files changed, 8 insertions(+), 5 deletions(-)
diff --git a/src/io_utils.c b/src/io_utils.c
index 809a1da0e455afa0dba0796a5f7ac406742328a1..a2502afb20f4bcb536428f3528900c2bb06997f5 100644
--- a/src/io_utils.c
+++ b/src/io_utils.c
@@ -363,8 +363,8 @@ sscg_io_utils_open_output_files (struct sscg_stream **streams, bool overwrite)
case IO_UTILS_CLIENT_UNMATCHED:
SSCG_ERROR (
- "The client certificate must have both public and private key "
- "locations specified.\n");
+ "The client certificate must have the public key location "
+ "specified.\n");
ret = EINVAL;
goto done;
diff --git a/src/sscg.c b/src/sscg.c
index 470af815d91f5170a1e8fe00006dbaee4d07b209..f34a43b83e562d0bd7da9a77e25911762db83693 100644
--- a/src/sscg.c
+++ b/src/sscg.c
@@ -300,6 +300,7 @@ main (int argc, const char **argv)
char *cert_key_password = NULL;
char *cert_key_passfile = NULL;
+ bool build_client_cert = false;
int client_mode = SSCG_CERT_DEFAULT_MODE;
int client_key_mode = SSCG_KEY_DEFAULT_MODE;
char *client_key_password = NULL;
@@ -1118,7 +1119,8 @@ main (int argc, const char **argv)
/* If requested, generate the client auth certificate and sign it with the
* private CA.
*/
- if (GET_BIO (SSCG_FILE_TYPE_CLIENT))
+ build_client_cert = !!(GET_BIO (SSCG_FILE_TYPE_CLIENT));
+ if (build_client_cert)
{
ret = create_cert (main_ctx,
options,
@@ -1136,7 +1138,7 @@ main (int argc, const char **argv)
/* Write private keys first */
- if (GET_BIO (SSCG_FILE_TYPE_CLIENT_KEY))
+ 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.
@@ -1201,7 +1203,7 @@ main (int argc, const char **argv)
/* Public keys come next, in chain order */
/* Start with the client certificate */
- if (GET_BIO (SSCG_FILE_TYPE_CLIENT))
+ if (build_client_cert)
{
sret = PEM_write_bio_X509 (GET_BIO (SSCG_FILE_TYPE_CLIENT),
client_cert->certificate);
diff --git a/src/x509.c b/src/x509.c
index 18f0627bc64e7cb503a9e81c36dbe726186d1144..c173f539791fbbc51e52e6b121e587dca43924d4 100644
--- a/src/x509.c
+++ b/src/x509.c
@@ -482,5 +482,6 @@ done:
*_cert = talloc_steal (mem_ctx, scert);
}
X509_NAME_free (subject);
+ talloc_free(tmp_ctx);
return ret;
}
--
2.23.0

View File

@ -0,0 +1,36 @@
From fa6be1a9bbc8c5d42a248e398e3aac08078e311e Mon Sep 17 00:00:00 2001
From: Stephen Gallagher <sgallagh@redhat.com>
Date: Fri, 13 Dec 2019 11:51:43 -0500
Subject: [PATCH 9/9] Fix help message for --client-key-file
Resolves: rhbz#1720667
Signed-off-by: Stephen Gallagher <sgallagh@redhat.com>
Further clarify --client-key-file help message
Resolves: rhbz#1720667
Signed-off-by: Stephen Gallagher <sgallagh@redhat.com>
---
src/sscg.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/src/sscg.c b/src/sscg.c
index f34a43b83e562d0bd7da9a77e25911762db83693..4d009a67488e83c4332f58ee52f7d6ea72a8ddbd 100644
--- a/src/sscg.c
+++ b/src/sscg.c
@@ -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)"),
NULL,
},
--
2.24.1

View File

@ -0,0 +1,920 @@
From 87530e9ebc872761c06506f3cb6a4fa5c494a614 Mon Sep 17 00:00:00 2001
From: Stephen Gallagher <sgallagh@redhat.com>
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 <sgallagh@redhat.com>
Output private keys with 2048 iteration count
Signed-off-by: Stephen Gallagher <sgallagh@redhat.com>
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 <sgallagh@redhat.com>
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 <sgallagh@redhat.com>
Fix memory leaks
Signed-off-by: Stephen Gallagher <sgallagh@redhat.com>
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 <sgallagh@redhat.com>
Prevent uninitialized read error
Signed-off-by: Stephen Gallagher <sgallagh@redhat.com>
Add missing newline for error message
Signed-off-by: Stephen Gallagher <sgallagh@redhat.com>
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 <sgallagh@redhat.com>
Fix formatting
Signed-off-by: Stephen Gallagher <sgallagh@redhat.com>
Fix missing error check
Signed-off-by: Stephen Gallagher <sgallagh@redhat.com>
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 <sgallagh@redhat.com>
---
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 <stdbool.h>
#include <talloc.h>
+#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 <sgallagh@redhat.com>
*/
+#ifndef _SSCG_KEY_H
+#define _SSCG_KEY_H
+
#include <openssl/rsa.h>
#include <openssl/evp.h>
#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 <errno.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
+#include <openssl/ui.h>
#include <stdbool.h>
#include <talloc.h>
#include <stdint.h>
-#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 <sgallagh@redhat.com>
*/
+#ifndef _SSCG_X509_H
+#define _SSCG_X509_H
+
#include <openssl/x509.h>
#include <openssl/x509v3.h>
@@ -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 <talloc.h>
#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 <assert.h>
#include <popt.h>
#include <stdlib.h>
#include <stdio.h>
@@ -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

View File

@ -9,7 +9,7 @@
Name: sscg
Version: 2.3.3
Release: 6%{?dist}
Release: 14%{?dist}
Summary: Simple SSL certificate generator
License: BSD
@ -34,6 +34,18 @@ Patch0002: 0002-Adjust-defaults-based-on-system-security-level.patch
Patch0003: 0003-Adjust-hash-defaults-based-on-system-security-level.patch
Patch0004: 0004-Properly-check-all-return-values.patch
# RHBZ #1717880
Patch0005: 0005-Add-password-support-for-private-keys.patch
Patch0006: 0006-Allow-specifying-keyfile-password-by-file.patch
# RHBZ #1720667
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
@ -67,6 +79,37 @@ false signatures from the service certificate.
%{_mandir}/man8/%{name}.8*
%changelog
* Tue Jan 21 2020 Stephen Gallagher <sgallagh@redhat.com> - 2.3.3-14
- Properly handling reading long passphrase files.
* Tue Jan 21 2020 Stephen Gallagher <sgallagh@redhat.com> - 2.3.3-13
- Fix missing error check for --*-key-passfile
* Thu Jan 09 2020 Stephen Gallagher <sgallagh@redhat.com> - 2.3.3-12
- Improve validation of command-line arguments
- Resolves: rhbz#1784441
- Resolves: rhbz#1784443
* Tue Jan 07 2020 Stephen Gallagher <sgallagh@redhat.com> - 2.3.3-11
- Further improve --client-key-file help message
- Resolves: rhbz#1720667
* Fri Dec 13 2019 Stephen Gallagher <sgallagh@redhat.com> - 2.3.3-10
- Fix incorrect help message
- Resolves: rhbz#1720667
* Fri Dec 13 2019 Stephen Gallagher <sgallagh@redhat.com> - 2.3.3-9
- Fix null-dereference and memory leak issues with client certs
- Resolves: rhbz#1720667
* Wed Dec 11 2019 Stephen Gallagher <sgallagh@redhat.com> - 2.3.3-8
- Add support for generating client authentication certificates
- Resolves: rhbz#1720667
* Fri Nov 01 2019 Stephen Gallagher <sgallagh@redhat.com> - 2.3.3-7
- Add support for password-protecting the private key files
- Resolves: rhbz#1717880
* Wed Nov 28 2018 Stephen Gallagher <sgallagh@redhat.com> - 2.3.3-6
- Fixes for issues detected by automated testing.
- Resolves: rhbz#1653323