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.
diff --git a/include/types/server.h b/include/types/server.h
index c973d69..781a889 100644
--- a/include/types/server.h
+++ b/include/types/server.h
@@ -254,6 +254,7 @@
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;
diff --git a/src/server.c b/src/server.c
index 6b0c496..602a7c9 100644
--- a/src/server.c
+++ b/src/server.c
@@ -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 @@
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 @@
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 @@
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 @@
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;
diff --git a/src/ssl_sock.c b/src/ssl_sock.c
index 9d85eac..4c1be5a 100644
--- a/src/ssl_sock.c
+++ b/src/ssl_sock.c
@@ -6679,32 +6679,17 @@
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;
-
- 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;
- }
+ free(newsrv->sni_expr);
+ newsrv->sni_expr = strdup(arg);
- 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 @@
{ "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 */