MEDIUM: ssl: Set verify 'required' as global default for servers side.

If no CA file specified on a server line, the config parser will show an error.

Adds an cmdline option '-dV' to re-set verify 'none' as global default on
servers side (previous behavior).

Also adds 'ssl-server-verify' global statement to set global default to
'none' or 'required'.

WARNING: this changes the default verify mode from "none" to "required" on
the server side, and it *will* break insecure setups.
diff --git a/doc/configuration.txt b/doc/configuration.txt
index 88964c4..141f12e 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -455,6 +455,7 @@
    - ulimit-n
    - user
    - stats
+   - ssl-server-verify
    - node
    - description
    - unix-bind
@@ -625,6 +626,11 @@
   warning will automatically be disabled when this setting is used, whatever
   the number of processes used.
 
+ssl-server-verify [none|required]
+  The default behavior for SSL verify on servers side. If specified to 'none',
+  servers certificates are not verified. The default is 'required' except if
+  forced using cmdline option '-dV'.
+
 stats socket [<address:port>|<path>] [param*]
   Binds a UNIX socket to <path> or a TCPv4/v6 address to <address:port>.
   Connections to this socket will return various statistics outputs and even
@@ -8519,9 +8525,10 @@
 
 verify [none|required]
   This setting is only available when support for OpenSSL was built in. If set
-  to 'none', server certificate is not verified. This is the default. In the
-  other case, The certificate provided by the server is verified using CAs from
-  'ca-file' and optional CRLs from 'crl-file'. On verify failure the handshake
+  to 'none', server certificate is not verified. In the other case, The
+  certificate provided by the server is verified using CAs from 'ca-file'
+  and optional CRLs from 'crl-file'. If 'ssl_server_verify' is not specified
+  in global  section, this is the default. On verify failure the handshake
   is aborted. It is critically important to verify server certificates when
   using SSL to connect to servers, otherwise the communication is prone to
   trivial man-in-the-middle attacks rendering SSL totally useless.
diff --git a/include/types/global.h b/include/types/global.h
index 678d4fb..3b010d8 100644
--- a/include/types/global.h
+++ b/include/types/global.h
@@ -64,6 +64,12 @@
 #define ACCESS_LVL_OPER     2
 #define ACCESS_LVL_ADMIN    3
 
+/* SSL server verify mode */
+enum {
+	SSL_SERVER_VERIFY_NONE = 0,
+	SSL_SERVER_VERIFY_REQUIRED = 1,
+};
+
 /* FIXME : this will have to be redefined correctly */
 struct global {
 #ifdef USE_OPENSSL
@@ -79,6 +85,7 @@
 	char *listen_default_ciphers;
 	char *connect_default_ciphers;
 #endif
+	unsigned int ssl_server_verify; /* default verify mode on servers side */
 	struct freq_ctr conn_per_sec;
 	struct freq_ctr sess_per_sec;
 	struct freq_ctr ssl_per_sec;
diff --git a/src/cfgparse.c b/src/cfgparse.c
index 4d1ecd0..c7a491f 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -862,6 +862,22 @@
 		goto out;
 #endif
 	}
+	else if (!strcmp(args[0], "ssl-server-verify")) {
+		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;
+		}
+		if (strcmp(args[1],"none") == 0)
+			global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
+		else if (strcmp(args[1],"required") == 0)
+			global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
+		else {
+			Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
+			err_code |= ERR_ALERT | ERR_FATAL;
+	                goto out;
+		}
+	}
 	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 fd6006d..442d16a 100644
--- a/src/haproxy.c
+++ b/src/haproxy.c
@@ -128,6 +128,7 @@
 	.maxzlibmem = 0,
 #endif
 	.comp_rate_lim = 0,
+	.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED,
 	.unix_bind = {
 		 .ux = {
 			 .uid = -1,
@@ -383,6 +384,7 @@
 #if defined(CONFIG_HAP_LINUX_SPLICE)
 		"        -dS disables splice usage (broken on old kernels)\n"
 #endif
+		"        -dV disables SSL verify on servers side\n"
 		"        -sf/-st [pid ]* finishes/terminates old pids. Must be last arguments.\n"
 		"\n",
 		name, DEFAULT_MAXCONN, cfg_maxpconn);
@@ -587,6 +589,8 @@
 			else if (*flag == 'd' && flag[1] == 'S')
 				global.tune.options &= ~GTUNE_USE_SPLICE;
 #endif
+			else if (*flag == 'd' && flag[1] == 'V')
+				global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
 			else if (*flag == 'V')
 				arg_mode |= MODE_VERBOSE;
 			else if (*flag == 'd' && flag[1] == 'b')
diff --git a/src/ssl_sock.c b/src/ssl_sock.c
index 88c758b..45a6dd0 100644
--- a/src/ssl_sock.c
+++ b/src/ssl_sock.c
@@ -86,6 +86,14 @@
 #define SSL_SOCK_ST_TO_CAEDEPTH(s) ((s >> (6+16)) & 15)
 #define SSL_SOCK_ST_TO_CRTERROR(s) ((s >> (4+6+16)) & 63)
 
+/* server and bind verify method, it uses a global value as default */
+enum {
+	SSL_SOCK_VERIFY_DEFAULT  = 0,
+	SSL_SOCK_VERIFY_REQUIRED = 1,
+	SSL_SOCK_VERIFY_OPTIONAL = 2,
+	SSL_SOCK_VERIFY_NONE     = 3,
+};
+
 int sslconns = 0;
 int totalsslconns = 0;
 
@@ -651,6 +659,7 @@
 int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, SSL_CTX *ctx, struct proxy *curproxy)
 {
 	int cfgerr = 0;
+	int verify = SSL_VERIFY_NONE;
 	int ssloptions =
 		SSL_OP_ALL | /* all known workarounds for bugs */
 		SSL_OP_NO_SSLv2 |
@@ -695,8 +704,19 @@
 
 	SSL_CTX_set_options(ctx, ssloptions);
 	SSL_CTX_set_mode(ctx, sslmode);
-	SSL_CTX_set_verify(ctx, bind_conf->verify ? bind_conf->verify : SSL_VERIFY_NONE, ssl_sock_bind_verifycbk);
-	if (bind_conf->verify & SSL_VERIFY_PEER) {
+	switch (bind_conf->verify) {
+		case SSL_SOCK_VERIFY_NONE:
+			verify = SSL_VERIFY_NONE;
+			break;
+		case SSL_SOCK_VERIFY_OPTIONAL:
+			verify = SSL_VERIFY_PEER;
+			break;
+		case SSL_SOCK_VERIFY_REQUIRED:
+			verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
+			break;
+	}
+	SSL_CTX_set_verify(ctx, verify, ssl_sock_bind_verifycbk);
+	if (verify & SSL_VERIFY_PEER) {
 		if (bind_conf->ca_file) {
 			/* load CAfile to verify */
 			if (!SSL_CTX_load_verify_locations(ctx, bind_conf->ca_file, NULL)) {
@@ -707,6 +727,11 @@
 			/* set CA names fo client cert request, function returns void */
 			SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(bind_conf->ca_file));
 		}
+		else {
+			Alert("Proxy '%s': verify is enabled but no CA file specified for bind '%s' at [%s:%d].\n",
+			      curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
+			cfgerr++;
+		}
 #ifdef X509_V_FLAG_CRL_CHECK
 		if (bind_conf->crl_file) {
 			X509_STORE *store = SSL_CTX_get_cert_store(ctx);
@@ -906,6 +931,7 @@
 		SSL_MODE_ENABLE_PARTIAL_WRITE |
 		SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
 		SSL_MODE_RELEASE_BUFFERS;
+	int verify = SSL_VERIFY_NONE;
 
 	/* Make sure openssl opens /dev/urandom before the chroot */
 	if (!ssl_initialize_random()) {
@@ -974,10 +1000,22 @@
 
 	SSL_CTX_set_options(srv->ssl_ctx.ctx, options);
 	SSL_CTX_set_mode(srv->ssl_ctx.ctx, mode);
+
+	if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
+		verify = SSL_VERIFY_PEER;
+
+	switch (srv->ssl_ctx.verify) {
+		case SSL_SOCK_VERIFY_NONE:
+			verify = SSL_VERIFY_NONE;
+			break;
+		case SSL_SOCK_VERIFY_REQUIRED:
+			verify = SSL_VERIFY_PEER;
+			break;
+	}
 	SSL_CTX_set_verify(srv->ssl_ctx.ctx,
-	                   srv->ssl_ctx.verify ? srv->ssl_ctx.verify : SSL_VERIFY_NONE,
+	                   verify,
 	                   srv->ssl_ctx.verify_host ? ssl_sock_srv_verifycbk : NULL);
-	if (srv->ssl_ctx.verify & SSL_VERIFY_PEER) {
+	if (verify & SSL_VERIFY_PEER) {
 		if (srv->ssl_ctx.ca_file) {
 			/* load CAfile to verify */
 			if (!SSL_CTX_load_verify_locations(srv->ssl_ctx.ctx, srv->ssl_ctx.ca_file, NULL)) {
@@ -987,6 +1025,17 @@
 				cfgerr++;
 			}
 		}
+		else {
+			if (global.ssl_server_verify == SSL_SERVER_VERIFY_REQUIRED)
+				Alert("Proxy '%s', server '%s' |%s:%d] verify is enabled by default but no CA file specified. If you're running on a LAN where you're certain to trust the server's certificate, please set an explicit 'verify none' statement on the 'server' line, or use 'ssl-server-verify none' in the global section to disable server-side verifications by default.\n",
+				      curproxy->id, srv->id,
+				      srv->conf.file, srv->conf.line);
+			else
+				Alert("Proxy '%s', server '%s' |%s:%d] verify is enabled but no CA file specified.\n",
+				      curproxy->id, srv->id,
+				      srv->conf.file, srv->conf.line);
+			cfgerr++;
+		}
 #ifdef X509_V_FLAG_CRL_CHECK
 		if (srv->ssl_ctx.crl_file) {
 			X509_STORE *store = SSL_CTX_get_cert_store(srv->ssl_ctx.ctx);
@@ -3190,11 +3239,11 @@
 	}
 
 	if (strcmp(args[cur_arg + 1], "none") == 0)
-		conf->verify = SSL_VERIFY_NONE;
+		conf->verify = SSL_SOCK_VERIFY_NONE;
 	else if (strcmp(args[cur_arg + 1], "optional") == 0)
-		conf->verify = SSL_VERIFY_PEER;
+		conf->verify = SSL_SOCK_VERIFY_OPTIONAL;
 	else if (strcmp(args[cur_arg + 1], "required") == 0)
-		conf->verify = SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
+		conf->verify = SSL_SOCK_VERIFY_REQUIRED;
 	else {
 		if (err)
 			memprintf(err, "'%s' : unknown verify method '%s', only 'none', 'optional', and 'required' are supported\n",
@@ -3380,9 +3429,9 @@
 	}
 
 	if (strcmp(args[*cur_arg + 1], "none") == 0)
-		newsrv->ssl_ctx.verify = SSL_VERIFY_NONE;
+		newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_NONE;
 	else if (strcmp(args[*cur_arg + 1], "required") == 0)
-		newsrv->ssl_ctx.verify = SSL_VERIFY_PEER;
+		newsrv->ssl_ctx.verify = SSL_SOCK_VERIFY_REQUIRED;
 	else {
 		if (err)
 			memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",