mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-04-29 22:38:40 +00:00
BUG/MINOR: ssl: fix cipherlist captures with sustainable SSL calls
Use SSL_set_ex_data/SSL_get_ex_data standard API call to store capture. We need to avoid internal structures/undocumented calls usage to try to control the beast and limit painful compatibilities.
This commit is contained in:
parent
f6b37c67be
commit
aaee75088a
@ -13880,14 +13880,12 @@ ssl_fc_cipher : string
|
|||||||
ssl_fc_cipherlist_bin : binary
|
ssl_fc_cipherlist_bin : binary
|
||||||
Returns the binary form of the client hello cipher list. The maximum returned
|
Returns the binary form of the client hello cipher list. The maximum returned
|
||||||
value length is according with the value of
|
value length is according with the value of
|
||||||
"tune.ssl.capture-cipherlist-size". Note that this sample-fetch is available
|
"tune.ssl.capture-cipherlist-size".
|
||||||
only with OpenSSL > 0.9.7
|
|
||||||
|
|
||||||
ssl_fc_cipherlist_hex : string
|
ssl_fc_cipherlist_hex : string
|
||||||
Returns the binary form of the client hello cipher list encoded as
|
Returns the binary form of the client hello cipher list encoded as
|
||||||
hexadecimal. The maximum returned value length is according with the value of
|
hexadecimal. The maximum returned value length is according with the value of
|
||||||
"tune.ssl.capture-cipherlist-size". Note that this sample-fetch is available
|
"tune.ssl.capture-cipherlist-size".
|
||||||
only with OpenSSL > 0.9.7
|
|
||||||
|
|
||||||
ssl_fc_cipherlist_str : string
|
ssl_fc_cipherlist_str : string
|
||||||
Returns the decoded text form of the client hello cipher list. The maximum
|
Returns the decoded text form of the client hello cipher list. The maximum
|
||||||
@ -13900,8 +13898,7 @@ ssl_fc_cipherlist_str : string
|
|||||||
ssl_fc_cipherlist_xxh : integer
|
ssl_fc_cipherlist_xxh : integer
|
||||||
Returns a xxh64 of the cipher list. This hash can be return only is the value
|
Returns a xxh64 of the cipher list. This hash can be return only is the value
|
||||||
"tune.ssl.capture-cipherlist-size" is set greater than 0, however the hash
|
"tune.ssl.capture-cipherlist-size" is set greater than 0, however the hash
|
||||||
take in account all the data of the cipher list. Note that this sample-fetch is
|
take in account all the data of the cipher list.
|
||||||
avalaible only with OpenSSL > 0.9.7
|
|
||||||
|
|
||||||
ssl_fc_has_crt : boolean
|
ssl_fc_has_crt : boolean
|
||||||
Returns true if a client certificate is present in an incoming connection over
|
Returns true if a client certificate is present in an incoming connection over
|
||||||
|
@ -165,10 +165,7 @@ static struct {
|
|||||||
.capture_cipherlist = 0,
|
.capture_cipherlist = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* This memory pool is used for capturing clienthello parameters.
|
/* This memory pool is used for capturing clienthello parameters. */
|
||||||
* The message callback is only available after openssl 0.9.7,
|
|
||||||
* so the memory pool is useless before this version.
|
|
||||||
*/
|
|
||||||
struct ssl_capture {
|
struct ssl_capture {
|
||||||
struct connection *conn;
|
struct connection *conn;
|
||||||
unsigned long long int xxh64;
|
unsigned long long int xxh64;
|
||||||
@ -176,17 +173,7 @@ struct ssl_capture {
|
|||||||
char ciphersuite[0];
|
char ciphersuite[0];
|
||||||
};
|
};
|
||||||
struct pool_head *pool2_ssl_capture = NULL;
|
struct pool_head *pool2_ssl_capture = NULL;
|
||||||
|
static int ssl_capture_ptr_index = -1;
|
||||||
#if OPENSSL_VERSION_NUMBER >= 0x00907000L
|
|
||||||
/* This fu**ing funtion is announced in some OpenSSL manual pages,
|
|
||||||
* but doesn't exists in the OpenSSL library !
|
|
||||||
* eg. https://www.openssl.org/docs/man1.0.1/ssl/SSL_get_msg_callback_arg.html
|
|
||||||
*/
|
|
||||||
static void *SSL_get_msg_callback_arg(SSL *ssl)
|
|
||||||
{
|
|
||||||
return ssl->msg_callback_arg;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
|
#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
|
||||||
struct list tlskeys_reference = LIST_HEAD_INIT(tlskeys_reference);
|
struct list tlskeys_reference = LIST_HEAD_INIT(tlskeys_reference);
|
||||||
@ -1258,11 +1245,11 @@ void ssl_sock_parse_clienthello(int write_p, int version, int content_type,
|
|||||||
/* Callback is called for ssl protocol analyse */
|
/* Callback is called for ssl protocol analyse */
|
||||||
void ssl_sock_msgcbk(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)
|
void ssl_sock_msgcbk(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)
|
||||||
{
|
{
|
||||||
/* If the SSL connection doesn't had sufficient memory while
|
if (global_ssl.capture_cipherlist) {
|
||||||
* the structure was initialized, arg is NULL.
|
struct ssl_capture *capture = SSL_get_ex_data(ssl, ssl_capture_ptr_index);
|
||||||
*/
|
if (capture)
|
||||||
if (global_ssl.capture_cipherlist && arg)
|
ssl_sock_parse_clienthello(write_p, version, content_type, buf, len, capture);
|
||||||
ssl_sock_parse_clienthello(write_p, version, content_type, buf, len, arg);
|
}
|
||||||
|
|
||||||
#ifdef TLS1_RT_HEARTBEAT
|
#ifdef TLS1_RT_HEARTBEAT
|
||||||
/* test heartbeat received (write_p is set to 0
|
/* test heartbeat received (write_p is set to 0
|
||||||
@ -3971,8 +3958,6 @@ ssl_sock_free_ca(struct bind_conf *bind_conf)
|
|||||||
*/
|
*/
|
||||||
static int ssl_sock_init(struct connection *conn)
|
static int ssl_sock_init(struct connection *conn)
|
||||||
{
|
{
|
||||||
struct ssl_capture *capture;
|
|
||||||
|
|
||||||
/* already initialized */
|
/* already initialized */
|
||||||
if (conn->xprt_ctx)
|
if (conn->xprt_ctx)
|
||||||
return 0;
|
return 0;
|
||||||
@ -4080,19 +4065,15 @@ static int ssl_sock_init(struct connection *conn)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if OPENSSL_VERSION_NUMBER >= 0x00907000L
|
|
||||||
/* Set capture struct as opaque argument for the msg callback. */
|
/* Set capture struct as opaque argument for the msg callback. */
|
||||||
if (global_ssl.capture_cipherlist > 0) {
|
if (global_ssl.capture_cipherlist > 0) {
|
||||||
capture = pool_alloc_dirty(pool2_ssl_capture);
|
struct ssl_capture *capture = pool_alloc_dirty(pool2_ssl_capture);
|
||||||
if (capture) {
|
if (capture) {
|
||||||
capture->conn = conn;
|
capture->conn = conn;
|
||||||
capture->ciphersuite_len = 0;
|
capture->ciphersuite_len = 0;
|
||||||
SSL_set_msg_callback_arg(conn->xprt_ctx, capture);
|
SSL_set_ex_data(conn->xprt_ctx, ssl_capture_ptr_index, capture);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
SSL_set_msg_callback_arg(conn->xprt_ctx, NULL);
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
SSL_set_accept_state(conn->xprt_ctx);
|
SSL_set_accept_state(conn->xprt_ctx);
|
||||||
|
|
||||||
@ -4541,13 +4522,8 @@ 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) {
|
||||||
struct ssl_capture *capture;
|
|
||||||
|
|
||||||
if (conn->xprt_ctx) {
|
if (conn->xprt_ctx) {
|
||||||
#if OPENSSL_VERSION_NUMBER >= 0x00907000L
|
|
||||||
capture = SSL_get_msg_callback_arg(conn->xprt_ctx);
|
|
||||||
pool_free2(pool2_ssl_capture, capture);
|
|
||||||
#endif
|
|
||||||
SSL_free(conn->xprt_ctx);
|
SSL_free(conn->xprt_ctx);
|
||||||
conn->xprt_ctx = NULL;
|
conn->xprt_ctx = NULL;
|
||||||
sslconns--;
|
sslconns--;
|
||||||
@ -5661,7 +5637,6 @@ smp_fetch_ssl_fc_sni(const struct arg *args, struct sample *smp, const char *kw,
|
|||||||
static int
|
static int
|
||||||
smp_fetch_ssl_fc_cl_bin(const struct arg *args, struct sample *smp, const char *kw, void *private)
|
smp_fetch_ssl_fc_cl_bin(const struct arg *args, struct sample *smp, const char *kw, void *private)
|
||||||
{
|
{
|
||||||
#if OPENSSL_VERSION_NUMBER >= 0x00907000L
|
|
||||||
struct connection *conn;
|
struct connection *conn;
|
||||||
struct ssl_capture *capture;
|
struct ssl_capture *capture;
|
||||||
|
|
||||||
@ -5669,7 +5644,7 @@ smp_fetch_ssl_fc_cl_bin(const struct arg *args, struct sample *smp, const char *
|
|||||||
if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
|
if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
capture = SSL_get_msg_callback_arg(conn->xprt_ctx);
|
capture = SSL_get_ex_data(conn->xprt_ctx, ssl_capture_ptr_index);
|
||||||
if (!capture)
|
if (!capture)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -5678,10 +5653,6 @@ smp_fetch_ssl_fc_cl_bin(const struct arg *args, struct sample *smp, const char *
|
|||||||
smp->data.u.str.str = capture->ciphersuite;
|
smp->data.u.str.str = capture->ciphersuite;
|
||||||
smp->data.u.str.len = capture->ciphersuite_len;
|
smp->data.u.str.len = capture->ciphersuite_len;
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
#else
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -5702,7 +5673,6 @@ smp_fetch_ssl_fc_cl_hex(const struct arg *args, struct sample *smp, const char *
|
|||||||
static int
|
static int
|
||||||
smp_fetch_ssl_fc_cl_xxh64(const struct arg *args, struct sample *smp, const char *kw, void *private)
|
smp_fetch_ssl_fc_cl_xxh64(const struct arg *args, struct sample *smp, const char *kw, void *private)
|
||||||
{
|
{
|
||||||
#if OPENSSL_VERSION_NUMBER >= 0x00907000L
|
|
||||||
struct connection *conn;
|
struct connection *conn;
|
||||||
struct ssl_capture *capture;
|
struct ssl_capture *capture;
|
||||||
|
|
||||||
@ -5710,17 +5680,13 @@ smp_fetch_ssl_fc_cl_xxh64(const struct arg *args, struct sample *smp, const char
|
|||||||
if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
|
if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
capture = SSL_get_msg_callback_arg(conn->xprt_ctx);
|
capture = SSL_get_ex_data(conn->xprt_ctx, ssl_capture_ptr_index);
|
||||||
if (!capture)
|
if (!capture)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
smp->data.type = SMP_T_SINT;
|
smp->data.type = SMP_T_SINT;
|
||||||
smp->data.u.sint = capture->xxh64;
|
smp->data.u.sint = capture->xxh64;
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
#else
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -6910,7 +6876,6 @@ static int ssl_parse_global_capture_cipherlist(char **args, int section_type, st
|
|||||||
struct proxy *defpx, const char *file, int line,
|
struct proxy *defpx, const char *file, int line,
|
||||||
char **err)
|
char **err)
|
||||||
{
|
{
|
||||||
#if OPENSSL_VERSION_NUMBER >= 0x00907000L
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
|
ret = ssl_parse_global_int(args, section_type, curpx, defpx, file, line, err);
|
||||||
@ -6928,10 +6893,6 @@ static int ssl_parse_global_capture_cipherlist(char **args, int section_type, st
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
#else
|
|
||||||
memprintf(err, "'%s' requires OpenSSL 0.9.7 or above.", args[0]);
|
|
||||||
return -1;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* parse "ssl.force-private-cache".
|
/* parse "ssl.force-private-cache".
|
||||||
@ -7482,6 +7443,10 @@ static void ssl_sock_sctl_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
static void ssl_sock_capture_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
|
||||||
|
{
|
||||||
|
pool_free2(pool2_ssl_capture, ptr);
|
||||||
|
}
|
||||||
|
|
||||||
__attribute__((constructor))
|
__attribute__((constructor))
|
||||||
static void __ssl_sock_init(void)
|
static void __ssl_sock_init(void)
|
||||||
@ -7502,6 +7467,7 @@ static void __ssl_sock_init(void)
|
|||||||
#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
|
#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
|
||||||
sctl_ex_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_sctl_free_func);
|
sctl_ex_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_sctl_free_func);
|
||||||
#endif
|
#endif
|
||||||
|
ssl_capture_ptr_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_capture_free_func);
|
||||||
sample_register_fetches(&sample_fetch_keywords);
|
sample_register_fetches(&sample_fetch_keywords);
|
||||||
acl_register_keywords(&acl_kws);
|
acl_register_keywords(&acl_kws);
|
||||||
bind_register_keywords(&bind_kws);
|
bind_register_keywords(&bind_kws);
|
||||||
|
Loading…
Reference in New Issue
Block a user