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.
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;
 	}