MINOR: ssl: add fetches and ACLs to return verify errors
Add fetch 'ssl_verify_caerr':
returns the first ssl verify error at depth > 0 (CA chain).
Add fetch 'ssl_verify_caerr_depth':
returns the first ssl verify error depth (max returns is 15 if depth > 15).
Add fetch 'ssl_verify_crterr':
returns the fist ssl verify error at depth == 0.
diff --git a/src/ssl_sock.c b/src/ssl_sock.c
index d06230f..18496d5 100644
--- a/src/ssl_sock.c
+++ b/src/ssl_sock.c
@@ -71,6 +71,16 @@
#include <proto/task.h>
#define SSL_SOCK_ST_FL_VERIFY_DONE 0x00000001
+/* bits 0xFFFF0000 are reserved to store verify errors */
+
+/* Verify errors macros */
+#define SSL_SOCK_CA_ERROR_TO_ST(e) (((e > 63) ? 63 : e) << (16))
+#define SSL_SOCK_CAEDEPTH_TO_ST(d) (((d > 15) ? 15 : d) << (6+16))
+#define SSL_SOCK_CRTERROR_TO_ST(e) (((e > 63) ? 63 : e) << (4+6+16))
+
+#define SSL_SOCK_ST_TO_CA_ERROR(s) ((s >> (16)) & 63)
+#define SSL_SOCK_ST_TO_CAEDEPTH(s) ((s >> (6+16)) & 15)
+#define SSL_SOCK_ST_TO_CRTERROR(s) ((s >> (4+6+16)) & 63)
static int sslconns = 0;
@@ -108,12 +118,20 @@
/* check if CA error needs to be ignored */
if (depth > 0) {
+ if (!SSL_SOCK_ST_TO_CA_ERROR(conn->data_st)) {
+ conn->data_st |= SSL_SOCK_CA_ERROR_TO_ST(err);
+ conn->data_st |= SSL_SOCK_CAEDEPTH_TO_ST(depth);
+ }
+
if (target_client(&conn->target)->bind_conf->ca_ignerr & (1ULL << err))
return 1;
return 0;
}
+ if (!SSL_SOCK_ST_TO_CRTERROR(conn->data_st))
+ conn->data_st |= SSL_SOCK_CRTERROR_TO_ST(err);
+
/* check if certificate error needs to be ignored */
if (target_client(&conn->target)->bind_conf->crt_ignerr & (1ULL << err))
return 1;
@@ -967,6 +985,66 @@
#endif
}
+/* integer, returns the first verify error ID in CA */
+static int
+smp_fetch_verify_caerr(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
+ const struct arg *args, struct sample *smp)
+{
+ if (!l4 || l4->si[0].conn.data != &ssl_sock)
+ return 0;
+
+ if (!(l4->si[0].conn.flags & CO_FL_CONNECTED)) {
+ smp->flags = SMP_F_MAY_CHANGE;
+ return 0;
+ }
+
+ smp->type = SMP_T_UINT;
+ smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CA_ERROR(l4->si[0].conn.data_st);
+ smp->flags = 0;
+
+ return 1;
+}
+
+/* integer, returns the depth of the first verify error in CA */
+static int
+smp_fetch_verify_caerr_depth(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
+ const struct arg *args, struct sample *smp)
+{
+ if (!l4 || l4->si[0].conn.data != &ssl_sock)
+ return 0;
+
+ if (!(l4->si[0].conn.flags & CO_FL_CONNECTED)) {
+ smp->flags = SMP_F_MAY_CHANGE;
+ return 0;
+ }
+
+ smp->type = SMP_T_UINT;
+ smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CAEDEPTH(l4->si[0].conn.data_st);
+ smp->flags = 0;
+
+ return 1;
+}
+
+/* integer, returns the depth of the first verify error in CA */
+static int
+smp_fetch_verify_crterr(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
+ const struct arg *args, struct sample *smp)
+{
+ if (!l4 || l4->si[0].conn.data != &ssl_sock)
+ return 0;
+
+ if (!(l4->si[0].conn.flags & CO_FL_CONNECTED)) {
+ smp->flags = SMP_F_MAY_CHANGE;
+ return 0;
+ }
+
+ smp->type = SMP_T_UINT;
+ smp->data.uint = (unsigned int)SSL_SOCK_ST_TO_CRTERROR(l4->si[0].conn.data_st);
+ smp->flags = 0;
+
+ return 1;
+}
+
/* integer, returns the verify result */
static int
smp_fetch_verify_result(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
@@ -1166,11 +1244,14 @@
* Please take care of keeping this list alphabetically sorted.
*/
static struct sample_fetch_kw_list sample_fetch_keywords = {{ },{
- { "client_crt", smp_fetch_client_crt, 0, NULL, SMP_T_BOOL, SMP_CAP_REQ|SMP_CAP_RES },
- { "is_ssl", smp_fetch_is_ssl, 0, NULL, SMP_T_BOOL, SMP_CAP_REQ|SMP_CAP_RES },
- { "ssl_has_sni", smp_fetch_has_sni, 0, NULL, SMP_T_BOOL, SMP_CAP_REQ|SMP_CAP_RES },
- { "ssl_sni", smp_fetch_ssl_sni, 0, NULL, SMP_T_CSTR, SMP_CAP_REQ|SMP_CAP_RES },
- { "ssl_verify_result", smp_fetch_verify_result, 0, NULL, SMP_T_UINT, SMP_CAP_REQ|SMP_CAP_RES },
+ { "client_crt", smp_fetch_client_crt, 0, NULL, SMP_T_BOOL, SMP_CAP_REQ|SMP_CAP_RES },
+ { "is_ssl", smp_fetch_is_ssl, 0, NULL, SMP_T_BOOL, SMP_CAP_REQ|SMP_CAP_RES },
+ { "ssl_has_sni", smp_fetch_has_sni, 0, NULL, SMP_T_BOOL, SMP_CAP_REQ|SMP_CAP_RES },
+ { "ssl_sni", smp_fetch_ssl_sni, 0, NULL, SMP_T_CSTR, SMP_CAP_REQ|SMP_CAP_RES },
+ { "ssl_verify_caerr", smp_fetch_verify_caerr, 0, NULL, SMP_T_UINT, SMP_CAP_REQ|SMP_CAP_RES },
+ { "ssl_verify_caerr_depth", smp_fetch_verify_caerr_depth, 0, NULL, SMP_T_UINT, SMP_CAP_REQ|SMP_CAP_RES },
+ { "ssl_verify_crterr", smp_fetch_verify_crterr, 0, NULL, SMP_T_UINT, SMP_CAP_REQ|SMP_CAP_RES },
+ { "ssl_verify_result", smp_fetch_verify_result, 0, NULL, SMP_T_UINT, SMP_CAP_REQ|SMP_CAP_RES },
{ NULL, NULL, 0, 0, 0 },
}};
@@ -1178,13 +1259,16 @@
* Please take care of keeping this list alphabetically sorted.
*/
static struct acl_kw_list acl_kws = {{ },{
- { "client_crt", acl_parse_int, smp_fetch_client_crt, acl_match_nothing, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
- { "is_ssl", acl_parse_int, smp_fetch_is_ssl, acl_match_nothing, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
- { "ssl_has_sni", acl_parse_int, smp_fetch_has_sni, acl_match_nothing, ACL_USE_L6REQ_PERMANENT, 0 },
- { "ssl_sni", acl_parse_str, smp_fetch_ssl_sni, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
- { "ssl_sni_end", acl_parse_str, smp_fetch_ssl_sni, acl_match_end, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
- { "ssl_sni_reg", acl_parse_str, smp_fetch_ssl_sni, acl_match_reg, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
- { "ssl_verify_result", acl_parse_int, smp_fetch_verify_result, acl_match_int, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
+ { "client_crt", acl_parse_int, smp_fetch_client_crt, acl_match_nothing, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
+ { "is_ssl", acl_parse_int, smp_fetch_is_ssl, acl_match_nothing, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
+ { "ssl_has_sni", acl_parse_int, smp_fetch_has_sni, acl_match_nothing, ACL_USE_L6REQ_PERMANENT, 0 },
+ { "ssl_sni", acl_parse_str, smp_fetch_ssl_sni, acl_match_str, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
+ { "ssl_sni_end", acl_parse_str, smp_fetch_ssl_sni, acl_match_end, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
+ { "ssl_sni_reg", acl_parse_str, smp_fetch_ssl_sni, acl_match_reg, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
+ { "ssl_verify_caerr", acl_parse_int, smp_fetch_verify_caerr, acl_match_int, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
+ { "ssl_verify_caerr_depth", acl_parse_int, smp_fetch_verify_caerr_depth, acl_match_int, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
+ { "ssl_verify_crterr", acl_parse_int, smp_fetch_verify_crterr, acl_match_int, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
+ { "ssl_verify_result", acl_parse_int, smp_fetch_verify_result, acl_match_int, ACL_USE_L6REQ_PERMANENT|ACL_MAY_LOOKUP, 0 },
{ NULL, NULL, NULL, NULL },
}};