diff --git a/doc/configuration.txt b/doc/configuration.txt index 7cb0b68b9..2c427f3aa 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -7156,6 +7156,15 @@ crl-file Supported in default-server: No +crt + This setting is only available when support for OpenSSL was built in. + It designates a PEM file from which to load both a certificate and the + associated private key. This file can be built by concatenating both PEM + files into one. This certificate will be sent if the server send a client + certificate request. + + 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 diff --git a/include/types/server.h b/include/types/server.h index 1a69f83d1..e65c2c021 100644 --- a/include/types/server.h +++ b/include/types/server.h @@ -200,6 +200,7 @@ struct server { 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 */ + char *client_crt; /* client certificate to send */ } ssl_ctx; #endif struct { diff --git a/src/ssl_sock.c b/src/ssl_sock.c index 1269932d9..0838929bd 100644 --- a/src/ssl_sock.c +++ b/src/ssl_sock.c @@ -621,7 +621,26 @@ int ssl_sock_prepare_srv_ctx(struct server *srv, struct proxy *curproxy) cfgerr++; return cfgerr; } - + if (srv->ssl_ctx.client_crt) { + if (SSL_CTX_use_PrivateKey_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt, SSL_FILETYPE_PEM) <= 0) { + Alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n", + proxy_type_str(curproxy), curproxy->id, + srv->id, srv->ssl_ctx.client_crt); + cfgerr++; + } + else if (SSL_CTX_use_certificate_chain_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt) <= 0) { + Alert("config : %s '%s', server '%s': unable to load ssl certificate from PEM file '%s'.\n", + proxy_type_str(curproxy), curproxy->id, + srv->id, srv->ssl_ctx.client_crt); + cfgerr++; + } + else if (SSL_CTX_check_private_key(srv->ssl_ctx.ctx) <= 0) { + Alert("config : %s '%s', server '%s': inconsistencies between private key and certificate loaded from PEM file '%s'.\n", + proxy_type_str(curproxy), curproxy->id, + srv->id, srv->ssl_ctx.client_crt); + cfgerr++; + } + } if (srv->ssl_ctx.options & SRV_SSL_O_NO_SSLV3) options |= SSL_OP_NO_SSLv3; @@ -2477,6 +2496,22 @@ static int srv_parse_crl_file(char **args, int *cur_arg, struct proxy *px, struc #endif } +/* parse the "crt" server keyword */ +static int srv_parse_crt(char **args, int *cur_arg, struct proxy *px, struct server *newsrv, char **err) +{ + if (!*args[*cur_arg + 1]) { + if (err) + memprintf(err, "'%s' : missing certificate file path", args[*cur_arg]); + return ERR_ALERT | ERR_FATAL; + } + + if ((*args[*cur_arg + 1] != '/') && global.crt_base) + memprintf(&newsrv->ssl_ctx.client_crt, "%s/%s", global.ca_base, args[*cur_arg + 1]); + else + memprintf(&newsrv->ssl_ctx.client_crt, "%s", args[*cur_arg + 1]); + + return 0; +} /* 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) @@ -2706,6 +2741,7 @@ static struct srv_kw_list srv_kws = { "SSL", { }, { { "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 */ + { "crt", srv_parse_crt, 1, 0 }, /* set client certificate */ { "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 */