|
|
|
@ -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) {
|
|
|
|
|