mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-04-23 23:45:37 +00:00
MINOR: payload: add support for tls session ticket ext
req.ssl_st_ext : integer Returns 0 if the client didn't send a SessionTicket TLS Extension (RFC5077) Returns 1 if the client sent SessionTicket TLS Extension Returns 2 if the client also sent non-zero length TLS SessionTicket
This commit is contained in:
parent
307ee1e01b
commit
bb2acf589f
@ -13210,6 +13210,17 @@ rep_ssl_hello_type : integer (deprecated)
|
||||
option. This is mostly used in ACL to detect presence of an SSL hello message
|
||||
that is supposed to contain an SSL session ID usable for stickiness.
|
||||
|
||||
req.ssl_st_ext : integer
|
||||
Returns 0 if the client didn't send a SessionTicket TLS Extension (RFC5077)
|
||||
Returns 1 if the client sent SessionTicket TLS Extension
|
||||
Returns 2 if the client also sent non-zero length TLS SessionTicket
|
||||
Note that this only applies to raw contents found in the request buffer and
|
||||
not to contents deciphered via an SSL data layer, so this will not work with
|
||||
"bind" lines having the "ssl" option. This can for example be used to detect
|
||||
whether the client sent a SessionTicket or not and stick it accordingly, if
|
||||
no SessionTicket then stick on SessionID or don't stick as there's no server
|
||||
side state is there when SessionTickets are in use.
|
||||
|
||||
req.ssl_ver : integer
|
||||
req_ssl_ver : integer (deprecated)
|
||||
Returns an integer value containing the version of the SSL/TLS protocol of a
|
||||
|
136
src/payload.c
136
src/payload.c
@ -56,6 +56,141 @@ smp_fetch_len(const struct arg *args, struct sample *smp, const char *kw, void *
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Returns 0 if the client didn't send a SessionTicket Extension
|
||||
* Returns 1 if the client sent SessionTicket Extension
|
||||
* Returns 2 if the client also sent non-zero length SessionTicket
|
||||
* Returns SMP_T_SINT data type
|
||||
*/
|
||||
static int
|
||||
smp_fetch_req_ssl_st_ext(const struct arg *args, struct sample *smp, const char *kw, void *private)
|
||||
{
|
||||
int hs_len, ext_len, bleft;
|
||||
struct channel *chn;
|
||||
unsigned char *data;
|
||||
|
||||
chn = ((smp->opt & SMP_OPT_DIR) == SMP_OPT_DIR_RES) ? &smp->strm->res : &smp->strm->req;
|
||||
if (!chn->buf)
|
||||
goto not_ssl_hello;
|
||||
|
||||
bleft = chn->buf->i;
|
||||
data = (unsigned char *)chn->buf->p;
|
||||
|
||||
/* Check for SSL/TLS Handshake */
|
||||
if (!bleft)
|
||||
goto too_short;
|
||||
if (*data != 0x16)
|
||||
goto not_ssl_hello;
|
||||
|
||||
/* Check for SSLv3 or later (SSL version >= 3.0) in the record layer*/
|
||||
if (bleft < 3)
|
||||
goto too_short;
|
||||
if (data[1] < 0x03)
|
||||
goto not_ssl_hello;
|
||||
|
||||
if (bleft < 5)
|
||||
goto too_short;
|
||||
hs_len = (data[3] << 8) + data[4];
|
||||
if (hs_len < 1 + 3 + 2 + 32 + 1 + 2 + 2 + 1 + 1 + 2 + 2)
|
||||
goto not_ssl_hello; /* too short to have an extension */
|
||||
|
||||
data += 5; /* enter TLS handshake */
|
||||
bleft -= 5;
|
||||
|
||||
/* Check for a complete client hello starting at <data> */
|
||||
if (bleft < 1)
|
||||
goto too_short;
|
||||
if (data[0] != 0x01) /* msg_type = Client Hello */
|
||||
goto not_ssl_hello;
|
||||
|
||||
/* Check the Hello's length */
|
||||
if (bleft < 4)
|
||||
goto too_short;
|
||||
hs_len = (data[1] << 16) + (data[2] << 8) + data[3];
|
||||
if (hs_len < 2 + 32 + 1 + 2 + 2 + 1 + 1 + 2 + 2)
|
||||
goto not_ssl_hello; /* too short to have an extension */
|
||||
|
||||
/* We want the full handshake here */
|
||||
if (bleft < hs_len)
|
||||
goto too_short;
|
||||
|
||||
data += 4;
|
||||
/* Start of the ClientHello message */
|
||||
if (data[0] < 0x03 || data[1] < 0x01) /* TLSv1 minimum */
|
||||
goto not_ssl_hello;
|
||||
|
||||
ext_len = data[34]; /* session_id_len */
|
||||
if (ext_len > 32 || ext_len > (hs_len - 35)) /* check for correct session_id len */
|
||||
goto not_ssl_hello;
|
||||
|
||||
/* Jump to cipher suite */
|
||||
hs_len -= 35 + ext_len;
|
||||
data += 35 + ext_len;
|
||||
|
||||
if (hs_len < 4 || /* minimum one cipher */
|
||||
(ext_len = (data[0] << 8) + data[1]) < 2 || /* minimum 2 bytes for a cipher */
|
||||
ext_len > hs_len)
|
||||
goto not_ssl_hello;
|
||||
|
||||
/* Jump to the compression methods */
|
||||
hs_len -= 2 + ext_len;
|
||||
data += 2 + ext_len;
|
||||
|
||||
if (hs_len < 2 || /* minimum one compression method */
|
||||
data[0] < 1 || data[0] > hs_len) /* minimum 1 bytes for a method */
|
||||
goto not_ssl_hello;
|
||||
|
||||
/* Jump to the extensions */
|
||||
hs_len -= 1 + data[0];
|
||||
data += 1 + data[0];
|
||||
|
||||
if (hs_len < 2 || /* minimum one extension list length */
|
||||
(ext_len = (data[0] << 8) + data[1]) > hs_len - 2) /* list too long */
|
||||
goto not_ssl_hello;
|
||||
|
||||
hs_len = ext_len; /* limit ourselves to the extension length */
|
||||
data += 2;
|
||||
|
||||
while (hs_len >= 4) {
|
||||
int ext_type, ext_len;
|
||||
|
||||
ext_type = (data[0] << 8) + data[1];
|
||||
ext_len = (data[2] << 8) + data[3];
|
||||
|
||||
if (ext_len > hs_len - 4) /* Extension too long */
|
||||
goto not_ssl_hello;
|
||||
|
||||
/* SesstionTicket extension */
|
||||
if (ext_type == 35) {
|
||||
smp->data.type = SMP_T_SINT;
|
||||
/* SessionTicket also present */
|
||||
if (ext_len > 0)
|
||||
smp->data.u.sint = 2;
|
||||
/* SessionTicket absent */
|
||||
else
|
||||
smp->data.u.sint = 1;
|
||||
smp->flags = SMP_F_VOLATILE;
|
||||
return 1;
|
||||
}
|
||||
|
||||
hs_len -= 4 + ext_len;
|
||||
data += 4 + ext_len;
|
||||
}
|
||||
/* SessionTicket Extension not found */
|
||||
smp->data.type = SMP_T_SINT;
|
||||
smp->data.u.sint = 0;
|
||||
smp->flags = SMP_F_VOLATILE;
|
||||
return 1;
|
||||
|
||||
/* server name not found */
|
||||
goto not_ssl_hello;
|
||||
|
||||
too_short:
|
||||
smp->flags = SMP_F_MAY_CHANGE;
|
||||
|
||||
not_ssl_hello:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Returns TRUE if the client sent Supported Elliptic Curves Extension (0x000a)
|
||||
* Mainly used to detect if client supports ECC cipher suites.
|
||||
*/
|
||||
@ -799,6 +934,7 @@ static struct sample_fetch_kw_list smp_kws = {ILH, {
|
||||
{ "req.rdp_cookie", smp_fetch_rdp_cookie, ARG1(0,STR), NULL, SMP_T_STR, SMP_USE_L6REQ },
|
||||
{ "req.rdp_cookie_cnt", smp_fetch_rdp_cookie_cnt, ARG1(0,STR), NULL, SMP_T_SINT, SMP_USE_L6REQ },
|
||||
{ "req.ssl_ec_ext", smp_fetch_req_ssl_ec_ext, 0, NULL, SMP_T_BOOL, SMP_USE_L6REQ },
|
||||
{ "req.ssl_st_ext", smp_fetch_req_ssl_st_ext, 0, NULL, SMP_T_SINT, SMP_USE_L6REQ },
|
||||
{ "req.ssl_hello_type", smp_fetch_ssl_hello_type, 0, NULL, SMP_T_SINT, SMP_USE_L6REQ },
|
||||
{ "req.ssl_sni", smp_fetch_ssl_hello_sni, 0, NULL, SMP_T_STR, SMP_USE_L6REQ },
|
||||
{ "req.ssl_ver", smp_fetch_req_ssl_ver, 0, NULL, SMP_T_SINT, SMP_USE_L6REQ },
|
||||
|
Loading…
Reference in New Issue
Block a user