Changeset d8afa3e in mod_gnutls for src/gnutls_hooks.c


Ignore:
Timestamp:
Dec 17, 2016, 6:56:34 PM (5 years ago)
Author:
Daniel Kahn Gillmor <dkg@…>
Branches:
debian/master, debian/stretch-backports, upstream
Children:
c598e21, d2b32f1
Parents:
ce12806 (diff), 677754f (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

New upstream version 0.8.0

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/gnutls_hooks.c

    rce12806 rd8afa3e  
    1 /**
     1/*
    22 *  Copyright 2004-2005 Paul Querna
    33 *  Copyright 2008, 2014 Nikos Mavrogiannopoulos
     
    1717 *  See the License for the specific language governing permissions and
    1818 *  limitations under the License.
    19  *
    2019 */
    2120
    2221#include "mod_gnutls.h"
     22#include "gnutls_cache.h"
     23#include "gnutls_ocsp.h"
    2324#include "http_vhost.h"
    2425#include "ap_mpm.h"
    2526#include "mod_status.h"
     27#include <util_mutex.h>
     28#include <apr_escape.h>
    2629
    2730#ifdef ENABLE_MSVA
     
    3336#endif
    3437
    35 #if !USING_2_1_RECENT
    36 extern server_rec *ap_server_conf;
    37 #endif
    38 
    3938#if MOD_GNUTLS_DEBUG
    4039static apr_file_t *debug_log_fp;
     
    4443    ((c->is_proxy == GNUTLS_ENABLED_TRUE) ? "proxy " : "")
    4544
     45/** Key to encrypt session tickets. Must be kept secret. This key is
     46 * generated in the `pre_config` hook and thus constant across
     47 * forks. The problem with this approach is that it does not support
     48 * regular key rotation. */
    4649static gnutls_datum_t session_ticket_key = {NULL, 0};
    4750
     
    5457static const char* mgs_x509_construct_uid(request_rec * pool, gnutls_x509_crt_t cert);
    5558#endif
    56 static int load_proxy_x509_credentials(server_rec *s);
     59static int load_proxy_x509_credentials(apr_pool_t *pconf, apr_pool_t *ptemp, server_rec *s)
     60    __attribute__((nonnull));
    5761
    5862/* Pool Cleanup Function */
    59 apr_status_t mgs_cleanup_pre_config(void *data __attribute__((unused))) {
    60         /* Free all session data */
     63apr_status_t mgs_cleanup_pre_config(void *data __attribute__((unused)))
     64{
     65    /* Free session ticket master key */
     66#if GNUTLS_VERSION_NUMBER >= 0x030400
     67    gnutls_memset(session_ticket_key.data, 0, session_ticket_key.size);
     68#endif
    6169    gnutls_free(session_ticket_key.data);
    6270    session_ticket_key.data = NULL;
     
    126134    AP_OPTIONAL_HOOK(status_hook, mgs_status_hook, NULL, NULL, APR_HOOK_MIDDLE);
    127135
    128         /* Register a pool clean-up function */
     136    ap_mutex_register(pconf, MGS_CACHE_MUTEX_NAME, NULL, APR_LOCK_DEFAULT, 0);
     137    ap_mutex_register(pconf, MGS_OCSP_MUTEX_NAME, NULL, APR_LOCK_DEFAULT, 0);
     138
     139    /* Register a pool clean-up function */
    129140    apr_pool_cleanup_register(pconf, NULL, mgs_cleanup_pre_config, apr_pool_cleanup_null);
    130141
     
    156167    /* Set Anon credentials */
    157168    gnutls_credentials_set(session, GNUTLS_CRD_ANON, ctxt->sc->anon_creds);
     169
     170    if (ctxt->sc->ocsp_staple)
     171    {
     172        gnutls_certificate_set_ocsp_status_request_function(ctxt->sc->certs,
     173                                                            mgs_get_ocsp_response,
     174                                                            ctxt);
     175    }
    158176
    159177#ifdef ENABLE_SRP
     
    295313}
    296314
    297 int mgs_hook_post_config(apr_pool_t * p, apr_pool_t * plog __attribute__((unused)), apr_pool_t * ptemp __attribute__((unused)), server_rec * base_server) {
    298 
     315/**
     316 * Post config hook.
     317 *
     318 * Must return OK or DECLINED on success, something else on
     319 * error. These codes are defined in Apache httpd.h along with the
     320 * HTTP status codes, so I'm going to use HTTP error codes both for
     321 * fun (and to avoid conflicts).
     322 */
     323int mgs_hook_post_config(apr_pool_t *pconf,
     324                         apr_pool_t *plog __attribute__((unused)),
     325                         apr_pool_t *ptemp,
     326                         server_rec *base_server)
     327{
    299328    int rv;
    300329    server_rec *s;
     
    316345
    317346
    318     rv = mgs_cache_post_config(p, s, sc_base);
    319     if (rv != 0) {
     347    rv = mgs_cache_post_config(pconf, s, sc_base);
     348    if (rv != APR_SUCCESS)
     349    {
    320350        ap_log_error(APLOG_MARK, APLOG_STARTUP, rv, s,
    321                 "GnuTLS: Post Config for GnuTLSCache Failed."
    322                 " Shutting Down.");
    323         exit(-1);
     351                     "Post config for cache failed.");
     352        return HTTP_INSUFFICIENT_STORAGE;
     353    }
     354
     355    if (sc_base->ocsp_mutex == NULL)
     356    {
     357        rv = ap_global_mutex_create(&sc_base->ocsp_mutex, NULL,
     358                                    MGS_OCSP_MUTEX_NAME, NULL,
     359                                    base_server, pconf, 0);
     360        if (rv != APR_SUCCESS)
     361        {
     362            ap_log_error(APLOG_MARK, APLOG_STARTUP, rv, base_server,
     363                         "Failed to create mutex '" MGS_OCSP_MUTEX_NAME
     364                         "'.");
     365            return HTTP_INTERNAL_SERVER_ERROR;
     366        }
    324367    }
    325368
     
    352395    }
    353396
    354     for (s = base_server; s; s = s->next) {
     397    for (s = base_server; s; s = s->next)
     398    {
    355399        sc = (mgs_srvconf_rec *) ap_get_module_config(s->module_config, &gnutls_module);
    356400        sc->cache_type = sc_base->cache_type;
    357401        sc->cache_config = sc_base->cache_config;
    358402        sc->cache_timeout = sc_base->cache_timeout;
    359 
    360         rv = mgs_load_files(p, s);
     403        sc->cache = sc_base->cache;
     404
     405        rv = mgs_load_files(pconf, ptemp, s);
    361406        if (rv != 0) {
    362407            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
    363408                "GnuTLS: Loading required files failed."
    364409                " Shutting Down.");
    365             exit(-1);
     410            return HTTP_NOT_FOUND;
     411        }
     412
     413        if (sc->ocsp_staple == GNUTLS_ENABLED_UNSET)
     414            sc->ocsp_staple = GNUTLS_ENABLED_FALSE;
     415
     416        sc->ocsp_mutex = sc_base->ocsp_mutex;
     417        /* init OCSP configuration if OCSP is enabled for this host */
     418        if (sc->ocsp_staple)
     419        {
     420            rv = mgs_ocsp_post_config_server(pconf, ptemp, s);
     421            if (rv != OK && rv != DECLINED)
     422                return rv;
    366423        }
    367424
     
    370427            sc->enabled = GNUTLS_ENABLED_FALSE;
    371428        if (sc->tickets == GNUTLS_ENABLED_UNSET)
    372             sc->tickets = GNUTLS_ENABLED_TRUE;
     429            sc->tickets = GNUTLS_ENABLED_FALSE;
    373430        if (sc->export_certificates_size < 0)
    374431            sc->export_certificates_size = 0;
     
    383440                    "GnuTLS: Host '%s:%d' is missing the GnuTLSPriorities directive!",
    384441                    s->server_hostname, s->port);
    385             exit(-1);
     442            return HTTP_NOT_ACCEPTABLE;
    386443        }
    387444
     
    415472                                                "GnuTLS: Host '%s:%d' is missing a Certificate File!",
    416473                                                s->server_hostname, s->port);
    417             exit(-1);
     474            return HTTP_UNAUTHORIZED;
    418475        }
    419476        if (sc->enabled == GNUTLS_ENABLED_TRUE &&
    420477            ((sc->certs_x509_chain_num > 0 && sc->privkey_x509 == NULL) ||
    421              (sc->cert_crt_pgp[0] != NULL && sc->privkey_pgp == NULL))) {
     478             (sc->cert_crt_pgp != NULL && sc->privkey_pgp == NULL)))
     479        {
    422480                        ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
    423481                                                "GnuTLS: Host '%s:%d' is missing a Private Key File!",
    424482                                                s->server_hostname, s->port);
    425             exit(-1);
     483            return HTTP_UNAUTHORIZED;
    426484        }
    427485
     
    429487            rv = -1;
    430488            if (sc->certs_x509_chain_num > 0) {
    431                 rv = read_crt_cn(s, p, sc->certs_x509_crt_chain[0], &sc->cert_cn);
     489                rv = read_crt_cn(s, pconf, sc->certs_x509_crt_chain[0], &sc->cert_cn);
    432490            }
    433491            if (rv < 0 && sc->cert_pgp != NULL) {
    434                 rv = read_pgpcrt_cn(s, p, sc->cert_crt_pgp[0], &sc->cert_cn);
     492                rv = read_pgpcrt_cn(s, pconf, sc->cert_crt_pgp[0], &sc->cert_cn);
    435493                        }
    436494
     
    446504        if (sc->enabled == GNUTLS_ENABLED_TRUE
    447505            && sc->proxy_enabled == GNUTLS_ENABLED_TRUE
    448             && load_proxy_x509_credentials(s) != APR_SUCCESS)
     506            && load_proxy_x509_credentials(pconf, ptemp, s) != APR_SUCCESS)
    449507        {
    450508            ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
     
    452510                         "'%s:%d' failed, exiting!",
    453511                         __func__, s->server_hostname, s->port);
    454             exit(-1);
    455         }
    456     }
    457 
    458 
    459     ap_add_version_component(p, "mod_gnutls/" MOD_GNUTLS_VERSION);
     512            return HTTP_PROXY_AUTHENTICATION_REQUIRED;
     513        }
     514    }
     515
     516
     517    ap_add_version_component(pconf, "mod_gnutls/" MOD_GNUTLS_VERSION);
    460518
    461519    {
    462520        const char* libvers = gnutls_check_version(NULL);
    463521        char* gnutls_version = NULL;
    464         if(libvers && (gnutls_version = apr_psprintf(p, "GnuTLS/%s", libvers))) {
    465             ap_add_version_component(p, gnutls_version);
     522        if(libvers && (gnutls_version = apr_psprintf(pconf, "GnuTLS/%s", libvers))) {
     523            ap_add_version_component(pconf, gnutls_version);
    466524        } else {
    467525            // In case we could not create the above string go for the static version instead
    468             ap_add_version_component(p, "GnuTLS/" GNUTLS_VERSION "-static");
     526            ap_add_version_component(pconf, "GnuTLS/" GNUTLS_VERSION "-static");
    469527        }
    470528    }
     
    473531}
    474532
    475 void mgs_hook_child_init(apr_pool_t * p, server_rec *s) {
     533void mgs_hook_child_init(apr_pool_t *p, server_rec *s)
     534{
    476535    apr_status_t rv = APR_SUCCESS;
    477     mgs_srvconf_rec *sc =
    478         (mgs_srvconf_rec *) ap_get_module_config(s->module_config, &gnutls_module);
     536    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
     537        ap_get_module_config(s->module_config, &gnutls_module);
    479538
    480539    _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__);
     540
    481541    /* if we use PKCS #11 reinitialize it */
    482 
    483542    if (mgs_pkcs11_reinit(s) < 0) {
    484543            ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s,
     
    494553        }
    495554    }
     555
     556    /* reinit OCSP mutex */
     557    const char *lockfile = apr_global_mutex_lockfile(sc->ocsp_mutex);
     558    rv = apr_global_mutex_child_init(&sc->ocsp_mutex, lockfile, p);
     559    if (rv != APR_SUCCESS)
     560        ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s,
     561                     "Failed to reinit mutex '" MGS_OCSP_MUTEX_NAME "'.");
     562
    496563    /* Block SIGPIPE Signals */
    497564    rv = apr_signal_block(SIGPIPE);
     
    541608#define MAX_HOST_LEN 255
    542609
    543 #if USING_2_1_RECENT
    544 
    545610typedef struct {
    546611    mgs_handle_t *ctxt;
     
    554619 * @param x vhost callback record
    555620 * @param s server record
     621 * @param tsc mod_gnutls server data for `s`
     622 *
    556623 * @return true if a match, false otherwise
    557624 *
    558625 */
    559 int check_server_aliases(vhost_cb_rec *x, server_rec * s, mgs_srvconf_rec *tsc) {
     626int check_server_aliases(vhost_cb_rec *x, server_rec * s, mgs_srvconf_rec *tsc)
     627{
    560628        apr_array_header_t *names;
    561629        int rv = 0;
     
    600668}
    601669
    602 static int vhost_cb(void *baton, conn_rec * conn __attribute__((unused)), server_rec * s) {
     670static int vhost_cb(void *baton, conn_rec *conn, server_rec * s)
     671{
    603672    mgs_srvconf_rec *tsc;
    604673    vhost_cb_rec *x = baton;
     
    618687        ret = gnutls_x509_crt_check_hostname(tsc->certs_x509_crt_chain[0], s->server_hostname);
    619688        if (0 == ret)
    620             ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
    621                          "GnuTLS: the certificate doesn't match requested hostname "
    622                          "'%s'", s->server_hostname);
     689            ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, conn,
     690                          "GnuTLS: the certificate doesn't match requested "
     691                          "hostname '%s'", s->server_hostname);
    623692    } else {
    624         ap_log_error(APLOG_MARK, APLOG_INFO, 0, s,
    625                      "GnuTLS: SNI request for '%s' but no X.509 certs available at all",
    626                      s->server_hostname);
     693        ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, conn,
     694                      "GnuTLS: SNI request for '%s' but no X.509 certs "
     695                      "available at all",
     696                      s->server_hostname);
    627697    }
    628698        return check_server_aliases(x, s, tsc);
    629699}
    630 #endif
    631700
    632701mgs_srvconf_rec *mgs_find_sni_server(gnutls_session_t session)
     
    637706    char sni_name[MAX_HOST_LEN];
    638707    mgs_handle_t *ctxt;
    639 #if USING_2_1_RECENT
    640708    vhost_cb_rec cbx;
    641 #else
    642     server_rec *s;
    643     mgs_srvconf_rec *tsc;
    644 #endif
    645709
    646710    if (session == NULL)
     
    658722
    659723    if (sni_type != GNUTLS_NAME_DNS) {
    660         ap_log_error(APLOG_MARK, APLOG_CRIT, 0,
    661                 ctxt->c->base_server,
    662                 "GnuTLS: Unknown type '%d' for SNI: "
    663                 "'%s'", sni_type, sni_name);
     724        ap_log_cerror(APLOG_MARK, APLOG_CRIT, 0, ctxt->c,
     725                      "GnuTLS: Unknown type '%d' for SNI: '%s'",
     726                      sni_type, sni_name);
    664727        return NULL;
    665728    }
     
    669732     * for this IP/Port combo.  Trust that the core did the 'right' thing.
    670733     */
    671 #if USING_2_1_RECENT
    672734    cbx.ctxt = ctxt;
    673735    cbx.sc = NULL;
     
    678740        return cbx.sc;
    679741    }
    680 #else
    681     for (s = ap_server_conf; s; s = s->next) {
    682 
    683         tsc = (mgs_srvconf_rec *) ap_get_module_config(s->module_config,
    684                                                        &gnutls_module);
    685 
    686         if (tsc->enabled != GNUTLS_ENABLED_TRUE) { continue; }
    687 
    688         if(check_server_aliases(x, s, tsc)) {
    689             return tsc;
    690         }
    691     }
    692 #endif
    693742    return NULL;
    694743}
     
    791840                          gnutls_strerror(err), err);
    792841        /* Initialize Session Tickets */
    793         if (session_ticket_key.data != NULL && ctxt->sc->tickets != 0)
     842        if (session_ticket_key.data != NULL &&
     843            ctxt->sc->tickets == GNUTLS_ENABLED_TRUE)
    794844        {
    795845            err = gnutls_session_ticket_enable_server(ctxt->session, &session_ticket_key);
     
    876926int mgs_hook_fixups(request_rec * r) {
    877927    unsigned char sbuf[GNUTLS_MAX_SESSION_ID];
    878     char buf[AP_IOBUFSIZE];
    879928    const char *tmp;
    880929    size_t len;
     
    946995    len = sizeof (sbuf);
    947996    gnutls_session_get_id(ctxt->session, sbuf, &len);
    948     tmp = mgs_session_id2sz(sbuf, len, buf, sizeof (buf));
    949     apr_table_setn(env, "SSL_SESSION_ID", apr_pstrdup(r->pool, tmp));
     997    apr_table_setn(env, "SSL_SESSION_ID",
     998                   apr_pescape_hex(r->pool, sbuf, len, 0));
    950999
    9511000    if (gnutls_certificate_type_get(ctxt->session) == GNUTLS_CRT_X509) {
     
    10821131    len = sizeof (sbuf);
    10831132    gnutls_x509_crt_get_serial(cert, sbuf, &len);
    1084     tmp = mgs_session_id2sz(sbuf, len, buf, sizeof (buf));
    1085     apr_table_setn(env, MGS_SIDE("_M_SERIAL"), apr_pstrdup(r->pool, tmp));
     1133    apr_table_setn(env, MGS_SIDE("_M_SERIAL"),
     1134                   apr_pescape_hex(r->pool, sbuf, len, 0));
    10861135
    10871136    ret = gnutls_x509_crt_get_version(cert);
     
    11991248    len = sizeof (sbuf);
    12001249    gnutls_openpgp_crt_get_fingerprint(cert, sbuf, &len);
    1201     tmp = mgs_session_id2sz(sbuf, len, buf, sizeof (buf));
    1202     apr_table_setn(env, MGS_SIDE("_FINGERPRINT"), apr_pstrdup(r->pool, tmp));
     1250    apr_table_setn(env, MGS_SIDE("_FINGERPRINT"),
     1251                   apr_pescape_hex(r->pool, sbuf, len, 0));
    12031252
    12041253    ret = gnutls_openpgp_crt_get_version(cert);
     
    17611810    }
    17621811
    1763     gnutls_datum_t * out = gnutls_malloc(sizeof(gnutls_datum_t));
    1764     /* GNUTLS_CRT_X509: ATM, only X509 is supported for proxy certs
    1765      * 0: according to function API, the last argument should be 0 */
    1766     err = gnutls_certificate_verification_status_print(status, GNUTLS_CRT_X509,
    1767                                                        out, 0);
    1768     if (err != GNUTLS_E_SUCCESS)
     1812    if (status == 0)
    17691813        ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, ctxt->c,
    1770                       "%s: server verify print failed: %s (%d)",
    1771                       __func__, gnutls_strerror(err), err);
     1814                      "%s: server certificate is trusted.",
     1815                      __func__);
    17721816    else
    17731817    {
    1774         /* If the certificate is trusted, logging the result is just
    1775          * nice for debugging. But if the back end server provided an
    1776          * untrusted certificate, warn! */
    1777         int level = (status == 0 ? APLOG_DEBUG : APLOG_WARNING);
    1778         ap_log_cerror(APLOG_MARK, level, 0, ctxt->c,
    1779                       "%s: server certificate verify result: %s",
    1780                       __func__, out->data);
    1781     }
    1782 
    1783     gnutls_free(out);
     1818        gnutls_datum_t out;
     1819        /* GNUTLS_CRT_X509: ATM, only X509 is supported for proxy
     1820         * certs 0: according to function API, the last argument
     1821         * should be 0 */
     1822        err = gnutls_certificate_verification_status_print(status,
     1823                                                           GNUTLS_CRT_X509,
     1824                                                           &out, 0);
     1825        if (err != GNUTLS_E_SUCCESS)
     1826            ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, ctxt->c,
     1827                          "%s: server verify print failed: %s (%d)",
     1828                          __func__, gnutls_strerror(err), err);
     1829        else
     1830            ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, ctxt->c,
     1831                          "%s: %s",
     1832                          __func__, out.data);
     1833        gnutls_free(out.data);
     1834    }
     1835
    17841836    return status;
    17851837}
     
    17871839
    17881840
    1789 static apr_status_t load_proxy_x509_credentials(server_rec *s)
     1841static apr_status_t cleanup_proxy_x509_credentials(void *arg)
     1842{
     1843    mgs_srvconf_rec *sc = (mgs_srvconf_rec *) arg;
     1844
     1845    if (sc->proxy_x509_creds)
     1846    {
     1847        /* This implicitly releases the associated trust list
     1848         * sc->proxy_x509_tl, too. */
     1849        gnutls_certificate_free_credentials(sc->proxy_x509_creds);
     1850        sc->proxy_x509_creds = NULL;
     1851        sc->proxy_x509_tl = NULL;
     1852    }
     1853
     1854    if (sc->anon_client_creds)
     1855    {
     1856        gnutls_anon_free_client_credentials(sc->anon_client_creds);
     1857        sc->anon_client_creds = NULL;
     1858    }
     1859
     1860    if (sc->proxy_priorities)
     1861    {
     1862        gnutls_priority_deinit(sc->proxy_priorities);
     1863        sc->proxy_priorities = NULL;
     1864    }
     1865
     1866    return APR_SUCCESS;
     1867}
     1868
     1869
     1870
     1871static apr_status_t load_proxy_x509_credentials(apr_pool_t *pconf,
     1872                                                apr_pool_t *ptemp,
     1873                                                server_rec *s)
    17901874{
    17911875    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
     
    17951879        return APR_EGENERAL;
    17961880
    1797     apr_status_t ret = APR_SUCCESS;
     1881    apr_status_t ret = APR_EINIT;
    17981882    int err = GNUTLS_E_SUCCESS;
     1883
     1884    /* Cleanup function for the GnuTLS structures allocated below */
     1885    apr_pool_cleanup_register(pconf, sc, cleanup_proxy_x509_credentials,
     1886                              apr_pool_cleanup_null);
    17991887
    18001888    /* Function pool, gets destroyed before exit. */
    18011889    apr_pool_t *pool;
    1802     ret = apr_pool_create(&pool, s->process->pool);
     1890    ret = apr_pool_create(&pool, ptemp);
    18031891    if (ret != APR_SUCCESS)
    18041892    {
Note: See TracChangeset for help on using the changeset viewer.