MEDIUM: config: implement maxsslconn in the global section

SSL connections take a huge amount of memory, and unfortunately openssl
does not check malloc() returns and easily segfaults when too many
connections are used.

The only solution against this is to provide a global maxsslconn setting
to reject SSL connections above the limit in order to avoid reaching
unsafe limits.
diff --git a/src/cfgparse.c b/src/cfgparse.c
index a150503..925013a 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -721,6 +721,22 @@
 		}
 #endif /* SYSTEM_MAXCONN */
 	}
+	else if (!strcmp(args[0], "maxsslconn")) {
+#ifdef USE_OPENSSL
+		if (*(args[1]) == 0) {
+			Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
+			err_code |= ERR_ALERT | ERR_FATAL;
+			goto out;
+		}
+		global.maxsslconn = atol(args[1]);
+#else
+		if (*(args[1]) == 0) {
+			Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
+			err_code |= ERR_ALERT | ERR_FATAL;
+			goto out;
+		}
+#endif
+	}
 	else if (!strcmp(args[0], "maxconnrate")) {
 		if (global.cps_lim != 0) {
 			Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
diff --git a/src/haproxy.c b/src/haproxy.c
index 7439a4c..def0f3f 100644
--- a/src/haproxy.c
+++ b/src/haproxy.c
@@ -129,6 +129,9 @@
 		.sslcachesize = 20000,
 #endif
 	},
+#if defined (USE_OPENSSL) && defined(DEFAULT_MAXSSLCONN)
+	.maxsslconn = DEFAULT_MAXSSLCONN,
+#endif
 	/* others NULL OK */
 };
 
diff --git a/src/ssl_sock.c b/src/ssl_sock.c
index cfe788d..69c4099 100644
--- a/src/ssl_sock.c
+++ b/src/ssl_sock.c
@@ -44,6 +44,7 @@
 #include <types/global.h>
 
 
+static int sslconns = 0;
 
 void ssl_sock_infocbk(const SSL *ssl, int where, int ret)
 {
@@ -69,10 +70,12 @@
 	if (conn->data_ctx)
 		return 0;
 
+	if (global.maxsslconn && sslconns >= global.maxsslconn)
+		return -1;
+
 	/* If it is in client mode initiate SSL session
 	   in connect state otherwise accept state */
 	if (target_srv(&conn->target)) {
-
 		/* Alloc a new SSL session ctx */
 		conn->data_ctx = SSL_new(target_srv(&conn->target)->ssl_ctx.ctx);
 		if (!conn->data_ctx)
@@ -87,10 +90,11 @@
 
 		/* leave init state and start handshake */
 		conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
+
+		sslconns++;
 		return 0;
 	}
 	else if (target_client(&conn->target)) {
-
 		/* Alloc a new SSL session ctx */
 		conn->data_ctx = SSL_new(target_client(&conn->target)->ssl_ctx.ctx);
 		if (!conn->data_ctx)
@@ -106,6 +110,8 @@
 
 		/* leave init state and start handshake */
 		conn->flags |= CO_FL_SSL_WAIT_HS | CO_FL_WAIT_L6_CONN;
+
+		sslconns++;
 		return 0;
 	}
 	/* don't know how to handle such a target */
@@ -339,8 +345,8 @@
 	if (conn->data_ctx) {
 		SSL_free(conn->data_ctx);
 		conn->data_ctx = NULL;
+		sslconns--;
 	}
-
 }
 
 /* This function tries to perform a clean shutdown on an SSL connection, and in