mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-08-06 07:07:04 +02:00
MEDIUM: ssl: protect against client-initiated renegociation
CVE-2009-3555 suggests that client-initiated renegociation should be prevented in the middle of data. The workaround here consists in having the SSL layer notify our callback about a handshake occurring, which in turn causes the connection to be marked in the error state if it was already considered established (which means if a previous handshake was completed). The result is that the connection with the client is immediately aborted and any pending data are dropped.
This commit is contained in:
parent
01f8e2f61b
commit
e1f38dbb44
@ -26,6 +26,7 @@
|
|||||||
|
|
||||||
extern struct data_ops ssl_sock;
|
extern struct data_ops ssl_sock;
|
||||||
int ssl_sock_handshake(struct connection *conn, unsigned int flag);
|
int ssl_sock_handshake(struct connection *conn, unsigned int flag);
|
||||||
|
void ssl_sock_infocbk(const SSL *ssl, int where, int ret);
|
||||||
|
|
||||||
#endif /* _PROTO_SSL_SOCK_H */
|
#endif /* _PROTO_SSL_SOCK_H */
|
||||||
|
|
||||||
|
@ -6704,6 +6704,7 @@ int check_config_validity()
|
|||||||
SSL_CTX_set_mode(listener->ssl_ctx.ctx, sslmode);
|
SSL_CTX_set_mode(listener->ssl_ctx.ctx, sslmode);
|
||||||
SSL_CTX_set_verify(listener->ssl_ctx.ctx, SSL_VERIFY_NONE, NULL);
|
SSL_CTX_set_verify(listener->ssl_ctx.ctx, SSL_VERIFY_NONE, NULL);
|
||||||
SSL_CTX_set_session_cache_mode(listener->ssl_ctx.ctx, SSL_SESS_CACHE_SERVER);
|
SSL_CTX_set_session_cache_mode(listener->ssl_ctx.ctx, SSL_SESS_CACHE_SERVER);
|
||||||
|
SSL_CTX_set_info_callback(listener->ssl_ctx.ctx, ssl_sock_infocbk);
|
||||||
|
|
||||||
if (SSL_CTX_use_PrivateKey_file(listener->ssl_ctx.ctx, listener->ssl_cert, SSL_FILETYPE_PEM) <= 0) {
|
if (SSL_CTX_use_PrivateKey_file(listener->ssl_ctx.ctx, listener->ssl_cert, SSL_FILETYPE_PEM) <= 0) {
|
||||||
Alert("Proxy '%s': unable to load SSL private key from file '%s' in listener %d (%s:%d).\n",
|
Alert("Proxy '%s': unable to load SSL private key from file '%s' in listener %d (%s:%d).\n",
|
||||||
|
@ -44,6 +44,19 @@
|
|||||||
#include <types/global.h>
|
#include <types/global.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void ssl_sock_infocbk(const SSL *ssl, int where, int ret)
|
||||||
|
{
|
||||||
|
struct connection *conn = (struct connection *)SSL_get_app_data(ssl);
|
||||||
|
(void)ret; /* shut gcc stupid warning */
|
||||||
|
|
||||||
|
if (where & SSL_CB_HANDSHAKE_START) {
|
||||||
|
/* Disable renegotiation (CVE-2009-3555) */
|
||||||
|
if (conn->flags & CO_FL_CONNECTED)
|
||||||
|
conn->flags |= CO_FL_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function is called if SSL * context is not yet allocated. The function
|
* This function is called if SSL * context is not yet allocated. The function
|
||||||
* is designed to be called before any other data-layer operation and sets the
|
* is designed to be called before any other data-layer operation and sets the
|
||||||
@ -88,6 +101,9 @@ static int ssl_sock_init(struct connection *conn)
|
|||||||
/* set fd on SSL session context */
|
/* set fd on SSL session context */
|
||||||
SSL_set_fd(conn->data_ctx, conn->t.sock.fd);
|
SSL_set_fd(conn->data_ctx, conn->t.sock.fd);
|
||||||
|
|
||||||
|
/* set connection pointer */
|
||||||
|
SSL_set_app_data(conn->data_ctx, conn);
|
||||||
|
|
||||||
/* leave init state and start handshake */
|
/* leave init state and start handshake */
|
||||||
conn->flags |= CO_FL_SSL_WAIT_HS;
|
conn->flags |= CO_FL_SSL_WAIT_HS;
|
||||||
return 0;
|
return 0;
|
||||||
@ -197,7 +213,10 @@ static int ssl_sock_to_buf(struct connection *conn, struct buffer *buf, int coun
|
|||||||
*/
|
*/
|
||||||
while (try) {
|
while (try) {
|
||||||
ret = SSL_read(conn->data_ctx, bi_end(buf), try);
|
ret = SSL_read(conn->data_ctx, bi_end(buf), try);
|
||||||
|
if (conn->flags & CO_FL_ERROR) {
|
||||||
|
/* CO_FL_ERROR may be set by ssl_sock_infocbk */
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (ret > 0) {
|
if (ret > 0) {
|
||||||
buf->i += ret;
|
buf->i += ret;
|
||||||
done += ret;
|
done += ret;
|
||||||
@ -271,6 +290,10 @@ static int ssl_sock_from_buf(struct connection *conn, struct buffer *buf, int fl
|
|||||||
try = buf->data + try - buf->p;
|
try = buf->data + try - buf->p;
|
||||||
|
|
||||||
ret = SSL_write(conn->data_ctx, bo_ptr(buf), try);
|
ret = SSL_write(conn->data_ctx, bo_ptr(buf), try);
|
||||||
|
if (conn->flags & CO_FL_ERROR) {
|
||||||
|
/* CO_FL_ERROR may be set by ssl_sock_infocbk */
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (ret > 0) {
|
if (ret > 0) {
|
||||||
buf->o -= ret;
|
buf->o -= ret;
|
||||||
done += ret;
|
done += ret;
|
||||||
|
Loading…
Reference in New Issue
Block a user