MINOR: server: Make 'default-server' support 'sni' keyword.

This patch makes 'default-server' directives support 'sni' settings.
A field 'sni_expr' has been added to 'struct server' to temporary
stores SNI expressions as strings during both 'default-server' and 'server'
lines parsing. So, to duplicate SNI expressions from 'default-server' 'sni' setting
for new 'server' instances we only have to "strdup" these strings as this is
often done for most of the 'server' settings.
Then, sample expressions are computed calling sample_parse_expr() (only for 'server'
instances).
A new function has been added to produce the same error output as before in case
of any error during 'sni' settings parsing (display_parser_err()).
Should not break anything.
This commit is contained in:
Frdric Lcaille 2017-03-20 14:54:41 +01:00 committed by Willy Tarreau
parent dba9707713
commit 9a146de934
3 changed files with 75 additions and 28 deletions

View File

@ -254,6 +254,7 @@ struct server {
int use_ssl; /* ssl enabled */
#ifdef USE_OPENSSL
char *sni_expr; /* Temporary variable to store a sample expression for SNI */
struct {
SSL_CTX *ctx;
SSL_SESSION *reused_sess;

View File

@ -36,6 +36,7 @@
#include <proto/port_range.h>
#include <proto/protocol.h>
#include <proto/queue.h>
#include <proto/sample.h>
#include <proto/server.h>
#include <proto/stream.h>
#include <proto/stream_interface.h>
@ -1438,6 +1439,53 @@ const char *server_parse_maxconn_change_request(struct server *sv,
return NULL;
}
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
static int server_parse_sni_expr(struct server *newsrv, struct proxy *px, char **err)
{
int idx;
struct sample_expr *expr;
const char *args[] = {
newsrv->sni_expr,
NULL,
};
idx = 0;
proxy->conf.args.ctx = ARGC_SRV;
expr = sample_parse_expr((char **)args, &idx, px->conf.file, px->conf.line,
err, &proxy->conf.args);
if (!expr) {
memprintf(err, "error detected while parsing sni expression : %s", *err);
return ERR_ALERT | ERR_FATAL;
}
if (!(expr->fetch->val & SMP_VAL_BE_SRV_CON)) {
memprintf(err, "error detected while parsing sni expression : "
" fetch method '%s' extracts information from '%s', "
"none of which is available here.\n",
args[0], sample_src_names(expr->fetch->use));
return ERR_ALERT | ERR_FATAL;
}
px->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
release_sample_expr(newsrv->ssl_ctx.sni);
newsrv->ssl_ctx.sni = expr;
return 0;
}
#endif
static void display_parser_err(const char *file, int linenum, char **args, int cur_arg, char **err)
{
if (err && *err) {
indent_msg(err, 2);
Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], *err);
}
else
Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
file, linenum, args[0], args[1], args[cur_arg]);
}
int parse_server(const char *file, int linenum, char **args, struct proxy *curproxy, struct proxy *defproxy)
{
struct server *newsrv = NULL;
@ -1688,6 +1736,8 @@ int parse_server(const char *file, int linenum, char **args, struct proxy *curpr
newsrv->ssl_ctx.verify_host = strdup(curproxy->defsrv.ssl_ctx.verify_host);
if (curproxy->defsrv.ssl_ctx.ciphers != NULL)
newsrv->ssl_ctx.ciphers = strdup(curproxy->defsrv.ssl_ctx.ciphers);
if (curproxy->defsrv.sni_expr != NULL)
newsrv->sni_expr = strdup(curproxy->defsrv.sni_expr);
#endif
#ifdef TCP_USER_TIMEOUT
@ -2135,13 +2185,7 @@ int parse_server(const char *file, int linenum, char **args, struct proxy *curpr
err_code |= code;
if (code) {
if (err && *err) {
indent_msg(&err, 2);
Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
}
else
Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
file, linenum, args[0], args[1], args[cur_arg]);
display_parser_err(file, linenum, args, cur_arg, &err);
if (code & ERR_FATAL) {
free(err);
cur_arg += 1 + kw->skip;
@ -2270,6 +2314,23 @@ int parse_server(const char *file, int linenum, char **args, struct proxy *curpr
srv_lb_commit_status(newsrv);
}
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
if (!defsrv && newsrv->sni_expr) {
int code;
char *err;
err = NULL;
code = server_parse_sni_expr(newsrv, curproxy, &err);
err_code |= code;
if (code) {
display_parser_err(file, linenum, args, cur_arg, &err);
free(err);
if (code & ERR_FATAL)
goto out;
}
}
#endif
}
free(fqdn);
return 0;

View File

@ -6679,32 +6679,17 @@ static int srv_parse_sni(char **args, int *cur_arg, struct proxy *px, struct ser
memprintf(err, "'%s' : the current SSL library doesn't support the SNI TLS extension", args[*cur_arg]);
return ERR_ALERT | ERR_FATAL;
#else
int idx;
struct sample_expr *expr;
char *arg;
if (!*args[*cur_arg + 1]) {
arg = args[*cur_arg + 1];
if (!*arg) {
memprintf(err, "'%s' : missing sni expression", args[*cur_arg]);
return ERR_ALERT | ERR_FATAL;
}
idx = (*cur_arg) + 1;
proxy->conf.args.ctx = ARGC_SRV;
free(newsrv->sni_expr);
newsrv->sni_expr = strdup(arg);
expr = sample_parse_expr((char **)args, &idx, px->conf.file, px->conf.line, err, &proxy->conf.args);
if (!expr) {
memprintf(err, "error detected while parsing sni expression : %s", *err);
return ERR_ALERT | ERR_FATAL;
}
if (!(expr->fetch->val & SMP_VAL_BE_SRV_CON)) {
memprintf(err, "error detected while parsing sni expression : "
" fetch method '%s' extracts information from '%s', none of which is available here.\n",
args[idx-1], sample_src_names(expr->fetch->use));
return ERR_ALERT | ERR_FATAL;
}
px->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
newsrv->ssl_ctx.sni = expr;
return 0;
#endif
}
@ -7510,7 +7495,7 @@ static struct srv_kw_list srv_kws = { "SSL", { }, {
{ "no-tls-tickets", srv_parse_no_tls_tickets, 0, 1 }, /* disable session resumption tickets */
{ "send-proxy-v2-ssl", srv_parse_send_proxy_ssl, 0, 1 }, /* send PROXY protocol header v2 with SSL info */
{ "send-proxy-v2-ssl-cn", srv_parse_send_proxy_cn, 0, 1 }, /* send PROXY protocol header v2 with CN */
{ "sni", srv_parse_sni, 1, 0 }, /* send SNI extension */
{ "sni", srv_parse_sni, 1, 1 }, /* send SNI extension */
{ "ssl", srv_parse_ssl, 0, 1 }, /* enable SSL processing */
{ "ssl-reuse", srv_parse_ssl_reuse, 0, 1 }, /* enable session reuse */
{ "sslv3", srv_parse_sslv3, 0, 1 }, /* enable SSLv3 */