From: Amaury Denoyelle Date: Thu, 23 May 2024 08:59:20 +0000 (+0200) Subject: MINOR: server: generalize sni expr parsing X-Git-Tag: v3.0-dev13~12 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=91001422b466ac8205acde1f94b7a6c4df536c49;p=thirdparty%2Fhaproxy.git MINOR: server: generalize sni expr parsing Two functions exists for server sni sample expression parsing. This is confusing so this commit aims at clarifying this. Functions are renamed with the following identifiers. First function is named parse_srv_expr() and can be used during parsing. Besides expression parsing, it has ensure sample fetch validity in the context of a server line. Second function is renamed _parse_srv_expr() and is used internally by parse_srv_expr(). It only implements sample parsing without extra checks. It is already use for server instantiation derived from server-template as checks were already performed. Also, it is now used in http-client code as SNI is a fixed string. Finally, both functions are generalized to remove any reference to SNI. This will allow to reuse it to parse other server keywords which use an expression. This will be the case for the future keyword pool-conn-name. --- diff --git a/include/haproxy/server.h b/include/haproxy/server.h index 8d58e74c45..b8f8c71316 100644 --- a/include/haproxy/server.h +++ b/include/haproxy/server.h @@ -26,9 +26,11 @@ #include #include +#include #include #include #include +#include #include #include #include @@ -48,7 +50,8 @@ void srv_settings_init(struct server *srv); void srv_settings_cpy(struct server *srv, const struct server *src, int srv_tmpl); int parse_server(const char *file, int linenum, char **args, struct proxy *curproxy, const struct proxy *defproxy, int parse_flags); int srv_update_addr(struct server *s, void *ip, int ip_sin_family, struct server_inetaddr_updater updater); -int server_parse_sni_expr(struct server *newsrv, struct proxy *px, char **err); +struct sample_expr *_parse_srv_expr(char *expr, struct arg_list *args_px, + const char *file, int linenum, char **err); int server_set_inetaddr(struct server *s, const struct server_inetaddr *inetaddr, struct server_inetaddr_updater updater, struct buffer *msg); int server_set_inetaddr_warn(struct server *s, const struct server_inetaddr *inetaddr, struct server_inetaddr_updater updater); void server_get_inetaddr(struct server *s, struct server_inetaddr *inetaddr); diff --git a/src/http_client.c b/src/http_client.c index 7a8d7fdf61..848e6cec0c 100644 --- a/src/http_client.c +++ b/src/http_client.c @@ -1389,9 +1389,12 @@ static int httpclient_postcheck_proxy(struct proxy *curproxy) /* init the SNI expression */ /* always use the host header as SNI, without the port */ srv_ssl->sni_expr = strdup("req.hdr(host),field(1,:)"); - err_code |= server_parse_sni_expr(srv_ssl, curproxy, &errmsg); - if (err_code & ERR_CODE) { - memprintf(&errmsg, "failed to configure sni: %s.", errmsg); + srv_ssl->ssl_ctx.sni = _parse_srv_expr(srv_ssl->sni_expr, + &curproxy->conf.args, + NULL, 0, NULL); + if (!srv_ssl->ssl_ctx.sni) { + memprintf(&errmsg, "failed to configure sni."); + err_code |= ERR_ALERT | ERR_FATAL; goto err; } } diff --git a/src/server.c b/src/server.c index 48984fe5c9..f0362a09bb 100644 --- a/src/server.c +++ b/src/server.c @@ -2429,42 +2429,56 @@ const char *server_parse_maxconn_change_request(struct server *sv, return NULL; } -static struct sample_expr *srv_sni_sample_parse_expr(struct server *srv, struct proxy *px, - const char *file, int linenum, char **err) +/* Interpret as sample expression. This function is reserved for + * internal server allocation. On parsing use parse_srv_expr() for extra sample + * check validity. + * + * Returns the allocated sample on success or NULL on error. + */ +struct sample_expr *_parse_srv_expr(char *expr, struct arg_list *args_px, + const char *file, int linenum, char **err) { int idx; const char *args[] = { - srv->sni_expr, + expr, NULL, }; idx = 0; - px->conf.args.ctx = ARGC_SRV; + args_px->ctx = ARGC_SRV; - return sample_parse_expr((char **)args, &idx, file, linenum, err, &px->conf.args, NULL); + return sample_parse_expr((char **)args, &idx, file, linenum, err, args_px, NULL); } -int server_parse_sni_expr(struct server *newsrv, struct proxy *px, char **err) +/* Interpret if not empty as a sample expression and store it into . + * Contrary to _parse_srv_expr(), fetch scope validity is checked to ensure it + * is valid on a server line context. It also updates HTTP mode + * requirement depending on fetch method used. + * + * Returns 0 on success else non zero. + */ +static int parse_srv_expr(char *str, struct sample_expr **out, struct proxy *px, + char **err) { struct sample_expr *expr; - expr = srv_sni_sample_parse_expr(newsrv, px, px->conf.file, px->conf.line, err); - if (!expr) { - memprintf(err, "error detected while parsing sni expression : %s", *err); + if (!str) + return 0; + + expr = _parse_srv_expr(str, &px->conf.args, px->conf.file, px->conf.line, err); + if (!expr) 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', " + memprintf(err, "fetch method '%s' extracts information from '%s', " "none of which is available here.", - newsrv->sni_expr, sample_src_names(expr->fetch->use)); + str, 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; + release_sample_expr(*out); + *out = expr; return 0; } @@ -3106,7 +3120,7 @@ static int _srv_parse_tmpl_init(struct server *srv, struct proxy *px) srv_prepare_for_resolution(newsrv, srv->hostname); if (newsrv->sni_expr) { - newsrv->ssl_ctx.sni = srv_sni_sample_parse_expr(newsrv, px, NULL, 0, NULL); + newsrv->ssl_ctx.sni = _parse_srv_expr(srv->sni_expr, &px->conf.args, NULL, 0, NULL); if (!newsrv->ssl_ctx.sni) goto err; } @@ -3495,25 +3509,6 @@ out: return err_code; } -/* This function is first intended to be used through parse_server to - * initialize a new server on startup. - */ -static int _srv_parse_sni_expr_init(char **args, int cur_arg, - struct server *srv, struct proxy *proxy, - char **errmsg) -{ - int ret; - - if (!srv->sni_expr) - return 0; - - ret = server_parse_sni_expr(srv, proxy, errmsg); - if (!ret) - return 0; - - return ret; -} - /* Server initializations finalization. * Initialize health check, agent check, SNI expression and outgoing TLVs if enabled. * Must not be called for a default server instance. @@ -3540,9 +3535,9 @@ static int _srv_parse_finalize(char **args, int cur_arg, return ERR_ALERT | ERR_FATAL; } - if ((ret = _srv_parse_sni_expr_init(args, cur_arg, srv, px, &errmsg)) != 0) { + if ((ret = parse_srv_expr(srv->sni_expr, &srv->ssl_ctx.sni, px, &errmsg))) { if (errmsg) { - ha_alert("%s\n", errmsg); + ha_alert("error detected while parsing sni expression : %s.\n", errmsg); free(errmsg); } return ret;