BUG/MINOR: ssl: Prevent removal of crt-list line if the instance is a default one

If the first active line of a crt-list file is also the first mentioned
certificate of a frontend that does not have the strict-sni option
enabled, then its certificate will be used as the default one. We then
do not want this instance to be removable since it would make a frontend
lose its default certificate.
Considering that a crt-list file can be used by multiple frontends, and
that its first mentioned certificate can be used as default certificate
for only a subset of those frontends, we do not want the line to be
removable for some frontends and not the others. So if any of the ckch
instances corresponding to a crt-list line is a default instance, the
removal of the crt-list line will be forbidden.

It can be backported as far as 2.2.

(cherry picked from commit bc2c386992decb1ec8b0096f0b2ffd860e9cd559)
Signed-off-by: William Lallemand <wlallemand@haproxy.org>
diff --git a/src/ssl_crtlist.c b/src/ssl_crtlist.c
index 976e4be..e7bbc82 100644
--- a/src/ssl_crtlist.c
+++ b/src/ssl_crtlist.c
@@ -1314,6 +1314,7 @@
 	int linenum = 0;
 	char *colons;
 	char *end;
+	int error_message_dumped = 0;
 
 	if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
 		return 1;
@@ -1394,6 +1395,20 @@
 		goto error;
 	}
 
+	/* Iterate over all the instances in order to see if any of them is a
+	 * default instance. If this is the case, the entry won't be suppressed. */
+	list_for_each_entry_safe(inst, inst_s, &entry->ckch_inst, by_crtlist_entry) {
+		if (inst->is_default && !inst->bind_conf->strict_sni) {
+			if (!error_message_dumped) {
+				memprintf(&err, "certificate '%s' cannot be deleted, it is used as default certificate by the following frontends:\n", cert_path);
+				error_message_dumped = 1;
+			}
+			memprintf(&err, "%s\t- %s:%d\n", err, inst->bind_conf->file, inst->bind_conf->line);
+		}
+	}
+	if (error_message_dumped)
+		goto error;
+
 	/* upon error free the ckch_inst and everything inside */
 
 	ebpt_delete(&entry->node);