MEDIUM: ssl: Chain ckch instances in ca-file entries

Each ca-file entry of the tree will now hold a list of the ckch
instances that use it so that we can iterate over them when updating the
ca-file via a cli command. Since the link between the SSL contexts and
the CA file tree entries is only built during the ssl_sock_prepare_ctx
function, which are called after all the ckch instances are created, we
need to add a little post processing after each ssl_sock_prepare_ctx
that builds the link between the corresponding ckch instance and CA file
tree entries.
In order to manage the ca-file and ca-verify-file options, any ckch
instance can be linked to multiple CA file tree entries and any CA file
entry can link multiple ckch instances. This is done thanks to a
dedicated list of ckch_inst references stored in the CA file tree
entries over which we can iterate (during an update for instance). We
avoid having one of those instances go stale by keeping a list of
references to those references in the instances.
When deleting a ckch_inst, we can then remove all the ckch_inst_link
instances that reference it, and when deleting a cafile_entry, we
iterate over the list of ckch_inst reference and clear the corresponding
entry in their own list of ckch_inst_link references.
diff --git a/src/ssl_sock.c b/src/ssl_sock.c
index 0fc3388..8f9f535 100644
--- a/src/ssl_sock.c
+++ b/src/ssl_sock.c
@@ -320,7 +320,9 @@
 static int ssl_set_cert_crl_file(X509_STORE *store_ctx, char *path)
 {
 	X509_STORE *store;
-	store = ssl_store_get0_locations_file(path);
+	struct cafile_entry *ca_e = ssl_store_get_cafile_entry(path, 0);
+	if (ca_e)
+		store = ca_e->ca_store;
 	if (store_ctx && store) {
 		int i;
 		X509_OBJECT *obj;
@@ -4218,7 +4220,7 @@
  * This function applies the SSL configuration on a SSL_CTX
  * It returns an error code and fills the <err> buffer
  */
-int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf, SSL_CTX *ctx, char **err)
+static int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf, SSL_CTX *ctx, char **err)
 {
 	struct proxy *curproxy = bind_conf->frontend;
 	int cfgerr = 0;
@@ -4444,6 +4446,28 @@
 	return cfgerr;
 }
 
+
+/*
+ * Prepare the SSL_CTX based on the bind line configuration.
+ * Since the CA file loading is made depending on the verify option of the bind
+ * line, the link between the SSL_CTX and the CA file tree entry is made here.
+ * If we want to create a link between the CA file entry and the corresponding
+ * ckch instance (for CA file hot update), it needs to be done after
+ * ssl_sock_prepare_ctx.
+ * Returns 0 in case of success.
+ */
+int ssl_sock_prep_ctx_and_inst(struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_conf,
+			       SSL_CTX *ctx, struct ckch_inst *ckch_inst, char **err)
+{
+	int errcode = 0;
+
+	errcode |= ssl_sock_prepare_ctx(bind_conf, ssl_conf, ctx, err);
+	if (!errcode && ckch_inst)
+		ckch_inst_add_cafile_link(ckch_inst, bind_conf, ssl_conf, NULL);
+
+	return errcode;
+}
+
 static int ssl_sock_srv_hostcheck(const char *pattern, const char *hostname)
 {
 	const char *pattern_wildcard, *pattern_left_label_end, *hostname_left_label_end;
@@ -4631,16 +4655,15 @@
 		srv->ssl_ctx.ctx = ctx;
 	}
 
-	cfgerr += ssl_sock_prepare_srv_ssl_ctx(srv, srv->ssl_ctx.ctx);
+	cfgerr += ssl_sock_prep_srv_ctx_and_inst(srv, srv->ssl_ctx.ctx, srv->ssl_ctx.inst);
 
 	return cfgerr;
 }
 
-
 /* Initialize an SSL context that will be used on the backend side.
  * Returns an error count.
  */
-int ssl_sock_prepare_srv_ssl_ctx(const struct server *srv, SSL_CTX *ctx)
+static int ssl_sock_prepare_srv_ssl_ctx(const struct server *srv, SSL_CTX *ctx)
 {
 	struct proxy *curproxy = srv->proxy;
 	int cfgerr = 0;
@@ -4804,10 +4827,33 @@
 		SSL_CTX_set_alpn_protos(ctx, (unsigned char *)srv->ssl_ctx.alpn_str, srv->ssl_ctx.alpn_len);
 #endif
 
+
+	return cfgerr;
+}
+
+/*
+ * Prepare the frontend's SSL_CTX based on the server line configuration.
+ * Since the CA file loading is made depending on the verify option of the
+ * server line, the link between the SSL_CTX and the CA file tree entry is
+ * made here.
+ * If we want to create a link between the CA file entry and the corresponding
+ * ckch instance (for CA file hot update), it needs to be done after
+ * ssl_sock_prepare_srv_ssl_ctx.
+ * Returns an error count.
+ */
+int ssl_sock_prep_srv_ctx_and_inst(const struct server *srv, SSL_CTX *ctx,
+				   struct ckch_inst *ckch_inst)
+{
+	int cfgerr = 0;
+
+	cfgerr += ssl_sock_prepare_srv_ssl_ctx(srv, ctx);
+	if (!cfgerr && ckch_inst)
+		ckch_inst_add_cafile_link(ckch_inst, NULL, NULL, srv);
 
 	return cfgerr;
 }
 
+
 /*
  * Create an initial CTX used to start the SSL connections.
  * May be used by QUIC xprt which makes usage of SSL sessions initialized from SSL_CTXs.
@@ -4854,18 +4900,20 @@
 		/* It should not be necessary to call this function, but it's
 		   necessary first to check and move all initialisation related
 		   to initial_ctx in ssl_initial_ctx. */
-		errcode |= ssl_sock_prepare_ctx(bind_conf, NULL, bind_conf->initial_ctx, &errmsg);
+		errcode |= ssl_sock_prep_ctx_and_inst(bind_conf, NULL, bind_conf->initial_ctx, NULL, &errmsg);
+	}
+	if (bind_conf->default_ctx) {
+		errcode |= ssl_sock_prep_ctx_and_inst(bind_conf, bind_conf->default_ssl_conf, bind_conf->default_ctx, NULL, &errmsg);
 	}
-	if (bind_conf->default_ctx)
-		errcode |= ssl_sock_prepare_ctx(bind_conf, bind_conf->default_ssl_conf, bind_conf->default_ctx, &errmsg);
 
 	node = ebmb_first(&bind_conf->sni_ctx);
 	while (node) {
 		sni = ebmb_entry(node, struct sni_ctx, name);
-		if (!sni->order && sni->ctx != bind_conf->default_ctx)
+		if (!sni->order && sni->ctx != bind_conf->default_ctx) {
 			/* only initialize the CTX on its first occurrence and
 			   if it is not the default_ctx */
-			errcode |= ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx, &errmsg);
+			errcode |= ssl_sock_prep_ctx_and_inst(bind_conf, sni->conf, sni->ctx, sni->ckch_inst, &errmsg);
+		}
 		node = ebmb_next(node);
 	}
 
@@ -4875,7 +4923,7 @@
 		if (!sni->order && sni->ctx != bind_conf->default_ctx) {
 			/* only initialize the CTX on its first occurrence and
 			   if it is not the default_ctx */
-			errcode |= ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx, &errmsg);
+			errcode |= ssl_sock_prep_ctx_and_inst(bind_conf, sni->conf, sni->ctx, sni->ckch_inst, &errmsg);
 		}
 		node = ebmb_next(node);
 	}