mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-01-10 16:00:08 +00:00
BUG/MEDIUM: ssl: Prevent ssl error from affecting other connections.
J. Maurice reported that ssllabs.com test affects unrelated legitimate traffic and cause SSL errors and broken connections. Sometimes openssl store read/write/handshake errors in a global stack. This stack is not specific to the current session. Openssl API does not clean the stack at the beginning of a new read/write. And the function used to retrieve error ID after read/write, returns the generic error SSL_ERROR_SSL if the global stack is not empty. The fix consists in cleaning the errors stack after read/write/handshake errors.
This commit is contained in:
parent
f26b252ee4
commit
644cde05f6
@ -232,6 +232,9 @@ int ssl_sock_load_dh_params(SSL_CTX *ctx, const char *file)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ret = 0; /* DH params not found */
|
ret = 0; /* DH params not found */
|
||||||
|
|
||||||
|
/* Clear openssl global errors stack */
|
||||||
|
ERR_clear_error();
|
||||||
end:
|
end:
|
||||||
if (dh)
|
if (dh)
|
||||||
DH_free(dh);
|
DH_free(dh);
|
||||||
@ -563,6 +566,7 @@ int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, SSL_CTX *ctx, struct proxy
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
ERR_clear_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (global.tune.ssllifetime)
|
if (global.tune.ssllifetime)
|
||||||
@ -1003,6 +1007,9 @@ reneg_ok:
|
|||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
out_error:
|
out_error:
|
||||||
|
/* Clear openssl global errors stack */
|
||||||
|
ERR_clear_error();
|
||||||
|
|
||||||
/* free resumed session if exists */
|
/* free resumed session if exists */
|
||||||
if (objt_server(conn->target) && objt_server(conn->target)->ssl_ctx.reused_sess) {
|
if (objt_server(conn->target) && objt_server(conn->target)->ssl_ctx.reused_sess) {
|
||||||
SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
|
SSL_SESSION_free(objt_server(conn->target)->ssl_ctx.reused_sess);
|
||||||
@ -1058,7 +1065,7 @@ static int ssl_sock_to_buf(struct connection *conn, struct buffer *buf, int coun
|
|||||||
ret = SSL_read(conn->xprt_ctx, bi_end(buf), try);
|
ret = SSL_read(conn->xprt_ctx, bi_end(buf), try);
|
||||||
if (conn->flags & CO_FL_ERROR) {
|
if (conn->flags & CO_FL_ERROR) {
|
||||||
/* CO_FL_ERROR may be set by ssl_sock_infocbk */
|
/* CO_FL_ERROR may be set by ssl_sock_infocbk */
|
||||||
break;
|
goto out_error;
|
||||||
}
|
}
|
||||||
if (ret > 0) {
|
if (ret > 0) {
|
||||||
buf->i += ret;
|
buf->i += ret;
|
||||||
@ -1069,6 +1076,11 @@ static int ssl_sock_to_buf(struct connection *conn, struct buffer *buf, int coun
|
|||||||
try = count;
|
try = count;
|
||||||
}
|
}
|
||||||
else if (ret == 0) {
|
else if (ret == 0) {
|
||||||
|
ret = SSL_get_error(conn->xprt_ctx, ret);
|
||||||
|
if (ret != SSL_ERROR_ZERO_RETURN) {
|
||||||
|
/* Clear openssl global errors stack */
|
||||||
|
ERR_clear_error();
|
||||||
|
}
|
||||||
goto read0;
|
goto read0;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -1100,6 +1112,9 @@ static int ssl_sock_to_buf(struct connection *conn, struct buffer *buf, int coun
|
|||||||
conn_sock_read0(conn);
|
conn_sock_read0(conn);
|
||||||
return done;
|
return done;
|
||||||
out_error:
|
out_error:
|
||||||
|
/* Clear openssl global errors stack */
|
||||||
|
ERR_clear_error();
|
||||||
|
|
||||||
conn->flags |= CO_FL_ERROR;
|
conn->flags |= CO_FL_ERROR;
|
||||||
return done;
|
return done;
|
||||||
}
|
}
|
||||||
@ -1141,7 +1156,7 @@ static int ssl_sock_from_buf(struct connection *conn, struct buffer *buf, int fl
|
|||||||
ret = SSL_write(conn->xprt_ctx, bo_ptr(buf), try);
|
ret = SSL_write(conn->xprt_ctx, bo_ptr(buf), try);
|
||||||
if (conn->flags & CO_FL_ERROR) {
|
if (conn->flags & CO_FL_ERROR) {
|
||||||
/* CO_FL_ERROR may be set by ssl_sock_infocbk */
|
/* CO_FL_ERROR may be set by ssl_sock_infocbk */
|
||||||
break;
|
goto out_error;
|
||||||
}
|
}
|
||||||
if (ret > 0) {
|
if (ret > 0) {
|
||||||
buf->o -= ret;
|
buf->o -= ret;
|
||||||
@ -1180,11 +1195,13 @@ static int ssl_sock_from_buf(struct connection *conn, struct buffer *buf, int fl
|
|||||||
return done;
|
return done;
|
||||||
|
|
||||||
out_error:
|
out_error:
|
||||||
|
/* Clear openssl global errors stack */
|
||||||
|
ERR_clear_error();
|
||||||
|
|
||||||
conn->flags |= CO_FL_ERROR;
|
conn->flags |= CO_FL_ERROR;
|
||||||
return done;
|
return done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void ssl_sock_close(struct connection *conn) {
|
static void ssl_sock_close(struct connection *conn) {
|
||||||
|
|
||||||
if (conn->xprt_ctx) {
|
if (conn->xprt_ctx) {
|
||||||
@ -1202,8 +1219,10 @@ static void ssl_sock_shutw(struct connection *conn, int clean)
|
|||||||
if (conn->flags & CO_FL_HANDSHAKE)
|
if (conn->flags & CO_FL_HANDSHAKE)
|
||||||
return;
|
return;
|
||||||
/* no handshake was in progress, try a clean ssl shutdown */
|
/* no handshake was in progress, try a clean ssl shutdown */
|
||||||
if (clean)
|
if (clean && (SSL_shutdown(conn->xprt_ctx) <= 0)) {
|
||||||
SSL_shutdown(conn->xprt_ctx);
|
/* Clear openssl global errors stack */
|
||||||
|
ERR_clear_error();
|
||||||
|
}
|
||||||
|
|
||||||
/* force flag on ssl to keep session in cache regardless shutdown result */
|
/* force flag on ssl to keep session in cache regardless shutdown result */
|
||||||
SSL_set_shutdown(conn->xprt_ctx, SSL_SENT_SHUTDOWN);
|
SSL_set_shutdown(conn->xprt_ctx, SSL_SENT_SHUTDOWN);
|
||||||
|
Loading…
Reference in New Issue
Block a user