diff --git a/hiredis_ssl.h b/hiredis_ssl.h index 604efe0..e3d3e1c 100644 --- a/hiredis_ssl.h +++ b/hiredis_ssl.h @@ -56,7 +56,9 @@ typedef enum { REDIS_SSL_CTX_CERT_KEY_REQUIRED, /* Client cert and key must both be specified or skipped */ REDIS_SSL_CTX_CA_CERT_LOAD_FAILED, /* Failed to load CA Certificate or CA Path */ REDIS_SSL_CTX_CLIENT_CERT_LOAD_FAILED, /* Failed to load client certificate */ - REDIS_SSL_CTX_PRIVATE_KEY_LOAD_FAILED /* Failed to load private key */ + REDIS_SSL_CTX_PRIVATE_KEY_LOAD_FAILED, /* Failed to load private key */ + REDIS_SSL_CTX_OS_CERTSTORE_OPEN_FAILED, /* Failed to open system certifcate store */ + REDIS_SSL_CTX_OS_CERT_ADD_FAILED /* Failed to add CA certificates obtained from system to the SSL context */ } redisSSLContextError; /** diff --git a/ssl.c b/ssl.c index 7df58fb..f8124e1 100644 --- a/ssl.c +++ b/ssl.c @@ -38,6 +38,7 @@ #include #ifdef _WIN32 #include +#include #else #include #endif @@ -182,6 +183,10 @@ const char *redisSSLContextGetError(redisSSLContextError error) return "Failed to load client certificate"; case REDIS_SSL_CTX_PRIVATE_KEY_LOAD_FAILED: return "Failed to load private key"; + case REDIS_SSL_CTX_OS_CERTSTORE_OPEN_FAILED: + return "Failed to open system certifcate store"; + case REDIS_SSL_CTX_OS_CERT_ADD_FAILED: + return "Failed to add CA certificates obtained from system to the SSL context"; default: return "Unknown error code"; } @@ -214,6 +219,11 @@ redisSSLContext *redisCreateSSLContext(const char *cacert_filename, const char * const char *cert_filename, const char *private_key_filename, const char *server_name, redisSSLContextError *error) { +#ifdef _WIN32 + HCERTSTORE win_store = NULL; + PCCERT_CONTEXT win_ctx = NULL; +#endif + redisSSLContext *ctx = hi_calloc(1, sizeof(redisSSLContext)); if (ctx == NULL) goto error; @@ -234,6 +244,31 @@ redisSSLContext *redisCreateSSLContext(const char *cacert_filename, const char * } if (capath || cacert_filename) { +#ifdef _WIN32 + if (0 == strcmp(cacert_filename, "wincert")) { + win_store = CertOpenSystemStore(NULL, "Root"); + if (!win_store) { + if (error) *error = REDIS_SSL_CTX_OS_CERTSTORE_OPEN_FAILED; + goto error; + } + X509_STORE* store = SSL_CTX_get_cert_store(ctx->ssl_ctx); + while (win_ctx = CertEnumCertificatesInStore(win_store, win_ctx)) { + X509* x509 = NULL; + x509 = d2i_X509(NULL, (const unsigned char**)&win_ctx->pbCertEncoded, win_ctx->cbCertEncoded); + if (x509) { + if ((1 != X509_STORE_add_cert(store, x509)) || + (1 != SSL_CTX_add_client_CA(ctx->ssl_ctx, x509))) + { + if (error) *error = REDIS_SSL_CTX_OS_CERT_ADD_FAILED; + goto error; + } + X509_free(x509); + } + } + CertFreeCertificateContext(win_ctx); + CertCloseStore(win_store, 0); + } else +#endif if (!SSL_CTX_load_verify_locations(ctx->ssl_ctx, cacert_filename, capath)) { if (error) *error = REDIS_SSL_CTX_CA_CERT_LOAD_FAILED; goto error; @@ -257,6 +292,10 @@ redisSSLContext *redisCreateSSLContext(const char *cacert_filename, const char * return ctx; error: +#ifdef _WIN32 + CertFreeCertificateContext(win_ctx); + CertCloseStore(win_store, 0); +#endif redisFreeSSLContext(ctx); return NULL; }