MINOR: ssl: add the ssl_s_* sample fetches for server side certificate

This commit adds some sample fetches that were lacking on the server
side:

ssl_s_key_alg, ssl_s_notafter, ssl_s_notbefore, ssl_s_sig_alg,
ssl_s_i_dn, ssl_s_s_dn, ssl_s_serial, ssl_s_sha1, ssl_s_der,
ssl_s_version
diff --git a/doc/configuration.txt b/doc/configuration.txt
index 780d27f..6612d3d 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -17077,6 +17077,74 @@
   Returns the symmetric cipher key size used in bits when the incoming
   connection was made over an SSL/TLS transport layer.
 
+ssl_s_der : binary
+  Returns the DER formatted certificate presented by the server when the
+  outgoing connection was made over an SSL/TLS transport layer. When used for
+  an ACL, the value(s) to match against can be passed in hexadecimal form.
+
+ssl_s_key_alg : string
+  Returns the name of the algorithm used to generate the key of the certificate
+  presented by the server when the outgoing connection was made over an
+  SSL/TLS transport layer.
+
+ssl_s_notafter : string
+  Returns the end date presented by the server as a formatted string
+  YYMMDDhhmmss[Z] when the outgoing connection was made over an SSL/TLS
+  transport layer.
+
+ssl_s_notbefore : string
+  Returns the start date presented by the server as a formatted string
+  YYMMDDhhmmss[Z] when the outgoing connection was made over an SSL/TLS
+  transport layer.
+
+ssl_s_i_dn([<entry>[,<occ>[,<format>]]]) : string
+  When the outgoing connection was made over an SSL/TLS transport layer,
+  returns the full distinguished name of the issuer of the certificate
+  presented by the server when no <entry> is specified, or the value of the
+  first given entry found from the beginning of the DN. If a positive/negative
+  occurrence number is specified as the optional second argument, it returns
+  the value of the nth given entry value from the beginning/end of the DN.
+  For instance, "ssl_f_i_dn(OU,2)" the second organization unit, and
+  "ssl_f_i_dn(CN)" retrieves the common name.
+  The <format> parameter allows you to receive the DN suitable for
+  consumption by different protocols. Currently supported is rfc2253 for
+  LDAP v3.
+  If you'd like to modify the format only you can specify an empty string
+  and zero for the first two parameters. Example: ssl_s_i_dn(,0,rfc2253)
+
+ssl_s_s_dn([<entry>[,<occ>[,<format>]]]) : string
+  When the outgoing connection was made over an SSL/TLS transport layer,
+  returns the full distinguished name of the subject of the certificate
+  presented by the server when no <entry> is specified, or the value of the
+  first given entry found from the beginning of the DN. If a positive/negative
+  occurrence number is specified as the optional second argument, it returns
+  the value of the nth given entry value from the beginning/end of the DN.
+  For instance, "ssl_f_s_dn(OU,2)" the second organization unit, and
+  "ssl_f_s_dn(CN)" retrieves the common name.
+  The <format> parameter allows you to receive the DN suitable for
+  consumption by different protocols. Currently supported is rfc2253 for
+  LDAP v3.
+  If you'd like to modify the format only you can specify an empty string
+  and zero for the first two parameters. Example: ssl_s_s_dn(,0,rfc2253)
+
+ssl_s_serial : binary
+  Returns the serial of the certificate presented by the server when the
+  outgoing connection was made over an SSL/TLS transport layer. When used for
+  an ACL, the value(s) to match against can be passed in hexadecimal form.
+
+ssl_s_sha1 : binary
+  Returns the SHA-1 fingerprint of the certificate presented by the server
+  when the outgoing connection was made over an SSL/TLS transport layer. This
+  can be used to know which certificate was chosen using SNI.
+
+ssl_s_sig_alg : string
+  Returns the name of the algorithm used to sign the certificate presented by
+  the server when the outgoing connection was made over an SSL/TLS transport
+  layer.
+
+ssl_s_version : integer
+  Returns the version of the certificate presented by the server when the
+  outgoing connection was made over an SSL/TLS transport layer.
 
 7.3.5. Fetching samples from buffer contents (Layer 6)
 ------------------------------------------------------
diff --git a/reg-tests/ssl/ssl_server_samples.vtc b/reg-tests/ssl/ssl_server_samples.vtc
new file mode 100644
index 0000000..0ee2998
--- /dev/null
+++ b/reg-tests/ssl/ssl_server_samples.vtc
@@ -0,0 +1,73 @@
+#REGTEST_TYPE=devel
+
+varnishtest "Test the ssl_s_* sample fetches"
+#REQUIRE_VERSION=2.2
+#REQUIRE_OPTIONS=OPENSSL
+feature ignore_unknown_macro
+
+server s1 -repeat 3 {
+    rxreq
+    txresp
+} -start
+
+haproxy h1 -conf {
+    global
+        tune.ssl.default-dh-param 2048
+        tune.ssl.capture-cipherlist-size 1
+        crt-base ${testdir}
+        stats socket "${tmpdir}/h1/stats" level admin
+
+    defaults
+        mode http
+        option httplog
+        ${no-htx} option http-use-htx
+        log stderr local0 debug err
+        option logasap
+        timeout connect 1s
+        timeout client  1s
+        timeout server  1s
+
+
+    listen clear-lst
+        bind "fd@${clearlst}"
+        balance roundrobin
+        http-response add-header x-ssl-sha1 %[ssl_s_sha1,hex]
+        http-response add-header x-ssl-notafter %[ssl_s_notafter]
+        http-response add-header x-ssl-notbefore %[ssl_s_notbefore]
+        http-response add-header x-ssl-sig_alg %[ssl_s_sig_alg]
+        http-response add-header x-ssl-i_dn %[ssl_s_i_dn]
+        http-response add-header x-ssl-s_dn %[ssl_s_s_dn]
+        http-response add-header x-ssl-s_serial %[ssl_s_serial,hex]
+        http-response add-header x-ssl-key_alg %[ssl_s_key_alg]
+        http-response add-header x-ssl-der %[ssl_s_der,hex]
+        http-response add-header x-ssl-version %[ssl_s_version]
+
+        server s1 "${tmpdir}/ssl.sock" ssl verify none sni str(www.test1.com)
+
+    listen ssl-lst
+        mode http
+        ${no-htx} option http-use-htx
+
+        bind "${tmpdir}/ssl.sock" ssl strict-sni crt-list ${testdir}/localhost.crt-list
+
+        server s1 ${s1_addr}:${s1_port}
+} -start
+
+
+client c1 -connect ${h1_clearlst_sock} {
+    txreq
+    rxresp
+    expect resp.status == 200
+    expect resp.http.x-ssl-sha1 == "2195C9F0FD58470313013FC27C1B9CF9864BD1C6"
+    expect resp.http.x-ssl-notafter == "180116230238Z"
+    expect resp.http.x-ssl-notbefore == "160117230238Z"
+    expect resp.http.x-ssl-sig_alg == "RSA-SHA256"
+    expect resp.http.x-ssl-i_dn == "/C=FR/ST=Ile-de-France/L=Paris/O=ozon.io/CN=Ozon Test CA/emailAddress=support@ozon.io"
+    expect resp.http.x-ssl-s_dn  == "/C=FR/ST=Ile-de-France/L=Neuilly-sur-Seine/O=TOAD Consulting/OU=eParapher Team/CN=www.test1.com/emailAddress=arnault.michel@toad-consulting.fr"
+    expect resp.http.x-ssl-s_serial == "02"
+    expect resp.http.x-ssl-key_alg == "rsaEncryption"
+    expect resp.http.x-ssl-version == "3"
+    expect resp.http.x-ssl-der ~ 3082067930820461A0030201020201.*
+} -run
+
+
diff --git a/src/ssl_sample.c b/src/ssl_sample.c
index cc6f537..4c7eccc 100644
--- a/src/ssl_sample.c
+++ b/src/ssl_sample.c
@@ -91,14 +91,20 @@
 static int
 smp_fetch_ssl_x_der(const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
-	int cert_peer = (kw[4] == 'c') ? 1 : 0;
+	int cert_peer = (kw[4] == 'c' || kw[4] == 's') ? 1 : 0;
+	int conn_server = (kw[4] == 's') ? 1 : 0;
+
 	X509 *crt = NULL;
 	int ret = 0;
 	struct buffer *smp_trash;
 	struct connection *conn;
 	SSL *ssl;
 
-	conn = objt_conn(smp->sess->origin);
+	if (conn_server)
+		conn = cs_conn(objt_cs(smp->strm->si[1].end));
+	else
+		conn = objt_conn(smp->sess->origin);
+
 	ssl = ssl_sock_get_ssl_object(conn);
 	if (!ssl)
 		return 0;
@@ -137,14 +143,18 @@
 static int
 smp_fetch_ssl_x_serial(const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
-	int cert_peer = (kw[4] == 'c') ? 1 : 0;
+	int cert_peer = (kw[4] == 'c' || kw[4] == 's') ? 1 : 0;
+	int conn_server = (kw[4] == 's') ? 1 : 0;
 	X509 *crt = NULL;
 	int ret = 0;
 	struct buffer *smp_trash;
 	struct connection *conn;
 	SSL *ssl;
 
-	conn = objt_conn(smp->sess->origin);
+	if (conn_server)
+		conn = cs_conn(objt_cs(smp->strm->si[1].end));
+	else
+		conn = objt_conn(smp->sess->origin);
 	ssl = ssl_sock_get_ssl_object(conn);
 	if (!ssl)
 		return 0;
@@ -183,7 +193,8 @@
 static int
 smp_fetch_ssl_x_sha1(const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
-	int cert_peer = (kw[4] == 'c') ? 1 : 0;
+	int cert_peer = (kw[4] == 'c' || kw[4] == 's') ? 1 : 0;
+	int conn_server = (kw[4] == 's') ? 1 : 0;
 	X509 *crt = NULL;
 	const EVP_MD *digest;
 	int ret = 0;
@@ -192,7 +203,11 @@
 	struct connection *conn;
 	SSL *ssl;
 
-	conn = objt_conn(smp->sess->origin);
+	if (conn_server)
+		conn = cs_conn(objt_cs(smp->strm->si[1].end));
+	else
+		conn = objt_conn(smp->sess->origin);
+
 	ssl = ssl_sock_get_ssl_object(conn);
 	if (!ssl)
 		return 0;
@@ -230,14 +245,19 @@
 static int
 smp_fetch_ssl_x_notafter(const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
-	int cert_peer = (kw[4] == 'c') ? 1 : 0;
+	int cert_peer = (kw[4] == 'c' || kw[4] == 's') ? 1 : 0;
+	int conn_server = (kw[4] == 's') ? 1 : 0;
 	X509 *crt = NULL;
 	int ret = 0;
 	struct buffer *smp_trash;
 	struct connection *conn;
 	SSL *ssl;
 
-	conn = objt_conn(smp->sess->origin);
+	if (conn_server)
+		conn = cs_conn(objt_cs(smp->strm->si[1].end));
+	else
+		conn = objt_conn(smp->sess->origin);
+
 	ssl = ssl_sock_get_ssl_object(conn);
 	if (!ssl)
 		return 0;
@@ -275,7 +295,8 @@
 static int
 smp_fetch_ssl_x_i_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
-	int cert_peer = (kw[4] == 'c') ? 1 : 0;
+	int cert_peer = (kw[4] == 'c' || kw[4] == 's') ? 1 : 0;
+	int conn_server = (kw[4] == 's') ? 1 : 0;
 	X509 *crt = NULL;
 	X509_NAME *name;
 	int ret = 0;
@@ -283,7 +304,11 @@
 	struct connection *conn;
 	SSL *ssl;
 
-	conn = objt_conn(smp->sess->origin);
+	if (conn_server)
+		conn = cs_conn(objt_cs(smp->strm->si[1].end));
+	else
+		conn = objt_conn(smp->sess->origin);
+
 	ssl = ssl_sock_get_ssl_object(conn);
 	if (!ssl)
 		return 0;
@@ -338,14 +363,19 @@
 static int
 smp_fetch_ssl_x_notbefore(const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
-	int cert_peer = (kw[4] == 'c') ? 1 : 0;
+	int cert_peer = (kw[4] == 'c' || kw[4] == 's') ? 1 : 0;
+	int conn_server = (kw[4] == 's') ? 1 : 0;
 	X509 *crt = NULL;
 	int ret = 0;
 	struct buffer *smp_trash;
 	struct connection *conn;
 	SSL *ssl;
 
-	conn = objt_conn(smp->sess->origin);
+	if (conn_server)
+		conn = cs_conn(objt_cs(smp->strm->si[1].end));
+	else
+		conn = objt_conn(smp->sess->origin);
+
 	ssl = ssl_sock_get_ssl_object(conn);
 	if (!ssl)
 		return 0;
@@ -383,7 +413,8 @@
 static int
 smp_fetch_ssl_x_s_dn(const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
-	int cert_peer = (kw[4] == 'c') ? 1 : 0;
+	int cert_peer = (kw[4] == 'c' || kw[4] == 's') ? 1 : 0;
+	int conn_server = (kw[4] == 's') ? 1 : 0;
 	X509 *crt = NULL;
 	X509_NAME *name;
 	int ret = 0;
@@ -391,7 +422,11 @@
 	struct connection *conn;
 	SSL *ssl;
 
-	conn = objt_conn(smp->sess->origin);
+	if (conn_server)
+		conn = cs_conn(objt_cs(smp->strm->si[1].end));
+	else
+		conn = objt_conn(smp->sess->origin);
+
 	ssl = ssl_sock_get_ssl_object(conn);
 	if (!ssl)
 		return 0;
@@ -475,12 +510,17 @@
 static int
 smp_fetch_ssl_x_version(const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
-	int cert_peer = (kw[4] == 'c') ? 1 : 0;
+	int cert_peer = (kw[4] == 'c' || kw[4] == 's') ? 1 : 0;
+	int conn_server = (kw[4] == 's') ? 1 : 0;
+
 	X509 *crt;
 	struct connection *conn;
 	SSL *ssl;
 
-	conn = objt_conn(smp->sess->origin);
+	if (conn_server)
+		conn = cs_conn(objt_cs(smp->strm->si[1].end));
+	else
+		conn = objt_conn(smp->sess->origin);
 	ssl = ssl_sock_get_ssl_object(conn);
 	if (!ssl)
 		return 0;
@@ -513,14 +553,19 @@
 static int
 smp_fetch_ssl_x_sig_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
-	int cert_peer = (kw[4] == 'c') ? 1 : 0;
+	int cert_peer = (kw[4] == 'c' || kw[4] == 's') ? 1 : 0;
+	int conn_server = (kw[4] == 's') ? 1 : 0;
 	X509 *crt;
 	__OPENSSL_110_CONST__ ASN1_OBJECT *algorithm;
 	int nid;
 	struct connection *conn;
 	SSL *ssl;
 
-	conn = objt_conn(smp->sess->origin);
+	if (conn_server)
+		conn = cs_conn(objt_cs(smp->strm->si[1].end));
+	else
+		conn = objt_conn(smp->sess->origin);
+
 	ssl = ssl_sock_get_ssl_object(conn);
 	if (!ssl)
 		return 0;
@@ -565,14 +610,18 @@
 static int
 smp_fetch_ssl_x_key_alg(const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
-	int cert_peer = (kw[4] == 'c') ? 1 : 0;
+	int cert_peer = (kw[4] == 'c' || kw[4] == 's') ? 1 : 0;
+	int conn_server = (kw[4] == 's') ? 1 : 0;
 	X509 *crt;
 	ASN1_OBJECT *algorithm;
 	int nid;
 	struct connection *conn;
 	SSL *ssl;
 
-	conn = objt_conn(smp->sess->origin);
+	if (conn_server)
+		conn = cs_conn(objt_cs(smp->strm->si[1].end));
+	else
+		conn = objt_conn(smp->sess->origin);
 	ssl = ssl_sock_get_ssl_object(conn);
 	if (!ssl)
 		return 0;
@@ -1337,6 +1386,18 @@
 	{ "ssl_fc_cipherlist_hex",  smp_fetch_ssl_fc_cl_hex,      0,                   NULL,    SMP_T_BIN,  SMP_USE_L5CLI },
 	{ "ssl_fc_cipherlist_str",  smp_fetch_ssl_fc_cl_str,      0,                   NULL,    SMP_T_STR,  SMP_USE_L5CLI },
 	{ "ssl_fc_cipherlist_xxh",  smp_fetch_ssl_fc_cl_xxh64,    0,                   NULL,    SMP_T_SINT, SMP_USE_L5CLI },
+
+/* SSL server certificate fetches */
+	{ "ssl_s_der",              smp_fetch_ssl_x_der,          0,                   NULL,    SMP_T_BIN,  SMP_USE_L5CLI },
+	{ "ssl_s_key_alg",          smp_fetch_ssl_x_key_alg,      0,                   NULL,    SMP_T_STR,  SMP_USE_L5CLI },
+	{ "ssl_s_notafter",         smp_fetch_ssl_x_notafter,     0,                   NULL,    SMP_T_STR,  SMP_USE_L5CLI },
+	{ "ssl_s_notbefore",        smp_fetch_ssl_x_notbefore,    0,                   NULL,    SMP_T_STR,  SMP_USE_L5CLI },
+	{ "ssl_s_sig_alg",          smp_fetch_ssl_x_sig_alg,      0,                   NULL,    SMP_T_STR,  SMP_USE_L5CLI },
+	{ "ssl_s_s_dn",             smp_fetch_ssl_x_s_dn,         ARG3(0,STR,SINT,STR),val_dnfmt,    SMP_T_STR,  SMP_USE_L5CLI },
+	{ "ssl_s_i_dn",             smp_fetch_ssl_x_i_dn,         ARG3(0,STR,SINT,STR),val_dnfmt,    SMP_T_STR,  SMP_USE_L5CLI },
+	{ "ssl_s_serial",           smp_fetch_ssl_x_serial,       0,                   NULL,    SMP_T_BIN,  SMP_USE_L5CLI },
+	{ "ssl_s_sha1",             smp_fetch_ssl_x_sha1,         0,                   NULL,    SMP_T_BIN,  SMP_USE_L5CLI },
+	{ "ssl_s_version",          smp_fetch_ssl_x_version,      0,                   NULL,    SMP_T_SINT, SMP_USE_L5CLI },
 	{ NULL, NULL, 0, 0, 0 },
 }};