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