MINOR: ssl: add statements 'verify', 'ca-file' and 'crl-file' on servers.

It now becomes possible to verify the server's certificate using the "verify"
directive. This one only supports "none" and "required", as it does not make
much sense to also support "optional" here.

diff --git a/doc/configuration.txt b/doc/configuration.txt
index d9a756f..598d5d2 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -7048,6 +7048,13 @@
 
   Supported in default-server: No
 
+ca-file <cafile>
+  This setting is only available when support for OpenSSL was built in. It
+  designates a PEM file from which to load CA certificates used to verify
+  server's certificate.
+
+  Supported in default-server: No
+
 check
   This option enables health checks on the server. By default, a server is
   always considered available. If "check" is set, the server is available when
@@ -7110,6 +7117,13 @@
 
   Supported in default-server: No
 
+crl-file <crlfile>
+  This setting is only available when support for OpenSSL was built in. It
+  designates a PEM file from which to load certificate revocation list used
+  to verify server's certificate.
+
+  Supported in default-server: No
+
 disabled
   The "disabled" keyword starts the server in the "disabled" state. That means
   that it is marked down in maintenance mode, and no connection other than the
@@ -7456,6 +7470,15 @@
 
   Supported in default-server: No
 
+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
+  is aborted.
+
+  Supported in default-server: No
+
 weight <weight>
   The "weight" parameter is used to adjust the server's weight relative to
   other servers. All servers will receive a load proportional to their weight
diff --git a/include/types/server.h b/include/types/server.h
index 2d2bb87..1a69f83 100644
--- a/include/types/server.h
+++ b/include/types/server.h
@@ -197,6 +197,9 @@
 		SSL_SESSION *reused_sess;
 		char *ciphers;			/* cipher suite to use if non-null */
 		int options;			/* ssl options */
+		int verify;			/* verify method (set of SSL_VERIFY_* flags) */
+		char *ca_file;			/* CAfile to use on verify */
+		char *crl_file;			/* CRLfile to use on verify */
 	} ssl_ctx;
 #endif
 	struct {
diff --git a/src/ssl_sock.c b/src/ssl_sock.c
index fb59515..6c9eae4 100644
--- a/src/ssl_sock.c
+++ b/src/ssl_sock.c
@@ -628,7 +628,34 @@
 
 	SSL_CTX_set_options(srv->ssl_ctx.ctx, options);
 	SSL_CTX_set_mode(srv->ssl_ctx.ctx, mode);
-	SSL_CTX_set_verify(srv->ssl_ctx.ctx, SSL_VERIFY_NONE, NULL);
+	SSL_CTX_set_verify(srv->ssl_ctx.ctx, srv->ssl_ctx.verify ? srv->ssl_ctx.verify : SSL_VERIFY_NONE, NULL);
+	if (srv->ssl_ctx.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)) {
+				Alert("Proxy '%s', server '%s' |%s:%d] unable to load CA file '%s'.\n",
+				      curproxy->id, srv->id,
+				      srv->conf.file, srv->conf.line, srv->ssl_ctx.ca_file);
+				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);
+
+			if (!store || !X509_STORE_load_locations(store, srv->ssl_ctx.crl_file, NULL)) {
+				Alert("Proxy '%s', server '%s' |%s:%d] unable to configure CRL file '%s'.\n",
+				      curproxy->id, srv->id,
+				      srv->conf.file, srv->conf.line, srv->ssl_ctx.crl_file);
+				cfgerr++;
+			}
+			else {
+				X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
+			}
+		}
+#endif
+	}
+
 	SSL_CTX_set_session_cache_mode(srv->ssl_ctx.ctx, SSL_SESS_CACHE_OFF);
 	if (srv->ssl_ctx.ciphers &&
 		!SSL_CTX_set_cipher_list(srv->ssl_ctx.ctx, srv->ssl_ctx.ciphers)) {
@@ -1189,14 +1216,11 @@
 		return ERR_ALERT | ERR_FATAL;
 	}
 
-	if ((*args[cur_arg + 1] != '/') && global.ca_base) {
-		conf->ca_file = malloc(strlen(global.ca_base) + 1 + strlen(args[cur_arg + 1]) + 1);
-		if (conf->ca_file)
-			sprintf(conf->ca_file, "%s/%s", global.ca_base, args[cur_arg + 1]);
-		return 0;
-	}
+	if ((*args[cur_arg + 1] != '/') && global.ca_base)
+		memprintf(&conf->ca_file, "%s/%s", global.ca_base, args[cur_arg + 1]);
+	else
+		memprintf(&conf->ca_file, "%s", args[cur_arg + 1]);
 
-	conf->ca_file = strdup(args[cur_arg + 1]);
 	return 0;
 }
 
@@ -1254,14 +1278,11 @@
 		return ERR_ALERT | ERR_FATAL;
 	}
 
-	if ((*args[cur_arg + 1] != '/') && global.ca_base) {
-		conf->crl_file = malloc(strlen(global.ca_base) + 1 + strlen(args[cur_arg + 1]) + 1);
-		if (conf->crl_file)
-			sprintf(conf->crl_file, "%s/%s", global.ca_base, args[cur_arg + 1]);
-		return 0;
-	}
+	if ((*args[cur_arg + 1] != '/') && global.ca_base)
+		memprintf(&conf->crl_file, "%s/%s", global.ca_base, args[cur_arg + 1]);
+	else
+		memprintf(&conf->crl_file, "%s", args[cur_arg + 1]);
 
-	conf->crl_file = strdup(args[cur_arg + 1]);
 	return 0;
 #endif
 }
@@ -1448,6 +1469,23 @@
 
 /************** "server" keywords ****************/
 
+/* parse the "ca-file" server keyword */
+static int srv_parse_ca_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
+{
+	if (!*args[*cur_arg + 1]) {
+		if (err)
+			memprintf(err, "'%s' : missing CAfile path", args[*cur_arg]);
+		return ERR_ALERT | ERR_FATAL;
+	}
+
+	if ((*args[*cur_arg + 1] != '/') && global.ca_base)
+		memprintf(&newsrv->ssl_ctx.ca_file, "%s/%s", global.ca_base, args[*cur_arg + 1]);
+	else
+		memprintf(&newsrv->ssl_ctx.ca_file, "%s", args[*cur_arg + 1]);
+
+	return 0;
+}
+
 /* parse the "check-ssl" server keyword */
 static int srv_parse_check_ssl(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
 {
@@ -1470,6 +1508,30 @@
 	return 0;
 }
 
+/* parse the "crl-file" server keyword */
+static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
+{
+#ifndef X509_V_FLAG_CRL_CHECK
+	if (err)
+		memprintf(err, "'%s' : library does not support CRL verify", args[*cur_arg]);
+	return ERR_ALERT | ERR_FATAL;
+#else
+	if (!*args[*cur_arg + 1]) {
+		if (err)
+			memprintf(err, "'%s' : missing CRLfile path", args[*cur_arg]);
+		return ERR_ALERT | ERR_FATAL;
+	}
+
+	if ((*args[*cur_arg + 1] != '/') && global.ca_base)
+		memprintf(&newsrv->ssl_ctx.crl_file, "%s/%s", global.ca_base, args[*cur_arg + 1]);
+	else
+		memprintf(&newsrv->ssl_ctx.crl_file, "%s", args[*cur_arg + 1]);
+
+	return 0;
+#endif
+}
+
+
 /* parse the "force-sslv3" server keyword */
 static int srv_parse_force_sslv3(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
 {
@@ -1554,6 +1616,29 @@
 	return 0;
 }
 
+/* parse the "verify" server keyword */
+static int srv_parse_verify(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err)
+{
+	if (!*args[*cur_arg + 1]) {
+		if (err)
+			memprintf(err, "'%s' : missing verify method", args[*cur_arg]);
+		return ERR_ALERT | ERR_FATAL;
+	}
+
+	if (strcmp(args[*cur_arg + 1], "none") == 0)
+		newsrv->ssl_ctx.verify = SSL_VERIFY_NONE;
+	else if (strcmp(args[*cur_arg + 1], "required") == 0)
+		newsrv->ssl_ctx.verify = SSL_VERIFY_PEER;
+	else {
+		if (err)
+			memprintf(err, "'%s' : unknown verify method '%s', only 'none' and 'required' are supported\n",
+			          args[*cur_arg], args[*cur_arg + 1]);
+		return ERR_ALERT | ERR_FATAL;
+	}
+
+	return 0;
+}
+
 /* Note: must not be declared <const> as its list will be overwritten.
  * Please take care of keeping this list alphabetically sorted.
  */
@@ -1623,8 +1708,10 @@
  * not enabled.
  */
 static struct srv_kw_list srv_kws = { "SSL", { }, {
+	{ "ca-file",               srv_parse_ca_file,        1, 0 }, /* set CAfile to process verify server cert */
 	{ "check-ssl",             srv_parse_check_ssl,      0, 0 }, /* enable SSL for health checks */
 	{ "ciphers",               srv_parse_ciphers,        1, 0 }, /* select the cipher suite */
+	{ "crl-file",              srv_parse_crl_file,       1, 0 }, /* set certificate revocation list file use on server cert verify */
 	{ "force-sslv3",           srv_parse_force_sslv3,    0, 0 }, /* force SSLv3 */
 	{ "force-tlsv10",          srv_parse_force_tlsv10,   0, 0 }, /* force TLSv10 */
 	{ "force-tlsv11",          srv_parse_force_tlsv11,   0, 0 }, /* force TLSv11 */
@@ -1635,6 +1722,7 @@
 	{ "no-tlsv12",             srv_parse_no_tlsv12,      0, 0 }, /* disable TLSv12 */
 	{ "no-tls-tickets",        srv_parse_no_tls_tickets, 0, 0 }, /* disable session resumption tickets */
 	{ "ssl",                   srv_parse_ssl,            0, 0 }, /* enable SSL processing */
+	{ "verify",                srv_parse_verify,         1, 0 }, /* set SSL verify method */
 	{ NULL, NULL, 0, 0 },
 }};