Add support for reading encrypted keyfiles. (#8644)
This commit is contained in:
parent
c3df27d1ea
commit
c4ef1efdb7
10
redis.conf
10
redis.conf
@ -150,6 +150,11 @@ tcp-keepalive 300
|
|||||||
#
|
#
|
||||||
# tls-cert-file redis.crt
|
# tls-cert-file redis.crt
|
||||||
# tls-key-file redis.key
|
# tls-key-file redis.key
|
||||||
|
#
|
||||||
|
# If the key file is encrypted using a passphrase, it can be included here
|
||||||
|
# as well.
|
||||||
|
#
|
||||||
|
# tls-key-file-pass secret
|
||||||
|
|
||||||
# Normally Redis uses the same certificate for both server functions (accepting
|
# Normally Redis uses the same certificate for both server functions (accepting
|
||||||
# connections) and client functions (replicating from a master, establishing
|
# connections) and client functions (replicating from a master, establishing
|
||||||
@ -162,6 +167,11 @@ tcp-keepalive 300
|
|||||||
#
|
#
|
||||||
# tls-client-cert-file client.crt
|
# tls-client-cert-file client.crt
|
||||||
# tls-client-key-file client.key
|
# tls-client-key-file client.key
|
||||||
|
#
|
||||||
|
# If the key file is encrypted using a passphrase, it can be included here
|
||||||
|
# as well.
|
||||||
|
#
|
||||||
|
# tls-client-key-file-pass secret
|
||||||
|
|
||||||
# Configure a DH parameters file to enable Diffie-Hellman (DH) key exchange:
|
# Configure a DH parameters file to enable Diffie-Hellman (DH) key exchange:
|
||||||
#
|
#
|
||||||
|
@ -2543,8 +2543,10 @@ standardConfig configs[] = {
|
|||||||
createBoolConfig("tls-session-caching", NULL, MODIFIABLE_CONFIG, server.tls_ctx_config.session_caching, 1, NULL, updateTlsCfgBool),
|
createBoolConfig("tls-session-caching", NULL, MODIFIABLE_CONFIG, server.tls_ctx_config.session_caching, 1, NULL, updateTlsCfgBool),
|
||||||
createStringConfig("tls-cert-file", NULL, MODIFIABLE_CONFIG, EMPTY_STRING_IS_NULL, server.tls_ctx_config.cert_file, NULL, NULL, updateTlsCfg),
|
createStringConfig("tls-cert-file", NULL, MODIFIABLE_CONFIG, EMPTY_STRING_IS_NULL, server.tls_ctx_config.cert_file, NULL, NULL, updateTlsCfg),
|
||||||
createStringConfig("tls-key-file", NULL, MODIFIABLE_CONFIG, EMPTY_STRING_IS_NULL, server.tls_ctx_config.key_file, NULL, NULL, updateTlsCfg),
|
createStringConfig("tls-key-file", NULL, MODIFIABLE_CONFIG, EMPTY_STRING_IS_NULL, server.tls_ctx_config.key_file, NULL, NULL, updateTlsCfg),
|
||||||
|
createStringConfig("tls-key-file-pass", NULL, MODIFIABLE_CONFIG, EMPTY_STRING_IS_NULL, server.tls_ctx_config.key_file_pass, NULL, NULL, updateTlsCfg),
|
||||||
createStringConfig("tls-client-cert-file", NULL, MODIFIABLE_CONFIG, EMPTY_STRING_IS_NULL, server.tls_ctx_config.client_cert_file, NULL, NULL, updateTlsCfg),
|
createStringConfig("tls-client-cert-file", NULL, MODIFIABLE_CONFIG, EMPTY_STRING_IS_NULL, server.tls_ctx_config.client_cert_file, NULL, NULL, updateTlsCfg),
|
||||||
createStringConfig("tls-client-key-file", NULL, MODIFIABLE_CONFIG, EMPTY_STRING_IS_NULL, server.tls_ctx_config.client_key_file, NULL, NULL, updateTlsCfg),
|
createStringConfig("tls-client-key-file", NULL, MODIFIABLE_CONFIG, EMPTY_STRING_IS_NULL, server.tls_ctx_config.client_key_file, NULL, NULL, updateTlsCfg),
|
||||||
|
createStringConfig("tls-client-key-file-pass", NULL, MODIFIABLE_CONFIG, EMPTY_STRING_IS_NULL, server.tls_ctx_config.client_key_file_pass, NULL, NULL, updateTlsCfg),
|
||||||
createStringConfig("tls-dh-params-file", NULL, MODIFIABLE_CONFIG, EMPTY_STRING_IS_NULL, server.tls_ctx_config.dh_params_file, NULL, NULL, updateTlsCfg),
|
createStringConfig("tls-dh-params-file", NULL, MODIFIABLE_CONFIG, EMPTY_STRING_IS_NULL, server.tls_ctx_config.dh_params_file, NULL, NULL, updateTlsCfg),
|
||||||
createStringConfig("tls-ca-cert-file", NULL, MODIFIABLE_CONFIG, EMPTY_STRING_IS_NULL, server.tls_ctx_config.ca_cert_file, NULL, NULL, updateTlsCfg),
|
createStringConfig("tls-ca-cert-file", NULL, MODIFIABLE_CONFIG, EMPTY_STRING_IS_NULL, server.tls_ctx_config.ca_cert_file, NULL, NULL, updateTlsCfg),
|
||||||
createStringConfig("tls-ca-cert-dir", NULL, MODIFIABLE_CONFIG, EMPTY_STRING_IS_NULL, server.tls_ctx_config.ca_cert_dir, NULL, NULL, updateTlsCfg),
|
createStringConfig("tls-ca-cert-dir", NULL, MODIFIABLE_CONFIG, EMPTY_STRING_IS_NULL, server.tls_ctx_config.ca_cert_dir, NULL, NULL, updateTlsCfg),
|
||||||
|
@ -1119,8 +1119,10 @@ typedef struct socketFds {
|
|||||||
typedef struct redisTLSContextConfig {
|
typedef struct redisTLSContextConfig {
|
||||||
char *cert_file; /* Server side and optionally client side cert file name */
|
char *cert_file; /* Server side and optionally client side cert file name */
|
||||||
char *key_file; /* Private key filename for cert_file */
|
char *key_file; /* Private key filename for cert_file */
|
||||||
|
char *key_file_pass; /* Optional password for key_file */
|
||||||
char *client_cert_file; /* Certificate to use as a client; if none, use cert_file */
|
char *client_cert_file; /* Certificate to use as a client; if none, use cert_file */
|
||||||
char *client_key_file; /* Private key filename for client_cert_file */
|
char *client_key_file; /* Private key filename for client_cert_file */
|
||||||
|
char *client_key_file_pass; /* Optional password for client_key_file */
|
||||||
char *dh_params_file;
|
char *dh_params_file;
|
||||||
char *ca_cert_file;
|
char *ca_cert_file;
|
||||||
char *ca_cert_dir;
|
char *ca_cert_dir;
|
||||||
|
28
src/tls.c
28
src/tls.c
@ -179,11 +179,28 @@ void tlsCleanup(void) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Callback for passing a keyfile password stored as an sds to OpenSSL */
|
||||||
|
static int tlsPasswordCallback(char *buf, int size, int rwflag, void *u) {
|
||||||
|
UNUSED(rwflag);
|
||||||
|
|
||||||
|
const char *pass = u;
|
||||||
|
size_t pass_len;
|
||||||
|
|
||||||
|
if (!pass) return -1;
|
||||||
|
pass_len = strlen(pass);
|
||||||
|
if (pass_len > (size_t) size) return -1;
|
||||||
|
memcpy(buf, pass, pass_len);
|
||||||
|
|
||||||
|
return (int) pass_len;
|
||||||
|
}
|
||||||
|
|
||||||
/* Create a *base* SSL_CTX using the SSL configuration provided. The base context
|
/* Create a *base* SSL_CTX using the SSL configuration provided. The base context
|
||||||
* includes everything that's common for both client-side and server-side connections.
|
* includes everything that's common for both client-side and server-side connections.
|
||||||
*/
|
*/
|
||||||
static SSL_CTX *createSSLContext(redisTLSContextConfig *ctx_config, int protocols,
|
static SSL_CTX *createSSLContext(redisTLSContextConfig *ctx_config, int protocols, int client) {
|
||||||
const char *cert_file, const char *key_file) {
|
const char *cert_file = client ? ctx_config->client_cert_file : ctx_config->cert_file;
|
||||||
|
const char *key_file = client ? ctx_config->client_key_file : ctx_config->key_file;
|
||||||
|
const char *key_file_pass = client ? ctx_config->client_key_file_pass : ctx_config->key_file_pass;
|
||||||
char errbuf[256];
|
char errbuf[256];
|
||||||
SSL_CTX *ctx = NULL;
|
SSL_CTX *ctx = NULL;
|
||||||
|
|
||||||
@ -215,6 +232,9 @@ static SSL_CTX *createSSLContext(redisTLSContextConfig *ctx_config, int protocol
|
|||||||
SSL_CTX_set_mode(ctx, SSL_MODE_ENABLE_PARTIAL_WRITE|SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
|
SSL_CTX_set_mode(ctx, SSL_MODE_ENABLE_PARTIAL_WRITE|SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
|
||||||
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
|
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
|
||||||
|
|
||||||
|
SSL_CTX_set_default_passwd_cb(ctx, tlsPasswordCallback);
|
||||||
|
SSL_CTX_set_default_passwd_cb_userdata(ctx, (void *) key_file_pass);
|
||||||
|
|
||||||
if (SSL_CTX_use_certificate_chain_file(ctx, cert_file) <= 0) {
|
if (SSL_CTX_use_certificate_chain_file(ctx, cert_file) <= 0) {
|
||||||
ERR_error_string_n(ERR_get_error(), errbuf, sizeof(errbuf));
|
ERR_error_string_n(ERR_get_error(), errbuf, sizeof(errbuf));
|
||||||
serverLog(LL_WARNING, "Failed to load certificate: %s: %s", cert_file, errbuf);
|
serverLog(LL_WARNING, "Failed to load certificate: %s: %s", cert_file, errbuf);
|
||||||
@ -281,7 +301,7 @@ int tlsConfigure(redisTLSContextConfig *ctx_config) {
|
|||||||
if (protocols == -1) goto error;
|
if (protocols == -1) goto error;
|
||||||
|
|
||||||
/* Create server side/generla context */
|
/* Create server side/generla context */
|
||||||
ctx = createSSLContext(ctx_config, protocols, ctx_config->cert_file, ctx_config->key_file);
|
ctx = createSSLContext(ctx_config, protocols, 0);
|
||||||
if (!ctx) goto error;
|
if (!ctx) goto error;
|
||||||
|
|
||||||
if (ctx_config->session_caching) {
|
if (ctx_config->session_caching) {
|
||||||
@ -332,7 +352,7 @@ int tlsConfigure(redisTLSContextConfig *ctx_config) {
|
|||||||
|
|
||||||
/* If a client-side certificate is configured, create an explicit client context */
|
/* If a client-side certificate is configured, create an explicit client context */
|
||||||
if (ctx_config->client_cert_file && ctx_config->client_key_file) {
|
if (ctx_config->client_cert_file && ctx_config->client_key_file) {
|
||||||
client_ctx = createSSLContext(ctx_config, protocols, ctx_config->client_cert_file, ctx_config->client_key_file);
|
client_ctx = createSSLContext(ctx_config, protocols, 1);
|
||||||
if (!client_ctx) goto error;
|
if (!client_ctx) goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,5 +139,20 @@ start_server {tags {"tls"}} {
|
|||||||
$rd PING
|
$rd PING
|
||||||
$rd close
|
$rd close
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test {TLS: Working with an encrypted keyfile} {
|
||||||
|
# Create an encrypted version
|
||||||
|
set keyfile [lindex [r config get tls-key-file] 1]
|
||||||
|
set keyfile_encrypted "$keyfile.encrypted"
|
||||||
|
exec -ignorestderr openssl rsa -in $keyfile -out $keyfile_encrypted -aes256 -passout pass:1234 2>/dev/null
|
||||||
|
|
||||||
|
# Using it without a password fails
|
||||||
|
catch {r config set tls-key-file $keyfile_encrypted} e
|
||||||
|
assert_match {*Unable to update TLS*} $e
|
||||||
|
|
||||||
|
# Now use a password
|
||||||
|
r config set tls-key-file-pass 1234
|
||||||
|
r config set tls-key-file $keyfile_encrypted
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user