]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: ssl: crt-list negative filters don't work
authorWilliam Lallemand <wlallemand@haproxy.com>
Mon, 17 Aug 2020 12:31:19 +0000 (14:31 +0200)
committerWilliam Lallemand <wlallemand@haproxy.org>
Mon, 17 Aug 2020 12:57:00 +0000 (14:57 +0200)
The negative filters which are supposed to exclude a SNI from a
wildcard, never worked. Indeed the negative filters were skipped in the
code.

To fix the issue, this patch looks for negative filters that are on the
same line as a the wildcard that just matched.

This patch should fix issue #818. It must be backported in 2.2.  The
problem also exists in versions > 1.8 but the infrastructure required to
fix this was only introduced in 2.1.  In older versions we should
probably change the documentation to state that negative filters are
useless.

src/ssl_sock.c

index b9d88b1c42fc4400d167fd15e87d7503390a5458..ac6537f38a35cbb2983743ab920d1a3cffc66be7 100644 (file)
@@ -2357,13 +2357,31 @@ static int ssl_sock_switchctx_cbk(SSL *ssl, int *al, void *arg)
        for (i = 0; i < 2; i++) {
                if (i == 0)     /* lookup in full qualified names */
                        node = ebst_lookup(&s->sni_ctx, trash.area);
-               else if (i == 1 && wildp) /* lookup in wildcards names */
+               else if (i == 1 && wildp)  /* lookup in wildcards names */
                        node = ebst_lookup(&s->sni_w_ctx, wildp);
                else
                        break;
+
                for (n = node; n; n = ebmb_next_dup(n)) {
+
                        /* lookup a not neg filter */
                        if (!container_of(n, struct sni_ctx, name)->neg) {
+                               struct sni_ctx *sni, *sni_tmp;
+                               int skip = 0;
+
+                               if (i == 1 && wildp) { /* wildcard */
+                                       /* If this is a wildcard, look for an exclusion on the same crt-list line */
+                                       sni = container_of(n, struct sni_ctx, name);
+                                       list_for_each_entry(sni_tmp, &sni->ckch_inst->sni_ctx, by_ckch_inst) {
+                                               if (sni_tmp->neg && (!strcmp((const char *)sni_tmp->name.key, trash.area))) {
+                                                       skip = 1;
+                                                       break;
+                                               }
+                                       }
+                                       if (skip)
+                                               continue;
+                               }
+
                                switch(container_of(n, struct sni_ctx, name)->kinfo.sig) {
                                case TLSEXT_signature_ecdsa:
                                        if (!node_ecdsa)