Browse Source

[mod_gnutls,fetch api] associate sni certs with dh params, fix fetch bug

personal/stbuehler/wip
Stefan Bühler 9 years ago
parent
commit
85fc9dbb6d
  1. 4
      src/common/fetch.c
  2. 122
      src/modules/mod_gnutls.c

4
src/common/fetch.c

@ -28,7 +28,7 @@ struct liFetchEntryP {
liFetchEntry public;
gint state; /* atomic access, write only with db->lock */
GQueue wait_queue; /* <liJobRef> */
GQueue wait_queue; /* <liFetchWaitElement links> */
liFetchEntryP *refreshing;
GList lru_link; /* only in LI_ENTRY_VALID state */
};
@ -608,7 +608,7 @@ create_new_entry:
goto out;
}
wakeup_add_job(&pentry_new->wait_queue, wakeup, wakeup_data);
wakeup_add_job(&pentry->wait_queue, wakeup, wakeup_data);
*wait = (liFetchWait*) pentry;
}

122
src/modules/mod_gnutls.c

@ -21,14 +21,65 @@ LI_API gboolean mod_gnutls_free(liModules *mods, liModule *mod);
static int load_dh_params_4096(gnutls_dh_params_t *dh_params);
typedef struct mod_connection_ctx mod_connection_ctx;
typedef struct mod_context mod_context;
struct mod_connection_ctx {
gnutls_session_t session;
liConnection *con;
mod_context *ctx;
liGnuTLSFilter *tls_filter;
liIOStream *sock_stream;
gpointer simple_socket_data;
#ifdef USE_SNI
liStream *sni_stream;
liJob sni_job;
liJobRef *sni_jobref;
liFetchEntry *sni_entry;
liFetchWait *sni_db_wait;
GString *sni_server_name;
#endif
};
struct mod_context {
gint refcount;
liSSLSessionDB *session_db;
gnutls_certificate_credentials_t server_cert;
gnutls_dh_params_t dh_params;
gnutls_priority_t server_priority;
gnutls_priority_t server_priority_beast;
#ifdef HAVE_SESSION_TICKET
gnutls_datum_t ticket_key;
#endif
#ifdef USE_SNI
liFetchDatabase *sni_db, *sni_backend_db;
gnutls_certificate_credentials_t sni_fallback_cert;
#endif
unsigned int protect_against_beast:1;
};
#ifdef USE_SNI
typedef struct fetch_cert_backend_lookup fetch_cert_backend_lookup;
struct fetch_cert_backend_lookup {
liFetchDatabase *backend;
liFetchWait *wait;
liFetchEntry *entry;
mod_context *ctx;
};
#endif
static void mod_gnutls_context_release(mod_context *ctx);
static void mod_gnutls_context_acquire(mod_context *ctx);
static gnutls_certificate_credentials_t creds_from_gstring(GString *str) {
#ifdef USE_SNI
static gnutls_certificate_credentials_t creds_from_gstring(mod_context *ctx, GString *str) {
gnutls_certificate_credentials_t creds = NULL;
gnutls_datum_t pemfile;
int r;
@ -44,6 +95,8 @@ static gnutls_certificate_credentials_t creds_from_gstring(GString *str) {
goto error_free_creds;
}
gnutls_certificate_set_dh_params(creds, ctx->dh_params);
return creds;
error_free_creds:
@ -55,14 +108,14 @@ static void fetch_cert_backend_ready(gpointer data) {
liFetchEntry *be;
fetch_cert_backend_lookup *lookup = (fetch_cert_backend_lookup*) data;
be = li_fetch_get2(lookup->backend, lookup->entry->key, fetch_cert_backend_ready, lookup, &lookup->wait);
be = li_fetch_get2(lookup->ctx->sni_backend_db, lookup->entry->key, fetch_cert_backend_ready, lookup, &lookup->wait);
if (NULL != be) {
liFetchEntry *entry = lookup->entry;
li_fetch_database_release(lookup->backend);
mod_context *ctx = lookup->ctx;
g_slice_free(fetch_cert_backend_lookup, lookup);
entry->backend_data = be;
entry->data = creds_from_gstring((GString*) be->data);
entry->data = creds_from_gstring(ctx, (GString*) be->data);
li_fetch_entry_ready(entry);
}
}
@ -71,8 +124,7 @@ static void fetch_cert_lookup(liFetchDatabase* db, gpointer data, liFetchEntry *
fetch_cert_backend_lookup *lookup = g_slice_new0(fetch_cert_backend_lookup);
UNUSED(db);
lookup->backend = (liFetchDatabase*) data;
li_fetch_database_acquire(lookup->backend);
lookup->ctx = (mod_context*) data;
lookup->entry = entry;
fetch_cert_backend_ready(lookup);
}
@ -93,8 +145,8 @@ static void fetch_cert_free_entry(gpointer data, liFetchEntry *entry) {
li_fetch_entry_release((liFetchEntry*) entry->backend_data);
}
static void fetch_cert_free_db(gpointer data) {
liFetchDatabase *backend = (liFetchDatabase*) data;
li_fetch_database_release(backend);
mod_context *ctx = (mod_context*) data;
mod_gnutls_context_release(ctx);
}
@ -105,52 +157,8 @@ static const liFetchCallbacks fetch_cert_callbacks = {
fetch_cert_free_entry,
fetch_cert_free_db
};
typedef struct mod_connection_ctx mod_connection_ctx;
typedef struct mod_context mod_context;
struct mod_connection_ctx {
gnutls_session_t session;
liConnection *con;
mod_context *ctx;
liGnuTLSFilter *tls_filter;
liIOStream *sock_stream;
gpointer simple_socket_data;
#ifdef USE_SNI
liStream *sni_stream;
liJob sni_job;
liJobRef *sni_jobref;
liFetchEntry *sni_entry;
liFetchWait *sni_db_wait;
GString *sni_server_name;
#endif
};
struct mod_context {
gint refcount;
liSSLSessionDB *session_db;
gnutls_certificate_credentials_t server_cert;
gnutls_dh_params_t dh_params;
gnutls_priority_t server_priority;
gnutls_priority_t server_priority_beast;
#ifdef HAVE_SESSION_TICKET
gnutls_datum_t ticket_key;
#endif
#ifdef USE_SNI
liFetchDatabase *sni_db;
gnutls_certificate_credentials_t sni_fallback_cert;
#endif
unsigned int protect_against_beast:1;
};
static void mod_gnutls_context_release(mod_context *ctx) {
if (!ctx) return;
@ -176,6 +184,10 @@ static void mod_gnutls_context_release(mod_context *ctx) {
li_fetch_database_release(ctx->sni_db);
ctx->sni_db = NULL;
}
if (NULL != ctx->sni_backend_db) {
li_fetch_database_release(ctx->sni_backend_db);
ctx->sni_backend_db = NULL;
}
if (NULL != ctx->sni_fallback_cert) {
gnutls_certificate_free_credentials(ctx->sni_fallback_cert);
ctx->sni_fallback_cert = NULL;
@ -671,7 +683,9 @@ static gboolean gnutls_setup(liServer *srv, liPlugin* p, liValue *val, gpointer
ERROR(srv, "gnutls: no fetch backend with name '%s' registered", sni_backend);
goto error_free_ctx;
}
ctx->sni_db = li_fetch_database_new(&fetch_cert_callbacks, backend, 64, 16);
ctx->sni_backend_db = backend;
mod_gnutls_context_acquire(ctx);
ctx->sni_db = li_fetch_database_new(&fetch_cert_callbacks, ctx, 64, 16);
}
if (NULL != sni_fallback_pemfile) {

Loading…
Cancel
Save