diff options
| author | Alessio M <masariello@gmail.com> | 2020-09-08 20:07:59 +0100 | 
|---|---|---|
| committer | Alessio M <masariello@gmail.com> | 2020-09-08 20:09:39 +0100 | 
| commit | 6693863f4c9370cb800fbc2ec45ed027c8fa5f02 (patch) | |
| tree | a0480e491a383d37c40b3cc72bc548d1ce8f7149 | |
| parent | 2a5a57b90a57af5142221aa71f38c08f4a737376 (diff) | |
| download | hiredict-6693863f4c9370cb800fbc2ec45ed027c8fa5f02.tar.xz | |
Add support for system CA certificate store on Windows
| -rw-r--r-- | hiredis_ssl.h | 4 | ||||
| -rw-r--r-- | ssl.c | 43 | 
2 files changed, 46 insertions, 1 deletions
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;  /** @@ -38,6 +38,7 @@  #include <string.h>  #ifdef _WIN32  #include <windows.h> +#include <wincrypt.h>  #else  #include <pthread.h>  #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,35 @@ 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 +296,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;  }  | 
