From 9143d374e84687dc2fa1afceeb6609d2e3d79c90 Mon Sep 17 00:00:00 2001 From: Emeric Brun Date: Thu, 20 Dec 2012 15:44:16 +0100 Subject: [PATCH] MINOR: ssl: add fetch and acl "ssl_c_used" to check if current SSL session uses a client certificate. --- doc/configuration.txt | 17 +++++++++++++++++ src/ssl_sock.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/doc/configuration.txt b/doc/configuration.txt index d70c9d8f3..f7aa1a362 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -8641,6 +8641,10 @@ ssl_c_sig_alg layer, and the name of the algorithm used to sign the certificate presented by the client matches the string. +ssl_c_used + Returns true if current SSL session uses a client certificate even if current + connection uses SSL session resumption. See also "ssl_fc_has_crt". + ssl_c_verify Returns true when the incoming connection was made over an SSL/TLS transport layer, and the verify result matches the specified value (check man verify @@ -8719,6 +8723,10 @@ ssl_fc_cipher ssl_fc_has_crt Returns true if a client certificate is present in an incoming connection over SSL/TLS transport layer. Useful if 'verify' statement is set to 'optional'. + Note: on SSL session resumption with Session ID or TLS ticket, client + certificate is not present in the current connection but may be retrieved + from the cache or the ticket. So prefer "ssl_c_used" if you want to check if + current SSL session uses a client certificate. ssl_fc_has_sni This is used to check for presence of a Server Name Indication TLS extension @@ -9439,6 +9447,10 @@ The list of currently supported pattern fetch functions is the following : presented by the client when the incoming connection was made over an SSL/TLS transport layer. + ssl_c_used + Returns 1 if current SSL session use a client certificate, + otherwise 0. See also "ssl_fc_has_crt". + ssl_c_verify Returns the verify result errorID when the incoming connection was made over an SSL/TLS transport layer, otherwise zero if no error is encountered. @@ -9516,6 +9528,11 @@ The list of currently supported pattern fetch functions is the following : ssl_fc_has_crt Returns 1 if a client certificate is present in the front connection over SSL/TLS transport layer, otherwise 0. + Note: on SSL session resumption with Session ID or TLS ticket, + client certificate is not present in the current connection but + may be retrieved from the cache or the ticket. So prefer + "ssl_c_used" if you want to check if current SSL session uses + a client certificate. ssl_fc_has_sni This checks the transport layer used by the front connection, and diff --git a/src/ssl_sock.c b/src/ssl_sock.c index 3e74ce546..0c0876905 100644 --- a/src/ssl_sock.c +++ b/src/ssl_sock.c @@ -1630,6 +1630,33 @@ out: X509_free(crt); return ret; } + +/* integer, returns true if current session use a client certificate */ +static int +smp_fetch_ssl_c_used(struct proxy *px, struct session *l4, void *l7, unsigned int opt, + const struct arg *args, struct sample *smp) +{ + X509 *crt; + + 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 returns a ptr on allocated X509 struct */ + crt = SSL_get_peer_certificate(l4->si[0].conn->xprt_ctx); + if (crt) { + X509_free(crt); + } + + smp->type = SMP_T_BOOL; + smp->data.uint = (crt != NULL); + return 1; +} + /* integer, returns the client certificate version */ static int smp_fetch_ssl_c_version(struct proxy *px, struct session *l4, void *l7, unsigned int opt, @@ -2769,6 +2796,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_CAP_REQ|SMP_CAP_RES }, { "ssl_c_s_dn", smp_fetch_ssl_c_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_CAP_REQ|SMP_CAP_RES }, { "ssl_c_serial", smp_fetch_ssl_c_serial, 0, NULL, SMP_T_BIN, SMP_CAP_REQ|SMP_CAP_RES }, + { "ssl_c_used", smp_fetch_ssl_c_used, 0, NULL, SMP_T_BOOL, SMP_CAP_REQ|SMP_CAP_RES }, { "ssl_c_verify", smp_fetch_ssl_c_verify, 0, NULL, SMP_T_UINT, SMP_CAP_REQ|SMP_CAP_RES }, { "ssl_c_version", smp_fetch_ssl_c_version, 0, NULL, SMP_T_UINT, SMP_CAP_REQ|SMP_CAP_RES }, { "ssl_f_i_dn", smp_fetch_ssl_f_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_CAP_REQ|SMP_CAP_RES }, @@ -2808,6 +2836,7 @@ static struct acl_kw_list acl_kws = {{ },{ { "ssl_c_sig_alg", acl_parse_str, smp_fetch_ssl_c_sig_alg, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 }, { "ssl_c_s_dn", acl_parse_str, smp_fetch_ssl_c_s_dn, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, ARG2(0,STR,SINT) }, { "ssl_c_serial", acl_parse_bin, smp_fetch_ssl_c_serial, acl_match_bin, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 }, + { "ssl_c_used", acl_parse_int, smp_fetch_ssl_c_used, acl_match_nothing, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 }, { "ssl_c_verify", acl_parse_int, smp_fetch_ssl_c_verify, acl_match_int, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 }, { "ssl_c_version", acl_parse_int, smp_fetch_ssl_c_version, acl_match_int, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 }, { "ssl_f_i_dn", acl_parse_str, smp_fetch_ssl_f_i_dn, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, ARG2(0,STR,SINT) },