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.
This commit is contained in:
Emeric Brun 2012-10-11 16:11:36 +02:00 committed by Willy Tarreau
parent f9c5c4701c
commit ef42d9219d
3 changed files with 129 additions and 15 deletions

View File

@ -7048,6 +7048,13 @@ backup
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 @@ cookie <value>
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 @@ track [<proxy>/]<server>
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

View File

@ -197,6 +197,9 @@ struct server {
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 {

View File

@ -628,7 +628,34 @@ int ssl_sock_prepare_srv_ctx(struct server *srv, struct proxy *curproxy)
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 @@ static int bind_parse_ca_file(char **args, int cur_arg, struct proxy *px, struct
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 @@ static int bind_parse_crl_file(char **args, int cur_arg, struct proxy *px, struc
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 @@ static int bind_parse_verify(char **args, int cur_arg, struct proxy *px, struct
/************** "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 @@ static int srv_parse_ciphers(char **args, int *cur_arg, struct proxy *px, struct
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 @@ static int srv_parse_ssl(char **args, int *cur_arg, struct proxy *px, struct ser
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 @@ static struct bind_kw_list bind_kws = { "SSL", { }, {
* 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 @@ static struct srv_kw_list srv_kws = { "SSL", { }, {
{ "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 },
}};