Changeset 0de1839 in mod_gnutls for src/gnutls_hooks.c


Ignore:
Timestamp:
Mar 19, 2015, 8:27:45 AM (5 years ago)
Author:
Thomas Klute <thomas2.klute@…>
Branches:
debian/master, debian/stretch-backports, jessie-backports, master, upstream
Children:
91ccb87
Parents:
10b3370
Message:

Support X.509 auth for TLS proxy connections

This commit adds support for X.509 certificate based authentication for
TLS proxy back end connections, including both server certificate
checking and (optionally) TLS client authentication. Some functions used
for this require GnuTLS 3.1.4 or later, so requirements change
accordingly.

Three new configuration parameters are added:

GnuTLSProxyCAFile FILEPATH

The given file must contain trusted CA certificates for server
verification. Required.

GnuTLSProxyKeyFile FILEPATH
GnuTLSProxyCertificateFile FILEPATH

Key and certificate for TLS client auth towards TLS back end servers. If
not set, TLS client auth is disabled.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/gnutls_hooks.c

    r10b3370 r0de1839  
    5353static const char* mgs_x509_construct_uid(request_rec * pool, gnutls_x509_crt_t cert);
    5454#endif
     55static int load_proxy_x509_credentials(server_rec *s);
    5556
    5657/* Pool Cleanup Function */
     
    457458                continue;
    458459            }
     460        }
     461
     462        if (sc->enabled == GNUTLS_ENABLED_TRUE
     463            && sc->proxy_enabled == GNUTLS_ENABLED_TRUE)
     464        {
     465            load_proxy_x509_credentials(s);
    459466        }
    460467    }
     
    802809            mgs_select_virtual_server_cb);
    803810
     811    /* Set GnuTLS user pointer, so we can access the module session
     812     * context in GnuTLS callbacks */
     813    gnutls_session_set_ptr(ctxt->session, ctxt);
     814
    804815    /* If mod_gnutls is the TLS server, mgs_select_virtual_server_cb
    805816     * will load appropriate credentials during handshake. However,
     
    813824        /* Set x509 credentials */
    814825        gnutls_credentials_set(ctxt->session, GNUTLS_CRD_CERTIFICATE,
    815                                ctxt->sc->certs);
     826                               ctxt->sc->proxy_x509_creds);
    816827        /* Load priorities from the server configuration */
    817828        err = gnutls_priority_set(ctxt->session, ctxt->sc->priorities);
     
    16691680}
    16701681
     1682
     1683
     1684/*
     1685 * Callback to check the server certificate for proxy HTTPS
     1686 * connections, to be used with
     1687 * gnutls_certificate_set_verify_function.
     1688
     1689 * Returns: 0 if certificate check was successful (certificate
     1690 * trusted), non-zero otherwise (error during check or untrusted
     1691 * certificate).
     1692 */
     1693static int gtls_check_server_cert(gnutls_session_t session)
     1694{
     1695    mgs_handle_t *ctxt = (mgs_handle_t *) gnutls_session_get_ptr(session);
     1696    unsigned int status;
     1697
     1698    int err = gnutls_certificate_verify_peers3(session, NULL, &status);
     1699    if (err != GNUTLS_E_SUCCESS)
     1700    {
     1701        ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, ctxt->c,
     1702                      "%s: server certificate check failed: %s (%d)",
     1703                      __func__, gnutls_strerror(err), err);
     1704        return err;
     1705    }
     1706
     1707    gnutls_datum_t * out = gnutls_malloc(sizeof(gnutls_datum_t));
     1708    /* GNUTLS_CRT_X509: ATM, only X509 is supported for proxy certs
     1709     * 0: according to function API, the last argument should be 0 */
     1710    err = gnutls_certificate_verification_status_print(status, GNUTLS_CRT_X509,
     1711                                                       out, 0);
     1712    if (err != GNUTLS_E_SUCCESS)
     1713        ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, ctxt->c,
     1714                      "%s: server verify print failed: %s (%d)",
     1715                      __func__, gnutls_strerror(err), err);
     1716    else
     1717    {
     1718        /* If the certificate is trusted, logging the result is just
     1719         * nice for debugging. But if the back end server provided an
     1720         * untrusted certificate, warn! */
     1721        int level = (status == 0 ? APLOG_DEBUG : APLOG_WARNING);
     1722        ap_log_cerror(APLOG_MARK, level, 0, ctxt->c,
     1723                      "%s: server certificate verify result: %s",
     1724                      __func__, out->data);
     1725    }
     1726
     1727    gnutls_free(out);
     1728    return status;
     1729}
     1730
     1731
     1732
     1733static int load_proxy_x509_credentials(server_rec *s)
     1734{
     1735    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
     1736        ap_get_module_config(s->module_config, &gnutls_module);
     1737
     1738    if (sc == NULL)
     1739        return APR_EGENERAL;
     1740
     1741    int ret = APR_SUCCESS;
     1742    int err = GNUTLS_E_SUCCESS;
     1743    if (sc->proxy_x509_key_file && sc->proxy_x509_cert_file)
     1744    {
     1745        err = gnutls_certificate_set_x509_key_file(sc->proxy_x509_creds,
     1746                                                   sc->proxy_x509_cert_file,
     1747                                                   sc->proxy_x509_key_file,
     1748                                                   GNUTLS_X509_FMT_PEM);
     1749        if (err != GNUTLS_E_SUCCESS)
     1750        {
     1751            ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
     1752                         "%s: loading proxy client credentials failed: %s (%d)",
     1753                         __func__, gnutls_strerror(err), err);
     1754            ret = APR_EGENERAL;
     1755        }
     1756    }
     1757    else if (!sc->proxy_x509_key_file && sc->proxy_x509_cert_file)
     1758    {
     1759        ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
     1760                     "%s: proxy key file not set!", __func__);
     1761        ret = APR_EGENERAL;
     1762    }
     1763    else if (!sc->proxy_x509_cert_file && sc->proxy_x509_key_file)
     1764    {
     1765        ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
     1766                     "%s: proxy certificate file not set!", __func__);
     1767        ret = APR_EGENERAL;
     1768    }
     1769    else
     1770        /* if both key and cert are NULL, client auth is not used */
     1771        ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
     1772                     "%s: no client credentials for proxy", __func__);
     1773
     1774    /* must be set if the server certificate is to be checked */
     1775    if (sc->proxy_x509_ca_file)
     1776    {
     1777        /* returns number of loaded certificates */
     1778        err = gnutls_certificate_set_x509_trust_file(sc->proxy_x509_creds,
     1779                                                     sc->proxy_x509_ca_file,
     1780                                                     GNUTLS_X509_FMT_PEM);
     1781        if (err <= 0)
     1782            ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
     1783                         "%s: proxy CA trust list is empty",
     1784                         __func__);
     1785        else
     1786            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
     1787                         "%s: proxy CA trust list: %d certificates loaded",
     1788                         __func__, err);
     1789    }
     1790    else
     1791        ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
     1792                     "%s: no CA trust list for proxy connections missing, "
     1793                     "TLS connections will fail!", __func__);
     1794
     1795    gnutls_certificate_set_verify_function(sc->proxy_x509_creds,
     1796                                           gtls_check_server_cert);
     1797    return ret;
     1798}
Note: See TracChangeset for help on using the changeset viewer.