BUG/MEDIUM: ssl/crt-list: fix error when no file found

When a file from a crt-list was not found, this one was ignored silently
letting HAProxy starts without it.

This bug was introduced by 47da821 ("MEDIUM: ssl: emulates the
multi-cert bundles in the crtlist").

This commit adds a found variable which is checked once we tried every
bundle combination so we can exits with an error if none were found.

Must be backported in 2.3.

(cherry picked from commit 77e1c6fb0a5c5704315f05162f9a964bd8689c41)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
diff --git a/src/ssl_crtlist.c b/src/ssl_crtlist.c
index 8e9e5a1..f72f60e 100644
--- a/src/ssl_crtlist.c
+++ b/src/ssl_crtlist.c
@@ -471,6 +471,7 @@
 		char *crt_path;
 		char path[MAXPATHLEN+1];
 		struct ckch_store *ckchs;
+		int found = 0;
 
 		if (missing_lf != -1) {
 			memprintf(err, "parsing [%s:%d]: Stray NUL character at position %d.\n",
@@ -537,6 +538,7 @@
 		ckchs = ckchs_lookup(crt_path);
 		if (ckchs == NULL) {
 			if (stat(crt_path, &buf) == 0) {
+				found++;
 
 				ckchs = ckchs_load_cert_file(crt_path, err);
 				if (ckchs == NULL) {
@@ -569,41 +571,51 @@
 						continue;
 
 					ckchs = ckchs_lookup(fp);
-					if (!ckchs && stat(fp, &buf) == 0) {
-
-						ckchs = ckchs_load_cert_file(fp, 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) {
+					if (!ckchs) {
+						if (stat(fp, &buf) == 0) {
+							ckchs = ckchs_load_cert_file(fp, err);
+							if (!ckchs) {
 								cfgerr |= ERR_ALERT | ERR_FATAL;
 								goto error;
 							}
-							entry_dup->linenum = linenum;
+						} 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_ADDQ(&newlist->ord_entries, &entry_dup->by_crtlist);
-						LIST_ADDQ(&ckchs->crtlist_entry, &entry_dup->by_ckch_store);
+					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 */
-					}
+					entry_dup = NULL; /* the entry was used, we need a new one next round */
 				}
 			}
+			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 {
 			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);
+			found++;
 		}
 		entry = NULL;
 	}