MINOR: ssl: add pattern and ACLs fetches 'ssl_c_notbefore', 'ssl_c_notafter', 'ssl_f_notbefore' and 'ssl_f_notafter'

ssl_c_notbefore: start date of client cert (string, eg: "121022182230Z" for YYMMDDhhmmss[Z])
ssl_c_notafter: end date of client cert (string, eg: "121022182230Z" for YYMMDDhhmmss[Z])
ssl_f_notbefore: start date of frontend cert (string, eg: "121022182230Z" for YYMMDDhhmmss[Z])
ssl_f_notafter: end date of frontend cert (string, eg: "121022182230Z" for YYMMDDhhmmss[Z])
This commit is contained in:
Emeric Brun 2012-10-22 14:11:22 +02:00 committed by Willy Tarreau
parent 521a011999
commit ce5ad80c34
2 changed files with 221 additions and 0 deletions

View File

@ -8390,6 +8390,16 @@ ssl_c_key_alg <string>
layer, and the name of the algorithm used to generate the key of the
certificate presented by the client matches the string.
ssl_c_notafter <string>
Returns true when the incoming connection was made over an SSL/TLS transport
layer, and the end date of the certificate presented by the client matches
the string formatted as YYMMDDhhmmss[Z].
ssl_c_notbefore <string>
Returns true when the incoming connection was made over an SSL/TLS transport
layer, and the start date of the certificate presented by the client matches
the string formatted as YYMMDDhhmmss[Z].
ssl_c_s_dn <string>
ssl_c_s_dn(entry[,occ]) <string>
If no entry specified, returns true when the incoming connection was made
@ -8437,6 +8447,16 @@ ssl_c_key_alg <string>
layer, and the name of the algorithm used to generate the key of the
certificate presented by the frontend matches the string.
ssl_f_notafter <string>
Returns true when the incoming connection was made over an SSL/TLS transport
layer, and the end date of the certificate presented by the frontend matches
the string formatted as YYMMDDhhmmss[Z].
ssl_f_notbefore <string>
Returns true when the incoming connection was made over an SSL/TLS transport
layer, and the start date of the certificate presented by the frontend matches
the string formatted as YYMMDDhhmmss[Z].
ssl_f_s_dn <string>
ssl_f_s_dn(entry[,occ]) <string>
If no entry specified, returns true when the incoming connection was made
@ -9157,6 +9177,16 @@ The list of currently supported pattern fetch functions is the following :
the certificate presented by the client when the incoming
connection was made over an SSL/TLS transport layer.
ssl_c_notafter
Returns the end date presented by the client as a formatted
string YYMMDDhhmmss[Z] when the incoming connection was made
over an SSL/TLS transport layer.
ssl_c_notbefore
Returns the start date presented by the client as a formatted
string YYMMDDhhmmss[Z] when the incoming connection was made
over an SSL/TLS transport layer.
ssl_c_s_dn[(entry[,occ])]
If no entry specified, returns the full distinguished name of
the subject of the certificate presented by the client when
@ -9204,6 +9234,16 @@ The list of currently supported pattern fetch functions is the following :
the certificate presented by the frontend when the incoming
connection was made over an SSL/TLS transport layer.
ssl_f_notafter
Returns the end date presented by the frontend as a formatted
string YYMMDDhhmmss[Z] when the incoming connection was made
over an SSL/TLS transport layer.
ssl_f_notbefore
Returns the start date presented by the frontend as a formatted
string YYMMDDhhmmss[Z] when the incoming connection was made
over an SSL/TLS transport layer.
ssl_f_s_dn[(entry[,occ])]
If no entry specified, returns the full distinguished name of
the subject of the certificate presented by the frontend when

View File

@ -1116,6 +1116,46 @@ ssl_sock_get_serial(X509 *crt, struct chunk *out)
return 1;
}
/* Copy Date in ASN1_UTCTIME format in struct chunk out.
* Returns 1 if serial is found and copied, 0 if no valid time found
* and -1 if output is not large enough.
*/
static int
ssl_sock_get_time(ASN1_TIME *tm, struct chunk *out)
{
if (tm->type == V_ASN1_GENERALIZEDTIME) {
ASN1_GENERALIZEDTIME *gentm = (ASN1_GENERALIZEDTIME *)tm;
if (gentm->length < 12)
return 0;
if (gentm->data[0] != 0x32 || gentm->data[1] != 0x30)
return 0;
if (out->size < gentm->length-2)
return -1;
memcpy(out->str, gentm->data+2, gentm->length-2);
out->len = gentm->length-2;
return 1;
}
else if (tm->type == V_ASN1_UTCTIME) {
ASN1_UTCTIME *utctm = (ASN1_UTCTIME *)tm;
if (utctm->length < 10)
return 0;
if (utctm->data[0] >= 0x35)
return 0;
if (out->size < utctm->length)
return -1;
memcpy(out->str, utctm->data, utctm->length);
out->len = utctm->length;
return 1;
}
return 0;
}
/* Extract an entry from a X509_NAME and copy its value to an output chunk.
* Returns 1 if entry found, 0 if entry not found, or -1 if output not large enough.
*/
@ -1265,6 +1305,41 @@ out:
return ret;
}
/*str, returns notafter date in ASN1_UTCTIME format */
static int
smp_fetch_ssl_c_notafter(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
const struct arg *args, struct sample *smp)
{
X509 *crt = NULL;
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 = sample_get_trash_chunk();
if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
goto out;
smp->data.str = *smp_trash;
smp->type = SMP_T_STR;
ret = 1;
out:
if (crt)
X509_free(crt);
return ret;
}
/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
static int
smp_fetch_ssl_c_i_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
@ -1316,6 +1391,41 @@ out:
return ret;
}
/*str, returns notbefore date in ASN1_UTCTIME format */
static int
smp_fetch_ssl_c_notbefore(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
const struct arg *args, struct sample *smp)
{
X509 *crt = NULL;
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 = sample_get_trash_chunk();
if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
goto out;
smp->data.str = *smp_trash;
smp->type = SMP_T_STR;
ret = 1;
out:
if (crt)
X509_free(crt);
return ret;
}
/* str, returns a string of a formatted full dn \C=..\O=..\OU=.. \CN=.. */
static int
smp_fetch_ssl_c_s_dn(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
@ -1518,6 +1628,69 @@ smp_fetch_ssl_f_serial(struct proxy *px, struct session *l4, void *l7, unsigned
out:
return ret;
}
/*str, returns notafter date in ASN1_UTCTIME format */
static int
smp_fetch_ssl_f_notafter(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
const struct arg *args, struct sample *smp)
{
X509 *crt = NULL;
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;
}
crt = SSL_get_certificate(l4->si[0].conn.xprt_ctx);
if (!crt)
goto out;
smp_trash = sample_get_trash_chunk();
if (ssl_sock_get_time(X509_get_notAfter(crt), smp_trash) <= 0)
goto out;
smp->data.str = *smp_trash;
smp->type = SMP_T_STR;
ret = 1;
out:
return ret;
}
/*str, returns notbefore date in ASN1_UTCTIME format */
static int
smp_fetch_ssl_f_notbefore(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
const struct arg *args, struct sample *smp)
{
X509 *crt = NULL;
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;
}
crt = SSL_get_certificate(l4->si[0].conn.xprt_ctx);
if (!crt)
goto out;
smp_trash = sample_get_trash_chunk();
if (ssl_sock_get_time(X509_get_notBefore(crt), smp_trash) <= 0)
goto out;
smp->data.str = *smp_trash;
smp->type = SMP_T_STR;
ret = 1;
out:
return ret;
}
/* integer, returns the frontend certificate version */
static int
@ -2421,6 +2594,8 @@ static struct sample_fetch_kw_list sample_fetch_keywords = {{ },{
{ "ssl_c_err", smp_fetch_ssl_c_err, 0, NULL, SMP_T_UINT, SMP_CAP_REQ|SMP_CAP_RES },
{ "ssl_c_i_dn", smp_fetch_ssl_c_i_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_CAP_REQ|SMP_CAP_RES },
{ "ssl_c_key_alg", smp_fetch_ssl_c_key_alg, 0, NULL, SMP_T_STR, SMP_CAP_REQ|SMP_CAP_RES },
{ "ssl_c_notafter", smp_fetch_ssl_c_notafter, 0, NULL, SMP_T_STR, SMP_CAP_REQ|SMP_CAP_RES },
{ "ssl_c_notbefore", smp_fetch_ssl_c_notbefore, 0, NULL, SMP_T_STR, SMP_CAP_REQ|SMP_CAP_RES },
{ "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 },
@ -2428,6 +2603,8 @@ static struct sample_fetch_kw_list sample_fetch_keywords = {{ },{
{ "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 },
{ "ssl_f_key_alg", smp_fetch_ssl_f_key_alg, 0, NULL, SMP_T_STR, SMP_CAP_REQ|SMP_CAP_RES },
{ "ssl_f_notafter", smp_fetch_ssl_f_notafter, 0, NULL, SMP_T_STR, SMP_CAP_REQ|SMP_CAP_RES },
{ "ssl_f_notbefore", smp_fetch_ssl_f_notbefore, 0, NULL, SMP_T_STR, SMP_CAP_REQ|SMP_CAP_RES },
{ "ssl_f_sig_alg", smp_fetch_ssl_f_sig_alg, 0, NULL, SMP_T_STR, SMP_CAP_REQ|SMP_CAP_RES },
{ "ssl_f_s_dn", smp_fetch_ssl_f_s_dn, ARG2(0,STR,SINT), NULL, SMP_T_STR, SMP_CAP_REQ|SMP_CAP_RES },
{ "ssl_f_serial", smp_fetch_ssl_f_serial, 0, NULL, SMP_T_BIN, SMP_CAP_REQ|SMP_CAP_RES },
@ -2456,6 +2633,8 @@ static struct acl_kw_list acl_kws = {{ },{
{ "ssl_c_err", acl_parse_int, smp_fetch_ssl_c_err, acl_match_int, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
{ "ssl_c_i_dn", acl_parse_str, smp_fetch_ssl_c_i_dn, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, ARG2(0,STR,SINT) },
{ "ssl_c_key_alg", acl_parse_str, smp_fetch_ssl_c_key_alg, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
{ "ssl_c_notafter", acl_parse_str, smp_fetch_ssl_c_notafter, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
{ "ssl_c_notbefore", acl_parse_str, smp_fetch_ssl_c_notbefore, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
{ "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 },
@ -2463,6 +2642,8 @@ static struct acl_kw_list acl_kws = {{ },{
{ "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) },
{ "ssl_f_key_alg", acl_parse_str, smp_fetch_ssl_f_key_alg, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
{ "ssl_f_notafter", acl_parse_str, smp_fetch_ssl_f_notafter, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
{ "ssl_f_notbefore", acl_parse_str, smp_fetch_ssl_f_notbefore, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
{ "ssl_f_sig_alg", acl_parse_str, smp_fetch_ssl_f_sig_alg, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
{ "ssl_f_s_dn", acl_parse_str, smp_fetch_ssl_f_s_dn, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, ARG2(0,STR,SINT) },
{ "ssl_f_serial", acl_parse_bin, smp_fetch_ssl_f_serial, acl_match_bin, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },