]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: ssl: emulates the multi-cert bundles in the crtlist
authorWilliam Lallemand <wlallemand@haproxy.com>
Thu, 10 Sep 2020 17:13:27 +0000 (19:13 +0200)
committerWilliam Lallemand <wlallemand@haproxy.org>
Wed, 16 Sep 2020 14:28:26 +0000 (16:28 +0200)
The multi-certificates bundle was the common way of offering multiple
certificates of different types (ecdsa and rsa) for a same SSL_CTX.
This was implemented with OpenSSL 1.0.2 before the client_hello callback
was available.

Now that all versions which does not support this callback are
depracated (< 1.1.0), we can safely removes the support for the bundle
which was inconvenient and complexify too much the code.

This patch emulates the bundle loading by looking for the bundle files
when the specified file in the configuration does not exist. It then
creates new entries in the crtlist, so they will appear as new line if
they are dumped from the CLI.

src/ssl_crtlist.c

index 393f4ea4212ea3c24a9c4fe165e242db7761aa43..1ab9468a5391b3a1aaae027136cfae4b45b75b2b 100644 (file)
@@ -519,23 +519,72 @@ int crtlist_parse_file(char *file, struct bind_conf *bind_conf, struct proxy *cu
                /* Look for a ckch_store or create one */
                ckchs = ckchs_lookup(crt_path);
                if (ckchs == NULL) {
-                       if (stat(crt_path, &buf) == 0)
+                       if (stat(crt_path, &buf) == 0) {
+
                                ckchs = ckchs_load_cert_file(crt_path, 0,  err);
-                       else
-                               ckchs = ckchs_load_cert_file(crt_path, 1,  err);
-               }
-               if (ckchs == NULL)
-                       cfgerr |= ERR_ALERT | ERR_FATAL;
+                               if (ckchs == NULL) {
+                                       cfgerr |= ERR_ALERT | ERR_FATAL;
+                                       goto error;
+                               }
+
+                               entry->node.key = ckchs;
+                               entry->crtlist = newlist;
+                               ebpt_insert(&newlist->entries, &entry->node);
+                               LIST_ADDQ(&newlist->ord_entries, &entry->by_crtlist);
+                               LIST_ADDQ(&ckchs->crtlist_entry, &entry->by_ckch_store);
+
+                       } else {
+                               /* If we didn't find the file, this could be a
+                               bundle, since 2.3 we don't support OpenSSL
+                               multi-certificate bundle, so we emulate it by
+                               loading each file separately. To do so we need
+                               to duplicate the entry in the crt-list because
+                               it becomes independent */
+                               char fp[MAXPATHLEN+1] = {0};
+                               int n = 0;
+                               struct crtlist_entry *entry_dup = entry; /* use the previous created entry */
+                               for (n = 0; n < SSL_SOCK_NUM_KEYTYPES; n++) {
+                                       struct stat buf;
+                                       int ret;
+
+                                       ret = snprintf(fp, sizeof(fp), "%s.%s", path, SSL_SOCK_KEYTYPE_NAMES[n]);
+                                       if (ret > sizeof(fp))
+                                               continue;
+
+                                       ckchs = ckchs_lookup(fp);
+                                       if (!ckchs && stat(fp, &buf) == 0) {
+
+                                               ckchs = ckchs_load_cert_file(fp, 0,  err);
+                                               if (ckchs == NULL) {
+                                                       cfgerr |= ERR_ALERT | ERR_FATAL;
+                                                       goto error;
+                                               }
 
+                                               linenum++; /* we duplicate the line for this entry in the bundle */
+                                               if (!entry_dup) { /* if the entry was used, duplicate one */
+                                                       linenum++;
+                                                       entry_dup = crtlist_entry_dup(entry);
+                                                       if (!entry_dup) {
+                                                               cfgerr |= ERR_ALERT | ERR_FATAL;
+                                                               goto error;
+                                                       }
+                                                       entry_dup->linenum = linenum;
+                                               }
+
+                                               entry_dup->node.key = ckchs;
+                                               entry_dup->crtlist = newlist;
+                                               ebpt_insert(&newlist->entries, &entry_dup->node);
+                                               LIST_ADDQ(&newlist->ord_entries, &entry_dup->by_crtlist);
+                                               LIST_ADDQ(&ckchs->crtlist_entry, &entry_dup->by_ckch_store);
+
+                                               entry_dup = NULL; /* the entry was used, we need a new one next round */
+                                       }
+                               }
+                       }
+               }
                if (cfgerr & ERR_CODE)
                        goto error;
 
-               entry->node.key = ckchs;
-               entry->crtlist = newlist;
-               ebpt_insert(&newlist->entries, &entry->node);
-               LIST_ADDQ(&newlist->ord_entries, &entry->by_crtlist);
-               LIST_ADDQ(&ckchs->crtlist_entry, &entry->by_ckch_store);
-
                entry = NULL;
        }
        if (cfgerr & ERR_CODE)