Hi again,

of course i forgot to attach the patch...


Kind regards,
Julian
diff --git a/include/types/ssl_sock.h b/include/types/ssl_sock.h
index 2e02631c..76073f37 100644
--- a/include/types/ssl_sock.h
+++ b/include/types/ssl_sock.h
@@ -71,4 +71,14 @@ struct sh_ssl_sess_hdr {
 	unsigned char key_data[SSL_MAX_SSL_SESSION_ID_LENGTH];
 };
 
+/* shared ssl ctx */
+struct shared_ssl_ctx {
+	struct list list; /* Used to chain refs. */
+	char *path;
+    SSL_CTX *ctx;
+	int refcount;  /* number of users of this shared_ssl_ctx. */
+	__decl_hathreads(HA_RWLOCK_T lock); /* lock used to protect the ref */
+    enum { loaded, prepared } state;
+};
+
 #endif /* _TYPES_SSL_SOCK_H */
diff --git a/src/ssl_sock.c b/src/ssl_sock.c
index d26ee789..823eda69 100644
--- a/src/ssl_sock.c
+++ b/src/ssl_sock.c
@@ -330,6 +330,7 @@ const char *SSL_SOCK_KEYTYPE_NAMES[] = {
 
 static struct shared_context *ssl_shctx = NULL; /* ssl shared session cache */
 static struct eb_root *sh_ssl_sess_tree; /* ssl shared session tree */
+static struct list shared_ssl_ctx_list = LIST_HEAD_INIT(shared_ssl_ctx_list); /* list of shared ssl ctxs */
 
 #define sh_ssl_sess_tree_delete(s)	ebmb_delete(&(s)->key);
 
@@ -910,6 +911,27 @@ int ssl_sock_update_tlskey(char *filename, struct buffer *tlskey, char **err)
 	return 0;
 }
 
+
+struct shared_ssl_ctx *shared_ssl_ctx_lookup_name(const char* path)
+{
+        struct shared_ssl_ctx *ss_ctx;
+
+        list_for_each_entry(ss_ctx, &shared_ssl_ctx_list, list)
+                if (ss_ctx->path && strcmp(path, ss_ctx->path) == 0)
+                        return ss_ctx;
+        return NULL;
+}
+
+struct shared_ssl_ctx *shared_ssl_ctx_lookup_ctx(SSL_CTX *ctx)
+{
+        struct shared_ssl_ctx *ss_ctx;
+
+        list_for_each_entry(ss_ctx, &shared_ssl_ctx_list, list)
+                if (ss_ctx->ctx && ctx == ss_ctx->ctx)
+                        return ss_ctx;
+        return NULL;
+}
+
 /* This function finalize the configuration parsing. Its set all the
  * automatic ids. It's called just after the basic checks. It returns
  * 0 on success otherwise ERR_*.
@@ -3322,20 +3344,30 @@ static int ssl_sock_load_cert_file(const char *path, struct bind_conf *bind_conf
 {
 	int ret;
 	SSL_CTX *ctx;
-
-	ctx = SSL_CTX_new(SSLv23_server_method());
-	if (!ctx) {
-		memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
-		          err && *err ? *err : "", path);
-		return 1;
-	}
-
-	if (SSL_CTX_use_PrivateKey_file(ctx, path, SSL_FILETYPE_PEM) <= 0) {
-		memprintf(err, "%sunable to load SSL private key from PEM file '%s'.\n",
-		          err && *err ? *err : "", path);
-		SSL_CTX_free(ctx);
-		return 1;
-	}
+    struct shared_ssl_ctx *ss_ctx;
+
+	ss_ctx = shared_ssl_ctx_lookup_name(path);
+    if(ss_ctx /* FIXME cfg */ ) {
+		ss_ctx->refcount++; /* FIXME lock needed? */
+        ss_ctx->state = loaded;
+        ctx = ss_ctx->ctx;
+    }
+
+    if(!ss_ctx) {
+        ctx = SSL_CTX_new(SSLv23_server_method());
+        if (!ctx) {
+            memprintf(err, "%sunable to allocate SSL context for cert '%s'.\n",
+                      err && *err ? *err : "", path);
+            return 1;
+        }
+
+        if (SSL_CTX_use_PrivateKey_file(ctx, path, SSL_FILETYPE_PEM) <= 0) {
+            memprintf(err, "%sunable to load SSL private key from PEM file '%s'.\n",
+                      err && *err ? *err : "", path);
+            SSL_CTX_free(ctx);
+            return 1;
+        }
+    }
 
 	ret = ssl_sock_load_cert_chain_file(ctx, path, bind_conf, ssl_conf, sni_filter, fcount);
 	if (ret <= 0) {
@@ -3346,54 +3378,73 @@ static int ssl_sock_load_cert_file(const char *path, struct bind_conf *bind_conf
 		return 1;
 	}
 
-	if (SSL_CTX_check_private_key(ctx) <= 0) {
+	if (!ss_ctx && SSL_CTX_check_private_key(ctx) <= 0) {
 		memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
 		          err && *err ? *err : "", path);
 		return 1;
 	}
 
-	/* we must not free the SSL_CTX anymore below, since it's already in
-	 * the tree, so it will be discovered and cleaned in time.
-	 */
+    if(!ss_ctx) {
+        /* we must not free the SSL_CTX anymore below, since it's already in
+         * the tree, so it will be discovered and cleaned in time.
+         */
 #ifndef OPENSSL_NO_DH
-	/* store a NULL pointer to indicate we have not yet loaded
-	   a custom DH param file */
-	if (ssl_dh_ptr_index >= 0) {
-		SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, NULL);
-	}
+        /* store a NULL pointer to indicate we have not yet loaded
+           a custom DH param file */
+        if (ssl_dh_ptr_index >= 0) {
+            SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, NULL);
+        }
 
-	ret = ssl_sock_load_dh_params(ctx, path);
-	if (ret < 0) {
-		if (err)
-			memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
-				  *err ? *err : "", path);
-		return 1;
-	}
+        ret = ssl_sock_load_dh_params(ctx, path);
+        if (ret < 0) {
+            if (err)
+                memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
+                      *err ? *err : "", path);
+            return 1;
+        }
 #endif
 
 #if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
-	ret = ssl_sock_load_ocsp(ctx, path);
-	if (ret < 0) {
-		if (err)
-			memprintf(err, "%s '%s.ocsp' is present and activates OCSP but it is impossible to compute the OCSP certificate ID (maybe the issuer could not be found)'.\n",
-				  *err ? *err : "", path);
-		return 1;
-	}
+        ret = ssl_sock_load_ocsp(ctx, path);
+        if (ret < 0) {
+            if (err)
+                memprintf(err, "%s '%s.ocsp' is present and activates OCSP but it is impossible to compute the OCSP certificate ID (maybe the issuer could not be found)'.\n",
+                      *err ? *err : "", path);
+            return 1;
+        }
 #elif (defined OPENSSL_IS_BORINGSSL)
-	ssl_sock_set_ocsp_response_from_file(ctx, path);
+        ssl_sock_set_ocsp_response_from_file(ctx, path);
 #endif
 
 #if (OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined OPENSSL_NO_TLSEXT && !defined OPENSSL_IS_BORINGSSL && !defined LIBRESSL_VERSION_NUMBER)
-	if (sctl_ex_index >= 0) {
-		ret = ssl_sock_load_sctl(ctx, path);
-		if (ret < 0) {
-			if (err)
-				memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
-					  *err ? *err : "", path);
-			return 1;
-		}
-	}
-#endif
+        if (sctl_ex_index >= 0) {
+            ret = ssl_sock_load_sctl(ctx, path);
+            if (ret < 0) {
+                if (err)
+                    memprintf(err, "%s '%s.sctl' is present but cannot be read or parsed'.\n",
+                          *err ? *err : "", path);
+                return 1;
+            }
+        }
+#endif
+
+        /* FIXME if config */ {
+            ss_ctx = malloc(sizeof(*ss_ctx));
+            if(!ss_ctx) {
+                memprintf(err, "out of memory.\n");
+                return 1;
+            }
+            ss_ctx->path = strdup(path);
+            if(!ss_ctx->path) {
+                memprintf(err, "out of memory.\n");
+                return 1;
+            }
+            ss_ctx->refcount = 1;
+            /* FIXME need lock? */
+            ss_ctx->ctx = ctx;
+            LIST_ADD(&shared_ssl_ctx_list, &ss_ctx->list);
+        }
+	} // FIXME ss_ctx.state
 
 #ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
 	if (bind_conf->default_ctx) {
@@ -4079,6 +4130,13 @@ int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_
 	struct ssl_bind_conf __maybe_unused *ssl_conf_cur;
 	const char *conf_ciphers;
 	const char *conf_curves = NULL;
+    struct shared_ssl_ctx *ss_ctx;
+
+	ss_ctx = shared_ssl_ctx_lookup_ctx(ctx);
+    if(ss_ctx && ss_ctx->state == prepared ) {
+        return cfgerr;
+    }
+
 
 	if (ssl_conf) {
 		struct tls_version_filter *conf_ssl_methods = &ssl_conf->ssl_methods;
@@ -4310,6 +4368,9 @@ int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_
 	}
 #endif
 
+    if(ss_ctx) {
+        ss_ctx->state = prepared;
+    }
 	return cfgerr;
 }
 

Reply via email to