summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStan Hu <stanhu@gmail.com>2022-08-10 09:30:24 -0700
committerStan Hu <stanhu@gmail.com>2022-08-15 11:21:44 -0700
commit71119a71d71d3c07bb9223de1ac5b4f97db3de0f (patch)
tree01d2b34e59a13e373619babe94bf320408e1ecea
parent0865c115ba963167214d33541870c6a6318897fb (diff)
Make it possible to set SSL verify mode
If no SSL certificates are provided, many Redis clients default to disabling SSL peer verification. Previously it was a bit cumbersome to configure this because the client would either have to reimplement `redisCreateSSLContext()` or reach into the internals to set the OpenSSL verify mode. We can improve the SSL API by introducing a `redisCreateSSLContextWithOptions()` call that takes into structured parameters for SSL initialization. This structure contains a verify mode that is used to set the OpenSSL verify mode. Relates to https://github.com/redis/hiredis/issues/646
-rw-r--r--hiredis_ssl.h33
-rw-r--r--ssl.c21
2 files changed, 53 insertions, 1 deletions
diff --git a/hiredis_ssl.h b/hiredis_ssl.h
index e3d3e1c..26bc9e9 100644
--- a/hiredis_ssl.h
+++ b/hiredis_ssl.h
@@ -61,6 +61,27 @@ typedef enum {
REDIS_SSL_CTX_OS_CERT_ADD_FAILED /* Failed to add CA certificates obtained from system to the SSL context */
} redisSSLContextError;
+/* Constants that mirror OpenSSL's verify modes. By default,
+ * REDIS_SSL_VERIFY_PEER is used with redisCreateSSLContext().
+ * Some Redis clients disable peer verification if there are no
+ * certificates specified.
+ */
+#define REDIS_SSL_VERIFY_NONE 0x00
+#define REDIS_SSL_VERIFY_PEER 0x01
+#define REDIS_SSL_VERIFY_FAIL_IF_NO_PEER_CERT 0x02
+#define REDIS_SSL_VERIFY_CLIENT_ONCE 0x04
+#define REDIS_SSL_VERIFY_POST_HANDSHAKE 0x08
+
+/* Options to create an OpenSSL context. */
+typedef struct {
+ const char *cacert_filename;
+ const char *capath;
+ const char *cert_filename;
+ const char *private_key_filename;
+ const char *server_name;
+ int verify_mode;
+} redisSSLOptions;
+
/**
* Return the error message corresponding with the specified error code.
*/
@@ -102,6 +123,18 @@ redisSSLContext *redisCreateSSLContext(const char *cacert_filename, const char *
const char *server_name, redisSSLContextError *error);
/**
+ * Helper function to initialize an OpenSSL context that can be used
+ * to initiate SSL connections. This is a more extensible version of redisCreateSSLContext().
+ *
+ * options contains a structure of SSL options to use.
+ *
+ * If error is non-null, it will be populated in case the context creation fails
+ * (returning a NULL).
+*/
+redisSSLContext *redisCreateSSLContextWithOptions(redisSSLOptions *options,
+ redisSSLContextError *error);
+
+/**
* Free a previously created OpenSSL context.
*/
void redisFreeSSLContext(redisSSLContext *redis_ssl_ctx);
diff --git a/ssl.c b/ssl.c
index c581f63..887e1fe 100644
--- a/ssl.c
+++ b/ssl.c
@@ -219,6 +219,25 @@ redisSSLContext *redisCreateSSLContext(const char *cacert_filename, const char *
const char *cert_filename, const char *private_key_filename,
const char *server_name, redisSSLContextError *error)
{
+ redisSSLOptions options = {
+ .cacert_filename = cacert_filename,
+ .capath = capath,
+ .cert_filename = cert_filename,
+ .private_key_filename = private_key_filename,
+ .server_name = server_name,
+ .verify_mode = REDIS_SSL_VERIFY_PEER,
+ };
+
+ return redisCreateSSLContextWithOptions(&options, error);
+}
+
+redisSSLContext *redisCreateSSLContextWithOptions(redisSSLOptions *options, redisSSLContextError *error) {
+ const char *cacert_filename = options->cacert_filename;
+ const char *capath = options->capath;
+ const char *cert_filename = options->cert_filename;
+ const char *private_key_filename = options->private_key_filename;
+ const char *server_name = options->server_name;
+
#ifdef _WIN32
HCERTSTORE win_store = NULL;
PCCERT_CONTEXT win_ctx = NULL;
@@ -235,7 +254,7 @@ redisSSLContext *redisCreateSSLContext(const char *cacert_filename, const char *
}
SSL_CTX_set_options(ctx->ssl_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
- SSL_CTX_set_verify(ctx->ssl_ctx, SSL_VERIFY_PEER, NULL);
+ SSL_CTX_set_verify(ctx->ssl_ctx, options->verify_mode, NULL);
if ((cert_filename != NULL && private_key_filename == NULL) ||
(private_key_filename != NULL && cert_filename == NULL)) {