MINOR: ssl: add a new error codes for wrong server certificates

If a server presents an unexpected certificate to haproxy, that is, a
certificate that doesn't match the expected name as configured in
verifyhost or as requested using SNI, we want to store that precious
information. Fortunately we have access to the connection in the
verification callback so it's possible to store an error code there.

For this purpose we use CO_ER_SSL_MISMATCH_SNI (for when the cert name
didn't match the one requested using SNI) and CO_ER_SSL_MISMATCH for
when it doesn't match verifyhost.
This commit is contained in:
Willy Tarreau 2017-07-26 20:09:56 +02:00
parent ad92a9a7be
commit 71d058c288
3 changed files with 9 additions and 0 deletions

View File

@ -605,6 +605,8 @@ static inline const char *conn_err_code_str(struct connection *c)
case CO_ER_SSL_RENEG: return "Rejected a client-initiated SSL renegociation attempt";
case CO_ER_SSL_CA_FAIL: return "SSL client CA chain cannot be verified";
case CO_ER_SSL_CRT_FAIL: return "SSL client certificate not trusted";
case CO_ER_SSL_MISMATCH: return "Server presented an SSL certificate different from the configured one";
case CO_ER_SSL_MISMATCH_SNI: return "Server presented an SSL certificate different from the expected one";
case CO_ER_SSL_HANDSHAKE: return "SSL handshake failure";
case CO_ER_SSL_HANDSHAKE_HB: return "SSL handshake failure after heartbeat";
case CO_ER_SSL_KILLED_HB: return "Stopped a TLSv1 heartbeat attack (CVE-2014-0160)";

View File

@ -179,6 +179,8 @@ enum {
CO_ER_SSL_RENEG, /* forbidden client renegociation */
CO_ER_SSL_CA_FAIL, /* client cert verification failed in the CA chain */
CO_ER_SSL_CRT_FAIL, /* client cert verification failed on the certificate */
CO_ER_SSL_MISMATCH, /* Server presented an SSL certificate different from the configured one */
CO_ER_SSL_MISMATCH_SNI, /* Server presented an SSL certificate different from the expected one */
CO_ER_SSL_HANDSHAKE, /* SSL error during handshake */
CO_ER_SSL_HANDSHAKE_HB, /* SSL error during handshake with heartbeat present */
CO_ER_SSL_KILLED_HB, /* Stopped a TLSv1 heartbeat attack (CVE-2014-0160) */

View File

@ -3931,6 +3931,7 @@ static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
SSL *ssl;
struct connection *conn;
const char *servername;
const char *sni;
int depth;
X509 *cert;
@ -3952,6 +3953,7 @@ static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
* verification is OK.
*/
servername = SSL_get_servername(conn->xprt_ctx, TLSEXT_NAMETYPE_host_name);
sni = servername;
if (!servername) {
servername = objt_server(conn->target)->ssl_ctx.verify_host;
if (!servername)
@ -4003,6 +4005,9 @@ static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
}
}
/* report the mismatch and indicate if SNI was used or not */
if (!ok && !conn->err_code)
conn->err_code = sni ? CO_ER_SSL_MISMATCH_SNI : CO_ER_SSL_MISMATCH;
return ok;
}