From e02dd8c03ce5b66c81a47830eebe73a21ce71002 Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Mon, 25 Oct 2010 21:21:04 +0200 Subject: indented code --- src/gnutls_cache.c | 925 ++++++++++++------------ src/gnutls_config.c | 1039 ++++++++++++++------------- src/gnutls_hooks.c | 1944 +++++++++++++++++++++++++++------------------------ src/gnutls_io.c | 1367 ++++++++++++++++++------------------ src/gnutls_lua.c | 465 ++++++------ src/mod_gnutls.c | 253 +++---- 6 files changed, 3101 insertions(+), 2892 deletions(-) (limited to 'src') diff --git a/src/gnutls_cache.c b/src/gnutls_cache.c index 90ea440..cbf879c 100644 --- a/src/gnutls_cache.c +++ b/src/gnutls_cache.c @@ -44,18 +44,18 @@ #endif char *mgs_session_id2sz(unsigned char *id, int idlen, - char *str, int strsize) + char *str, int strsize) { - char *cp; - int n; - - cp = str; - for (n = 0; n < idlen && n < GNUTLS_MAX_SESSION_ID; n++) { - apr_snprintf(cp, strsize - (cp-str), "%02X", id[n]); - cp += 2; - } - *cp = '\0'; - return str; + char *cp; + int n; + + cp = str; + for (n = 0; n < idlen && n < GNUTLS_MAX_SESSION_ID; n++) { + apr_snprintf(cp, strsize - (cp - str), "%02X", id[n]); + cp += 2; + } + *cp = '\0'; + return str; } @@ -63,35 +63,38 @@ char *mgs_session_id2sz(unsigned char *id, int idlen, * server:port.SessionID * to disallow resuming sessions on different servers */ -static int mgs_session_id2dbm(conn_rec* c, unsigned char *id, int idlen, - apr_datum_t* dbmkey) +static int mgs_session_id2dbm(conn_rec * c, unsigned char *id, int idlen, + apr_datum_t * dbmkey) { -char buf[STR_SESSION_LEN]; -char *sz; - - sz = mgs_session_id2sz(id, idlen, buf, sizeof(buf)); - if (sz == NULL) - return -1; - - dbmkey->dptr = apr_psprintf(c->pool, "%s:%d.%s", c->base_server->server_hostname, c->base_server->port, sz); - dbmkey->dsize = strlen( dbmkey->dptr); - - return 0; + char buf[STR_SESSION_LEN]; + char *sz; + + sz = mgs_session_id2sz(id, idlen, buf, sizeof(buf)); + if (sz == NULL) + return -1; + + dbmkey->dptr = + apr_psprintf(c->pool, "%s:%d.%s", + c->base_server->server_hostname, + c->base_server->port, sz); + dbmkey->dsize = strlen(dbmkey->dptr); + + return 0; } #define CTIME "%b %d %k:%M:%S %Y %Z" char *mgs_time2sz(time_t in_time, char *str, int strsize) { - apr_time_exp_t vtm; - apr_size_t ret_size; - apr_time_t t; - - - apr_time_ansi_put (&t, in_time); - apr_time_exp_gmt (&vtm, t); - apr_strftime(str, &ret_size, strsize-1, CTIME, &vtm); - - return str; + apr_time_exp_t vtm; + apr_size_t ret_size; + apr_time_t t; + + + apr_time_ansi_put(&t, in_time); + apr_time_exp_gmt(&vtm, t); + apr_strftime(str, &ret_size, strsize - 1, CTIME, &vtm); + + return str; } #if HAVE_APR_MEMCACHE @@ -99,16 +102,18 @@ char *mgs_time2sz(time_t in_time, char *str, int strsize) * server:port.SessionID * to disallow resuming sessions on different servers */ -static char* mgs_session_id2mc(conn_rec* c, unsigned char *id, int idlen) +static char *mgs_session_id2mc(conn_rec * c, unsigned char *id, int idlen) { -char buf[STR_SESSION_LEN]; -char *sz; - - sz = mgs_session_id2sz(id, idlen, buf, sizeof(buf)); - if (sz == NULL) - return NULL; - - return apr_psprintf(c->pool, MC_TAG"%s:%d.%s", c->base_server->server_hostname, c->base_server->port, sz); + char buf[STR_SESSION_LEN]; + char *sz; + + sz = mgs_session_id2sz(id, idlen, buf, sizeof(buf)); + if (sz == NULL) + return NULL; + + return apr_psprintf(c->pool, MC_TAG "%s:%d.%s", + c->base_server->server_hostname, + c->base_server->port, sz); } /** @@ -117,482 +122,498 @@ char *sz; */ /* The underlying apr_memcache system is thread safe... woohoo */ -static apr_memcache_t* mc; +static apr_memcache_t *mc; -static int mc_cache_child_init(apr_pool_t *p, server_rec *s, - mgs_srvconf_rec *sc) +static int mc_cache_child_init(apr_pool_t * p, server_rec * s, + mgs_srvconf_rec * sc) { - apr_status_t rv = APR_SUCCESS; - int thread_limit = 0; - int nservers = 0; - char* cache_config; - char* split; - char* tok; - - ap_mpm_query(AP_MPMQ_HARD_LIMIT_THREADS, &thread_limit); - - /* Find all the servers in the first run to get a total count */ - cache_config = apr_pstrdup(p, sc->cache_config); - split = apr_strtok(cache_config, " ", &tok); - while (split) { - nservers++; - split = apr_strtok(NULL," ", &tok); - } - - rv = apr_memcache_create(p, nservers, 0, &mc); - if (rv != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, - "[gnutls_cache] Failed to create Memcache Object of '%d' size.", - nservers); - return rv; - } - - /* Now add each server to the memcache */ - cache_config = apr_pstrdup(p, sc->cache_config); - split = apr_strtok(cache_config, " ", &tok); - while (split) { - apr_memcache_server_t* st; - char* host_str; - char* scope_id; - apr_port_t port; - - rv = apr_parse_addr_port(&host_str, &scope_id, &port, split, p); - if (rv != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, - "[gnutls_cache] Failed to Parse Server: '%s'", split); - return rv; - } - - if (host_str == NULL) { - ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, - "[gnutls_cache] Failed to Parse Server, " - "no hostname specified: '%s'", split); - return rv; - } - - if (port == 0) { - port = 11211; /* default port */ - } - - /* Should Max Conns be (thread_limit / nservers) ? */ - rv = apr_memcache_server_create(p, - host_str, port, - 0, - 1, - thread_limit, - 600, - &st); - if (rv != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, - "[gnutls_cache] Failed to Create Server: %s:%d", - host_str, port); - return rv; - } - - rv = apr_memcache_add_server(mc, st); - if (rv != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, - "[gnutls_cache] Failed to Add Server: %s:%d", - host_str, port); - return rv; - } - - split = apr_strtok(NULL," ", &tok); - } - return rv; + apr_status_t rv = APR_SUCCESS; + int thread_limit = 0; + int nservers = 0; + char *cache_config; + char *split; + char *tok; + + ap_mpm_query(AP_MPMQ_HARD_LIMIT_THREADS, &thread_limit); + + /* Find all the servers in the first run to get a total count */ + cache_config = apr_pstrdup(p, sc->cache_config); + split = apr_strtok(cache_config, " ", &tok); + while (split) { + nservers++; + split = apr_strtok(NULL, " ", &tok); + } + + rv = apr_memcache_create(p, nservers, 0, &mc); + if (rv != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, + "[gnutls_cache] Failed to create Memcache Object of '%d' size.", + nservers); + return rv; + } + + /* Now add each server to the memcache */ + cache_config = apr_pstrdup(p, sc->cache_config); + split = apr_strtok(cache_config, " ", &tok); + while (split) { + apr_memcache_server_t *st; + char *host_str; + char *scope_id; + apr_port_t port; + + rv = apr_parse_addr_port(&host_str, &scope_id, &port, + split, p); + if (rv != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, + "[gnutls_cache] Failed to Parse Server: '%s'", + split); + return rv; + } + + if (host_str == NULL) { + ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, + "[gnutls_cache] Failed to Parse Server, " + "no hostname specified: '%s'", split); + return rv; + } + + if (port == 0) { + port = 11211; /* default port */ + } + + /* Should Max Conns be (thread_limit / nservers) ? */ + rv = apr_memcache_server_create(p, + host_str, port, + 0, + 1, thread_limit, 600, &st); + if (rv != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, + "[gnutls_cache] Failed to Create Server: %s:%d", + host_str, port); + return rv; + } + + rv = apr_memcache_add_server(mc, st); + if (rv != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, + "[gnutls_cache] Failed to Add Server: %s:%d", + host_str, port); + return rv; + } + + split = apr_strtok(NULL, " ", &tok); + } + return rv; } -static int mc_cache_store(void* baton, gnutls_datum_t key, - gnutls_datum_t data) +static int mc_cache_store(void *baton, gnutls_datum_t key, + gnutls_datum_t data) { - apr_status_t rv = APR_SUCCESS; - mgs_handle_t *ctxt = baton; - char* strkey = NULL; - apr_uint32_t timeout; + apr_status_t rv = APR_SUCCESS; + mgs_handle_t *ctxt = baton; + char *strkey = NULL; + apr_uint32_t timeout; - strkey = mgs_session_id2mc(ctxt->c, key.data, key.size); - if(!strkey) - return -1; + strkey = mgs_session_id2mc(ctxt->c, key.data, key.size); + if (!strkey) + return -1; - timeout = apr_time_sec(ctxt->sc->cache_timeout); + timeout = apr_time_sec(ctxt->sc->cache_timeout); - rv = apr_memcache_set(mc, strkey, data.data, data.size, timeout, 0); + rv = apr_memcache_set(mc, strkey, data.data, data.size, timeout, + 0); - if (rv != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_CRIT, rv, - ctxt->c->base_server, - "[gnutls_cache] error setting key '%s' " - "with %d bytes of data", strkey, data.size); - return -1; - } + if (rv != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_CRIT, rv, + ctxt->c->base_server, + "[gnutls_cache] error setting key '%s' " + "with %d bytes of data", strkey, data.size); + return -1; + } - return 0; + return 0; } -static gnutls_datum_t mc_cache_fetch(void* baton, gnutls_datum_t key) +static gnutls_datum_t mc_cache_fetch(void *baton, gnutls_datum_t key) { - apr_status_t rv = APR_SUCCESS; - mgs_handle_t *ctxt = baton; - char* strkey = NULL; - char* value; - apr_size_t value_len; - gnutls_datum_t data = { NULL, 0 }; - - strkey = mgs_session_id2mc(ctxt->c, key.data, key.size); - if (!strkey) { - return data; - } - - rv = apr_memcache_getp(mc, ctxt->c->pool, strkey, - &value, &value_len, NULL); - - if (rv != APR_SUCCESS) { + apr_status_t rv = APR_SUCCESS; + mgs_handle_t *ctxt = baton; + char *strkey = NULL; + char *value; + apr_size_t value_len; + gnutls_datum_t data = { NULL, 0 }; + + strkey = mgs_session_id2mc(ctxt->c, key.data, key.size); + if (!strkey) { + return data; + } + + rv = apr_memcache_getp(mc, ctxt->c->pool, strkey, + &value, &value_len, NULL); + + if (rv != APR_SUCCESS) { #if MOD_GNUTLS_DEBUG - ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, - ctxt->c->base_server, - "[gnutls_cache] error fetching key '%s' ", - strkey); + ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, + ctxt->c->base_server, + "[gnutls_cache] error fetching key '%s' ", + strkey); #endif - data.size = 0; - data.data = NULL; - return data; - } + data.size = 0; + data.data = NULL; + return data; + } - /* TODO: Eliminate this memcpy. gnutls-- */ - data.data = gnutls_malloc(value_len); - if (data.data == NULL) - return data; + /* TODO: Eliminate this memcpy. gnutls-- */ + data.data = gnutls_malloc(value_len); + if (data.data == NULL) + return data; - data.size = value_len; - memcpy(data.data, value, value_len); + data.size = value_len; + memcpy(data.data, value, value_len); - return data; + return data; } -static int mc_cache_delete(void* baton, gnutls_datum_t key) +static int mc_cache_delete(void *baton, gnutls_datum_t key) { - apr_status_t rv = APR_SUCCESS; - mgs_handle_t *ctxt = baton; - char* strkey = NULL; + apr_status_t rv = APR_SUCCESS; + mgs_handle_t *ctxt = baton; + char *strkey = NULL; - strkey = mgs_session_id2mc(ctxt->c, key.data, key.size); - if(!strkey) - return -1; + strkey = mgs_session_id2mc(ctxt->c, key.data, key.size); + if (!strkey) + return -1; - rv = apr_memcache_delete(mc, strkey, 0); + rv = apr_memcache_delete(mc, strkey, 0); - if (rv != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, - ctxt->c->base_server, - "[gnutls_cache] error deleting key '%s' ", - strkey); - return -1; - } + if (rv != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, + ctxt->c->base_server, + "[gnutls_cache] error deleting key '%s' ", + strkey); + return -1; + } - return 0; + return 0; } -#endif /* have_apr_memcache */ +#endif /* have_apr_memcache */ -const char* db_type(mgs_srvconf_rec * sc) +const char *db_type(mgs_srvconf_rec * sc) { - if (sc->cache_type == mgs_cache_gdbm) - return "gdbm"; - else - return "db"; + if (sc->cache_type == mgs_cache_gdbm) + return "gdbm"; + else + return "db"; } #define SSL_DBM_FILE_MODE ( APR_UREAD | APR_UWRITE | APR_GREAD | APR_WREAD ) -static void dbm_cache_expire(mgs_handle_t *ctxt) +static void dbm_cache_expire(mgs_handle_t * ctxt) { - apr_status_t rv; - apr_dbm_t *dbm; - apr_datum_t dbmkey; - apr_datum_t dbmval; - apr_time_t now; - apr_time_t dtime; - apr_pool_t* spool; - int total, deleted; - - now = apr_time_now(); - - if (now - ctxt->sc->last_cache_check < (ctxt->sc->cache_timeout)/2) - return; - - ctxt->sc->last_cache_check = now; - - apr_pool_create(&spool, ctxt->c->pool); - - total = 0; - deleted = 0; - - rv = apr_dbm_open_ex(&dbm, db_type(ctxt->sc), ctxt->sc->cache_config, APR_DBM_RWCREATE, - SSL_DBM_FILE_MODE, spool); - if (rv != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, - ctxt->c->base_server, - "[gnutls_cache] error opening cache searcher '%s'", - ctxt->sc->cache_config); - apr_pool_destroy(spool); - return; - } - - apr_dbm_firstkey(dbm, &dbmkey); - while (dbmkey.dptr != NULL) { - apr_dbm_fetch(dbm, dbmkey, &dbmval); - if (dbmval.dptr != NULL && dbmval.dsize >= sizeof(apr_time_t)) { - memcpy(&dtime, dbmval.dptr, sizeof(apr_time_t)); - - if (now >= dtime) { - apr_dbm_delete(dbm, dbmkey); - deleted++; - } - apr_dbm_freedatum( dbm, dbmval); - } else { - apr_dbm_delete(dbm, dbmkey); - deleted++; - } - total++; - apr_dbm_nextkey(dbm, &dbmkey); - } - apr_dbm_close(dbm); - - ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, - ctxt->c->base_server, - "[gnutls_cache] Cleaned up cache '%s'. Deleted %d and left %d", - ctxt->sc->cache_config, deleted, total-deleted); - - apr_pool_destroy(spool); - - return; + apr_status_t rv; + apr_dbm_t *dbm; + apr_datum_t dbmkey; + apr_datum_t dbmval; + apr_time_t now; + apr_time_t dtime; + apr_pool_t *spool; + int total, deleted; + + now = apr_time_now(); + + if (now - ctxt->sc->last_cache_check < + (ctxt->sc->cache_timeout) / 2) + return; + + ctxt->sc->last_cache_check = now; + + apr_pool_create(&spool, ctxt->c->pool); + + total = 0; + deleted = 0; + + rv = apr_dbm_open_ex(&dbm, db_type(ctxt->sc), + ctxt->sc->cache_config, APR_DBM_RWCREATE, + SSL_DBM_FILE_MODE, spool); + if (rv != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, + ctxt->c->base_server, + "[gnutls_cache] error opening cache searcher '%s'", + ctxt->sc->cache_config); + apr_pool_destroy(spool); + return; + } + + apr_dbm_firstkey(dbm, &dbmkey); + while (dbmkey.dptr != NULL) { + apr_dbm_fetch(dbm, dbmkey, &dbmval); + if (dbmval.dptr != NULL + && dbmval.dsize >= sizeof(apr_time_t)) { + memcpy(&dtime, dbmval.dptr, sizeof(apr_time_t)); + + if (now >= dtime) { + apr_dbm_delete(dbm, dbmkey); + deleted++; + } + apr_dbm_freedatum(dbm, dbmval); + } else { + apr_dbm_delete(dbm, dbmkey); + deleted++; + } + total++; + apr_dbm_nextkey(dbm, &dbmkey); + } + apr_dbm_close(dbm); + + ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, + ctxt->c->base_server, + "[gnutls_cache] Cleaned up cache '%s'. Deleted %d and left %d", + ctxt->sc->cache_config, deleted, total - deleted); + + apr_pool_destroy(spool); + + return; } -static gnutls_datum_t dbm_cache_fetch(void* baton, gnutls_datum_t key) +static gnutls_datum_t dbm_cache_fetch(void *baton, gnutls_datum_t key) { - gnutls_datum_t data = { NULL, 0 }; - apr_dbm_t *dbm; - apr_datum_t dbmkey; - apr_datum_t dbmval; - mgs_handle_t *ctxt = baton; - apr_status_t rv; - - if (mgs_session_id2dbm(ctxt->c, key.data, key.size, &dbmkey) < 0) - return data; - - rv = apr_dbm_open_ex(&dbm, db_type(ctxt->sc), ctxt->sc->cache_config, - APR_DBM_READONLY, SSL_DBM_FILE_MODE, ctxt->c->pool); - if (rv != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, - ctxt->c->base_server, - "[gnutls_cache] error opening cache '%s'", - ctxt->sc->cache_config); - return data; - } - - rv = apr_dbm_fetch(dbm, dbmkey, &dbmval); - - if (rv != APR_SUCCESS) { - apr_dbm_close(dbm); - return data; - } - - if (dbmval.dptr == NULL || dbmval.dsize <= sizeof(apr_time_t)) { - apr_dbm_freedatum( dbm, dbmval); - apr_dbm_close(dbm); - return data; - } - - data.size = dbmval.dsize - sizeof(apr_time_t); - - data.data = gnutls_malloc(data.size); - if (data.data == NULL) { - apr_dbm_freedatum( dbm, dbmval); - apr_dbm_close(dbm); - return data; - } - - memcpy(data.data, dbmval.dptr+sizeof(apr_time_t), data.size); - - apr_dbm_freedatum( dbm, dbmval); - apr_dbm_close(dbm); - - return data; + gnutls_datum_t data = { NULL, 0 }; + apr_dbm_t *dbm; + apr_datum_t dbmkey; + apr_datum_t dbmval; + mgs_handle_t *ctxt = baton; + apr_status_t rv; + + if (mgs_session_id2dbm(ctxt->c, key.data, key.size, &dbmkey) < 0) + return data; + + rv = apr_dbm_open_ex(&dbm, db_type(ctxt->sc), + ctxt->sc->cache_config, APR_DBM_READONLY, + SSL_DBM_FILE_MODE, ctxt->c->pool); + if (rv != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, + ctxt->c->base_server, + "[gnutls_cache] error opening cache '%s'", + ctxt->sc->cache_config); + return data; + } + + rv = apr_dbm_fetch(dbm, dbmkey, &dbmval); + + if (rv != APR_SUCCESS) { + apr_dbm_close(dbm); + return data; + } + + if (dbmval.dptr == NULL || dbmval.dsize <= sizeof(apr_time_t)) { + apr_dbm_freedatum(dbm, dbmval); + apr_dbm_close(dbm); + return data; + } + + data.size = dbmval.dsize - sizeof(apr_time_t); + + data.data = gnutls_malloc(data.size); + if (data.data == NULL) { + apr_dbm_freedatum(dbm, dbmval); + apr_dbm_close(dbm); + return data; + } + + memcpy(data.data, dbmval.dptr + sizeof(apr_time_t), data.size); + + apr_dbm_freedatum(dbm, dbmval); + apr_dbm_close(dbm); + + return data; } -static int dbm_cache_store(void* baton, gnutls_datum_t key, - gnutls_datum_t data) +static int dbm_cache_store(void *baton, gnutls_datum_t key, + gnutls_datum_t data) { - apr_dbm_t *dbm; - apr_datum_t dbmkey; - apr_datum_t dbmval; - mgs_handle_t *ctxt = baton; - apr_status_t rv; - apr_time_t expiry; - apr_pool_t* spool; - - if (mgs_session_id2dbm(ctxt->c, key.data, key.size, &dbmkey) < 0) - return -1; - - /* we expire dbm only on every store - */ - dbm_cache_expire(ctxt); - - apr_pool_create(&spool, ctxt->c->pool); - - /* create DBM value */ - dbmval.dsize = data.size + sizeof(apr_time_t); - dbmval.dptr = (char *)apr_palloc(spool, dbmval.dsize); - - expiry = apr_time_now() + ctxt->sc->cache_timeout; - - memcpy((char *)dbmval.dptr, &expiry, sizeof(apr_time_t)); - memcpy((char *)dbmval.dptr+sizeof(apr_time_t), - data.data, data.size); - - rv = apr_dbm_open_ex(&dbm, db_type(ctxt->sc), ctxt->sc->cache_config, - APR_DBM_RWCREATE, SSL_DBM_FILE_MODE, ctxt->c->pool); - if (rv != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, - ctxt->c->base_server, - "[gnutls_cache] error opening cache '%s'", - ctxt->sc->cache_config); - apr_pool_destroy(spool); - return -1; - } - - rv = apr_dbm_store(dbm, dbmkey, dbmval); - - if (rv != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, - ctxt->c->base_server, - "[gnutls_cache] error storing in cache '%s'", - ctxt->sc->cache_config); - apr_dbm_close(dbm); - apr_pool_destroy(spool); - return -1; - } - - apr_dbm_close(dbm); - - apr_pool_destroy(spool); - - return 0; + apr_dbm_t *dbm; + apr_datum_t dbmkey; + apr_datum_t dbmval; + mgs_handle_t *ctxt = baton; + apr_status_t rv; + apr_time_t expiry; + apr_pool_t *spool; + + if (mgs_session_id2dbm(ctxt->c, key.data, key.size, &dbmkey) < 0) + return -1; + + /* we expire dbm only on every store + */ + dbm_cache_expire(ctxt); + + apr_pool_create(&spool, ctxt->c->pool); + + /* create DBM value */ + dbmval.dsize = data.size + sizeof(apr_time_t); + dbmval.dptr = (char *) apr_palloc(spool, dbmval.dsize); + + expiry = apr_time_now() + ctxt->sc->cache_timeout; + + memcpy((char *) dbmval.dptr, &expiry, sizeof(apr_time_t)); + memcpy((char *) dbmval.dptr + sizeof(apr_time_t), + data.data, data.size); + + rv = apr_dbm_open_ex(&dbm, db_type(ctxt->sc), + ctxt->sc->cache_config, APR_DBM_RWCREATE, + SSL_DBM_FILE_MODE, ctxt->c->pool); + if (rv != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, + ctxt->c->base_server, + "[gnutls_cache] error opening cache '%s'", + ctxt->sc->cache_config); + apr_pool_destroy(spool); + return -1; + } + + rv = apr_dbm_store(dbm, dbmkey, dbmval); + + if (rv != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, + ctxt->c->base_server, + "[gnutls_cache] error storing in cache '%s'", + ctxt->sc->cache_config); + apr_dbm_close(dbm); + apr_pool_destroy(spool); + return -1; + } + + apr_dbm_close(dbm); + + apr_pool_destroy(spool); + + return 0; } -static int dbm_cache_delete(void* baton, gnutls_datum_t key) +static int dbm_cache_delete(void *baton, gnutls_datum_t key) { - apr_dbm_t *dbm; - apr_datum_t dbmkey; - mgs_handle_t *ctxt = baton; - apr_status_t rv; - - if (mgs_session_id2dbm(ctxt->c, key.data, key.size, &dbmkey) < 0) - return -1; - - rv = apr_dbm_open_ex(&dbm, db_type(ctxt->sc), ctxt->sc->cache_config, - APR_DBM_RWCREATE, SSL_DBM_FILE_MODE, ctxt->c->pool); - if (rv != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, - ctxt->c->base_server, - "[gnutls_cache] error opening cache '%s'", - ctxt->sc->cache_config); - return -1; - } - - rv = apr_dbm_delete(dbm, dbmkey); - - if (rv != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, - ctxt->c->base_server, - "[gnutls_cache] error deleting from cache '%s'", - ctxt->sc->cache_config); - apr_dbm_close(dbm); - return -1; - } - - apr_dbm_close(dbm); - - return 0; + apr_dbm_t *dbm; + apr_datum_t dbmkey; + mgs_handle_t *ctxt = baton; + apr_status_t rv; + + if (mgs_session_id2dbm(ctxt->c, key.data, key.size, &dbmkey) < 0) + return -1; + + rv = apr_dbm_open_ex(&dbm, db_type(ctxt->sc), + ctxt->sc->cache_config, APR_DBM_RWCREATE, + SSL_DBM_FILE_MODE, ctxt->c->pool); + if (rv != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, + ctxt->c->base_server, + "[gnutls_cache] error opening cache '%s'", + ctxt->sc->cache_config); + return -1; + } + + rv = apr_dbm_delete(dbm, dbmkey); + + if (rv != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, + ctxt->c->base_server, + "[gnutls_cache] error deleting from cache '%s'", + ctxt->sc->cache_config); + apr_dbm_close(dbm); + return -1; + } + + apr_dbm_close(dbm); + + return 0; } -static int dbm_cache_post_config(apr_pool_t *p, server_rec *s, - mgs_srvconf_rec *sc) +static int dbm_cache_post_config(apr_pool_t * p, server_rec * s, + mgs_srvconf_rec * sc) { - apr_status_t rv; - apr_dbm_t *dbm; - const char* path1; - const char* path2; + apr_status_t rv; + apr_dbm_t *dbm; + const char *path1; + const char *path2; - rv = apr_dbm_open_ex(&dbm, db_type(sc), sc->cache_config, APR_DBM_RWCREATE, - SSL_DBM_FILE_MODE, p); + rv = apr_dbm_open_ex(&dbm, db_type(sc), sc->cache_config, + APR_DBM_RWCREATE, SSL_DBM_FILE_MODE, p); - if (rv != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, - "GnuTLS: Cannot create DBM Cache at `%s'", - sc->cache_config); - return rv; - } + if (rv != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, + "GnuTLS: Cannot create DBM Cache at `%s'", + sc->cache_config); + return rv; + } - apr_dbm_close(dbm); + apr_dbm_close(dbm); - apr_dbm_get_usednames_ex(p, db_type(sc), sc->cache_config, &path1, &path2); + apr_dbm_get_usednames_ex(p, db_type(sc), sc->cache_config, &path1, + &path2); - /* The Following Code takes logic directly from mod_ssl's DBM Cache */ + /* The Following Code takes logic directly from mod_ssl's DBM Cache */ #if !defined(OS2) && !defined(WIN32) && !defined(BEOS) && !defined(NETWARE) - /* Running as Root */ - if (path1 && geteuid() == 0) { - chown(path1, ap_unixd_config.user_id, -1); - if (path2 != NULL) { - chown(path2, ap_unixd_config.user_id, -1); - } - } + /* Running as Root */ + if (path1 && geteuid() == 0) { + chown(path1, ap_unixd_config.user_id, -1); + if (path2 != NULL) { + chown(path2, ap_unixd_config.user_id, -1); + } + } #endif - return rv; + return rv; } -int mgs_cache_post_config(apr_pool_t *p, server_rec *s, - mgs_srvconf_rec *sc) +int mgs_cache_post_config(apr_pool_t * p, server_rec * s, + mgs_srvconf_rec * sc) { - if (sc->cache_type == mgs_cache_dbm || sc->cache_type == mgs_cache_gdbm) { - return dbm_cache_post_config(p, s, sc); - } - return 0; + if (sc->cache_type == mgs_cache_dbm + || sc->cache_type == mgs_cache_gdbm) { + return dbm_cache_post_config(p, s, sc); + } + return 0; } -int mgs_cache_child_init(apr_pool_t *p, server_rec *s, - mgs_srvconf_rec *sc) +int mgs_cache_child_init(apr_pool_t * p, server_rec * s, + mgs_srvconf_rec * sc) { - if (sc->cache_type == mgs_cache_dbm || sc->cache_type == mgs_cache_gdbm) { - return 0; - } + if (sc->cache_type == mgs_cache_dbm + || sc->cache_type == mgs_cache_gdbm) { + return 0; + } #if HAVE_APR_MEMCACHE - else if (sc->cache_type == mgs_cache_memcache) { - return mc_cache_child_init(p, s, sc); - } + else if (sc->cache_type == mgs_cache_memcache) { + return mc_cache_child_init(p, s, sc); + } #endif - return 0; + return 0; } - #include +#include -int mgs_cache_session_init(mgs_handle_t *ctxt) +int mgs_cache_session_init(mgs_handle_t * ctxt) { - if (ctxt->sc->cache_type == mgs_cache_dbm || ctxt->sc->cache_type == mgs_cache_gdbm) { - gnutls_db_set_retrieve_function(ctxt->session, dbm_cache_fetch); - gnutls_db_set_remove_function(ctxt->session, dbm_cache_delete); - gnutls_db_set_store_function(ctxt->session, dbm_cache_store); - gnutls_db_set_ptr(ctxt->session, ctxt); - } + if (ctxt->sc->cache_type == mgs_cache_dbm + || ctxt->sc->cache_type == mgs_cache_gdbm) { + gnutls_db_set_retrieve_function(ctxt->session, + dbm_cache_fetch); + gnutls_db_set_remove_function(ctxt->session, + dbm_cache_delete); + gnutls_db_set_store_function(ctxt->session, + dbm_cache_store); + gnutls_db_set_ptr(ctxt->session, ctxt); + } #if HAVE_APR_MEMCACHE - else if (ctxt->sc->cache_type == mgs_cache_memcache) { - gnutls_db_set_retrieve_function(ctxt->session, mc_cache_fetch); - gnutls_db_set_remove_function(ctxt->session, mc_cache_delete); - gnutls_db_set_store_function(ctxt->session, mc_cache_store); - gnutls_db_set_ptr(ctxt->session, ctxt); - } + else if (ctxt->sc->cache_type == mgs_cache_memcache) { + gnutls_db_set_retrieve_function(ctxt->session, + mc_cache_fetch); + gnutls_db_set_remove_function(ctxt->session, + mc_cache_delete); + gnutls_db_set_store_function(ctxt->session, + mc_cache_store); + gnutls_db_set_ptr(ctxt->session, ctxt); + } #endif - return 0; + return 0; } diff --git a/src/gnutls_config.c b/src/gnutls_config.c index ff8ec33..fc3e166 100644 --- a/src/gnutls_config.c +++ b/src/gnutls_config.c @@ -21,284 +21,308 @@ static int load_datum_from_file(apr_pool_t * pool, const char *file, gnutls_datum_t * data) { - apr_file_t *fp; - apr_finfo_t finfo; - apr_status_t rv; - apr_size_t br = 0; + apr_file_t *fp; + apr_finfo_t finfo; + apr_status_t rv; + apr_size_t br = 0; - rv = apr_file_open(&fp, file, APR_READ | APR_BINARY, APR_OS_DEFAULT, - pool); - if (rv != APR_SUCCESS) { - return rv; - } + rv = apr_file_open(&fp, file, APR_READ | APR_BINARY, + APR_OS_DEFAULT, pool); + if (rv != APR_SUCCESS) { + return rv; + } - rv = apr_file_info_get(&finfo, APR_FINFO_SIZE, fp); + rv = apr_file_info_get(&finfo, APR_FINFO_SIZE, fp); - if (rv != APR_SUCCESS) { - return rv; - } + if (rv != APR_SUCCESS) { + return rv; + } - data->data = apr_palloc(pool, finfo.size + 1); - rv = apr_file_read_full(fp, data->data, finfo.size, &br); + data->data = apr_palloc(pool, finfo.size + 1); + rv = apr_file_read_full(fp, data->data, finfo.size, &br); - if (rv != APR_SUCCESS) { - return rv; - } - apr_file_close(fp); + if (rv != APR_SUCCESS) { + return rv; + } + apr_file_close(fp); - data->data[br] = '\0'; - data->size = br; + data->data[br] = '\0'; + data->size = br; - return 0; + return 0; } const char *mgs_set_dh_file(cmd_parms * parms, void *dummy, const char *arg) { - int ret; - gnutls_datum_t data; - const char *file; - apr_pool_t *spool; - mgs_srvconf_rec *sc = - (mgs_srvconf_rec *) ap_get_module_config(parms->server-> - module_config, - &gnutls_module); - - apr_pool_create(&spool, parms->pool); - - file = ap_server_root_relative(spool, arg); - - if (load_datum_from_file(spool, file, &data) != 0) { - return apr_psprintf(parms->pool, "GnuTLS: Error Reading " - "DH params '%s'", file); - } - - ret = gnutls_dh_params_init(&sc->dh_params); - if (ret < 0) { - return apr_psprintf(parms->pool, "GnuTLS: Failed to initialize" - ": (%d) %s", ret, gnutls_strerror(ret)); - } - - ret = - gnutls_dh_params_import_pkcs3(sc->dh_params, &data, GNUTLS_X509_FMT_PEM); - if (ret < 0) { - return apr_psprintf(parms->pool, "GnuTLS: Failed to Import " - "DH params '%s': (%d) %s", file, ret, - gnutls_strerror(ret)); - } - - apr_pool_destroy(spool); - - return NULL; + int ret; + gnutls_datum_t data; + const char *file; + apr_pool_t *spool; + mgs_srvconf_rec *sc = + (mgs_srvconf_rec *) ap_get_module_config(parms->server-> + module_config, + &gnutls_module); + + apr_pool_create(&spool, parms->pool); + + file = ap_server_root_relative(spool, arg); + + if (load_datum_from_file(spool, file, &data) != 0) { + return apr_psprintf(parms->pool, "GnuTLS: Error Reading " + "DH params '%s'", file); + } + + ret = gnutls_dh_params_init(&sc->dh_params); + if (ret < 0) { + return apr_psprintf(parms->pool, + "GnuTLS: Failed to initialize" + ": (%d) %s", ret, + gnutls_strerror(ret)); + } + + ret = + gnutls_dh_params_import_pkcs3(sc->dh_params, &data, + GNUTLS_X509_FMT_PEM); + if (ret < 0) { + return apr_psprintf(parms->pool, + "GnuTLS: Failed to Import " + "DH params '%s': (%d) %s", file, ret, + gnutls_strerror(ret)); + } + + apr_pool_destroy(spool); + + return NULL; } const char *mgs_set_rsa_export_file(cmd_parms * parms, void *dummy, const char *arg) { - int ret; - gnutls_datum_t data; - const char *file; - apr_pool_t *spool; - mgs_srvconf_rec *sc = - (mgs_srvconf_rec *) ap_get_module_config(parms->server-> - module_config, - &gnutls_module); - - apr_pool_create(&spool, parms->pool); - - file = ap_server_root_relative(spool, arg); - - if (load_datum_from_file(spool, file, &data) != 0) { - return apr_psprintf(parms->pool, "GnuTLS: Error Reading " - "RSA params '%s'", file); - } - - ret = gnutls_rsa_params_init(&sc->rsa_params); - if (ret < 0) { - return apr_psprintf(parms->pool, "GnuTLS: Failed to initialize" - ": (%d) %s", ret, gnutls_strerror(ret)); - } - - ret = - gnutls_rsa_params_import_pkcs1(sc->rsa_params, &data, GNUTLS_X509_FMT_PEM); - if (ret != 0) { - return apr_psprintf(parms->pool, "GnuTLS: Failed to Import " - "RSA params '%s': (%d) %s", file, ret, - gnutls_strerror(ret)); - } - - apr_pool_destroy(spool); - return NULL; + int ret; + gnutls_datum_t data; + const char *file; + apr_pool_t *spool; + mgs_srvconf_rec *sc = + (mgs_srvconf_rec *) ap_get_module_config(parms->server-> + module_config, + &gnutls_module); + + apr_pool_create(&spool, parms->pool); + + file = ap_server_root_relative(spool, arg); + + if (load_datum_from_file(spool, file, &data) != 0) { + return apr_psprintf(parms->pool, "GnuTLS: Error Reading " + "RSA params '%s'", file); + } + + ret = gnutls_rsa_params_init(&sc->rsa_params); + if (ret < 0) { + return apr_psprintf(parms->pool, + "GnuTLS: Failed to initialize" + ": (%d) %s", ret, + gnutls_strerror(ret)); + } + + ret = + gnutls_rsa_params_import_pkcs1(sc->rsa_params, &data, + GNUTLS_X509_FMT_PEM); + if (ret != 0) { + return apr_psprintf(parms->pool, + "GnuTLS: Failed to Import " + "RSA params '%s': (%d) %s", file, ret, + gnutls_strerror(ret)); + } + + apr_pool_destroy(spool); + return NULL; } const char *mgs_set_cert_file(cmd_parms * parms, void *dummy, const char *arg) { - int ret; - gnutls_datum_t data; - const char *file; - apr_pool_t *spool; - mgs_srvconf_rec *sc = - (mgs_srvconf_rec *) ap_get_module_config(parms->server-> - module_config, - &gnutls_module); - apr_pool_create(&spool, parms->pool); - - file = ap_server_root_relative(spool, arg); - - if (load_datum_from_file(spool, file, &data) != 0) { - return apr_psprintf(parms->pool, "GnuTLS: Error Reading " - "Certificate '%s'", file); - } - - sc->certs_x509_num = MAX_CHAIN_SIZE; - ret = - gnutls_x509_crt_list_import(sc->certs_x509, &sc->certs_x509_num, &data, GNUTLS_X509_FMT_PEM, 0); - if (ret < 0) { - return apr_psprintf(parms->pool, "GnuTLS: Failed to Import " - "Certificate '%s': (%d) %s", file, ret, - gnutls_strerror(ret)); - } - - apr_pool_destroy(spool); - return NULL; + int ret; + gnutls_datum_t data; + const char *file; + apr_pool_t *spool; + mgs_srvconf_rec *sc = + (mgs_srvconf_rec *) ap_get_module_config(parms->server-> + module_config, + &gnutls_module); + apr_pool_create(&spool, parms->pool); + + file = ap_server_root_relative(spool, arg); + + if (load_datum_from_file(spool, file, &data) != 0) { + return apr_psprintf(parms->pool, "GnuTLS: Error Reading " + "Certificate '%s'", file); + } + + sc->certs_x509_num = MAX_CHAIN_SIZE; + ret = + gnutls_x509_crt_list_import(sc->certs_x509, + &sc->certs_x509_num, &data, + GNUTLS_X509_FMT_PEM, 0); + if (ret < 0) { + return apr_psprintf(parms->pool, + "GnuTLS: Failed to Import " + "Certificate '%s': (%d) %s", file, ret, + gnutls_strerror(ret)); + } + + apr_pool_destroy(spool); + return NULL; } const char *mgs_set_key_file(cmd_parms * parms, void *dummy, const char *arg) { - int ret; - gnutls_datum_t data; - const char *file; - apr_pool_t *spool; - mgs_srvconf_rec *sc = - (mgs_srvconf_rec *) ap_get_module_config(parms->server-> - module_config, - &gnutls_module); - apr_pool_create(&spool, parms->pool); - - file = ap_server_root_relative(spool, arg); - - if (load_datum_from_file(spool, file, &data) != 0) { - return apr_psprintf(parms->pool, "GnuTLS: Error Reading " - "Private Key '%s'", file); - } - - ret = gnutls_x509_privkey_init(&sc->privkey_x509); - if (ret < 0) { - return apr_psprintf(parms->pool, "GnuTLS: Failed to initialize" - ": (%d) %s", ret, gnutls_strerror(ret)); - } - - ret = - gnutls_x509_privkey_import(sc->privkey_x509, &data, - GNUTLS_X509_FMT_PEM); - - if (ret < 0) - ret = gnutls_x509_privkey_import_pkcs8 (sc->privkey_x509, &data, GNUTLS_X509_FMT_PEM, - NULL, GNUTLS_PKCS_PLAIN); - - if (ret < 0) { - return apr_psprintf(parms->pool, "GnuTLS: Failed to Import " - "Private Key '%s': (%d) %s", file, ret, - gnutls_strerror(ret)); - } - apr_pool_destroy(spool); - return NULL; + int ret; + gnutls_datum_t data; + const char *file; + apr_pool_t *spool; + mgs_srvconf_rec *sc = + (mgs_srvconf_rec *) ap_get_module_config(parms->server-> + module_config, + &gnutls_module); + apr_pool_create(&spool, parms->pool); + + file = ap_server_root_relative(spool, arg); + + if (load_datum_from_file(spool, file, &data) != 0) { + return apr_psprintf(parms->pool, "GnuTLS: Error Reading " + "Private Key '%s'", file); + } + + ret = gnutls_x509_privkey_init(&sc->privkey_x509); + if (ret < 0) { + return apr_psprintf(parms->pool, + "GnuTLS: Failed to initialize" + ": (%d) %s", ret, + gnutls_strerror(ret)); + } + + ret = + gnutls_x509_privkey_import(sc->privkey_x509, &data, + GNUTLS_X509_FMT_PEM); + + if (ret < 0) + ret = + gnutls_x509_privkey_import_pkcs8(sc->privkey_x509, + &data, + GNUTLS_X509_FMT_PEM, + NULL, + GNUTLS_PKCS_PLAIN); + + if (ret < 0) { + return apr_psprintf(parms->pool, + "GnuTLS: Failed to Import " + "Private Key '%s': (%d) %s", file, ret, + gnutls_strerror(ret)); + } + apr_pool_destroy(spool); + return NULL; } const char *mgs_set_pgpcert_file(cmd_parms * parms, void *dummy, - const char *arg) + const char *arg) { - int ret; - gnutls_datum_t data; - const char *file; - apr_pool_t *spool; - mgs_srvconf_rec *sc = - (mgs_srvconf_rec *) ap_get_module_config(parms->server-> - module_config, - &gnutls_module); - apr_pool_create(&spool, parms->pool); - - file = ap_server_root_relative(spool, arg); - - if (load_datum_from_file(spool, file, &data) != 0) { - return apr_psprintf(parms->pool, "GnuTLS: Error Reading " - "Certificate '%s'", file); - } - - ret = gnutls_openpgp_crt_init( &sc->cert_pgp); - if (ret < 0) { - return apr_psprintf(parms->pool, "GnuTLS: Failed to Init " - "PGP Certificate: (%d) %s", ret, - gnutls_strerror(ret)); - } - - ret = - gnutls_openpgp_crt_import(sc->cert_pgp, &data, GNUTLS_OPENPGP_FMT_BASE64); - if (ret < 0) { - return apr_psprintf(parms->pool, "GnuTLS: Failed to Import " - "PGP Certificate '%s': (%d) %s", file, ret, - gnutls_strerror(ret)); - } - - apr_pool_destroy(spool); - return NULL; + int ret; + gnutls_datum_t data; + const char *file; + apr_pool_t *spool; + mgs_srvconf_rec *sc = + (mgs_srvconf_rec *) ap_get_module_config(parms->server-> + module_config, + &gnutls_module); + apr_pool_create(&spool, parms->pool); + + file = ap_server_root_relative(spool, arg); + + if (load_datum_from_file(spool, file, &data) != 0) { + return apr_psprintf(parms->pool, "GnuTLS: Error Reading " + "Certificate '%s'", file); + } + + ret = gnutls_openpgp_crt_init(&sc->cert_pgp); + if (ret < 0) { + return apr_psprintf(parms->pool, "GnuTLS: Failed to Init " + "PGP Certificate: (%d) %s", ret, + gnutls_strerror(ret)); + } + + ret = + gnutls_openpgp_crt_import(sc->cert_pgp, &data, + GNUTLS_OPENPGP_FMT_BASE64); + if (ret < 0) { + return apr_psprintf(parms->pool, + "GnuTLS: Failed to Import " + "PGP Certificate '%s': (%d) %s", file, + ret, gnutls_strerror(ret)); + } + + apr_pool_destroy(spool); + return NULL; } const char *mgs_set_pgpkey_file(cmd_parms * parms, void *dummy, - const char *arg) + const char *arg) { - int ret; - gnutls_datum_t data; - const char *file; - apr_pool_t *spool; - mgs_srvconf_rec *sc = - (mgs_srvconf_rec *) ap_get_module_config(parms->server-> - module_config, - &gnutls_module); - apr_pool_create(&spool, parms->pool); - - file = ap_server_root_relative(spool, arg); - - if (load_datum_from_file(spool, file, &data) != 0) { - return apr_psprintf(parms->pool, "GnuTLS: Error Reading " - "Private Key '%s'", file); - } - - ret = gnutls_openpgp_privkey_init(&sc->privkey_pgp); - if (ret < 0) { - return apr_psprintf(parms->pool, "GnuTLS: Failed to initialize" - ": (%d) %s", ret, gnutls_strerror(ret)); - } - - ret = - gnutls_openpgp_privkey_import(sc->privkey_pgp, &data, - GNUTLS_OPENPGP_FMT_BASE64, NULL, 0); - if (ret != 0) { - return apr_psprintf(parms->pool, "GnuTLS: Failed to Import " - "PGP Private Key '%s': (%d) %s", file, ret, - gnutls_strerror(ret)); - } - apr_pool_destroy(spool); - return NULL; + int ret; + gnutls_datum_t data; + const char *file; + apr_pool_t *spool; + mgs_srvconf_rec *sc = + (mgs_srvconf_rec *) ap_get_module_config(parms->server-> + module_config, + &gnutls_module); + apr_pool_create(&spool, parms->pool); + + file = ap_server_root_relative(spool, arg); + + if (load_datum_from_file(spool, file, &data) != 0) { + return apr_psprintf(parms->pool, "GnuTLS: Error Reading " + "Private Key '%s'", file); + } + + ret = gnutls_openpgp_privkey_init(&sc->privkey_pgp); + if (ret < 0) { + return apr_psprintf(parms->pool, + "GnuTLS: Failed to initialize" + ": (%d) %s", ret, + gnutls_strerror(ret)); + } + + ret = + gnutls_openpgp_privkey_import(sc->privkey_pgp, &data, + GNUTLS_OPENPGP_FMT_BASE64, NULL, + 0); + if (ret != 0) { + return apr_psprintf(parms->pool, + "GnuTLS: Failed to Import " + "PGP Private Key '%s': (%d) %s", file, + ret, gnutls_strerror(ret)); + } + apr_pool_destroy(spool); + return NULL; } const char *mgs_set_tickets(cmd_parms * parms, void *dummy, - const char *arg) + const char *arg) { - mgs_srvconf_rec *sc = - (mgs_srvconf_rec *) ap_get_module_config(parms->server-> - module_config, - &gnutls_module); + mgs_srvconf_rec *sc = + (mgs_srvconf_rec *) ap_get_module_config(parms->server-> + module_config, + &gnutls_module); - sc->tickets = 0; - if (strcasecmp("on", arg) == 0) { - sc->tickets = 1; - } + sc->tickets = 0; + if (strcasecmp("on", arg) == 0) { + sc->tickets = 1; + } - return NULL; + return NULL; } @@ -307,27 +331,28 @@ const char *mgs_set_tickets(cmd_parms * parms, void *dummy, const char *mgs_set_srp_tpasswd_file(cmd_parms * parms, void *dummy, const char *arg) { - mgs_srvconf_rec *sc = - (mgs_srvconf_rec *) ap_get_module_config(parms->server-> - module_config, - &gnutls_module); + mgs_srvconf_rec *sc = + (mgs_srvconf_rec *) ap_get_module_config(parms->server-> + module_config, + &gnutls_module); - sc->srp_tpasswd_file = ap_server_root_relative(parms->pool, arg); + sc->srp_tpasswd_file = ap_server_root_relative(parms->pool, arg); - return NULL; + return NULL; } const char *mgs_set_srp_tpasswd_conf_file(cmd_parms * parms, void *dummy, const char *arg) { - mgs_srvconf_rec *sc = - (mgs_srvconf_rec *) ap_get_module_config(parms->server-> - module_config, - &gnutls_module); + mgs_srvconf_rec *sc = + (mgs_srvconf_rec *) ap_get_module_config(parms->server-> + module_config, + &gnutls_module); - sc->srp_tpasswd_conf_file = ap_server_root_relative(parms->pool, arg); + sc->srp_tpasswd_conf_file = + ap_server_root_relative(parms->pool, arg); - return NULL; + return NULL; } #endif @@ -335,308 +360,326 @@ const char *mgs_set_srp_tpasswd_conf_file(cmd_parms * parms, void *dummy, const char *mgs_set_cache(cmd_parms * parms, void *dummy, const char *type, const char *arg) { - const char *err; - mgs_srvconf_rec *sc = ap_get_module_config(parms->server-> - module_config, - &gnutls_module); - if ((err = ap_check_cmd_context(parms, GLOBAL_ONLY))) { - return err; - } - - if (strcasecmp("none", type) == 0) { - sc->cache_type = mgs_cache_none; - } else if (strcasecmp("dbm", type) == 0) { - sc->cache_type = mgs_cache_dbm; - } - else if (strcasecmp("gdbm", type) == 0) { - sc->cache_type = mgs_cache_gdbm; - } + const char *err; + mgs_srvconf_rec *sc = + ap_get_module_config(parms->server->module_config, + &gnutls_module); + if ((err = ap_check_cmd_context(parms, GLOBAL_ONLY))) { + return err; + } + + if (strcasecmp("none", type) == 0) { + sc->cache_type = mgs_cache_none; + } else if (strcasecmp("dbm", type) == 0) { + sc->cache_type = mgs_cache_dbm; + } else if (strcasecmp("gdbm", type) == 0) { + sc->cache_type = mgs_cache_gdbm; + } #if HAVE_APR_MEMCACHE - else if (strcasecmp("memcache", type) == 0) { - sc->cache_type = mgs_cache_memcache; - } + else if (strcasecmp("memcache", type) == 0) { + sc->cache_type = mgs_cache_memcache; + } #endif - else { - return "Invalid Type for GnuTLSCache!"; - } - - if (sc->cache_type == mgs_cache_dbm || sc->cache_type == mgs_cache_gdbm) { - sc->cache_config = ap_server_root_relative(parms->pool, arg); - } else { - sc->cache_config = apr_pstrdup(parms->pool, arg); - } - - return NULL; + else { + return "Invalid Type for GnuTLSCache!"; + } + + if (sc->cache_type == mgs_cache_dbm + || sc->cache_type == mgs_cache_gdbm) { + sc->cache_config = + ap_server_root_relative(parms->pool, arg); + } else { + sc->cache_config = apr_pstrdup(parms->pool, arg); + } + + return NULL; } const char *mgs_set_cache_timeout(cmd_parms * parms, void *dummy, const char *arg) { - int argint; - mgs_srvconf_rec *sc = - (mgs_srvconf_rec *) ap_get_module_config(parms->server-> - module_config, - &gnutls_module); - - argint = atoi(arg); - - if (argint < 0) { - return "GnuTLSCacheTimeout: Invalid argument"; - } else if (argint == 0) { - sc->cache_timeout = 0; - } else { - sc->cache_timeout = apr_time_from_sec(argint); - } - - return NULL; -} - -const char *mgs_set_client_verify(cmd_parms * parms, void *dummy, - const char *arg) -{ - int mode; - - if (strcasecmp("none", arg) == 0 || strcasecmp("ignore", arg) == 0) { - mode = GNUTLS_CERT_IGNORE; - } else if (strcasecmp("optional", arg) == 0 - || strcasecmp("request", arg) == 0) { - mode = GNUTLS_CERT_REQUEST; - } else if (strcasecmp("require", arg) == 0) { - mode = GNUTLS_CERT_REQUIRE; - } else { - return "GnuTLSClientVerify: Invalid argument"; - } - - /* This was set from a directory context */ - if (parms->path) { - mgs_dirconf_rec *dc = (mgs_dirconf_rec *) dummy; - dc->client_verify_mode = mode; - } else { + int argint; mgs_srvconf_rec *sc = (mgs_srvconf_rec *) ap_get_module_config(parms->server-> module_config, &gnutls_module); - sc->client_verify_mode = mode; - } - return NULL; + argint = atoi(arg); + + if (argint < 0) { + return "GnuTLSCacheTimeout: Invalid argument"; + } else if (argint == 0) { + sc->cache_timeout = 0; + } else { + sc->cache_timeout = apr_time_from_sec(argint); + } + + return NULL; +} + +const char *mgs_set_client_verify(cmd_parms * parms, void *dummy, + const char *arg) +{ + int mode; + + if (strcasecmp("none", arg) == 0 || strcasecmp("ignore", arg) == 0) { + mode = GNUTLS_CERT_IGNORE; + } else if (strcasecmp("optional", arg) == 0 + || strcasecmp("request", arg) == 0) { + mode = GNUTLS_CERT_REQUEST; + } else if (strcasecmp("require", arg) == 0) { + mode = GNUTLS_CERT_REQUIRE; + } else { + return "GnuTLSClientVerify: Invalid argument"; + } + + /* This was set from a directory context */ + if (parms->path) { + mgs_dirconf_rec *dc = (mgs_dirconf_rec *) dummy; + dc->client_verify_mode = mode; + } else { + mgs_srvconf_rec *sc = + (mgs_srvconf_rec *) + ap_get_module_config(parms->server->module_config, + &gnutls_module); + sc->client_verify_mode = mode; + } + + return NULL; } #define INIT_CA_SIZE 128 const char *mgs_set_client_ca_file(cmd_parms * parms, void *dummy, const char *arg) { - int rv; - const char *file; - apr_pool_t *spool; - gnutls_datum_t data; - - mgs_srvconf_rec *sc = - (mgs_srvconf_rec *) ap_get_module_config(parms->server-> - module_config, - &gnutls_module); - apr_pool_create(&spool, parms->pool); - - file = ap_server_root_relative(spool, arg); - - if (load_datum_from_file(spool, file, &data) != 0) { - return apr_psprintf(parms->pool, "GnuTLS: Error Reading " - "Client CA File '%s'", file); - } - - sc->ca_list_size = INIT_CA_SIZE; - sc->ca_list = malloc(sc->ca_list_size * sizeof(*sc->ca_list)); - if (sc->ca_list == NULL) { - return apr_psprintf(parms->pool, "mod_gnutls: Memory allocation error"); - } - - rv = gnutls_x509_crt_list_import(sc->ca_list, &sc->ca_list_size, - &data, GNUTLS_X509_FMT_PEM, GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED); - if (rv < 0 && rv != GNUTLS_E_SHORT_MEMORY_BUFFER) { - return apr_psprintf(parms->pool, "GnuTLS: Failed to load " - "Client CA File '%s': (%d) %s", file, rv, - gnutls_strerror(rv)); - } - - if (INIT_CA_SIZE < sc->ca_list_size) { - sc->ca_list = realloc(sc->ca_list, sc->ca_list_size*sizeof(*sc->ca_list)); - if (sc->ca_list == NULL) { - return apr_psprintf(parms->pool, "mod_gnutls: Memory allocation error"); - } - - /* re-read */ - rv = gnutls_x509_crt_list_import(sc->ca_list, &sc->ca_list_size, - &data, GNUTLS_X509_FMT_PEM, 0); - - if (rv < 0) { - return apr_psprintf(parms->pool, "GnuTLS: Failed to load " - "Client CA File '%s': (%d) %s", file, rv, - gnutls_strerror(rv)); - } - } - - apr_pool_destroy(spool); - return NULL; + int rv; + const char *file; + apr_pool_t *spool; + gnutls_datum_t data; + + mgs_srvconf_rec *sc = + (mgs_srvconf_rec *) ap_get_module_config(parms->server-> + module_config, + &gnutls_module); + apr_pool_create(&spool, parms->pool); + + file = ap_server_root_relative(spool, arg); + + if (load_datum_from_file(spool, file, &data) != 0) { + return apr_psprintf(parms->pool, "GnuTLS: Error Reading " + "Client CA File '%s'", file); + } + + sc->ca_list_size = INIT_CA_SIZE; + sc->ca_list = malloc(sc->ca_list_size * sizeof(*sc->ca_list)); + if (sc->ca_list == NULL) { + return apr_psprintf(parms->pool, + "mod_gnutls: Memory allocation error"); + } + + rv = gnutls_x509_crt_list_import(sc->ca_list, &sc->ca_list_size, + &data, GNUTLS_X509_FMT_PEM, + GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED); + if (rv < 0 && rv != GNUTLS_E_SHORT_MEMORY_BUFFER) { + return apr_psprintf(parms->pool, "GnuTLS: Failed to load " + "Client CA File '%s': (%d) %s", file, + rv, gnutls_strerror(rv)); + } + + if (INIT_CA_SIZE < sc->ca_list_size) { + sc->ca_list = + realloc(sc->ca_list, + sc->ca_list_size * sizeof(*sc->ca_list)); + if (sc->ca_list == NULL) { + return apr_psprintf(parms->pool, + "mod_gnutls: Memory allocation error"); + } + + /* re-read */ + rv = gnutls_x509_crt_list_import(sc->ca_list, + &sc->ca_list_size, &data, + GNUTLS_X509_FMT_PEM, 0); + + if (rv < 0) { + return apr_psprintf(parms->pool, + "GnuTLS: Failed to load " + "Client CA File '%s': (%d) %s", + file, rv, gnutls_strerror(rv)); + } + } + + apr_pool_destroy(spool); + return NULL; } const char *mgs_set_keyring_file(cmd_parms * parms, void *dummy, - const char *arg) + const char *arg) { - int rv; - const char *file; - apr_pool_t *spool; - gnutls_datum_t data; - - mgs_srvconf_rec *sc = - (mgs_srvconf_rec *) ap_get_module_config(parms->server-> - module_config, - &gnutls_module); - apr_pool_create(&spool, parms->pool); - - file = ap_server_root_relative(spool, arg); - - if (load_datum_from_file(spool, file, &data) != 0) { - return apr_psprintf(parms->pool, "GnuTLS: Error Reading " - "Keyring File '%s'", file); - } - - rv = gnutls_openpgp_keyring_init(&sc->pgp_list); - if (rv < 0) { - return apr_psprintf(parms->pool, "GnuTLS: Failed to initialize" - "keyring: (%d) %s", rv, gnutls_strerror(rv)); - } - - rv = gnutls_openpgp_keyring_import(sc->pgp_list, &data, GNUTLS_OPENPGP_FMT_BASE64); - if (rv < 0) { - return apr_psprintf(parms->pool, "GnuTLS: Failed to load " - "Keyring File '%s': (%d) %s", file, rv, - gnutls_strerror(rv)); - } - - apr_pool_destroy(spool); - return NULL; + int rv; + const char *file; + apr_pool_t *spool; + gnutls_datum_t data; + + mgs_srvconf_rec *sc = + (mgs_srvconf_rec *) ap_get_module_config(parms->server-> + module_config, + &gnutls_module); + apr_pool_create(&spool, parms->pool); + + file = ap_server_root_relative(spool, arg); + + if (load_datum_from_file(spool, file, &data) != 0) { + return apr_psprintf(parms->pool, "GnuTLS: Error Reading " + "Keyring File '%s'", file); + } + + rv = gnutls_openpgp_keyring_init(&sc->pgp_list); + if (rv < 0) { + return apr_psprintf(parms->pool, + "GnuTLS: Failed to initialize" + "keyring: (%d) %s", rv, + gnutls_strerror(rv)); + } + + rv = gnutls_openpgp_keyring_import(sc->pgp_list, &data, + GNUTLS_OPENPGP_FMT_BASE64); + if (rv < 0) { + return apr_psprintf(parms->pool, "GnuTLS: Failed to load " + "Keyring File '%s': (%d) %s", file, rv, + gnutls_strerror(rv)); + } + + apr_pool_destroy(spool); + return NULL; } const char *mgs_set_enabled(cmd_parms * parms, void *dummy, const char *arg) { - mgs_srvconf_rec *sc = - (mgs_srvconf_rec *) ap_get_module_config(parms->server-> - module_config, - &gnutls_module); - if (!strcasecmp(arg, "On")) { - sc->enabled = GNUTLS_ENABLED_TRUE; - } else if (!strcasecmp(arg, "Off")) { - sc->enabled = GNUTLS_ENABLED_FALSE; - } else { - return "GnuTLSEnable must be set to 'On' or 'Off'"; - } - - return NULL; + mgs_srvconf_rec *sc = + (mgs_srvconf_rec *) ap_get_module_config(parms->server-> + module_config, + &gnutls_module); + if (!strcasecmp(arg, "On")) { + sc->enabled = GNUTLS_ENABLED_TRUE; + } else if (!strcasecmp(arg, "Off")) { + sc->enabled = GNUTLS_ENABLED_FALSE; + } else { + return "GnuTLSEnable must be set to 'On' or 'Off'"; + } + + return NULL; } -const char *mgs_set_export_certificates_enabled(cmd_parms * parms, void *dummy, - const char *arg) +const char *mgs_set_export_certificates_enabled(cmd_parms * parms, + void *dummy, + const char *arg) { - mgs_srvconf_rec *sc = - (mgs_srvconf_rec *) ap_get_module_config(parms->server-> - module_config, - &gnutls_module); - if (!strcasecmp(arg, "On")) { - sc->export_certificates_enabled = GNUTLS_ENABLED_TRUE; - } else if (!strcasecmp(arg, "Off")) { - sc->export_certificates_enabled = GNUTLS_ENABLED_FALSE; - } else { - return "GnuTLSExportCertificates must be set to 'On' or 'Off'"; - } - - return NULL; + mgs_srvconf_rec *sc = + (mgs_srvconf_rec *) ap_get_module_config(parms->server-> + module_config, + &gnutls_module); + if (!strcasecmp(arg, "On")) { + sc->export_certificates_enabled = GNUTLS_ENABLED_TRUE; + } else if (!strcasecmp(arg, "Off")) { + sc->export_certificates_enabled = GNUTLS_ENABLED_FALSE; + } else { + return + "GnuTLSExportCertificates must be set to 'On' or 'Off'"; + } + + return NULL; } -const char *mgs_set_priorities(cmd_parms * parms, void *dummy, const char *arg) +const char *mgs_set_priorities(cmd_parms * parms, void *dummy, + const char *arg) { - int ret; - const char *err; - mgs_srvconf_rec *sc = - (mgs_srvconf_rec *) ap_get_module_config(parms->server-> - module_config, - &gnutls_module); - - - ret = gnutls_priority_init( &sc->priorities, arg, &err); - if (ret < 0) { - if (ret == GNUTLS_E_INVALID_REQUEST) - return apr_psprintf(parms->pool, "GnuTLS: Syntax error parsing priorities string at: %s", err); - return "Error setting priorities"; - } - - return NULL; + int ret; + const char *err; + mgs_srvconf_rec *sc = + (mgs_srvconf_rec *) ap_get_module_config(parms->server-> + module_config, + &gnutls_module); + + + ret = gnutls_priority_init(&sc->priorities, arg, &err); + if (ret < 0) { + if (ret == GNUTLS_E_INVALID_REQUEST) + return apr_psprintf(parms->pool, + "GnuTLS: Syntax error parsing priorities string at: %s", + err); + return "Error setting priorities"; + } + + return NULL; } void *mgs_config_server_create(apr_pool_t * p, server_rec * s) { - mgs_srvconf_rec *sc = apr_pcalloc(p, sizeof(*sc)); - int ret; - - sc->enabled = GNUTLS_ENABLED_FALSE; - - ret = gnutls_certificate_allocate_credentials(&sc->certs); - if (ret < 0) { - return apr_psprintf(p, "GnuTLS: Failed to initialize" - ": (%d) %s", ret, gnutls_strerror(ret)); - } - - ret = gnutls_anon_allocate_server_credentials(&sc->anon_creds); - if (ret < 0) { - return apr_psprintf(p, "GnuTLS: Failed to initialize" - ": (%d) %s", ret, gnutls_strerror(ret)); - } + mgs_srvconf_rec *sc = apr_pcalloc(p, sizeof(*sc)); + int ret; + sc->enabled = GNUTLS_ENABLED_FALSE; + + ret = gnutls_certificate_allocate_credentials(&sc->certs); + if (ret < 0) { + return apr_psprintf(p, "GnuTLS: Failed to initialize" + ": (%d) %s", ret, + gnutls_strerror(ret)); + } + + ret = gnutls_anon_allocate_server_credentials(&sc->anon_creds); + if (ret < 0) { + return apr_psprintf(p, "GnuTLS: Failed to initialize" + ": (%d) %s", ret, + gnutls_strerror(ret)); + } #ifdef ENABLE_SRP - ret = gnutls_srp_allocate_server_credentials(&sc->srp_creds); - if (ret < 0) { - return apr_psprintf(p, "GnuTLS: Failed to initialize" - ": (%d) %s", ret, gnutls_strerror(ret)); - } - - sc->srp_tpasswd_conf_file = NULL; - sc->srp_tpasswd_file = NULL; + ret = gnutls_srp_allocate_server_credentials(&sc->srp_creds); + if (ret < 0) { + return apr_psprintf(p, "GnuTLS: Failed to initialize" + ": (%d) %s", ret, + gnutls_strerror(ret)); + } + + sc->srp_tpasswd_conf_file = NULL; + sc->srp_tpasswd_file = NULL; #endif - sc->privkey_x509 = NULL; - memset( sc->certs_x509, 0, sizeof(sc->certs_x509)); - sc->certs_x509_num = 0; - sc->cache_timeout = apr_time_from_sec(300); - sc->cache_type = mgs_cache_none; - sc->cache_config = ap_server_root_relative(p, "conf/gnutls_cache"); - sc->tickets = 1; /* by default enable session tickets */ + sc->privkey_x509 = NULL; + memset(sc->certs_x509, 0, sizeof(sc->certs_x509)); + sc->certs_x509_num = 0; + sc->cache_timeout = apr_time_from_sec(300); + sc->cache_type = mgs_cache_none; + sc->cache_config = ap_server_root_relative(p, "conf/gnutls_cache"); + sc->tickets = 1; /* by default enable session tickets */ - sc->client_verify_mode = GNUTLS_CERT_IGNORE; + sc->client_verify_mode = GNUTLS_CERT_IGNORE; - return sc; + return sc; } void *mgs_config_dir_merge(apr_pool_t * p, void *basev, void *addv) { - mgs_dirconf_rec *new; + mgs_dirconf_rec *new; /* mgs_dirconf_rec *base = (mgs_dirconf_rec *) basev; */ - mgs_dirconf_rec *add = (mgs_dirconf_rec *) addv; - - new = (mgs_dirconf_rec *) apr_pcalloc(p, sizeof(mgs_dirconf_rec)); - new->lua_bytecode = apr_pstrmemdup(p, add->lua_bytecode, - add->lua_bytecode_len); - new->lua_bytecode_len = add->lua_bytecode_len; - new->client_verify_mode = add->client_verify_mode; - return new; + mgs_dirconf_rec *add = (mgs_dirconf_rec *) addv; + + new = (mgs_dirconf_rec *) apr_pcalloc(p, sizeof(mgs_dirconf_rec)); + new->lua_bytecode = apr_pstrmemdup(p, add->lua_bytecode, + add->lua_bytecode_len); + new->lua_bytecode_len = add->lua_bytecode_len; + new->client_verify_mode = add->client_verify_mode; + return new; } void *mgs_config_dir_create(apr_pool_t * p, char *dir) { - mgs_dirconf_rec *dc = apr_palloc(p, sizeof(*dc)); + mgs_dirconf_rec *dc = apr_palloc(p, sizeof(*dc)); - dc->client_verify_mode = -1; - dc->lua_bytecode = NULL; - dc->lua_bytecode_len = 0; - return dc; + dc->client_verify_mode = -1; + dc->lua_bytecode = NULL; + dc->lua_bytecode_len = 0; + return dc; } diff --git a/src/gnutls_hooks.c b/src/gnutls_hooks.c index 7c638fb..34c3585 100644 --- a/src/gnutls_hooks.c +++ b/src/gnutls_hooks.c @@ -40,179 +40,191 @@ static gnutls_datum session_ticket_key = { NULL, 0 }; static int mgs_cert_verify(request_rec * r, mgs_handle_t * ctxt); /* use side==0 for server and side==1 for client */ -static void mgs_add_common_cert_vars(request_rec * r, gnutls_x509_crt_t cert, - int side, - int export_certificates_enabled); -static void mgs_add_common_pgpcert_vars(request_rec * r, gnutls_openpgp_crt_t cert, - int side, +static void mgs_add_common_cert_vars(request_rec * r, + gnutls_x509_crt_t cert, int side, int export_certificates_enabled); +static void mgs_add_common_pgpcert_vars(request_rec * r, + gnutls_openpgp_crt_t cert, + int side, + int export_certificates_enabled); static apr_status_t mgs_cleanup_pre_config(void *data) { - gnutls_free(session_ticket_key.data); - session_ticket_key.data = NULL; - session_ticket_key.size = 0; - gnutls_global_deinit(); - return APR_SUCCESS; + gnutls_free(session_ticket_key.data); + session_ticket_key.data = NULL; + session_ticket_key.size = 0; + gnutls_global_deinit(); + return APR_SUCCESS; } #if MOD_GNUTLS_DEBUG static void gnutls_debug_log_all(int level, const char *str) { - apr_file_printf(debug_log_fp, "<%d> %s\n", level, str); + apr_file_printf(debug_log_fp, "<%d> %s\n", level, str); } + #define _gnutls_log apr_file_printf #else -# define _gnutls_log(...) +# define _gnutls_log(...) #endif int mgs_hook_pre_config(apr_pool_t * pconf, apr_pool_t * plog, apr_pool_t * ptemp) { -int ret; + int ret; #if MOD_GNUTLS_DEBUG - apr_file_open(&debug_log_fp, "/tmp/gnutls_debug", - APR_APPEND | APR_WRITE | APR_CREATE, APR_OS_DEFAULT, - pconf); + apr_file_open(&debug_log_fp, "/tmp/gnutls_debug", + APR_APPEND | APR_WRITE | APR_CREATE, APR_OS_DEFAULT, + pconf); - _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); + _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); - gnutls_global_set_log_level(9); - gnutls_global_set_log_function(gnutls_debug_log_all); - _gnutls_log(debug_log_fp, "gnutls: %s\n", gnutls_check_version(NULL)); + gnutls_global_set_log_level(9); + gnutls_global_set_log_function(gnutls_debug_log_all); + _gnutls_log(debug_log_fp, "gnutls: %s\n", + gnutls_check_version(NULL)); #endif #if APR_HAS_THREADS - ap_mpm_query(AP_MPMQ_IS_THREADED, &mpm_is_threaded); + ap_mpm_query(AP_MPMQ_IS_THREADED, &mpm_is_threaded); #if (GNUTLS_VERSION_MAJOR == 2 && GNUTLS_VERSION_MINOR < 11) || GNUTLS_VERSION_MAJOR < 2 - if (mpm_is_threaded) { - gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread); - } + if (mpm_is_threaded) { + gcry_control(GCRYCTL_SET_THREAD_CBS, + &gcry_threads_pthread); + } #endif #else - mpm_is_threaded = 0; + mpm_is_threaded = 0; #endif - if (gnutls_check_version(LIBGNUTLS_VERSION)==NULL) { - _gnutls_log(debug_log_fp, "gnutls_check_version() failed. Required: gnutls-%s Found: gnutls-%s\n", - LIBGNUTLS_VERSION, gnutls_check_version(NULL)); - return -3; - } + if (gnutls_check_version(LIBGNUTLS_VERSION) == NULL) { + _gnutls_log(debug_log_fp, + "gnutls_check_version() failed. Required: gnutls-%s Found: gnutls-%s\n", + LIBGNUTLS_VERSION, gnutls_check_version(NULL)); + return -3; + } + + ret = gnutls_global_init(); + if (ret < 0) { + _gnutls_log(debug_log_fp, "gnutls_global_init: %s\n", + gnutls_strerror(ret)); + return -3; + } - ret = gnutls_global_init(); - if (ret < 0) { - _gnutls_log(debug_log_fp, "gnutls_global_init: %s\n", gnutls_strerror(ret)); - return -3; - } - - ret = gnutls_session_ticket_key_generate( &session_ticket_key); - if (ret < 0) { - _gnutls_log(debug_log_fp, "gnutls_session_ticket_key_generate: %s\n", gnutls_strerror(ret)); - } + ret = gnutls_session_ticket_key_generate(&session_ticket_key); + if (ret < 0) { + _gnutls_log(debug_log_fp, + "gnutls_session_ticket_key_generate: %s\n", + gnutls_strerror(ret)); + } - apr_pool_cleanup_register(pconf, NULL, mgs_cleanup_pre_config, - apr_pool_cleanup_null); + apr_pool_cleanup_register(pconf, NULL, mgs_cleanup_pre_config, + apr_pool_cleanup_null); - return OK; + return OK; } static int mgs_select_virtual_server_cb(gnutls_session_t session) { - mgs_handle_t *ctxt; - mgs_srvconf_rec *tsc; - int ret; - int cprio[2]; + mgs_handle_t *ctxt; + mgs_srvconf_rec *tsc; + int ret; + int cprio[2]; - _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); + _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); - ctxt = gnutls_transport_get_ptr(session); + ctxt = gnutls_transport_get_ptr(session); - /* find the virtual server */ - tsc = mgs_find_sni_server(session); + /* find the virtual server */ + tsc = mgs_find_sni_server(session); - if (tsc != NULL) - ctxt->sc = tsc; + if (tsc != NULL) + ctxt->sc = tsc; - gnutls_certificate_server_set_request(session, - ctxt->sc->client_verify_mode); + gnutls_certificate_server_set_request(session, + ctxt-> + sc->client_verify_mode); - /* set the new server credentials - */ + /* set the new server credentials + */ - gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, - ctxt->sc->certs); + gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, + ctxt->sc->certs); - gnutls_credentials_set(session, GNUTLS_CRD_ANON, ctxt->sc->anon_creds); + gnutls_credentials_set(session, GNUTLS_CRD_ANON, + ctxt->sc->anon_creds); #ifdef ENABLE_SRP - if (ctxt->sc->srp_tpasswd_conf_file != NULL - && ctxt->sc->srp_tpasswd_file != NULL) { - gnutls_credentials_set(session, GNUTLS_CRD_SRP, - ctxt->sc->srp_creds); - } + if (ctxt->sc->srp_tpasswd_conf_file != NULL + && ctxt->sc->srp_tpasswd_file != NULL) { + gnutls_credentials_set(session, GNUTLS_CRD_SRP, + ctxt->sc->srp_creds); + } #endif - /* update the priorities - to avoid negotiating a ciphersuite that is not - * enabled on this virtual server. Note that here we ignore the version - * negotiation. - */ - ret = gnutls_priority_set(session, ctxt->sc->priorities); - /* actually it shouldn't fail since we have checked at startup */ - if (ret < 0) - return ret; + /* update the priorities - to avoid negotiating a ciphersuite that is not + * enabled on this virtual server. Note that here we ignore the version + * negotiation. + */ + ret = gnutls_priority_set(session, ctxt->sc->priorities); + /* actually it shouldn't fail since we have checked at startup */ + if (ret < 0) + return ret; - /* If both certificate types are not present disallow them from - * being negotiated. - */ - if (ctxt->sc->certs_x509[0] != NULL && ctxt->sc->cert_pgp == NULL) { - cprio[0] = GNUTLS_CRT_X509; - cprio[1] = 0; - gnutls_certificate_type_set_priority( session, cprio); - } else if (ctxt->sc->cert_pgp != NULL && ctxt->sc->certs_x509[0]==NULL) { - cprio[0] = GNUTLS_CRT_OPENPGP; - cprio[1] = 0; - gnutls_certificate_type_set_priority( session, cprio); - } - - return 0; + /* If both certificate types are not present disallow them from + * being negotiated. + */ + if (ctxt->sc->certs_x509[0] != NULL && ctxt->sc->cert_pgp == NULL) { + cprio[0] = GNUTLS_CRT_X509; + cprio[1] = 0; + gnutls_certificate_type_set_priority(session, cprio); + } else if (ctxt->sc->cert_pgp != NULL + && ctxt->sc->certs_x509[0] == NULL) { + cprio[0] = GNUTLS_CRT_OPENPGP; + cprio[1] = 0; + gnutls_certificate_type_set_priority(session, cprio); + } + + return 0; } static int cert_retrieve_fn(gnutls_session_t session, gnutls_retr_st * ret) { - mgs_handle_t *ctxt; + mgs_handle_t *ctxt; + + _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); + ctxt = gnutls_transport_get_ptr(session); - _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); - ctxt = gnutls_transport_get_ptr(session); + if (ctxt == NULL) + return GNUTLS_E_INTERNAL_ERROR; - if (ctxt == NULL) - return GNUTLS_E_INTERNAL_ERROR; + if (gnutls_certificate_type_get(session) == GNUTLS_CRT_X509) { + ret->type = GNUTLS_CRT_X509; + ret->ncerts = ctxt->sc->certs_x509_num; + ret->deinit_all = 0; - if (gnutls_certificate_type_get( session) == GNUTLS_CRT_X509) { - ret->type = GNUTLS_CRT_X509; - ret->ncerts = ctxt->sc->certs_x509_num; - ret->deinit_all = 0; + ret->cert.x509 = ctxt->sc->certs_x509; + ret->key.x509 = ctxt->sc->privkey_x509; - ret->cert.x509 = ctxt->sc->certs_x509; - ret->key.x509 = ctxt->sc->privkey_x509; - - return 0; - } else if (gnutls_certificate_type_get( session) == GNUTLS_CRT_OPENPGP) { - ret->type = GNUTLS_CRT_OPENPGP; - ret->ncerts = 1; - ret->deinit_all = 0; + return 0; + } else if (gnutls_certificate_type_get(session) == + GNUTLS_CRT_OPENPGP) { + ret->type = GNUTLS_CRT_OPENPGP; + ret->ncerts = 1; + ret->deinit_all = 0; - ret->cert.pgp = ctxt->sc->cert_pgp; - ret->key.pgp = ctxt->sc->privkey_pgp; + ret->cert.pgp = ctxt->sc->cert_pgp; + ret->key.pgp = ctxt->sc->privkey_pgp; - return 0; - - } + return 0; - return GNUTLS_E_INTERNAL_ERROR; + } + + return GNUTLS_E_INTERNAL_ERROR; } /* 2048-bit group parameters from SRP specification */ @@ -233,78 +245,81 @@ const char static_dh_params[] = "-----BEGIN DH PARAMETERS-----\n" static int read_crt_cn(server_rec * s, apr_pool_t * p, gnutls_x509_crt_t cert, char **cert_cn) { - int rv = 0, i; - size_t data_len; - + int rv = 0, i; + size_t data_len; - _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); - *cert_cn = NULL; - data_len = 0; - rv = gnutls_x509_crt_get_dn_by_oid(cert, - GNUTLS_OID_X520_COMMON_NAME, - 0, 0, NULL, &data_len); + _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); + *cert_cn = NULL; - if (rv == GNUTLS_E_SHORT_MEMORY_BUFFER && data_len > 1) { - *cert_cn = apr_palloc(p, data_len); + data_len = 0; rv = gnutls_x509_crt_get_dn_by_oid(cert, - GNUTLS_OID_X520_COMMON_NAME, 0, - 0, *cert_cn, &data_len); - } else { /* No CN return subject alternative name */ - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, - "No common name found in certificate for '%s:%d'. Looking for subject alternative name...", - s->server_hostname, s->port); - rv = 0; - /* read subject alternative name */ - for (i = 0; !(rv < 0); i++) { - data_len = 0; - rv = gnutls_x509_crt_get_subject_alt_name(cert, i, - NULL, &data_len, - NULL); - - if (rv == GNUTLS_E_SHORT_MEMORY_BUFFER && data_len > 1) { - /* FIXME: not very efficient. What if we have several alt names - * before DNSName? - */ - *cert_cn = apr_palloc(p, data_len + 1); - - rv = gnutls_x509_crt_get_subject_alt_name(cert, i, - *cert_cn, - &data_len, NULL); - (*cert_cn)[data_len] = 0; - - if (rv == GNUTLS_SAN_DNSNAME) - break; - } + GNUTLS_OID_X520_COMMON_NAME, + 0, 0, NULL, &data_len); + + if (rv == GNUTLS_E_SHORT_MEMORY_BUFFER && data_len > 1) { + *cert_cn = apr_palloc(p, data_len); + rv = gnutls_x509_crt_get_dn_by_oid(cert, + GNUTLS_OID_X520_COMMON_NAME, + 0, 0, *cert_cn, + &data_len); + } else { /* No CN return subject alternative name */ + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, + "No common name found in certificate for '%s:%d'. Looking for subject alternative name...", + s->server_hostname, s->port); + rv = 0; + /* read subject alternative name */ + for (i = 0; !(rv < 0); i++) { + data_len = 0; + rv = gnutls_x509_crt_get_subject_alt_name(cert, i, + NULL, + &data_len, + NULL); + + if (rv == GNUTLS_E_SHORT_MEMORY_BUFFER + && data_len > 1) { + /* FIXME: not very efficient. What if we have several alt names + * before DNSName? + */ + *cert_cn = apr_palloc(p, data_len + 1); + + rv = gnutls_x509_crt_get_subject_alt_name + (cert, i, *cert_cn, &data_len, NULL); + (*cert_cn)[data_len] = 0; + + if (rv == GNUTLS_SAN_DNSNAME) + break; + } + } } - } - return rv; + return rv; } static int read_pgpcrt_cn(server_rec * s, apr_pool_t * p, - gnutls_openpgp_crt_t cert, char **cert_cn) + gnutls_openpgp_crt_t cert, char **cert_cn) { - int rv = 0; - size_t data_len; + int rv = 0; + size_t data_len; - _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); - *cert_cn = NULL; + _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); + *cert_cn = NULL; - data_len = 0; - rv = gnutls_openpgp_crt_get_name(cert, 0, NULL, &data_len); + data_len = 0; + rv = gnutls_openpgp_crt_get_name(cert, 0, NULL, &data_len); - if (rv == GNUTLS_E_SHORT_MEMORY_BUFFER && data_len > 1) { - *cert_cn = apr_palloc(p, data_len); - rv = gnutls_openpgp_crt_get_name(cert, 0, *cert_cn, &data_len); - } else { /* No CN return subject alternative name */ - ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, - "No name found in PGP certificate for '%s:%d'.", - s->server_hostname, s->port); - } + if (rv == GNUTLS_E_SHORT_MEMORY_BUFFER && data_len > 1) { + *cert_cn = apr_palloc(p, data_len); + rv = gnutls_openpgp_crt_get_name(cert, 0, *cert_cn, + &data_len); + } else { /* No CN return subject alternative name */ + ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, + "No name found in PGP certificate for '%s:%d'.", + s->server_hostname, s->port); + } - return rv; + return rv; } @@ -312,27 +327,27 @@ int mgs_hook_post_config(apr_pool_t * p, apr_pool_t * plog, apr_pool_t * ptemp, server_rec * base_server) { - int rv; - server_rec *s; - gnutls_dh_params_t dh_params = NULL; - gnutls_rsa_params_t rsa_params = NULL; - mgs_srvconf_rec *sc; - mgs_srvconf_rec *sc_base; - void *data = NULL; - int first_run = 0; - const char *userdata_key = "mgs_init"; - - _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); - apr_pool_userdata_get(&data, userdata_key, base_server->process->pool); - if (data == NULL) { - first_run = 1; - apr_pool_userdata_set((const void *) 1, userdata_key, - apr_pool_cleanup_null, + int rv; + server_rec *s; + gnutls_dh_params_t dh_params = NULL; + gnutls_rsa_params_t rsa_params = NULL; + mgs_srvconf_rec *sc; + mgs_srvconf_rec *sc_base; + void *data = NULL; + int first_run = 0; + const char *userdata_key = "mgs_init"; + + _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); + apr_pool_userdata_get(&data, userdata_key, base_server->process->pool); - } + if (data == NULL) { + first_run = 1; + apr_pool_userdata_set((const void *) 1, userdata_key, + apr_pool_cleanup_null, + base_server->process->pool); + } - { s = base_server; sc_base = (mgs_srvconf_rec *) ap_get_module_config(s->module_config, @@ -341,545 +356,568 @@ mgs_hook_post_config(apr_pool_t * p, apr_pool_t * plog, gnutls_dh_params_init(&dh_params); if (sc_base->dh_params == NULL) { - gnutls_datum pdata = { (void *) static_dh_params, sizeof(static_dh_params) }; - /* loading defaults */ - rv = gnutls_dh_params_import_pkcs3(dh_params, &pdata, - GNUTLS_X509_FMT_PEM); - - if (rv < 0) { - ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, - "GnuTLS: Unable to load DH Params: (%d) %s", - rv, gnutls_strerror(rv)); - exit(rv); - } - } else dh_params = sc_base->dh_params; - - if (sc_base->rsa_params != NULL) - rsa_params = sc_base->rsa_params; + gnutls_datum pdata = { + (void *) static_dh_params, + sizeof(static_dh_params) + }; + /* loading defaults */ + rv = gnutls_dh_params_import_pkcs3(dh_params, &pdata, + GNUTLS_X509_FMT_PEM); + + if (rv < 0) { + ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, + "GnuTLS: Unable to load DH Params: (%d) %s", + rv, gnutls_strerror(rv)); + exit(rv); + } + } else + dh_params = sc_base->dh_params; + + if (sc_base->rsa_params != NULL) + rsa_params = sc_base->rsa_params; /* else not an error but RSA-EXPORT ciphersuites are not available */ rv = mgs_cache_post_config(p, s, sc_base); if (rv != 0) { - ap_log_error(APLOG_MARK, APLOG_STARTUP, rv, s, - "GnuTLS: Post Config for GnuTLSCache Failed." - " Shutting Down."); - exit(-1); + ap_log_error(APLOG_MARK, APLOG_STARTUP, rv, s, + "GnuTLS: Post Config for GnuTLSCache Failed." + " Shutting Down."); + exit(-1); } for (s = base_server; s; s = s->next) { - void *load = NULL; - sc = (mgs_srvconf_rec *) ap_get_module_config(s->module_config, - &gnutls_module); - sc->cache_type = sc_base->cache_type; - sc->cache_config = sc_base->cache_config; - - /* Check if the priorities have been set */ - if (sc->priorities == NULL && sc->enabled == GNUTLS_ENABLED_TRUE) { - ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, - "GnuTLS: Host '%s:%d' is missing the GnuTLSPriorities directive!", - s->server_hostname, s->port); - exit(-1); - } - - /* Check if DH or RSA params have been set per host */ - if (sc->rsa_params != NULL) - load = sc->rsa_params; - else if (rsa_params) load = rsa_params; - - if (load != NULL) - gnutls_certificate_set_rsa_export_params(sc->certs, load); - - - load = NULL; - if (sc->dh_params != NULL) - load = sc->dh_params; - else if (dh_params) load = dh_params; - - if (load != NULL) { /* not needed but anyway */ - gnutls_certificate_set_dh_params(sc->certs, load); - gnutls_anon_set_server_dh_params(sc->anon_creds, load); - } - - gnutls_certificate_server_set_retrieve_function(sc->certs, - cert_retrieve_fn); + void *load = NULL; + sc = (mgs_srvconf_rec *) + ap_get_module_config(s->module_config, &gnutls_module); + sc->cache_type = sc_base->cache_type; + sc->cache_config = sc_base->cache_config; + + /* Check if the priorities have been set */ + if (sc->priorities == NULL + && sc->enabled == GNUTLS_ENABLED_TRUE) { + ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, + "GnuTLS: Host '%s:%d' is missing the GnuTLSPriorities directive!", + s->server_hostname, s->port); + exit(-1); + } + + /* Check if DH or RSA params have been set per host */ + if (sc->rsa_params != NULL) + load = sc->rsa_params; + else if (rsa_params) + load = rsa_params; + + if (load != NULL) + gnutls_certificate_set_rsa_export_params(sc->certs, + load); + + + load = NULL; + if (sc->dh_params != NULL) + load = sc->dh_params; + else if (dh_params) + load = dh_params; + + if (load != NULL) { /* not needed but anyway */ + gnutls_certificate_set_dh_params(sc->certs, load); + gnutls_anon_set_server_dh_params(sc->anon_creds, + load); + } + + gnutls_certificate_server_set_retrieve_function(sc->certs, + cert_retrieve_fn); #ifdef ENABLE_SRP - if (sc->srp_tpasswd_conf_file != NULL - && sc->srp_tpasswd_file != NULL) { - rv = gnutls_srp_set_server_credentials_file(sc->srp_creds, - sc-> - srp_tpasswd_file, - sc-> - srp_tpasswd_conf_file); - - if (rv < 0 && sc->enabled == GNUTLS_ENABLED_TRUE) { - ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, - "[GnuTLS] - Host '%s:%d' is missing a " - "SRP password or conf File!", - s->server_hostname, s->port); - exit(-1); + if (sc->srp_tpasswd_conf_file != NULL + && sc->srp_tpasswd_file != NULL) { + rv = gnutls_srp_set_server_credentials_file + (sc->srp_creds, sc->srp_tpasswd_file, + sc->srp_tpasswd_conf_file); + + if (rv < 0 && sc->enabled == GNUTLS_ENABLED_TRUE) { + ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, + s, + "[GnuTLS] - Host '%s:%d' is missing a " + "SRP password or conf File!", + s->server_hostname, s->port); + exit(-1); + } } - } #endif - if (sc->certs_x509[0] == NULL && - sc->cert_pgp == NULL && - sc->enabled == GNUTLS_ENABLED_TRUE) { - ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, - "[GnuTLS] - Host '%s:%d' is missing a " - "Certificate File!", s->server_hostname, - s->port); - exit(-1); - } - - if (sc->enabled == GNUTLS_ENABLED_TRUE && - ((sc->certs_x509[0] != NULL && sc->privkey_x509 == NULL) || - (sc->cert_pgp != NULL && sc->privkey_pgp == NULL))) { - ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, - "[GnuTLS] - Host '%s:%d' is missing a " - "Private Key File!", - s->server_hostname, s->port); - exit(-1); - } + if (sc->certs_x509[0] == NULL && + sc->cert_pgp == NULL && + sc->enabled == GNUTLS_ENABLED_TRUE) { + ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, + "[GnuTLS] - Host '%s:%d' is missing a " + "Certificate File!", + s->server_hostname, s->port); + exit(-1); + } - if (sc->enabled == GNUTLS_ENABLED_TRUE) { - rv = read_crt_cn(s, p, sc->certs_x509[0], &sc->cert_cn); - if (rv < 0 && sc->cert_pgp != NULL) /* try openpgp certificate */ - rv = read_pgpcrt_cn(s, p, sc->cert_pgp, &sc->cert_cn); + if (sc->enabled == GNUTLS_ENABLED_TRUE && + ((sc->certs_x509[0] != NULL + && sc->privkey_x509 == NULL) || (sc->cert_pgp != NULL + && sc->privkey_pgp + == NULL))) { + ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, + "[GnuTLS] - Host '%s:%d' is missing a " + "Private Key File!", + s->server_hostname, s->port); + exit(-1); + } - if (rv < 0) { - ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, - "[GnuTLS] - Cannot find a certificate for host '%s:%d'!", - s->server_hostname, s->port); - sc->cert_cn = NULL; - continue; + if (sc->enabled == GNUTLS_ENABLED_TRUE) { + rv = read_crt_cn(s, p, sc->certs_x509[0], + &sc->cert_cn); + if (rv < 0 && sc->cert_pgp != NULL) /* try openpgp certificate */ + rv = read_pgpcrt_cn(s, p, sc->cert_pgp, + &sc->cert_cn); + + if (rv < 0) { + ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, + s, + "[GnuTLS] - Cannot find a certificate for host '%s:%d'!", + s->server_hostname, s->port); + sc->cert_cn = NULL; + continue; + } } - } } - } - ap_add_version_component(p, "mod_gnutls/" MOD_GNUTLS_VERSION); - return OK; + ap_add_version_component(p, "mod_gnutls/" MOD_GNUTLS_VERSION); + + return OK; } void mgs_hook_child_init(apr_pool_t * p, server_rec * s) { - apr_status_t rv = APR_SUCCESS; - mgs_srvconf_rec *sc = ap_get_module_config(s->module_config, - &gnutls_module); - - _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); - if (sc->cache_type != mgs_cache_none) { - rv = mgs_cache_child_init(p, s, sc); - if (rv != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, - "[GnuTLS] - Failed to run Cache Init"); + apr_status_t rv = APR_SUCCESS; + mgs_srvconf_rec *sc = ap_get_module_config(s->module_config, + &gnutls_module); + + _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); + if (sc->cache_type != mgs_cache_none) { + rv = mgs_cache_child_init(p, s, sc); + if (rv != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, + "[GnuTLS] - Failed to run Cache Init"); + } + } else { + ap_log_error(APLOG_MARK, APLOG_CRIT, 0, s, + "[GnuTLS] - No Cache Configured. Hint: GnuTLSCache"); } - } else { - ap_log_error(APLOG_MARK, APLOG_CRIT, 0, s, - "[GnuTLS] - No Cache Configured. Hint: GnuTLSCache"); - } } const char *mgs_hook_http_scheme(const request_rec * r) { - mgs_srvconf_rec *sc; - - if (r == NULL) - return NULL; - - sc = - (mgs_srvconf_rec *) ap_get_module_config(r->server->module_config, - &gnutls_module); - - _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); - if (sc->enabled == GNUTLS_ENABLED_FALSE) { - return NULL; - } + mgs_srvconf_rec *sc; - return "https"; + if (r == NULL) + return NULL; + + sc = (mgs_srvconf_rec *) ap_get_module_config(r-> + server->module_config, + &gnutls_module); + + _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); + if (sc->enabled == GNUTLS_ENABLED_FALSE) { + return NULL; + } + + return "https"; } apr_port_t mgs_hook_default_port(const request_rec * r) { - mgs_srvconf_rec *sc; - - if (r == NULL) - return 0; - - sc = - (mgs_srvconf_rec *) ap_get_module_config(r->server->module_config, - &gnutls_module); - - _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); - if (sc->enabled == GNUTLS_ENABLED_FALSE) { - return 0; - } + mgs_srvconf_rec *sc; + + if (r == NULL) + return 0; + + sc = (mgs_srvconf_rec *) ap_get_module_config(r-> + server->module_config, + &gnutls_module); + + _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); + if (sc->enabled == GNUTLS_ENABLED_FALSE) { + return 0; + } - return 443; + return 443; } #define MAX_HOST_LEN 255 #if USING_2_1_RECENT typedef struct { - mgs_handle_t *ctxt; - mgs_srvconf_rec *sc; - const char *sni_name; + mgs_handle_t *ctxt; + mgs_srvconf_rec *sc; + const char *sni_name; } vhost_cb_rec; static int vhost_cb(void *baton, conn_rec * conn, server_rec * s) { - mgs_srvconf_rec *tsc; - vhost_cb_rec *x = baton; + mgs_srvconf_rec *tsc; + vhost_cb_rec *x = baton; - _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); - tsc = (mgs_srvconf_rec *) ap_get_module_config(s->module_config, - &gnutls_module); + _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); + tsc = (mgs_srvconf_rec *) ap_get_module_config(s->module_config, + &gnutls_module); - if (tsc->enabled != GNUTLS_ENABLED_TRUE || tsc->cert_cn == NULL) { - return 0; - } + if (tsc->enabled != GNUTLS_ENABLED_TRUE || tsc->cert_cn == NULL) { + return 0; + } - /* The CN can contain a * -- this will match those too. */ - if (ap_strcasecmp_match(x->sni_name, tsc->cert_cn) == 0) { - /* found a match */ + /* The CN can contain a * -- this will match those too. */ + if (ap_strcasecmp_match(x->sni_name, tsc->cert_cn) == 0) { + /* found a match */ #if MOD_GNUTLS_DEBUG - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, - x->ctxt->c->base_server, - "GnuTLS: Virtual Host CB: " - "'%s' == '%s'", tsc->cert_cn, x->sni_name); + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, + x->ctxt->c->base_server, + "GnuTLS: Virtual Host CB: " + "'%s' == '%s'", tsc->cert_cn, x->sni_name); #endif - /* Because we actually change the server used here, we need to reset - * things like ClientVerify. - */ - x->sc = tsc; - /* Shit. Crap. Dammit. We *really* should rehandshake here, as our - * certificate structure *should* change when the server changes. - * acccckkkkkk. - */ - return 1; - } else { + /* Because we actually change the server used here, we need to reset + * things like ClientVerify. + */ + x->sc = tsc; + /* Shit. Crap. Dammit. We *really* should rehandshake here, as our + * certificate structure *should* change when the server changes. + * acccckkkkkk. + */ + return 1; + } else { #if MOD_GNUTLS_DEBUG - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, - x->ctxt->c->base_server, - "GnuTLS: Virtual Host CB: " - "'%s' != '%s'", tsc->cert_cn, x->sni_name); + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, + x->ctxt->c->base_server, + "GnuTLS: Virtual Host CB: " + "'%s' != '%s'", tsc->cert_cn, x->sni_name); #endif - } - return 0; + } + return 0; } #endif mgs_srvconf_rec *mgs_find_sni_server(gnutls_session_t session) { - int rv; - unsigned int sni_type; - size_t data_len = MAX_HOST_LEN; - char sni_name[MAX_HOST_LEN]; - mgs_handle_t *ctxt; + int rv; + unsigned int sni_type; + size_t data_len = MAX_HOST_LEN; + char sni_name[MAX_HOST_LEN]; + mgs_handle_t *ctxt; #if USING_2_1_RECENT - vhost_cb_rec cbx; + vhost_cb_rec cbx; #else - server_rec *s; - mgs_srvconf_rec *tsc; + server_rec *s; + mgs_srvconf_rec *tsc; #endif - if (session == NULL) - return NULL; + if (session == NULL) + return NULL; - _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); - ctxt = gnutls_transport_get_ptr(session); + _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); + ctxt = gnutls_transport_get_ptr(session); - rv = gnutls_server_name_get(ctxt->session, sni_name, - &data_len, &sni_type, 0); + rv = gnutls_server_name_get(ctxt->session, sni_name, + &data_len, &sni_type, 0); - if (rv != 0) { - return NULL; - } + if (rv != 0) { + return NULL; + } - if (sni_type != GNUTLS_NAME_DNS) { - ap_log_error(APLOG_MARK, APLOG_CRIT, 0, - ctxt->c->base_server, - "GnuTLS: Unknown type '%d' for SNI: " - "'%s'", sni_type, sni_name); - return NULL; - } + if (sni_type != GNUTLS_NAME_DNS) { + ap_log_error(APLOG_MARK, APLOG_CRIT, 0, + ctxt->c->base_server, + "GnuTLS: Unknown type '%d' for SNI: " + "'%s'", sni_type, sni_name); + return NULL; + } /** * Code in the Core already sets up the c->base_server as the base * for this IP/Port combo. Trust that the core did the 'right' thing. */ #if USING_2_1_RECENT - cbx.ctxt = ctxt; - cbx.sc = NULL; - cbx.sni_name = sni_name; - - rv = ap_vhost_iterate_given_conn(ctxt->c, vhost_cb, &cbx); - if (rv == 1) { - return cbx.sc; - } -#else - for (s = ap_server_conf; s; s = s->next) { + cbx.ctxt = ctxt; + cbx.sc = NULL; + cbx.sni_name = sni_name; - tsc = (mgs_srvconf_rec *) ap_get_module_config(s->module_config, - &gnutls_module); - if (tsc->enabled != GNUTLS_ENABLED_TRUE) { - continue; + rv = ap_vhost_iterate_given_conn(ctxt->c, vhost_cb, &cbx); + if (rv == 1) { + return cbx.sc; } +#else + for (s = ap_server_conf; s; s = s->next) { + + tsc = + (mgs_srvconf_rec *) + ap_get_module_config(s->module_config, &gnutls_module); + if (tsc->enabled != GNUTLS_ENABLED_TRUE) { + continue; + } #if MOD_GNUTLS_DEBUG - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, - ctxt->c->base_server, - "GnuTLS: sni-x509 cn: %s/%d pk: %s s: 0x%08X s->n: 0x%08X sc: 0x%08X", - tsc->cert_cn, rv, - gnutls_pk_algorithm_get_name - (gnutls_x509_privkey_get_pk_algorithm - (ctxt->sc->privkey_x509)), (unsigned int) s, - (unsigned int) s->next, (unsigned int) tsc); + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, + ctxt->c->base_server, + "GnuTLS: sni-x509 cn: %s/%d pk: %s s: 0x%08X s->n: 0x%08X sc: 0x%08X", + tsc->cert_cn, rv, + gnutls_pk_algorithm_get_name + (gnutls_x509_privkey_get_pk_algorithm + (ctxt->sc->privkey_x509)), (unsigned int) s, + (unsigned int) s->next, (unsigned int) tsc); #endif - /* The CN can contain a * -- this will match those too. */ - if (ap_strcasecmp_match(sni_name, tsc->cert_cn) == 0) { + /* The CN can contain a * -- this will match those too. */ + if (ap_strcasecmp_match(sni_name, tsc->cert_cn) == 0) { #if MOD_GNUTLS_DEBUG - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, - ctxt->c->base_server, - "GnuTLS: Virtual Host: " - "'%s' == '%s'", tsc->cert_cn, sni_name); + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, + ctxt->c->base_server, + "GnuTLS: Virtual Host: " + "'%s' == '%s'", tsc->cert_cn, + sni_name); #endif - return tsc; + return tsc; + } } - } #endif - return NULL; + return NULL; } static const int protocol_priority[] = { - GNUTLS_TLS1_1, GNUTLS_TLS1_0, GNUTLS_SSL3, 0 + GNUTLS_TLS1_1, GNUTLS_TLS1_0, GNUTLS_SSL3, 0 }; static mgs_handle_t *create_gnutls_handle(apr_pool_t * pool, conn_rec * c) { - mgs_handle_t *ctxt; - mgs_srvconf_rec *sc = - (mgs_srvconf_rec *) ap_get_module_config(c->base_server-> - module_config, - &gnutls_module); - - _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); - ctxt = apr_pcalloc(pool, sizeof(*ctxt)); - ctxt->c = c; - ctxt->sc = sc; - ctxt->status = 0; - - ctxt->input_rc = APR_SUCCESS; - ctxt->input_bb = apr_brigade_create(c->pool, c->bucket_alloc); - ctxt->input_cbuf.length = 0; - - ctxt->output_rc = APR_SUCCESS; - ctxt->output_bb = apr_brigade_create(c->pool, c->bucket_alloc); - ctxt->output_blen = 0; - ctxt->output_length = 0; - - gnutls_init(&ctxt->session, GNUTLS_SERVER); - if (session_ticket_key.data != NULL && ctxt->sc->tickets != 0) - gnutls_session_ticket_enable_server(ctxt->session, &session_ticket_key); - - /* because we don't set any default priorities here (we set later at - * the user hello callback) we need to at least set this in order for - * gnutls to be able to read packets. - */ - gnutls_protocol_set_priority(ctxt->session, protocol_priority); + mgs_handle_t *ctxt; + mgs_srvconf_rec *sc = + (mgs_srvconf_rec *) ap_get_module_config(c->base_server-> + module_config, + &gnutls_module); + + _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); + ctxt = apr_pcalloc(pool, sizeof(*ctxt)); + ctxt->c = c; + ctxt->sc = sc; + ctxt->status = 0; + + ctxt->input_rc = APR_SUCCESS; + ctxt->input_bb = apr_brigade_create(c->pool, c->bucket_alloc); + ctxt->input_cbuf.length = 0; + + ctxt->output_rc = APR_SUCCESS; + ctxt->output_bb = apr_brigade_create(c->pool, c->bucket_alloc); + ctxt->output_blen = 0; + ctxt->output_length = 0; + + gnutls_init(&ctxt->session, GNUTLS_SERVER); + if (session_ticket_key.data != NULL && ctxt->sc->tickets != 0) + gnutls_session_ticket_enable_server(ctxt->session, + &session_ticket_key); + + /* because we don't set any default priorities here (we set later at + * the user hello callback) we need to at least set this in order for + * gnutls to be able to read packets. + */ + gnutls_protocol_set_priority(ctxt->session, protocol_priority); - gnutls_handshake_set_post_client_hello_function(ctxt->session, - mgs_select_virtual_server_cb); + gnutls_handshake_set_post_client_hello_function(ctxt->session, + mgs_select_virtual_server_cb); - mgs_cache_session_init(ctxt); + mgs_cache_session_init(ctxt); - return ctxt; + return ctxt; } int mgs_hook_pre_connection(conn_rec * c, void *csd) { - mgs_handle_t *ctxt; - mgs_srvconf_rec *sc; - - _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); - - if (c == NULL) - return DECLINED; - - sc = - (mgs_srvconf_rec *) ap_get_module_config(c->base_server-> - module_config, - &gnutls_module); - - if (!(sc && (sc->enabled == GNUTLS_ENABLED_TRUE))) { - return DECLINED; - } + mgs_handle_t *ctxt; + mgs_srvconf_rec *sc; + + _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); + + if (c == NULL) + return DECLINED; - if(c->remote_addr->hostname) - /* Connection initiated by Apache (mod_proxy) => ignore */ - return OK; + sc = (mgs_srvconf_rec *) ap_get_module_config(c->base_server-> + module_config, + &gnutls_module); - ctxt = create_gnutls_handle(c->pool, c); + if (!(sc && (sc->enabled == GNUTLS_ENABLED_TRUE))) { + return DECLINED; + } + + if (c->remote_addr->hostname) + /* Connection initiated by Apache (mod_proxy) => ignore */ + return OK; + + ctxt = create_gnutls_handle(c->pool, c); - ap_set_module_config(c->conn_config, &gnutls_module, ctxt); + ap_set_module_config(c->conn_config, &gnutls_module, ctxt); - gnutls_transport_set_pull_function(ctxt->session, mgs_transport_read); - gnutls_transport_set_push_function(ctxt->session, mgs_transport_write); - gnutls_transport_set_ptr(ctxt->session, ctxt); + gnutls_transport_set_pull_function(ctxt->session, + mgs_transport_read); + gnutls_transport_set_push_function(ctxt->session, + mgs_transport_write); + gnutls_transport_set_ptr(ctxt->session, ctxt); - ctxt->input_filter = - ap_add_input_filter(GNUTLS_INPUT_FILTER_NAME, ctxt, NULL, c); - ctxt->output_filter = - ap_add_output_filter(GNUTLS_OUTPUT_FILTER_NAME, ctxt, NULL, c); + ctxt->input_filter = + ap_add_input_filter(GNUTLS_INPUT_FILTER_NAME, ctxt, NULL, c); + ctxt->output_filter = + ap_add_output_filter(GNUTLS_OUTPUT_FILTER_NAME, ctxt, NULL, c); - return OK; + return OK; } int mgs_hook_fixups(request_rec * r) { - unsigned char sbuf[GNUTLS_MAX_SESSION_ID]; - char buf[AP_IOBUFSIZE]; - const char *tmp; - size_t len; - mgs_handle_t *ctxt; - int rv = OK; + unsigned char sbuf[GNUTLS_MAX_SESSION_ID]; + char buf[AP_IOBUFSIZE]; + const char *tmp; + size_t len; + mgs_handle_t *ctxt; + int rv = OK; - if (r == NULL) - return DECLINED; + if (r == NULL) + return DECLINED; - _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); - apr_table_t *env = r->subprocess_env; + _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); + apr_table_t *env = r->subprocess_env; - ctxt = - ap_get_module_config(r->connection->conn_config, &gnutls_module); + ctxt = + ap_get_module_config(r->connection->conn_config, + &gnutls_module); - if (!ctxt || ctxt->session == NULL) { - return DECLINED; - } + if (!ctxt || ctxt->session == NULL) { + return DECLINED; + } - apr_table_setn(env, "HTTPS", "on"); + apr_table_setn(env, "HTTPS", "on"); - apr_table_setn(env, "SSL_VERSION_LIBRARY", - "GnuTLS/" LIBGNUTLS_VERSION); - apr_table_setn(env, "SSL_VERSION_INTERFACE", - "mod_gnutls/" MOD_GNUTLS_VERSION); + apr_table_setn(env, "SSL_VERSION_LIBRARY", + "GnuTLS/" LIBGNUTLS_VERSION); + apr_table_setn(env, "SSL_VERSION_INTERFACE", + "mod_gnutls/" MOD_GNUTLS_VERSION); - apr_table_setn(env, "SSL_PROTOCOL", - gnutls_protocol_get_name(gnutls_protocol_get_version - (ctxt->session))); + apr_table_setn(env, "SSL_PROTOCOL", + gnutls_protocol_get_name(gnutls_protocol_get_version + (ctxt->session))); - /* should have been called SSL_CIPHERSUITE instead */ - apr_table_setn(env, "SSL_CIPHER", - gnutls_cipher_suite_get_name(gnutls_kx_get - (ctxt->session), - gnutls_cipher_get(ctxt-> - session), - gnutls_mac_get(ctxt-> - session))); + /* should have been called SSL_CIPHERSUITE instead */ + apr_table_setn(env, "SSL_CIPHER", + gnutls_cipher_suite_get_name(gnutls_kx_get + (ctxt->session), + gnutls_cipher_get + (ctxt->session), + gnutls_mac_get + (ctxt->session))); - apr_table_setn(env, "SSL_COMPRESS_METHOD", - gnutls_compression_get_name(gnutls_compression_get - (ctxt->session))); + apr_table_setn(env, "SSL_COMPRESS_METHOD", + gnutls_compression_get_name(gnutls_compression_get + (ctxt->session))); #ifdef ENABLE_SRP - tmp = gnutls_srp_server_get_username(ctxt->session); - apr_table_setn(env, "SSL_SRP_USER", (tmp!=NULL)?tmp:""); + tmp = gnutls_srp_server_get_username(ctxt->session); + apr_table_setn(env, "SSL_SRP_USER", (tmp != NULL) ? tmp : ""); #endif - if (apr_table_get(env, "SSL_CLIENT_VERIFY") == NULL) - apr_table_setn(env, "SSL_CLIENT_VERIFY", "NONE"); + if (apr_table_get(env, "SSL_CLIENT_VERIFY") == NULL) + apr_table_setn(env, "SSL_CLIENT_VERIFY", "NONE"); - unsigned int key_size = - 8 * gnutls_cipher_get_key_size(gnutls_cipher_get(ctxt->session)); - tmp = apr_psprintf(r->pool, "%u", key_size); + unsigned int key_size = + 8 * + gnutls_cipher_get_key_size(gnutls_cipher_get(ctxt->session)); + tmp = apr_psprintf(r->pool, "%u", key_size); - apr_table_setn(env, "SSL_CIPHER_USEKEYSIZE", tmp); + apr_table_setn(env, "SSL_CIPHER_USEKEYSIZE", tmp); - apr_table_setn(env, "SSL_CIPHER_ALGKEYSIZE", tmp); + apr_table_setn(env, "SSL_CIPHER_ALGKEYSIZE", tmp); - apr_table_setn(env, "SSL_CIPHER_EXPORT", - (key_size <= 40) ? "true" : "false"); + apr_table_setn(env, "SSL_CIPHER_EXPORT", + (key_size <= 40) ? "true" : "false"); - len = sizeof(sbuf); - gnutls_session_get_id(ctxt->session, sbuf, &len); - tmp = mgs_session_id2sz(sbuf, len, buf, sizeof(buf)); - apr_table_setn(env, "SSL_SESSION_ID", apr_pstrdup(r->pool, tmp)); + len = sizeof(sbuf); + gnutls_session_get_id(ctxt->session, sbuf, &len); + tmp = mgs_session_id2sz(sbuf, len, buf, sizeof(buf)); + apr_table_setn(env, "SSL_SESSION_ID", apr_pstrdup(r->pool, tmp)); - if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_X509) - mgs_add_common_cert_vars(r, ctxt->sc->certs_x509[0], 0, - ctxt->sc->export_certificates_enabled); - else if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_OPENPGP) - mgs_add_common_pgpcert_vars(r, ctxt->sc->cert_pgp, 0, - ctxt->sc->export_certificates_enabled); + if (gnutls_certificate_type_get(ctxt->session) == GNUTLS_CRT_X509) + mgs_add_common_cert_vars(r, ctxt->sc->certs_x509[0], 0, + ctxt-> + sc->export_certificates_enabled); + else if (gnutls_certificate_type_get(ctxt->session) == + GNUTLS_CRT_OPENPGP) + mgs_add_common_pgpcert_vars(r, ctxt->sc->cert_pgp, 0, + ctxt-> + sc->export_certificates_enabled); - return rv; + return rv; } int mgs_hook_authz(request_rec * r) { - int rv; - mgs_handle_t *ctxt; - mgs_dirconf_rec *dc; - - if (r == NULL) - return DECLINED; - - dc = ap_get_module_config(r->per_dir_config, - &gnutls_module); - - _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); - ctxt = - ap_get_module_config(r->connection->conn_config, &gnutls_module); - - if (!ctxt || ctxt->session == NULL) { - return DECLINED; - } - - if (dc->client_verify_mode == GNUTLS_CERT_IGNORE) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, - "GnuTLS: Directory set to Ignore Client Certificate!"); - } else { - if (ctxt->sc->client_verify_mode < dc->client_verify_mode) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, - "GnuTLS: Attempting to rehandshake with peer. %d %d", - ctxt->sc->client_verify_mode, - dc->client_verify_mode); - - /* If we already have a client certificate, there's no point in - * re-handshaking... */ - rv = mgs_cert_verify(r, ctxt); - if (rv != DECLINED && rv != HTTP_FORBIDDEN) - return rv; - - gnutls_certificate_server_set_request(ctxt->session, - dc->client_verify_mode); - - if (mgs_rehandshake(ctxt) != 0) { - return HTTP_FORBIDDEN; - } - } else if (ctxt->sc->client_verify_mode == GNUTLS_CERT_IGNORE) { + int rv; + mgs_handle_t *ctxt; + mgs_dirconf_rec *dc; + + if (r == NULL) + return DECLINED; + + dc = ap_get_module_config(r->per_dir_config, &gnutls_module); + + _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); + ctxt = + ap_get_module_config(r->connection->conn_config, + &gnutls_module); + + if (!ctxt || ctxt->session == NULL) { + return DECLINED; + } + + if (dc->client_verify_mode == GNUTLS_CERT_IGNORE) { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, + "GnuTLS: Directory set to Ignore Client Certificate!"); + } else { + if (ctxt->sc->client_verify_mode < dc->client_verify_mode) { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, + "GnuTLS: Attempting to rehandshake with peer. %d %d", + ctxt->sc->client_verify_mode, + dc->client_verify_mode); + + /* If we already have a client certificate, there's no point in + * re-handshaking... */ + rv = mgs_cert_verify(r, ctxt); + if (rv != DECLINED && rv != HTTP_FORBIDDEN) + return rv; + + gnutls_certificate_server_set_request + (ctxt->session, dc->client_verify_mode); + + if (mgs_rehandshake(ctxt) != 0) { + return HTTP_FORBIDDEN; + } + } else if (ctxt->sc->client_verify_mode == + GNUTLS_CERT_IGNORE) { #if MOD_GNUTLS_DEBUG - ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, - "GnuTLS: Peer is set to IGNORE"); + ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, + "GnuTLS: Peer is set to IGNORE"); #endif - return DECLINED; - } - rv = mgs_cert_verify(r, ctxt); - if (rv != DECLINED && - (rv != HTTP_FORBIDDEN || - dc->client_verify_mode == GNUTLS_CERT_REQUIRE)) { - return rv; + return DECLINED; + } + rv = mgs_cert_verify(r, ctxt); + if (rv != DECLINED && + (rv != HTTP_FORBIDDEN || + dc->client_verify_mode == GNUTLS_CERT_REQUIRE)) { + return rv; + } } - } - return DECLINED; + return DECLINED; } /* variables that are not sent by default: @@ -895,359 +933,413 @@ static void mgs_add_common_cert_vars(request_rec * r, gnutls_x509_crt_t cert, int side, int export_certificates_enabled) { - unsigned char sbuf[64]; /* buffer to hold serials */ - char buf[AP_IOBUFSIZE]; - const char *tmp; - char *tmp2; - size_t len; - int ret, i; - - if (r == NULL) - return; - - apr_table_t *env = r->subprocess_env; - - _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); - if (export_certificates_enabled != 0) { - char cert_buf[10 * 1024]; - len = sizeof(cert_buf); - - if (gnutls_x509_crt_export - (cert, GNUTLS_X509_FMT_PEM, cert_buf, &len) >= 0) - apr_table_setn(env, - apr_pstrcat(r->pool, MGS_SIDE, "_CERT", NULL), - apr_pstrmemdup(r->pool, cert_buf, len)); - - } - - len = sizeof(buf); - gnutls_x509_crt_get_dn(cert, buf, &len); - apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_S_DN", NULL), - apr_pstrmemdup(r->pool, buf, len)); - - len = sizeof(buf); - gnutls_x509_crt_get_issuer_dn(cert, buf, &len); - apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_I_DN", NULL), - apr_pstrmemdup(r->pool, buf, len)); - - len = sizeof(sbuf); - gnutls_x509_crt_get_serial(cert, sbuf, &len); - tmp = mgs_session_id2sz(sbuf, len, buf, sizeof(buf)); - apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_M_SERIAL", NULL), - apr_pstrdup(r->pool, tmp)); - - ret = gnutls_x509_crt_get_version(cert); - if (ret > 0) + unsigned char sbuf[64]; /* buffer to hold serials */ + char buf[AP_IOBUFSIZE]; + const char *tmp; + char *tmp2; + size_t len; + int ret, i; + + if (r == NULL) + return; + + apr_table_t *env = r->subprocess_env; + + _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); + if (export_certificates_enabled != 0) { + char cert_buf[10 * 1024]; + len = sizeof(cert_buf); + + if (gnutls_x509_crt_export + (cert, GNUTLS_X509_FMT_PEM, cert_buf, &len) >= 0) + apr_table_setn(env, + apr_pstrcat(r->pool, MGS_SIDE, + "_CERT", NULL), + apr_pstrmemdup(r->pool, cert_buf, + len)); + + } + + len = sizeof(buf); + gnutls_x509_crt_get_dn(cert, buf, &len); + apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_S_DN", NULL), + apr_pstrmemdup(r->pool, buf, len)); + + len = sizeof(buf); + gnutls_x509_crt_get_issuer_dn(cert, buf, &len); + apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_I_DN", NULL), + apr_pstrmemdup(r->pool, buf, len)); + + len = sizeof(sbuf); + gnutls_x509_crt_get_serial(cert, sbuf, &len); + tmp = mgs_session_id2sz(sbuf, len, buf, sizeof(buf)); apr_table_setn(env, - apr_pstrcat(r->pool, MGS_SIDE, "_M_VERSION", NULL), - apr_psprintf(r->pool, "%u", ret)); - - apr_table_setn(env, - apr_pstrcat(r->pool, MGS_SIDE, "_CERT_TYPE", NULL), "X.509"); - - tmp = - mgs_time2sz(gnutls_x509_crt_get_expiration_time - (cert), buf, sizeof(buf)); - apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_V_END", NULL), - apr_pstrdup(r->pool, tmp)); - - tmp = - mgs_time2sz(gnutls_x509_crt_get_activation_time - (cert), buf, sizeof(buf)); - apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_V_START", NULL), - apr_pstrdup(r->pool, tmp)); - - ret = gnutls_x509_crt_get_signature_algorithm(cert); - if (ret >= 0) { - apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_A_SIG", NULL), - gnutls_sign_algorithm_get_name(ret)); - } - - ret = gnutls_x509_crt_get_pk_algorithm(cert, NULL); - if (ret >= 0) { - apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_A_KEY", NULL), - gnutls_pk_algorithm_get_name(ret)); - } - - /* export all the alternative names (DNS, RFC822 and URI) */ - for (i = 0; !(ret < 0); i++) { - len = 0; - ret = gnutls_x509_crt_get_subject_alt_name(cert, i, - NULL, &len, NULL); - - if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER && len > 1) { - tmp2 = apr_palloc(r->pool, len + 1); - - ret = - gnutls_x509_crt_get_subject_alt_name(cert, i, tmp2, &len, - NULL); - tmp2[len] = 0; - - if (ret == GNUTLS_SAN_DNSNAME) { - apr_table_setn(env, - apr_psprintf(r->pool, "%s_S_AN%u", MGS_SIDE, i), - apr_psprintf(r->pool, "DNSNAME:%s", tmp2)); - } else if (ret == GNUTLS_SAN_RFC822NAME) { + apr_pstrcat(r->pool, MGS_SIDE, "_M_SERIAL", NULL), + apr_pstrdup(r->pool, tmp)); + + ret = gnutls_x509_crt_get_version(cert); + if (ret > 0) apr_table_setn(env, - apr_psprintf(r->pool, "%s_S_AN%u", MGS_SIDE, i), - apr_psprintf(r->pool, "RFC822NAME:%s", tmp2)); - } else if (ret == GNUTLS_SAN_URI) { + apr_pstrcat(r->pool, MGS_SIDE, "_M_VERSION", + NULL), apr_psprintf(r->pool, + "%u", ret)); + + apr_table_setn(env, + apr_pstrcat(r->pool, MGS_SIDE, "_CERT_TYPE", NULL), + "X.509"); + + tmp = + mgs_time2sz(gnutls_x509_crt_get_expiration_time + (cert), buf, sizeof(buf)); + apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_V_END", NULL), + apr_pstrdup(r->pool, tmp)); + + tmp = + mgs_time2sz(gnutls_x509_crt_get_activation_time + (cert), buf, sizeof(buf)); + apr_table_setn(env, + apr_pstrcat(r->pool, MGS_SIDE, "_V_START", NULL), + apr_pstrdup(r->pool, tmp)); + + ret = gnutls_x509_crt_get_signature_algorithm(cert); + if (ret >= 0) { apr_table_setn(env, - apr_psprintf(r->pool, "%s_S_AN%u", MGS_SIDE, i), - apr_psprintf(r->pool, "URI:%s", tmp2)); - } else { + apr_pstrcat(r->pool, MGS_SIDE, "_A_SIG", + NULL), + gnutls_sign_algorithm_get_name(ret)); + } + + ret = gnutls_x509_crt_get_pk_algorithm(cert, NULL); + if (ret >= 0) { apr_table_setn(env, - apr_psprintf(r->pool, "%s_S_AN%u", MGS_SIDE, i), - "UNSUPPORTED"); - } + apr_pstrcat(r->pool, MGS_SIDE, "_A_KEY", + NULL), + gnutls_pk_algorithm_get_name(ret)); + } + + /* export all the alternative names (DNS, RFC822 and URI) */ + for (i = 0; !(ret < 0); i++) { + len = 0; + ret = gnutls_x509_crt_get_subject_alt_name(cert, i, + NULL, &len, + NULL); + + if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER && len > 1) { + tmp2 = apr_palloc(r->pool, len + 1); + + ret = + gnutls_x509_crt_get_subject_alt_name(cert, i, + tmp2, + &len, + NULL); + tmp2[len] = 0; + + if (ret == GNUTLS_SAN_DNSNAME) { + apr_table_setn(env, + apr_psprintf(r->pool, + "%s_S_AN%u", + MGS_SIDE, i), + apr_psprintf(r->pool, + "DNSNAME:%s", + tmp2)); + } else if (ret == GNUTLS_SAN_RFC822NAME) { + apr_table_setn(env, + apr_psprintf(r->pool, + "%s_S_AN%u", + MGS_SIDE, i), + apr_psprintf(r->pool, + "RFC822NAME:%s", + tmp2)); + } else if (ret == GNUTLS_SAN_URI) { + apr_table_setn(env, + apr_psprintf(r->pool, + "%s_S_AN%u", + MGS_SIDE, i), + apr_psprintf(r->pool, + "URI:%s", + tmp2)); + } else { + apr_table_setn(env, + apr_psprintf(r->pool, + "%s_S_AN%u", + MGS_SIDE, i), + "UNSUPPORTED"); + } + } } - } } static void -mgs_add_common_pgpcert_vars(request_rec * r, gnutls_openpgp_crt_t cert, int side, - int export_certificates_enabled) +mgs_add_common_pgpcert_vars(request_rec * r, gnutls_openpgp_crt_t cert, + int side, int export_certificates_enabled) { - unsigned char sbuf[64]; /* buffer to hold serials */ - char buf[AP_IOBUFSIZE]; - const char *tmp; - size_t len; - int ret; - - if (r == NULL) - return; - - _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); - apr_table_t *env = r->subprocess_env; - - if (export_certificates_enabled != 0) { - char cert_buf[10 * 1024]; - len = sizeof(cert_buf); - - if (gnutls_openpgp_crt_export - (cert, GNUTLS_OPENPGP_FMT_BASE64, cert_buf, &len) >= 0) - apr_table_setn(env, - apr_pstrcat(r->pool, MGS_SIDE, "_CERT", NULL), - apr_pstrmemdup(r->pool, cert_buf, len)); - - } - - len = sizeof(buf); - gnutls_openpgp_crt_get_name(cert, 0, buf, &len); - apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_NAME", NULL), - apr_pstrmemdup(r->pool, buf, len)); - - len = sizeof(sbuf); - gnutls_openpgp_crt_get_fingerprint(cert, sbuf, &len); - tmp = mgs_session_id2sz(sbuf, len, buf, sizeof(buf)); - apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_FINGERPRINT", NULL), - apr_pstrdup(r->pool, tmp)); - - ret = gnutls_openpgp_crt_get_version(cert); - if (ret > 0) + unsigned char sbuf[64]; /* buffer to hold serials */ + char buf[AP_IOBUFSIZE]; + const char *tmp; + size_t len; + int ret; + + if (r == NULL) + return; + + _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); + apr_table_t *env = r->subprocess_env; + + if (export_certificates_enabled != 0) { + char cert_buf[10 * 1024]; + len = sizeof(cert_buf); + + if (gnutls_openpgp_crt_export + (cert, GNUTLS_OPENPGP_FMT_BASE64, cert_buf, &len) >= 0) + apr_table_setn(env, + apr_pstrcat(r->pool, MGS_SIDE, + "_CERT", NULL), + apr_pstrmemdup(r->pool, cert_buf, + len)); + + } + + len = sizeof(buf); + gnutls_openpgp_crt_get_name(cert, 0, buf, &len); + apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_NAME", NULL), + apr_pstrmemdup(r->pool, buf, len)); + + len = sizeof(sbuf); + gnutls_openpgp_crt_get_fingerprint(cert, sbuf, &len); + tmp = mgs_session_id2sz(sbuf, len, buf, sizeof(buf)); apr_table_setn(env, - apr_pstrcat(r->pool, MGS_SIDE, "_M_VERSION", NULL), - apr_psprintf(r->pool, "%u", ret)); - - apr_table_setn(env, - apr_pstrcat(r->pool, MGS_SIDE, "_CERT_TYPE", NULL), "OPENPGP"); - - tmp = - mgs_time2sz(gnutls_openpgp_crt_get_expiration_time - (cert), buf, sizeof(buf)); - apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_V_END", NULL), - apr_pstrdup(r->pool, tmp)); - - tmp = - mgs_time2sz(gnutls_openpgp_crt_get_creation_time - (cert), buf, sizeof(buf)); - apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_V_START", NULL), - apr_pstrdup(r->pool, tmp)); - - ret = gnutls_openpgp_crt_get_pk_algorithm(cert, NULL); - if (ret >= 0) { - apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_A_KEY", NULL), - gnutls_pk_algorithm_get_name(ret)); - } + apr_pstrcat(r->pool, MGS_SIDE, "_FINGERPRINT", + NULL), apr_pstrdup(r->pool, tmp)); + + ret = gnutls_openpgp_crt_get_version(cert); + if (ret > 0) + apr_table_setn(env, + apr_pstrcat(r->pool, MGS_SIDE, "_M_VERSION", + NULL), apr_psprintf(r->pool, + "%u", ret)); + + apr_table_setn(env, + apr_pstrcat(r->pool, MGS_SIDE, "_CERT_TYPE", NULL), + "OPENPGP"); + + tmp = + mgs_time2sz(gnutls_openpgp_crt_get_expiration_time + (cert), buf, sizeof(buf)); + apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_V_END", NULL), + apr_pstrdup(r->pool, tmp)); + + tmp = + mgs_time2sz(gnutls_openpgp_crt_get_creation_time + (cert), buf, sizeof(buf)); + apr_table_setn(env, + apr_pstrcat(r->pool, MGS_SIDE, "_V_START", NULL), + apr_pstrdup(r->pool, tmp)); + + ret = gnutls_openpgp_crt_get_pk_algorithm(cert, NULL); + if (ret >= 0) { + apr_table_setn(env, + apr_pstrcat(r->pool, MGS_SIDE, "_A_KEY", + NULL), + gnutls_pk_algorithm_get_name(ret)); + } } /* TODO: Allow client sending a X.509 certificate chain */ static int mgs_cert_verify(request_rec * r, mgs_handle_t * ctxt) { - const gnutls_datum_t *cert_list; - unsigned int cert_list_size, status; - int rv = GNUTLS_E_NO_CERTIFICATE_FOUND, ret; - unsigned int ch_size = 0; - union { - gnutls_x509_crt_t x509[MAX_CHAIN_SIZE]; - gnutls_openpgp_crt_t pgp; - } cert; - apr_time_t expiration_time, cur_time; - - if (r == NULL || ctxt == NULL || ctxt->session == NULL) - return HTTP_FORBIDDEN; - - _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); - cert_list = - gnutls_certificate_get_peers(ctxt->session, &cert_list_size); - - if (cert_list == NULL || cert_list_size == 0) { - /* It is perfectly OK for a client not to send a certificate if on REQUEST mode + const gnutls_datum_t *cert_list; + unsigned int cert_list_size, status; + int rv = GNUTLS_E_NO_CERTIFICATE_FOUND, ret; + unsigned int ch_size = 0; + union { + gnutls_x509_crt_t x509[MAX_CHAIN_SIZE]; + gnutls_openpgp_crt_t pgp; + } cert; + apr_time_t expiration_time, cur_time; + + if (r == NULL || ctxt == NULL || ctxt->session == NULL) + return HTTP_FORBIDDEN; + + _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); + cert_list = + gnutls_certificate_get_peers(ctxt->session, &cert_list_size); + + if (cert_list == NULL || cert_list_size == 0) { + /* It is perfectly OK for a client not to send a certificate if on REQUEST mode + */ + if (ctxt->sc->client_verify_mode == GNUTLS_CERT_REQUEST) + return OK; + + /* no certificate provided by the client, but one was required. */ + ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, + "GnuTLS: Failed to Verify Peer: " + "Client did not submit a certificate"); + return HTTP_FORBIDDEN; + } + + if (gnutls_certificate_type_get(ctxt->session) == GNUTLS_CRT_X509) { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, + "GnuTLS: A Chain of %d certificate(s) was provided for validation", + cert_list_size); + + for (ch_size = 0; ch_size < cert_list_size; ch_size++) { + gnutls_x509_crt_init(&cert.x509[ch_size]); + rv = gnutls_x509_crt_import(cert.x509[ch_size], + &cert_list[ch_size], + GNUTLS_X509_FMT_DER); + // When failure to import, leave the loop + if (rv != GNUTLS_E_SUCCESS) { + if (ch_size < 1) { + ap_log_rerror(APLOG_MARK, + APLOG_INFO, 0, r, + "GnuTLS: Failed to Verify Peer: " + "Failed to import peer certificates."); + ret = HTTP_FORBIDDEN; + goto exit; + } + ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, + "GnuTLS: Failed to import some peer certificates. Using %d certificates", + ch_size); + rv = GNUTLS_E_SUCCESS; + break; + } + } + } else if (gnutls_certificate_type_get(ctxt->session) == + GNUTLS_CRT_OPENPGP) { + if (cert_list_size > 1) { + ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, + "GnuTLS: Failed to Verify Peer: " + "Chained Client Certificates are not supported."); + return HTTP_FORBIDDEN; + } + + gnutls_openpgp_crt_init(&cert.pgp); + rv = gnutls_openpgp_crt_import(cert.pgp, &cert_list[0], + GNUTLS_OPENPGP_FMT_RAW); + + } else + return HTTP_FORBIDDEN; + + if (rv < 0) { + ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, + "GnuTLS: Failed to Verify Peer: " + "Failed to import peer certificates."); + ret = HTTP_FORBIDDEN; + goto exit; + } + + if (gnutls_certificate_type_get(ctxt->session) == GNUTLS_CRT_X509) { + apr_time_ansi_put(&expiration_time, + gnutls_x509_crt_get_expiration_time + (cert.x509[0])); + + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, + "GnuTLS: Verifying list of %d certificate(s)", + ch_size); + rv = gnutls_x509_crt_list_verify(cert.x509, ch_size, + ctxt->sc->ca_list, + ctxt->sc->ca_list_size, + NULL, 0, 0, &status); + } else { + apr_time_ansi_put(&expiration_time, + gnutls_openpgp_crt_get_expiration_time + (cert.pgp)); + + rv = gnutls_openpgp_crt_verify_ring(cert.pgp, + ctxt->sc->pgp_list, 0, + &status); + } + + if (rv < 0) { + ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, + "GnuTLS: Failed to Verify Peer certificate: (%d) %s", + rv, gnutls_strerror(rv)); + if (rv == GNUTLS_E_NO_CERTIFICATE_FOUND) + ap_log_rerror(APLOG_MARK, APLOG_EMERG, 0, r, + "GnuTLS: No certificate was found for verification. Did you set the GnuTLSX509CAFile or GnuTLSPGPKeyringFile directives?"); + ret = HTTP_FORBIDDEN; + goto exit; + } + + /* TODO: X509 CRL Verification. */ + /* May add later if anyone needs it. */ - if (ctxt->sc->client_verify_mode == GNUTLS_CERT_REQUEST) - return OK; - - /* no certificate provided by the client, but one was required. */ - ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, - "GnuTLS: Failed to Verify Peer: " - "Client did not submit a certificate"); - return HTTP_FORBIDDEN; - } - - if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_X509) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, - "GnuTLS: A Chain of %d certificate(s) was provided for validation", cert_list_size); - - for (ch_size = 0; ch_sizesession) == GNUTLS_CRT_OPENPGP) { - if (cert_list_size > 1) { - ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, - "GnuTLS: Failed to Verify Peer: " - "Chained Client Certificates are not supported."); - return HTTP_FORBIDDEN; - } - - gnutls_openpgp_crt_init(&cert.pgp); - rv = gnutls_openpgp_crt_import(cert.pgp, &cert_list[0], GNUTLS_OPENPGP_FMT_RAW); - - } else return HTTP_FORBIDDEN; - - if (rv < 0) { - ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, - "GnuTLS: Failed to Verify Peer: " - "Failed to import peer certificates."); - ret = HTTP_FORBIDDEN; - goto exit; - } - - if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_X509) { - apr_time_ansi_put(&expiration_time, - gnutls_x509_crt_get_expiration_time(cert.x509[0])); - - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, - "GnuTLS: Verifying list of %d certificate(s)", ch_size); - rv = gnutls_x509_crt_list_verify(cert.x509, ch_size, - ctxt->sc->ca_list, ctxt->sc->ca_list_size, - NULL, 0, 0, &status); - } else { - apr_time_ansi_put(&expiration_time, - gnutls_openpgp_crt_get_expiration_time(cert.pgp)); - - rv = gnutls_openpgp_crt_verify_ring(cert.pgp, ctxt->sc->pgp_list, - 0, &status); - } - - if (rv < 0) { - ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, - "GnuTLS: Failed to Verify Peer certificate: (%d) %s", - rv, gnutls_strerror(rv)); - if (rv == GNUTLS_E_NO_CERTIFICATE_FOUND) - ap_log_rerror(APLOG_MARK, APLOG_EMERG, 0, r, - "GnuTLS: No certificate was found for verification. Did you set the GnuTLSX509CAFile or GnuTLSPGPKeyringFile directives?"); - ret = HTTP_FORBIDDEN; - goto exit; - } - - /* TODO: X509 CRL Verification. */ - /* May add later if anyone needs it. - */ - /* ret = gnutls_x509_crt_check_revocation(crt, crl_list, crl_list_size); */ - - cur_time = apr_time_now(); - - if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) { - ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, - "GnuTLS: Could not find Signer for Peer Certificate"); - } - - if (status & GNUTLS_CERT_SIGNER_NOT_CA) { - ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, - "GnuTLS: Peer's Certificate signer is not a CA"); - } - - if (status & GNUTLS_CERT_INSECURE_ALGORITHM) { - ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, - "GnuTLS: Peer's Certificate is using insecure algorithms"); - } - - if (status & GNUTLS_CERT_EXPIRED || status & GNUTLS_CERT_NOT_ACTIVATED) { - ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, - "GnuTLS: Peer's Certificate signer is expired or not yet activated"); - } - - if (status & GNUTLS_CERT_INVALID) { - ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, - "GnuTLS: Peer Certificate is invalid."); - } else if (status & GNUTLS_CERT_REVOKED) { - ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, - "GnuTLS: Peer Certificate is revoked."); - } - - if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_X509) - mgs_add_common_cert_vars(r, cert.x509[0], 1, - ctxt->sc->export_certificates_enabled); - else if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_OPENPGP) - mgs_add_common_pgpcert_vars(r, cert.pgp, 1, - ctxt->sc->export_certificates_enabled); - - { - /* days remaining */ - unsigned long remain = - (apr_time_sec(expiration_time) - - apr_time_sec(cur_time)) / 86400; - apr_table_setn(r->subprocess_env, "SSL_CLIENT_V_REMAIN", - apr_psprintf(r->pool, "%lu", remain)); - } - - if (status == 0) { - apr_table_setn(r->subprocess_env, "SSL_CLIENT_VERIFY", "SUCCESS"); - ret = OK; - } else { - apr_table_setn(r->subprocess_env, "SSL_CLIENT_VERIFY", "FAILED"); - if (ctxt->sc->client_verify_mode == GNUTLS_CERT_REQUEST) - ret = OK; - else - ret = HTTP_FORBIDDEN; - } - - exit: - if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_X509) { - int i; - for (i=0; isession) == GNUTLS_CRT_OPENPGP) - gnutls_openpgp_crt_deinit(cert.pgp); - return ret; + /* ret = gnutls_x509_crt_check_revocation(crt, crl_list, crl_list_size); */ + + cur_time = apr_time_now(); + + if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) { + ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, + "GnuTLS: Could not find Signer for Peer Certificate"); + } + + if (status & GNUTLS_CERT_SIGNER_NOT_CA) { + ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, + "GnuTLS: Peer's Certificate signer is not a CA"); + } + + if (status & GNUTLS_CERT_INSECURE_ALGORITHM) { + ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, + "GnuTLS: Peer's Certificate is using insecure algorithms"); + } + + if (status & GNUTLS_CERT_EXPIRED + || status & GNUTLS_CERT_NOT_ACTIVATED) { + ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, + "GnuTLS: Peer's Certificate signer is expired or not yet activated"); + } + + if (status & GNUTLS_CERT_INVALID) { + ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, + "GnuTLS: Peer Certificate is invalid."); + } else if (status & GNUTLS_CERT_REVOKED) { + ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, + "GnuTLS: Peer Certificate is revoked."); + } + + if (gnutls_certificate_type_get(ctxt->session) == GNUTLS_CRT_X509) + mgs_add_common_cert_vars(r, cert.x509[0], 1, + ctxt-> + sc->export_certificates_enabled); + else if (gnutls_certificate_type_get(ctxt->session) == + GNUTLS_CRT_OPENPGP) + mgs_add_common_pgpcert_vars(r, cert.pgp, 1, + ctxt-> + sc->export_certificates_enabled); + + { + /* days remaining */ + unsigned long remain = + (apr_time_sec(expiration_time) - + apr_time_sec(cur_time)) / 86400; + apr_table_setn(r->subprocess_env, "SSL_CLIENT_V_REMAIN", + apr_psprintf(r->pool, "%lu", remain)); + } + + if (status == 0) { + apr_table_setn(r->subprocess_env, "SSL_CLIENT_VERIFY", + "SUCCESS"); + ret = OK; + } else { + apr_table_setn(r->subprocess_env, "SSL_CLIENT_VERIFY", + "FAILED"); + if (ctxt->sc->client_verify_mode == GNUTLS_CERT_REQUEST) + ret = OK; + else + ret = HTTP_FORBIDDEN; + } + + exit: + if (gnutls_certificate_type_get(ctxt->session) == GNUTLS_CRT_X509) { + int i; + for (i = 0; i < ch_size; i++) { + gnutls_x509_crt_deinit(cert.x509[i]); + } + } else if (gnutls_certificate_type_get(ctxt->session) == + GNUTLS_CRT_OPENPGP) + gnutls_openpgp_crt_deinit(cert.pgp); + return ret; } diff --git a/src/gnutls_io.c b/src/gnutls_io.c index 174a424..37b73e7 100644 --- a/src/gnutls_io.c +++ b/src/gnutls_io.c @@ -32,67 +32,64 @@ alloc) static apr_status_t gnutls_io_filter_error(ap_filter_t * f, - apr_bucket_brigade * bb, - apr_status_t status) + apr_bucket_brigade * bb, + apr_status_t status) { - mgs_handle_t *ctxt = (mgs_handle_t *) f->ctx; - apr_bucket *bucket; + mgs_handle_t *ctxt = (mgs_handle_t *) f->ctx; + apr_bucket *bucket; - switch (status) { - case HTTP_BAD_REQUEST: - /* log the situation */ - ap_log_error(APLOG_MARK, APLOG_INFO, 0, - f->c->base_server, - "GnuTLS handshake failed: HTTP spoken on HTTPS port; " - "trying to send HTML error page"); + switch (status) { + case HTTP_BAD_REQUEST: + /* log the situation */ + ap_log_error(APLOG_MARK, APLOG_INFO, 0, + f->c->base_server, + "GnuTLS handshake failed: HTTP spoken on HTTPS port; " + "trying to send HTML error page"); - ctxt->status = -1; + ctxt->status = -1; - /* fake the request line */ - bucket = HTTP_ON_HTTPS_PORT_BUCKET(f->c->bucket_alloc); - break; + /* fake the request line */ + bucket = HTTP_ON_HTTPS_PORT_BUCKET(f->c->bucket_alloc); + break; - default: - return status; - } + default: + return status; + } - APR_BRIGADE_INSERT_TAIL(bb, bucket); - bucket = apr_bucket_eos_create(f->c->bucket_alloc); - APR_BRIGADE_INSERT_TAIL(bb, bucket); + APR_BRIGADE_INSERT_TAIL(bb, bucket); + bucket = apr_bucket_eos_create(f->c->bucket_alloc); + APR_BRIGADE_INSERT_TAIL(bb, bucket); - return APR_SUCCESS; + return APR_SUCCESS; } -static int char_buffer_read(mgs_char_buffer_t * buffer, char *in, - int inl) +static int char_buffer_read(mgs_char_buffer_t * buffer, char *in, int inl) { - if (!buffer->length) { - return 0; - } - - if (buffer->length > inl) { - /* we have have enough to fill the caller's buffer */ - memmove(in, buffer->value, inl); - buffer->value += inl; - buffer->length -= inl; - } - else { - /* swallow remainder of the buffer */ - memmove(in, buffer->value, buffer->length); - inl = buffer->length; - buffer->value = NULL; - buffer->length = 0; - } - - return inl; + if (!buffer->length) { + return 0; + } + + if (buffer->length > inl) { + /* we have have enough to fill the caller's buffer */ + memmove(in, buffer->value, inl); + buffer->value += inl; + buffer->length -= inl; + } else { + /* swallow remainder of the buffer */ + memmove(in, buffer->value, buffer->length); + inl = buffer->length; + buffer->value = NULL; + buffer->length = 0; + } + + return inl; } -static int char_buffer_write(mgs_char_buffer_t * buffer, char *in, - int inl) +static int char_buffer_write(mgs_char_buffer_t * buffer, char *in, int inl) { - buffer->value = in; - buffer->length = inl; - return inl; + buffer->value = in; + buffer->length = inl; + return inl; } /** @@ -101,679 +98,715 @@ static int char_buffer_write(mgs_char_buffer_t * buffer, char *in, * proceeds. It will read at most *len bytes. */ static apr_status_t brigade_consume(apr_bucket_brigade * bb, - apr_read_type_e block, - char *c, apr_size_t * len) + apr_read_type_e block, + char *c, apr_size_t * len) { - apr_size_t actual = 0; - apr_status_t status = APR_SUCCESS; - - while (!APR_BRIGADE_EMPTY(bb)) { - apr_bucket *b = APR_BRIGADE_FIRST(bb); - const char *str; - apr_size_t str_len; - apr_size_t consume; - - /* Justin points out this is an http-ism that might - * not fit if brigade_consume is added to APR. Perhaps - * apr_bucket_read(eos_bucket) should return APR_EOF? - * Then this becomes mainline instead of a one-off. - */ - if (APR_BUCKET_IS_EOS(b)) { - status = APR_EOF; - break; - } - - /* The reason I'm not offering brigade_consume yet - * across to apr-util is that the following call - * illustrates how borked that API really is. For - * this sort of case (caller provided buffer) it - * would be much more trivial for apr_bucket_consume - * to do all the work that follows, based on the - * particular characteristics of the bucket we are - * consuming here. - */ - status = apr_bucket_read(b, &str, &str_len, block); - - if (status != APR_SUCCESS) { - if (APR_STATUS_IS_EOF(status)) { - /* This stream bucket was consumed */ - apr_bucket_delete(b); - continue; - } - break; - } - - if (str_len > 0) { - /* Do not block once some data has been consumed */ - block = APR_NONBLOCK_READ; - - /* Assure we don't overflow. */ - consume = (str_len + actual > *len) ? *len - actual : str_len; - - memcpy(c, str, consume); - - c += consume; - actual += consume; - - if (consume >= b->length) { - /* This physical bucket was consumed */ - apr_bucket_delete(b); - } - else { - /* Only part of this physical bucket was consumed */ - b->start += consume; - b->length -= consume; - } - } - else if (b->length == 0) { - apr_bucket_delete(b); - } - - /* This could probably be actual == *len, but be safe from stray - * photons. */ - if (actual >= *len) { - break; - } - } - - *len = actual; - return status; + apr_size_t actual = 0; + apr_status_t status = APR_SUCCESS; + + while (!APR_BRIGADE_EMPTY(bb)) { + apr_bucket *b = APR_BRIGADE_FIRST(bb); + const char *str; + apr_size_t str_len; + apr_size_t consume; + + /* Justin points out this is an http-ism that might + * not fit if brigade_consume is added to APR. Perhaps + * apr_bucket_read(eos_bucket) should return APR_EOF? + * Then this becomes mainline instead of a one-off. + */ + if (APR_BUCKET_IS_EOS(b)) { + status = APR_EOF; + break; + } + + /* The reason I'm not offering brigade_consume yet + * across to apr-util is that the following call + * illustrates how borked that API really is. For + * this sort of case (caller provided buffer) it + * would be much more trivial for apr_bucket_consume + * to do all the work that follows, based on the + * particular characteristics of the bucket we are + * consuming here. + */ + status = apr_bucket_read(b, &str, &str_len, block); + + if (status != APR_SUCCESS) { + if (APR_STATUS_IS_EOF(status)) { + /* This stream bucket was consumed */ + apr_bucket_delete(b); + continue; + } + break; + } + + if (str_len > 0) { + /* Do not block once some data has been consumed */ + block = APR_NONBLOCK_READ; + + /* Assure we don't overflow. */ + consume = + (str_len + actual > + *len) ? *len - actual : str_len; + + memcpy(c, str, consume); + + c += consume; + actual += consume; + + if (consume >= b->length) { + /* This physical bucket was consumed */ + apr_bucket_delete(b); + } else { + /* Only part of this physical bucket was consumed */ + b->start += consume; + b->length -= consume; + } + } else if (b->length == 0) { + apr_bucket_delete(b); + } + + /* This could probably be actual == *len, but be safe from stray + * photons. */ + if (actual >= *len) { + break; + } + } + + *len = actual; + return status; } static apr_status_t gnutls_io_input_read(mgs_handle_t * ctxt, - char *buf, apr_size_t * len) + char *buf, apr_size_t * len) { - apr_size_t wanted = *len; - apr_size_t bytes = 0; - int rc; - - *len = 0; - - /* If we have something leftover from last time, try that first. */ - if ((bytes = char_buffer_read(&ctxt->input_cbuf, buf, wanted))) { - *len = bytes; - if (ctxt->input_mode == AP_MODE_SPECULATIVE) { - /* We want to rollback this read. */ - if (ctxt->input_cbuf.length > 0) { - ctxt->input_cbuf.value -= bytes; - ctxt->input_cbuf.length += bytes; - } - else { - char_buffer_write(&ctxt->input_cbuf, buf, (int) bytes); - } - return APR_SUCCESS; - } - /* This could probably be *len == wanted, but be safe from stray - * photons. - */ - if (*len >= wanted) { - return APR_SUCCESS; - } - if (ctxt->input_mode == AP_MODE_GETLINE) { - if (memchr(buf, APR_ASCII_LF, *len)) { - return APR_SUCCESS; - } - } - else { - /* Down to a nonblock pattern as we have some data already - */ - ctxt->input_block = APR_NONBLOCK_READ; - } - } - - if (ctxt->session == NULL) { - return APR_EGENERAL; - } - - while (1) { - - rc = gnutls_record_recv(ctxt->session, buf + bytes, wanted - bytes); - - if (rc > 0) { - *len += rc; - if (ctxt->input_mode == AP_MODE_SPECULATIVE) { - /* We want to rollback this read. */ - char_buffer_write(&ctxt->input_cbuf, buf, rc); - } - return ctxt->input_rc; - } - else if (rc == 0) { - /* If EAGAIN, we will loop given a blocking read, - * otherwise consider ourselves at EOF. - */ - if (APR_STATUS_IS_EAGAIN(ctxt->input_rc) - || APR_STATUS_IS_EINTR(ctxt->input_rc)) { - /* Already read something, return APR_SUCCESS instead. - * On win32 in particular, but perhaps on other kernels, - * a blocking call isn't 'always' blocking. - */ - if (*len > 0) { - ctxt->input_rc = APR_SUCCESS; - break; - } - if (ctxt->input_block == APR_NONBLOCK_READ) { - break; - } - } - else { - if (*len > 0) { - ctxt->input_rc = APR_SUCCESS; - } - else { - ctxt->input_rc = APR_EOF; - } - break; - } - } - else { /* (rc < 0) */ - - if (rc == GNUTLS_E_REHANDSHAKE) { - /* A client has asked for a new Hankshake. Currently, we don't do it */ - ap_log_error(APLOG_MARK, APLOG_INFO, ctxt->input_rc, - ctxt->c->base_server, - "GnuTLS: Error reading data. Client Requested a New Handshake." - " (%d) '%s'", rc, gnutls_strerror(rc)); - } - else if (rc == GNUTLS_E_WARNING_ALERT_RECEIVED) { - rc = gnutls_alert_get(ctxt->session); - ap_log_error(APLOG_MARK, APLOG_INFO, ctxt->input_rc, - ctxt->c->base_server, - "GnuTLS: Warning Alert From Client: " - " (%d) '%s'", rc, gnutls_alert_get_name(rc)); - } - else if (rc == GNUTLS_E_FATAL_ALERT_RECEIVED) { - rc = gnutls_alert_get(ctxt->session); - ap_log_error(APLOG_MARK, APLOG_INFO, ctxt->input_rc, - ctxt->c->base_server, - "GnuTLS: Fatal Alert From Client: " - "(%d) '%s'", rc, gnutls_alert_get_name(rc)); - ctxt->input_rc = APR_EGENERAL; - break; - } - else { - /* Some Other Error. Report it. Die. */ - if(gnutls_error_is_fatal(rc)) { - ap_log_error(APLOG_MARK, APLOG_INFO, ctxt->input_rc, - ctxt->c->base_server, - "GnuTLS: Error reading data. (%d) '%s'", rc, - gnutls_strerror(rc)); - } - else if(*len > 0) { - ctxt->input_rc = APR_SUCCESS; - break; - } - } - - if (ctxt->input_rc == APR_SUCCESS) { - ctxt->input_rc = APR_EGENERAL; - } - break; - } - } - return ctxt->input_rc; + apr_size_t wanted = *len; + apr_size_t bytes = 0; + int rc; + + *len = 0; + + /* If we have something leftover from last time, try that first. */ + if ((bytes = char_buffer_read(&ctxt->input_cbuf, buf, wanted))) { + *len = bytes; + if (ctxt->input_mode == AP_MODE_SPECULATIVE) { + /* We want to rollback this read. */ + if (ctxt->input_cbuf.length > 0) { + ctxt->input_cbuf.value -= bytes; + ctxt->input_cbuf.length += bytes; + } else { + char_buffer_write(&ctxt->input_cbuf, buf, + (int) bytes); + } + return APR_SUCCESS; + } + /* This could probably be *len == wanted, but be safe from stray + * photons. + */ + if (*len >= wanted) { + return APR_SUCCESS; + } + if (ctxt->input_mode == AP_MODE_GETLINE) { + if (memchr(buf, APR_ASCII_LF, *len)) { + return APR_SUCCESS; + } + } else { + /* Down to a nonblock pattern as we have some data already + */ + ctxt->input_block = APR_NONBLOCK_READ; + } + } + + if (ctxt->session == NULL) { + return APR_EGENERAL; + } + + while (1) { + + rc = gnutls_record_recv(ctxt->session, buf + bytes, + wanted - bytes); + + if (rc > 0) { + *len += rc; + if (ctxt->input_mode == AP_MODE_SPECULATIVE) { + /* We want to rollback this read. */ + char_buffer_write(&ctxt->input_cbuf, buf, + rc); + } + return ctxt->input_rc; + } else if (rc == 0) { + /* If EAGAIN, we will loop given a blocking read, + * otherwise consider ourselves at EOF. + */ + if (APR_STATUS_IS_EAGAIN(ctxt->input_rc) + || APR_STATUS_IS_EINTR(ctxt->input_rc)) { + /* Already read something, return APR_SUCCESS instead. + * On win32 in particular, but perhaps on other kernels, + * a blocking call isn't 'always' blocking. + */ + if (*len > 0) { + ctxt->input_rc = APR_SUCCESS; + break; + } + if (ctxt->input_block == APR_NONBLOCK_READ) { + break; + } + } else { + if (*len > 0) { + ctxt->input_rc = APR_SUCCESS; + } else { + ctxt->input_rc = APR_EOF; + } + break; + } + } else { /* (rc < 0) */ + + if (rc == GNUTLS_E_REHANDSHAKE) { + /* A client has asked for a new Hankshake. Currently, we don't do it */ + ap_log_error(APLOG_MARK, APLOG_INFO, + ctxt->input_rc, + ctxt->c->base_server, + "GnuTLS: Error reading data. Client Requested a New Handshake." + " (%d) '%s'", rc, + gnutls_strerror(rc)); + } else if (rc == GNUTLS_E_WARNING_ALERT_RECEIVED) { + rc = gnutls_alert_get(ctxt->session); + ap_log_error(APLOG_MARK, APLOG_INFO, + ctxt->input_rc, + ctxt->c->base_server, + "GnuTLS: Warning Alert From Client: " + " (%d) '%s'", rc, + gnutls_alert_get_name(rc)); + } else if (rc == GNUTLS_E_FATAL_ALERT_RECEIVED) { + rc = gnutls_alert_get(ctxt->session); + ap_log_error(APLOG_MARK, APLOG_INFO, + ctxt->input_rc, + ctxt->c->base_server, + "GnuTLS: Fatal Alert From Client: " + "(%d) '%s'", rc, + gnutls_alert_get_name(rc)); + ctxt->input_rc = APR_EGENERAL; + break; + } else { + /* Some Other Error. Report it. Die. */ + if (gnutls_error_is_fatal(rc)) { + ap_log_error(APLOG_MARK, + APLOG_INFO, + ctxt->input_rc, + ctxt->c->base_server, + "GnuTLS: Error reading data. (%d) '%s'", + rc, + gnutls_strerror(rc)); + } else if (*len > 0) { + ctxt->input_rc = APR_SUCCESS; + break; + } + } + + if (ctxt->input_rc == APR_SUCCESS) { + ctxt->input_rc = APR_EGENERAL; + } + break; + } + } + return ctxt->input_rc; } static apr_status_t gnutls_io_input_getline(mgs_handle_t * ctxt, - char *buf, apr_size_t * len) + char *buf, apr_size_t * len) { - const char *pos = NULL; - apr_status_t status; - apr_size_t tmplen = *len, buflen = *len, offset = 0; + const char *pos = NULL; + apr_status_t status; + apr_size_t tmplen = *len, buflen = *len, offset = 0; - *len = 0; + *len = 0; - while (tmplen > 0) { - status = gnutls_io_input_read(ctxt, buf + offset, &tmplen); + while (tmplen > 0) { + status = gnutls_io_input_read(ctxt, buf + offset, &tmplen); - if (status != APR_SUCCESS) { - return status; - } + if (status != APR_SUCCESS) { + return status; + } - *len += tmplen; + *len += tmplen; - if ((pos = memchr(buf, APR_ASCII_LF, *len))) { - break; - } + if ((pos = memchr(buf, APR_ASCII_LF, *len))) { + break; + } - offset += tmplen; - tmplen = buflen - offset; - } + offset += tmplen; + tmplen = buflen - offset; + } - if (pos) { - char *value; - int length; - apr_size_t bytes = pos - buf; + if (pos) { + char *value; + int length; + apr_size_t bytes = pos - buf; - bytes += 1; - value = buf + bytes; - length = *len - bytes; + bytes += 1; + value = buf + bytes; + length = *len - bytes; - char_buffer_write(&ctxt->input_cbuf, value, length); + char_buffer_write(&ctxt->input_cbuf, value, length); - *len = bytes; - } + *len = bytes; + } - return APR_SUCCESS; + return APR_SUCCESS; } #define HANDSHAKE_MAX_TRIES 1024 static int gnutls_do_handshake(mgs_handle_t * ctxt) { - int ret; - int errcode; - int maxtries = HANDSHAKE_MAX_TRIES; - - if (ctxt->status != 0 || ctxt->session == NULL) { - return -1; - } - -tryagain: - do { - ret = gnutls_handshake(ctxt->session); - maxtries--; - } while ((ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) && maxtries > 0); - - if (maxtries < 1) { - ctxt->status = -1; + int ret; + int errcode; + int maxtries = HANDSHAKE_MAX_TRIES; + + if (ctxt->status != 0 || ctxt->session == NULL) { + return -1; + } + + tryagain: + do { + ret = gnutls_handshake(ctxt->session); + maxtries--; + } while ((ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) + && maxtries > 0); + + if (maxtries < 1) { + ctxt->status = -1; #if USING_2_1_RECENT - ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, ctxt->c, - "GnuTLS: Handshake Failed. Hit Maximum Attempts"); + ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, ctxt->c, + "GnuTLS: Handshake Failed. Hit Maximum Attempts"); #else - ap_log_error(APLOG_MARK, APLOG_ERR, 0, ctxt->c->base_server, - "GnuTLS: Handshake Failed. Hit Maximum Attempts"); + ap_log_error(APLOG_MARK, APLOG_ERR, 0, + ctxt->c->base_server, + "GnuTLS: Handshake Failed. Hit Maximum Attempts"); #endif - if (ctxt->session) { - gnutls_alert_send(ctxt->session, GNUTLS_AL_FATAL, - gnutls_error_to_alert(GNUTLS_E_INTERNAL_ERROR, NULL)); - gnutls_deinit(ctxt->session); - } - ctxt->session = NULL; - return -1; - } - - if (ret < 0) { - if (ret == GNUTLS_E_WARNING_ALERT_RECEIVED - || ret == GNUTLS_E_FATAL_ALERT_RECEIVED) { - errcode = gnutls_alert_get(ctxt->session); - ap_log_error(APLOG_MARK, APLOG_INFO, 0, ctxt->c->base_server, - "GnuTLS: Hanshake Alert (%d) '%s'.", errcode, - gnutls_alert_get_name(errcode)); - } - - if (!gnutls_error_is_fatal(ret)) { - ap_log_error(APLOG_MARK, APLOG_INFO, 0, ctxt->c->base_server, - "GnuTLS: Non-Fatal Handshake Error: (%d) '%s'", ret, - gnutls_strerror(ret)); - goto tryagain; - } + if (ctxt->session) { + gnutls_alert_send(ctxt->session, GNUTLS_AL_FATAL, + gnutls_error_to_alert + (GNUTLS_E_INTERNAL_ERROR, NULL)); + gnutls_deinit(ctxt->session); + } + ctxt->session = NULL; + return -1; + } + + if (ret < 0) { + if (ret == GNUTLS_E_WARNING_ALERT_RECEIVED + || ret == GNUTLS_E_FATAL_ALERT_RECEIVED) { + errcode = gnutls_alert_get(ctxt->session); + ap_log_error(APLOG_MARK, APLOG_INFO, 0, + ctxt->c->base_server, + "GnuTLS: Hanshake Alert (%d) '%s'.", + errcode, + gnutls_alert_get_name(errcode)); + } + + if (!gnutls_error_is_fatal(ret)) { + ap_log_error(APLOG_MARK, APLOG_INFO, 0, + ctxt->c->base_server, + "GnuTLS: Non-Fatal Handshake Error: (%d) '%s'", + ret, gnutls_strerror(ret)); + goto tryagain; + } #if USING_2_1_RECENT - ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, ctxt->c, - "GnuTLS: Handshake Failed (%d) '%s'", ret, - gnutls_strerror(ret)); + ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, ctxt->c, + "GnuTLS: Handshake Failed (%d) '%s'", ret, + gnutls_strerror(ret)); #else - ap_log_error(APLOG_MARK, APLOG_INFO, 0, ctxt->c->base_server, - "GnuTLS: Handshake Failed (%d) '%s'", ret, - gnutls_strerror(ret)); + ap_log_error(APLOG_MARK, APLOG_INFO, 0, + ctxt->c->base_server, + "GnuTLS: Handshake Failed (%d) '%s'", ret, + gnutls_strerror(ret)); #endif - ctxt->status = -1; - if (ctxt->session) { - gnutls_alert_send(ctxt->session, GNUTLS_AL_FATAL, - gnutls_error_to_alert(ret, NULL)); - gnutls_deinit(ctxt->session); - } - ctxt->session = NULL; - return ret; - } - else { - /* all done with the handshake */ - ctxt->status = 1; - /* If the session was resumed, we did not set the correct - * server_rec in ctxt->sc. Go Find it. (ick!) - */ - if (gnutls_session_is_resumed(ctxt->session)) { - mgs_srvconf_rec* sc; - sc = mgs_find_sni_server(ctxt->session); - if (sc) { - ctxt->sc = sc; - } - } - return 0; - } + ctxt->status = -1; + if (ctxt->session) { + gnutls_alert_send(ctxt->session, GNUTLS_AL_FATAL, + gnutls_error_to_alert(ret, + NULL)); + gnutls_deinit(ctxt->session); + } + ctxt->session = NULL; + return ret; + } else { + /* all done with the handshake */ + ctxt->status = 1; + /* If the session was resumed, we did not set the correct + * server_rec in ctxt->sc. Go Find it. (ick!) + */ + if (gnutls_session_is_resumed(ctxt->session)) { + mgs_srvconf_rec *sc; + sc = mgs_find_sni_server(ctxt->session); + if (sc) { + ctxt->sc = sc; + } + } + return 0; + } } int mgs_rehandshake(mgs_handle_t * ctxt) { - int rv; - - if (ctxt->session == NULL) - return -1; - - rv = gnutls_rehandshake(ctxt->session); - - if (rv != 0) { - /* the client did not want to rehandshake. goodbye */ - ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ctxt->c->base_server, - "GnuTLS: Client Refused Rehandshake request."); - return -1; - } - - ctxt->status = 0; - - rv = gnutls_do_handshake(ctxt); - - return rv; + int rv; + + if (ctxt->session == NULL) + return -1; + + rv = gnutls_rehandshake(ctxt->session); + + if (rv != 0) { + /* the client did not want to rehandshake. goodbye */ + ap_log_error(APLOG_MARK, APLOG_WARNING, 0, + ctxt->c->base_server, + "GnuTLS: Client Refused Rehandshake request."); + return -1; + } + + ctxt->status = 0; + + rv = gnutls_do_handshake(ctxt); + + return rv; } -apr_status_t mgs_filter_input(ap_filter_t* f, - apr_bucket_brigade * bb, - ap_input_mode_t mode, - apr_read_type_e block, - apr_off_t readbytes) +apr_status_t mgs_filter_input(ap_filter_t * f, + apr_bucket_brigade * bb, + ap_input_mode_t mode, + apr_read_type_e block, apr_off_t readbytes) { - apr_status_t status = APR_SUCCESS; - mgs_handle_t *ctxt = (mgs_handle_t *) f->ctx; - apr_size_t len = sizeof(ctxt->input_buffer); - - if (f->c->aborted) { - apr_bucket *bucket = apr_bucket_eos_create(f->c->bucket_alloc); - APR_BRIGADE_INSERT_TAIL(bb, bucket); - return APR_ECONNABORTED; - } - - if (ctxt->status == 0) { - gnutls_do_handshake(ctxt); - } - - if (ctxt->status < 0) { - return ap_get_brigade(f->next, bb, mode, block, readbytes); - } - - /* XXX: we don't currently support anything other than these modes. */ - if (mode != AP_MODE_READBYTES && mode != AP_MODE_GETLINE && - mode != AP_MODE_SPECULATIVE && mode != AP_MODE_INIT) { - return APR_ENOTIMPL; - } - - ctxt->input_mode = mode; - ctxt->input_block = block; - - if (ctxt->input_mode == AP_MODE_READBYTES || - ctxt->input_mode == AP_MODE_SPECULATIVE) { - /* Err. This is bad. readbytes *can* be a 64bit int! len.. is NOT */ - if (readbytes < len) { - len = (apr_size_t) readbytes; - } - status = gnutls_io_input_read(ctxt, ctxt->input_buffer, &len); - } - else if (ctxt->input_mode == AP_MODE_GETLINE) { - status = gnutls_io_input_getline(ctxt, ctxt->input_buffer, &len); - } - else { - /* We have no idea what you are talking about, so return an error. */ - return APR_ENOTIMPL; - } - - if (status != APR_SUCCESS) { - return gnutls_io_filter_error(f, bb, status); - } - - /* Create a transient bucket out of the decrypted data. */ - if (len > 0) { - apr_bucket *bucket = - apr_bucket_transient_create(ctxt->input_buffer, len, - f->c->bucket_alloc); - APR_BRIGADE_INSERT_TAIL(bb, bucket); - } - - return status; + apr_status_t status = APR_SUCCESS; + mgs_handle_t *ctxt = (mgs_handle_t *) f->ctx; + apr_size_t len = sizeof(ctxt->input_buffer); + + if (f->c->aborted) { + apr_bucket *bucket = + apr_bucket_eos_create(f->c->bucket_alloc); + APR_BRIGADE_INSERT_TAIL(bb, bucket); + return APR_ECONNABORTED; + } + + if (ctxt->status == 0) { + gnutls_do_handshake(ctxt); + } + + if (ctxt->status < 0) { + return ap_get_brigade(f->next, bb, mode, block, readbytes); + } + + /* XXX: we don't currently support anything other than these modes. */ + if (mode != AP_MODE_READBYTES && mode != AP_MODE_GETLINE && + mode != AP_MODE_SPECULATIVE && mode != AP_MODE_INIT) { + return APR_ENOTIMPL; + } + + ctxt->input_mode = mode; + ctxt->input_block = block; + + if (ctxt->input_mode == AP_MODE_READBYTES || + ctxt->input_mode == AP_MODE_SPECULATIVE) { + /* Err. This is bad. readbytes *can* be a 64bit int! len.. is NOT */ + if (readbytes < len) { + len = (apr_size_t) readbytes; + } + status = + gnutls_io_input_read(ctxt, ctxt->input_buffer, &len); + } else if (ctxt->input_mode == AP_MODE_GETLINE) { + status = + gnutls_io_input_getline(ctxt, ctxt->input_buffer, + &len); + } else { + /* We have no idea what you are talking about, so return an error. */ + return APR_ENOTIMPL; + } + + if (status != APR_SUCCESS) { + return gnutls_io_filter_error(f, bb, status); + } + + /* Create a transient bucket out of the decrypted data. */ + if (len > 0) { + apr_bucket *bucket = + apr_bucket_transient_create(ctxt->input_buffer, len, + f->c->bucket_alloc); + APR_BRIGADE_INSERT_TAIL(bb, bucket); + } + + return status; } -apr_status_t mgs_filter_output(ap_filter_t * f, - apr_bucket_brigade * bb) +apr_status_t mgs_filter_output(ap_filter_t * f, apr_bucket_brigade * bb) { - apr_size_t ret; - apr_bucket* e; - mgs_handle_t *ctxt = (mgs_handle_t *) f->ctx; - apr_status_t status = APR_SUCCESS; - apr_read_type_e rblock = APR_NONBLOCK_READ; - - if (f->c->aborted) { - apr_brigade_cleanup(bb); - return APR_ECONNABORTED; - } - - if (ctxt->status == 0) { - gnutls_do_handshake(ctxt); - } - - if (ctxt->status < 0) { - return ap_pass_brigade(f->next, bb); - } - - while (!APR_BRIGADE_EMPTY(bb)) { - apr_bucket *bucket = APR_BRIGADE_FIRST(bb); - - if (AP_BUCKET_IS_EOC(bucket)) { - if (ctxt->session != NULL) { - do { - ret = gnutls_bye( ctxt->session, GNUTLS_SHUT_WR); - } while(ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN); - } - - apr_bucket_copy(bucket, &e); - APR_BRIGADE_INSERT_TAIL(ctxt->output_bb, e); - - if ((status = ap_pass_brigade(f->next, ctxt->output_bb)) != APR_SUCCESS) { - apr_brigade_cleanup(ctxt->output_bb); - return status; - } - - apr_brigade_cleanup(ctxt->output_bb); - if (ctxt->session) { - gnutls_deinit(ctxt->session); - ctxt->session = NULL; - } - continue; - } else if (APR_BUCKET_IS_FLUSH(bucket) || APR_BUCKET_IS_EOS(bucket)) { - - apr_bucket_copy(bucket, &e); - APR_BRIGADE_INSERT_TAIL(ctxt->output_bb, e); - if ((status = ap_pass_brigade(f->next, bb)) != APR_SUCCESS) { - apr_brigade_cleanup(ctxt->output_bb); - return status; - } - - apr_brigade_cleanup(ctxt->output_bb); - continue; - } - else { - /* filter output */ - const char *data; - apr_size_t len; - - status = apr_bucket_read(bucket, &data, &len, rblock); - - if (APR_STATUS_IS_EAGAIN(status)) { - rblock = APR_BLOCK_READ; - continue; /* and try again with a blocking read. */ - } - - rblock = APR_NONBLOCK_READ; - - if (!APR_STATUS_IS_EOF(status) && (status != APR_SUCCESS)) { - break; - } - - if (len > 0) { - - if (ctxt->session == NULL) { - ret = GNUTLS_E_INVALID_REQUEST; - } else { - do { - ret = gnutls_record_send(ctxt->session, data, len); - } - while(ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN); - } - - if (ret < 0) { - /* error sending output */ - ap_log_error(APLOG_MARK, APLOG_INFO, ctxt->output_rc, - ctxt->c->base_server, - "GnuTLS: Error writing data." - " (%d) '%s'", (int)ret, gnutls_strerror(ret)); - if (ctxt->output_rc == APR_SUCCESS) { - ctxt->output_rc = APR_EGENERAL; - } - } - else if (ret != len) { - /* Not able to send the entire bucket, - split it and send it again. */ - apr_bucket_split(bucket, ret); - } - } - - apr_bucket_delete(bucket); - - if (ctxt->output_rc != APR_SUCCESS) { - break; - } - } - } - - return status; + apr_size_t ret; + apr_bucket *e; + mgs_handle_t *ctxt = (mgs_handle_t *) f->ctx; + apr_status_t status = APR_SUCCESS; + apr_read_type_e rblock = APR_NONBLOCK_READ; + + if (f->c->aborted) { + apr_brigade_cleanup(bb); + return APR_ECONNABORTED; + } + + if (ctxt->status == 0) { + gnutls_do_handshake(ctxt); + } + + if (ctxt->status < 0) { + return ap_pass_brigade(f->next, bb); + } + + while (!APR_BRIGADE_EMPTY(bb)) { + apr_bucket *bucket = APR_BRIGADE_FIRST(bb); + + if (AP_BUCKET_IS_EOC(bucket)) { + if (ctxt->session != NULL) { + do { + ret = + gnutls_bye(ctxt->session, + GNUTLS_SHUT_WR); + } while (ret == GNUTLS_E_INTERRUPTED + || ret == GNUTLS_E_AGAIN); + } + + apr_bucket_copy(bucket, &e); + APR_BRIGADE_INSERT_TAIL(ctxt->output_bb, e); + + if ((status = + ap_pass_brigade(f->next, + ctxt->output_bb)) != + APR_SUCCESS) { + apr_brigade_cleanup(ctxt->output_bb); + return status; + } + + apr_brigade_cleanup(ctxt->output_bb); + if (ctxt->session) { + gnutls_deinit(ctxt->session); + ctxt->session = NULL; + } + continue; + } else if (APR_BUCKET_IS_FLUSH(bucket) + || APR_BUCKET_IS_EOS(bucket)) { + + apr_bucket_copy(bucket, &e); + APR_BRIGADE_INSERT_TAIL(ctxt->output_bb, e); + if ((status = + ap_pass_brigade(f->next, + bb)) != APR_SUCCESS) { + apr_brigade_cleanup(ctxt->output_bb); + return status; + } + + apr_brigade_cleanup(ctxt->output_bb); + continue; + } else { + /* filter output */ + const char *data; + apr_size_t len; + + status = + apr_bucket_read(bucket, &data, &len, rblock); + + if (APR_STATUS_IS_EAGAIN(status)) { + rblock = APR_BLOCK_READ; + continue; /* and try again with a blocking read. */ + } + + rblock = APR_NONBLOCK_READ; + + if (!APR_STATUS_IS_EOF(status) + && (status != APR_SUCCESS)) { + break; + } + + if (len > 0) { + + if (ctxt->session == NULL) { + ret = GNUTLS_E_INVALID_REQUEST; + } else { + do { + ret = + gnutls_record_send + (ctxt->session, data, + len); + } + while (ret == GNUTLS_E_INTERRUPTED + || ret == GNUTLS_E_AGAIN); + } + + if (ret < 0) { + /* error sending output */ + ap_log_error(APLOG_MARK, + APLOG_INFO, + ctxt->output_rc, + ctxt->c->base_server, + "GnuTLS: Error writing data." + " (%d) '%s'", + (int) ret, + gnutls_strerror(ret)); + if (ctxt->output_rc == APR_SUCCESS) { + ctxt->output_rc = + APR_EGENERAL; + } + } else if (ret != len) { + /* Not able to send the entire bucket, + split it and send it again. */ + apr_bucket_split(bucket, ret); + } + } + + apr_bucket_delete(bucket); + + if (ctxt->output_rc != APR_SUCCESS) { + break; + } + } + } + + return status; } ssize_t mgs_transport_read(gnutls_transport_ptr_t ptr, - void *buffer, size_t len) + void *buffer, size_t len) { - mgs_handle_t *ctxt = ptr; - apr_status_t rc; - apr_size_t in = len; - apr_read_type_e block = ctxt->input_block; - - ctxt->input_rc = APR_SUCCESS; - - /* If Len = 0, we don't do anything. */ - if (!len) - return 0; - - if (!ctxt->input_bb) { - ctxt->input_rc = APR_EOF; - return -1; - } - - if (APR_BRIGADE_EMPTY(ctxt->input_bb)) { - - rc = ap_get_brigade(ctxt->input_filter->next, ctxt->input_bb, - AP_MODE_READBYTES, ctxt->input_block, in); - - /* Not a problem, there was simply no data ready yet. - */ - if (APR_STATUS_IS_EAGAIN(rc) || APR_STATUS_IS_EINTR(rc) - || (rc == APR_SUCCESS && APR_BRIGADE_EMPTY(ctxt->input_bb))) { - - if (APR_STATUS_IS_EOF(ctxt->input_rc)) { - return 0; - } else { - if (ctxt->session) - gnutls_transport_set_errno(ctxt->session, EINTR); - return -1; - } - } - - - if (rc != APR_SUCCESS) { - /* Unexpected errors discard the brigade */ - apr_brigade_cleanup(ctxt->input_bb); - ctxt->input_bb = NULL; - return -1; - } - } - - ctxt->input_rc = brigade_consume(ctxt->input_bb, block, buffer, &len); - - if (ctxt->input_rc == APR_SUCCESS) { - return (ssize_t) len; - } - - if (APR_STATUS_IS_EAGAIN(ctxt->input_rc) - || APR_STATUS_IS_EINTR(ctxt->input_rc)) { - if (len == 0) { - if (ctxt->session) - gnutls_transport_set_errno(ctxt->session, EINTR); - return -1; - } - - return (ssize_t) len; - } - - /* Unexpected errors and APR_EOF clean out the brigade. - * Subsequent calls will return APR_EOF. - */ - apr_brigade_cleanup(ctxt->input_bb); - ctxt->input_bb = NULL; - - if (APR_STATUS_IS_EOF(ctxt->input_rc) && len) { - /* Provide the results of this read pass, - * without resetting the BIO retry_read flag - */ - return (ssize_t) len; - } - - return -1; + mgs_handle_t *ctxt = ptr; + apr_status_t rc; + apr_size_t in = len; + apr_read_type_e block = ctxt->input_block; + + ctxt->input_rc = APR_SUCCESS; + + /* If Len = 0, we don't do anything. */ + if (!len) + return 0; + + if (!ctxt->input_bb) { + ctxt->input_rc = APR_EOF; + return -1; + } + + if (APR_BRIGADE_EMPTY(ctxt->input_bb)) { + + rc = ap_get_brigade(ctxt->input_filter->next, + ctxt->input_bb, AP_MODE_READBYTES, + ctxt->input_block, in); + + /* Not a problem, there was simply no data ready yet. + */ + if (APR_STATUS_IS_EAGAIN(rc) || APR_STATUS_IS_EINTR(rc) + || (rc == APR_SUCCESS + && APR_BRIGADE_EMPTY(ctxt->input_bb))) { + + if (APR_STATUS_IS_EOF(ctxt->input_rc)) { + return 0; + } else { + if (ctxt->session) + gnutls_transport_set_errno(ctxt-> + session, + EINTR); + return -1; + } + } + + + if (rc != APR_SUCCESS) { + /* Unexpected errors discard the brigade */ + apr_brigade_cleanup(ctxt->input_bb); + ctxt->input_bb = NULL; + return -1; + } + } + + ctxt->input_rc = + brigade_consume(ctxt->input_bb, block, buffer, &len); + + if (ctxt->input_rc == APR_SUCCESS) { + return (ssize_t) len; + } + + if (APR_STATUS_IS_EAGAIN(ctxt->input_rc) + || APR_STATUS_IS_EINTR(ctxt->input_rc)) { + if (len == 0) { + if (ctxt->session) + gnutls_transport_set_errno(ctxt->session, + EINTR); + return -1; + } + + return (ssize_t) len; + } + + /* Unexpected errors and APR_EOF clean out the brigade. + * Subsequent calls will return APR_EOF. + */ + apr_brigade_cleanup(ctxt->input_bb); + ctxt->input_bb = NULL; + + if (APR_STATUS_IS_EOF(ctxt->input_rc) && len) { + /* Provide the results of this read pass, + * without resetting the BIO retry_read flag + */ + return (ssize_t) len; + } + + return -1; } static ssize_t write_flush(mgs_handle_t * ctxt) { - apr_bucket *e; - - if (!(ctxt->output_blen || ctxt->output_length)) { - ctxt->output_rc = APR_SUCCESS; - return 1; - } - - if (ctxt->output_blen) { - e = apr_bucket_transient_create(ctxt->output_buffer, - ctxt->output_blen, - ctxt->output_bb->bucket_alloc); - /* we filled this buffer first so add it to the - * head of the brigade - */ - APR_BRIGADE_INSERT_HEAD(ctxt->output_bb, e); - ctxt->output_blen = 0; - } - - ctxt->output_length = 0; - e = apr_bucket_flush_create(ctxt->output_bb->bucket_alloc); - APR_BRIGADE_INSERT_TAIL(ctxt->output_bb, e); - - ctxt->output_rc = ap_pass_brigade(ctxt->output_filter->next, - ctxt->output_bb); - /* clear the brigade to be ready for next time */ - apr_brigade_cleanup(ctxt->output_bb); - - return (ctxt->output_rc == APR_SUCCESS) ? 1 : -1; + apr_bucket *e; + + if (!(ctxt->output_blen || ctxt->output_length)) { + ctxt->output_rc = APR_SUCCESS; + return 1; + } + + if (ctxt->output_blen) { + e = apr_bucket_transient_create(ctxt->output_buffer, + ctxt->output_blen, + ctxt->output_bb-> + bucket_alloc); + /* we filled this buffer first so add it to the + * head of the brigade + */ + APR_BRIGADE_INSERT_HEAD(ctxt->output_bb, e); + ctxt->output_blen = 0; + } + + ctxt->output_length = 0; + e = apr_bucket_flush_create(ctxt->output_bb->bucket_alloc); + APR_BRIGADE_INSERT_TAIL(ctxt->output_bb, e); + + ctxt->output_rc = ap_pass_brigade(ctxt->output_filter->next, + ctxt->output_bb); + /* clear the brigade to be ready for next time */ + apr_brigade_cleanup(ctxt->output_bb); + + return (ctxt->output_rc == APR_SUCCESS) ? 1 : -1; } ssize_t mgs_transport_write(gnutls_transport_ptr_t ptr, - const void *buffer, size_t len) + const void *buffer, size_t len) { - mgs_handle_t *ctxt = ptr; - - /* pass along the encrypted data - * need to flush since we're using SSL's malloc-ed buffer - * which will be overwritten once we leave here - */ - apr_bucket *bucket = apr_bucket_transient_create(buffer, len, - ctxt->output_bb->bucket_alloc); - ctxt->output_length += len; - APR_BRIGADE_INSERT_TAIL(ctxt->output_bb, bucket); - - if (write_flush(ctxt) < 0) { - return -1; - } - return len; + mgs_handle_t *ctxt = ptr; + + /* pass along the encrypted data + * need to flush since we're using SSL's malloc-ed buffer + * which will be overwritten once we leave here + */ + apr_bucket *bucket = apr_bucket_transient_create(buffer, len, + ctxt->output_bb-> + bucket_alloc); + ctxt->output_length += len; + APR_BRIGADE_INSERT_TAIL(ctxt->output_bb, bucket); + + if (write_flush(ctxt) < 0) { + return -1; + } + return len; } diff --git a/src/gnutls_lua.c b/src/gnutls_lua.c index 6d80574..4401b61 100644 --- a/src/gnutls_lua.c +++ b/src/gnutls_lua.c @@ -25,268 +25,285 @@ static char *MGS_LUA_RRKEY = "request_rec"; -static request_rec *mgs_lua_getrr(lua_State *lvm) +static request_rec *mgs_lua_getrr(lua_State * lvm) { - request_rec *r; - - /* Push the request_rec off the registry, onto the stack. */ - lua_pushlightuserdata(lvm, MGS_LUA_RRKEY); - lua_gettable(lvm, LUA_REGISTRYINDEX); - r = lua_touserdata(lvm, -1); - lua_pop(lvm, 1); - return r; + request_rec *r; + + /* Push the request_rec off the registry, onto the stack. */ + lua_pushlightuserdata(lvm, MGS_LUA_RRKEY); + lua_gettable(lvm, LUA_REGISTRYINDEX); + r = lua_touserdata(lvm, -1); + lua_pop(lvm, 1); + return r; } -static int get_request_table(lua_State *lvm, long offset) -{ - const char *key; - request_rec *r; - const char *value; - apr_table_t *t; - key = luaL_checkstring(lvm, 1); - - r = mgs_lua_getrr(lvm); - - t = *(apr_table_t **)((char *)r + offset); - - value = apr_table_get(t, key); - - if (value) { - lua_pushstring(lvm, value); - return 1; - } - else { - return 0; - } +static int get_request_table(lua_State * lvm, long offset) +{ + const char *key; + request_rec *r; + const char *value; + apr_table_t *t; + key = luaL_checkstring(lvm, 1); + + r = mgs_lua_getrr(lvm); + + t = *(apr_table_t **) ((char *) r + offset); + + value = apr_table_get(t, key); + + if (value) { + lua_pushstring(lvm, value); + return 1; + } else { + return 0; + } } -static int mgs_lua_getenv(lua_State *lvm) +static int mgs_lua_getenv(lua_State * lvm) { - return get_request_table(lvm, APR_OFFSETOF(request_rec, subprocess_env)); + return get_request_table(lvm, + APR_OFFSETOF(request_rec, + subprocess_env)); } -static int mgs_lua_getheader(lua_State *lvm) -{ - return get_request_table(lvm, APR_OFFSETOF(request_rec, headers_in)); -} +static int mgs_lua_getheader(lua_State * lvm) +{ + return get_request_table(lvm, + APR_OFFSETOF(request_rec, headers_in)); +} static const luaL_reg mgs_lua_reg[] = { - {"getenv", mgs_lua_getenv}, - {"header", mgs_lua_getheader}, - {NULL, NULL} + {"getenv", mgs_lua_getenv}, + {"header", mgs_lua_getheader}, + {NULL, NULL} }; -lua_State* get_luastate() +lua_State *get_luastate() { - lua_State* lvm = lua_open(); - luaopen_base(lvm); - luaopen_io(lvm); - luaopen_table(lvm); - luaopen_string(lvm); - luaopen_math(lvm); - luaopen_loadlib(lvm); - luaL_openlib(lvm, "ap", mgs_lua_reg, 0); - - return lvm; + lua_State *lvm = lua_open(); + luaopen_base(lvm); + luaopen_io(lvm); + luaopen_table(lvm); + luaopen_string(lvm); + luaopen_math(lvm); + luaopen_loadlib(lvm); + luaL_openlib(lvm, "ap", mgs_lua_reg, 0); + + return lvm; } -int mgs_authz_lua(request_rec* r) +int mgs_authz_lua(request_rec * r) { - int rv; - lua_State* lvm; - mgs_dirconf_rec *dc = ap_get_module_config(r->per_dir_config, - &gnutls_module); - - if (dc->lua_bytecode_len <= 0) { - return 0; - } - - lvm = get_luastate(); - lua_pushlightuserdata(lvm, MGS_LUA_RRKEY); - lua_pushlightuserdata(lvm, r); - lua_settable(lvm, LUA_REGISTRYINDEX); - - /* Push Bytecode onto the stack */ - rv = luaL_loadbuffer(lvm, dc->lua_bytecode, dc->lua_bytecode_len, "gnutls-lua"); - - if (rv != 0) { - /* Get the Error message */ - const char* error = lua_tostring(lvm, -1); - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, - "GnuTLS: Error Loading Lua Bytecode: %s", error); - lua_pop(lvm, 1); - return -1; - } - - rv = lua_pcall(lvm, 0, 1, 0); - if (rv != 0) { - /* Get the Error message */ - const char* error = lua_tostring(lvm, -1); - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, - "GnuTLS: Error Running Lua: %s", error); - lua_pop(lvm, 1); - return -1; - } - - rv = (int)lua_tonumber(lvm, -1); - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, - "GnuTLS: (%d) Lua Return: %d", - dc->lua_bytecode_len, rv); - lua_pop(lvm, 1); - lua_close(lvm); - return rv; + int rv; + lua_State *lvm; + mgs_dirconf_rec *dc = ap_get_module_config(r->per_dir_config, + &gnutls_module); + + if (dc->lua_bytecode_len <= 0) { + return 0; + } + + lvm = get_luastate(); + lua_pushlightuserdata(lvm, MGS_LUA_RRKEY); + lua_pushlightuserdata(lvm, r); + lua_settable(lvm, LUA_REGISTRYINDEX); + + /* Push Bytecode onto the stack */ + rv = luaL_loadbuffer(lvm, dc->lua_bytecode, dc->lua_bytecode_len, + "gnutls-lua"); + + if (rv != 0) { + /* Get the Error message */ + const char *error = lua_tostring(lvm, -1); + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, + "GnuTLS: Error Loading Lua Bytecode: %s", + error); + lua_pop(lvm, 1); + return -1; + } + + rv = lua_pcall(lvm, 0, 1, 0); + if (rv != 0) { + /* Get the Error message */ + const char *error = lua_tostring(lvm, -1); + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, + "GnuTLS: Error Running Lua: %s", error); + lua_pop(lvm, 1); + return -1; + } + + rv = (int) lua_tonumber(lvm, -1); + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, + "GnuTLS: (%d) Lua Return: %d", + dc->lua_bytecode_len, rv); + lua_pop(lvm, 1); + lua_close(lvm); + return rv; } -static apr_size_t config_getstr(ap_configfile_t *cfg, char *buf, size_t bufsiz) +static apr_size_t config_getstr(ap_configfile_t * cfg, char *buf, + size_t bufsiz) { - apr_size_t i = 0; - - if (cfg->getstr) { - const char *res = (cfg->getstr)(buf, bufsiz, cfg->param); - if (res) { - i = strlen(buf); - if (i && buf[i - 1] == '\n') ++cfg->line_number; - } - else { - buf[0] = '\0'; - i = 0; - } - } - else { - while (i < bufsiz) { - int ch = (cfg->getch)(cfg->param); - if (ch == EOF) break; - buf[i++] = ch; - if (ch == '\n') { - ++cfg->line_number; - break; - } - } - } - return i; + apr_size_t i = 0; + + if (cfg->getstr) { + const char *res = (cfg->getstr) (buf, bufsiz, cfg->param); + if (res) { + i = strlen(buf); + if (i && buf[i - 1] == '\n') + ++cfg->line_number; + } else { + buf[0] = '\0'; + i = 0; + } + } else { + while (i < bufsiz) { + int ch = (cfg->getch) (cfg->param); + if (ch == EOF) + break; + buf[i++] = ch; + if (ch == '\n') { + ++cfg->line_number; + break; + } + } + } + return i; } struct cr_ctx { - ap_configfile_t *cfp; - size_t startline; - char buf[HUGE_STRING_LEN]; + ap_configfile_t *cfp; + size_t startline; + char buf[HUGE_STRING_LEN]; }; static const char *LUACMD = "gnutlsrequire"; -static const char *lf = "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"; +static const char *lf = + "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"; #define N_LF 32 -static const char *direct_chunkreader(lua_State *lvm, void *udata, size_t *plen) +static const char *direct_chunkreader(lua_State * lvm, void *udata, + size_t * plen) { - const char *p; - struct cr_ctx *ctx = udata; - - if (ctx->startline) { - *plen = ctx->startline > N_LF ? N_LF : ctx->startline; - ctx->startline -= *plen; - return lf; - } - *plen = config_getstr(ctx->cfp, ctx->buf, HUGE_STRING_LEN); - - for (p = ctx->buf; isspace(*p); ++p); - if (p[0] == '<' && p[1] == '/') { - int i = 0; - while (i < strlen(LUACMD)) { - if (tolower(p[i + 2]) != LUACMD[i]) return ctx->buf; - ++i; - } - *plen = 0; - return NULL; - } - return ctx->buf; + const char *p; + struct cr_ctx *ctx = udata; + + if (ctx->startline) { + *plen = ctx->startline > N_LF ? N_LF : ctx->startline; + ctx->startline -= *plen; + return lf; + } + *plen = config_getstr(ctx->cfp, ctx->buf, HUGE_STRING_LEN); + + for (p = ctx->buf; isspace(*p); ++p); + if (p[0] == '<' && p[1] == '/') { + int i = 0; + while (i < strlen(LUACMD)) { + if (tolower(p[i + 2]) != LUACMD[i]) + return ctx->buf; + ++i; + } + *plen = 0; + return NULL; + } + return ctx->buf; } -static int ldump_writer (lua_State *L, const void* b, size_t size, void* B) { - (void)L; - luaL_addlstring((luaL_Buffer*) B, (const char *)b, size); - return 1; +static int ldump_writer(lua_State * L, const void *b, size_t size, void *B) +{ + (void) L; + luaL_addlstring((luaL_Buffer *) B, (const char *) b, size); + return 1; } /* a bytecode buffer*/ typedef struct bcbuf_ctx { - apr_size_t buflen; - char* buf; + apr_size_t buflen; + char *buf; } bcbuf_ctx; -const char *mgs_set_require_section(cmd_parms *cmd, void *mconfig, const char *arg) +const char *mgs_set_require_section(cmd_parms * cmd, void *mconfig, + const char *arg) { - apr_size_t bytecode_len; - const char* bytecode; - bcbuf_ctx* bcbuf; - luaL_Buffer b; - ap_directive_t **current = mconfig; - struct cr_ctx ctx[1]; - int result; - const char *filename = apr_psprintf(cmd->pool, "@%s", cmd->config_file->name); - // get a word argument - const char *word; - apr_size_t wordlen; - lua_State *lvm = get_luastate(); - - word = ap_getword_conf(cmd->pool, &arg); - wordlen = strlen(word); - do { - if (wordlen) { - if (word[wordlen - 1] == '>') { - --wordlen; - break; - } - if (*arg == '>') break; - } - return apr_pstrcat(cmd->pool, "<", LUACMD, "> takes exactly one argument", NULL); - } while (0); - - ctx->cfp = cmd->config_file; - ctx->startline = cmd->config_file->line_number; - lua_settop(lvm, 0); - result = lua_load(lvm, direct_chunkreader, ctx, filename); - - if (result != 0) { - word = apr_pstrcat(cmd->pool, "Lua Error:", lua_tostring(lvm, -1), NULL); - lua_close(lvm); - return word; - } - else { - luaL_buffinit(lvm, &b); - lua_dump(lvm, ldump_writer, &b); - luaL_pushresult(&b); - bytecode = lua_tostring(lvm, -1); - bytecode_len = lua_strlen(lvm, -1); - } - - /* Here, we have to replace our current config node for the next pass */ - if (!*current) { - *current = apr_pcalloc(cmd->pool, sizeof(**current)); - } - - (*current)->filename = cmd->config_file->name; - (*current)->line_num = ctx->startline; - (*current)->directive = apr_pstrdup(cmd->pool, "GnuTLSRequireByteCode"); - (*current)->args = NULL; - - bcbuf = apr_pcalloc(cmd->pool, sizeof(bcbuf)); - bcbuf->buflen = bytecode_len; - bcbuf->buf = apr_pstrmemdup(cmd->pool, bytecode, bytecode_len); - - (*current)->data = bcbuf; - lua_close(lvm); - return NULL; + apr_size_t bytecode_len; + const char *bytecode; + bcbuf_ctx *bcbuf; + luaL_Buffer b; + ap_directive_t **current = mconfig; + struct cr_ctx ctx[1]; + int result; + const char *filename = + apr_psprintf(cmd->pool, "@%s", cmd->config_file->name); + // get a word argument + const char *word; + apr_size_t wordlen; + lua_State *lvm = get_luastate(); + + word = ap_getword_conf(cmd->pool, &arg); + wordlen = strlen(word); + do { + if (wordlen) { + if (word[wordlen - 1] == '>') { + --wordlen; + break; + } + if (*arg == '>') + break; + } + return apr_pstrcat(cmd->pool, "<", LUACMD, + "> takes exactly one argument", NULL); + } while (0); + + ctx->cfp = cmd->config_file; + ctx->startline = cmd->config_file->line_number; + lua_settop(lvm, 0); + result = lua_load(lvm, direct_chunkreader, ctx, filename); + + if (result != 0) { + word = + apr_pstrcat(cmd->pool, "Lua Error:", + lua_tostring(lvm, -1), NULL); + lua_close(lvm); + return word; + } else { + luaL_buffinit(lvm, &b); + lua_dump(lvm, ldump_writer, &b); + luaL_pushresult(&b); + bytecode = lua_tostring(lvm, -1); + bytecode_len = lua_strlen(lvm, -1); + } + + /* Here, we have to replace our current config node for the next pass */ + if (!*current) { + *current = apr_pcalloc(cmd->pool, sizeof(**current)); + } + + (*current)->filename = cmd->config_file->name; + (*current)->line_num = ctx->startline; + (*current)->directive = + apr_pstrdup(cmd->pool, "GnuTLSRequireByteCode"); + (*current)->args = NULL; + + bcbuf = apr_pcalloc(cmd->pool, sizeof(bcbuf)); + bcbuf->buflen = bytecode_len; + bcbuf->buf = apr_pstrmemdup(cmd->pool, bytecode, bytecode_len); + + (*current)->data = bcbuf; + lua_close(lvm); + return NULL; } -const char *mgs_set_require_bytecode(cmd_parms *cmd, void *mconfig, const char *arg) +const char *mgs_set_require_bytecode(cmd_parms * cmd, void *mconfig, + const char *arg) { - bcbuf_ctx* bcbuf; - ap_directive_t *directive = cmd->directive; - mgs_dirconf_rec *dc = mconfig; - - bcbuf = directive->data; - dc->lua_bytecode_len = bcbuf->buflen; - dc->lua_bytecode = apr_pstrmemdup(cmd->pool, bcbuf->buf, bcbuf->buflen); - - return NULL; + bcbuf_ctx *bcbuf; + ap_directive_t *directive = cmd->directive; + mgs_dirconf_rec *dc = mconfig; + + bcbuf = directive->data; + dc->lua_bytecode_len = bcbuf->buflen; + dc->lua_bytecode = + apr_pstrmemdup(cmd->pool, bcbuf->buf, bcbuf->buflen); + + return NULL; } diff --git a/src/mod_gnutls.c b/src/mod_gnutls.c index c95d183..49f4e43 100644 --- a/src/mod_gnutls.c +++ b/src/mod_gnutls.c @@ -19,143 +19,146 @@ static void gnutls_hooks(apr_pool_t * p) { - ap_hook_pre_connection(mgs_hook_pre_connection, NULL, NULL, - APR_HOOK_MIDDLE); - ap_hook_post_config(mgs_hook_post_config, NULL, NULL, - APR_HOOK_MIDDLE); - ap_hook_child_init(mgs_hook_child_init, NULL, NULL, - APR_HOOK_MIDDLE); + ap_hook_pre_connection(mgs_hook_pre_connection, NULL, NULL, + APR_HOOK_MIDDLE); + ap_hook_post_config(mgs_hook_post_config, NULL, NULL, + APR_HOOK_MIDDLE); + ap_hook_child_init(mgs_hook_child_init, NULL, NULL, + APR_HOOK_MIDDLE); #if USING_2_1_RECENT - ap_hook_http_scheme(mgs_hook_http_scheme, NULL, NULL, - APR_HOOK_MIDDLE); + ap_hook_http_scheme(mgs_hook_http_scheme, NULL, NULL, + APR_HOOK_MIDDLE); #else - ap_hook_http_method(mgs_hook_http_scheme, NULL, NULL, - APR_HOOK_MIDDLE); + ap_hook_http_method(mgs_hook_http_scheme, NULL, NULL, + APR_HOOK_MIDDLE); #endif - ap_hook_default_port(mgs_hook_default_port, NULL, NULL, - APR_HOOK_MIDDLE); - ap_hook_pre_config(mgs_hook_pre_config, NULL, NULL, - APR_HOOK_MIDDLE); - - ap_hook_access_checker(mgs_hook_authz, NULL, NULL, APR_HOOK_REALLY_FIRST); - - ap_hook_fixups(mgs_hook_fixups, NULL, NULL, APR_HOOK_REALLY_FIRST); - - /* TODO: HTTP Upgrade Filter */ - /* ap_register_output_filter ("UPGRADE_FILTER", - * ssl_io_filter_Upgrade, NULL, AP_FTYPE_PROTOCOL + 5); - */ + ap_hook_default_port(mgs_hook_default_port, NULL, NULL, + APR_HOOK_MIDDLE); + ap_hook_pre_config(mgs_hook_pre_config, NULL, NULL, + APR_HOOK_MIDDLE); - ap_register_input_filter(GNUTLS_INPUT_FILTER_NAME, - mgs_filter_input, NULL, - AP_FTYPE_CONNECTION + 5); - ap_register_output_filter(GNUTLS_OUTPUT_FILTER_NAME, - mgs_filter_output, NULL, - AP_FTYPE_CONNECTION + 5); + ap_hook_access_checker(mgs_hook_authz, NULL, NULL, + APR_HOOK_REALLY_FIRST); + + ap_hook_fixups(mgs_hook_fixups, NULL, NULL, APR_HOOK_REALLY_FIRST); + + /* TODO: HTTP Upgrade Filter */ + /* ap_register_output_filter ("UPGRADE_FILTER", + * ssl_io_filter_Upgrade, NULL, AP_FTYPE_PROTOCOL + 5); + */ + + ap_register_input_filter(GNUTLS_INPUT_FILTER_NAME, + mgs_filter_input, NULL, + AP_FTYPE_CONNECTION + 5); + ap_register_output_filter(GNUTLS_OUTPUT_FILTER_NAME, + mgs_filter_output, NULL, + AP_FTYPE_CONNECTION + 5); } static const command_rec mgs_config_cmds[] = { - AP_INIT_TAKE1("GnuTLSClientVerify", mgs_set_client_verify, - NULL, - RSRC_CONF|OR_AUTHCFG, - "Set Verification Requirements of the Client Certificate"), - AP_INIT_TAKE1("GnuTLSClientCAFile", mgs_set_client_ca_file, - NULL, - RSRC_CONF, - "Set the CA File to verify Client Certificates"), - AP_INIT_TAKE1("GnuTLSX509CAFile", mgs_set_client_ca_file, - NULL, - RSRC_CONF, - "Set the CA File to verify Client Certificates"), - AP_INIT_TAKE1("GnuTLSPGPKeyringFile", mgs_set_keyring_file, - NULL, - RSRC_CONF, - "Set the Keyring File to verify Client Certificates"), - AP_INIT_TAKE1("GnuTLSDHFile", mgs_set_dh_file, - NULL, - RSRC_CONF, - "Set the file to read Diffie Hellman parameters from"), - AP_INIT_TAKE1("GnuTLSRSAFile", mgs_set_rsa_export_file, - NULL, - RSRC_CONF, - "Set the file to read RSA-EXPORT parameters from"), - AP_INIT_TAKE1("GnuTLSCertificateFile", mgs_set_cert_file, - NULL, - RSRC_CONF, - "SSL Server X509 Certificate file"), - AP_INIT_TAKE1("GnuTLSKeyFile", mgs_set_key_file, - NULL, - RSRC_CONF, - "SSL Server X509 Private Key file"), - AP_INIT_TAKE1("GnuTLSX509CertificateFile", mgs_set_cert_file, - NULL, - RSRC_CONF, - "SSL Server X509 Certificate file"), - AP_INIT_TAKE1("GnuTLSX509KeyFile", mgs_set_key_file, - NULL, - RSRC_CONF, - "SSL Server X509 Private Key file"), - AP_INIT_TAKE1("GnuTLSPGPCertificateFile", mgs_set_pgpcert_file, - NULL, - RSRC_CONF, - "SSL Server PGP Certificate file"), - AP_INIT_TAKE1("GnuTLSPGPKeyFile", mgs_set_pgpkey_file, - NULL, - RSRC_CONF, - "SSL Server PGP Private key file"), + AP_INIT_TAKE1("GnuTLSClientVerify", mgs_set_client_verify, + NULL, + RSRC_CONF | OR_AUTHCFG, + "Set Verification Requirements of the Client Certificate"), + AP_INIT_TAKE1("GnuTLSClientCAFile", mgs_set_client_ca_file, + NULL, + RSRC_CONF, + "Set the CA File to verify Client Certificates"), + AP_INIT_TAKE1("GnuTLSX509CAFile", mgs_set_client_ca_file, + NULL, + RSRC_CONF, + "Set the CA File to verify Client Certificates"), + AP_INIT_TAKE1("GnuTLSPGPKeyringFile", mgs_set_keyring_file, + NULL, + RSRC_CONF, + "Set the Keyring File to verify Client Certificates"), + AP_INIT_TAKE1("GnuTLSDHFile", mgs_set_dh_file, + NULL, + RSRC_CONF, + "Set the file to read Diffie Hellman parameters from"), + AP_INIT_TAKE1("GnuTLSRSAFile", mgs_set_rsa_export_file, + NULL, + RSRC_CONF, + "Set the file to read RSA-EXPORT parameters from"), + AP_INIT_TAKE1("GnuTLSCertificateFile", mgs_set_cert_file, + NULL, + RSRC_CONF, + "SSL Server X509 Certificate file"), + AP_INIT_TAKE1("GnuTLSKeyFile", mgs_set_key_file, + NULL, + RSRC_CONF, + "SSL Server X509 Private Key file"), + AP_INIT_TAKE1("GnuTLSX509CertificateFile", mgs_set_cert_file, + NULL, + RSRC_CONF, + "SSL Server X509 Certificate file"), + AP_INIT_TAKE1("GnuTLSX509KeyFile", mgs_set_key_file, + NULL, + RSRC_CONF, + "SSL Server X509 Private Key file"), + AP_INIT_TAKE1("GnuTLSPGPCertificateFile", mgs_set_pgpcert_file, + NULL, + RSRC_CONF, + "SSL Server PGP Certificate file"), + AP_INIT_TAKE1("GnuTLSPGPKeyFile", mgs_set_pgpkey_file, + NULL, + RSRC_CONF, + "SSL Server PGP Private key file"), #ifdef ENABLE_SRP - AP_INIT_TAKE1("GnuTLSSRPPasswdFile", mgs_set_srp_tpasswd_file, - NULL, - RSRC_CONF, - "SSL Server SRP Password Conf file"), - AP_INIT_TAKE1("GnuTLSSRPPasswdConfFile", mgs_set_srp_tpasswd_conf_file, - NULL, - RSRC_CONF, - "SSL Server SRP Parameters file"), + AP_INIT_TAKE1("GnuTLSSRPPasswdFile", mgs_set_srp_tpasswd_file, + NULL, + RSRC_CONF, + "SSL Server SRP Password Conf file"), + AP_INIT_TAKE1("GnuTLSSRPPasswdConfFile", + mgs_set_srp_tpasswd_conf_file, + NULL, + RSRC_CONF, + "SSL Server SRP Parameters file"), #endif - AP_INIT_TAKE1("GnuTLSCacheTimeout", mgs_set_cache_timeout, - NULL, - RSRC_CONF, - "Cache Timeout"), - AP_INIT_TAKE2("GnuTLSCache", mgs_set_cache, - NULL, - RSRC_CONF, - "Cache Configuration"), - AP_INIT_TAKE1("GnuTLSSessionTickets", mgs_set_tickets, - NULL, - RSRC_CONF, - "Session Tickets Configuration"), - AP_INIT_RAW_ARGS("GnuTLSPriorities", mgs_set_priorities, - NULL, - RSRC_CONF, - "The priorities to enable (ciphers, Key exchange, macs, compression)."), - AP_INIT_TAKE1("GnuTLSEnable", mgs_set_enabled, - NULL, - RSRC_CONF, - "Whether this server has GnuTLS Enabled. Default: Off"), - AP_INIT_TAKE1("GnuTLSExportCertificates", mgs_set_export_certificates_enabled, - NULL, - RSRC_CONF, - "Whether to export PEM encoded certificates to CGIs. Default: Off"), + AP_INIT_TAKE1("GnuTLSCacheTimeout", mgs_set_cache_timeout, + NULL, + RSRC_CONF, + "Cache Timeout"), + AP_INIT_TAKE2("GnuTLSCache", mgs_set_cache, + NULL, + RSRC_CONF, + "Cache Configuration"), + AP_INIT_TAKE1("GnuTLSSessionTickets", mgs_set_tickets, + NULL, + RSRC_CONF, + "Session Tickets Configuration"), + AP_INIT_RAW_ARGS("GnuTLSPriorities", mgs_set_priorities, + NULL, + RSRC_CONF, + "The priorities to enable (ciphers, Key exchange, macs, compression)."), + AP_INIT_TAKE1("GnuTLSEnable", mgs_set_enabled, + NULL, + RSRC_CONF, + "Whether this server has GnuTLS Enabled. Default: Off"), + AP_INIT_TAKE1("GnuTLSExportCertificates", + mgs_set_export_certificates_enabled, + NULL, + RSRC_CONF, + "Whether to export PEM encoded certificates to CGIs. Default: Off"), #if 0 - AP_INIT_RAW_ARGS("