MINOR: ssl: add ssl_fc_unique_id to fetch TLS Unique ID

The TLS unique id, or unique channel binding, is a byte string that can be
pulled from a TLS connection and it is unique to that connection. It is
defined in RFC 5929 section 3.  The value is used by various upper layer
protocols as part of an extra layer of security.  For example XMPP
(RFC 6120) and EST (RFC 7030).

Add the ssl_fc_unique_id keyword and corresponding sample fetch method.
Value is retrieved from OpenSSL and base64 encoded as described in RFC
5929 section 3.
This commit is contained in:
David S 2014-04-08 18:48:47 -04:00 committed by Willy Tarreau
parent 6a0b6bd648
commit c1ad52e8f7
2 changed files with 56 additions and 0 deletions

View File

@ -10335,6 +10335,11 @@ ssl_fc_protocol : string
ACL derivatives :
ssl_fc_protocol : exact string match
ssl_fc_unique_id : string
When the incoming connection was made over an SSL/TLS transport layer,
returns a base64 encoded string containing the TLS unique ID as defined
in RFC5929 section 3.
ssl_fc_session_id : binary
Returns the SSL ID of the front connection when the incoming connection was
made over an SSL/TLS transport layer. It is useful to stick a given client to

View File

@ -45,6 +45,7 @@
#include <openssl/err.h>
#include <openssl/rand.h>
#include <common/base64.h>
#include <common/buffer.h>
#include <common/compat.h>
#include <common/config.h>
@ -2810,6 +2811,55 @@ smp_fetch_ssl_fc_sni(struct proxy *px, struct session *l4, void *l7, unsigned in
#endif
}
static int
smp_fetch_ssl_fc_unique_id(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
const struct arg *args, struct sample *smp, const char *kw)
{
#if OPENSSL_VERSION_NUMBER > 0x0090800fL
struct connection *conn;
int finished_len;
int b64_len;
struct chunk *finished_trash;
struct chunk *smp_trash;
smp->flags = 0;
if (!l4)
return 0;
conn = objt_conn(l4->si[0].end);
if (!conn || !conn->xprt_ctx || conn->xprt != &ssl_sock)
return 0;
if (!(conn->flags & CO_FL_CONNECTED)) {
smp->flags |= SMP_F_MAY_CHANGE;
return 0;
}
finished_trash = get_trash_chunk();
if (!SSL_session_reused(conn->xprt_ctx))
finished_len = SSL_get_peer_finished(conn->xprt_ctx, finished_trash->str, finished_trash->size);
else
finished_len = SSL_get_finished(conn->xprt_ctx, finished_trash->str, finished_trash->size);
if (!finished_len)
return 0;
smp_trash = get_trash_chunk();
b64_len = a2base64(finished_trash->str, finished_len, smp_trash->str, smp_trash->size);
if (b64_len < 0)
return 0;
smp->data.str.str = smp_trash->str;
smp->type = SMP_T_CSTR;
smp->data.str.len = b64_len;
return 1;
#else
return 0;
#endif
}
/* integer, returns the first verify error in CA chain of client certificate chain. */
static int
smp_fetch_ssl_c_ca_err(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
@ -3536,6 +3586,7 @@ static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
{ "ssl_fc_alpn", smp_fetch_ssl_fc_alpn, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
#endif
{ "ssl_fc_protocol", smp_fetch_ssl_fc_protocol, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
{ "ssl_fc_unique_id", smp_fetch_ssl_fc_unique_id, 0, NULL, SMP_T_CSTR, SMP_USE_L5CLI },
{ "ssl_fc_use_keysize", smp_fetch_ssl_fc_use_keysize, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
{ "ssl_fc_session_id", smp_fetch_ssl_fc_session_id, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
{ "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },