From 265be280e3f8b3816b5c6e86cdaf2f26aae6f640 Mon Sep 17 00:00:00 2001
From: Emmanuel Hocdet <manu@gandi.net>
Date: Fri, 13 Oct 2017 17:17:44 +0200
Subject: [PATCH 4/4] MINOR: connection: add send-proxy-v2-ssl-crypto parameter

This parameter add crypto informations to proxy-protocol v2 in ssl
context (subtype: SSL_CIPHER, SSL_KEY_ALG, SSL_SIG_ALG).
---
 doc/configuration.txt  | 36 ++++++++++++++++++++++++++++--------
 include/types/server.h |  1 +
 src/connection.c       | 14 ++++++++++++++
 src/ssl_sock.c         | 20 ++++++++++++++++++++
 4 files changed, 63 insertions(+), 8 deletions(-)

diff --git a/doc/configuration.txt b/doc/configuration.txt
index e68eefb88..6ff131bab 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -11330,6 +11330,13 @@ no-send-proxy-v2-ssl-cn
   It may also be used as "default-server" setting to reset any previous
   "default-server" "send-proxy-v2-ssl-cn" setting.
 
+no-send-proxy-v2-ssl-crypto
+  This option may be used as "server" setting to reset any
+  "send-proxy-v2-ssl-crypto" setting which would have been inherited from
+  "default-server" directive as default value.
+  It may also be used as "default-server" setting to reset any previous
+  "default-server" "send-proxy-v2-ssl-crypto" setting.
+
 no-ssl
   This option may be used as "server" setting to reset any "ssl"
   setting which would have been inherited from "default-server" directive as
@@ -11565,16 +11572,29 @@ send-proxy-v2-ssl
   "send-proxy-v2" option of the "bind" keyword.
 
 send-proxy-v2-ssl-cn
-  The "send-proxy-v2-ssl" parameter enforces use of the PROXY protocol version
-  2 over any connection established to this server. The PROXY protocol informs
-  the other end about the layer 3/4 addresses of the incoming connection, so
-  that it can know the client's address or the public address it accessed to,
+  The "send-proxy-v2-ssl-cn" parameter enforces use of the PROXY protocol
+  version 2 over any connection established to this server. The PROXY protocol
+  informs the other end about the layer 3/4 addresses of the incoming connection,
+  so that it can know the client's address or the public address it accessed to,
+  whatever the upper layer protocol. In addition, the SSL information extension
+  of the PROXY protocol, along with the Common Name from the subject of the
+  client certificate (if any), is added to the PROXY protocol header. This setting
+  must not be used if the server isn't aware of this version of the protocol.
+  See also the "no-send-proxy-v2-ssl-cn" option of this section and the
+  "send-proxy-v2-ssl" option of the "bind" keyword.
+
+send-proxy-v2-ssl-crypto
+  The "send-proxy-v2-ssl-crypto" parameter enforces use of the PROXY protocol
+  version 2 over any connection established to this server. The PROXY protocol
+  informs the other end about the layer 3/4 addresses of the incoming connection,
+  so that it can know the client's address or the public address it accessed to,
   whatever the upper layer protocol. In addition, the SSL information extension
-  of the PROXY protocol, along along with the Common Name from the subject of
-  the client certificate (if any), is added to the PROXY protocol header. This
+  of the PROXY protocol, along with crypo information is added to the PROXY
+  protocol header (cipher, private key algorithm, certificate signature). This
   setting must not be used if the server isn't aware of this version of the
-  protocol. See also the "no-send-proxy-v2-ssl-cn" option of this section and the
-  "send-proxy-v2" option of the "bind" keyword.
+  protocol.
+  See also the "no-send-proxy-v2-ssl-crypto" option of this section and the
+  "send-proxy-v2-ssl" option of the "bind" keyword.
 
 slowstart <start_time_in_ms>
   The "slowstart" parameter for a server accepts a value in milliseconds which
diff --git a/include/types/server.h b/include/types/server.h
index 4a31934d5..6d1c46665 100644
--- a/include/types/server.h
+++ b/include/types/server.h
@@ -148,6 +148,7 @@ enum srv_initaddr {
 #define SRV_PP_V2          0x0002        /* proxy protocol version 2 */
 #define SRV_PP_V2_SSL      0x0004        /* proxy protocol version 2 with SSL*/
 #define SRV_PP_V2_SSL_CN   0x0008        /* proxy protocol version 2 with SSL and CN*/
+#define SRV_PP_V2_SSL_CRYPTO 0x0010      /* proxy protocol version 2 with SSL crypto info*/
 
 /* function which act on servers need to return various errors */
 #define SRV_STATUS_OK       0   /* everything is OK. */
diff --git a/src/connection.c b/src/connection.c
index 26bcadd22..ea4b69eae 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -1070,6 +1070,20 @@ int make_proxy_line_v2(char *buf, int buf_len, struct server *srv, struct connec
 					ssl_tlv_len += make_tlv(&buf[ret+ssl_tlv_len], (buf_len - ret - ssl_tlv_len), PP2_SUBTYPE_SSL_CN, cn_trash->len, cn_trash->str);
 				}
 			}
+			if (srv->pp_opts & SRV_PP_V2_SSL_CRYPTO) {
+				struct chunk *pkey_trash = get_trash_chunk();
+				if (ssl_sock_get_pkey_algo(remote, pkey_trash) > 0) {
+					ssl_tlv_len += make_tlv(&buf[ret+ssl_tlv_len], (buf_len - ret - ssl_tlv_len), PP2_SUBTYPE_SSL_KEY_ALG, pkey_trash->len, pkey_trash->str);
+				}
+				value = ssl_sock_get_cert_sign(remote);
+				if (value) {
+					ssl_tlv_len += make_tlv(&buf[ret+ssl_tlv_len], (buf_len - ret - ssl_tlv_len), PP2_SUBTYPE_SSL_SIG_ALG, strlen(value)+1, value);
+				}
+				value = ssl_sock_get_cipher_name(remote);
+				if (value) {
+					ssl_tlv_len += make_tlv(&buf[ret+ssl_tlv_len], (buf_len - ret - ssl_tlv_len), PP2_SUBTYPE_SSL_CIPHER, strlen(value)+1, value);
+				}
+			}
 		}
 		tlv->tlv.length_hi = (uint16_t)(ssl_tlv_len - sizeof(struct tlv)) >> 8;
 		tlv->tlv.length_lo = (uint16_t)(ssl_tlv_len - sizeof(struct tlv)) & 0x00ff;
diff --git a/src/ssl_sock.c b/src/ssl_sock.c
index cc26d6715..171c87134 100644
--- a/src/ssl_sock.c
+++ b/src/ssl_sock.c
@@ -7778,6 +7778,15 @@ static int srv_parse_no_send_proxy_cn(char **args, int *cur_arg, struct proxy *p
 	return 0;
 }
 
+/* parse the "no-send-proxy-v2-ssl-crypto" server keyword */
+static int srv_parse_no_send_proxy_crypto(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
+{
+	newsrv->pp_opts &= ~SRV_PP_V2;
+	newsrv->pp_opts &= ~SRV_PP_V2_SSL;
+	newsrv->pp_opts &= ~SRV_PP_V2_SSL_CRYPTO;
+	return 0;
+}
+
 /* parse the "no-ssl" server keyword */
 static int srv_parse_no_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
 {
@@ -7817,6 +7826,15 @@ static int srv_parse_send_proxy_cn(char **args, int *cur_arg, struct proxy *px,
 	return 0;
 }
 
+/* parse the "send-proxy-v2-ssl-crypto" server keyword */
+static int srv_parse_send_proxy_crypto(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
+{
+	newsrv->pp_opts |= SRV_PP_V2;
+	newsrv->pp_opts |= SRV_PP_V2_SSL;
+	newsrv->pp_opts |= SRV_PP_V2_SSL_CRYPTO;
+	return 0;
+}
+
 /* parse the "sni" server keyword */
 static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
 {
@@ -8654,6 +8672,7 @@ static struct srv_kw_list srv_kws = { "SSL", { }, {
 	{ "no-check-ssl",            srv_parse_no_check_ssl,       0, 1 }, /* disable SSL for health checks */
 	{ "no-send-proxy-v2-ssl",    srv_parse_no_send_proxy_ssl,  0, 1 }, /* do not send PROXY protocol header v2 with SSL info */
 	{ "no-send-proxy-v2-ssl-cn", srv_parse_no_send_proxy_cn,   0, 1 }, /* do not send PROXY protocol header v2 with CN */
+	{ "no-send-proxy-v2-ssl-crypto", srv_parse_no_send_proxy_crypto,   0, 1 }, /* do not send PROXY protocol header v2 with crypto info */
 	{ "no-ssl",                  srv_parse_no_ssl,             0, 1 }, /* disable SSL processing */
 	{ "no-ssl-reuse",            srv_parse_no_ssl_reuse,       0, 1 }, /* disable session reuse */
 	{ "no-sslv3",                srv_parse_tls_method_options, 0, 0 }, /* disable SSLv3 */
@@ -8664,6 +8683,7 @@ static struct srv_kw_list srv_kws = { "SSL", { }, {
 	{ "no-tls-tickets",          srv_parse_no_tls_tickets,     0, 1 }, /* disable session resumption tickets */
 	{ "send-proxy-v2-ssl",       srv_parse_send_proxy_ssl,     0, 1 }, /* send PROXY protocol header v2 with SSL info */
 	{ "send-proxy-v2-ssl-cn",    srv_parse_send_proxy_cn,      0, 1 }, /* send PROXY protocol header v2 with CN */
+	{ "send-proxy-v2-ssl-crypto", srv_parse_send_proxy_crypto, 0, 1 }, /* send PROXY protocol header v2 with crypto info */
 	{ "sni",                     srv_parse_sni,                1, 1 }, /* send SNI extension */
 	{ "ssl",                     srv_parse_ssl,                0, 1 }, /* enable SSL processing */
 	{ "ssl-min-ver",             srv_parse_tls_method_minmax,  1, 1 }, /* minimum version */
-- 
2.11.0

