Changes in / [2afbe2e:9b20a1e] in mod_gnutls


Ignore:
Files:
163 added
96 deleted
11 edited

Legend:

Unmodified
Added
Removed
  • CHANGELOG

    r2afbe2e r9b20a1e  
    11**TODO:
    2 - Fix support for proxy termination
    32- Handle Unclean Shutdowns
    43- make session cache use generic apache caches
     4
     5** Version 0.7 beta (2015-06-27)
     6- Security fix for TLS client authentication (CVE-2015-2091)
     7- Bug fixes that enable support for reverse proxy operation
     8- Various test suite improvements. Tests are configured through autoconf,
     9  so the test suite now works for builds without Monkeysphere support.
     10- Add support for TLS connections to back end servers when operating as a
     11  reverse proxy (X.509 authentication only at the moment).
     12- PKCS #11 support for server keys and certificates
     13- Use strict compiler arguments by default (-Wall -Werror -Wextra)
     14- Allow limiting the size of certificates exported as SSL_SERVER_CERT
     15  and SSL_CLIENT_CERT through the GnuTLSExportCertificates directive
    516
    617** Version 0.6 (2014-02-17)
     
    8899- Added support for subject alternative names in certificates.
    89100Only one per certificate is supported.
    90 - New enviroment variables: SSL_CLIENT_M_VERSION, SSL_CLIENT_S_SAN%, 
     101- New enviroment variables: SSL_CLIENT_M_VERSION, SSL_CLIENT_S_SAN%,
    91102SSL_CLIENT_S_TYPE, SSL_SERVER_M_VERSION, SSL_SERVER_S_SAN%, SSL_SERVER_S_TYPE
    92103- The compatibility mode can now be enabled explicitely with the
  • Makefile.am

    r2afbe2e r9b20a1e  
    22
    33EXTRA_DIST = m4/outoforder.m4 m4/apache.m4 \
    4                 m4/libgnutls.m4 m4/apr_memcache.m4 \
     4                m4/apr_memcache.m4 \
    55                m4/apache_test.m4  \
    66                include/mod_gnutls.h.in \
    7                 README README.ENV NEWS \
    8                 NOTICE LICENSE autogen.sh
     7                README CHANGELOG \
     8                NOTICE LICENSE
    99
    10 SUBDIRS = src
     10SUBDIRS = src test doc
    1111ACLOCAL_AMFLAGS = -I m4
    12 TESTS = run_tests.sh
  • README

    r2afbe2e r9b20a1e  
    1818  Nikos Mavrogiannopoulos <nmav at gnutls.org>
    1919  Dash Shendy <neuromancer at dash.za.net>
     20  Thomas Klute <thomas2.klute@uni-dortmund.de>
    2021
    2122Prerequisites
    2223-------------
    2324
    24  * GnuTLS          >= 2.12.6 <http://www.gnutls.org/> (3.* preferred)
     25 * GnuTLS          >= 3.1.4 <http://www.gnutls.org/> (3.2.* or newer preferred)
    2526 * Apache HTTPD    >= 2.2 <http://httpd.apache.org/> (2.4.* preferred)
    2627 * autotools & gcc
    2728 * APR Memcache    >= 0.7.0 (Optional)
    28  * libmsv          >= 0.1 (Optional)
     29 * libmsv          >= 0.1 (Optional, enable with ./configure --enable-msva)
     30 * pandoc (for documentation, optional)
    2931
    3032Installation
     
    3436 cd mod_gnutls-version/
    3537 autoreconf -fiv
    36  ./configure --with-apxs=PATH --enable-msva
     38 ./configure
    3739 make
    3840 make install
  • configure.ac

    r2afbe2e r9b20a1e  
    11dnl
    2 AC_INIT(mod_gnutls, 0.6)
     2AC_INIT(mod_gnutls, 0.7-beta)
    33OOO_CONFIG_NICE(config.nice)
    44MOD_GNUTLS_VERSION=AC_PACKAGE_VERSION
     
    2828)
    2929
    30 PKG_CHECK_MODULES([LIBGNUTLS], [gnutls >= 2.12.6])
     30PKG_CHECK_MODULES([LIBGNUTLS], [gnutls >= 3.1.4])
    3131
    3232LIBGNUTLS_VERSION=`pkg-config --modversion gnutls`
     
    3737       use_srp=$enableval, use_srp=yes)
    3838
     39# check if the available GnuTLS library supports SRP
     40AC_SEARCH_LIBS([gnutls_srp_server_get_username], [gnutls], [], [use_srp="no"])
     41
    3942SRP_CFLAGS=""
    4043if test "$use_srp" != "no"; then
    41         SRP_CFLAGS="-DENABLE_SRP=1"
     44        SRP_CFLAGS="-DENABLE_SRP=1"
    4245fi
    4346
     
    5962               [enable Monkeysphere client certificate verification]),
    6063       use_msva=$enableval, use_msva=no)
     64AM_CONDITIONAL([USE_MSVA], [test "$use_msva" != "no"])
    6165
    6266MSVA_CFLAGS=""
    6367if test "$use_msva" != "no"; then
    64         AC_CHECK_HEADERS([msv/msv.h], [],
     68        AC_CHECK_HEADERS([msv/msv.h], [],
    6569                         [AC_MSG_ERROR([*** No libmsv headers found!])])
    6670        AC_SEARCH_LIBS([msv_query_agent], [msv], [],
    6771                         [AC_MSG_ERROR([*** No libmsv found with msv_query_agent!])])
    68         MSVA_CFLAGS="-DENABLE_MSVA=1"
     72        MSVA_CFLAGS="-DENABLE_MSVA=1"
    6973fi
    7074
     
    7680AC_SUBST(have_apr_memcache)
    7781
     82# Building documentation requires pandoc, which in turn needs pdflatex
     83# to build PDF output.
     84build_doc=no
     85AC_PATH_PROG([PANDOC], [pandoc], [no])
     86if test "$PANDOC" != "no"; then
     87        AC_PATH_PROG([PDFLATEX], [pdflatex], [no])
     88        if test "$PDFLATEX" != "no"; then
     89                build_doc=yes
     90        else
     91                build_doc="html only"
     92        fi
     93fi
     94AM_CONDITIONAL([USE_PANDOC], [test "$PANDOC" != "no"])
     95AM_CONDITIONAL([USE_PDFLATEX], [test "$PANDOC" != "no" && \
     96                               test "$PDFLATEX" != "no"])
     97
     98# Check for Apache binary
     99AC_PATH_PROGS([APACHE2], [apache2 httpd], [no])
     100if test "${APACHE2}" = "no"; then
     101        AC_MSG_WARN([Neither apache2 nor httpd found in \
     102                     PATH. Test suite will fail.])
     103fi
     104
    78105MODULE_CFLAGS="${LIBGNUTLS_CFLAGS} ${SRP_CFLAGS} ${MSVA_CFLAGS} ${APR_MEMCACHE_CFLAGS} ${APXS_CFLAGS} ${AP_INCLUDES} ${APR_INCLUDES} ${APU_INCLUDES} ${STRICT_CFLAGS}"
    79106MODULE_LIBS="${APR_MEMCACHE_LIBS} ${LIBGNUTLS_LIBS}"
     
    82109AC_SUBST(MODULE_LIBS)
    83110
    84 AC_CONFIG_FILES([Makefile src/Makefile include/mod_gnutls.h])
     111AC_CONFIG_FILES([Makefile src/Makefile test/Makefile test/tests/Makefile \
     112                          doc/Makefile include/mod_gnutls.h])
    85113AC_OUTPUT
    86114
     
    91119echo "   * Apache Modules directory:    ${AP_LIBEXECDIR}"
    92120echo "   * GnuTLS Library version:      ${LIBGNUTLS_VERSION}"
    93 echo "   * SRP Authentication:          ${use_srp}"
    94 echo "   * MSVA Client Verification:    ${use_msva}"
     121echo "   * SRP Authentication:  ${use_srp}"
     122echo "   * MSVA Client Verification:    ${use_msva}"
     123echo "   * Build documentation: ${build_doc}"
    95124echo ""
    96125echo "---"
  • include/mod_gnutls.h.in

    r2afbe2e r9b20a1e  
    11/**
    22 *  Copyright 2004-2005 Paul Querna
     3 *  Copyright 2015 Thomas Klute
    34 *
    45 *  Licensed under the Apache License, Version 2.0 (the "License");
     
    3435#include <gnutls/extra.h>
    3536#endif
     37#include <gnutls/abstract.h>
    3638#include <gnutls/openpgp.h>
    3739#include <gnutls/x509.h>
     
    104106/* Server Configuration Record */
    105107typedef struct {
    106         /* x509 Certificate Structure */
     108    /* --- Configuration values --- */
     109        /* Is the module enabled? */
     110    int enabled;
     111        /* Is mod_proxy enabled? */
     112    int proxy_enabled;
     113        /* A Plain HTTP request */
     114    int non_ssl_request;
     115
     116    /* Additional PKCS #11 provider module to load, only valid in the
     117     * base config, ignored in virtual hosts */
     118    char *p11_module;
     119
     120    /* PIN used for PKCS #11 operations */
     121    char *pin;
     122
     123    /* the SRK PIN used in TPM operations */
     124    char *srk_pin;
     125
     126    char *x509_cert_file;
     127    char *x509_key_file;
     128    char *x509_ca_file;
     129
     130    char *pgp_cert_file;
     131    char *pgp_key_file;
     132    char *pgp_ring_file;
     133
     134    char *dh_file;
     135
     136    char *priorities_str;
     137    char *proxy_priorities_str;
     138
     139    const char* srp_tpasswd_file;
     140    const char* srp_tpasswd_conf_file;
     141
     142        /* Cache timeout value */
     143    int cache_timeout;
     144        /* Chose Cache Type */
     145    mgs_cache_e cache_type;
     146    const char* cache_config;
     147
     148        /* GnuTLS uses Session Tickets */
     149    int tickets;
     150
     151    /* --- Things initialized at _child_init --- */
     152
     153    /* x509 Certificate Structure */
    107154    gnutls_certificate_credentials_t certs;
    108         /* SRP Certificate Structure*/
     155    /* x509 credentials for proxy connections */
     156    gnutls_certificate_credentials_t proxy_x509_creds;
     157    /* trust list for proxy_x509_creds */
     158    gnutls_x509_trust_list_t proxy_x509_tl;
     159    const char* proxy_x509_key_file;
     160    const char* proxy_x509_cert_file;
     161    const char* proxy_x509_ca_file;
     162    const char* proxy_x509_crl_file;
     163    /* GnuTLS priorities for proxy connections */
     164    gnutls_priority_t proxy_priorities;
     165    /* SRP Certificate Structure*/
    109166    gnutls_srp_server_credentials_t srp_creds;
    110         /* Annonymous Certificate Structure */
     167    /* Anonymous Certificate Structure */
    111168    gnutls_anon_server_credentials_t anon_creds;
     169    /* Anonymous Client Certificate Structure, used for proxy
     170     * connections */
     171    gnutls_anon_client_credentials_t anon_client_creds;
    112172        /* Current x509 Certificate CN [Common Name] */
    113173    char* cert_cn;
    114174        /* Current x509 Certificate SAN [Subject Alternate Name]s*/
    115         char* cert_san[MAX_CERT_SAN];
    116         /* A x509 Certificate Chain */
    117     gnutls_x509_crt_t *certs_x509_chain;
    118         /* Current x509 Certificate Private Key */
    119     gnutls_x509_privkey_t privkey_x509;
    120         /* OpenPGP Certificate */
    121     gnutls_openpgp_crt_t cert_pgp;
    122         /* OpenPGP Certificate Private Key */
    123     gnutls_openpgp_privkey_t privkey_pgp;
     175    char* cert_san[MAX_CERT_SAN];
     176        /* An x509 Certificate Chain */
     177    gnutls_pcert_st *certs_x509_chain;
     178    gnutls_x509_crt_t *certs_x509_crt_chain;
    124179        /* Number of Certificates in Chain */
    125180    unsigned int certs_x509_chain_num;
    126         /* Is the module enabled? */
    127     int enabled;
     181
     182        /* Current x509 Certificate Private Key */
     183    gnutls_privkey_t privkey_x509;
     184
     185        /* OpenPGP Certificate */
     186    gnutls_pcert_st *cert_pgp;
     187    gnutls_openpgp_crt_t *cert_crt_pgp;
     188
     189        /* OpenPGP Certificate Private Key */
     190    gnutls_privkey_t privkey_pgp;
     191#if GNUTLS_VERSION_NUMBER < 0x030312
     192    /* Internal structure for the OpenPGP private key, used in the
     193     * workaround for a bug in gnutls_privkey_import_openpgp_raw that
     194     * frees memory that is still needed. DO NOT USE for any other
     195     * purpose. */
     196    gnutls_openpgp_privkey_t privkey_pgp_internal;
     197#endif
     198
    128199    /* Export full certificates to CGI environment: */
    129200    int export_certificates_size;
     
    132203        /* GnuTLS DH Parameters */
    133204    gnutls_dh_params_t dh_params;
    134         /* Cache timeout value */
    135     int cache_timeout;
    136         /* Chose Cache Type */
    137     mgs_cache_e cache_type;
    138     const char* cache_config;
    139     const char* srp_tpasswd_file;
    140     const char* srp_tpasswd_conf_file;
    141205        /* A list of CA Certificates */
    142206    gnutls_x509_crt_t *ca_list;
     
    151215        /* Last Cache timestamp */
    152216    apr_time_t last_cache_check;
    153         /* GnuTLS uses Session Tickets */
    154     int tickets;
    155         /* Is mod_proxy enabled? */
    156     int proxy_enabled;
    157         /* A Plain HTTP request */
    158     int non_ssl_request;
    159217} mgs_srvconf_rec;
    160218
     
    171229        /* Connection record */
    172230    conn_rec* c;
     231        /* Is TLS enabled for this connection? */
     232    int enabled;
     233    /* Is this a proxy connection? */
     234    int is_proxy;
    173235        /* GnuTLS Session handle */
    174236    gnutls_session_t session;
     
    302364
    303365/**
     366 * Perform any reinitialization required in PKCS #11
     367 */
     368int mgs_pkcs11_reinit(server_rec * s);
     369
     370/**
    304371 * Convert a SSL Session ID into a Null Terminated Hex Encoded String
    305372 * @param id raw SSL Session ID
     
    321388
    322389/* Configuration Functions */
     390
     391/* Loads all files set in the configuration */
     392int mgs_load_files(apr_pool_t * p, server_rec * s);
    323393
    324394const char *mgs_set_srp_tpasswd_conf_file(cmd_parms * parms, void *dummy,
     
    355425                                   const char *arg);
    356426
     427const char *mgs_set_p11_module(cmd_parms * parms, void *dummy,
     428                               const char *arg);
     429
     430const char *mgs_set_pin(cmd_parms * parms, void *dummy,
     431                                   const char *arg);
     432
     433const char *mgs_set_srk_pin(cmd_parms * parms, void *dummy,
     434                                   const char *arg);
     435
    357436const char *mgs_set_keyring_file(cmd_parms * parms, void *dummy,
    358437                                   const char *arg);
     
    381460mgs_srvconf_rec* mgs_find_sni_server(gnutls_session_t session);
    382461
     462const char *mgs_store_cred_path(cmd_parms * parms,
     463                                void *dummy __attribute__((unused)),
     464                                const char *arg);
     465
    383466/* mod_gnutls Hooks. */
    384467
  • m4/apr_memcache.m4

    r2afbe2e r9b20a1e  
    4545    apr_memcache_includedir=$includedir/apr_memcache-0
    4646fi
     47
    4748CFLAGS="-I$apr_memcache_includedir $CFLAGS"
     49
    4850
    4951AC_CHECK_LIB(
     
    5860    ]
    5961)
     62
     63
     64dnl # if the apr_memcache was not found, try apr-util
     65if test -z "${APR_MEMCACHE_LIBS}"; then
     66    if test -n "$apr_memcache_includes"; then
     67        apr_memcache_includedir=$apr_memcache_includes
     68    elif test -n "$apr_memcache_prefix"; then
     69        apr_memcache_includedir=$apr_memcache_prefix/include/aprutil-1
     70    else
     71        apr_memcache_includedir=$includedir/aprutil-1
     72    fi
     73    AC_CHECK_LIB(
     74        aprutil-1,
     75        apr_memcache_create,
     76        [
     77            APR_MEMCACHE_LIBS="`apu-1-config --link-ld`"
     78            APR_MEMCACHE_CFLAGS="`apu-1-config --includes`"
     79        ]
     80    )
     81fi
     82
     83
    6084CFLAGS=$save_CFLAGS
    6185LDFLAGS=$save_LDFLAGS
  • src/gnutls_cache.c

    r2afbe2e r9b20a1e  
    33 *  Copyright 2008 Nikos Mavrogiannopoulos
    44 *  Copyright 2011 Dash Shendy
     5 *  Copyright 2015 Thomas Klute
    56 *
    67 *  Licensed under the Apache License, Version 2.0 (the "License");
     
    580581}
    581582
    582 int mgs_cache_child_init(apr_pool_t * p, server_rec * s,
    583         mgs_srvconf_rec * sc) {
     583#if HAVE_APR_MEMCACHE
     584int mgs_cache_child_init(apr_pool_t * p,
     585                         server_rec * s,
     586                         mgs_srvconf_rec * sc)
     587#else
     588int mgs_cache_child_init(apr_pool_t * p __attribute__((unused)),
     589                         server_rec * s __attribute__((unused)),
     590                         mgs_srvconf_rec * sc)
     591#endif
     592{
    584593    if (sc->cache_type == mgs_cache_dbm
    585594            || sc->cache_type == mgs_cache_gdbm) {
  • src/gnutls_config.c

    r2afbe2e r9b20a1e  
    33 *  Copyright 2008 Nikos Mavrogiannopoulos
    44 *  Copyright 2011 Dash Shendy
     5 *  Copyright 2015 Thomas Klute
    56 *
    67 *  Licensed under the Apache License, Version 2.0 (the "License");
     
    2021#include "mod_gnutls.h"
    2122#include "apr_lib.h"
     23#include <gnutls/abstract.h>
     24
     25#define INIT_CA_SIZE 128
    2226
    2327#ifdef APLOG_USE_MODULE
     
    2529#endif
    2630
     31static int pin_callback(void *user, int attempt __attribute__((unused)),
     32                        const char *token_url __attribute__((unused)),
     33                        const char *token_label, unsigned int flags,
     34                        char *pin, size_t pin_max)
     35{
     36    mgs_srvconf_rec *sc = user;
     37
     38    if (sc->pin == NULL || flags & GNUTLS_PIN_FINAL_TRY ||
     39        flags & GNUTLS_PIN_WRONG) {
     40        return -1;
     41    }
     42
     43    if (token_label && strcmp(token_label, "SRK") == 0) {
     44         snprintf(pin, pin_max, "%s", sc->srk_pin);
     45    } else {
     46         snprintf(pin, pin_max, "%s", sc->pin);
     47    }
     48    return 0;
     49}
     50
    2751static int load_datum_from_file(apr_pool_t * pool,
    28         const char *file, gnutls_datum_t * data) {
     52                                const char *file, gnutls_datum_t * data)
     53{
    2954    apr_file_t *fp;
    3055    apr_finfo_t finfo;
     
    3358
    3459    rv = apr_file_open(&fp, file, APR_READ | APR_BINARY,
    35             APR_OS_DEFAULT, pool);
     60                       APR_OS_DEFAULT, pool);
    3661    if (rv != APR_SUCCESS) {
    37         return rv;
     62        return rv;
    3863    }
    3964
     
    4166
    4267    if (rv != APR_SUCCESS) {
    43         return rv;
     68        return rv;
    4469    }
    4570
     
    4873
    4974    if (rv != APR_SUCCESS) {
    50         return rv;
     75        return rv;
    5176    }
    5277    apr_file_close(fp);
     
    5883}
    5984
     85/* 2048-bit group parameters from SRP specification */
     86const char static_dh_params[] = "-----BEGIN DH PARAMETERS-----\n"
     87        "MIIBBwKCAQCsa9tBMkqam/Fm3l4TiVgvr3K2ZRmH7gf8MZKUPbVgUKNzKcu0oJnt\n"
     88        "gZPgdXdnoT3VIxKrSwMxDc1/SKnaBP1Q6Ag5ae23Z7DPYJUXmhY6s2YaBfvV+qro\n"
     89        "KRipli8Lk7hV+XmT7Jde6qgNdArb9P90c1nQQdXDPqcdKB5EaxR3O8qXtDoj+4AW\n"
     90        "dr0gekNsZIHx0rkHhxdGGludMuaI+HdIVEUjtSSw1X1ep3onddLs+gMs+9v1L7N4\n"
     91        "YWAnkATleuavh05zA85TKZzMBBx7wwjYKlaY86jQw4JxrjX46dv7tpS1yAPYn3rk\n"
     92        "Nd4jbVJfVHWbZeNy/NaO8g+nER+eSv9zAgEC\n"
     93        "-----END DH PARAMETERS-----\n";
     94
     95int mgs_load_files(apr_pool_t * p, server_rec * s)
     96{
     97    apr_pool_t *spool;
     98    const char *file;
     99    gnutls_datum_t data;
     100    int ret;
     101    mgs_srvconf_rec *sc =
     102        (mgs_srvconf_rec *) ap_get_module_config(s->module_config,
     103                                                 &gnutls_module);
     104
     105    apr_pool_create(&spool, p);
     106
     107    sc->cert_pgp = apr_pcalloc(p, sizeof(sc->cert_pgp[0]));
     108    sc->cert_crt_pgp = apr_pcalloc(p, sizeof(sc->cert_crt_pgp[0]));
     109    sc->certs_x509_chain =
     110        apr_pcalloc(p, MAX_CHAIN_SIZE * sizeof(sc->certs_x509_chain[0]));
     111    sc->certs_x509_crt_chain =
     112        apr_pcalloc(p,
     113                    MAX_CHAIN_SIZE * sizeof(sc->certs_x509_crt_chain[0]));
     114
     115    ret = gnutls_certificate_allocate_credentials(&sc->certs);
     116    if (ret < 0) {
     117        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
     118                     "GnuTLS: Failed to initialize" ": (%d) %s", ret,
     119                     gnutls_strerror(ret));
     120        ret = -1;
     121        goto cleanup;
     122    }
     123
     124    ret = gnutls_anon_allocate_server_credentials(&sc->anon_creds);
     125    if (ret < 0) {
     126        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
     127                     "GnuTLS: Failed to initialize" ": (%d) %s", ret,
     128                     gnutls_strerror(ret));
     129        ret = -1;
     130        goto cleanup;
     131    }
     132
     133    /* Load SRP parameters */
     134#ifdef ENABLE_SRP
     135    ret = gnutls_srp_allocate_server_credentials(&sc->srp_creds);
     136    if (ret < 0) {
     137        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
     138                     "GnuTLS: Failed to initialize" ": (%d) %s", ret,
     139                     gnutls_strerror(ret));
     140        ret = -1;
     141        goto cleanup;
     142    }
     143
     144    if (sc->srp_tpasswd_conf_file != NULL && sc->srp_tpasswd_file != NULL) {
     145        ret = gnutls_srp_set_server_credentials_file
     146            (sc->srp_creds, sc->srp_tpasswd_file,
     147             sc->srp_tpasswd_conf_file);
     148
     149        if (ret < 0 && sc->enabled == GNUTLS_ENABLED_TRUE) {
     150            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0,
     151                         s,
     152                         "GnuTLS: Host '%s:%d' is missing a "
     153                         "SRP password or conf File!",
     154                         s->server_hostname, s->port);
     155            ret = -1;
     156            goto cleanup;
     157        }
     158    }
     159#endif
     160
     161    ret = gnutls_dh_params_init(&sc->dh_params);
     162    if (ret < 0) {
     163            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
     164                         "GnuTLS: Failed to initialize"
     165                         ": (%d) %s", ret, gnutls_strerror(ret));
     166            ret = -1;
     167            goto cleanup;
     168    }
     169
     170    /* Load DH parameters */
     171    if (sc->dh_file) {
     172        if (load_datum_from_file(spool, sc->dh_file, &data) != 0) {
     173            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
     174                         "GnuTLS: Error Reading " "DH params '%s'", sc->dh_file);
     175            ret = -1;
     176            goto cleanup;
     177        }
     178
     179        ret =
     180            gnutls_dh_params_import_pkcs3(sc->dh_params, &data,
     181                                          GNUTLS_X509_FMT_PEM);
     182        if (ret < 0) {
     183            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
     184                         "GnuTLS: Failed to Import "
     185                         "DH params '%s': (%d) %s", sc->dh_file, ret,
     186                         gnutls_strerror(ret));
     187            ret = -1;
     188            goto cleanup;
     189        }
     190    } else {
     191        gnutls_datum_t pdata = {
     192            (void *) static_dh_params,
     193            sizeof(static_dh_params)
     194        };
     195
     196        ret = gnutls_dh_params_import_pkcs3(sc->dh_params, &pdata, GNUTLS_X509_FMT_PEM);
     197        if (ret < 0) {
     198            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
     199                    "GnuTLS: Unable to generate or load DH Params: (%d) %s",
     200                    ret, gnutls_strerror(ret));
     201            ret = -1;
     202            goto cleanup;
     203        }
     204    }
     205
     206    if (sc->x509_cert_file != NULL) {
     207        unsigned int chain_num, i;
     208        unsigned format = GNUTLS_X509_FMT_PEM;
     209
     210        /* Load X.509 certificate */
     211        if (strncmp(sc->x509_cert_file, "pkcs11:", 7) == 0) {
     212            gnutls_pkcs11_obj_t obj;
     213
     214            file = sc->x509_cert_file;
     215
     216            ret = gnutls_pkcs11_obj_init(&obj);
     217            if (ret < 0) {
     218                ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
     219                             "GnuTLS: Error Initializing PKCS #11 object");
     220                ret = -1;
     221                goto cleanup;
     222            }
     223
     224            gnutls_pkcs11_obj_set_pin_function(obj, pin_callback, sc);
     225
     226            ret = gnutls_pkcs11_obj_import_url(obj, file, GNUTLS_PKCS11_OBJ_FLAG_LOGIN);
     227            if (ret < 0) {
     228                ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
     229                             "GnuTLS: Error Importing PKCS #11 object: '%s': %s",
     230                             file, gnutls_strerror(ret));
     231                ret = -1;
     232                goto cleanup;
     233            }
     234
     235            format = GNUTLS_X509_FMT_DER;
     236            ret = gnutls_pkcs11_obj_export2(obj, &data);
     237            if (ret < 0) {
     238                ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
     239                             "GnuTLS: Error Exporting a PKCS #11 object: '%s': %s",
     240                             file, gnutls_strerror(ret));
     241                ret = -1;
     242                goto cleanup;
     243            }
     244
     245            gnutls_pkcs11_obj_deinit(obj);
     246        } else {
     247            file = ap_server_root_relative(spool, sc->x509_cert_file);
     248
     249            ret = gnutls_load_file(file, &data);
     250            if (ret < 0) {
     251                ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
     252                             "GnuTLS: Error Reading Certificate '%s': %s",
     253                             file, gnutls_strerror(ret));
     254                ret = -1;
     255                goto cleanup;
     256            }
     257        }
     258
     259        ret =
     260            gnutls_x509_crt_list_import2(&sc->certs_x509_crt_chain,
     261                                        &chain_num, &data, format,
     262                                        GNUTLS_X509_CRT_LIST_FAIL_IF_UNSORTED);
     263        gnutls_free(data.data);
     264        sc->certs_x509_chain_num = chain_num;
     265
     266        if (ret < 0) {
     267            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
     268                         "GnuTLS: Failed to Import Certificate Chain '%s': (%d) %s",
     269                         file, ret, gnutls_strerror(ret));
     270            ret = -1;
     271            goto cleanup;
     272        }
     273
     274        for (i = 0; i < chain_num; i++) {
     275            ret =
     276                gnutls_pcert_import_x509(&sc->certs_x509_chain[i],
     277                                         sc->certs_x509_crt_chain[i], 0);
     278            if (ret < 0) {
     279                ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
     280                             "GnuTLS: Failed to Import pCertificate '%s': (%d) %s",
     281                             file, ret, gnutls_strerror(ret));
     282                ret = -1;
     283                goto cleanup;
     284            }
     285        }
     286        sc->certs_x509_chain_num = chain_num;
     287    }
     288
     289    if (sc->x509_key_file) {
     290        ret = gnutls_privkey_init(&sc->privkey_x509);
     291        if (ret < 0) {
     292            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
     293                         "GnuTLS: Failed to initialize: (%d) %s", ret,
     294                         gnutls_strerror(ret));
     295            ret = -1;
     296            goto cleanup;
     297        }
     298
     299        if (gnutls_url_is_supported(sc->x509_key_file) != 0) {
     300            file = sc->x509_key_file;
     301
     302            gnutls_privkey_set_pin_function(sc->privkey_x509, pin_callback,
     303                                            sc);
     304
     305            ret = gnutls_privkey_import_url(sc->privkey_x509, file, 0);
     306
     307            if (ret < 0) {
     308                ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
     309                             "GnuTLS: Failed to Import Private Key URL '%s': (%d) %s",
     310                             file, ret, gnutls_strerror(ret));
     311                ret = -1;
     312                goto cleanup;
     313            }
     314        } else {
     315            file = ap_server_root_relative(spool, sc->x509_key_file);
     316
     317            if (load_datum_from_file(spool, file, &data) != 0) {
     318                ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
     319                             "GnuTLS: Error Reading Private Key '%s'",
     320                             file);
     321                ret = -1;
     322                goto cleanup;
     323            }
     324
     325            ret =
     326                gnutls_privkey_import_x509_raw(sc->privkey_x509, &data,
     327                                               GNUTLS_X509_FMT_PEM, sc->pin,
     328                                               0);
     329
     330            if (ret < 0) {
     331                ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
     332                             "GnuTLS: Failed to Import Private Key '%s': (%d) %s",
     333                             file, ret, gnutls_strerror(ret));
     334                ret = -1;
     335                goto cleanup;
     336            }
     337        }
     338    }
     339
     340    /* Load the X.509 CA file */
     341    if (sc->x509_ca_file) {
     342        if (load_datum_from_file(spool, sc->x509_ca_file, &data) != 0) {
     343            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
     344                         "GnuTLS: Error Reading " "Client CA File '%s'",
     345                         sc->x509_ca_file);
     346            ret = -1;
     347            goto cleanup;
     348        }
     349
     350        ret = gnutls_x509_crt_list_import2(&sc->ca_list, &sc->ca_list_size,
     351                                         &data, GNUTLS_X509_FMT_PEM, 0);
     352        if (ret < 0) {
     353            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
     354                         "GnuTLS: Failed to load "
     355                         "Client CA File '%s': (%d) %s", sc->x509_ca_file,
     356                         ret, gnutls_strerror(ret));
     357            ret = -1;
     358            goto cleanup;
     359        }
     360    }
     361
     362    if (sc->pgp_cert_file) {
     363        if (load_datum_from_file(spool, sc->pgp_cert_file, &data) != 0) {
     364            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
     365                         "GnuTLS: Error Reading " "Certificate '%s'",
     366                         sc->pgp_cert_file);
     367            ret = -1;
     368            goto cleanup;
     369        }
     370
     371        ret = gnutls_openpgp_crt_init(&sc->cert_crt_pgp[0]);
     372        if (ret < 0) {
     373            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
     374                         "GnuTLS: Failed to Init "
     375                         "PGP Certificate: (%d) %s", ret,
     376                         gnutls_strerror(ret));
     377            ret = -1;
     378            goto cleanup;
     379        }
     380
     381        ret =
     382            gnutls_openpgp_crt_import(sc->cert_crt_pgp[0], &data,
     383                                      GNUTLS_OPENPGP_FMT_BASE64);
     384        if (ret < 0) {
     385            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
     386                         "GnuTLS: Failed to Import "
     387                         "PGP Certificate: (%d) %s", ret,
     388                         gnutls_strerror(ret));
     389            ret = -1;
     390            goto cleanup;
     391        }
     392
     393        ret =
     394            gnutls_pcert_import_openpgp(sc->cert_pgp, sc->cert_crt_pgp[0],
     395                                        0);
     396        if (ret < 0) {
     397            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
     398                         "GnuTLS: Failed to Import "
     399                         "PGP pCertificate: (%d) %s", ret,
     400                         gnutls_strerror(ret));
     401            ret = -1;
     402            goto cleanup;
     403        }
     404    }
     405
     406    /* Load the PGP key file */
     407    if (sc->pgp_key_file) {
     408        if (load_datum_from_file(spool, sc->pgp_key_file, &data) != 0) {
     409            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
     410                         "GnuTLS: Error Reading " "Private Key '%s'",
     411                         sc->pgp_key_file);
     412            ret = -1;
     413            goto cleanup;
     414        }
     415
     416        ret = gnutls_privkey_init(&sc->privkey_pgp);
     417        if (ret < 0) {
     418            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
     419                         "GnuTLS: Failed to initialize"
     420                         ": (%d) %s", ret, gnutls_strerror(ret));
     421            ret = -1;
     422            goto cleanup;
     423        }
     424
     425#if GNUTLS_VERSION_NUMBER < 0x030312
     426        /* GnuTLS versions before 3.3.12 contain a bug in
     427         * gnutls_privkey_import_openpgp_raw which frees data that is
     428         * accessed when the key is used, leading to segfault. Loading
     429         * the key into a gnutls_openpgp_privkey_t and then assigning
     430         * it to the gnutls_privkey_t works around the bug, hence this
     431         * chain of gnutls_openpgp_privkey_init,
     432         * gnutls_openpgp_privkey_import and
     433         * gnutls_privkey_import_openpgp. */
     434        ret = gnutls_openpgp_privkey_init(&sc->privkey_pgp_internal);
     435        if (ret != 0) {
     436            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
     437                         "GnuTLS: Failed to initialize "
     438                         "PGP Private Key '%s': (%d) %s",
     439                         sc->pgp_key_file, ret, gnutls_strerror(ret));
     440            ret = -1;
     441            goto cleanup;
     442        }
     443
     444        ret = gnutls_openpgp_privkey_import(sc->privkey_pgp_internal, &data,
     445                                            GNUTLS_OPENPGP_FMT_BASE64, NULL, 0);
     446        if (ret != 0) {
     447            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
     448                         "GnuTLS: Failed to Import "
     449                         "PGP Private Key '%s': (%d) %s",
     450                         sc->pgp_key_file, ret, gnutls_strerror(ret));
     451            ret = -1;
     452            goto cleanup;
     453        }
     454
     455        ret = gnutls_privkey_import_openpgp(sc->privkey_pgp,
     456                                            sc->privkey_pgp_internal, 0);
     457        if (ret != 0)
     458        {
     459            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
     460                         "GnuTLS: Failed to assign PGP Private Key '%s' "
     461                         "to gnutls_privkey_t structure: (%d) %s",
     462                         sc->pgp_key_file, ret, gnutls_strerror(ret));
     463            ret = -1;
     464            goto cleanup;
     465        }
     466#else
     467        ret = gnutls_privkey_import_openpgp_raw(sc->privkey_pgp, &data,
     468                                                GNUTLS_OPENPGP_FMT_BASE64,
     469                                                NULL, NULL);
     470        if (ret != 0)
     471        {
     472            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
     473                         "GnuTLS: Failed to Import "
     474                         "PGP Private Key '%s': (%d) %s",
     475                         sc->pgp_key_file, ret, gnutls_strerror(ret));
     476            ret = -1;
     477            goto cleanup;
     478        }
     479#endif
     480    }
     481
     482    /* Load the keyring file */
     483    if (sc->pgp_ring_file) {
     484        if (load_datum_from_file(spool, sc->pgp_ring_file, &data) != 0) {
     485            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
     486                         "GnuTLS: Error Reading " "Keyring File '%s'",
     487                         sc->pgp_ring_file);
     488            ret = -1;
     489            goto cleanup;
     490        }
     491
     492        ret = gnutls_openpgp_keyring_init(&sc->pgp_list);
     493        if (ret < 0) {
     494            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
     495                         "GnuTLS: Failed to initialize"
     496                         "keyring: (%d) %s", ret, gnutls_strerror(ret));
     497            ret = -1;
     498            goto cleanup;
     499        }
     500
     501        ret = gnutls_openpgp_keyring_import(sc->pgp_list, &data,
     502                                           GNUTLS_OPENPGP_FMT_BASE64);
     503        if (ret < 0) {
     504            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
     505                         "GnuTLS: Failed to load "
     506                         "Keyring File '%s': (%d) %s", sc->pgp_ring_file,
     507                         ret, gnutls_strerror(ret));
     508            ret = -1;
     509            goto cleanup;
     510        }
     511    }
     512
     513    if (sc->priorities_str) {
     514        const char *err;
     515        ret = gnutls_priority_init(&sc->priorities, sc->priorities_str, &err);
     516
     517        if (ret < 0) {
     518            if (ret == GNUTLS_E_INVALID_REQUEST) {
     519                ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
     520                             "GnuTLS: Syntax error parsing priorities string at: %s",
     521                             err);
     522            } else {
     523                ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
     524                             "GnuTLS: error parsing priorities string");
     525
     526            }
     527            ret = -1;
     528            goto cleanup;
     529        }
     530    }
     531
     532    ret = 0;
     533  cleanup:
     534    apr_pool_destroy(spool);
     535
     536    return ret;
     537}
     538
     539int mgs_pkcs11_reinit(server_rec * base_server)
     540{
     541    int ret;
     542    server_rec *s;
     543    mgs_srvconf_rec *sc;
     544
     545    gnutls_pkcs11_reinit();
     546
     547    for (s = base_server; s; s = s->next) {
     548        sc = (mgs_srvconf_rec *) ap_get_module_config(s->module_config, &gnutls_module);
     549
     550            /* gnutls caches the session in a private key, so we need to open
     551             * a new one */
     552            if (sc->x509_key_file && gnutls_url_is_supported(sc->x509_key_file) != 0) {
     553                gnutls_privkey_deinit(sc->privkey_x509);
     554
     555                ret = gnutls_privkey_init(&sc->privkey_x509);
     556                if (ret < 0) {
     557                    ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s,
     558                                 "GnuTLS: Failed to initialize: (%d) %s", ret,
     559                                 gnutls_strerror(ret));
     560                    goto fail;
     561                }
     562
     563                gnutls_privkey_set_pin_function(sc->privkey_x509, pin_callback, sc);
     564
     565                ret = gnutls_privkey_import_url(sc->privkey_x509, sc->x509_key_file, 0);
     566                if (ret < 0) {
     567                    ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s,
     568                             "GnuTLS: Failed to Re-Import Private Key URL '%s': (%d) %s",
     569                             sc->x509_key_file, ret, gnutls_strerror(ret));
     570                    goto fail;
     571                }
     572            }
     573    }
     574
     575    return 0;
     576
     577 fail:
     578    gnutls_privkey_deinit(sc->privkey_x509);
     579    return -1;
     580}
     581
    60582const char *mgs_set_dh_file(cmd_parms * parms, void *dummy __attribute__((unused)),
    61583        const char *arg) {
    62     int ret;
    63     gnutls_datum_t data;
    64     const char *file;
    65     apr_pool_t *spool;
    66     mgs_srvconf_rec *sc =
    67             (mgs_srvconf_rec *) ap_get_module_config(parms->server->
    68             module_config,
    69             &gnutls_module);
    70 
    71     apr_pool_create(&spool, parms->pool);
    72 
    73     file = ap_server_root_relative(spool, arg);
    74 
    75     if (load_datum_from_file(spool, file, &data) != 0) {
    76         return apr_psprintf(parms->pool, "GnuTLS: Error Reading "
    77                 "DH params '%s'", file);
    78     }
    79 
    80     ret = gnutls_dh_params_init(&sc->dh_params);
    81     if (ret < 0) {
    82         return apr_psprintf(parms->pool,
    83                 "GnuTLS: Failed to initialize"
    84                 ": (%d) %s", ret,
    85                 gnutls_strerror(ret));
    86     }
    87 
    88     ret =
    89             gnutls_dh_params_import_pkcs3(sc->dh_params, &data,
    90             GNUTLS_X509_FMT_PEM);
    91     if (ret < 0) {
    92         return apr_psprintf(parms->pool,
    93                 "GnuTLS: Failed to Import "
    94                 "DH params '%s': (%d) %s", file, ret,
    95                 gnutls_strerror(ret));
    96     }
    97 
    98     apr_pool_destroy(spool);
     584    mgs_srvconf_rec *sc =
     585        (mgs_srvconf_rec *) ap_get_module_config(parms->server->
     586                                                 module_config,
     587                                                 &gnutls_module);
     588
     589    sc->dh_file = ap_server_root_relative(parms->pool, arg);
    99590
    100591    return NULL;
     
    103594const char *mgs_set_cert_file(cmd_parms * parms, void *dummy __attribute__((unused)), const char *arg) {
    104595
    105     int ret;
    106     gnutls_datum_t data;
    107     const char *file;
    108     apr_pool_t *spool;
    109 
    110     mgs_srvconf_rec *sc = (mgs_srvconf_rec *) ap_get_module_config(parms->server->module_config, &gnutls_module);
    111     apr_pool_create(&spool, parms->pool);
    112 
    113     file = ap_server_root_relative(spool, arg);
    114 
    115     if (load_datum_from_file(spool, file, &data) != 0) {
    116                 apr_pool_destroy(spool);
    117         return apr_psprintf(parms->pool, "GnuTLS: Error Reading Certificate '%s'", file);
    118     }
    119 
    120     sc->certs_x509_chain_num = MAX_CHAIN_SIZE;
    121     ret = gnutls_x509_crt_list_import(sc->certs_x509_chain, &sc->certs_x509_chain_num, &data, GNUTLS_X509_FMT_PEM, 0);
    122     if (ret < 0) {
    123                 apr_pool_destroy(spool);
    124         return apr_psprintf(parms->pool, "GnuTLS: Failed to Import Certificate '%s': (%d) %s", file, ret, gnutls_strerror(ret));
    125     }
    126 
    127         apr_pool_destroy(spool);
     596    mgs_srvconf_rec *sc =
     597        (mgs_srvconf_rec *) ap_get_module_config(parms->
     598                                                 server->module_config,
     599                                                 &gnutls_module);
     600
     601    sc->x509_cert_file = apr_pstrdup(parms->pool, arg);
     602
    128603    return NULL;
    129604
     
    132607const char *mgs_set_key_file(cmd_parms * parms, void *dummy __attribute__((unused)), const char *arg) {
    133608
    134     int ret;
    135     gnutls_datum_t data;
    136     const char *file;
    137     apr_pool_t *spool;
    138     const char *out;
    139 
    140         mgs_srvconf_rec *sc = (mgs_srvconf_rec *) ap_get_module_config(parms->server->module_config, &gnutls_module);
    141 
    142         apr_pool_create(&spool, parms->pool);
    143 
    144     file = ap_server_root_relative(spool, arg);
    145 
    146     if (load_datum_from_file(spool, file, &data) != 0) {
    147         out = apr_psprintf(parms->pool, "GnuTLS: Error Reading Private Key '%s'", file);
    148                 apr_pool_destroy(spool);
    149         return out;
    150     }
    151 
    152     ret = gnutls_x509_privkey_init(&sc->privkey_x509);
    153 
    154     if (ret < 0) {
    155                 apr_pool_destroy(spool);
    156         return apr_psprintf(parms->pool, "GnuTLS: Failed to initialize: (%d) %s", ret, gnutls_strerror(ret));
    157     }
    158 
    159     ret = gnutls_x509_privkey_import(sc->privkey_x509, &data, GNUTLS_X509_FMT_PEM);
    160 
    161     if (ret < 0) {
    162         ret = gnutls_x509_privkey_import_pkcs8(sc->privkey_x509, &data, GNUTLS_X509_FMT_PEM, NULL, GNUTLS_PKCS_PLAIN);
    163         }
    164 
    165     if (ret < 0) {
    166         out = apr_psprintf(parms->pool, "GnuTLS: Failed to Import Private Key '%s': (%d) %s", file, ret, gnutls_strerror(ret));
    167                 apr_pool_destroy(spool);
    168         return out;
    169     }
    170 
    171     apr_pool_destroy(spool);
     609    mgs_srvconf_rec *sc =
     610        (mgs_srvconf_rec *) ap_get_module_config(parms->
     611                                                 server->module_config,
     612                                                 &gnutls_module);
     613
     614    sc->x509_key_file = apr_pstrdup(parms->pool, arg);
    172615
    173616    return NULL;
     
    175618
    176619const char *mgs_set_pgpcert_file(cmd_parms * parms, void *dummy __attribute__((unused)),
    177         const char *arg) {
    178     int ret;
    179     gnutls_datum_t data;
    180     const char *file;
    181     apr_pool_t *spool;
    182     mgs_srvconf_rec *sc =
    183             (mgs_srvconf_rec *) ap_get_module_config(parms->server->
    184             module_config,
    185             &gnutls_module);
    186     apr_pool_create(&spool, parms->pool);
    187 
    188     file = ap_server_root_relative(spool, arg);
    189 
    190     if (load_datum_from_file(spool, file, &data) != 0) {
    191         return apr_psprintf(parms->pool, "GnuTLS: Error Reading "
    192                 "Certificate '%s'", file);
    193     }
    194 
    195     ret = gnutls_openpgp_crt_init(&sc->cert_pgp);
    196     if (ret < 0) {
    197         return apr_psprintf(parms->pool, "GnuTLS: Failed to Init "
    198                 "PGP Certificate: (%d) %s", ret,
    199                 gnutls_strerror(ret));
    200     }
    201 
    202     ret =
    203             gnutls_openpgp_crt_import(sc->cert_pgp, &data,
    204             GNUTLS_OPENPGP_FMT_BASE64);
    205     if (ret < 0) {
    206         return apr_psprintf(parms->pool,
    207                 "GnuTLS: Failed to Import "
    208                 "PGP Certificate '%s': (%d) %s", file,
    209                 ret, gnutls_strerror(ret));
    210     }
    211 
    212     apr_pool_destroy(spool);
     620        const char *arg)
     621{
     622    mgs_srvconf_rec *sc =
     623        (mgs_srvconf_rec *) ap_get_module_config(parms->server->
     624                                                 module_config,
     625                                                 &gnutls_module);
     626
     627    sc->pgp_cert_file = ap_server_root_relative(parms->pool, arg);
     628
    213629    return NULL;
    214630}
     
    216632const char *mgs_set_pgpkey_file(cmd_parms * parms, void *dummy __attribute__((unused)),
    217633        const char *arg) {
    218     int ret;
    219     gnutls_datum_t data;
    220     const char *file;
    221     apr_pool_t *spool;
    222     mgs_srvconf_rec *sc =
    223             (mgs_srvconf_rec *) ap_get_module_config(parms->server->
    224             module_config,
    225             &gnutls_module);
    226     apr_pool_create(&spool, parms->pool);
    227 
    228     file = ap_server_root_relative(spool, arg);
    229 
    230     if (load_datum_from_file(spool, file, &data) != 0) {
    231         return apr_psprintf(parms->pool, "GnuTLS: Error Reading "
    232                 "Private Key '%s'", file);
    233     }
    234 
    235     ret = gnutls_openpgp_privkey_init(&sc->privkey_pgp);
    236     if (ret < 0) {
    237         return apr_psprintf(parms->pool,
    238                 "GnuTLS: Failed to initialize"
    239                 ": (%d) %s", ret,
    240                 gnutls_strerror(ret));
    241     }
    242 
    243     ret =
    244             gnutls_openpgp_privkey_import(sc->privkey_pgp, &data,
    245             GNUTLS_OPENPGP_FMT_BASE64, NULL,
    246             0);
    247     if (ret != 0) {
    248         return apr_psprintf(parms->pool,
    249                 "GnuTLS: Failed to Import "
    250                 "PGP Private Key '%s': (%d) %s", file,
    251                 ret, gnutls_strerror(ret));
    252     }
    253     apr_pool_destroy(spool);
     634    mgs_srvconf_rec *sc =
     635        (mgs_srvconf_rec *) ap_get_module_config(parms->server->
     636                                                 module_config,
     637                                                 &gnutls_module);
     638
     639    sc->pgp_key_file = ap_server_root_relative(parms->pool, arg);
     640
    254641    return NULL;
    255642}
     
    258645        const char *arg) {
    259646    mgs_srvconf_rec *sc =
    260             (mgs_srvconf_rec *) ap_get_module_config(parms->server->
    261             module_config,
    262             &gnutls_module);
     647        (mgs_srvconf_rec *) ap_get_module_config(parms->server->
     648                                                module_config,
     649                                                &gnutls_module);
    263650
    264651    sc->tickets = 0;
    265652    if (strcasecmp("on", arg) == 0) {
    266         sc->tickets = 1;
     653        sc->tickets = 1;
    267654    }
    268655
     
    276663        const char *arg) {
    277664    mgs_srvconf_rec *sc =
    278             (mgs_srvconf_rec *) ap_get_module_config(parms->server->
    279             module_config,
    280             &gnutls_module);
     665        (mgs_srvconf_rec *) ap_get_module_config(parms->server->
     666                                                module_config,
     667                                                &gnutls_module);
    281668
    282669    sc->srp_tpasswd_file = ap_server_root_relative(parms->pool, arg);
     
    288675        const char *arg) {
    289676    mgs_srvconf_rec *sc =
    290             (mgs_srvconf_rec *) ap_get_module_config(parms->server->
    291             module_config,
    292             &gnutls_module);
    293 
    294     sc->srp_tpasswd_conf_file =
    295             ap_server_root_relative(parms->pool, arg);
     677        (mgs_srvconf_rec *) ap_get_module_config(parms->server->
     678                                                 module_config,
     679                                                 &gnutls_module);
     680
     681    sc->srp_tpasswd_conf_file = ap_server_root_relative(parms->pool, arg);
    296682
    297683    return NULL;
     
    304690    const char *err;
    305691    mgs_srvconf_rec *sc =
    306             ap_get_module_config(parms->server->module_config,
    307             &gnutls_module);
     692        ap_get_module_config(parms->server->module_config,
     693                             &gnutls_module);
    308694    if ((err = ap_check_cmd_context(parms, GLOBAL_ONLY))) {
    309         return err;
     695        return err;
    310696    }
    311697
    312698    if (strcasecmp("none", type) == 0) {
    313         sc->cache_type = mgs_cache_none;
    314         sc->cache_config = NULL;
    315         return NULL;
     699        sc->cache_type = mgs_cache_none;
     700        sc->cache_config = NULL;
     701        return NULL;
    316702    } else if (strcasecmp("dbm", type) == 0) {
    317         sc->cache_type = mgs_cache_dbm;
     703        sc->cache_type = mgs_cache_dbm;
    318704    } else if (strcasecmp("gdbm", type) == 0) {
    319         sc->cache_type = mgs_cache_gdbm;
     705        sc->cache_type = mgs_cache_gdbm;
    320706    }
    321707#if HAVE_APR_MEMCACHE
    322708    else if (strcasecmp("memcache", type) == 0) {
    323         sc->cache_type = mgs_cache_memcache;
     709        sc->cache_type = mgs_cache_memcache;
    324710    }
    325711#endif
    326712    else {
    327         return "Invalid Type for GnuTLSCache!";
     713        return "Invalid Type for GnuTLSCache!";
    328714    }
    329715
    330716    if (arg == NULL)
    331         return "Invalid argument 2 for GnuTLSCache!";
     717        return "Invalid argument 2 for GnuTLSCache!";
    332718
    333719    if (sc->cache_type == mgs_cache_dbm
    334             || sc->cache_type == mgs_cache_gdbm) {
    335         sc->cache_config =
    336                 ap_server_root_relative(parms->pool, arg);
     720        || sc->cache_type == mgs_cache_gdbm) {
     721        sc->cache_config = ap_server_root_relative(parms->pool, arg);
    337722    } else {
    338         sc->cache_config = apr_pstrdup(parms->pool, arg);
     723        sc->cache_config = apr_pstrdup(parms->pool, arg);
    339724    }
    340725
     
    347732    const char *err;
    348733    mgs_srvconf_rec *sc =
    349             (mgs_srvconf_rec *) ap_get_module_config(parms->server->
    350             module_config,
    351             &gnutls_module);
     734        (mgs_srvconf_rec *) ap_get_module_config(parms->server->
     735                                                module_config,
     736                                                &gnutls_module);
    352737
    353738    if ((err = ap_check_cmd_context(parms, GLOBAL_ONLY))) {
    354         return err;
     739        return err;
    355740    }
    356741
     
    358743
    359744    if (argint < 0) {
    360         return "GnuTLSCacheTimeout: Invalid argument";
     745        return "GnuTLSCacheTimeout: Invalid argument";
    361746    } else if (argint == 0) {
    362         sc->cache_timeout = 0;
     747        sc->cache_timeout = 0;
    363748    } else {
    364         sc->cache_timeout = apr_time_from_sec(argint);
     749        sc->cache_timeout = apr_time_from_sec(argint);
    365750    }
    366751
     
    373758
    374759    if (strcasecmp("cartel", arg) == 0) {
    375         sc->client_verify_method = mgs_cvm_cartel;
     760        sc->client_verify_method = mgs_cvm_cartel;
    376761    } else if (strcasecmp("msva", arg) == 0) {
    377762#ifdef ENABLE_MSVA
    378         sc->client_verify_method = mgs_cvm_msva;
     763        sc->client_verify_method = mgs_cvm_msva;
    379764#else
    380         return "GnuTLSClientVerifyMethod: msva is not supported";
     765        return "GnuTLSClientVerifyMethod: msva is not supported";
    381766#endif
    382767    } else {
    383         return "GnuTLSClientVerifyMethod: Invalid argument";
     768        return "GnuTLSClientVerifyMethod: Invalid argument";
    384769    }
    385770
     
    393778
    394779    if (strcasecmp("none", arg) == 0 || strcasecmp("ignore", arg) == 0) {
    395         mode = GNUTLS_CERT_IGNORE;
     780        mode = GNUTLS_CERT_IGNORE;
    396781    } else if (strcasecmp("optional", arg) == 0
    397             || strcasecmp("request", arg) == 0) {
    398         mode = GNUTLS_CERT_REQUEST;
     782               || strcasecmp("request", arg) == 0) {
     783        mode = GNUTLS_CERT_REQUEST;
    399784    } else if (strcasecmp("require", arg) == 0) {
    400         mode = GNUTLS_CERT_REQUIRE;
     785        mode = GNUTLS_CERT_REQUIRE;
    401786    } else {
    402         return "GnuTLSClientVerify: Invalid argument";
     787        return "GnuTLSClientVerify: Invalid argument";
    403788    }
    404789
     
    408793        dc->client_verify_mode = mode;
    409794    } else {
    410         mgs_srvconf_rec *sc =
    411                 (mgs_srvconf_rec *)
    412                 ap_get_module_config(parms->server->module_config,
    413                 &gnutls_module);
    414         sc->client_verify_mode = mode;
    415     }
    416 
    417     return NULL;
    418 }
    419 
    420 #define INIT_CA_SIZE 128
     795        mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
     796            ap_get_module_config(parms->server->module_config,
     797                                 &gnutls_module);
     798        sc->client_verify_mode = mode;
     799    }
     800
     801    return NULL;
     802}
    421803
    422804const char *mgs_set_client_ca_file(cmd_parms * parms, void *dummy __attribute__((unused)),
    423805        const char *arg) {
    424     int rv;
    425     const char *file;
    426     apr_pool_t *spool;
    427     gnutls_datum_t data;
    428 
    429     mgs_srvconf_rec *sc =
    430             (mgs_srvconf_rec *) ap_get_module_config(parms->server->
    431             module_config,
    432             &gnutls_module);
    433     apr_pool_create(&spool, parms->pool);
    434 
    435     file = ap_server_root_relative(spool, arg);
    436 
    437     if (load_datum_from_file(spool, file, &data) != 0) {
    438         return apr_psprintf(parms->pool, "GnuTLS: Error Reading "
    439                 "Client CA File '%s'", file);
    440     }
    441 
    442     sc->ca_list_size = INIT_CA_SIZE;
    443     sc->ca_list = malloc(sc->ca_list_size * sizeof (*sc->ca_list));
    444     if (sc->ca_list == NULL) {
    445         return apr_psprintf(parms->pool,
    446                 "mod_gnutls: Memory allocation error");
    447     }
    448 
    449     rv = gnutls_x509_crt_list_import(sc->ca_list, &sc->ca_list_size,
    450             &data, GNUTLS_X509_FMT_PEM,
    451             GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED);
    452     if (rv < 0 && rv != GNUTLS_E_SHORT_MEMORY_BUFFER) {
    453         return apr_psprintf(parms->pool, "GnuTLS: Failed to load "
    454                 "Client CA File '%s': (%d) %s", file,
    455                 rv, gnutls_strerror(rv));
    456     }
    457 
    458     if (INIT_CA_SIZE < sc->ca_list_size) {
    459         sc->ca_list =
    460                 realloc(sc->ca_list,
    461                 sc->ca_list_size * sizeof (*sc->ca_list));
    462         if (sc->ca_list == NULL) {
    463             return apr_psprintf(parms->pool,
    464                     "mod_gnutls: Memory allocation error");
    465         }
    466 
    467         /* re-read */
    468         rv = gnutls_x509_crt_list_import(sc->ca_list,
    469                 &sc->ca_list_size, &data,
    470                 GNUTLS_X509_FMT_PEM, 0);
    471 
    472         if (rv < 0) {
    473             return apr_psprintf(parms->pool,
    474                     "GnuTLS: Failed to load "
    475                     "Client CA File '%s': (%d) %s",
    476                     file, rv, gnutls_strerror(rv));
    477         }
    478     }
    479 
    480     apr_pool_destroy(spool);
     806    mgs_srvconf_rec *sc =
     807        (mgs_srvconf_rec *) ap_get_module_config(parms->server->
     808                                                 module_config,
     809                                                 &gnutls_module);
     810
     811    sc->x509_ca_file = ap_server_root_relative(parms->pool, arg);
     812
    481813    return NULL;
    482814}
     
    484816const char *mgs_set_keyring_file(cmd_parms * parms, void *dummy __attribute__((unused)),
    485817        const char *arg) {
    486     int rv;
    487     const char *file;
    488     apr_pool_t *spool;
    489     gnutls_datum_t data;
    490 
    491     mgs_srvconf_rec *sc =
    492             (mgs_srvconf_rec *) ap_get_module_config(parms->server->
    493             module_config,
    494             &gnutls_module);
    495     apr_pool_create(&spool, parms->pool);
    496 
    497     file = ap_server_root_relative(spool, arg);
    498 
    499     if (load_datum_from_file(spool, file, &data) != 0) {
    500         return apr_psprintf(parms->pool, "GnuTLS: Error Reading "
    501                 "Keyring File '%s'", file);
    502     }
    503 
    504     rv = gnutls_openpgp_keyring_init(&sc->pgp_list);
    505     if (rv < 0) {
    506         return apr_psprintf(parms->pool,
    507                 "GnuTLS: Failed to initialize"
    508                 "keyring: (%d) %s", rv,
    509                 gnutls_strerror(rv));
    510     }
    511 
    512     rv = gnutls_openpgp_keyring_import(sc->pgp_list, &data,
    513             GNUTLS_OPENPGP_FMT_BASE64);
    514     if (rv < 0) {
    515         return apr_psprintf(parms->pool, "GnuTLS: Failed to load "
    516                 "Keyring File '%s': (%d) %s", file, rv,
    517                 gnutls_strerror(rv));
    518     }
    519 
    520     apr_pool_destroy(spool);
     818    mgs_srvconf_rec *sc =
     819        (mgs_srvconf_rec *) ap_get_module_config(parms->server->
     820                                                 module_config,
     821                                                 &gnutls_module);
     822
     823    sc->pgp_ring_file = ap_server_root_relative(parms->pool, arg);
     824
    521825    return NULL;
    522826}
     
    525829        const char *arg) {
    526830
    527     mgs_srvconf_rec *sc =(mgs_srvconf_rec *)
    528             ap_get_module_config(parms->server->module_config, &gnutls_module);
     831    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
     832        ap_get_module_config(parms->server->module_config, &gnutls_module);
    529833
    530834    if (!strcasecmp(arg, "On")) {
    531         sc->proxy_enabled = GNUTLS_ENABLED_TRUE;
     835        sc->proxy_enabled = GNUTLS_ENABLED_TRUE;
    532836    } else if (!strcasecmp(arg, "Off")) {
    533         sc->proxy_enabled = GNUTLS_ENABLED_FALSE;
     837        sc->proxy_enabled = GNUTLS_ENABLED_FALSE;
    534838    } else {
    535         return "SSLProxyEngine must be set to 'On' or 'Off'";
     839        return "GnuTLSProxyEngine must be set to 'On' or 'Off'";
    536840    }
    537841
     
    542846        const char *arg) {
    543847    mgs_srvconf_rec *sc =
    544             (mgs_srvconf_rec *) ap_get_module_config(parms->server->
    545             module_config,
    546             &gnutls_module);
     848        (mgs_srvconf_rec *) ap_get_module_config(parms->server->
     849                                                module_config,
     850                                                &gnutls_module);
    547851    if (!strcasecmp(arg, "On")) {
    548         sc->enabled = GNUTLS_ENABLED_TRUE;
     852        sc->enabled = GNUTLS_ENABLED_TRUE;
    549853    } else if (!strcasecmp(arg, "Off")) {
    550         sc->enabled = GNUTLS_ENABLED_FALSE;
     854        sc->enabled = GNUTLS_ENABLED_FALSE;
    551855    } else {
    552         return "GnuTLSEnable must be set to 'On' or 'Off'";
     856        return "GnuTLSEnable must be set to 'On' or 'Off'";
    553857    }
    554858
     
    559863    mgs_srvconf_rec *sc = (mgs_srvconf_rec *) ap_get_module_config(parms->server->module_config, &gnutls_module);
    560864    if (!strcasecmp(arg, "On")) {
    561         sc->export_certificates_size = 16 * 1024;
     865        sc->export_certificates_size = 16 * 1024;
    562866    } else if (!strcasecmp(arg, "Off")) {
    563         sc->export_certificates_size = 0;
     867        sc->export_certificates_size = 0;
    564868    } else {
    565         char* endptr;
    566         sc->export_certificates_size = strtol(arg, &endptr, 10);
    567         while (apr_isspace(*endptr)) endptr++;
    568         if (*endptr == '\0' || *endptr == 'b' || *endptr == 'B') {
    569             ;
    570         } else if (*endptr == 'k' || *endptr == 'K') {
    571             sc->export_certificates_size *= 1024;
    572         } else {
    573             return "GnuTLSExportCertificates must be set to a size (in bytes) or 'On' or 'Off'";
    574         }
    575     }
    576 
    577     return NULL;
    578 }
    579 
    580 const char *mgs_set_priorities(cmd_parms * parms, void *dummy __attribute__((unused)), const char *arg) {
    581 
    582         int ret;
    583     const char *err;
    584 
     869        char *endptr;
     870        sc->export_certificates_size = strtol(arg, &endptr, 10);
     871        while (apr_isspace(*endptr))
     872            endptr++;
     873        if (*endptr == '\0' || *endptr == 'b' || *endptr == 'B') {
     874            ;
     875        } else if (*endptr == 'k' || *endptr == 'K') {
     876            sc->export_certificates_size *= 1024;
     877        } else {
     878            return
     879                "GnuTLSExportCertificates must be set to a size (in bytes) or 'On' or 'Off'";
     880        }
     881    }
     882
     883    return NULL;
     884}
     885
     886
     887
     888/*
     889 * Store GnuTLS priority strings. Used for GnuTLSPriorities and
     890 * GnuTLSProxyPriorities.
     891 */
     892const char *mgs_set_priorities(cmd_parms * parms,
     893                               void *dummy __attribute__((unused)),
     894                               const char *arg)
     895{
    585896    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
    586                                                   ap_get_module_config(parms->server->module_config, &gnutls_module);
    587 
    588     ret = gnutls_priority_init(&sc->priorities, arg, &err);
    589 
    590     if (ret < 0) {
    591         if (ret == GNUTLS_E_INVALID_REQUEST) {
    592             return apr_psprintf(parms->pool,
    593                                                                 "GnuTLS: Syntax error parsing priorities string at: %s", err);
    594                 }
    595         return "Error setting priorities";
    596     }
    597 
    598     return NULL;
    599 }
    600 
    601 static mgs_srvconf_rec *_mgs_config_server_create(apr_pool_t * p, char** err) {
    602     mgs_srvconf_rec *sc = apr_pcalloc(p, sizeof (*sc));
    603     int ret;
     897        ap_get_module_config(parms->server->module_config, &gnutls_module);
     898
     899    if (!strcasecmp(parms->directive->directive, "GnuTLSPriorities"))
     900        sc->priorities_str = apr_pstrdup(parms->pool, arg);
     901    else if (!strcasecmp(parms->directive->directive, "GnuTLSProxyPriorities"))
     902        sc->proxy_priorities_str = apr_pstrdup(parms->pool, arg);
     903    else
     904        /* Can't happen unless there's a serious bug in mod_gnutls or Apache */
     905        return apr_psprintf(parms->pool,
     906                            "mod_gnutls: %s called for invalid option '%s'",
     907                            __func__, parms->directive->directive);
     908
     909    return NULL;
     910}
     911
     912
     913
     914const char *mgs_set_pin(cmd_parms * parms, void *dummy __attribute__((unused)),
     915                        const char *arg)
     916{
     917
     918    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
     919        ap_get_module_config(parms->server->module_config, &gnutls_module);
     920
     921    sc->pin = apr_pstrdup(parms->pool, arg);
     922
     923    return NULL;
     924}
     925
     926const char *mgs_set_srk_pin(cmd_parms * parms,
     927                            void *dummy __attribute__((unused)),
     928                            const char *arg)
     929{
     930
     931    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
     932        ap_get_module_config(parms->server->module_config, &gnutls_module);
     933
     934    sc->srk_pin = apr_pstrdup(parms->pool, arg);
     935
     936    return NULL;
     937}
     938
     939
     940
     941static mgs_srvconf_rec *_mgs_config_server_create(apr_pool_t * p,
     942                                                  char **err __attribute__((unused)))
     943{
     944    mgs_srvconf_rec *sc = apr_pcalloc(p, sizeof(*sc));
    604945
    605946    sc->enabled = GNUTLS_ENABLED_UNSET;
    606947
    607     ret = gnutls_certificate_allocate_credentials(&sc->certs);
    608     if (ret < 0) {
    609         *err = apr_psprintf(p, "GnuTLS: Failed to initialize"
    610                             ": (%d) %s", ret,
    611                             gnutls_strerror(ret));
    612         return NULL;
    613     }
    614 
    615     ret = gnutls_anon_allocate_server_credentials(&sc->anon_creds);
    616     if (ret < 0) {
    617         *err = apr_psprintf(p, "GnuTLS: Failed to initialize"
    618                             ": (%d) %s", ret,
    619                             gnutls_strerror(ret));
    620         return NULL;
    621     }
    622 #ifdef ENABLE_SRP
    623     ret = gnutls_srp_allocate_server_credentials(&sc->srp_creds);
    624     if (ret < 0) {
    625         *err =  apr_psprintf(p, "GnuTLS: Failed to initialize"
    626                              ": (%d) %s", ret,
    627                              gnutls_strerror(ret));
    628         return NULL;
    629     }
    630 
    631     sc->srp_tpasswd_conf_file = NULL;
    632     sc->srp_tpasswd_file = NULL;
    633 #endif
    634 
    635948    sc->privkey_x509 = NULL;
    636         /* Initialize all Certificate Chains */
    637     /* FIXME: how do we indicate that this is unset for a merge? (that
    638      * is, how can a subordinate server override the chain by setting
    639      * an empty one?  what would that even look like in the
    640      * configuration?) */
    641         sc->certs_x509_chain = malloc(MAX_CHAIN_SIZE * sizeof (*sc->certs_x509_chain));
     949    sc->privkey_pgp = NULL;
    642950    sc->certs_x509_chain_num = 0;
    643     sc->cache_timeout = -1; /* -1 means "unset" */
     951    sc->p11_module = NULL;
     952    sc->pin = NULL;
     953    sc->priorities_str = NULL;
     954    sc->cache_timeout = -1;     /* -1 means "unset" */
    644955    sc->cache_type = mgs_cache_unset;
    645956    sc->cache_config = NULL;
     
    651962    sc->client_verify_method = mgs_cvm_unset;
    652963
     964    sc->proxy_x509_key_file = NULL;
     965    sc->proxy_x509_cert_file = NULL;
     966    sc->proxy_x509_ca_file = NULL;
     967    sc->proxy_x509_crl_file = NULL;
     968    sc->proxy_priorities_str = NULL;
     969    sc->proxy_priorities = NULL;
     970
    653971/* this relies on GnuTLS never changing the gnutls_certificate_request_t enum to define -1 */
    654972    sc->client_verify_mode = -1;
     
    661979    char *err = NULL;
    662980    mgs_srvconf_rec *sc = _mgs_config_server_create(p, &err);
    663     if (sc) return sc; else return err;
     981    if (sc)
     982        return sc;
     983    else
     984        return err;
    664985}
    665986
     
    667988#define gnutls_srvconf_assign(t) sc->t = add->t
    668989
    669 void *mgs_config_server_merge(apr_pool_t *p, void *BASE, void *ADD) {
     990void *mgs_config_server_merge(apr_pool_t * p, void *BASE, void *ADD)
     991{
    670992    int i;
    671993    char *err = NULL;
    672     mgs_srvconf_rec *base = (mgs_srvconf_rec *)BASE;
    673     mgs_srvconf_rec *add = (mgs_srvconf_rec *)ADD;
     994    mgs_srvconf_rec *base = (mgs_srvconf_rec *) BASE;
     995    mgs_srvconf_rec *add = (mgs_srvconf_rec *) ADD;
    674996    mgs_srvconf_rec *sc = _mgs_config_server_create(p, &err);
    675     if (NULL == sc) return err;
     997    if (NULL == sc)
     998        return err;
    676999
    6771000    gnutls_srvconf_merge(enabled, GNUTLS_ENABLED_UNSET);
     
    6831006    gnutls_srvconf_merge(srp_tpasswd_file, NULL);
    6841007    gnutls_srvconf_merge(srp_tpasswd_conf_file, NULL);
    685     gnutls_srvconf_merge(privkey_x509, NULL);
    686     gnutls_srvconf_merge(priorities, NULL);
    687     gnutls_srvconf_merge(dh_params, NULL);
     1008    gnutls_srvconf_merge(x509_cert_file, NULL);
     1009
     1010    gnutls_srvconf_merge(x509_key_file, NULL);
     1011    gnutls_srvconf_merge(x509_ca_file, NULL);
     1012    gnutls_srvconf_merge(p11_module, NULL);
     1013    gnutls_srvconf_merge(pin, NULL);
     1014    gnutls_srvconf_merge(pgp_cert_file, NULL);
     1015    gnutls_srvconf_merge(pgp_key_file, NULL);
     1016    gnutls_srvconf_merge(pgp_ring_file, NULL);
     1017    gnutls_srvconf_merge(dh_file, NULL);
     1018    gnutls_srvconf_merge(priorities_str, NULL);
     1019
     1020    gnutls_srvconf_merge(proxy_x509_key_file, NULL);
     1021    gnutls_srvconf_merge(proxy_x509_cert_file, NULL);
     1022    gnutls_srvconf_merge(proxy_x509_ca_file, NULL);
     1023    gnutls_srvconf_merge(proxy_x509_crl_file, NULL);
     1024    gnutls_srvconf_merge(proxy_priorities_str, NULL);
     1025    gnutls_srvconf_merge(proxy_priorities, NULL);
    6881026
    6891027    /* FIXME: the following items are pre-allocated, and should be
    6901028     * properly disposed of before assigning in order to avoid leaks;
    6911029     * so at the moment, we can't actually have them in the config.
    692      * what happens during de-allocation?
    693 
    694      * This is probably leaky.
    695      */
     1030     * what happens during de-allocation? */
     1031    /* TODO: mgs_load_files takes care of most of these now, verify
     1032     * and clean up the following lines */
     1033    gnutls_srvconf_assign(ca_list);
     1034    gnutls_srvconf_assign(ca_list_size);
     1035    gnutls_srvconf_assign(cert_pgp);
     1036    gnutls_srvconf_assign(cert_crt_pgp);
     1037    gnutls_srvconf_assign(pgp_list);
    6961038    gnutls_srvconf_assign(certs);
    6971039    gnutls_srvconf_assign(anon_creds);
    6981040    gnutls_srvconf_assign(srp_creds);
    6991041    gnutls_srvconf_assign(certs_x509_chain);
     1042    gnutls_srvconf_assign(certs_x509_crt_chain);
    7001043    gnutls_srvconf_assign(certs_x509_chain_num);
    7011044
     
    7041047    gnutls_srvconf_assign(cert_cn);
    7051048    for (i = 0; i < MAX_CERT_SAN; i++)
    706         gnutls_srvconf_assign(cert_san[i]);
    707     gnutls_srvconf_assign(ca_list);
    708     gnutls_srvconf_assign(ca_list_size);
    709     gnutls_srvconf_assign(cert_pgp);
    710     gnutls_srvconf_assign(pgp_list);
    711     gnutls_srvconf_assign(privkey_pgp);
     1049        gnutls_srvconf_assign(cert_san[i]);
    7121050
    7131051    return sc;
     
    7241062    mgs_dirconf_rec *add = (mgs_dirconf_rec *) addv;
    7251063
    726     new = (mgs_dirconf_rec *) apr_pcalloc(p, sizeof (mgs_dirconf_rec));
     1064    new = (mgs_dirconf_rec *) apr_pcalloc(p, sizeof(mgs_dirconf_rec));
    7271065    new->client_verify_mode = add->client_verify_mode;
    7281066    return new;
     
    7361074}
    7371075
     1076
     1077
     1078/*
     1079 * Store paths to proxy credentials
     1080 *
     1081 * This function copies the paths provided in the configuration file
     1082 * into the server configuration. The post configuration hook takes
     1083 * care of actually loading the credentials, which means than invalid
     1084 * paths or the like will be detected there.
     1085 */
     1086const char *mgs_store_cred_path(cmd_parms * parms,
     1087                                void *dummy __attribute__((unused)),
     1088                                const char *arg)
     1089{
     1090    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
     1091        ap_get_module_config(parms->server->module_config, &gnutls_module);
     1092
     1093    /* parms->directive->directive contains the directive string */
     1094    if (!strcasecmp(parms->directive->directive, "GnuTLSProxyKeyFile"))
     1095        sc->proxy_x509_key_file = apr_pstrdup(parms->pool, arg);
     1096    else if (!strcasecmp(parms->directive->directive,
     1097                         "GnuTLSProxyCertificateFile"))
     1098        sc->proxy_x509_cert_file = apr_pstrdup(parms->pool, arg);
     1099    else if (!strcasecmp(parms->directive->directive, "GnuTLSProxyCAFile"))
     1100        sc->proxy_x509_ca_file = apr_pstrdup(parms->pool, arg);
     1101    else if (!strcasecmp(parms->directive->directive, "GnuTLSProxyCRLFile"))
     1102        sc->proxy_x509_crl_file = apr_pstrdup(parms->pool, arg);
     1103    return NULL;
     1104}
     1105
     1106
     1107
     1108/*
     1109 * Record additional PKCS #11 module to load. Note that the value is
     1110 * only used in the base config, settings in virtual hosts are
     1111 * ignored.
     1112 */
     1113const char *mgs_set_p11_module(cmd_parms * parms,
     1114                               void *dummy __attribute__((unused)),
     1115                               const char *arg)
     1116{
     1117    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
     1118        ap_get_module_config(parms->server->module_config, &gnutls_module);
     1119    sc->p11_module = apr_pstrdup(parms->pool, arg);
     1120    return NULL;
     1121}
  • src/gnutls_hooks.c

    r2afbe2e r9b20a1e  
    44 *  Copyright 2011 Dash Shendy
    55 *  Copyright 2013-2014 Daniel Kahn Gillmor
     6 *  Copyright 2015 Thomas Klute
    67 *
    78 *  Licensed under the Apache License, Version 2.0 (the "License");
     
    4041#endif
    4142
     43#define IS_PROXY_STR(c) \
     44    ((c->is_proxy == GNUTLS_ENABLED_TRUE) ? "proxy " : "")
     45
    4246static gnutls_datum_t session_ticket_key = {NULL, 0};
    4347
     
    5054static const char* mgs_x509_construct_uid(request_rec * pool, gnutls_x509_crt_t cert);
    5155#endif
     56static int load_proxy_x509_credentials(server_rec *s);
    5257
    5358/* Pool Cleanup Function */
     
    147152    gnutls_certificate_server_set_request(session, ctxt->sc->client_verify_mode);
    148153
     154    /* Set x509 credentials */
     155    gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, ctxt->sc->certs);
    149156    /* Set Anon credentials */
    150     gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, ctxt->sc->certs);
    151         /* Set x509 credentials */
    152157    gnutls_credentials_set(session, GNUTLS_CRD_ANON, ctxt->sc->anon_creds);
    153158
     
    171176
    172177static int cert_retrieve_fn(gnutls_session_t session,
    173                                                         const gnutls_datum_t * req_ca_rdn __attribute__((unused)), int nreqs __attribute__((unused)),
    174                                                         const gnutls_pk_algorithm_t * pk_algos __attribute__((unused)), int pk_algos_length __attribute__((unused)),
    175                                                         gnutls_retr2_st *ret) {
    176 
    177 
    178         _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__);
    179 
    180         mgs_handle_t *ctxt;
     178                            const gnutls_datum_t * req_ca_rdn __attribute__((unused)),
     179                            int nreqs __attribute__((unused)),
     180                            const gnutls_pk_algorithm_t * pk_algos __attribute__((unused)),
     181                            int pk_algos_length __attribute__((unused)),
     182                            gnutls_pcert_st **pcerts,
     183                            unsigned int *pcert_length,
     184                            gnutls_privkey_t *privkey)
     185{
     186    _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__);
     187
     188    mgs_handle_t *ctxt;
    181189
    182190    if (session == NULL) {
    183191                // ERROR INVALID SESSION
    184                 ret->ncerts = 0;
    185                 ret->deinit_all = 1;
    186192        return -1;
    187         }
     193    }
     194
    188195    ctxt = gnutls_transport_get_ptr(session);
    189196
    190197    if (gnutls_certificate_type_get(session) == GNUTLS_CRT_X509) {
    191198                // X509 CERTIFICATE
    192                 ret->cert_type = GNUTLS_CRT_X509;
    193                 ret->key_type = GNUTLS_PRIVKEY_X509;
    194         ret->ncerts = ctxt->sc->certs_x509_chain_num;
    195         ret->deinit_all = 0;
    196         ret->cert.x509 = ctxt->sc->certs_x509_chain;
    197         ret->key.x509 = ctxt->sc->privkey_x509;
     199        *pcerts = ctxt->sc->certs_x509_chain;
     200        *pcert_length = ctxt->sc->certs_x509_chain_num;
     201        *privkey = ctxt->sc->privkey_x509;
    198202        return 0;
    199203    } else if (gnutls_certificate_type_get(session) == GNUTLS_CRT_OPENPGP) {
    200204                // OPENPGP CERTIFICATE
    201                 ret->cert_type = GNUTLS_CRT_OPENPGP;
    202                 ret->key_type = GNUTLS_PRIVKEY_OPENPGP;
    203         ret->ncerts = 1;
    204         ret->deinit_all = 0;
    205         ret->cert.pgp = ctxt->sc->cert_pgp;
    206         ret->key.pgp = ctxt->sc->privkey_pgp;
     205        *pcerts = ctxt->sc->cert_pgp;
     206        *pcert_length = 1;
     207        *privkey = ctxt->sc->privkey_pgp;
    207208        return 0;
    208209    } else {
    209210                // UNKNOWN CERTIFICATE
    210                 ret->ncerts = 0;
    211                 ret->deinit_all = 1;
    212211            return -1;
    213212        }
    214213}
    215 
    216 /* 2048-bit group parameters from SRP specification */
    217 const char static_dh_params[] = "-----BEGIN DH PARAMETERS-----\n"
    218         "MIIBBwKCAQCsa9tBMkqam/Fm3l4TiVgvr3K2ZRmH7gf8MZKUPbVgUKNzKcu0oJnt\n"
    219         "gZPgdXdnoT3VIxKrSwMxDc1/SKnaBP1Q6Ag5ae23Z7DPYJUXmhY6s2YaBfvV+qro\n"
    220         "KRipli8Lk7hV+XmT7Jde6qgNdArb9P90c1nQQdXDPqcdKB5EaxR3O8qXtDoj+4AW\n"
    221         "dr0gekNsZIHx0rkHhxdGGludMuaI+HdIVEUjtSSw1X1ep3onddLs+gMs+9v1L7N4\n"
    222         "YWAnkATleuavh05zA85TKZzMBBx7wwjYKlaY86jQw4JxrjX46dv7tpS1yAPYn3rk\n"
    223         "Nd4jbVJfVHWbZeNy/NaO8g+nER+eSv9zAgEC\n"
    224         "-----END DH PARAMETERS-----\n";
    225214
    226215/* Read the common name or the alternative name of the certificate.
     
    322311    }
    323312
    324 
    325313    s = base_server;
    326314    sc_base = (mgs_srvconf_rec *) ap_get_module_config(s->module_config, &gnutls_module);
    327315
    328     gnutls_dh_params_init(&dh_params);
    329 
    330     if (sc_base->dh_params == NULL) {
    331         gnutls_datum_t pdata = {
    332             (void *) static_dh_params,
    333             sizeof(static_dh_params)
    334         };
    335         rv = gnutls_dh_params_import_pkcs3(dh_params, &pdata, GNUTLS_X509_FMT_PEM);
    336         /* Generate DH Params
    337         int dh_bits = gnutls_sec_param_to_pk_bits(GNUTLS_PK_DH,
    338                 GNUTLS_SEC_PARAM_NORMAL);
    339         ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
    340             "GnuTLS: Generating DH Params of %i bits.  "
    341             "To avoid this use GnuTLSDHFile to specify DH Params for this host",
    342             dh_bits);
    343 #if MOD_GNUTLS_DEBUG
    344             ap_log_error(APLOG_MARK, APLOG_INFO, 0, s,
    345                     "GnuTLS: Generated DH Params of %i bits",dh_bits);
    346 #endif
    347         rv = gnutls_dh_params_generate2 (dh_params,dh_bits);
    348         */
    349         if (rv < 0) {
    350             ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
    351                     "GnuTLS: Unable to generate or load DH Params: (%d) %s",
    352                     rv, gnutls_strerror(rv));
    353             exit(rv);
    354         }
    355     } else {
    356         dh_params = sc_base->dh_params;
    357     }
    358316
    359317    rv = mgs_cache_post_config(p, s, sc_base);
     
    365323    }
    366324
     325    /* Load additional PKCS #11 module, if requested */
     326    if (sc_base->p11_module != NULL)
     327    {
     328        rv = gnutls_pkcs11_add_provider(sc_base->p11_module, NULL);
     329        if (rv != GNUTLS_E_SUCCESS)
     330            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
     331                         "GnuTLS: Loading PKCS #11 provider module %s "
     332                         "failed: %s (%d).",
     333                         sc_base->p11_module, gnutls_strerror(rv), rv);
     334    }
     335
    367336    for (s = base_server; s; s = s->next) {
    368337        sc = (mgs_srvconf_rec *) ap_get_module_config(s->module_config, &gnutls_module);
     
    370339        sc->cache_config = sc_base->cache_config;
    371340        sc->cache_timeout = sc_base->cache_timeout;
     341
     342        rv = mgs_load_files(p, s);
     343        if (rv != 0) {
     344            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
     345                "GnuTLS: Loading required files failed."
     346                " Shutting Down.");
     347            exit(-1);
     348        }
    372349
    373350        /* defaults for unset values: */
     
    383360            sc->client_verify_method = mgs_cvm_cartel;
    384361
    385 
    386362        /* Check if the priorities have been set */
    387363        if (sc->priorities == NULL && sc->enabled == GNUTLS_ENABLED_TRUE) {
     
    401377        }
    402378
    403         gnutls_certificate_set_retrieve_function(sc->certs, cert_retrieve_fn);
    404 
    405 #ifdef ENABLE_SRP
    406         if (sc->srp_tpasswd_conf_file != NULL
    407                 && sc->srp_tpasswd_file != NULL) {
    408             rv = gnutls_srp_set_server_credentials_file
    409                     (sc->srp_creds, sc->srp_tpasswd_file,
    410                     sc->srp_tpasswd_conf_file);
    411 
    412             if (rv < 0 && sc->enabled == GNUTLS_ENABLED_TRUE) {
    413                 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0,
    414                         s,
    415                         "[GnuTLS] - Host '%s:%d' is missing a "
    416                         "SRP password or conf File!",
    417                         s->server_hostname, s->port);
    418                 exit(-1);
    419             }
    420         }
     379        /* The call after this comment is a workaround for bug in
     380         * gnutls_certificate_set_retrieve_function2 that ignores
     381         * supported certificate types. Should be fixed in GnuTLS
     382         * 3.3.12.
     383         *
     384         * Details:
     385         * https://lists.gnupg.org/pipermail/gnutls-devel/2015-January/007377.html
     386         * Workaround from:
     387         * https://github.com/vanrein/tlspool/commit/4938102d3d1b086491d147e6c8e4e2a02825fc12 */
     388#if GNUTLS_VERSION_NUMBER < 0x030312
     389        gnutls_certificate_set_retrieve_function(sc->certs, (void *) exit);
    421390#endif
     391
     392        gnutls_certificate_set_retrieve_function2(sc->certs, cert_retrieve_fn);
    422393
    423394        if ((sc->certs_x509_chain == NULL || sc->certs_x509_chain_num < 1) &&
    424395            sc->cert_pgp == NULL && sc->enabled == GNUTLS_ENABLED_TRUE) {
    425396                        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
    426                                                 "[GnuTLS] - Host '%s:%d' is missing a Certificate File!",
     397                                                "GnuTLS: Host '%s:%d' is missing a Certificate File!",
    427398                                                s->server_hostname, s->port);
    428399            exit(-1);
    429400        }
    430 
    431401        if (sc->enabled == GNUTLS_ENABLED_TRUE &&
    432             ((sc->certs_x509_chain != NULL && sc->certs_x509_chain_num > 0 && sc->privkey_x509 == NULL) ||
    433              (sc->cert_pgp != NULL && sc->privkey_pgp == NULL))) {
     402            ((sc->certs_x509_chain_num > 0 && sc->privkey_x509 == NULL) ||
     403             (sc->cert_crt_pgp[0] != NULL && sc->privkey_pgp == NULL))) {
    434404                        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
    435                                                 "[GnuTLS] - Host '%s:%d' is missing a Private Key File!",
     405                                                "GnuTLS: Host '%s:%d' is missing a Private Key File!",
    436406                                                s->server_hostname, s->port);
    437407            exit(-1);
     
    441411            rv = -1;
    442412            if (sc->certs_x509_chain_num > 0) {
    443                 rv = read_crt_cn(s, p, sc->certs_x509_chain[0], &sc->cert_cn);
     413                rv = read_crt_cn(s, p, sc->certs_x509_crt_chain[0], &sc->cert_cn);
    444414            }
    445415            if (rv < 0 && sc->cert_pgp != NULL) {
    446                 rv = read_pgpcrt_cn(s, p, sc->cert_pgp, &sc->cert_cn);
     416                rv = read_pgpcrt_cn(s, p, sc->cert_crt_pgp[0], &sc->cert_cn);
    447417                        }
    448418
    449419            if (rv < 0) {
    450420                ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
    451                                                         "[GnuTLS] - Cannot find a certificate for host '%s:%d'!",
     421                                                        "GnuTLS: Cannot find a certificate for host '%s:%d'!",
    452422                                                        s->server_hostname, s->port);
    453423                sc->cert_cn = NULL;
    454424                continue;
    455425            }
     426        }
     427
     428        if (sc->enabled == GNUTLS_ENABLED_TRUE
     429            && sc->proxy_enabled == GNUTLS_ENABLED_TRUE
     430            && load_proxy_x509_credentials(s) != APR_SUCCESS)
     431        {
     432            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
     433                         "%s: loading proxy credentials for host "
     434                         "'%s:%d' failed, exiting!",
     435                         __func__, s->server_hostname, s->port);
     436            exit(-1);
    456437        }
    457438    }
     
    474455}
    475456
    476 void mgs_hook_child_init(apr_pool_t * p, server_rec * s) {
     457void mgs_hook_child_init(apr_pool_t * p, server_rec *s) {
    477458    apr_status_t rv = APR_SUCCESS;
    478     mgs_srvconf_rec *sc = ap_get_module_config(s->module_config,
    479             &gnutls_module);
     459    mgs_srvconf_rec *sc =
     460        (mgs_srvconf_rec *) ap_get_module_config(s->module_config, &gnutls_module);
    480461
    481462    _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__);
     463    /* if we use PKCS #11 reinitialize it */
     464
     465    if (mgs_pkcs11_reinit(s) < 0) {
     466            ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s,
     467                    "GnuTLS: Failed to reinitialize PKCS #11");
     468            exit(-1);
     469    }
     470
    482471    if (sc->cache_type != mgs_cache_none) {
    483472        rv = mgs_cache_child_init(p, s, sc);
    484473        if (rv != APR_SUCCESS) {
    485474            ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s,
    486                     "[GnuTLS] - Failed to run Cache Init");
     475                    "GnuTLS: Failed to run Cache Init");
    487476        }
    488477    }
     
    605594
    606595    if (tsc->certs_x509_chain_num > 0) {
    607         /* why are we doing this check? */
    608         ret = gnutls_x509_crt_check_hostname(tsc->certs_x509_chain[0], s->server_hostname);
     596        /* this check is there to warn administrator of any missing hostname
     597         * in the certificate. */
     598        ret = gnutls_x509_crt_check_hostname(tsc->certs_x509_crt_chain[0], s->server_hostname);
    609599        if (0 == ret)
    610             ap_log_error(APLOG_MARK, APLOG_INFO, 0, s,
    611                          "GnuTLS: Error checking certificate for hostname "
     600            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
     601                         "GnuTLS: the certificate doesn't match requested hostname "
    612602                         "'%s'", s->server_hostname);
    613603    } else {
     
    620610#endif
    621611
    622 mgs_srvconf_rec *mgs_find_sni_server(gnutls_session_t session) {
     612mgs_srvconf_rec *mgs_find_sni_server(gnutls_session_t session)
     613{
    623614    int rv;
    624615    unsigned int sni_type;
     
    671662
    672663        tsc = (mgs_srvconf_rec *) ap_get_module_config(s->module_config,
    673                 &gnutls_module);
     664                                                       &gnutls_module);
    674665
    675666        if (tsc->enabled != GNUTLS_ENABLED_TRUE) { continue; }
    676667
    677                                 if(check_server_aliases(x, s, tsc)) {
    678                                         return tsc;
    679                                 }
     668        if(check_server_aliases(x, s, tsc)) {
     669            return tsc;
     670        }
     671    }
    680672#endif
    681673    return NULL;
    682674}
    683675
    684 static void create_gnutls_handle(conn_rec * c) {
    685     mgs_handle_t *ctxt;
    686     /* Get mod_gnutls Configuration Record */
    687     mgs_srvconf_rec *sc =(mgs_srvconf_rec *)
    688             ap_get_module_config(c->base_server->module_config,&gnutls_module);
     676/*
     677 * This function is intended as a cleanup handler for connections
     678 * using GnuTLS.
     679 *
     680 * @param data must point to the mgs_handle_t associated with the
     681 * connection
     682 */
     683static apr_status_t cleanup_gnutls_session(void *data)
     684{
     685    /* nothing to do */
     686    if (data == NULL)
     687        return APR_SUCCESS;
     688
     689    /* check if session needs closing */
     690    mgs_handle_t *ctxt = (mgs_handle_t *) data;
     691    if (ctxt->session != NULL)
     692    {
     693        int ret;
     694        /* Try A Clean Shutdown */
     695        do
     696            ret = gnutls_bye(ctxt->session, GNUTLS_SHUT_WR);
     697        while (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN);
     698        if (ret != GNUTLS_E_SUCCESS)
     699            ap_log_cerror(APLOG_MARK, APLOG_INFO, ret, ctxt->c,
     700                          "%s: error while closing TLS %sconnection: %s (%d)",
     701                          __func__, IS_PROXY_STR(ctxt),
     702                          gnutls_strerror(ret), ret);
     703        else
     704            ap_log_cerror(APLOG_MARK, APLOG_DEBUG, ret, ctxt->c,
     705                          "%s: TLS %sconnection closed.",
     706                          __func__, IS_PROXY_STR(ctxt));
     707        /* De-Initialize Session */
     708        gnutls_deinit(ctxt->session);
     709        ctxt->session = NULL;
     710    }
     711    return APR_SUCCESS;
     712}
     713
     714static void create_gnutls_handle(conn_rec * c)
     715{
     716    /* Get mod_gnutls server configuration */
     717    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
     718            ap_get_module_config(c->base_server->module_config, &gnutls_module);
    689719
    690720    _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__);
    691     ctxt = apr_pcalloc(c->pool, sizeof (*ctxt));
     721
     722    /* Get connection specific configuration */
     723    mgs_handle_t *ctxt = (mgs_handle_t *) ap_get_module_config(c->conn_config, &gnutls_module);
     724    if (ctxt == NULL)
     725    {
     726        ctxt = apr_pcalloc(c->pool, sizeof (*ctxt));
     727        ap_set_module_config(c->conn_config, &gnutls_module, ctxt);
     728        ctxt->is_proxy = GNUTLS_ENABLED_FALSE;
     729    }
     730    ctxt->enabled = GNUTLS_ENABLED_TRUE;
    692731    ctxt->c = c;
    693732    ctxt->sc = sc;
     
    700739    ctxt->output_blen = 0;
    701740    ctxt->output_length = 0;
     741
    702742    /* Initialize GnuTLS Library */
    703     gnutls_init(&ctxt->session, GNUTLS_SERVER);
    704     /* Initialize Session Tickets */
    705     if (session_ticket_key.data != NULL && ctxt->sc->tickets != 0) {
    706         gnutls_session_ticket_enable_server(ctxt->session,&session_ticket_key);
     743    int err = 0;
     744    if (ctxt->is_proxy == GNUTLS_ENABLED_TRUE)
     745    {
     746        /* this is an outgoing proxy connection, client mode */
     747        err = gnutls_init(&ctxt->session, GNUTLS_CLIENT);
     748        if (err != GNUTLS_E_SUCCESS)
     749            ap_log_cerror(APLOG_MARK, APLOG_ERR, err, c,
     750                          "gnutls_init for proxy connection failed: %s (%d)",
     751                          gnutls_strerror(err), err);
     752        err = gnutls_session_ticket_enable_client(ctxt->session);
     753        if (err != GNUTLS_E_SUCCESS)
     754            ap_log_cerror(APLOG_MARK, APLOG_ERR, err, c,
     755                          "gnutls_session_ticket_enable_client failed: %s (%d)",
     756                          gnutls_strerror(err), err);
     757        /* Try to close and deinit the session when the connection
     758         * pool is cleared. Note that mod_proxy might not close
     759         * connections immediately, if you need that, look at the
     760         * "proxy-nokeepalive" environment variable for
     761         * mod_proxy_http. */
     762        apr_pool_pre_cleanup_register(c->pool, ctxt, cleanup_gnutls_session);
     763    }
     764    else
     765    {
     766        /* incoming connection, server mode */
     767        err = gnutls_init(&ctxt->session, GNUTLS_SERVER);
     768        if (err != GNUTLS_E_SUCCESS)
     769            ap_log_cerror(APLOG_MARK, APLOG_ERR, err, c,
     770                          "gnutls_init for server side failed: %s (%d)",
     771                          gnutls_strerror(err), err);
     772        /* Initialize Session Tickets */
     773        if (session_ticket_key.data != NULL && ctxt->sc->tickets != 0)
     774        {
     775            err = gnutls_session_ticket_enable_server(ctxt->session, &session_ticket_key);
     776            if (err != GNUTLS_E_SUCCESS)
     777                ap_log_cerror(APLOG_MARK, APLOG_ERR, err, c,
     778                              "gnutls_session_ticket_enable_server failed: %s (%d)",
     779                              gnutls_strerror(err), err);
     780        }
    707781    }
    708782
    709783    /* Set Default Priority */
    710         gnutls_priority_set_direct (ctxt->session, "NORMAL", NULL);
     784        err = gnutls_priority_set_direct(ctxt->session, "NORMAL", NULL);
     785    if (err != GNUTLS_E_SUCCESS)
     786        ap_log_cerror(APLOG_MARK, APLOG_ERR, err, c, "gnutls_priority_set_direct failed!");
    711787    /* Set Handshake function */
    712788    gnutls_handshake_set_post_client_hello_function(ctxt->session,
    713789            mgs_select_virtual_server_cb);
     790
     791    /* Set GnuTLS user pointer, so we can access the module session
     792     * context in GnuTLS callbacks */
     793    gnutls_session_set_ptr(ctxt->session, ctxt);
     794
     795    /* If mod_gnutls is the TLS server, mgs_select_virtual_server_cb
     796     * will load appropriate credentials during handshake. However,
     797     * when handling a proxy backend connection, mod_gnutls acts as
     798     * TLS client and credentials must be loaded here. */
     799    if (ctxt->is_proxy == GNUTLS_ENABLED_TRUE)
     800    {
     801        /* Set anonymous client credentials for proxy connections */
     802        gnutls_credentials_set(ctxt->session, GNUTLS_CRD_ANON,
     803                               ctxt->sc->anon_client_creds);
     804        /* Set x509 credentials */
     805        gnutls_credentials_set(ctxt->session, GNUTLS_CRD_CERTIFICATE,
     806                               ctxt->sc->proxy_x509_creds);
     807        /* Load priorities from the server configuration */
     808        err = gnutls_priority_set(ctxt->session, ctxt->sc->proxy_priorities);
     809        if (err != GNUTLS_E_SUCCESS)
     810            ap_log_cerror(APLOG_MARK, APLOG_ERR, err, c,
     811                          "%s: setting priorities for proxy connection "
     812                          "failed: %s (%d)",
     813                          __func__, gnutls_strerror(err), err);
     814    }
     815
    714816    /* Initialize Session Cache */
    715817    mgs_cache_session_init(ctxt);
    716818
    717     /* Set this config for this connection */
    718     ap_set_module_config(c->conn_config, &gnutls_module, ctxt);
    719819    /* Set pull, push & ptr functions */
    720820    gnutls_transport_set_pull_function(ctxt->session,
     
    730830}
    731831
    732 int mgs_hook_pre_connection(conn_rec * c, void *csd __attribute__((unused))) {
    733     mgs_srvconf_rec *sc;
    734 
     832int mgs_hook_pre_connection(conn_rec * c, void *csd __attribute__((unused)))
     833{
    735834    _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__);
    736835
    737     sc = (mgs_srvconf_rec *) ap_get_module_config(c->base_server->module_config,
    738             &gnutls_module);
    739 
    740     if (sc && (!sc->enabled || sc->proxy_enabled == GNUTLS_ENABLED_TRUE)) {
     836    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
     837        ap_get_module_config(c->base_server->module_config, &gnutls_module);
     838    mgs_handle_t *ctxt = (mgs_handle_t *)
     839        ap_get_module_config(c->conn_config, &gnutls_module);
     840
     841    if ((sc && (!sc->enabled)) || (ctxt && ctxt->enabled == GNUTLS_ENABLED_FALSE))
     842    {
     843        ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, "%s declined connection",
     844                      __func__);
    741845        return DECLINED;
    742846    }
     
    760864    apr_table_t *env = r->subprocess_env;
    761865
    762     ctxt =
    763             ap_get_module_config(r->connection->conn_config,
    764             &gnutls_module);
    765 
    766     if (!ctxt || ctxt->session == NULL) {
     866    ctxt = ap_get_module_config(r->connection->conn_config,
     867                                &gnutls_module);
     868
     869    if (!ctxt || ctxt->enabled != GNUTLS_ENABLED_TRUE || ctxt->session == NULL)
     870    {
     871        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "request declined in %s", __func__);
    767872        return DECLINED;
    768873    }
     
    821926
    822927    if (gnutls_certificate_type_get(ctxt->session) == GNUTLS_CRT_X509) {
    823                 mgs_add_common_cert_vars(r, ctxt->sc->certs_x509_chain[0], 0, ctxt->sc->export_certificates_size);
    824         } else if (gnutls_certificate_type_get(ctxt->session) == GNUTLS_CRT_OPENPGP) {
    825         mgs_add_common_pgpcert_vars(r, ctxt->sc->cert_pgp, 0, ctxt->sc->export_certificates_size);
    826         }
     928        mgs_add_common_cert_vars(r, ctxt->sc->certs_x509_crt_chain[0], 0, ctxt->sc->export_certificates_size);
     929    } else if (gnutls_certificate_type_get(ctxt->session) == GNUTLS_CRT_OPENPGP) {
     930        mgs_add_common_pgpcert_vars(r, ctxt->sc->cert_crt_pgp[0], 0, ctxt->sc->export_certificates_size);
     931    }
    827932
    828933    return rv;
     
    879984        }
    880985        rv = mgs_cert_verify(r, ctxt);
    881         if (rv != DECLINED &&
    882                 (rv != HTTP_FORBIDDEN ||
    883                 dc->client_verify_mode == GNUTLS_CERT_REQUIRE)) {
     986        if (rv != DECLINED
     987            && (rv != HTTP_FORBIDDEN
     988                || dc->client_verify_mode == GNUTLS_CERT_REQUIRE
     989                || (dc->client_verify_mode == -1
     990                    && ctxt->sc->client_verify_mode == GNUTLS_CERT_REQUIRE)))
     991        {
    884992            return rv;
    885993        }
     
    15531661}
    15541662
     1663
     1664
     1665/*
     1666 * Callback to check the server certificate for proxy HTTPS
     1667 * connections, to be used with
     1668 * gnutls_certificate_set_verify_function.
     1669
     1670 * Returns: 0 if certificate check was successful (certificate
     1671 * trusted), non-zero otherwise (error during check or untrusted
     1672 * certificate).
     1673 */
     1674static int gtls_check_server_cert(gnutls_session_t session)
     1675{
     1676    mgs_handle_t *ctxt = (mgs_handle_t *) gnutls_session_get_ptr(session);
     1677    unsigned int status;
     1678
     1679    /* Get peer hostname from a note left by mod_proxy */
     1680    const char *peer_hostname =
     1681        apr_table_get(ctxt->c->notes, "proxy-request-hostname");
     1682    if (peer_hostname == NULL)
     1683        ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, ctxt->c,
     1684                      "%s: proxy-request-hostname is NULL, cannot check "
     1685                      "peer's hostname", __func__);
     1686
     1687    /* Verify certificate, including hostname match. Should
     1688     * peer_hostname be NULL for some reason, the name is not
     1689     * checked. */
     1690    int err = gnutls_certificate_verify_peers3(session, peer_hostname,
     1691                                               &status);
     1692    if (err != GNUTLS_E_SUCCESS)
     1693    {
     1694        ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, ctxt->c,
     1695                      "%s: server certificate check failed: %s (%d)",
     1696                      __func__, gnutls_strerror(err), err);
     1697        return err;
     1698    }
     1699
     1700    gnutls_datum_t * out = gnutls_malloc(sizeof(gnutls_datum_t));
     1701    /* GNUTLS_CRT_X509: ATM, only X509 is supported for proxy certs
     1702     * 0: according to function API, the last argument should be 0 */
     1703    err = gnutls_certificate_verification_status_print(status, GNUTLS_CRT_X509,
     1704                                                       out, 0);
     1705    if (err != GNUTLS_E_SUCCESS)
     1706        ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, ctxt->c,
     1707                      "%s: server verify print failed: %s (%d)",
     1708                      __func__, gnutls_strerror(err), err);
     1709    else
     1710    {
     1711        /* If the certificate is trusted, logging the result is just
     1712         * nice for debugging. But if the back end server provided an
     1713         * untrusted certificate, warn! */
     1714        int level = (status == 0 ? APLOG_DEBUG : APLOG_WARNING);
     1715        ap_log_cerror(APLOG_MARK, level, 0, ctxt->c,
     1716                      "%s: server certificate verify result: %s",
     1717                      __func__, out->data);
     1718    }
     1719
     1720    gnutls_free(out);
     1721    return status;
     1722}
     1723
     1724
     1725
     1726static apr_status_t load_proxy_x509_credentials(server_rec *s)
     1727{
     1728    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
     1729        ap_get_module_config(s->module_config, &gnutls_module);
     1730
     1731    if (sc == NULL)
     1732        return APR_EGENERAL;
     1733
     1734    apr_status_t ret = APR_SUCCESS;
     1735    int err = GNUTLS_E_SUCCESS;
     1736
     1737    /* Function pool, gets destroyed before exit. */
     1738    apr_pool_t *pool;
     1739    ret = apr_pool_create(&pool, s->process->pool);
     1740    if (ret != APR_SUCCESS)
     1741    {
     1742        ap_log_error(APLOG_MARK, APLOG_ERR, ret, s,
     1743                     "%s: failed to allocate function memory pool.", __func__);
     1744        return ret;
     1745    }
     1746
     1747    /* allocate credentials structures */
     1748    err = gnutls_certificate_allocate_credentials(&sc->proxy_x509_creds);
     1749    if (err != GNUTLS_E_SUCCESS)
     1750    {
     1751        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
     1752                     "%s: Failed to initialize proxy credentials: (%d) %s",
     1753                     __func__, err, gnutls_strerror(err));
     1754        return APR_EGENERAL;
     1755    }
     1756    err = gnutls_anon_allocate_client_credentials(&sc->anon_client_creds);
     1757    if (err != GNUTLS_E_SUCCESS)
     1758    {
     1759        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
     1760                     "%s: Failed to initialize anon credentials for proxy: "
     1761                     "(%d) %s", __func__, err, gnutls_strerror(err));
     1762        return APR_EGENERAL;
     1763    }
     1764
     1765    /* Check if the proxy priorities have been set, fail immediately
     1766     * if not */
     1767    if (sc->proxy_priorities_str == NULL)
     1768    {
     1769        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
     1770                     "Host '%s:%d' is missing the GnuTLSProxyPriorities "
     1771                     "directive!",
     1772                     s->server_hostname, s->port);
     1773        return APR_EGENERAL;
     1774    }
     1775    /* parse proxy priorities */
     1776    const char *err_pos = NULL;
     1777    err = gnutls_priority_init(&sc->proxy_priorities,
     1778                               sc->proxy_priorities_str, &err_pos);
     1779    if (err != GNUTLS_E_SUCCESS)
     1780    {
     1781        if (ret == GNUTLS_E_INVALID_REQUEST)
     1782            ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
     1783                         "%s: Syntax error parsing proxy priorities "
     1784                         "string at: %s",
     1785                         __func__, err_pos);
     1786        else
     1787            ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
     1788                         "Error setting proxy priorities: %s (%d)",
     1789                         gnutls_strerror(err), err);
     1790        ret = APR_EGENERAL;
     1791    }
     1792
     1793    /* load certificate and key for client auth, if configured */
     1794    if (sc->proxy_x509_key_file && sc->proxy_x509_cert_file)
     1795    {
     1796        char* cert_file = ap_server_root_relative(pool,
     1797                                                  sc->proxy_x509_cert_file);
     1798        char* key_file = ap_server_root_relative(pool,
     1799                                                 sc->proxy_x509_key_file);
     1800        err = gnutls_certificate_set_x509_key_file(sc->proxy_x509_creds,
     1801                                                   cert_file,
     1802                                                   key_file,
     1803                                                   GNUTLS_X509_FMT_PEM);
     1804        if (err != GNUTLS_E_SUCCESS)
     1805        {
     1806            ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
     1807                         "%s: loading proxy client credentials failed: %s (%d)",
     1808                         __func__, gnutls_strerror(err), err);
     1809            ret = APR_EGENERAL;
     1810        }
     1811    }
     1812    else if (!sc->proxy_x509_key_file && sc->proxy_x509_cert_file)
     1813    {
     1814        ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
     1815                     "%s: proxy key file not set!", __func__);
     1816        ret = APR_EGENERAL;
     1817    }
     1818    else if (!sc->proxy_x509_cert_file && sc->proxy_x509_key_file)
     1819    {
     1820        ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
     1821                     "%s: proxy certificate file not set!", __func__);
     1822        ret = APR_EGENERAL;
     1823    }
     1824    else
     1825        /* if both key and cert are NULL, client auth is not used */
     1826        ap_log_error(APLOG_MARK, APLOG_INFO, 0, s,
     1827                     "%s: no client credentials for proxy", __func__);
     1828
     1829    /* must be set if the server certificate is to be checked */
     1830    if (sc->proxy_x509_ca_file)
     1831    {
     1832        /* initialize the trust list */
     1833        err = gnutls_x509_trust_list_init(&sc->proxy_x509_tl, 0);
     1834        if (err != GNUTLS_E_SUCCESS)
     1835        {
     1836            ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
     1837                         "%s: gnutls_x509_trust_list_init failed: %s (%d)",
     1838                         __func__, gnutls_strerror(err), err);
     1839            ret = APR_EGENERAL;
     1840        }
     1841
     1842        char* ca_file = ap_server_root_relative(pool,
     1843                                                sc->proxy_x509_ca_file);
     1844        /* if no CRL is used, sc->proxy_x509_crl_file is NULL */
     1845        char* crl_file = NULL;
     1846        if (sc->proxy_x509_crl_file)
     1847            crl_file = ap_server_root_relative(pool,
     1848                                               sc->proxy_x509_crl_file);
     1849
     1850        /* returns number of loaded elements */
     1851        err = gnutls_x509_trust_list_add_trust_file(sc->proxy_x509_tl,
     1852                                                    ca_file,
     1853                                                    crl_file,
     1854                                                    GNUTLS_X509_FMT_PEM,
     1855                                                    0 /* tl_flags */,
     1856                                                    0 /* tl_vflags */);
     1857        if (err > 0)
     1858            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
     1859                         "%s: proxy CA trust list: %d structures loaded",
     1860                         __func__, err);
     1861        else if (err == 0)
     1862            ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
     1863                         "%s: proxy CA trust list is empty (%d)",
     1864                         __func__, err);
     1865        else /* err < 0 */
     1866        {
     1867            ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
     1868                         "%s: error loading proxy CA trust list: %s (%d)",
     1869                         __func__, gnutls_strerror(err), err);
     1870            ret = APR_EGENERAL;
     1871        }
     1872
     1873        /* attach trust list to credentials */
     1874        gnutls_certificate_set_trust_list(sc->proxy_x509_creds,
     1875                                          sc->proxy_x509_tl, 0);
     1876    }
     1877    else
     1878        ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
     1879                     "%s: no CA trust list for proxy connections, "
     1880                     "TLS connections will fail!", __func__);
     1881
     1882    gnutls_certificate_set_verify_function(sc->proxy_x509_creds,
     1883                                           gtls_check_server_cert);
     1884    apr_pool_destroy(pool);
     1885    return ret;
     1886}
  • src/gnutls_io.c

    r2afbe2e r9b20a1e  
    33 *  Copyright 2008 Nikos Mavrogiannopoulos
    44 *  Copyright 2011 Dash Shendy
     5 *  Copyright 2015 Thomas Klute
    56 *
    67 *  Licensed under the Apache License, Version 2.0 (the "License");
     
    3839                               alloc)
    3940
     41#define IS_PROXY_STR(c) \
     42    ((c->is_proxy == GNUTLS_ENABLED_TRUE) ? "proxy " : "")
     43
    4044static apr_status_t gnutls_io_filter_error(ap_filter_t * f,
    4145        apr_bucket_brigade * bb,
     
    4549
    4650    switch (status) {
    47         case HTTP_BAD_REQUEST:
    48             /* log the situation */
    49             ap_log_error(APLOG_MARK, APLOG_INFO, 0,
    50                     f->c->base_server,
    51                     "GnuTLS handshake failed: HTTP spoken on HTTPS port; "
    52                     "trying to send HTML error page");
    53 
    54                                     mgs_srvconf_rec *sc = (mgs_srvconf_rec *) ap_get_module_config(
    55                                                                                                                                                                                                                                 f->c->base_server->module_config,
    56                                                                                                                                                                                                                                 &gnutls_module
    57                                                                                                                                                                                                                         );
    58             ctxt->status = -1;
    59             sc->non_ssl_request = 1;
    60 
    61             /* fake the request line */
    62             bucket = HTTP_ON_HTTPS_PORT_BUCKET(f->c->bucket_alloc);
    63             break;
    64 
    65         default:
    66             return status;
     51    case HTTP_BAD_REQUEST:
     52        /* log the situation */
     53        ap_log_error(APLOG_MARK, APLOG_INFO, 0,
     54                     f->c->base_server,
     55                     "GnuTLS handshake failed: HTTP spoken on HTTPS port; "
     56                     "trying to send HTML error page");
     57        mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
     58            ap_get_module_config(f->c->base_server->module_config,
     59                                 &gnutls_module);
     60        ctxt->status = -1;
     61        sc->non_ssl_request = 1;
     62
     63        /* fake the request line */
     64        bucket = HTTP_ON_HTTPS_PORT_BUCKET(f->c->bucket_alloc);
     65        break;
     66
     67    default:
     68        return status;
    6769    }
    6870
     
    186188
    187189static apr_status_t gnutls_io_input_read(mgs_handle_t * ctxt,
    188         char *buf, apr_size_t * len) {
     190        char *buf, apr_size_t * len)
     191{
    189192    apr_size_t wanted = *len;
    190193    apr_size_t bytes = 0;
     
    225228
    226229    if (ctxt->session == NULL) {
     230        ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, ctxt->c,
     231                      "%s: GnuTLS session is NULL!", __func__);
    227232        return APR_EGENERAL;
    228233    }
     
    230235    while (1) {
    231236
    232         rc = gnutls_record_recv(ctxt->session, buf + bytes,
    233                 wanted - bytes);
     237        do
     238            rc = gnutls_record_recv(ctxt->session, buf + bytes,
     239                                    wanted - bytes);
     240        while (rc == GNUTLS_E_INTERRUPTED || rc == GNUTLS_E_AGAIN);
    234241
    235242        if (rc > 0) {
     
    270277            if (rc == GNUTLS_E_REHANDSHAKE) {
    271278                /* A client has asked for a new Hankshake. Currently, we don't do it */
    272                 ap_log_error(APLOG_MARK, APLOG_INFO,
     279                ap_log_cerror(APLOG_MARK, APLOG_INFO,
    273280                        ctxt->input_rc,
    274                         ctxt->c->base_server,
     281                        ctxt->c,
    275282                        "GnuTLS: Error reading data. Client Requested a New Handshake."
    276283                        " (%d) '%s'", rc,
     
    278285            } else if (rc == GNUTLS_E_WARNING_ALERT_RECEIVED) {
    279286                rc = gnutls_alert_get(ctxt->session);
    280                 ap_log_error(APLOG_MARK, APLOG_INFO,
     287                ap_log_cerror(APLOG_MARK, APLOG_INFO,
    281288                        ctxt->input_rc,
    282                         ctxt->c->base_server,
     289                        ctxt->c,
    283290                        "GnuTLS: Warning Alert From Client: "
    284291                        " (%d) '%s'", rc,
     
    286293            } else if (rc == GNUTLS_E_FATAL_ALERT_RECEIVED) {
    287294                rc = gnutls_alert_get(ctxt->session);
    288                 ap_log_error(APLOG_MARK, APLOG_INFO,
     295                ap_log_cerror(APLOG_MARK, APLOG_INFO,
    289296                        ctxt->input_rc,
    290                         ctxt->c->base_server,
     297                        ctxt->c,
    291298                        "GnuTLS: Fatal Alert From Client: "
    292299                        "(%d) '%s'", rc,
     
    297304                /* Some Other Error. Report it. Die. */
    298305                if (gnutls_error_is_fatal(rc)) {
    299                     ap_log_error(APLOG_MARK,
     306                    ap_log_cerror(APLOG_MARK,
    300307                            APLOG_INFO,
    301308                            ctxt->input_rc,
    302                             ctxt->c->base_server,
     309                            ctxt->c,
    303310                            "GnuTLS: Error reading data. (%d) '%s'",
    304311                            rc,
     
    311318
    312319            if (ctxt->input_rc == APR_SUCCESS) {
     320                ap_log_cerror(APLOG_MARK, APLOG_INFO, ctxt->input_rc, ctxt->c,
     321                              "%s: GnuTLS error: %s (%d)",
     322                              __func__, gnutls_strerror(rc), rc);
    313323                ctxt->input_rc = APR_EGENERAL;
    314324            }
     
    405415            ap_log_error(APLOG_MARK, APLOG_INFO, 0,
    406416                    ctxt->c->base_server,
    407                     "GnuTLS: Hanshake Alert (%d) '%s'.",
     417                    "GnuTLS: Handshake Alert (%d) '%s'.",
    408418                    errcode,
    409419                    gnutls_alert_get_name(errcode));
     
    449459            }
    450460        }
    451         return 0;
     461        return GNUTLS_E_SUCCESS;
    452462    }
    453463}
     
    479489        apr_bucket_brigade * bb,
    480490        ap_input_mode_t mode,
    481         apr_read_type_e block, apr_off_t readbytes) {
     491        apr_read_type_e block, apr_off_t readbytes)
     492{
    482493    apr_status_t status = APR_SUCCESS;
    483494    mgs_handle_t *ctxt = (mgs_handle_t *) f->ctx;
     
    488499                apr_bucket_eos_create(f->c->bucket_alloc);
    489500        APR_BRIGADE_INSERT_TAIL(bb, bucket);
     501        ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, ctxt->c,
     502                      "%s: %sconnection aborted",
     503                      __func__, IS_PROXY_STR(ctxt));
    490504        return APR_ECONNABORTED;
    491505    }
    492506
    493507    if (ctxt->status == 0) {
    494         gnutls_do_handshake(ctxt);
     508        int ret = gnutls_do_handshake(ctxt);
     509        if (ret == GNUTLS_E_SUCCESS)
     510            ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, ctxt->c,
     511                          "%s: TLS %sconnection opened.",
     512                          __func__, IS_PROXY_STR(ctxt));
    495513    }
    496514
    497515    if (ctxt->status < 0) {
     516        ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, ctxt->c,
     517                      "%s %s: ap_get_brigade", __func__, IS_PROXY_STR(ctxt));
    498518        return ap_get_brigade(f->next, bb, mode, block, readbytes);
    499519    }
     
    588608
    589609    if (ctxt->status == 0) {
    590         gnutls_do_handshake(ctxt);
     610        ret = gnutls_do_handshake(ctxt);
     611        if (ret == GNUTLS_E_SUCCESS)
     612            ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, ctxt->c,
     613                          "%s: TLS %sconnection opened.",
     614                          __func__, IS_PROXY_STR(ctxt));
    591615    }
    592616
     
    615639                    ret = gnutls_bye(ctxt->session, GNUTLS_SHUT_WR);
    616640                } while (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN);
     641                ap_log_cerror(APLOG_MARK, APLOG_DEBUG, ret, ctxt->c,
     642                              "%s: TLS %sconnection closed.",
     643                              __func__, IS_PROXY_STR(ctxt));
    617644                /* De-Initialize Session */
    618645                gnutls_deinit(ctxt->session);
  • src/mod_gnutls.c

    r2afbe2e r9b20a1e  
    33 *  Copyright 2008 Nikos Mavrogiannopoulos
    44 *  Copyright 2011 Dash Shendy
     5 *  Copyright 2015 Thomas Klute
    56 *
    67 *  Licensed under the Apache License, Version 2.0 (the "License");
     
    2021#include "mod_gnutls.h"
    2122
    22 static void gnutls_hooks(apr_pool_t * p __attribute__((unused))) {
    23 
     23#ifdef APLOG_USE_MODULE
     24APLOG_USE_MODULE(gnutls);
     25#endif
     26
     27static void gnutls_hooks(apr_pool_t * p __attribute__((unused)))
     28{
    2429    /* Try Run Post-Config Hook After mod_proxy */
    2530    static const char * const aszPre[] = { "mod_proxy.c", NULL };
    26     ap_hook_post_config(mgs_hook_post_config, aszPre, NULL,APR_HOOK_REALLY_LAST);
     31    ap_hook_post_config(mgs_hook_post_config, aszPre, NULL,
     32                        APR_HOOK_REALLY_LAST);
    2733    /* HTTP Scheme Hook */
    2834#if USING_2_1_RECENT
     
    3238#endif
    3339    /* Default Port Hook */
    34     ap_hook_default_port(mgs_hook_default_port,  NULL,NULL, APR_HOOK_MIDDLE);
     40    ap_hook_default_port(mgs_hook_default_port, NULL, NULL, APR_HOOK_MIDDLE);
    3541    /* Pre-Connect Hook */
    36     ap_hook_pre_connection(mgs_hook_pre_connection, NULL, NULL, APR_HOOK_MIDDLE);
     42    ap_hook_pre_connection(mgs_hook_pre_connection, NULL, NULL,
     43                           APR_HOOK_MIDDLE);
    3744    /* Pre-Config Hook */
    3845    ap_hook_pre_config(mgs_hook_pre_config, NULL, NULL,
    39             APR_HOOK_MIDDLE);
     46                       APR_HOOK_MIDDLE);
    4047    /* Child-Init Hook */
    4148    ap_hook_child_init(mgs_hook_child_init, NULL, NULL,
    42             APR_HOOK_MIDDLE);
     49                       APR_HOOK_MIDDLE);
    4350    /* Authentication Hook */
    4451    ap_hook_access_checker(mgs_hook_authz, NULL, NULL,
    45             APR_HOOK_REALLY_FIRST);
     52                           APR_HOOK_REALLY_FIRST);
    4653    /* Fixups Hook */
    4754    ap_hook_fixups(mgs_hook_fixups, NULL, NULL, APR_HOOK_REALLY_FIRST);
     
    5360
    5461    /* Input Filter */
    55     ap_register_input_filter(GNUTLS_INPUT_FILTER_NAME,
    56             mgs_filter_input, NULL,AP_FTYPE_CONNECTION + 5);
     62    ap_register_input_filter(GNUTLS_INPUT_FILTER_NAME, mgs_filter_input,
     63                             NULL, AP_FTYPE_CONNECTION + 5);
    5764    /* Output Filter */
    58     ap_register_output_filter(GNUTLS_OUTPUT_FILTER_NAME,
    59             mgs_filter_output, NULL,AP_FTYPE_CONNECTION + 5);
     65    ap_register_output_filter(GNUTLS_OUTPUT_FILTER_NAME, mgs_filter_output,
     66                              NULL, AP_FTYPE_CONNECTION + 5);
    6067
    6168    /* mod_proxy calls these functions */
     
    6471}
    6572
    66 int ssl_is_https(conn_rec *c) {
     73int ssl_is_https(conn_rec *c)
     74{
    6775    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
    68             ap_get_module_config(c->base_server->module_config, &gnutls_module);
     76        ap_get_module_config(c->base_server->module_config, &gnutls_module);
    6977    if(sc->enabled == 0 || sc->non_ssl_request == 1) {
    7078        /* SSL/TLS Disabled or Plain HTTP Connection Detected */
     
    7583}
    7684
    77 int ssl_engine_disable(conn_rec *c) {
     85int ssl_engine_disable(conn_rec *c)
     86{
    7887    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
    79             ap_get_module_config(c->base_server->module_config, &gnutls_module);
     88        ap_get_module_config(c->base_server->module_config, &gnutls_module);
    8089    if(sc->enabled == GNUTLS_ENABLED_FALSE) {
    8190        return 1;
    8291    }
    83     ap_remove_input_filter(c->input_filters);
    84     ap_remove_input_filter(c->output_filters);
    85     mgs_cleanup_pre_config(c->pool);
    86     sc->enabled = 0;
     92
     93    /* disable TLS for this connection */
     94    mgs_handle_t *ctxt = (mgs_handle_t *)
     95        ap_get_module_config(c->conn_config, &gnutls_module);
     96    if (ctxt == NULL)
     97    {
     98        ctxt = apr_pcalloc(c->pool, sizeof (*ctxt));
     99        ap_set_module_config(c->conn_config, &gnutls_module, ctxt);
     100    }
     101    ctxt->enabled = GNUTLS_ENABLED_FALSE;
     102    ctxt->is_proxy = GNUTLS_ENABLED_TRUE;
     103
     104    if (c->input_filters)
     105        ap_remove_input_filter(c->input_filters);
     106    if (c->output_filters)
     107        ap_remove_output_filter(c->output_filters);
     108
    87109    return 1;
    88110}
    89111
    90 int ssl_proxy_enable(conn_rec *c) {
     112int ssl_proxy_enable(conn_rec *c)
     113{
     114    /* check if TLS proxy support is enabled */
    91115    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
    92             ap_get_module_config(c->base_server->module_config, &gnutls_module);
    93     sc->proxy_enabled = 1;
    94     sc->enabled = 0;
     116        ap_get_module_config(c->base_server->module_config, &gnutls_module);
     117    if (sc->proxy_enabled != GNUTLS_ENABLED_TRUE)
     118    {
     119        ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c,
     120                      "%s: mod_proxy requested TLS proxy, but not enabled "
     121                      "for %s", __func__, sc->cert_cn);
     122        return 0;
     123    }
     124
     125    /* enable TLS for this connection */
     126    mgs_handle_t *ctxt = (mgs_handle_t *)
     127        ap_get_module_config(c->conn_config, &gnutls_module);
     128    if (ctxt == NULL)
     129    {
     130        ctxt = apr_pcalloc(c->pool, sizeof (*ctxt));
     131        ap_set_module_config(c->conn_config, &gnutls_module, ctxt);
     132    }
     133    ctxt->enabled = GNUTLS_ENABLED_TRUE;
     134    ctxt->is_proxy = GNUTLS_ENABLED_TRUE;
    95135    return 1;
    96136}
    97137
    98138static const command_rec mgs_config_cmds[] = {
    99     AP_INIT_TAKE1("SSLProxyEngine", mgs_set_proxy_engine,
     139    AP_INIT_TAKE1("GnuTLSProxyEngine", mgs_set_proxy_engine,
    100140    NULL,
    101141    RSRC_CONF | OR_AUTHCFG,
    102142    "Enable SSL Proxy Engine"),
     143    AP_INIT_TAKE1("GnuTLSP11Module", mgs_set_p11_module,
     144    NULL,
     145    RSRC_CONF,
     146    "Load this additional PKCS #11 provider library"),
     147    AP_INIT_RAW_ARGS("GnuTLSPIN", mgs_set_pin,
     148    NULL,
     149    RSRC_CONF,
     150    "The PIN to use in case of encrypted keys or PKCS #11 tokens."),
     151    AP_INIT_RAW_ARGS("GnuTLSSRKPIN", mgs_set_srk_pin,
     152    NULL,
     153    RSRC_CONF,
     154    "The SRK PIN to use in case of TPM keys."),
    103155    AP_INIT_TAKE1("GnuTLSClientVerify", mgs_set_client_verify,
    104156    NULL,
     
    185237    RSRC_CONF,
    186238    "Max size to export PEM encoded certificates to CGIs (or off to disable). Default: off"),
     239    AP_INIT_TAKE1("GnuTLSProxyKeyFile", mgs_store_cred_path,
     240    NULL,
     241    RSRC_CONF,
     242    "X509 client private file for proxy connections"),
     243    AP_INIT_TAKE1("GnuTLSProxyCertificateFile", mgs_store_cred_path,
     244    NULL,
     245    RSRC_CONF,
     246    "X509 client certificate file for proxy connections"),
     247    AP_INIT_TAKE1("GnuTLSProxyCAFile", mgs_store_cred_path,
     248    NULL,
     249    RSRC_CONF,
     250    "X509 trusted CA file for proxy connections"),
     251    AP_INIT_TAKE1("GnuTLSProxyCRLFile", mgs_store_cred_path,
     252    NULL,
     253    RSRC_CONF,
     254    "X509 CRL file for proxy connections"),
     255    AP_INIT_RAW_ARGS("GnuTLSProxyPriorities", mgs_set_priorities,
     256    NULL,
     257    RSRC_CONF,
     258    "The priorities to enable for proxy connections (ciphers, key exchange, "
     259    "MACs, compression)."),
    187260    { NULL },
    188261};
Note: See TracChangeset for help on using the changeset viewer.