MEDIUM: ssl_sock: implement ssl_sock_prepare_bind_conf()

Instead of hard-coding all SSL preparation in cfgparse.c, we now register
this new function as the transport layer's prepare_bind_conf() and call it
only when definied. This removes some non-obvious SSL-specific code from
cfgparse.c as well as a #ifdef.
diff --git a/include/proto/ssl_sock.h b/include/proto/ssl_sock.h
index 119368a..eea5344 100644
--- a/include/proto/ssl_sock.h
+++ b/include/proto/ssl_sock.h
@@ -45,6 +45,7 @@
 int ssl_sock_handshake(struct connection *conn, unsigned int flag);
 int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, SSL_CTX *ctx);
 int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf);
+int ssl_sock_prepare_bind_conf(struct bind_conf *bind_conf);
 int ssl_sock_prepare_srv_ctx(struct server *srv);
 void ssl_sock_free_srv_ctx(struct server *srv);
 void ssl_sock_free_all_ctx(struct bind_conf *bind_conf);
diff --git a/src/cfgparse.c b/src/cfgparse.c
index c4c392f..f1f0f9b 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -8717,45 +8717,15 @@
 		struct listener *listener;
 		unsigned int next_id;
 
-#ifdef USE_OPENSSL
 		/* Configure SSL for each bind line.
 		 * Note: if configuration fails at some point, the ->ctx member
 		 * remains NULL so that listeners can later detach.
 		 */
 		list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
-			int alloc_ctx;
-
-			if (!bind_conf->is_ssl) {
-				if (bind_conf->default_ctx) {
-					Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
-					        curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
-				}
-				continue;
-			}
-			if (!bind_conf->default_ctx) {
-				Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
-				      curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
+			if (bind_conf->xprt->prepare_bind_conf &&
+			    bind_conf->xprt->prepare_bind_conf(bind_conf) < 0)
 				cfgerr++;
-				continue;
-			}
-
-			alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
-			if (alloc_ctx < 0) {
-				if (alloc_ctx == SHCTX_E_INIT_LOCK)
-					Alert("Unable to initialize the lock for the shared SSL session cache. You can retry using the global statement 'tune.ssl.force-private-cache' but it could increase CPU usage due to renegotiations if nbproc > 1.\n");
-				else
-					Alert("Unable to allocate SSL session cache.\n");
-				cfgerr++;
-				continue;
-			}
-
-			/* initialize all certificate contexts */
-			cfgerr += ssl_sock_prepare_all_ctx(bind_conf);
-
-			/* initialize CA variables if the certificates generation is enabled */
-			cfgerr += ssl_sock_load_ca(bind_conf);
 		}
-#endif /* USE_OPENSSL */
 
 		/* adjust this proxy's listeners */
 		next_id = 1;
diff --git a/src/ssl_sock.c b/src/ssl_sock.c
index 6cb8d63..490003f 100644
--- a/src/ssl_sock.c
+++ b/src/ssl_sock.c
@@ -3223,6 +3223,47 @@
 	return err;
 }
 
+/* Prepares all the contexts for a bind_conf and allocates the shared SSL
+ * context if needed. Returns < 0 on error, 0 on success. The warnings and
+ * alerts are directly emitted since the rest of the stack does it below.
+ */
+int ssl_sock_prepare_bind_conf(struct bind_conf *bind_conf)
+{
+	struct proxy *px = bind_conf->frontend;
+	int alloc_ctx;
+	int err;
+
+	if (!bind_conf->is_ssl) {
+		if (bind_conf->default_ctx) {
+			Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
+				px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
+		}
+		return 0;
+	}
+	if (!bind_conf->default_ctx) {
+		Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
+		      px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
+		return -1;
+	}
+
+	alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
+	if (alloc_ctx < 0) {
+		if (alloc_ctx == SHCTX_E_INIT_LOCK)
+			Alert("Unable to initialize the lock for the shared SSL session cache. You can retry using the global statement 'tune.ssl.force-private-cache' but it could increase CPU usage due to renegotiations if nbproc > 1.\n");
+		else
+			Alert("Unable to allocate SSL session cache.\n");
+		return -1;
+	}
+
+	err = 0;
+	/* initialize all certificate contexts */
+	err += ssl_sock_prepare_all_ctx(bind_conf);
+
+	/* initialize CA variables if the certificates generation is enabled */
+	err += ssl_sock_load_ca(bind_conf);
+
+	return -err;
+}
 
 /* release ssl context allocated for servers. */
 void ssl_sock_free_srv_ctx(struct server *srv)
@@ -6590,6 +6631,7 @@
 	.shutw    = ssl_sock_shutw,
 	.close    = ssl_sock_close,
 	.init     = ssl_sock_init,
+	.prepare_bind_conf = ssl_sock_prepare_bind_conf,
 	.name     = "SSL",
 };