MINOR: ssl: x509_v_err_str converter transforms an integer to a X509_V_ERR name

The x509_v_err_str converter transforms a numerical X509 verify error
to its constant name.
diff --git a/doc/configuration.txt b/doc/configuration.txt
index 5d617d7..cef8e7a 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -18171,6 +18171,26 @@
   collision rate, though care must be taken as the algorithm is not considered
   as cryptographically secure.
 
+x509_v_err_str
+  Convert a numerical value to its corresponding X509_V_ERR constant name. It
+  is useful in ACL in order to have a configuration which works with multiple
+  version of OpenSSL since some codes might change when changing version.
+
+  The list of constant provided by OpenSSL can be found at
+  https://www.openssl.org/docs/manmaster/man3/X509_STORE_CTX_get_error.html#ERROR-CODES
+  Be careful to read the page for the right version of OpenSSL.
+
+  Example:
+
+    bind :443 ssl crt common.pem ca-file ca-auth.crt verify optional crt-ignore-err X509_V_ERR_CERT_REVOKED,X509_V_ERR_CERT_HAS_EXPIRED
+
+    acl cert_expired ssl_c_verify,x509_v_err_str -m str X509_V_ERR_CERT_HAS_EXPIRED
+    acl cert_revoked ssl_c_verify,x509_v_err_str -m str X509_V_ERR_CERT_REVOKED
+    acl cert_ok      ssl_c_verify,x509_v_err_str -m str X509_V_OK
+
+    http-response add-header X-SSL Ok if cert_ok
+    http-response add-header X-SSL Expired if cert_expired
+    http-response add-header X-SSL Revoked if cert_revoked
 
 7.3.2. Fetching samples from internal states
 --------------------------------------------
diff --git a/reg-tests/ssl/ssl_client_auth.vtc b/reg-tests/ssl/ssl_client_auth.vtc
index b8107d4..d806141 100644
--- a/reg-tests/ssl/ssl_client_auth.vtc
+++ b/reg-tests/ssl/ssl_client_auth.vtc
@@ -50,9 +50,9 @@
         # crl-file: revocation list for client auth: the client1 certificate is revoked
         bind "${tmpdir}/ssl.sock" ssl crt ${testdir}/common.pem ca-file ${testdir}/ca-auth.crt verify optional crt-ignore-err X509_V_ERR_CERT_REVOKED,X509_V_ERR_CERT_HAS_EXPIRED crl-file ${testdir}/crl-auth.pem
 
-        acl cert_expired ssl_c_verify 10
-        acl cert_revoked ssl_c_verify 23
-        acl cert_ok ssl_c_verify 0
+        acl cert_expired ssl_c_verify,x509_v_err_str -m str X509_V_ERR_CERT_HAS_EXPIRED
+        acl cert_revoked ssl_c_verify,x509_v_err_str -m str X509_V_ERR_CERT_REVOKED
+        acl cert_ok      ssl_c_verify,x509_v_err_str -m str X509_V_OK
 
         http-response add-header X-SSL Ok if cert_ok
         http-response add-header X-SSL Expired if cert_expired
diff --git a/src/ssl_sample.c b/src/ssl_sample.c
index 35fcec3..7eee065 100644
--- a/src/ssl_sample.c
+++ b/src/ssl_sample.c
@@ -398,6 +398,24 @@
 	return 1;
 }
 
+/* Take a numerical X509_V_ERR and return its constant name */
+static int sample_conv_x509_v_err(const struct arg *arg_p, struct sample *smp, void *private)
+{
+	const char *res = x509_v_err_int_to_str(smp->data.u.sint);
+
+	/* if the value was found return its string */
+	if (res) {
+		smp->data.u.str.area = (char *)res;
+		smp->data.u.str.data = strlen(res);
+		smp->data.type = SMP_T_STR;
+		smp->flags |= SMP_F_CONST;
+
+		return 1;
+	}
+
+	return 0;
+}
+
 static int check_crypto_hmac(struct arg *args, struct sample_conv *conv,
 						  const char *file, int line, char **err)
 {
@@ -2199,6 +2217,7 @@
 #ifdef EVP_CIPH_GCM_MODE
 	{ "aes_gcm_dec",        sample_conv_aes_gcm_dec,      ARG4(4,SINT,STR,STR,STR), check_aes_gcm,           SMP_T_BIN,  SMP_T_BIN  },
 #endif
+	{ "x509_v_err_str",     sample_conv_x509_v_err,       0,                        NULL,                    SMP_T_SINT, SMP_T_STR },
 	{ "digest",             sample_conv_crypto_digest,    ARG1(1,STR),              check_crypto_digest,     SMP_T_BIN,  SMP_T_BIN  },
 	{ "hmac",               sample_conv_crypto_hmac,      ARG2(2,STR,STR),          check_crypto_hmac,       SMP_T_BIN,  SMP_T_BIN  },
 #if defined(HAVE_CRYPTO_memcmp)