CLEANUP: ssl: separate the directory loading in a new function
In order to store and cache the directory loading, the directory loading
was separated from ssl_sock_load_cert() and put in a new function
ssl_sock_load_cert_dir() to be more readable.
This patch only splits the function in two.
diff --git a/src/ssl_sock.c b/src/ssl_sock.c
index ef3091e..1a98e2a 100644
--- a/src/ssl_sock.c
+++ b/src/ssl_sock.c
@@ -4427,9 +4427,9 @@
return errcode;
}
-
-/* Returns a set of ERR_* flags possibly with an error in <err>. */
-int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, char **err)
+/* Read a directory and open its certificates
+ * Returns a set of ERR_* flags possibly with an error in <err>. */
+static int ssl_sock_load_cert_dir(char *path, struct bind_conf *bind_conf, char **err)
{
struct dirent **de_list;
int i, n;
@@ -4442,106 +4442,115 @@
int is_bundle;
int j;
#endif
- if ((ckchs = ckchs_lookup(path))) {
- /* we found the ckchs in the tree, we can use it directly */
- return ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
- }
-
- if (stat(path, &buf) == 0) {
- if (S_ISDIR(buf.st_mode) == 0) {
- ckchs = ckchs_load_cert_file(path, 0, err);
- if (!ckchs)
- return ERR_ALERT | ERR_FATAL;
- return ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
- }
+ /* strip trailing slashes, including first one */
+ for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
+ *end = 0;
- /* strip trailing slashes, including first one */
- for (end = path + strlen(path) - 1; end >= path && *end == '/'; end--)
- *end = 0;
-
- n = scandir(path, &de_list, 0, alphasort);
- if (n < 0) {
- memprintf(err, "%sunable to scan directory '%s' : %s.\n",
- err && *err ? *err : "", path, strerror(errno));
- cfgerr |= ERR_ALERT | ERR_FATAL;
- }
- else {
- for (i = 0; i < n; i++) {
- struct dirent *de = de_list[i];
+ n = scandir(path, &de_list, 0, alphasort);
+ if (n < 0) {
+ memprintf(err, "%sunable to scan directory '%s' : %s.\n",
+ err && *err ? *err : "", path, strerror(errno));
+ cfgerr |= ERR_ALERT | ERR_FATAL;
+ }
+ else {
+ for (i = 0; i < n; i++) {
+ struct dirent *de = de_list[i];
- end = strrchr(de->d_name, '.');
- if (end && (!strcmp(end, ".issuer") || !strcmp(end, ".ocsp") || !strcmp(end, ".sctl") || !strcmp(end, ".key")))
- goto ignore_entry;
+ end = strrchr(de->d_name, '.');
+ if (end && (!strcmp(end, ".issuer") || !strcmp(end, ".ocsp") || !strcmp(end, ".sctl") || !strcmp(end, ".key")))
+ goto ignore_entry;
- snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
- if (stat(fp, &buf) != 0) {
- memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
- err && *err ? *err : "", fp, strerror(errno));
- cfgerr |= ERR_ALERT | ERR_FATAL;
- goto ignore_entry;
- }
- if (!S_ISREG(buf.st_mode))
- goto ignore_entry;
+ snprintf(fp, sizeof(fp), "%s/%s", path, de->d_name);
+ if (stat(fp, &buf) != 0) {
+ memprintf(err, "%sunable to stat SSL certificate from file '%s' : %s.\n",
+ err && *err ? *err : "", fp, strerror(errno));
+ cfgerr |= ERR_ALERT | ERR_FATAL;
+ goto ignore_entry;
+ }
+ if (!S_ISREG(buf.st_mode))
+ goto ignore_entry;
#if HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL
- is_bundle = 0;
- /* Check if current entry in directory is part of a multi-cert bundle */
+ is_bundle = 0;
+ /* Check if current entry in directory is part of a multi-cert bundle */
- if ((global_ssl.extra_files & SSL_GF_BUNDLE) && end) {
- for (j = 0; j < SSL_SOCK_NUM_KEYTYPES; j++) {
- if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
- is_bundle = 1;
- break;
- }
+ if ((global_ssl.extra_files & SSL_GF_BUNDLE) && end) {
+ for (j = 0; j < SSL_SOCK_NUM_KEYTYPES; j++) {
+ if (!strcmp(end + 1, SSL_SOCK_KEYTYPE_NAMES[j])) {
+ is_bundle = 1;
+ break;
}
-
- if (is_bundle) {
- int dp_len;
+ }
- dp_len = end - de->d_name;
+ if (is_bundle) {
+ int dp_len;
- /* increment i and free de until we get to a non-bundle cert
- * Note here that we look at de_list[i + 1] before freeing de
- * this is important since ignore_entry will free de. This also
- * guarantees that de->d_name continues to hold the same prefix.
- */
- while (i + 1 < n && !strncmp(de_list[i + 1]->d_name, de->d_name, dp_len)) {
- free(de);
- i++;
- de = de_list[i];
- }
+ dp_len = end - de->d_name;
- snprintf(fp, sizeof(fp), "%s/%.*s", path, dp_len, de->d_name);
- if ((ckchs = ckchs_lookup(fp)) == NULL)
- ckchs = ckchs_load_cert_file(fp, 1, err);
- if (!ckchs)
- cfgerr |= ERR_ALERT | ERR_FATAL;
- else
- cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
- /* Successfully processed the bundle */
- goto ignore_entry;
+ /* increment i and free de until we get to a non-bundle cert
+ * Note here that we look at de_list[i + 1] before freeing de
+ * this is important since ignore_entry will free de. This also
+ * guarantees that de->d_name continues to hold the same prefix.
+ */
+ while (i + 1 < n && !strncmp(de_list[i + 1]->d_name, de->d_name, dp_len)) {
+ free(de);
+ i++;
+ de = de_list[i];
}
+
+ snprintf(fp, sizeof(fp), "%s/%.*s", path, dp_len, de->d_name);
+ if ((ckchs = ckchs_lookup(fp)) == NULL)
+ ckchs = ckchs_load_cert_file(fp, 1, err);
+ if (!ckchs)
+ cfgerr |= ERR_ALERT | ERR_FATAL;
+ else
+ cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
+ /* Successfully processed the bundle */
+ goto ignore_entry;
}
+ }
#endif
- if ((ckchs = ckchs_lookup(fp)) == NULL)
- ckchs = ckchs_load_cert_file(fp, 0, err);
- if (!ckchs)
- cfgerr |= ERR_ALERT | ERR_FATAL;
- else
- cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
+ if ((ckchs = ckchs_lookup(fp)) == NULL)
+ ckchs = ckchs_load_cert_file(fp, 0, err);
+ if (!ckchs)
+ cfgerr |= ERR_ALERT | ERR_FATAL;
+ else
+ cfgerr |= ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
ignore_entry:
- free(de);
- }
- free(de_list);
+ free(de);
}
- return cfgerr;
+ free(de_list);
+ }
+ return cfgerr;
+}
- } else {
- /* stat failed */
+/* Returns a set of ERR_* flags possibly with an error in <err>. */
+int ssl_sock_load_cert(char *path, struct bind_conf *bind_conf, char **err)
+{
+ struct stat buf;
+ char fp[MAXPATHLEN+1];
+ int cfgerr = 0;
+ struct ckch_store *ckchs;
+ if ((ckchs = ckchs_lookup(path))) {
+ /* we found the ckchs in the tree, we can use it directly */
+ return ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
+ }
+ if (stat(path, &buf) == 0) {
+ if (S_ISDIR(buf.st_mode) == 0) {
+ ckchs = ckchs_load_cert_file(path, 0, err);
+ if (!ckchs)
+ return ERR_ALERT | ERR_FATAL;
+
+ return ssl_sock_load_ckchs(path, ckchs, bind_conf, NULL, NULL, 0, err);
+ } else {
+ return ssl_sock_load_cert_dir(path, bind_conf, err);
+ }
+ } else {
+ /* stat failed, could be a bundle */
if (global_ssl.extra_files & SSL_GF_BUNDLE) {
/* try to load a bundle if it is permitted */
ckchs = ckchs_load_cert_file(path, 1, err);