Changes in / [d04f7da:2cde026d] in mod_gnutls


Ignore:
Files:
32 added
17 edited

Legend:

Unmodified
Added
Removed
  • .gitignore

    rd04f7da r2cde026d  
    2121m4/ltversion.m4
    2222m4/lt~obsolete.m4
     23docs/mod_gnutls_manual.html
     24docs/mod_gnutls_manual.pdf
  • README

    rd04f7da r2cde026d  
    2222-------------
    2323
    24  * GnuTLS          >= 3.1.3 <http://www.gnutls.org/> (3.2.* preferred)
     24 * GnuTLS          >= 3.1.4 <http://www.gnutls.org/> (3.2.* or newer preferred)
    2525 * Apache HTTPD    >= 2.2 <http://httpd.apache.org/> (2.4.* preferred)
    2626 * autotools & gcc
  • configure.ac

    rd04f7da r2cde026d  
    2828)
    2929
    30 PKG_CHECK_MODULES([LIBGNUTLS], [gnutls >= 3.1.3])
     30PKG_CHECK_MODULES([LIBGNUTLS], [gnutls >= 3.1.4])
    3131
    3232LIBGNUTLS_VERSION=`pkg-config --modversion gnutls`
  • docs/mod_gnutls_manual.mdwn

    rd04f7da r2cde026d  
    153153---------------
    154154
    155 Set to the PEM Encoded Server Certificate
    156 
    157     GnuTLSCertificateFile FILEPATH
    158 
    159 Default: *none*\
    160 Context: server config, virtual host
    161 
    162 Takes an absolute or relative path to the Server Private Key.  This
    163 key cannot currently be password protected.
     155Set to the PEM Encoded Server Private Key
     156
     157    GnuTLSKeyFile FILEPATH
     158
     159Default: *none*\
     160Context: server config, virtual host
     161
     162Takes an absolute or relative path to the Server Private Key. This key
     163cannot currently be password protected.
    164164
    165165**Security Warning:**\
     
    422422With GnuTLSExportCertificates enabled, `mod_gnutls` exports the same
    423423environment variables to the CGI process as `mod_ssl`.
     424
     425
     426`SSLProxyEngine`
     427--------------
     428
     429Enable TLS proxy connections for this virtual host
     430
     431    SSLProxyEngine [on|off]
     432
     433Default: *off*\
     434Context: virtual host
     435
     436This directive enables support for TLS proxy connections for a virtual
     437host.
     438
     439`GnuTLSProxyCAFile`
     440--------------------
     441
     442Set to the PEM encoded Certificate Authority Certificate
     443
     444    GnuTLSProxyCAFile FILEPATH
     445
     446Default: *none*\
     447Context: server config, virtual host
     448
     449Takes an absolute or relative path to a PEM encoded certificate to use
     450as a Certificate Authority when verifying certificates provided by
     451proxy back end servers. This file may contain a list of trusted
     452authorities. If not set, verification of TLS back end servers will
     453always fail due to lack of a trusted CA.
     454
     455`GnuTLSProxyCRLFile`
     456--------------------
     457
     458Set to the PEM encoded Certificate Revocation List
     459
     460    GnuTLSProxyCRLFile FILEPATH
     461
     462Default: *none*\
     463Context: server config, virtual host
     464
     465Takes an absolute or relative path to a PEM encoded Certificate
     466Revocation List to use when verifying certificates provided by proxy
     467back end servers. The file may contain a list of CRLs.
     468
     469`GnuTLSProxyCertificateFile`
     470-----------------------
     471
     472Set to the PEM encoded Client Certificate
     473
     474    GnuTLSProxyCertificateFile FILEPATH
     475
     476Default: *none*\
     477Context: server config, virtual host
     478
     479Takes an absolute or relative path to a PEM encoded X.509 certificate
     480to use as this Server's End Entity (EE) client certificate for TLS
     481client authentication in proxy TLS connections. If you need to supply
     482certificates for intermediate Certificate Authorities (iCAs), they
     483should be listed in sequence in the file, from EE to the iCA closest
     484to the root CA. Optionally, you can also include the root CA's
     485certificate as the last certificate in the list.
     486
     487If not set, TLS client authentication will be disabled for TLS proxy
     488connections. If set, `GnuTLSProxyKeyFile` must be set as well to
     489provide the matching private key.
     490
     491`GnuTLSProxyKeyFile`
     492---------------
     493
     494Set to the PEM encoded Private Key
     495
     496    GnuTLSProxyKeyFile FILEPATH
     497
     498Default: *none*\
     499Context: server config, virtual host
     500
     501Takes an absolute or relative path to the Private Key matching the
     502certificate configured using the `GnuTLSProxyCertificateFile`
     503directive. This key cannot currently be password protected.
     504
     505**Security Warning:**\
     506This private key must be protected. It is read while Apache is still
     507running as root, and does not need to be readable by the nobody or
     508apache user.
     509
     510`GnuTLSProxyPriorities`
     511------------------
     512
     513Set the allowed ciphers, key exchange algorithms, MACs and compression
     514methods for proxy connections
     515
     516    GnuTLSProxyPriorities NORMAL:+CIPHER_0:+CIPHER_1:...:+CIPHER_N
     517
     518Default: *none*\
     519Context: server config, virtual host
     520
     521This option is used to set the allowed ciphers, key exchange
     522algorithms, MACs and compression methods for proxy connections. It
     523takes the same parameters as `GnuTLSPriorities`. Required if
     524`SSLProxyEngine` is `On`.
    424525
    425526* * * * *
  • include/mod_gnutls.h.in

    rd04f7da r2cde026d  
    145145    /* --- Things initialized at _child_init --- */
    146146
    147         /* x509 Certificate Structure */
     147    /* x509 Certificate Structure */
    148148    gnutls_certificate_credentials_t certs;
    149         /* SRP Certificate Structure*/
     149    /* x509 credentials for proxy connections */
     150    gnutls_certificate_credentials_t proxy_x509_creds;
     151    /* trust list for proxy_x509_creds */
     152    gnutls_x509_trust_list_t proxy_x509_tl;
     153    const char* proxy_x509_key_file;
     154    const char* proxy_x509_cert_file;
     155    const char* proxy_x509_ca_file;
     156    const char* proxy_x509_crl_file;
     157    /* GnuTLS priorities for proxy connections */
     158    gnutls_priority_t proxy_priorities;
     159    /* SRP Certificate Structure*/
    150160    gnutls_srp_server_credentials_t srp_creds;
    151         /* Annonymous Certificate Structure */
     161    /* Anonymous Certificate Structure */
    152162    gnutls_anon_server_credentials_t anon_creds;
     163    /* Anonymous Client Certificate Structure, used for proxy
     164     * connections */
     165    gnutls_anon_client_credentials_t anon_client_creds;
    153166        /* Current x509 Certificate CN [Common Name] */
    154167    char* cert_cn;
     
    212225        /* Is TLS enabled for this connection? */
    213226    int enabled;
     227    /* Is this a proxy connection? */
     228    int is_proxy;
    214229        /* GnuTLS Session handle */
    215230    gnutls_session_t session;
     
    435450mgs_srvconf_rec* mgs_find_sni_server(gnutls_session_t session);
    436451
     452const char *mgs_store_cred_path(cmd_parms * parms,
     453                                void *dummy __attribute__((unused)),
     454                                const char *arg);
     455
    437456/* mod_gnutls Hooks. */
    438457
  • src/gnutls_config.c

    rd04f7da r2cde026d  
    883883}
    884884
    885 const char *mgs_set_priorities(cmd_parms * parms, void *dummy __attribute__((unused)), const char *arg)
     885
     886
     887/*
     888 * Initialize a GnuTLS priorities cache from a configuration
     889 * string. Used for GnuTLSPriorities and GnuTLSProxyPriorities.
     890 */
     891const char *mgs_set_priorities(cmd_parms * parms,
     892                               void *dummy __attribute__((unused)),
     893                               const char *arg)
    886894{
     895    int ret;
     896    const char *err;
     897
    887898    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
    888         ap_get_module_config(parms->server->module_config, &gnutls_module);
    889 
    890     sc->priorities_str = apr_pstrdup(parms->pool, arg);
    891 
    892     return NULL;
    893 }
     899        ap_get_module_config(parms->server->module_config, &gnutls_module);
     900
     901    /* Setting a priority cache works the same no matter for which
     902     * option. Just point the pointer at the right one. */
     903    gnutls_priority_t *prio = NULL;
     904    if (!strcasecmp(parms->directive->directive, "GnuTLSPriorities"))
     905    {
     906        /* save string to be handled in mgs_load_files
     907         *
     908         * TODO: return to one wany of handling priorities for front
     909         * end and proxy connections */
     910        sc->priorities_str = apr_pstrdup(parms->pool, arg);
     911        return NULL;
     912        /* prio = &sc->priorities; */
     913    }
     914    else if (!strcasecmp(parms->directive->directive, "GnuTLSProxyPriorities"))
     915        prio = &sc->proxy_priorities;
     916    else
     917        /* Can't happen unless there's a serious bug in mod_gnutls or Apache */
     918        return apr_psprintf(parms->pool,
     919                            "mod_gnutls: %s called for invalid option '%s'",
     920                            __func__, parms->directive->directive);
     921
     922    ret = gnutls_priority_init(prio, arg, &err);
     923    if (ret < 0)
     924    {
     925        if (ret == GNUTLS_E_INVALID_REQUEST)
     926            return apr_psprintf(parms->pool,
     927                                "mod_gnutls: Syntax error parsing priorities "
     928                                "string for %s at: %s",
     929                                parms->directive->directive, err);
     930        return  apr_psprintf(parms->pool,
     931                             "Error setting priorities: %s (%d)",
     932                             gnutls_strerror(ret), ret);
     933    }
     934
     935    return NULL;
     936}
     937
     938
    894939
    895940const char *mgs_set_pin(cmd_parms * parms, void *dummy __attribute__((unused)),
     
    918963}
    919964
     965
     966
    920967static mgs_srvconf_rec *_mgs_config_server_create(apr_pool_t * p,
    921968                                                  char **err __attribute__((unused)))
     
    925972    sc->enabled = GNUTLS_ENABLED_UNSET;
    926973
    927 
    928974    sc->privkey_x509 = NULL;
    929975    sc->privkey_pgp = NULL;
    930976    sc->certs_x509_chain_num = 0;
     977    sc->pin = NULL;
     978    sc->priorities_str = NULL;
    931979    sc->cache_timeout = -1;     /* -1 means "unset" */
    932980    sc->cache_type = mgs_cache_unset;
     
    939987    sc->client_verify_method = mgs_cvm_unset;
    940988
     989    sc->proxy_x509_key_file = NULL;
     990    sc->proxy_x509_cert_file = NULL;
     991    sc->proxy_x509_ca_file = NULL;
     992    sc->proxy_x509_crl_file = NULL;
     993    sc->proxy_priorities = NULL;
     994
    941995/* this relies on GnuTLS never changing the gnutls_certificate_request_t enum to define -1 */
    942996    sc->client_verify_mode = -1;
     
    9871041    gnutls_srvconf_merge(priorities_str, NULL);
    9881042
     1043    gnutls_srvconf_merge(proxy_x509_key_file, NULL);
     1044    gnutls_srvconf_merge(proxy_x509_cert_file, NULL);
     1045    gnutls_srvconf_merge(proxy_x509_ca_file, NULL);
     1046    gnutls_srvconf_merge(proxy_x509_crl_file, NULL);
     1047    gnutls_srvconf_merge(proxy_priorities, NULL);
     1048
    9891049    /* FIXME: the following items are pre-allocated, and should be
    9901050     * properly disposed of before assigning in order to avoid leaks;
    9911051     * so at the moment, we can't actually have them in the config.
    9921052     * what happens during de-allocation? */
     1053    /* TODO: mgs_load_files takes care of most of these now, verify
     1054     * and clean up the following lines */
    9931055    gnutls_srvconf_assign(ca_list);
    9941056    gnutls_srvconf_assign(ca_list_size);
     
    10331095    return dc;
    10341096}
     1097
     1098
     1099
     1100/*
     1101 * Store paths to proxy credentials
     1102 *
     1103 * This function copies the paths provided in the configuration file
     1104 * into the server configuration. The post configuration hook takes
     1105 * care of actually loading the credentials, which means than invalid
     1106 * paths or the like will be detected there.
     1107 */
     1108const char *mgs_store_cred_path(cmd_parms * parms,
     1109                                void *dummy __attribute__((unused)),
     1110                                const char *arg)
     1111{
     1112    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
     1113        ap_get_module_config(parms->server->module_config, &gnutls_module);
     1114
     1115    /* parms->directive->directive contains the directive string */
     1116    if (!strcasecmp(parms->directive->directive, "GnuTLSProxyKeyFile"))
     1117        sc->proxy_x509_key_file = apr_pstrdup(parms->pool, arg);
     1118    else if (!strcasecmp(parms->directive->directive,
     1119                         "GnuTLSProxyCertificateFile"))
     1120        sc->proxy_x509_cert_file = apr_pstrdup(parms->pool, arg);
     1121    else if (!strcasecmp(parms->directive->directive, "GnuTLSProxyCAFile"))
     1122        sc->proxy_x509_ca_file = apr_pstrdup(parms->pool, arg);
     1123    else if (!strcasecmp(parms->directive->directive, "GnuTLSProxyCRLFile"))
     1124        sc->proxy_x509_crl_file = apr_pstrdup(parms->pool, arg);
     1125    return NULL;
     1126}
  • src/gnutls_hooks.c

    rd04f7da r2cde026d  
    4040#endif
    4141
     42#define IS_PROXY_STR(c) \
     43    ((c->is_proxy == GNUTLS_ENABLED_TRUE) ? "proxy " : "")
     44
    4245static gnutls_datum_t session_ticket_key = {NULL, 0};
    4346
     
    5053static const char* mgs_x509_construct_uid(request_rec * pool, gnutls_x509_crt_t cert);
    5154#endif
     55static int load_proxy_x509_credentials(server_rec *s);
    5256
    5357/* Pool Cleanup Function */
     
    147151    gnutls_certificate_server_set_request(session, ctxt->sc->client_verify_mode);
    148152
     153    /* Set x509 credentials */
     154    gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, ctxt->sc->certs);
    149155    /* Set Anon credentials */
    150     gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, ctxt->sc->certs);
    151         /* Set x509 credentials */
    152156    gnutls_credentials_set(session, GNUTLS_CRD_ANON, ctxt->sc->anon_creds);
    153157
     
    408412                continue;
    409413            }
     414        }
     415
     416        if (sc->enabled == GNUTLS_ENABLED_TRUE
     417            && sc->proxy_enabled == GNUTLS_ENABLED_TRUE)
     418        {
     419            /* Check if the proxy priorities have been set */
     420            if (sc->proxy_priorities == NULL)
     421            {
     422                ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
     423                             "Host '%s:%d' is missing the "
     424                             "GnuTLSProxyPriorities directive!",
     425                             s->server_hostname, s->port);
     426                exit(-1);
     427            }
     428            /* Set up proxy credentials */
     429            load_proxy_x509_credentials(s);
    410430        }
    411431    }
     
    583603#endif
    584604
    585 mgs_srvconf_rec *mgs_find_sni_server(gnutls_session_t session) {
     605mgs_srvconf_rec *mgs_find_sni_server(gnutls_session_t session)
     606{
    586607    int rv;
    587608    unsigned int sni_type;
     
    634655
    635656        tsc = (mgs_srvconf_rec *) ap_get_module_config(s->module_config,
    636                 &gnutls_module);
     657                                                       &gnutls_module);
    637658
    638659        if (tsc->enabled != GNUTLS_ENABLED_TRUE) { continue; }
    639660
    640                                 if(check_server_aliases(x, s, tsc)) {
    641                                         return tsc;
    642                                 }
     661        if(check_server_aliases(x, s, tsc)) {
     662            return tsc;
     663        }
     664    }
    643665#endif
    644666    return NULL;
     667}
     668
     669/*
     670 * This function is intended as a cleanup handler for connections
     671 * using GnuTLS.
     672 *
     673 * @param data must point to the mgs_handle_t associated with the
     674 * connection
     675 */
     676static apr_status_t cleanup_gnutls_session(void *data)
     677{
     678    /* nothing to do */
     679    if (data == NULL)
     680        return APR_SUCCESS;
     681
     682    /* check if session needs closing */
     683    mgs_handle_t *ctxt = (mgs_handle_t *) data;
     684    if (ctxt->session != NULL)
     685    {
     686        int ret;
     687        /* Try A Clean Shutdown */
     688        do
     689            ret = gnutls_bye(ctxt->session, GNUTLS_SHUT_WR);
     690        while (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN);
     691        if (ret != GNUTLS_E_SUCCESS)
     692            ap_log_cerror(APLOG_MARK, APLOG_INFO, ret, ctxt->c,
     693                          "%s: error while closing TLS %sconnection: %s (%d)",
     694                          __func__, IS_PROXY_STR(ctxt),
     695                          gnutls_strerror(ret), ret);
     696        else
     697            ap_log_cerror(APLOG_MARK, APLOG_DEBUG, ret, ctxt->c,
     698                          "%s: TLS %sconnection closed.",
     699                          __func__, IS_PROXY_STR(ctxt));
     700        /* De-Initialize Session */
     701        gnutls_deinit(ctxt->session);
     702        ctxt->session = NULL;
     703    }
     704    return APR_SUCCESS;
    645705}
    646706
     
    657717    if (ctxt == NULL)
    658718    {
    659         ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, "%s: allocating connection memory", __func__);
    660719        ctxt = apr_pcalloc(c->pool, sizeof (*ctxt));
    661720        ap_set_module_config(c->conn_config, &gnutls_module, ctxt);
     721        ctxt->is_proxy = GNUTLS_ENABLED_FALSE;
    662722    }
    663723    ctxt->enabled = GNUTLS_ENABLED_TRUE;
     
    674734
    675735    /* Initialize GnuTLS Library */
    676     int err = gnutls_init(&ctxt->session, GNUTLS_SERVER);
    677     if (err != GNUTLS_E_SUCCESS)
    678         ap_log_cerror(APLOG_MARK, APLOG_ERR, err, c, "gnutls_init failed!");
    679     /* Initialize Session Tickets */
    680     if (session_ticket_key.data != NULL && ctxt->sc->tickets != 0) {
    681         err = gnutls_session_ticket_enable_server(ctxt->session, &session_ticket_key);
     736    int err = 0;
     737    if (ctxt->is_proxy == GNUTLS_ENABLED_TRUE)
     738    {
     739        /* this is an outgoing proxy connection, client mode */
     740        err = gnutls_init(&ctxt->session, GNUTLS_CLIENT);
    682741        if (err != GNUTLS_E_SUCCESS)
    683             ap_log_cerror(APLOG_MARK, APLOG_ERR, err, c, "gnutls_session_ticket_enable_server failed!");
     742            ap_log_cerror(APLOG_MARK, APLOG_ERR, err, c,
     743                          "gnutls_init for proxy connection failed: %s (%d)",
     744                          gnutls_strerror(err), err);
     745        err = gnutls_session_ticket_enable_client(ctxt->session);
     746        if (err != GNUTLS_E_SUCCESS)
     747            ap_log_cerror(APLOG_MARK, APLOG_ERR, err, c,
     748                          "gnutls_session_ticket_enable_client failed: %s (%d)",
     749                          gnutls_strerror(err), err);
     750        /* Try to close and deinit the session when the connection
     751         * pool is cleared. Note that mod_proxy might not close
     752         * connections immediately, if you need that, look at the
     753         * "proxy-nokeepalive" environment variable for
     754         * mod_proxy_http. */
     755        apr_pool_pre_cleanup_register(c->pool, ctxt, cleanup_gnutls_session);
     756    }
     757    else
     758    {
     759        /* incoming connection, server mode */
     760        err = gnutls_init(&ctxt->session, GNUTLS_SERVER);
     761        if (err != GNUTLS_E_SUCCESS)
     762            ap_log_cerror(APLOG_MARK, APLOG_ERR, err, c,
     763                          "gnutls_init for server side failed: %s (%d)",
     764                          gnutls_strerror(err), err);
     765        /* Initialize Session Tickets */
     766        if (session_ticket_key.data != NULL && ctxt->sc->tickets != 0)
     767        {
     768            err = gnutls_session_ticket_enable_server(ctxt->session, &session_ticket_key);
     769            if (err != GNUTLS_E_SUCCESS)
     770                ap_log_cerror(APLOG_MARK, APLOG_ERR, err, c,
     771                              "gnutls_session_ticket_enable_server failed: %s (%d)",
     772                              gnutls_strerror(err), err);
     773        }
    684774    }
    685775
     
    691781    gnutls_handshake_set_post_client_hello_function(ctxt->session,
    692782            mgs_select_virtual_server_cb);
     783
     784    /* Set GnuTLS user pointer, so we can access the module session
     785     * context in GnuTLS callbacks */
     786    gnutls_session_set_ptr(ctxt->session, ctxt);
     787
     788    /* If mod_gnutls is the TLS server, mgs_select_virtual_server_cb
     789     * will load appropriate credentials during handshake. However,
     790     * when handling a proxy backend connection, mod_gnutls acts as
     791     * TLS client and credentials must be loaded here. */
     792    if (ctxt->is_proxy == GNUTLS_ENABLED_TRUE)
     793    {
     794        /* Set anonymous client credentials for proxy connections */
     795        gnutls_credentials_set(ctxt->session, GNUTLS_CRD_ANON,
     796                               ctxt->sc->anon_client_creds);
     797        /* Set x509 credentials */
     798        gnutls_credentials_set(ctxt->session, GNUTLS_CRD_CERTIFICATE,
     799                               ctxt->sc->proxy_x509_creds);
     800        /* Load priorities from the server configuration */
     801        err = gnutls_priority_set(ctxt->session, ctxt->sc->proxy_priorities);
     802        if (err != GNUTLS_E_SUCCESS)
     803            ap_log_cerror(APLOG_MARK, APLOG_ERR, err, c,
     804                          "%s: setting priorities for proxy connection "
     805                          "failed: %s (%d)",
     806                          __func__, gnutls_strerror(err), err);
     807    }
     808
    693809    /* Initialize Session Cache */
    694810    mgs_cache_session_init(ctxt);
     
    716832        ap_get_module_config(c->conn_config, &gnutls_module);
    717833
    718     if ((sc && (!sc->enabled || sc->proxy_enabled == GNUTLS_ENABLED_TRUE))
    719         || (ctxt && ctxt->enabled == GNUTLS_ENABLED_FALSE))
     834    if ((sc && (!sc->enabled)) || (ctxt && ctxt->enabled == GNUTLS_ENABLED_FALSE))
    720835    {
    721836        ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, "%s declined connection",
     
    15391654}
    15401655
     1656
     1657
     1658/*
     1659 * Callback to check the server certificate for proxy HTTPS
     1660 * connections, to be used with
     1661 * gnutls_certificate_set_verify_function.
     1662
     1663 * Returns: 0 if certificate check was successful (certificate
     1664 * trusted), non-zero otherwise (error during check or untrusted
     1665 * certificate).
     1666 */
     1667static int gtls_check_server_cert(gnutls_session_t session)
     1668{
     1669    mgs_handle_t *ctxt = (mgs_handle_t *) gnutls_session_get_ptr(session);
     1670    unsigned int status;
     1671
     1672    /* Get peer hostname from a note left by mod_proxy */
     1673    const char *peer_hostname =
     1674        apr_table_get(ctxt->c->notes, "proxy-request-hostname");
     1675    if (peer_hostname == NULL)
     1676        ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, ctxt->c,
     1677                      "%s: proxy-request-hostname is NULL, cannot check "
     1678                      "peer's hostname", __func__);
     1679
     1680    /* Verify certificate, including hostname match. Should
     1681     * peer_hostname be NULL for some reason, the name is not
     1682     * checked. */
     1683    int err = gnutls_certificate_verify_peers3(session, peer_hostname,
     1684                                               &status);
     1685    if (err != GNUTLS_E_SUCCESS)
     1686    {
     1687        ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, ctxt->c,
     1688                      "%s: server certificate check failed: %s (%d)",
     1689                      __func__, gnutls_strerror(err), err);
     1690        return err;
     1691    }
     1692
     1693    gnutls_datum_t * out = gnutls_malloc(sizeof(gnutls_datum_t));
     1694    /* GNUTLS_CRT_X509: ATM, only X509 is supported for proxy certs
     1695     * 0: according to function API, the last argument should be 0 */
     1696    err = gnutls_certificate_verification_status_print(status, GNUTLS_CRT_X509,
     1697                                                       out, 0);
     1698    if (err != GNUTLS_E_SUCCESS)
     1699        ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, ctxt->c,
     1700                      "%s: server verify print failed: %s (%d)",
     1701                      __func__, gnutls_strerror(err), err);
     1702    else
     1703    {
     1704        /* If the certificate is trusted, logging the result is just
     1705         * nice for debugging. But if the back end server provided an
     1706         * untrusted certificate, warn! */
     1707        int level = (status == 0 ? APLOG_DEBUG : APLOG_WARNING);
     1708        ap_log_cerror(APLOG_MARK, level, 0, ctxt->c,
     1709                      "%s: server certificate verify result: %s",
     1710                      __func__, out->data);
     1711    }
     1712
     1713    gnutls_free(out);
     1714    return status;
     1715}
     1716
     1717
     1718
     1719static apr_status_t load_proxy_x509_credentials(server_rec *s)
     1720{
     1721    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
     1722        ap_get_module_config(s->module_config, &gnutls_module);
     1723
     1724    if (sc == NULL)
     1725        return APR_EGENERAL;
     1726
     1727    apr_status_t ret = APR_SUCCESS;
     1728    int err = GNUTLS_E_SUCCESS;
     1729
     1730    /* Function pool, gets destroyed before exit. */
     1731    apr_pool_t *pool;
     1732    ret = apr_pool_create(&pool, s->process->pool);
     1733    if (ret != APR_SUCCESS)
     1734    {
     1735        ap_log_error(APLOG_MARK, APLOG_ERR, ret, s,
     1736                     "%s: failed to allocate function memory pool.", __func__);
     1737        return ret;
     1738    }
     1739
     1740    /* allocate credentials structures */
     1741    err = gnutls_certificate_allocate_credentials(&sc->proxy_x509_creds);
     1742    if (err != GNUTLS_E_SUCCESS)
     1743    {
     1744        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
     1745                     "%s: Failed to initialize proxy credentials: (%d) %s",
     1746                     __func__, err, gnutls_strerror(err));
     1747        return APR_EGENERAL;
     1748    }
     1749    err = gnutls_anon_allocate_client_credentials(&sc->anon_client_creds);
     1750    if (err != GNUTLS_E_SUCCESS)
     1751    {
     1752        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
     1753                     "%s: Failed to initialize anon credentials for proxy: "
     1754                     "(%d) %s", __func__, err, gnutls_strerror(err));
     1755        return APR_EGENERAL;
     1756    }
     1757
     1758    /* load certificate and key for client auth, if configured */
     1759    if (sc->proxy_x509_key_file && sc->proxy_x509_cert_file)
     1760    {
     1761        char* cert_file = ap_server_root_relative(pool,
     1762                                                  sc->proxy_x509_cert_file);
     1763        char* key_file = ap_server_root_relative(pool,
     1764                                                 sc->proxy_x509_key_file);
     1765        err = gnutls_certificate_set_x509_key_file(sc->proxy_x509_creds,
     1766                                                   cert_file,
     1767                                                   key_file,
     1768                                                   GNUTLS_X509_FMT_PEM);
     1769        if (err != GNUTLS_E_SUCCESS)
     1770        {
     1771            ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
     1772                         "%s: loading proxy client credentials failed: %s (%d)",
     1773                         __func__, gnutls_strerror(err), err);
     1774            ret = APR_EGENERAL;
     1775        }
     1776    }
     1777    else if (!sc->proxy_x509_key_file && sc->proxy_x509_cert_file)
     1778    {
     1779        ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
     1780                     "%s: proxy key file not set!", __func__);
     1781        ret = APR_EGENERAL;
     1782    }
     1783    else if (!sc->proxy_x509_cert_file && sc->proxy_x509_key_file)
     1784    {
     1785        ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
     1786                     "%s: proxy certificate file not set!", __func__);
     1787        ret = APR_EGENERAL;
     1788    }
     1789    else
     1790        /* if both key and cert are NULL, client auth is not used */
     1791        ap_log_error(APLOG_MARK, APLOG_INFO, 0, s,
     1792                     "%s: no client credentials for proxy", __func__);
     1793
     1794    /* must be set if the server certificate is to be checked */
     1795    if (sc->proxy_x509_ca_file)
     1796    {
     1797        /* initialize the trust list */
     1798        err = gnutls_x509_trust_list_init(&sc->proxy_x509_tl, 0);
     1799        if (err != GNUTLS_E_SUCCESS)
     1800        {
     1801            ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
     1802                         "%s: gnutls_x509_trust_list_init failed: %s (%d)",
     1803                         __func__, gnutls_strerror(err), err);
     1804            ret = APR_EGENERAL;
     1805        }
     1806
     1807        char* ca_file = ap_server_root_relative(pool,
     1808                                                sc->proxy_x509_ca_file);
     1809        /* if no CRL is used, sc->proxy_x509_crl_file is NULL */
     1810        char* crl_file = NULL;
     1811        if (sc->proxy_x509_crl_file)
     1812            crl_file = ap_server_root_relative(pool,
     1813                                               sc->proxy_x509_crl_file);
     1814
     1815        /* returns number of loaded elements */
     1816        err = gnutls_x509_trust_list_add_trust_file(sc->proxy_x509_tl,
     1817                                                    ca_file,
     1818                                                    crl_file,
     1819                                                    GNUTLS_X509_FMT_PEM,
     1820                                                    0 /* tl_flags */,
     1821                                                    0 /* tl_vflags */);
     1822        if (err > 0)
     1823            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
     1824                         "%s: proxy CA trust list: %d structures loaded",
     1825                         __func__, err);
     1826        else if (err == 0)
     1827            ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
     1828                         "%s: proxy CA trust list is empty (%d)",
     1829                         __func__, err);
     1830        else /* err < 0 */
     1831        {
     1832            ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
     1833                         "%s: error loading proxy CA trust list: %s (%d)",
     1834                         __func__, gnutls_strerror(err), err);
     1835            ret = APR_EGENERAL;
     1836        }
     1837
     1838        /* attach trust list to credentials */
     1839        gnutls_certificate_set_trust_list(sc->proxy_x509_creds,
     1840                                          sc->proxy_x509_tl, 0);
     1841    }
     1842    else
     1843        ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
     1844                     "%s: no CA trust list for proxy connections, "
     1845                     "TLS connections will fail!", __func__);
     1846
     1847    gnutls_certificate_set_verify_function(sc->proxy_x509_creds,
     1848                                           gtls_check_server_cert);
     1849    apr_pool_destroy(pool);
     1850    return ret;
     1851}
  • src/gnutls_io.c

    rd04f7da r2cde026d  
    3838                               alloc)
    3939
     40#define IS_PROXY_STR(c) \
     41    ((c->is_proxy == GNUTLS_ENABLED_TRUE) ? "proxy " : "")
     42
    4043static apr_status_t gnutls_io_filter_error(ap_filter_t * f,
    4144        apr_bucket_brigade * bb,
     
    4548
    4649    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;
     50    case HTTP_BAD_REQUEST:
     51        /* log the situation */
     52        ap_log_error(APLOG_MARK, APLOG_INFO, 0,
     53                     f->c->base_server,
     54                     "GnuTLS handshake failed: HTTP spoken on HTTPS port; "
     55                     "trying to send HTML error page");
     56        mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
     57            ap_get_module_config(f->c->base_server->module_config,
     58                                 &gnutls_module);
     59        ctxt->status = -1;
     60        sc->non_ssl_request = 1;
     61
     62        /* fake the request line */
     63        bucket = HTTP_ON_HTTPS_PORT_BUCKET(f->c->bucket_alloc);
     64        break;
     65
     66    default:
     67        return status;
    6768    }
    6869
     
    186187
    187188static apr_status_t gnutls_io_input_read(mgs_handle_t * ctxt,
    188         char *buf, apr_size_t * len) {
     189        char *buf, apr_size_t * len)
     190{
    189191    apr_size_t wanted = *len;
    190192    apr_size_t bytes = 0;
     
    225227
    226228    if (ctxt->session == NULL) {
     229        ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, ctxt->c,
     230                      "%s: GnuTLS session is NULL!", __func__);
    227231        return APR_EGENERAL;
    228232    }
     
    230234    while (1) {
    231235
    232         rc = gnutls_record_recv(ctxt->session, buf + bytes,
    233                 wanted - bytes);
     236        do
     237            rc = gnutls_record_recv(ctxt->session, buf + bytes,
     238                                    wanted - bytes);
     239        while (rc == GNUTLS_E_INTERRUPTED || rc == GNUTLS_E_AGAIN);
    234240
    235241        if (rc > 0) {
     
    270276            if (rc == GNUTLS_E_REHANDSHAKE) {
    271277                /* A client has asked for a new Hankshake. Currently, we don't do it */
    272                 ap_log_error(APLOG_MARK, APLOG_INFO,
     278                ap_log_cerror(APLOG_MARK, APLOG_INFO,
    273279                        ctxt->input_rc,
    274                         ctxt->c->base_server,
     280                        ctxt->c,
    275281                        "GnuTLS: Error reading data. Client Requested a New Handshake."
    276282                        " (%d) '%s'", rc,
     
    278284            } else if (rc == GNUTLS_E_WARNING_ALERT_RECEIVED) {
    279285                rc = gnutls_alert_get(ctxt->session);
    280                 ap_log_error(APLOG_MARK, APLOG_INFO,
     286                ap_log_cerror(APLOG_MARK, APLOG_INFO,
    281287                        ctxt->input_rc,
    282                         ctxt->c->base_server,
     288                        ctxt->c,
    283289                        "GnuTLS: Warning Alert From Client: "
    284290                        " (%d) '%s'", rc,
     
    286292            } else if (rc == GNUTLS_E_FATAL_ALERT_RECEIVED) {
    287293                rc = gnutls_alert_get(ctxt->session);
    288                 ap_log_error(APLOG_MARK, APLOG_INFO,
     294                ap_log_cerror(APLOG_MARK, APLOG_INFO,
    289295                        ctxt->input_rc,
    290                         ctxt->c->base_server,
     296                        ctxt->c,
    291297                        "GnuTLS: Fatal Alert From Client: "
    292298                        "(%d) '%s'", rc,
     
    297303                /* Some Other Error. Report it. Die. */
    298304                if (gnutls_error_is_fatal(rc)) {
    299                     ap_log_error(APLOG_MARK,
     305                    ap_log_cerror(APLOG_MARK,
    300306                            APLOG_INFO,
    301307                            ctxt->input_rc,
    302                             ctxt->c->base_server,
     308                            ctxt->c,
    303309                            "GnuTLS: Error reading data. (%d) '%s'",
    304310                            rc,
     
    311317
    312318            if (ctxt->input_rc == APR_SUCCESS) {
     319                ap_log_cerror(APLOG_MARK, APLOG_INFO, ctxt->input_rc, ctxt->c,
     320                              "%s: GnuTLS error: %s (%d)",
     321                              __func__, gnutls_strerror(rc), rc);
    313322                ctxt->input_rc = APR_EGENERAL;
    314323            }
     
    405414            ap_log_error(APLOG_MARK, APLOG_INFO, 0,
    406415                    ctxt->c->base_server,
    407                     "GnuTLS: Hanshake Alert (%d) '%s'.",
     416                    "GnuTLS: Handshake Alert (%d) '%s'.",
    408417                    errcode,
    409418                    gnutls_alert_get_name(errcode));
     
    449458            }
    450459        }
    451         return 0;
     460        return GNUTLS_E_SUCCESS;
    452461    }
    453462}
     
    479488        apr_bucket_brigade * bb,
    480489        ap_input_mode_t mode,
    481         apr_read_type_e block, apr_off_t readbytes) {
     490        apr_read_type_e block, apr_off_t readbytes)
     491{
    482492    apr_status_t status = APR_SUCCESS;
    483493    mgs_handle_t *ctxt = (mgs_handle_t *) f->ctx;
     
    488498                apr_bucket_eos_create(f->c->bucket_alloc);
    489499        APR_BRIGADE_INSERT_TAIL(bb, bucket);
     500        ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, ctxt->c,
     501                      "%s: %sconnection aborted",
     502                      __func__, IS_PROXY_STR(ctxt));
    490503        return APR_ECONNABORTED;
    491504    }
    492505
    493506    if (ctxt->status == 0) {
    494         gnutls_do_handshake(ctxt);
     507        int ret = gnutls_do_handshake(ctxt);
     508        if (ret == GNUTLS_E_SUCCESS)
     509            ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, ctxt->c,
     510                          "%s: TLS %sconnection opened.",
     511                          __func__, IS_PROXY_STR(ctxt));
    495512    }
    496513
    497514    if (ctxt->status < 0) {
     515        ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, ctxt->c,
     516                      "%s %s: ap_get_brigade", __func__, IS_PROXY_STR(ctxt));
    498517        return ap_get_brigade(f->next, bb, mode, block, readbytes);
    499518    }
     
    588607
    589608    if (ctxt->status == 0) {
    590         gnutls_do_handshake(ctxt);
     609        ret = gnutls_do_handshake(ctxt);
     610        if (ret == GNUTLS_E_SUCCESS)
     611            ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, ctxt->c,
     612                          "%s: TLS %sconnection opened.",
     613                          __func__, IS_PROXY_STR(ctxt));
    591614    }
    592615
     
    615638                    ret = gnutls_bye(ctxt->session, GNUTLS_SHUT_WR);
    616639                } while (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN);
     640                ap_log_cerror(APLOG_MARK, APLOG_DEBUG, ret, ctxt->c,
     641                              "%s: TLS %sconnection closed.",
     642                              __func__, IS_PROXY_STR(ctxt));
    617643                /* De-Initialize Session */
    618644                gnutls_deinit(ctxt->session);
  • src/mod_gnutls.c

    rd04f7da r2cde026d  
    2828    /* Try Run Post-Config Hook After mod_proxy */
    2929    static const char * const aszPre[] = { "mod_proxy.c", NULL };
    30     ap_hook_post_config(mgs_hook_post_config, aszPre, NULL,APR_HOOK_REALLY_LAST);
     30    ap_hook_post_config(mgs_hook_post_config, aszPre, NULL,
     31                        APR_HOOK_REALLY_LAST);
    3132    /* HTTP Scheme Hook */
    3233#if USING_2_1_RECENT
     
    3637#endif
    3738    /* Default Port Hook */
    38     ap_hook_default_port(mgs_hook_default_port,  NULL,NULL, APR_HOOK_MIDDLE);
     39    ap_hook_default_port(mgs_hook_default_port, NULL, NULL, APR_HOOK_MIDDLE);
    3940    /* Pre-Connect Hook */
    40     ap_hook_pre_connection(mgs_hook_pre_connection, NULL, NULL, APR_HOOK_MIDDLE);
     41    ap_hook_pre_connection(mgs_hook_pre_connection, NULL, NULL,
     42                           APR_HOOK_MIDDLE);
    4143    /* Pre-Config Hook */
    4244    ap_hook_pre_config(mgs_hook_pre_config, NULL, NULL,
    43             APR_HOOK_MIDDLE);
     45                       APR_HOOK_MIDDLE);
    4446    /* Child-Init Hook */
    4547    ap_hook_child_init(mgs_hook_child_init, NULL, NULL,
    46             APR_HOOK_MIDDLE);
     48                       APR_HOOK_MIDDLE);
    4749    /* Authentication Hook */
    4850    ap_hook_access_checker(mgs_hook_authz, NULL, NULL,
    49             APR_HOOK_REALLY_FIRST);
     51                           APR_HOOK_REALLY_FIRST);
    5052    /* Fixups Hook */
    5153    ap_hook_fixups(mgs_hook_fixups, NULL, NULL, APR_HOOK_REALLY_FIRST);
     
    5759
    5860    /* Input Filter */
    59     ap_register_input_filter(GNUTLS_INPUT_FILTER_NAME,
    60             mgs_filter_input, NULL,AP_FTYPE_CONNECTION + 5);
     61    ap_register_input_filter(GNUTLS_INPUT_FILTER_NAME, mgs_filter_input,
     62                             NULL, AP_FTYPE_CONNECTION + 5);
    6163    /* Output Filter */
    62     ap_register_output_filter(GNUTLS_OUTPUT_FILTER_NAME,
    63             mgs_filter_output, NULL,AP_FTYPE_CONNECTION + 5);
     64    ap_register_output_filter(GNUTLS_OUTPUT_FILTER_NAME, mgs_filter_output,
     65                              NULL, AP_FTYPE_CONNECTION + 5);
    6466
    6567    /* mod_proxy calls these functions */
     
    6870}
    6971
    70 int ssl_is_https(conn_rec *c) {
     72int ssl_is_https(conn_rec *c)
     73{
    7174    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
    72             ap_get_module_config(c->base_server->module_config, &gnutls_module);
     75        ap_get_module_config(c->base_server->module_config, &gnutls_module);
    7376    if(sc->enabled == 0 || sc->non_ssl_request == 1) {
    7477        /* SSL/TLS Disabled or Plain HTTP Connection Detected */
     
    8891
    8992    /* disable TLS for this connection */
    90     mgs_handle_t *ctxt = (mgs_handle_t *) ap_get_module_config(c->conn_config, &gnutls_module);
     93    mgs_handle_t *ctxt = (mgs_handle_t *)
     94        ap_get_module_config(c->conn_config, &gnutls_module);
    9195    if (ctxt == NULL)
    9296    {
    93         ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, "%s: allocating connection memory", __func__);
    9497        ctxt = apr_pcalloc(c->pool, sizeof (*ctxt));
    9598        ap_set_module_config(c->conn_config, &gnutls_module, ctxt);
    9699    }
    97100    ctxt->enabled = GNUTLS_ENABLED_FALSE;
     101    ctxt->is_proxy = GNUTLS_ENABLED_TRUE;
    98102
    99103    if (c->input_filters)
     
    105109}
    106110
    107 int ssl_proxy_enable(conn_rec *c) {
     111int ssl_proxy_enable(conn_rec *c)
     112{
     113    /* check if TLS proxy support is enabled */
    108114    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
    109             ap_get_module_config(c->base_server->module_config, &gnutls_module);
    110     sc->proxy_enabled = GNUTLS_ENABLED_TRUE;
    111     sc->enabled = GNUTLS_ENABLED_FALSE;
     115        ap_get_module_config(c->base_server->module_config, &gnutls_module);
     116    if (sc->proxy_enabled != GNUTLS_ENABLED_TRUE)
     117    {
     118        ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c,
     119                      "%s: mod_proxy requested TLS proxy, but not enabled "
     120                      "for %s", __func__, sc->cert_cn);
     121        return 0;
     122    }
     123
     124    /* enable TLS for this connection */
     125    mgs_handle_t *ctxt = (mgs_handle_t *)
     126        ap_get_module_config(c->conn_config, &gnutls_module);
     127    if (ctxt == NULL)
     128    {
     129        ctxt = apr_pcalloc(c->pool, sizeof (*ctxt));
     130        ap_set_module_config(c->conn_config, &gnutls_module, ctxt);
     131    }
     132    ctxt->enabled = GNUTLS_ENABLED_TRUE;
     133    ctxt->is_proxy = GNUTLS_ENABLED_TRUE;
    112134    return 1;
    113135}
     
    210232    RSRC_CONF,
    211233    "Max size to export PEM encoded certificates to CGIs (or off to disable). Default: off"),
     234    AP_INIT_TAKE1("GnuTLSProxyKeyFile", mgs_store_cred_path,
     235    NULL,
     236    RSRC_CONF,
     237    "X509 client private file for proxy connections"),
     238    AP_INIT_TAKE1("GnuTLSProxyCertificateFile", mgs_store_cred_path,
     239    NULL,
     240    RSRC_CONF,
     241    "X509 client certificate file for proxy connections"),
     242    AP_INIT_TAKE1("GnuTLSProxyCAFile", mgs_store_cred_path,
     243    NULL,
     244    RSRC_CONF,
     245    "X509 trusted CA file for proxy connections"),
     246    AP_INIT_TAKE1("GnuTLSProxyCRLFile", mgs_store_cred_path,
     247    NULL,
     248    RSRC_CONF,
     249    "X509 CRL file for proxy connections"),
     250    AP_INIT_RAW_ARGS("GnuTLSProxyPriorities", mgs_set_priorities,
     251    NULL,
     252    RSRC_CONF,
     253    "The priorities to enable for proxy connections (ciphers, key exchange, "
     254    "MACs, compression)."),
    212255    { NULL },
    213256};
  • test/.gitignore

    rd04f7da r2cde026d  
    1414authority.template
    1515msva.gnupghome
     16crl.pem
    1617*.log
    1718*.trs
    18 test.lock
     19*.lock
  • test/Makefile.am

    rd04f7da r2cde026d  
    1919TESTS += test-16_view-status.bash \
    2020        test-17_cgi_vars_large_cert.bash \
    21         test-18_client_verification_wrong_cert.bash
     21        test-18_client_verification_wrong_cert.bash \
     22        test-19_TLS_reverse_proxy.bash \
     23        test-20_TLS_reverse_proxy_client_auth.bash \
     24        test-21_TLS_reverse_proxy_wrong_cert.bash \
     25        test-22_TLS_reverse_proxy_crl_revoke.bash \
     26        test-23_TLS_reverse_proxy_mismatched_priorities.bash
    2227
    2328clean-local:
  • test/TestMakefile

    rd04f7da r2cde026d  
    1313
    1414export TEST_GAP ?= 1.5
    15 export TEST_QUERY_DELAY ?= 6
     15export TEST_QUERY_DELAY ?= 30
    1616
    1717TEST_LOCK := ./test.lock
     
    8888
    8989clean:
    90         rm -rf server client authority logs cache outputs setup.done server.template msva.gnupghome \
    91          */*.pgp */*.gpg */*.gpg~ */*.pem */*.key authority.template client.template server.uid
    92         rmdir imposter rogueca
     90        rm -rf server client authority logs cache outputs setup.done \
     91        server.template msva.gnupghome \
     92        */*.pgp */*.gpg */*.gpg~ */*.pem */*.key authority.template \
     93        client.template server.uid *.lock tests/*/*.pem
     94        rmdir imposter rogueca || true
    9395
    9496.PHONY: all clean
  • test/authority.template.in

    rd04f7da r2cde026d  
    33ca
    44cert_signing_key
     5crl_signing_key
  • test/base_apache.conf

    rd04f7da r2cde026d  
    22
    33LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined
    4 CustomLog logs/${TEST_NAME}.access.log combined 
     4CustomLog logs/${TEST_NAME}.access.log combined
    55ErrorLog logs/${TEST_NAME}.error.log
    66HostnameLookups Off
  • test/client.template.in

    rd04f7da r2cde026d  
    1 serial=2
     1serial=3
    22cn="Test User"
    33email=test0@modgnutls.test
  • test/rogueca.template

    rd04f7da r2cde026d  
    33ca
    44cert_signing_key
     5crl_signing_key
  • test/runtests

    rd04f7da r2cde026d  
    3333}
    3434
     35# Compare expected/actual outputs, filtering out headers from actual
     36# output that are expected to change between runs or builds (currently
     37# "Date" and "Server"). The headers must be excluded in the expected
     38# output.
     39#
     40# Parameters:
     41# $1: path to expected output
     42# $2: path to actual output
     43# $3: additional options for diff (optional)
     44function diff_output_filter_headers()
     45{
     46    local expected="$1"
     47    local actual="$2"
     48    diff $3 -u "${expected}" <( cat "${actual}" | \
     49        grep -v -P '^Date:\s.*GMT\s?$' | \
     50        grep -v -P '^Server:\sApache'  | \
     51        tail -n "$(wc -l < ${expected})" )
     52}
     53
     54# Run a command, storing its PID in the given file
     55# Usage: run_with_pidfile PIDFILE COMMAND [ARGS]
     56function run_with_pidfile()
     57{
     58    local pidfile=$1
     59    local cmd=$2
     60    shift 2
     61    echo $BASHPID >${pidfile}
     62    exec ${cmd} $*
     63}
     64
     65# Kills the process with the PID contained in a given file, then
     66# deletes the file.
     67# Usage: kill_by_pidfile PIDFILE
     68function kill_by_pidfile()
     69{
     70    local pidfile="${1}"
     71    # In some testcases with expected failure, gnutls-cli sometimes
     72    # failed before the subshell in front of the pipe (see gnutls-cli
     73    # call below) got so far as to write the PID, much less exec
     74    # sleep. So we need to check if there actually is anything to
     75    # kill.
     76    if [ -n "${pidfile}" ]; then
     77        local pid=$(cat "${pidfile}")
     78        if [ -n "${pid}" ] && ps -p "${pid}"; then
     79            kill "${pid}"
     80        fi
     81        rm "${pidfile}"
     82    fi
     83}
     84
    3585function apache_down_err() {
    3686    printf "FAILURE: %s\n" "$TEST_NAME"
    3787    /usr/sbin/apache2 -f "$(pwd)/apache.conf" -k stop || true
    3888    if [ -e output ]; then
    39         printf "\ngnutls-cli outputs:\n"
    40         diff -u output <( tail -n "$(wc -l < output)" "$output" ) || true
     89        printf "\ngnutls-cli outputs:\n"
     90        diff_output_filter_headers "output" "$output" || true
    4191    fi
     92
     93    if [ -n "${sleep_pidfile}" ]; then
     94        kill_by_pidfile "${sleep_pidfile}"
     95    fi
     96
    4297    printf "\nApache error logs:\n"
    4398    tail "../../logs/${TEST_NAME}.error.log"
     99
    44100    if [ -n "${USE_MSVA}" ]; then
    45101        stop_msva
     
    91147    fi
    92148
     149    # PID file for sleep command (explanation below)
     150    sleep_pidfile="$(mktemp mod_gnutls_test-XXXXXX.pid)"
     151
    93152    # The sleep call keeps the pipe from the subshell to gnutls-cli
    94153    # open. Without it gnutls-cli would terminate as soon as sed is
    95154    # done, and not wait for a response from the server, leading to
    96155    # failing tests. Sending sleep to the background allows the test
    97     # case to proceed instead of waiting for it to return, but has the
    98     # disadvantage of leaving the sleep process dangling until it
    99     # eventually times out. Still preferable to a fixed delay.
     156    # case to proceed instead of waiting for it to return. The sleep
     157    # process is stopped after gnutls-cli terminates.
    100158    if (sed "s/__HOSTNAME__/${TEST_HOST}/" <./input && \
    101         sleep "${TEST_QUERY_DELAY}" &) | \
     159        run_with_pidfile "${sleep_pidfile}" sleep "${TEST_QUERY_DELAY}" &) | \
    102160        gnutls-cli -p "${TEST_PORT}" $(cat ./gnutls-cli.args) "${TEST_HOST}" \
    103161        >"$output";
     
    114172    fi
    115173
     174    kill_by_pidfile "${sleep_pidfile}"
     175    unset sleep_pidfile
     176
    116177    if [ -e output ] ; then
    117         diff -q -u output <( tail -n "$(wc -l < output)" "$output" )
     178        diff_output_filter_headers "output" "$output" "-q"
    118179    fi
    119180    /usr/sbin/apache2 -f "$(pwd)/apache.conf" -k stop || [ -e fail.server ]
Note: See TracChangeset for help on using the changeset viewer.