MEDIUM: log: report SSL ciphers and version in logs using logformat %sslc/%sslv

These two new log-format tags report the SSL protocol version (%sslv) and the
SSL ciphers (%sslc) used for the connection with the client. For instance, to
append these information just after the client's IP/port address information
on an HTTP log line, use the following configuration :

    log-format %Ci:%Cp\ %sslv:%sslc\ [%t]\ %ft\ %b/%s\ %Tq/%Tw/%Tc/%Tr/%Tt\ %st\ %B\ %cc\ \ %cs\ %tsc\ %ac/%fc/%bc/%sc/%rc\ %sq/%bq\ %hr\ %hs\ %{+Q}r

It will report a line such as the following one :

    Oct 12 20:47:30 haproxy[9643]: 127.0.0.1:43602 TLSv1:AES-SHA [12/Oct/2012:20:47:30.303] stick2~ stick2/s1 7/0/12/0/19 200 145 - - ---- 0/0/0/0/0 0/0 "GET /?t=0 HTTP/1.0"
diff --git a/doc/configuration.txt b/doc/configuration.txt
index aee1d90..208c432 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -9716,7 +9716,7 @@
 Please refer to the table below for currently defined variables :
 
   +---+------+-----------------------------------------------+-------------+
-  | H | var  | field name (8.2.2 and 8.2.3 for description)  | type        |
+  | R | var  | field name (8.2.2 and 8.2.3 for description)  | type        |
   +---+------+-----------------------------------------------+-------------+
   |   | %o   | special variable, apply flags on all next var |             |
   +---+------+-----------------------------------------------+-------------+
@@ -9733,8 +9733,8 @@
   |   | %Sp  | server_port                                   | numeric     |
   |   | %T   | gmt_date_time                                 | date        |
   |   | %Tc  | Tc                                            | numeric     |
-  | * | %Tq  | Tq                                            | numeric     |
-  | * | %Tr  | Tr                                            | numeric     |
+  | H | %Tq  | Tq                                            | numeric     |
+  | H | %Tr  | Tr                                            | numeric     |
   |   | %Ts  | timestamp                                     | numeric     |
   |   | %Tt  | Tt                                            | numeric     |
   |   | %Tw  | Tw                                            | numeric     |
@@ -9742,30 +9742,32 @@
   |   | %b   | backend_name                                  | string      |
   |   | %bc  | beconn                                        | numeric     |
   |   | %bq  | backend_queue                                 | numeric     |
-  | * | %cc  | captured_request_cookie                       | string      |
-  | * | %rt  | http_request_counter                          | numeric     |
-  | * | %cs  | captured_response_cookie                      | string      |
+  | H | %cc  | captured_request_cookie                       | string      |
+  | H | %rt  | http_request_counter                          | numeric     |
+  | H | %cs  | captured_response_cookie                      | string      |
   |   | %f   | frontend_name                                 | string      |
   |   | %ft  | frontend_name_transport ('~' suffix for SSL)  | string      |
   |   | %fc  | feconn                                        | numeric     |
-  | * | %hr  | captured_request_headers default style        | string      |
-  | * | %hrl | captured_request_headers CLF style            | string list |
-  | * | %hs  | captured_response_headers default style       | string      |
-  | * | %hsl | captured_response_headers CLF style           | string list |
+  | H | %hr  | captured_request_headers default style        | string      |
+  | H | %hrl | captured_request_headers CLF style            | string list |
+  | H | %hs  | captured_response_headers default style       | string      |
+  | H | %hsl | captured_response_headers CLF style           | string list |
   |   | %ms  | accept date milliseconds                      | numeric     |
   |   | %pid | PID                                           | numeric     |
-  | * | %r   | http_request                                  | string      |
+  | H | %r   | http_request                                  | string      |
   |   | %rc  | retries                                       | numeric     |
   |   | %s   | server_name                                   | string      |
   |   | %sc  | srv_conn                                      | numeric     |
   |   | %sq  | srv_queue                                     | numeric     |
-  | * | %st  | status_code                                   | numeric     |
+  | S | %sslc| ssl_ciphers (ex: AES-SHA)                     | string      |
+  | S | %sslv| ssl_version (ex: TLSv1)                       | string      |
+  | H | %st  | status_code                                   | numeric     |
   |   | %t   | date_time                                     | date        |
   |   | %ts  | termination_state                             | string      |
-  | * | %tsc | termination_state with cookie status          | string      |
+  | H | %tsc | termination_state with cookie status          | string      |
   +---+------+-----------------------------------------------+-------------+
 
-*: mode http only
+    R = Restrictions : H = mode http only ; S = SSL only
 
 8.3. Advanced logging options
 -----------------------------
diff --git a/include/proto/ssl_sock.h b/include/proto/ssl_sock.h
index 8246b35..5f83dbc 100644
--- a/include/proto/ssl_sock.h
+++ b/include/proto/ssl_sock.h
@@ -35,6 +35,8 @@
 int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf, struct proxy *px);
 int ssl_sock_prepare_srv_ctx(struct server *srv, struct proxy *px);
 void ssl_sock_free_all_ctx(struct bind_conf *bind_conf);
+const char *ssl_sock_get_cipher_name(struct connection *conn);
+const char *ssl_sock_get_proto_version(struct connection *conn);
 
 #endif /* _PROTO_SSL_SOCK_H */
 
diff --git a/include/types/log.h b/include/types/log.h
index 70dc9fa..8c28310 100644
--- a/include/types/log.h
+++ b/include/types/log.h
@@ -91,6 +91,8 @@
 	LOG_FMT_REQ,
 	LOG_FMT_HOSTNAME,
 	LOG_FMT_UNIQUEID,
+	LOG_FMT_SSL_CIPHER,
+	LOG_FMT_SSL_VERSION,
 };
 
 /* enum for parse_logformat */
diff --git a/src/log.c b/src/log.c
index 15ba27b..130c378 100644
--- a/src/log.c
+++ b/src/log.c
@@ -113,6 +113,8 @@
 	{ "rt", LOG_FMT_COUNTER, PR_MODE_HTTP, LW_REQ, NULL }, /* HTTP request counter */
 	{ "H", LOG_FMT_HOSTNAME, PR_MODE_TCP, LW_INIT, NULL }, /* Hostname */
 	{ "ID", LOG_FMT_UNIQUEID, PR_MODE_HTTP, LW_BYTES, NULL }, /* Unique ID */
+	{ "sslc", LOG_FMT_SSL_CIPHER, PR_MODE_TCP, LW_XPRT, NULL }, /* client-side SSL ciphers */
+	{ "sslv", LOG_FMT_SSL_VERSION, PR_MODE_TCP, LW_XPRT, NULL }, /* client-side SSL protocol version */
 	{ 0, 0, 0, 0, NULL }
 };
 
@@ -1001,7 +1003,29 @@
 					LOGCHAR('"');
 				last_isspace = 0;
 				break;
+#ifdef USE_OPENSSL
+			case LOG_FMT_SSL_CIPHER: // %sslc
+				src = NULL;
+				if (s->listener->xprt == &ssl_sock)
+					src = ssl_sock_get_cipher_name(&s->si[0].conn);
+				ret = lf_text(tmplog, src, dst + maxsize - tmplog, tmp);
+				if (ret == NULL)
+					goto out;
+				tmplog = ret;
+				last_isspace = 0;
+				break;
 
+			case LOG_FMT_SSL_VERSION: // %sslv
+				src = NULL;
+				if (s->listener->xprt == &ssl_sock)
+					src = ssl_sock_get_proto_version(&s->si[0].conn);
+				ret = lf_text(tmplog, src, dst + maxsize - tmplog, tmp);
+				if (ret == NULL)
+					goto out;
+				tmplog = ret;
+				last_isspace = 0;
+				break;
+#endif
 			case LOG_FMT_BACKEND: // %b
 				src = be->id;
 				ret = lf_text(tmplog, src, dst + maxsize - tmplog, tmp);
diff --git a/src/ssl_sock.c b/src/ssl_sock.c
index 6c9eae4..9aed915 100644
--- a/src/ssl_sock.c
+++ b/src/ssl_sock.c
@@ -1053,6 +1053,22 @@
 	SSL_set_shutdown(conn->xprt_ctx, SSL_SENT_SHUTDOWN);
 }
 
+/* used for logging, may be changed for a sample fetch later */
+const char *ssl_sock_get_cipher_name(struct connection *conn)
+{
+	if (!conn->xprt && !conn->xprt_ctx)
+		return NULL;
+	return SSL_get_cipher_name(conn->xprt_ctx);
+}
+
+/* used for logging, may be changed for a sample fetch later */
+const char *ssl_sock_get_proto_version(struct connection *conn)
+{
+	if (!conn->xprt && !conn->xprt_ctx)
+		return NULL;
+	return SSL_get_version(conn->xprt_ctx);
+}
+
 /***** Below are some sample fetching functions for ACL/patterns *****/
 
 /* boolean, returns true if client cert was present */