MINOR: ssl: add pattern fetch 'ssl_c_sha1'

This new pattern fetch returns the client certificate's SHA-1 fingerprint
(i.e. SHA-1 hash of DER-encoded certificate) in a binary chunk.

This can be useful to pass it to a server in a header or to stick a client
to a server across multiple SSL connections.
This commit is contained in:
James Voth 2013-05-14 20:37:59 +02:00 committed by Willy Tarreau
parent 06da4df056
commit a051b4aa3a
2 changed files with 42 additions and 0 deletions

View File

@ -10442,6 +10442,11 @@ The list of currently supported pattern fetch functions is the following :
when the incoming connection was made over an SSL/TLS transport when the incoming connection was made over an SSL/TLS transport
layer. layer.
ssl_c_sha1 Returns the SHA-1 fingerprint of the certificate presented by
the client when the incoming connection was made over an SSL/TLS
transport layer. This can be used to stick a client to a server,
or to pass this information to a server.
ssl_c_sig_alg ssl_c_sig_alg
Returns the name of the algorithm used to sign the certificate Returns the name of the algorithm used to sign the certificate
presented by the client when the incoming connection was made presented by the client when the incoming connection was made

View File

@ -1628,6 +1628,42 @@ smp_fetch_ssl_c_serial(struct proxy *px, struct session *l4, void *l7, unsigned
return ret; return ret;
} }
/* bin, returns the client certificate's SHA-1 fingerprint (SHA-1 hash of DER-encoded certificate) in a binary chunk */
static int
smp_fetch_ssl_c_sha1(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
const struct arg *args, struct sample *smp)
{
X509 *crt = NULL;
const EVP_MD *digest;
int ret = 0;
struct chunk *smp_trash;
if (!l4 || l4->si[0].conn->xprt != &ssl_sock)
return 0;
if (!(l4->si[0].conn->flags & CO_FL_CONNECTED)) {
smp->flags |= SMP_F_MAY_CHANGE;
return 0;
}
/* SSL_get_peer_certificate, it increase X509 * ref count */
crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx);
if (!crt)
goto out;
smp_trash = get_trash_chunk();
digest = EVP_sha1();
X509_digest(crt, digest, (unsigned char *)smp_trash->str, (unsigned int *)&smp_trash->len);
smp->data.str = *smp_trash;
smp->type = SMP_T_BIN;
ret = 1;
out:
if (crt)
X509_free(crt);
return ret;
}
/*str, returns notafter date in ASN1_UTCTIME format */ /*str, returns notafter date in ASN1_UTCTIME format */
static int static int
smp_fetch_ssl_c_notafter(struct proxy *px, struct session *l4, void *l7, unsigned int opt, smp_fetch_ssl_c_notafter(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
@ -3058,6 +3094,7 @@ static struct sample_fetch_kw_list sample_fetch_keywords = {{ },{
{ "ssl_c_sig_alg", smp_fetch_ssl_c_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI }, { "ssl_c_sig_alg", smp_fetch_ssl_c_sig_alg, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
{ "ssl_c_s_dn", smp_fetch_ssl_c_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI }, { "ssl_c_s_dn", smp_fetch_ssl_c_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_USE_L5CLI },
{ "ssl_c_serial", smp_fetch_ssl_c_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI }, { "ssl_c_serial", smp_fetch_ssl_c_serial, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
{ "ssl_c_sha1", smp_fetch_ssl_c_sha1, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
{ "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI }, { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_USE_L5CLI },
{ "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI }, { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },
{ "ssl_c_version", smp_fetch_ssl_c_version, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI }, { "ssl_c_version", smp_fetch_ssl_c_version, 0, NULL, SMP_T_UINT, SMP_USE_L5CLI },