mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-04-19 21:45:33 +00:00
BUG/MINOR: ssl: fix management of the cache where forged certificates are stored
First, the LRU cache must be initialized after the configuration parsing to correctly set its size. Next, the function 'ssl_sock_set_generated_cert' returns -1 when an error occurs (0 if success). In that case, the caller is responsible to free the memory allocated for the certificate. Finally, when a SSL certificate is generated by HAProxy but cannot be inserted in the cache, it must be freed when the SSL connection is closed. This happens when 'tune.ssl.ssl-ctx-cache-size' is set to 0.
This commit is contained in:
parent
d57ad64873
commit
d2cab92e75
@ -72,7 +72,7 @@ int ssl_sock_load_global_dh_param_from_file(const char *filename);
|
|||||||
|
|
||||||
SSL_CTX *ssl_sock_create_cert(const char *servername, unsigned int serial, X509 *cacert, EVP_PKEY *capkey);
|
SSL_CTX *ssl_sock_create_cert(const char *servername, unsigned int serial, X509 *cacert, EVP_PKEY *capkey);
|
||||||
SSL_CTX *ssl_sock_get_generated_cert(unsigned int serial, X509 *cacert);
|
SSL_CTX *ssl_sock_get_generated_cert(unsigned int serial, X509 *cacert);
|
||||||
void ssl_sock_set_generated_cert(SSL_CTX *ctx, unsigned int serial, X509 *cacert);
|
int ssl_sock_set_generated_cert(SSL_CTX *ctx, unsigned int serial, X509 *cacert);
|
||||||
unsigned int ssl_sock_generated_cert_serial(const void *data, size_t len);
|
unsigned int ssl_sock_generated_cert_serial(const void *data, size_t len);
|
||||||
|
|
||||||
#endif /* _PROTO_SSL_SOCK_H */
|
#endif /* _PROTO_SSL_SOCK_H */
|
||||||
|
@ -1127,8 +1127,9 @@ ssl_sock_get_generated_cert(unsigned int serial, X509 *cacert)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set a certificate int the LRU cache used to store generated certificate. */
|
/* Set a certificate int the LRU cache used to store generated
|
||||||
void
|
* certificate. Return 0 on success, otherwise -1 */
|
||||||
|
int
|
||||||
ssl_sock_set_generated_cert(SSL_CTX *ssl_ctx, unsigned int serial, X509 *cacert)
|
ssl_sock_set_generated_cert(SSL_CTX *ssl_ctx, unsigned int serial, X509 *cacert)
|
||||||
{
|
{
|
||||||
struct lru64 *lru = NULL;
|
struct lru64 *lru = NULL;
|
||||||
@ -1136,11 +1137,13 @@ ssl_sock_set_generated_cert(SSL_CTX *ssl_ctx, unsigned int serial, X509 *cacert)
|
|||||||
if (ssl_ctx_lru_tree) {
|
if (ssl_ctx_lru_tree) {
|
||||||
lru = lru64_get(serial, ssl_ctx_lru_tree, cacert, 0);
|
lru = lru64_get(serial, ssl_ctx_lru_tree, cacert, 0);
|
||||||
if (!lru)
|
if (!lru)
|
||||||
return;
|
return -1;
|
||||||
if (lru->domain && lru->data)
|
if (lru->domain && lru->data)
|
||||||
lru->free((SSL_CTX *)lru->data);
|
lru->free((SSL_CTX *)lru->data);
|
||||||
lru64_commit(lru, ssl_ctx, cacert, 0, (void (*)(void *))SSL_CTX_free);
|
lru64_commit(lru, ssl_ctx, cacert, 0, (void (*)(void *))SSL_CTX_free);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Compute the serial that will be used to create/set/get a certificate. */
|
/* Compute the serial that will be used to create/set/get a certificate. */
|
||||||
@ -1164,13 +1167,13 @@ ssl_sock_generate_certificate(const char *servername, struct bind_conf *bind_con
|
|||||||
lru = lru64_get(serial, ssl_ctx_lru_tree, cacert, 0);
|
lru = lru64_get(serial, ssl_ctx_lru_tree, cacert, 0);
|
||||||
if (lru && lru->domain)
|
if (lru && lru->domain)
|
||||||
ssl_ctx = (SSL_CTX *)lru->data;
|
ssl_ctx = (SSL_CTX *)lru->data;
|
||||||
}
|
if (!ssl_ctx && lru) {
|
||||||
|
ssl_ctx = ssl_sock_create_cert(servername, serial, cacert, capkey);
|
||||||
if (!ssl_ctx) {
|
|
||||||
ssl_ctx = ssl_sock_create_cert(servername, serial, cacert, capkey);
|
|
||||||
if (lru)
|
|
||||||
lru64_commit(lru, ssl_ctx, cacert, 0, (void (*)(void *))SSL_CTX_free);
|
lru64_commit(lru, ssl_ctx, cacert, 0, (void (*)(void *))SSL_CTX_free);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
ssl_ctx = ssl_sock_create_cert(servername, serial, cacert, capkey);
|
||||||
return ssl_ctx;
|
return ssl_ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2489,6 +2492,10 @@ ssl_sock_load_ca(struct bind_conf *bind_conf, struct proxy *px)
|
|||||||
if (!bind_conf || !bind_conf->generate_certs)
|
if (!bind_conf || !bind_conf->generate_certs)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
if (global.tune.ssl_ctx_cache)
|
||||||
|
ssl_ctx_lru_tree = lru64_new(global.tune.ssl_ctx_cache);
|
||||||
|
ssl_ctx_lru_seed = (unsigned int)time(NULL);
|
||||||
|
|
||||||
if (!bind_conf->ca_sign_file) {
|
if (!bind_conf->ca_sign_file) {
|
||||||
Alert("Proxy '%s': cannot enable certificate generation, "
|
Alert("Proxy '%s': cannot enable certificate generation, "
|
||||||
"no CA certificate File configured at [%s:%d].\n",
|
"no CA certificate File configured at [%s:%d].\n",
|
||||||
@ -2838,7 +2845,6 @@ int ssl_sock_handshake(struct connection *conn, unsigned int flag)
|
|||||||
}
|
}
|
||||||
|
|
||||||
reneg_ok:
|
reneg_ok:
|
||||||
|
|
||||||
/* Handshake succeeded */
|
/* Handshake succeeded */
|
||||||
if (!SSL_session_reused(conn->xprt_ctx)) {
|
if (!SSL_session_reused(conn->xprt_ctx)) {
|
||||||
if (objt_server(conn->target)) {
|
if (objt_server(conn->target)) {
|
||||||
@ -3082,6 +3088,11 @@ static int ssl_sock_from_buf(struct connection *conn, struct buffer *buf, int fl
|
|||||||
static void ssl_sock_close(struct connection *conn) {
|
static void ssl_sock_close(struct connection *conn) {
|
||||||
|
|
||||||
if (conn->xprt_ctx) {
|
if (conn->xprt_ctx) {
|
||||||
|
if (!ssl_ctx_lru_tree && objt_listener(conn->target)) {
|
||||||
|
SSL_CTX *ctx = SSL_get_SSL_CTX(conn->xprt_ctx);
|
||||||
|
if (ctx != objt_listener(conn->target)->bind_conf->default_ctx)
|
||||||
|
SSL_CTX_free(ctx);
|
||||||
|
}
|
||||||
SSL_free(conn->xprt_ctx);
|
SSL_free(conn->xprt_ctx);
|
||||||
conn->xprt_ctx = NULL;
|
conn->xprt_ctx = NULL;
|
||||||
sslconns--;
|
sslconns--;
|
||||||
@ -5344,21 +5355,12 @@ static void __ssl_sock_init(void)
|
|||||||
#ifndef OPENSSL_NO_DH
|
#ifndef OPENSSL_NO_DH
|
||||||
ssl_dh_ptr_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
|
ssl_dh_ptr_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
|
|
||||||
/* Add a global parameter for the LRU cache size */
|
|
||||||
if (global.tune.ssl_ctx_cache)
|
|
||||||
ssl_ctx_lru_tree = lru64_new(global.tune.ssl_ctx_cache);
|
|
||||||
ssl_ctx_lru_seed = (unsigned int)time(NULL);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((destructor))
|
__attribute__((destructor))
|
||||||
static void __ssl_sock_deinit(void)
|
static void __ssl_sock_deinit(void)
|
||||||
{
|
{
|
||||||
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
|
|
||||||
lru64_destroy(ssl_ctx_lru_tree);
|
lru64_destroy(ssl_ctx_lru_tree);
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef OPENSSL_NO_DH
|
#ifndef OPENSSL_NO_DH
|
||||||
if (local_dh_1024) {
|
if (local_dh_1024) {
|
||||||
|
Loading…
Reference in New Issue
Block a user