]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: ssl/crtlist: split the ckch_conf loading from the crtlist line parsing
authorWilliam Lallemand <wlallemand@haproxy.com>
Tue, 11 Feb 2025 14:01:33 +0000 (15:01 +0100)
committerWilliam Lallemand <wlallemand@haproxy.com>
Mon, 17 Feb 2025 17:26:37 +0000 (18:26 +0100)
ckch_conf loading is not that simple as it requires to check
- if the cert already exists in the ckchs_tree
- if the ckch_conf is compatible with an existing cert in ckchs_tree
- if the cert is a bundle which need to load multiple ckch_store

This logic could be reuse elsewhere, so this commit introduce the new
crtlist_load_crt() function which does that.

include/haproxy/ssl_crtlist.h
src/ssl_crtlist.c

index f81ee9ea011e78c44f2406ad8b7608e1b21ae91f..313226748c83728a3f2dbc0fa7179e6b630310ad 100644 (file)
@@ -41,6 +41,7 @@ struct crtlist *crtlist_new(const char *filename, int unique);
 int crtlist_parse_line(char *line, char **crt_path, struct crtlist_entry *entry, struct ckch_conf *conf, const char *file, int linenum, int from_cli, char **err);
 int crtlist_parse_file(char *file, struct bind_conf *bind_conf, struct proxy *curproxy, struct crtlist **crtlist, char **err);
 int crtlist_load_cert_dir(char *path, struct bind_conf *bind_conf, struct crtlist **crtlist, char **err);
+int crtlist_load_crt(char *crt_path, struct ckch_conf *cc, struct crtlist *newlist, struct crtlist_entry *entry, char *file, int linenum, char **err);
 
 void crtlist_deinit();
 
index f19864fd389d0244a9800b8fe92bb6a73067ec4c..0e3bbb0976b2799f42a519a2ea98a1b1a1e07462 100644 (file)
@@ -501,6 +501,138 @@ error:
        return cfgerr;
 }
 
+/*
+ * Look for a ckch_store <crt_path> which is a compatible with <cc>
+ * Or create a new ckch_store if none exists with this name.
+ *
+ * If the file is a bundle, then duplicate the entries
+ * Then insert the entries in the list
+ */
+int crtlist_load_crt(char *crt_path, struct ckch_conf *cc, struct crtlist *newlist, struct crtlist_entry *entry, char *file, int linenum, char **err)
+{
+       struct ckch_store *ckchs;
+       int found = 0;
+       struct stat st;
+       int cfgerr = 0;
+
+       /* Look for a ckch_store or create one */
+       ckchs = ckchs_lookup(crt_path);
+       if (ckchs == NULL) {
+               if (stat(crt_path, &st) == 0) {
+                       found++;
+                       free(cc->crt);
+                       cc->crt = strdup(crt_path);
+                       if (cc->crt == NULL) {
+                               cfgerr |= ERR_ALERT | ERR_FATAL;
+                               goto error;
+                       }
+
+                       ckchs = ckch_store_new_load_files_conf(crt_path, cc, err);
+                       if (ckchs == NULL) {
+                               cfgerr |= ERR_ALERT | ERR_FATAL;
+                               goto error;
+                       }
+
+                       ckchs->conf = *cc;
+
+                       entry->node.key = ckchs;
+                       entry->crtlist = newlist;
+                       ebpt_insert(&newlist->entries, &entry->node);
+                       LIST_APPEND(&newlist->ord_entries, &entry->by_crtlist);
+                       LIST_APPEND(&ckchs->crtlist_entry, &entry->by_ckch_store);
+
+               } else if (global_ssl.extra_files & SSL_GF_BUNDLE) {
+                       /* If we didn't find the file, this could be a
+                          bundle, since 2.3 we don't support multiple
+                          certificate in the same OpenSSL store, 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++) {
+                               int ret;
+
+                               ret = snprintf(fp, sizeof(fp), "%s.%s", crt_path, SSL_SOCK_KEYTYPE_NAMES[n]);
+                               if (ret > sizeof(fp))
+                                       continue;
+
+                               ckchs = ckchs_lookup(fp);
+                               if (!ckchs) {
+                                       if (stat(fp, &st) == 0) {
+
+                                               if (cc->used) {
+                                                       memprintf(err, "%sCan't load '%s'. Using crt-store keyword is not compatible with multi certificates bundle.\n",
+                                                                       err && *err ? *err : "", crt_path);
+                                                       cfgerr |= ERR_ALERT | ERR_FATAL;
+                                               }
+                                               ckchs = ckch_store_new_load_files_path(fp, err);
+                                               if (!ckchs) {
+                                                       cfgerr |= ERR_ALERT | ERR_FATAL;
+                                                       goto error;
+                                               }
+                                       } else {
+                                               continue; /* didn't find this extension, skip */
+                                       }
+                               }
+                               found++;
+                               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_APPEND(&newlist->ord_entries, &entry_dup->by_crtlist);
+                               LIST_APPEND(&ckchs->crtlist_entry, &entry_dup->by_ckch_store);
+
+                               entry_dup = NULL; /* the entry was used, we need a new one next round */
+                       }
+#if HA_OPENSSL_VERSION_NUMBER < 0x10101000L
+                       if (found) {
+                               memprintf(err, "%sCan't load '%s'. Loading a multi certificates bundle requires OpenSSL >= 1.1.1\n",
+                                               err && *err ? *err : "", crt_path);
+                               cfgerr |= ERR_ALERT | ERR_FATAL;
+                       }
+#endif
+               }
+               if (!found) {
+                       memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
+                                       err && *err ? *err : "", crt_path, strerror(errno));
+                       cfgerr |= ERR_ALERT | ERR_FATAL;
+               }
+
+       } else {
+               if (ckch_conf_cmp(&ckchs->conf, cc, err) != 0) {
+                       memprintf(err, "'%s' in crt-list '%s' line %d, is already defined with incompatible parameters:\n %s", crt_path, file, linenum, err ? *err : "");
+                       cfgerr |= ERR_ALERT | ERR_FATAL;
+                       goto error;
+               }
+
+               entry->node.key = ckchs;
+               entry->crtlist = newlist;
+
+               ebpt_insert(&newlist->entries, &entry->node);
+               LIST_APPEND(&newlist->ord_entries, &entry->by_crtlist);
+               LIST_APPEND(&ckchs->crtlist_entry, &entry->by_ckch_store);
+               found++;
+       }
+       entry = NULL;
+
+error:
+       return cfgerr;
+
+}
 
 
 /* This function parse a crt-list file and store it in a struct crtlist, each line is a crtlist_entry structure
@@ -514,7 +646,6 @@ int crtlist_parse_file(char *file, struct bind_conf *bind_conf, struct proxy *cu
        struct crtlist_entry *entry = NULL;
        char thisline[CRT_LINESIZE];
        FILE *f;
-       struct stat buf;
        int linenum = 0;
        int cfgerr = 0;
        int missing_lf = -1;
@@ -536,9 +667,7 @@ int crtlist_parse_file(char *file, struct bind_conf *bind_conf, struct proxy *cu
                char *line = thisline;
                char *crt_path;
                char path[MAXPATHLEN+1];
-               struct ckch_store *ckchs;
                struct ckch_conf cc = {};
-               int found = 0;
 
                if (missing_lf != -1) {
                        memprintf(err, "parsing [%s:%d]: Stray NUL character at position %d.\n",
@@ -601,120 +730,10 @@ int crtlist_parse_file(char *file, struct bind_conf *bind_conf, struct proxy *cu
                        crt_path = path;
                }
 
-               /* Look for a ckch_store or create one */
-               ckchs = ckchs_lookup(crt_path);
-               if (ckchs == NULL) {
-                       if (stat(crt_path, &buf) == 0) {
-                               found++;
-                               free(cc.crt);
-                               cc.crt = strdup(crt_path);
-                               if (cc.crt == NULL) {
-                                       cfgerr |= ERR_ALERT | ERR_FATAL;
-                                       goto error;
-                               }
-
-                               ckchs = ckch_store_new_load_files_conf(crt_path, &cc, err);
-                               if (ckchs == NULL) {
-                                       cfgerr |= ERR_ALERT | ERR_FATAL;
-                                       goto error;
-                               }
-
-                               ckchs->conf = cc;
-
-                               entry->node.key = ckchs;
-                               entry->crtlist = newlist;
-                               ebpt_insert(&newlist->entries, &entry->node);
-                               LIST_APPEND(&newlist->ord_entries, &entry->by_crtlist);
-                               LIST_APPEND(&ckchs->crtlist_entry, &entry->by_ckch_store);
-
-                       } else if (global_ssl.extra_files & SSL_GF_BUNDLE) {
-                               /* If we didn't find the file, this could be a
-                               bundle, since 2.3 we don't support multiple
-                               certificate in the same OpenSSL store, 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", crt_path, SSL_SOCK_KEYTYPE_NAMES[n]);
-                                       if (ret > sizeof(fp))
-                                               continue;
-
-                                       ckchs = ckchs_lookup(fp);
-                                       if (!ckchs) {
-                                               if (stat(fp, &buf) == 0) {
-
-                                                       if (cc.used) {
-                                                               memprintf(err, "%sCan't load '%s'. Using crt-store keyword is not compatible with multi certificates bundle.\n",
-                                                                         err && *err ? *err : "", crt_path);
-                                                               cfgerr |= ERR_ALERT | ERR_FATAL;
-                                                       }
-                                                       ckchs = ckch_store_new_load_files_path(fp, err);
-                                                       if (!ckchs) {
-                                                               cfgerr |= ERR_ALERT | ERR_FATAL;
-                                                               goto error;
-                                                       }
-                                               } else {
-                                                       continue; /* didn't find this extension, skip */
-                                               }
-                                       }
-                                       found++;
-                                       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_APPEND(&newlist->ord_entries, &entry_dup->by_crtlist);
-                                       LIST_APPEND(&ckchs->crtlist_entry, &entry_dup->by_ckch_store);
-
-                                       entry_dup = NULL; /* the entry was used, we need a new one next round */
-                               }
-#if HA_OPENSSL_VERSION_NUMBER < 0x10101000L
-                               if (found) {
-                                       memprintf(err, "%sCan't load '%s'. Loading a multi certificates bundle requires OpenSSL >= 1.1.1\n",
-                                                 err && *err ? *err : "", crt_path);
-                                       cfgerr |= ERR_ALERT | ERR_FATAL;
-                               }
-#endif
-                       }
-                       if (!found) {
-                               memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
-                                         err && *err ? *err : "", crt_path, strerror(errno));
-                               cfgerr |= ERR_ALERT | ERR_FATAL;
-                       }
-
-               } else {
-                       if (ckch_conf_cmp(&ckchs->conf, &cc, err) != 0) {
-                               memprintf(err, "'%s' in crt-list '%s' line %d, is already defined with incompatible parameters:\n %s", crt_path, file, linenum, err ? *err : "");
-                               cfgerr |= ERR_ALERT | ERR_FATAL;
-                               goto error;
-                       }
-
-                       entry->node.key = ckchs;
-                       entry->crtlist = newlist;
+               cfgerr |= crtlist_load_crt(crt_path, &cc, newlist, entry, file, linenum, err);
+               if (cfgerr & ERR_CODE)
+                       goto error;
 
-                       ebpt_insert(&newlist->entries, &entry->node);
-                       LIST_APPEND(&newlist->ord_entries, &entry->by_crtlist);
-                       LIST_APPEND(&ckchs->crtlist_entry, &entry->by_ckch_store);
-                       found++;
-               }
-               entry = NULL;
        }
 
        if (missing_lf != -1) {