]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: server: generalize sni expr parsing
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Thu, 23 May 2024 08:59:20 +0000 (10:59 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Fri, 24 May 2024 12:36:31 +0000 (14:36 +0200)
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.

include/haproxy/server.h
src/http_client.c
src/server.c

index 8d58e74c4581230f2efd3fea493ebc10b7eaf40e..b8f8c71316f8c638ce972847a0a71b2f871fa667 100644 (file)
 
 #include <haproxy/api.h>
 #include <haproxy/applet-t.h>
+#include <haproxy/arg-t.h>
 #include <haproxy/freq_ctr.h>
 #include <haproxy/proxy-t.h>
 #include <haproxy/resolvers-t.h>
+#include <haproxy/sample-t.h>
 #include <haproxy/server-t.h>
 #include <haproxy/task.h>
 #include <haproxy/thread-t.h>
@@ -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);
index 7a8d7fdf61154b201c6b4d0897824693f3675877..848e6cec0ce0cec6211b34e10c04522efd82d6f0 100644 (file)
@@ -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;
                }
        }
index 48984fe5c925e0a35eb4d4fe6fe96ded7e793b4b..f0362a09bb63e4f0b90aaad0d2867261e352fefb 100644 (file)
@@ -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 <expr> 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 <str> if not empty as a sample expression and store it into <out>.
+ * Contrary to _parse_srv_expr(), fetch scope validity is checked to ensure it
+ * is valid on a server line context. It also updates <px> 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;