Changeset f4ac9cc in mod_gnutls


Ignore:
Timestamp:
Apr 16, 2018, 8:43:01 PM (5 months ago)
Author:
Daniel Kahn Gillmor <dkg@…>
Branches:
debian/master, debian/stretch-backports, upstream
Children:
8982265
Parents:
f5342b1 (diff), e00a037 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

New upstream version 0.8.4

Files:
2 added
26 edited

Legend:

Unmodified
Added
Removed
  • CHANGELOG

    rf5342b1 rf4ac9cc  
     1** Version 0.8.4 (2018-04-13)
     2- Support Apache HTTPD 2.4.33 API for proxy TLS connections
     3- Support TLS for HTTP/2 connections with mod_http2
     4- Fix configuration of OCSP stapling callback
     5
    16** Version 0.8.3 (2017-10-20)
    27- Use GnuTLS' default DH parameters by default
  • README

    rf5342b1 rf4ac9cc  
    1010Lead Maintainer:
    1111
    12   Thomas Klute <thomas2.klute@uni-dortmund.de>
     12  Fiona Klute <fiona.klute@gmx.de>
    1313
    1414Past maintainers and other contributors:
     
    2323
    2424 * GnuTLS          >= 3.3 <https://www.gnutls.org/> (3.4 or newer recommended)
    25  * Apache HTTPD    >= 2.4 <https://httpd.apache.org/>
     25 * Apache HTTPD    >= 2.4.17 <https://httpd.apache.org/>
    2626 * autotools, GNU make, & GCC
    2727 * libmsv          >= 0.1 (Optional, enable with ./configure --enable-msva)
  • configure.ac

    rf5342b1 rf4ac9cc  
    1 AC_INIT(mod_gnutls, 0.8.3)
     1AC_INIT(mod_gnutls, 0.8.4)
    22OOO_CONFIG_NICE(config.nice)
    33MOD_GNUTLS_VERSION=AC_PACKAGE_VERSION
     
    2525AC_CONFIG_MACRO_DIR([m4])
    2626
    27 AP_VERSION=2.4.0
     27AP_VERSION=2.4.17
    2828CHECK_APACHE(,$AP_VERSION,
    2929    :,:,
  • include/mod_gnutls.h.in

    rf5342b1 rf4ac9cc  
    22 *  Copyright 2004-2005 Paul Querna
    33 *  Copyright 2014 Nikos Mavrogiannopoulos
    4  *  Copyright 2015-2016 Thomas Klute
     4 *  Copyright 2015-2018 Fiona Klute
    55 *
    66 *  Licensed under the Apache License, Version 2.0 (the "License");
     
    292292is using SSL/TLS. */
    293293APR_DECLARE_OPTIONAL_FN(int, ssl_is_https, (conn_rec *));
     294/* The ssl_var_lookup() optional function retrieves SSL environment
     295 * variables. */
     296APR_DECLARE_OPTIONAL_FN(char *, ssl_var_lookup,
     297                        (apr_pool_t *, server_rec *,
     298                         conn_rec *, request_rec *,
     299                         char *));
    294300/* The ssl_proxy_enable() and ssl_engine_disable() optional functions
    295301 * are used by mod_proxy to enable use of SSL for outgoing
     
    297303APR_DECLARE_OPTIONAL_FN(int, ssl_proxy_enable, (conn_rec *));
    298304APR_DECLARE_OPTIONAL_FN(int, ssl_engine_disable, (conn_rec *));
     305APR_DECLARE_OPTIONAL_FN(int, ssl_engine_set, (conn_rec *,
     306                                              ap_conf_vector_t *,
     307                                              int proxy, int enable));
     308mgs_handle_t* get_effective_gnutls_ctxt(conn_rec *c);
    299309int ssl_is_https(conn_rec *c);
     310char* ssl_var_lookup(apr_pool_t *p, server_rec *s, conn_rec *c,
     311                     request_rec *r, char *var);
    300312int ssl_proxy_enable(conn_rec *c);
    301313int ssl_engine_disable(conn_rec *c);
     
    458470int mgs_hook_pre_connection(conn_rec * c, void *csd);
    459471
     472int mgs_hook_process_connection(conn_rec* c);
     473
    460474int mgs_hook_fixups(request_rec *r);
    461475
  • src/gnutls_cache.c

    rf5342b1 rf4ac9cc  
    33 *  Copyright 2008 Nikos Mavrogiannopoulos
    44 *  Copyright 2011 Dash Shendy
    5  *  Copyright 2015-2016 Thomas Klute
     5 *  Copyright 2015-2016 Fiona Klute
    66 *
    77 *  Licensed under the Apache License, Version 2.0 (the "License");
  • src/gnutls_cache.h

    rf5342b1 rf4ac9cc  
    22 *  Copyright 2004-2005 Paul Querna
    33 *  Copyright 2014 Nikos Mavrogiannopoulos
    4  *  Copyright 2015-2016 Thomas Klute
     4 *  Copyright 2015-2016 Fiona Klute
    55 *
    66 *  Licensed under the Apache License, Version 2.0 (the "License");
  • src/gnutls_config.c

    rf5342b1 rf4ac9cc  
    33 *  Copyright 2008, 2014 Nikos Mavrogiannopoulos
    44 *  Copyright 2011 Dash Shendy
    5  *  Copyright 2015-2016 Thomas Klute
     5 *  Copyright 2015-2016 Fiona Klute
    66 *
    77 *  Licensed under the Apache License, Version 2.0 (the "License");
  • src/gnutls_config.h

    rf5342b1 rf4ac9cc  
    11/*
    2  *  Copyright 2016 Thomas Klute
     2 *  Copyright 2016 Fiona Klute
    33 *
    44 *  Licensed under the Apache License, Version 2.0 (the "License");
  • src/gnutls_hooks.c

    rf5342b1 rf4ac9cc  
    44 *  Copyright 2011 Dash Shendy
    55 *  Copyright 2013-2014 Daniel Kahn Gillmor
    6  *  Copyright 2015-2017 Thomas Klute
     6 *  Copyright 2015-2018 Fiona Klute
    77 *
    88 *  Licensed under the Apache License, Version 2.0 (the "License");
     
    2222#include "gnutls_cache.h"
    2323#include "gnutls_ocsp.h"
     24#include "gnutls_util.h"
    2425#include "http_vhost.h"
    2526#include "ap_mpm.h"
     
    133134    return OK;
    134135}
     136
     137
     138
     139/**
     140 * Get the list of available protocols for this connection and add it
     141 * to the GnuTLS session. Must run before the client hello function.
     142 */
     143static void prepare_alpn_proposals(mgs_handle_t *ctxt)
     144{
     145    /* Check if any protocol upgrades are available
     146     *
     147     * The "report_all" parameter to ap_get_protocol_upgrades() is 0
     148     * (report only more preferable protocols) because setting it to 1
     149     * doesn't actually report ALL protocols, but only all except the
     150     * current one. This way we can at least list the current one as
     151     * available by appending it without potentially negotiating a
     152     * less preferred protocol. */
     153    const apr_array_header_t *pupgrades = NULL;
     154    apr_status_t ret =
     155        ap_get_protocol_upgrades(ctxt->c, NULL, ctxt->c->base_server,
     156                                 /*report_all*/ 0, &pupgrades);
     157    if (ret != APR_SUCCESS)
     158    {
     159        ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, ctxt->c,
     160                      "%s: ap_get_protocol_upgrades() failed, "
     161                      "cannot configure ALPN!", __func__);
     162        return;
     163    }
     164
     165    if (pupgrades == NULL || pupgrades->nelts == 0)
     166    {
     167        ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, ctxt->c,
     168                      "%s: No protocol upgrades available.", __func__);
     169        return;
     170    }
     171
     172    ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, ctxt->c,
     173                  "%s: Found %d protocol upgrade(s) for ALPN: %s",
     174                  __func__, pupgrades->nelts,
     175                  apr_array_pstrcat(ctxt->c->pool, pupgrades, ','));
     176    gnutls_datum_t *alpn_protos =
     177        apr_palloc(ctxt->c->pool,
     178                   (pupgrades->nelts + 1) * sizeof(gnutls_datum_t));
     179    for (int i = 0; i < pupgrades->nelts; i++)
     180    {
     181        alpn_protos[i].data = (void *) APR_ARRAY_IDX(pupgrades, i, char *);
     182        alpn_protos[i].size =
     183            strnlen(APR_ARRAY_IDX(pupgrades, i, char *),
     184                    pupgrades->elt_size);
     185    }
     186
     187    /* Add the current (default) protocol at the end of the list */
     188    alpn_protos[pupgrades->nelts].data =
     189        (void*) apr_pstrdup(ctxt->c->pool, ap_get_protocol(ctxt->c));
     190    alpn_protos[pupgrades->nelts].size =
     191        strlen((char*) alpn_protos[pupgrades->nelts].data);
     192    ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, ctxt->c,
     193                  "%s: Adding current protocol %s to ALPN set.",
     194                  __func__, alpn_protos[pupgrades->nelts].data);
     195
     196    gnutls_alpn_set_protocols(ctxt->session,
     197                              alpn_protos,
     198                              pupgrades->nelts,
     199                              GNUTLS_ALPN_SERVER_PRECEDENCE);
     200}
     201
     202
     203
     204/**
     205 * Check if ALPN selected any protocol upgrade, try to switch if so.
     206 */
     207static int process_alpn_result(mgs_handle_t *ctxt)
     208{
     209    int ret = 0;
     210    gnutls_datum_t alpn_proto;
     211    ret = gnutls_alpn_get_selected_protocol(ctxt->session, &alpn_proto);
     212    if (ret != GNUTLS_E_SUCCESS)
     213    {
     214        ap_log_cerror(APLOG_MARK, APLOG_TRACE1, APR_SUCCESS, ctxt->c,
     215                      "%s: No ALPN result: %s (%d)",
     216                      __func__, gnutls_strerror(ret), ret);
     217        return GNUTLS_E_SUCCESS;
     218    }
     219
     220    apr_array_header_t *client_protos =
     221        apr_array_make(ctxt->c->pool, 1, sizeof(char *));
     222    /* apr_pstrndup to ensure that the protocol is null terminated */
     223    APR_ARRAY_PUSH(client_protos, char *) =
     224        apr_pstrndup(ctxt->c->pool, (char*) alpn_proto.data, alpn_proto.size);
     225    const char *selected =
     226        ap_select_protocol(ctxt->c, NULL, ctxt->c->base_server,
     227                           client_protos);
     228
     229    /* ap_select_protocol() will return NULL if none of the ALPN
     230     * proposals matched. GnuTLS negotiated alpn_proto based on the
     231     * list provided by the server, but the vhost might have changed
     232     * based on SNI. Apache seems to adjust the proposal list to avoid
     233     * such issues though.
     234     *
     235     * GnuTLS will return a fatal "no_application_protocol" alert as
     236     * required by RFC 7301 if the post client hello function returns
     237     * GNUTLS_E_NO_APPLICATION_PROTOCOL. */
     238    if (!selected)
     239    {
     240        ap_log_cerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, ctxt->c,
     241                      "%s: ap_select_protocol() returned NULL! Please "
     242                      "make sure any overlapping vhosts have the same "
     243                      "protocols available.",
     244                      __func__);
     245        return GNUTLS_E_NO_APPLICATION_PROTOCOL;
     246    }
     247
     248    if (strcmp(selected, ap_get_protocol(ctxt->c)) == 0)
     249    {
     250        ap_log_cerror(APLOG_MARK, APLOG_TRACE1, APR_SUCCESS, ctxt->c,
     251                      "%s: Already using protocol '%s', nothing to do.",
     252                      __func__, selected);
     253        return GNUTLS_E_SUCCESS;
     254    }
     255
     256    ap_log_cerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, ctxt->c,
     257                  "%s: Switching protocol to '%s' based on ALPN.",
     258                  __func__, selected);
     259    apr_status_t status = ap_switch_protocol(ctxt->c, NULL,
     260                                             ctxt->c->base_server,
     261                                             selected);
     262    if (status != APR_SUCCESS)
     263    {
     264        ap_log_cerror(APLOG_MARK, APLOG_ERR, status, ctxt->c,
     265                      "%s: Protocol switch to '%s' failed!",
     266                      __func__, selected);
     267        return GNUTLS_E_NO_APPLICATION_PROTOCOL;
     268    }
     269    /* ALPN done! */
     270    return GNUTLS_E_SUCCESS;
     271}
     272
     273
    135274
    136275/**
     
    165304    gnutls_credentials_set(session, GNUTLS_CRD_ANON, ctxt->sc->anon_creds);
    166305
    167     if (ctxt->sc->ocsp_staple)
    168     {
    169         gnutls_certificate_set_ocsp_status_request_function(ctxt->sc->certs,
    170                                                             mgs_get_ocsp_response,
    171                                                             ctxt);
    172     }
    173 
    174306#ifdef ENABLE_SRP
    175307        /* Set SRP credentials */
     
    179311#endif
    180312
    181     /* update the priorities - to avoid negotiating a ciphersuite that is not
     313    ret = process_alpn_result(ctxt);
     314    if (ret != GNUTLS_E_SUCCESS)
     315        return ret;
     316
     317    /* Update the priorities - to avoid negotiating a ciphersuite that is not
    182318     * enabled on this virtual server. Note that here we ignore the version
    183      * negotiation.
    184      */
     319     * negotiation. */
    185320    ret = gnutls_priority_set(session, ctxt->sc->priorities);
    186321
     
    9641099static void create_gnutls_handle(conn_rec * c)
    9651100{
    966     /* Get mod_gnutls server configuration */
    967     mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
    968             ap_get_module_config(c->base_server->module_config, &gnutls_module);
    969 
    9701101    _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__);
    9711102
    9721103    /* Get connection specific configuration */
    973     mgs_handle_t *ctxt = (mgs_handle_t *) ap_get_module_config(c->conn_config, &gnutls_module);
    974     if (ctxt == NULL)
    975     {
    976         ctxt = apr_pcalloc(c->pool, sizeof (*ctxt));
    977         ap_set_module_config(c->conn_config, &gnutls_module, ctxt);
    978         ctxt->is_proxy = GNUTLS_ENABLED_FALSE;
    979     }
     1104    mgs_handle_t *ctxt = init_gnutls_ctxt(c);
    9801105    ctxt->enabled = GNUTLS_ENABLED_TRUE;
    981     ctxt->c = c;
    982     ctxt->sc = sc;
    9831106    ctxt->status = 0;
    9841107    ctxt->input_rc = APR_SUCCESS;
     
    10581181    }
    10591182
     1183    prepare_alpn_proposals(ctxt);
     1184
    10601185    /* Initialize Session Cache */
    10611186    mgs_cache_session_init(ctxt);
     
    10781203    _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__);
    10791204
     1205    if (c->master)
     1206    {
     1207        ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, c,
     1208                      "%s declined secondary connection", __func__);
     1209        return DECLINED;
     1210    }
     1211
    10801212    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
    10811213        ap_get_module_config(c->base_server->module_config, &gnutls_module);
     
    10831215        ap_get_module_config(c->conn_config, &gnutls_module);
    10841216
    1085     if ((sc && (!sc->enabled)) || (ctxt && ctxt->enabled == GNUTLS_ENABLED_FALSE))
     1217    if ((sc && (!sc->enabled))
     1218        || (ctxt && ctxt->enabled == GNUTLS_ENABLED_FALSE))
    10861219    {
    10871220        ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, "%s declined connection",
     
    10931226    return OK;
    10941227}
     1228
     1229
     1230
     1231/**
     1232 * process_connection hook: Do a zero byte read to trigger the
     1233 * handshake. Doesn't change anything for traditional protocols that
     1234 * just do reads, but HTTP/2 needs the TLS handshake and ALPN to
     1235 * happen before its process_connection hook runs.
     1236 */
     1237int mgs_hook_process_connection(conn_rec* c)
     1238{
     1239    mgs_handle_t *ctxt = (mgs_handle_t *)
     1240        ap_get_module_config(c->conn_config, &gnutls_module);
     1241
     1242    if ((ctxt != NULL) && (ctxt->enabled == GNUTLS_ENABLED_TRUE))
     1243    {
     1244        /* This connection is supposed to use TLS. Give the filters a
     1245         * kick with a zero byte read to trigger the handshake. */
     1246        apr_bucket_brigade* temp =
     1247            apr_brigade_create(c->pool, c->bucket_alloc);
     1248        ap_get_brigade(c->input_filters, temp,
     1249                       AP_MODE_INIT, APR_BLOCK_READ, 0);
     1250        apr_brigade_destroy(temp);
     1251    }
     1252    return DECLINED;
     1253}
     1254
     1255
    10951256
    10961257int mgs_hook_fixups(request_rec * r) {
     
    11071268    apr_table_t *env = r->subprocess_env;
    11081269
    1109     ctxt = ap_get_module_config(r->connection->conn_config,
    1110                                 &gnutls_module);
     1270    ctxt = get_effective_gnutls_ctxt(r->connection);
    11111271
    11121272    if (!ctxt || ctxt->enabled != GNUTLS_ENABLED_TRUE || ctxt->session == NULL)
     
    11881348
    11891349    _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__);
    1190     ctxt =
    1191             ap_get_module_config(r->connection->conn_config,
    1192             &gnutls_module);
     1350    ctxt = get_effective_gnutls_ctxt(r->connection);
    11931351
    11941352    if (!ctxt || ctxt->session == NULL) {
     
    19202078    if (sc->enabled != GNUTLS_ENABLED_FALSE)
    19212079    {
    1922         mgs_handle_t* ctxt =
    1923             ap_get_module_config(r->connection->conn_config, &gnutls_module);
     2080        mgs_handle_t* ctxt = get_effective_gnutls_ctxt(r->connection);
    19242081        if (ctxt && ctxt->session != NULL)
    19252082        {
  • src/gnutls_io.c

    rf5342b1 rf4ac9cc  
    33 *  Copyright 2008 Nikos Mavrogiannopoulos
    44 *  Copyright 2011 Dash Shendy
    5  *  Copyright 2015-2017 Thomas Klute
     5 *  Copyright 2015-2017 Fiona Klute
    66 *
    77 *  Licensed under the Apache License, Version 2.0 (the "License");
  • src/gnutls_ocsp.c

    rf5342b1 rf4ac9cc  
    11/*
    2  *  Copyright 2016 Thomas Klute
     2 *  Copyright 2016 Fiona Klute
    33 *
    44 *  Licensed under the Apache License, Version 2.0 (the "License");
     
    737737
    738738
    739 int mgs_get_ocsp_response(gnutls_session_t session __attribute__((unused)),
    740                           void *ptr,
     739int mgs_get_ocsp_response(gnutls_session_t session,
     740                          void *ptr __attribute__((unused)),
    741741                          gnutls_datum_t *ocsp_response)
    742742{
    743     mgs_handle_t *ctxt = (mgs_handle_t *) ptr;
    744     if (!ctxt->sc->ocsp_staple || ctxt->sc->cache == NULL)
     743    mgs_handle_t *ctxt = gnutls_session_get_ptr(session);
     744    mgs_srvconf_rec *sc = ctxt->sc;
     745
     746    if (!sc->ocsp_staple || sc->cache == NULL)
    745747    {
    746748        /* OCSP must be enabled and caching requires a cache. */
     
    748750    }
    749751
    750     *ocsp_response = ctxt->sc->cache->fetch(ctxt,
    751                                             ctxt->sc->ocsp->fingerprint);
     752    *ocsp_response = sc->cache->fetch(ctxt,
     753                                      sc->ocsp->fingerprint);
    752754    if (ocsp_response->size == 0)
    753755    {
     
    775777                  "No valid OCSP response in cache, trying to update.");
    776778
    777     apr_status_t rv = apr_global_mutex_trylock(ctxt->sc->ocsp_mutex);
     779    apr_status_t rv = apr_global_mutex_trylock(sc->ocsp_mutex);
    778780    if (APR_STATUS_IS_EBUSY(rv))
    779781    {
    780782        /* Another thread is currently holding the mutex, wait. */
    781         apr_global_mutex_lock(ctxt->sc->ocsp_mutex);
     783        apr_global_mutex_lock(sc->ocsp_mutex);
    782784        /* Check if this other thread updated the response we need. It
    783785         * would be better to have a vhost specific mutex, but at the
    784786         * moment there's no good way to integrate that with the
    785787         * Apache Mutex directive. */
    786         *ocsp_response = ctxt->sc->cache->fetch(ctxt,
    787                                                 ctxt->sc->ocsp->fingerprint);
     788        *ocsp_response = sc->cache->fetch(ctxt,
     789                                          sc->ocsp->fingerprint);
    788790        if (ocsp_response->size > 0)
    789791        {
    790792            /* Got a valid response now, unlock mutex and return. */
    791             apr_global_mutex_unlock(ctxt->sc->ocsp_mutex);
     793            apr_global_mutex_unlock(sc->ocsp_mutex);
    792794            return GNUTLS_E_SUCCESS;
    793795        }
     
    806808        /* cache failure to rate limit retries */
    807809        mgs_cache_ocsp_failure(ctxt->c->base_server);
    808         apr_global_mutex_unlock(ctxt->sc->ocsp_mutex);
     810        apr_global_mutex_unlock(sc->ocsp_mutex);
    809811        goto fail_cleanup;
    810812    }
    811     apr_global_mutex_unlock(ctxt->sc->ocsp_mutex);
     813    apr_global_mutex_unlock(sc->ocsp_mutex);
    812814
    813815    /* retry reading from cache */
    814     *ocsp_response = ctxt->sc->cache->fetch(ctxt,
    815                                             ctxt->sc->ocsp->fingerprint);
     816    *ocsp_response = sc->cache->fetch(ctxt,
     817                                      sc->ocsp->fingerprint);
    816818    if (ocsp_response->size == 0)
    817819    {
     
    976978                              apr_pool_cleanup_null);
    977979
     980    /* enable status request callback */
     981    gnutls_certificate_set_ocsp_status_request_function(sc->certs,
     982                                                        mgs_get_ocsp_response,
     983                                                        sc);
     984
    978985    return OK;
    979986}
  • src/gnutls_ocsp.h

    rf5342b1 rf4ac9cc  
    11/*
    2  *  Copyright 2016 Thomas Klute
     2 *  Copyright 2016 Fiona Klute
    33 *
    44 *  Licensed under the Apache License, Version 2.0 (the "License");
  • src/gnutls_util.c

    rf5342b1 rf4ac9cc  
    11/*
    2  *  Copyright 2016 Thomas Klute
     2 *  Copyright 2016-2018 Fiona Klute
    33 *
    44 *  Licensed under the Apache License, Version 2.0 (the "License");
     
    126126    return rv;
    127127}
     128
     129
     130
     131mgs_handle_t *init_gnutls_ctxt(conn_rec *c)
     132{
     133    mgs_handle_t *ctxt = (mgs_handle_t *)
     134        ap_get_module_config(c->conn_config, &gnutls_module);
     135    if (ctxt == NULL)
     136    {
     137        ctxt = apr_pcalloc(c->pool, sizeof (*ctxt));
     138        ap_set_module_config(c->conn_config, &gnutls_module, ctxt);
     139
     140        /* Get mod_gnutls server configuration */
     141        mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
     142            ap_get_module_config(c->base_server->module_config,
     143                                 &gnutls_module);
     144
     145        /* Set up connection and server references */
     146        ctxt->c = c;
     147        ctxt->sc = sc;
     148        /* Default, unconditionally changed in proxy setup functions */
     149        ctxt->is_proxy = GNUTLS_ENABLED_FALSE;
     150    }
     151    return ctxt;
     152}
  • src/gnutls_util.h

    rf5342b1 rf4ac9cc  
    11/*
    2  *  Copyright 2016 Thomas Klute
     2 *  Copyright 2016-2018 Fiona Klute
    33 *
    44 *  Licensed under the Apache License, Version 2.0 (the "License");
     
    2121#include <apr_uri.h>
    2222#include <gnutls/gnutls.h>
     23#include "mod_gnutls.h"
    2324
    2425#ifndef __MOD_GNUTLS_UTIL_H__
     
    6768    __attribute__((nonnull));
    6869
     70/**
     71 * Allocate the connection configuration structure if necessary, set
     72 * some defaults.
     73 */
     74mgs_handle_t *init_gnutls_ctxt(conn_rec *c);
     75
    6976#endif /* __MOD_GNUTLS_UTIL_H__ */
  • src/mod_gnutls.c

    rf5342b1 rf4ac9cc  
    33 *  Copyright 2008, 2014 Nikos Mavrogiannopoulos
    44 *  Copyright 2011 Dash Shendy
    5  *  Copyright 2015-2016 Thomas Klute
     5 *  Copyright 2015-2018 Fiona Klute
    66 *
    77 *  Licensed under the Apache License, Version 2.0 (the "License");
     
    2020#include "mod_gnutls.h"
    2121#include "gnutls_ocsp.h"
     22#include "gnutls_util.h"
    2223
    2324#ifdef APLOG_USE_MODULE
     
    2526#endif
    2627
     28int ssl_engine_set(conn_rec *c,
     29                   ap_conf_vector_t *dir_conf __attribute__((unused)),
     30                   int proxy, int enable);
     31
     32static const char * const mod_proxy[] = { "mod_proxy.c", NULL };
     33static const char * const mod_http2[] = { "mod_http2.c", NULL };
     34
    2735static void gnutls_hooks(apr_pool_t * p __attribute__((unused)))
    2836{
    2937    /* Try Run Post-Config Hook After mod_proxy */
    30     static const char * const aszPre[] = { "mod_proxy.c", NULL };
    31     ap_hook_post_config(mgs_hook_post_config, aszPre, NULL,
    32                         APR_HOOK_REALLY_LAST);
     38    ap_hook_post_config(mgs_hook_post_config, mod_proxy, mod_http2,
     39                        APR_HOOK_MIDDLE);
    3340    /* HTTP Scheme Hook */
    3441    ap_hook_http_scheme(mgs_hook_http_scheme, NULL, NULL, APR_HOOK_MIDDLE);
     
    3643    ap_hook_default_port(mgs_hook_default_port, NULL, NULL, APR_HOOK_MIDDLE);
    3744    /* Pre-Connect Hook */
    38     ap_hook_pre_connection(mgs_hook_pre_connection, NULL, NULL,
     45    ap_hook_pre_connection(mgs_hook_pre_connection, mod_http2, NULL,
    3946                           APR_HOOK_MIDDLE);
     47    ap_hook_process_connection(mgs_hook_process_connection,
     48                               NULL, mod_http2, APR_HOOK_MIDDLE);
    4049    /* Pre-Config Hook */
    4150    ap_hook_pre_config(mgs_hook_pre_config, NULL, NULL,
     
    6574    APR_REGISTER_OPTIONAL_FN(ssl_proxy_enable);
    6675    APR_REGISTER_OPTIONAL_FN(ssl_engine_disable);
     76    APR_REGISTER_OPTIONAL_FN(ssl_engine_set);
    6777
    6878    /* mod_rewrite calls this function to detect HTTPS */
    6979    APR_REGISTER_OPTIONAL_FN(ssl_is_https);
     80    /* some modules look up TLS-related variables */
     81    APR_REGISTER_OPTIONAL_FN(ssl_var_lookup);
     82}
     83
     84
     85
     86/**
     87 * Get the connection context, resolving to a master connection if
     88 * any.
     89 *
     90 * @param c the connection handle
     91 *
     92 * @return mod_gnutls session context, might be `NULL`
     93 */
     94mgs_handle_t* get_effective_gnutls_ctxt(conn_rec *c)
     95{
     96    mgs_handle_t *ctxt = (mgs_handle_t *)
     97        ap_get_module_config(c->conn_config, &gnutls_module);
     98    if (!(ctxt != NULL && ctxt->enabled) && (c->master != NULL))
     99    {
     100        ctxt = (mgs_handle_t *)
     101            ap_get_module_config(c->master->conn_config, &gnutls_module);
     102    }
     103    return ctxt;
    70104}
    71105
     
    80114int ssl_is_https(conn_rec *c)
    81115{
     116    mgs_handle_t *ctxt = get_effective_gnutls_ctxt(c);
    82117    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
    83118        ap_get_module_config(c->base_server->module_config, &gnutls_module);
    84     mgs_handle_t *ctxt = (mgs_handle_t *)
    85         ap_get_module_config(c->conn_config, &gnutls_module);
    86119
    87120    if(sc->enabled == GNUTLS_ENABLED_FALSE
     
    98131
    99132
    100 int ssl_engine_disable(conn_rec *c)
    101 {
    102     mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
    103         ap_get_module_config(c->base_server->module_config, &gnutls_module);
    104     if(sc->enabled == GNUTLS_ENABLED_FALSE) {
    105         return 1;
    106     }
    107 
    108     /* disable TLS for this connection */
    109     mgs_handle_t *ctxt = (mgs_handle_t *)
    110         ap_get_module_config(c->conn_config, &gnutls_module);
    111     if (ctxt == NULL)
     133/**
     134 * Return variables describing the current TLS session (if any).
     135 *
     136 * mod_ssl doc for this function: "This function must remain safe to
     137 * use for a non-SSL connection." mod_http2 uses it to check if an
     138 * acceptable TLS session is used.
     139 */
     140char* ssl_var_lookup(apr_pool_t *p, server_rec *s __attribute__((unused)),
     141                     conn_rec *c, request_rec *r, char *var)
     142{
     143    /*
     144     * When no pool is given try to find one
     145     */
     146    if (p == NULL) {
     147        if (r != NULL)
     148            p = r->pool;
     149        else if (c != NULL)
     150            p = c->pool;
     151        else
     152            return NULL;
     153    }
     154
     155    if (strcmp(var, "HTTPS") == 0)
    112156    {
    113         ctxt = apr_pcalloc(c->pool, sizeof (*ctxt));
    114         ap_set_module_config(c->conn_config, &gnutls_module, ctxt);
    115     }
    116     ctxt->enabled = GNUTLS_ENABLED_FALSE;
    117     ctxt->is_proxy = GNUTLS_ENABLED_TRUE;
    118 
    119     if (c->input_filters)
    120         ap_remove_input_filter(c->input_filters);
    121     if (c->output_filters)
    122         ap_remove_output_filter(c->output_filters);
    123 
    124     return 1;
    125 }
    126 
    127 int ssl_proxy_enable(conn_rec *c)
    128 {
    129     /* check if TLS proxy support is enabled */
    130     mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
    131         ap_get_module_config(c->base_server->module_config, &gnutls_module);
    132     if (sc->proxy_enabled != GNUTLS_ENABLED_TRUE)
     157        if (c != NULL && ssl_is_https(c))
     158            return "on";
     159        else
     160            return "off";
     161    }
     162
     163    mgs_handle_t *ctxt = get_effective_gnutls_ctxt(c);
     164
     165    /* TLS parameters are empty if there is no session */
     166    if (ctxt == NULL || ctxt->c == NULL)
     167        return NULL;
     168
     169    if (strcmp(var, "SSL_PROTOCOL") == 0)
     170        return apr_pstrdup(p, gnutls_protocol_get_name(gnutls_protocol_get_version(ctxt->session)));
     171
     172    if (strcmp(var, "SSL_CIPHER") == 0)
     173        return apr_pstrdup(p, gnutls_cipher_suite_get_name(gnutls_kx_get(ctxt->session),
     174                                                           gnutls_cipher_get(ctxt->session),
     175                                                           gnutls_mac_get(ctxt->session)));
     176
     177    /* mod_ssl supports a LOT more variables */
     178    ap_log_cerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, c,
     179                  "unsupported variable requested: '%s'",
     180                  var);
     181
     182    return NULL;
     183}
     184
     185
     186
     187/**
     188 * In Apache versions from 2.4.33 mod_proxy uses this function to set
     189 * up its client connections. Note that mod_gnutls does not (yet)
     190 * implement per directory configuration for such connections.
     191 *
     192 * @param c the connection
     193 * @param dir_conf per directory configuration, unused for now
     194 * @param proxy Is this a proxy connection?
     195 * @param enable Should TLS be enabled on this connection?
     196 *
     197 * @param `true` (1) if successful, `false` (0) otherwise
     198 */
     199int ssl_engine_set(conn_rec *c,
     200                   ap_conf_vector_t *dir_conf __attribute__((unused)),
     201                   int proxy, int enable)
     202{
     203    mgs_handle_t *ctxt = init_gnutls_ctxt(c);
     204
     205    /* If TLS proxy has been requested, check if support is enabled
     206     * for the server */
     207    if (proxy && (ctxt->sc->proxy_enabled != GNUTLS_ENABLED_TRUE))
    133208    {
    134209        ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c,
    135210                      "%s: mod_proxy requested TLS proxy, but not enabled "
    136                       "for %s", __func__, sc->cert_cn);
     211                      "for %s", __func__, ctxt->sc->cert_cn);
    137212        return 0;
    138213    }
    139214
    140     /* enable TLS for this connection */
    141     mgs_handle_t *ctxt = (mgs_handle_t *)
    142         ap_get_module_config(c->conn_config, &gnutls_module);
    143     if (ctxt == NULL)
    144     {
    145         ctxt = apr_pcalloc(c->pool, sizeof (*ctxt));
    146         ap_set_module_config(c->conn_config, &gnutls_module, ctxt);
    147     }
    148     ctxt->enabled = GNUTLS_ENABLED_TRUE;
    149     ctxt->is_proxy = GNUTLS_ENABLED_TRUE;
     215    if (proxy)
     216        ctxt->is_proxy = GNUTLS_ENABLED_TRUE;
     217    else
     218        ctxt->is_proxy = GNUTLS_ENABLED_FALSE;
     219
     220    if (enable)
     221        ctxt->enabled = GNUTLS_ENABLED_TRUE;
     222    else
     223        ctxt->enabled = GNUTLS_ENABLED_FALSE;
     224
    150225    return 1;
     226}
     227
     228int ssl_engine_disable(conn_rec *c)
     229{
     230    return ssl_engine_set(c, NULL, 0, 0);
     231}
     232
     233int ssl_proxy_enable(conn_rec *c)
     234{
     235    return ssl_engine_set(c, NULL, 1, 1);
    151236}
    152237
  • test/Makefile.am

    rf5342b1 rf4ac9cc  
    3030        test-25_Disable_TLS_1.0.bash \
    3131        test-26_redirect_HTTP_to_HTTPS.bash \
    32         test-27_OCSP_server.bash
     32        test-27_OCSP_server.bash \
     33        test-28_HTTP2_support.bash
    3334
    3435TEST_EXTENSIONS = .bash
  • test/README

    rf5342b1 rf4ac9cc  
    33
    44Authors: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
    5          Thomas Klute <thomas2.klute@uni-dortmund.de>
     5         Fiona Klute <fiona.klute@gmx.de>
    66
    77There are a lot of ways that a TLS-capable web server can go wrong.  I
  • test/cert_helper.c

    rf5342b1 rf4ac9cc  
    22 * Helper functions for certificate handling in the mod_gnutls test suite
    33 *
    4  * Copyright 2016 Thomas Klute
     4 * Copyright 2016 Fiona Klute
    55 *
    66 * Licensed under the Apache License, Version 2.0 (the "License"); you
  • test/cert_helper.h

    rf5342b1 rf4ac9cc  
    22 * Helper functions for certificate handling in the mod_gnutls test suite
    33 *
    4  * Copyright 2016 Thomas Klute
     4 * Copyright 2016 Fiona Klute
    55 *
    66 * Licensed under the Apache License, Version 2.0 (the "License"); you
  • test/data/ocsp.cgi

    rf5342b1 rf4ac9cc  
    22# CGI wrapper to use "openssl ocsp" as a simple OCSP responder
    33#
    4 # Copyright 2016 Thomas Klute
     4# Copyright 2016 Fiona Klute
    55#
    66# Licensed under the Apache License, Version 2.0 (the "License"); you
  • test/gen_ocsp_index.c

    rf5342b1 rf4ac9cc  
    55 * moment, all certificates are marked as valid.
    66 *
    7  * Copyright 2016 Thomas Klute
     7 * Copyright 2016 Fiona Klute
    88 *
    99 * Licensed under the Apache License, Version 2.0 (the "License"); you
  • test/gnutls_openpgp_support.c

    rf5342b1 rf4ac9cc  
    22 * Check if GnuTLS was compiled with OpenPGP support
    33 *
    4  * Copyright 2017 Thomas Klute
     4 * Copyright 2017 Fiona Klute
    55 *
    66 * Licensed under the Apache License, Version 2.0 (the "License"); you
  • test/runtests

    rf5342b1 rf4ac9cc  
    33# Authors:
    44# Daniel Kahn Gillmor <dkg@fifthhorseman.net>
    5 # Thomas Klute <thomas2.klute@uni-dortmund.de>
     5# Fiona Klute <fiona.klute@gmx.de>
    66
    77set -e
  • test/test-26_redirect_HTTP_to_HTTPS.bash

    rf5342b1 rf4ac9cc  
    1616export TEST_HTTP_PORT
    1717
    18 # "Proxy backend" functions are used to start the only instance needed
    19 # here without "runtests". We have to override BACKEND_PORT to make it
    20 # match what a runtests-based test would use.
    21 export BACKEND_PORT="${TEST_PORT}"
    22 function stop_backend
     18function stop_server
    2319{
    2420    apache_service "${testdir}" "apache.conf" stop
    2521}
    2622apache_service "${testdir}" "apache.conf" start "${TEST_LOCK}"
    27 trap stop_backend EXIT
     23trap stop_server EXIT
    2824
    2925output="outputs/${TEST_NAME}.output"
     
    4642grep "Current TLS session: (TLS" "${output}"
    4743
    48 apache_service "${testdir}" "apache.conf" stop
     44stop_server
    4945trap - EXIT
  • test/test_ca.mk

    rf5342b1 rf4ac9cc  
    22# Authors:
    33# Daniel Kahn Gillmor <dkg@fifthhorseman.net>
    4 # Thomas Klute <thomas2.klute@uni-dortmund.de>
     4# Fiona Klute <fiona.klute@gmx.de>
    55
    66# General rules to set up a miniature CA & server & client environment
  • test/tests/Makefile.am

    rf5342b1 rf4ac9cc  
    2727        25_Disable_TLS_1.0/apache.conf 25_Disable_TLS_1.0/fail.client 25_Disable_TLS_1.0/gnutls-cli.args 25_Disable_TLS_1.0/input \
    2828        26_redirect_HTTP_to_HTTPS/apache.conf \
    29         27_OCSP_server/apache.conf 27_OCSP_server/gnutls-cli.args 27_OCSP_server/input 27_OCSP_server/ocsp.conf 27_OCSP_server/output
     29        27_OCSP_server/apache.conf 27_OCSP_server/gnutls-cli.args 27_OCSP_server/input 27_OCSP_server/ocsp.conf 27_OCSP_server/output \
     30        28_HTTP2_support/apache.conf
Note: See TracChangeset for help on using the changeset viewer.