]> git.kaiwu.me - haproxy.git/commitdiff
MINOR: http: support default hardening names "untrusted" and "trusted"
authorWilly Tarreau <w@1wt.eu>
Mon, 26 Oct 2026 19:41:09 +0000 (20:41 +0100)
committerWilly Tarreau <w@1wt.eu>
Wed, 4 Nov 2026 21:45:32 +0000 (22:45 +0100)
And also reserve "auto" for future use. Both "untrusted" and "trusted"
have a global storage and are available all the time. They're just not
registered in the tree by default so that we'll find them once missed
in the tree lookup. If a section with these names is created, it
inherits their settings. This will allow new default settings to
change over time, with minimal maintenance effort for the users.

They are preset to the default permissive rules.

include/haproxy/http-t.h
include/haproxy/http.h
src/http.c

index 787ed32715dd0f38bcfa963f597f84d57329a5d4..684a69325e14a0f21307e4fd003aaa3fdaba3218 100644 (file)
@@ -246,6 +246,10 @@ struct http_violation {
 /* default policy for a new profile: permissive */
 #define HTTP_HRD_DEFAULT  HTTP_HRD_NONE
 
+/* default contents of the implicit "untrusted" and "trusted" profiles */
+#define HTTP_HRD_UNTRUSTED_DEFAULT             HTTP_HRD_DEFAULT
+#define HTTP_HRD_TRUSTED_DEFAULT               HTTP_HRD_DEFAULT
+
 /* a hardening keyword */
 struct http_hardening_kw {
        const char *name;
index fcfa7846e42ffd362b681e47fd5e95fa6ae3dca6..50c47c9b2cce811562413f2d966b3da40c35eba2 100644 (file)
@@ -36,6 +36,8 @@ extern const uint8_t http_char_classes[256];
 extern long http_err_status_codes[512 / sizeof(long)];
 extern long http_fail_status_codes[512 / sizeof(long)];
 extern const struct http_hardening_kw http_hardening_kws[];
+extern struct http_hdng_prf http_hardening_untrusted;
+extern struct http_hdng_prf http_hardening_trusted;
 
 enum http_meth_t find_http_meth(const char *str, const int len);
 int http_get_status_idx(unsigned int status);
index 7da24791e3d8e32d4591fa043c884f4af06e13c3..6a1c6103f47bc3dc9c1dcb80c9b7bc105b65bd8e 100644 (file)
@@ -1773,20 +1773,32 @@ const struct http_hardening_kw http_hardening_kws[] = {
 };
 
 /* Declared profiles are indexed by name in <http_hardening_by_name>. They must
- * be declared before being referenced, like for "defaults" sections.
+ * be declared before being referenced, like for "defaults" sections. The
+ * implicit "untrusted" and "trusted" profiles are static, so that they may
+ * always be referenced, and are only inserted into the tree when their section
+ * is parsed, in which case they are reset to their default values beforehand.
  */
 static struct ceb_root *http_hardening_by_name;
+struct http_hdng_prf http_hardening_untrusted  = { .name = "untrusted",  .mask = HTTP_HRD_UNTRUSTED_DEFAULT  };
+struct http_hdng_prf http_hardening_trusted    = { .name = "trusted",    .mask = HTTP_HRD_TRUSTED_DEFAULT    };
 
 /* the profile being filled by the "http-hardening" section parser */
 static struct http_hdng_prf *curr_http_hdng_prf;
 
-/* Returns the declared profile named <name>, or NULL if it doesn't exist.
+/* Returns the declared profile named <name>, or the implicit one if it's
+ * "untrusted" or "trusted" and not declared, or NULL if it doesn't exist.
  */
 struct http_hdng_prf *http_hardening_lookup(const char *name)
 {
        struct http_hdng_prf *prf;
 
        prf = cebuis_item_lookup(&http_hardening_by_name, name_node, name, name, struct http_hdng_prf);
+       if (!prf) {
+               if (strcmp(name, http_hardening_untrusted.name) == 0)
+                       prf = &http_hardening_untrusted;
+               else if (strcmp(name, http_hardening_trusted.name) == 0)
+                       prf = &http_hardening_trusted;
+       }
        return prf;
 }
 
@@ -1834,8 +1846,10 @@ struct http_hdng_prf *http_hardening_resolve(const char *name, char **err)
 
 /* parses the "http-hardening" section and its keywords. A section is declared
  * with a name, and optionally "from" and the name of an already declared
- * profile whose settings are inherited. Each hardening option is followed by
- * "on" or "off" to enable or disable the matching checks.
+ * profile whose settings are inherited. Otherwise the default settings of the
+ * "untrusted" (resp. "trusted") profile apply to all but "trusted". Each
+ * hardening option is followed by "on" or "off" to enable or disable the
+ * matching checks.
  */
 int cfg_parse_http_hardening(const char *file, int linenum, char **args, int kwm)
 {
@@ -1861,6 +1875,12 @@ int cfg_parse_http_hardening(const char *file, int linenum, char **args, int kwm
                        goto out;
                }
 
+               if (strcmp(args[1], "auto") == 0) {
+                       ha_alert("parsing [%s:%d] : '%s' name 'auto' is reserved.\n", file, linenum, args[0]);
+                       err_code |= ERR_ALERT | ERR_ABORT;
+                       goto out;
+               }
+
                if (*args[2]) {
                        if (strcmp(args[2], "from") != 0 || !*args[3]) {
                                ha_alert("parsing [%s:%d] : '%s %s' only supports an optional 'from <name>'.\n",
@@ -1890,8 +1910,13 @@ int cfg_parse_http_hardening(const char *file, int linenum, char **args, int kwm
                        goto out;
                }
 
-               /* create the profile */
-               prf = http_hardening_new(args[1]);
+               /* use the implicit profile or create it */
+               if (strcmp(args[1], http_hardening_untrusted.name) == 0)
+                       prf = &http_hardening_untrusted;
+               else if (strcmp(args[1], http_hardening_trusted.name) == 0)
+                       prf = &http_hardening_trusted;
+               else
+                       prf = http_hardening_new(args[1]);
 
                if (!prf) {
                        ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum);
@@ -1916,8 +1941,13 @@ int cfg_parse_http_hardening(const char *file, int linenum, char **args, int kwm
                prf->line = linenum;
                cebuis_item_insert(&http_hardening_by_name, name_node, name, prf);
 
+               /* note: was preset during allocation */
                if (base)
                        prf->mask = base->mask;
+               else if (prf == &http_hardening_trusted)
+                       prf->mask = HTTP_HRD_TRUSTED_DEFAULT;
+               else if (prf == &http_hardening_untrusted)
+                       prf->mask = HTTP_HRD_UNTRUSTED_DEFAULT;
 
                curr_http_hdng_prf = prf;
        }
@@ -1976,8 +2006,10 @@ static int cfg_post_parse_http_hardening()
 static void http_hardening_free(struct http_hdng_prf *prf)
 {
        ha_free(&prf->file);
-       free(prf->name);
-       free(prf);
+       if (prf != &http_hardening_untrusted && prf != &http_hardening_trusted) {
+               free(prf->name);
+               free(prf);
+       }
 }
 
 static void http_hardening_deinit()