Fix typo in patch formatting.
Richard
diff --git a/include/haproxy/ssl_ckch.h b/include/haproxy/ssl_ckch.h index 94c53b301..00ba2bf18 100644 --- a/include/haproxy/ssl_ckch.h +++ b/include/haproxy/ssl_ckch.h @@ -72,5 +72,14 @@ int __ssl_store_load_locations_file(char *path, int create_if_none, enum cafile_ extern struct cert_exts cert_exts[]; extern int (*ssl_commit_crlfile_cb)(const char *path, X509_STORE *ctx, char **err); +struct ckch_data_cache { + struct ckch_data_cache *next; + struct ckch_data *key; + uint8_t *data; + int len; +}; + +struct ckch_data_cache *ckch_data_get(void *key); + #endif /* USE_OPENSSL */ #endif /* _HAPROXY_SSL_CRTLIST_H */ diff --git a/src/ssl_ckch.c b/src/ssl_ckch.c index add42b69e..9c256f193 100644 --- a/src/ssl_ckch.c +++ b/src/ssl_ckch.c @@ -516,11 +516,63 @@ int ssl_sock_load_files_into_ckch(const char *path, struct ckch_data *data, char * * Return 0 on success or != 0 on failure */ + +struct ckch_data_cache *cache[31] = {0}; + +/* + * This caches the BIO data in case the private key i + * + * to be instantiated in the child process (used for HSM keys) + * + * The key ckch_data* and the value is ckch_data_cache* + * + */ +static void ckch_data_put(void *key, uint8_t *data, int len) +{ + int idx = (unsigned long)key % 31; + struct ckch_data_cache *prev, *cur, *last = NULL; + + ha_notice("caching ckch_data:%p len:%d\n", key, len); + + for(prev = cache[idx]; prev != NULL;) { + last = prev; + prev = prev->next; + } + + cur = malloc(sizeof(struct ckch_data_cache)); + memset(cur, 0, sizeof(struct ckch_data_cache)); + if (last == NULL) + cache[idx] = cur; + else + last->next = cur; + cur->key = key; + cur->data = malloc(len); + memcpy(cur->data, data, len); + cur->len = len; +} + +struct ckch_data_cache *ckch_data_get(void *key) +{ + int idx = (unsigned long)key % 31; + struct ckch_data_cache *prev; + + for(prev = cache[idx]; prev != NULL; prev = prev->next) { + if (prev->key == key) + return prev; + } + + return NULL; +} + int ssl_sock_load_key_into_ckch(const char *path, char *buf, struct ckch_data *data , char **err) { BIO *in = NULL; int ret = 1; EVP_PKEY *key = NULL; + static char src[16384]; + char *src_temp; + int len; + int filetype = 0; if (buf) { /* reading from a buffer */ @@ -538,14 +590,25 @@ int ssl_sock_load_key_into_ckch(const char *path, char *buf, struct ckch_data *d if (BIO_read_filename(in, path) <= 0) goto end; + filetype = 1; } /* Read Private Key */ + if(filetype) { + len = BIO_read(in, src, sizeof(src)); + BIO_reset(in); + } else { + len = BIO_get_mem_data(in, &src_temp); + memcpy(src, src_temp, len); + } + key = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL); if (key == NULL) { memprintf(err, "%sunable to load private key from file '%s'.\n", err && *err ? *err : "", path); goto end; + } else { + ckch_data_put(data, (uint8_t*)src, len); } ret = 0; @@ -581,6 +644,10 @@ int ssl_sock_load_pem_into_ckch(const char *path, char *buf, struct ckch_data *d EVP_PKEY *key = NULL; HASSL_DH *dh = NULL; STACK_OF(X509) *chain = NULL; + int filetype = 0; + int len; + static char src[16384]; + char *src_temp; if (buf) { /* reading from a buffer */ @@ -603,11 +670,23 @@ int ssl_sock_load_pem_into_ckch(const char *path, char *buf, struct ckch_data *d err && *err ? *err : "", path); goto end; } + filetype = 1; } /* Read Private Key */ + if(filetype) { + len = BIO_read(in, src, sizeof(src)); + BIO_reset(in); + } else { + len = BIO_get_mem_data(in, &src_temp); + memcpy(src, src_temp, len); + } + key = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL); /* no need to check for errors here, because the private key could be loaded later */ + if(key && global.mode&MODE_MWORKER) { + ckch_data_put(data, (uint8_t *)src, len); + } #ifndef OPENSSL_NO_DH /* Seek back to beginning of file */ diff --git a/src/ssl_sock.c b/src/ssl_sock.c index 824bdaa72..64bd7ac04 100644 --- a/src/ssl_sock.c +++ b/src/ssl_sock.c @@ -2009,10 +2009,77 @@ struct methodVersions methodVersions[] = { {SSL_OP_NO_TLSv1_3, MC_SSL_O_NO_TLSV13, ctx_set_TLSv13_func, ssl_set_TLSv13_func, "TLSv1.3"}, /* CONF_TLSV13 */ }; +/* cache SSL_CTX* to ckch_data + * so we can recreate private key + */ +struct ssl_ctx_cache { + void *key; + struct ckch_data_cache *value; + struct ssl_ctx_cache *next; + EVP_PKEY *pkey; +}; +static struct ssl_ctx_cache *ctx_cache[31]; + +void ssl_ctx_put(void *key, void *data) +{ + int idx = (unsigned long)key % 31; + struct ssl_ctx_cache *prev, *cur, *last = NULL; + + ha_notice("ssl_ctx_cache key = %p value = %p\n", key, data); + + for(prev = ctx_cache[idx]; prev != NULL;) { + last = prev; + prev = prev->next; + } + + cur = malloc(sizeof(struct ssl_ctx_cache)); + memset(cur, 0, sizeof(struct ssl_ctx_cache)); + if (last == NULL) + ctx_cache[idx] = cur; + else + last->next = cur; + cur->next = NULL; + cur->key = key; + cur->value = data; +} + +struct ssl_ctx_cache *ssl_ctx_get(void *key) +{ + int idx = (unsigned long)key % 31; + struct ssl_ctx_cache *prev; + + for(prev = ctx_cache[idx]; prev != NULL; prev = prev->next) { + if (prev->key == key) { + ha_notice("ssl_ctx_cache found key = %p value = %p\n", key, prev->value); + return prev; + } + } + + return NULL; +} + static void ssl_sock_switchctx_set(SSL *ssl, SSL_CTX *ctx) { + struct ssl_ctx_cache *value = NULL; + BIO *in; + SSL_set_verify(ssl, SSL_CTX_get_verify_mode(ctx), ssl_sock_bind_verifycbk); SSL_set_client_CA_list(ssl, SSL_dup_CA_list(SSL_CTX_get_client_CA_list(ctx))); + + if ((value = ssl_ctx_get(ctx))) { + if (value->pkey == NULL) { + in = BIO_new_mem_buf(value->value->data, value->value->len); + if ((value->pkey = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL))) { + SSL_CTX_use_PrivateKey(ctx, value->pkey); + ha_notice("loaded private key PID=%d SSL_CTX*=%p\n", getpid(), ctx); + } + else { + value->pkey = (EVP_PKEY*)-1L; + ha_notice("unable to realize private key from memory buffer\n"); + } + } + } + SSL_set_SSL_CTX(ssl, ctx); } @@ -3323,11 +3390,16 @@ static int ssl_sock_load_cert_chain(const char *path, const struct ckch_data *da static int ssl_sock_put_ckch_into_ctx(const char *path, struct ckch_data *data, SSL_CTX *ctx, char **err) { int errcode = 0; + struct ckch_data_cache *value; STACK_OF(X509) *find_chain = NULL; ERR_clear_error(); - if (SSL_CTX_use_PrivateKey(ctx, data->key) <= 0) { + if(global.mode&MODE_MWORKER && (value = ckch_data_get(data))) { + ssl_ctx_put(ctx, value); + } + + if (!(global.mode&MODE_MWORKER) && SSL_CTX_use_PrivateKey(ctx, data->key) <= 0) { int ret; ret = ERR_get_error();