source: server/common/patches/httpd-2.2.x-sni.patch @ 930

Last change on this file since 930 was 836, checked in by andersk, 16 years ago
Update the SNI patch as per <http://www.mail-archive.com/dev@httpd.apache.org/msg41417.html>. This is claimed to fix unnecessary SSL renegotiations, so maybe it has something to do with the repeated Firefox certificate popups.
File size: 19.5 KB
  • httpd-2.2.x/modules/ssl/ssl_private.h

    # httpd-2.2.x-sni.patch - server name indication support for Apache 2.2
    # (see RFC 4366, "Transport Layer Security (TLS) Extensions")
    
    # based on a patch from the EdelKey project
    # (http://www.edelweb.fr/EdelKey/files/apache-2.2.0+0.9.9+servername.patch)
    
    # Needs openssl-SNAP-20060330 / OpenSSL 0.9.8f or later
    # to work properly (ftp://ftp.openssl.org/snapshot/). The 0.9.8 versions
    # must be configured explicitly for TLS extension support at compile time
    # ("./config enable-tlsext").
    
     
    3535#include "http_connection.h"
    3636#include "http_request.h"
    3737#include "http_protocol.h"
     38#include "http_vhost.h"
    3839#include "util_script.h"
    3940#include "util_filter.h"
    4041#include "util_ebcdic.h"
    int ssl_callback_NewSessionCach 
    555556SSL_SESSION *ssl_callback_GetSessionCacheEntry(SSL *, unsigned char *, int, int *);
    556557void         ssl_callback_DelSessionCacheEntry(SSL_CTX *, SSL_SESSION *);
    557558void         ssl_callback_LogTracingState(MODSSL_INFO_CB_ARG_TYPE, int, int);
     559#ifndef OPENSSL_NO_TLSEXT
     560int          ssl_callback_ServerNameIndication(SSL *, int *, modssl_ctx_t *);
     561#endif
    558562
    559563/**  Session Cache Support  */
    560564void         ssl_scache_init(server_rec *, apr_pool_t *);
  • httpd-2.2.x/modules/ssl/ssl_engine_init.c

    static void ssl_init_server_check(server 
    355355    }
    356356}
    357357
     358#ifndef OPENSSL_NO_TLSEXT
     359static void ssl_init_ctx_tls_extensions(server_rec *s,
     360                                        apr_pool_t *p,
     361                                        apr_pool_t *ptemp,
     362                                        modssl_ctx_t *mctx)
     363{
     364    /*
     365     * Configure TLS extensions support
     366     */
     367    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
     368                 "Configuring TLS extension handling");
     369
     370    /*
     371     * Server name indication (SNI)
     372     */
     373    if (!SSL_CTX_set_tlsext_servername_callback(mctx->ssl_ctx,
     374                          ssl_callback_ServerNameIndication) ||
     375        !SSL_CTX_set_tlsext_servername_arg(mctx->ssl_ctx, mctx)) {
     376        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
     377                     "Unable to initialize TLS servername extension "
     378                     "callback (incompatible OpenSSL version?)");
     379        ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, s);
     380        ssl_die();
     381    }
     382}
     383#endif
     384
    358385static void ssl_init_ctx_protocol(server_rec *s,
    359386                                  apr_pool_t *p,
    360387                                  apr_pool_t *ptemp,
    static void ssl_init_ctx(server_rec *s, 
    687714    if (mctx->pks) {
    688715        /* XXX: proxy support? */
    689716        ssl_init_ctx_cert_chain(s, p, ptemp, mctx);
     717#ifndef OPENSSL_NO_TLSEXT
     718        ssl_init_ctx_tls_extensions(s, p, ptemp, mctx);
     719#endif
    690720    }
    691721}
    692722
    void ssl_init_CheckServers(server_rec *b 
    10361066        klen = strlen(key);
    10371067
    10381068        if ((ps = (server_rec *)apr_hash_get(table, key, klen))) {
    1039             ap_log_error(APLOG_MARK, APLOG_WARNING, 0,
     1069            ap_log_error(APLOG_MARK,
     1070#ifdef OPENSSL_NO_TLSEXT
     1071                         APLOG_WARNING,
     1072#else
     1073                         APLOG_DEBUG,
     1074#endif
     1075                         0,
    10401076                         base_server,
     1077#ifdef OPENSSL_NO_TLSEXT
    10411078                         "Init: SSL server IP/port conflict: "
     1079#else
     1080                         "Init: SSL server IP/port overlap: "
     1081#endif
    10421082                         "%s (%s:%d) vs. %s (%s:%d)",
    10431083                         ssl_util_vhostid(p, s),
    10441084                         (s->defn_name ? s->defn_name : "unknown"),
    void ssl_init_CheckServers(server_rec *b 
    10551095
    10561096    if (conflict) {
    10571097        ap_log_error(APLOG_MARK, APLOG_WARNING, 0, base_server,
     1098#ifdef OPENSSL_NO_TLSEXT
    10581099                     "Init: You should not use name-based "
    10591100                     "virtual hosts in conjunction with SSL!!");
     1101#else
     1102                     "Init: Name-based SSL virtual hosts only "
     1103                     "work for clients with TLS server name indication "
     1104                     "support (RFC 4366)");
     1105#endif
    10601106    }
    10611107}
    10621108
  • httpd-2.2.x/modules/ssl/ssl_engine_vars.c

    static char *ssl_var_lookup_ssl(apr_pool 
    320320    else if (ssl != NULL && strcEQ(var, "COMPRESS_METHOD")) {
    321321        result = ssl_var_lookup_ssl_compress_meth(ssl);
    322322    }
     323#ifndef OPENSSL_NO_TLSEXT
     324    else if (ssl != NULL && strcEQ(var, "TLS_SNI")) {
     325        result = apr_pstrdup(p, SSL_get_servername(ssl,
     326                                                   TLSEXT_NAMETYPE_host_name));
     327    }
     328#endif
    323329    return result;
    324330}
    325331
  • httpd-2.2.x/modules/ssl/ssl_engine_kernel.c

     
    3131#include "ssl_private.h"
    3232
    3333static void ssl_configure_env(request_rec *r, SSLConnRec *sslconn);
     34#ifndef OPENSSL_NO_TLSEXT
     35static int ssl_find_vhost(void *servername, conn_rec *c, server_rec *s);
     36#endif
    3437
    3538/*
    3639 *  Post Read Request Handler
    int ssl_hook_ReadReq(request_rec *r) 
    3942{
    4043    SSLConnRec *sslconn = myConnConfig(r->connection);
    4144    SSL *ssl;
     45#ifndef OPENSSL_NO_TLSEXT
     46    const char *servername;
     47#endif
    4248
    4349    if (!sslconn) {
    4450        return DECLINED;
    int ssl_hook_ReadReq(request_rec *r) 
    8793    if (!ssl) {
    8894        return DECLINED;
    8995    }
     96#ifndef OPENSSL_NO_TLSEXT
     97    if (!r->hostname &&
     98        (servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name))) {
     99        /* Use the SNI extension as the hostname if no Host: header was sent */
     100        r->hostname = apr_pstrdup(r->pool, servername);
     101        ap_update_vhost_from_headers(r);
     102    }
     103#endif
    90104    SSL_set_app_data2(ssl, r);
    91105
    92106    /*
    int ssl_hook_Access(request_rec *r) 
    252266     *   has to enable this via ``SSLOptions +OptRenegotiate''. So we do no
    253267     *   implicit optimizations.
    254268     */
    255     if (dc->szCipherSuite) {
     269    if (dc->szCipherSuite || (r->server != r->connection->base_server)) {
    256270        /* remember old state */
    257271
    258272        if (dc->nOptions & SSL_OPT_OPTRENEGOTIATE) {
    int ssl_hook_Access(request_rec *r) 
    267281        }
    268282
    269283        /* configure new state */
    270         if (!modssl_set_cipher_list(ssl, dc->szCipherSuite)) {
     284        if ((dc->szCipherSuite &&
     285             !modssl_set_cipher_list(ssl, dc->szCipherSuite)) ||
     286            (sc->server->auth.cipher_suite &&
     287             !modssl_set_cipher_list(ssl, sc->server->auth.cipher_suite))) {
    271288            ap_log_error(APLOG_MARK, APLOG_WARNING, 0,
    272289                         r->server,
    273290                         "Unable to reconfigure (per-directory) "
    int ssl_hook_Access(request_rec *r) 
    334351            sk_SSL_CIPHER_free(cipher_list_old);
    335352        }
    336353
    337         /* tracing */
    338354        if (renegotiate) {
     355#ifdef SSL_OP_CIPHER_SERVER_PREFERENCE
     356            if (sc->cipher_server_pref == TRUE) {
     357                SSL_set_options(ssl, SSL_OP_CIPHER_SERVER_PREFERENCE);
     358            }
     359#endif
     360            /* tracing */
    339361            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
    340362                         "Reconfigured cipher suite will force renegotiation");
    341363        }
    int ssl_hook_Access(request_rec *r) 
    353375     * currently active/remembered verify depth (because this means more
    354376     * restriction on the certificate chain).
    355377     */
    356     if (dc->nVerifyDepth != UNSET) {
     378    if ((dc->nVerifyDepth != UNSET) ||
     379        (sc->server->auth.verify_depth != 1)) {
    357380        /* XXX: doesnt look like sslconn->verify_depth is actually used */
    358381        if (!(n = sslconn->verify_depth)) {
    359382            sslconn->verify_depth = n = sc->server->auth.verify_depth;
    360383        }
    361384
    362385        /* determine whether a renegotiation has to be forced */
    363         if (dc->nVerifyDepth < n) {
     386        if ((dc->nVerifyDepth < n) ||
     387            (sc->server->auth.verify_depth < n)) {
    364388            renegotiate = TRUE;
    365389            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
    366390                         "Reduced client verification depth will force "
    int ssl_hook_Access(request_rec *r) 
    382406     * verification but at least skip the I/O-intensive renegotation
    383407     * handshake.
    384408     */
    385     if (dc->nVerifyClient != SSL_CVERIFY_UNSET) {
     409    if ((dc->nVerifyClient != SSL_CVERIFY_UNSET) ||
     410        (sc->server->auth.verify_mode != SSL_CVERIFY_UNSET)) {
    386411        /* remember old state */
    387412        verify_old = SSL_get_verify_mode(ssl);
    388413        /* configure new state */
    389414        verify = SSL_VERIFY_NONE;
    390415
    391         if (dc->nVerifyClient == SSL_CVERIFY_REQUIRE) {
     416        if ((dc->nVerifyClient == SSL_CVERIFY_REQUIRE) ||
     417            (sc->server->auth.verify_mode == SSL_CVERIFY_REQUIRE)) {
    392418            verify |= SSL_VERIFY_PEER_STRICT;
    393419        }
    394420
    395421        if ((dc->nVerifyClient == SSL_CVERIFY_OPTIONAL) ||
    396             (dc->nVerifyClient == SSL_CVERIFY_OPTIONAL_NO_CA))
     422            (dc->nVerifyClient == SSL_CVERIFY_OPTIONAL_NO_CA) ||
     423            (sc->server->auth.verify_mode == SSL_CVERIFY_OPTIONAL) ||
     424            (sc->server->auth.verify_mode == SSL_CVERIFY_OPTIONAL_NO_CA))
    397425        {
    398426            verify |= SSL_VERIFY_PEER;
    399427        }
    int ssl_hook_Access(request_rec *r) 
    491519                     "Changed client verification locations will force "
    492520                     "renegotiation");
    493521    }
     522#else
     523#ifndef OPENSSL_NO_TLSEXT
     524#define MODSSL_CFG_CA_NE(f, sc1, sc2) \
     525    (sc1->server->auth.f && \
     526     (!sc2->server->auth.f || \
     527      sc2->server->auth.f && strNE(sc1->server->auth.f, sc2->server->auth.f)))
     528
     529    /* If we're handling a request for a vhost other than the default one,
     530     * then we need to make sure that client authentication is properly
     531     * enforced. For clients supplying an SNI extension, the peer certificate
     532     * verification has happened in the handshake already (and r->server
     533     * has been set to r->connection->base_server). For non-SNI requests,
     534     * an additional check is needed here. If client authentication is
     535     * configured as mandatory, then we can only proceed if the CA list
     536     * doesn't have to be changed (SSL_set_cert_store() would be required
     537     * for this).
     538     */
     539    if ((r->server != r->connection->base_server) &&
     540        (verify & SSL_VERIFY_FAIL_IF_NO_PEER_CERT) &&
     541        renegotiate &&
     542        !(SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name))) {
     543        SSLSrvConfigRec *bssc = mySrvConfig(r->connection->base_server);
     544
     545        if (MODSSL_CFG_CA_NE(ca_cert_file, sc, bssc) ||
     546            MODSSL_CFG_CA_NE(ca_cert_path, sc, bssc)) {
     547            ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
     548                 "Non-default virtual host with SSLVerify set to 'require' "
     549                 "and VirtualHost-specific CA certificate list is only "
     550                 "supported for clients with TLS server name indication "
     551                 "(SNI) support");
     552            return HTTP_FORBIDDEN;
     553        }
     554    }
     555#endif /* OPENSSL_NO_TLSEXT */
    494556#endif /* HAVE_SSL_SET_CERT_STORE */
    495557
    496558    /* If a renegotiation is now required for this location, and the
    int ssl_hook_Access(request_rec *r) 
    666728        /*
    667729         * Finally check for acceptable renegotiation results
    668730         */
    669         if (dc->nVerifyClient != SSL_CVERIFY_NONE) {
    670             BOOL do_verify = (dc->nVerifyClient == SSL_CVERIFY_REQUIRE);
     731        if ((dc->nVerifyClient != SSL_CVERIFY_NONE) ||
     732            (sc->server->auth.verify_mode != SSL_CVERIFY_NONE)) {
     733            BOOL do_verify = ((dc->nVerifyClient == SSL_CVERIFY_REQUIRE) ||
     734                              (sc->server->auth.verify_mode == SSL_CVERIFY_REQUIRE));
    671735
    672736            if (do_verify && (SSL_get_verify_result(ssl) != X509_V_OK)) {
    673737                ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
    int ssl_hook_Fixup(request_rec *r) 
    9971061    SSLDirConfigRec *dc = myDirConfig(r);
    9981062    apr_table_t *env = r->subprocess_env;
    9991063    char *var, *val = "";
     1064#ifndef OPENSSL_NO_TLSEXT
     1065    const char *servername;
     1066#endif
    10001067    STACK_OF(X509) *peer_certs;
    10011068    SSL *ssl;
    10021069    int i;
    int ssl_hook_Fixup(request_rec *r) 
    10181085    /* the always present HTTPS (=HTTP over SSL) flag! */
    10191086    apr_table_setn(env, "HTTPS", "on");
    10201087
     1088#ifndef OPENSSL_NO_TLSEXT
     1089    /* add content of SNI TLS extension (if supplied with ClientHello) */
     1090    if ((servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name))) {
     1091        apr_table_set(env, "SSL_TLS_SNI", servername);
     1092    }
     1093#endif
     1094
    10211095    /* standard SSL environment variables */
    10221096    if (dc->nOptions & SSL_OPT_STDENVVARS) {
    10231097        for (i = 0; ssl_hook_Fixup_vars[i]; i++) {
    int ssl_callback_SSLVerify(int ok, X509_ 
    11661240    SSL *ssl = X509_STORE_CTX_get_ex_data(ctx,
    11671241                                          SSL_get_ex_data_X509_STORE_CTX_idx());
    11681242    conn_rec *conn      = (conn_rec *)SSL_get_app_data(ssl);
    1169     server_rec *s       = conn->base_server;
    11701243    request_rec *r      = (request_rec *)SSL_get_app_data2(ssl);
     1244    server_rec *s       = r ? r->server : conn->base_server;
    11711245
    11721246    SSLSrvConfigRec *sc = mySrvConfig(s);
    11731247    SSLDirConfigRec *dc = r ? myDirConfig(r) : NULL;
    int ssl_callback_SSLVerify(int ok, X509_ 
    12901364
    12911365int ssl_callback_SSLVerify_CRL(int ok, X509_STORE_CTX *ctx, conn_rec *c)
    12921366{
    1293     server_rec *s       = c->base_server;
     1367    SSL *ssl = X509_STORE_CTX_get_ex_data(ctx,
     1368                                          SSL_get_ex_data_X509_STORE_CTX_idx());
     1369    request_rec *r      = (request_rec *)SSL_get_app_data2(ssl);
     1370    server_rec *s       = r ? r->server : c->base_server;
    12941371    SSLSrvConfigRec *sc = mySrvConfig(s);
    12951372    SSLConnRec *sslconn = myConnConfig(c);
    12961373    modssl_ctx_t *mctx  = myCtxConfig(sslconn, sc);
    void ssl_callback_LogTracingState(MODSSL 
    18101887    }
    18111888}
    18121889
     1890#ifndef OPENSSL_NO_TLSEXT
     1891/*
     1892 * This callback function is executed when OpenSSL encounters an extended
     1893 * client hello with a server name indication extension ("SNI", cf. RFC 4366).
     1894 */
     1895int ssl_callback_ServerNameIndication(SSL *ssl, int *al, modssl_ctx_t *mctx)
     1896{
     1897    const char *servername =
     1898                SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
     1899
     1900    if (servername) {
     1901        conn_rec *c = (conn_rec *)SSL_get_app_data(ssl);
     1902        if (c) {
     1903            if (ap_vhost_iterate_given_conn(c, ssl_find_vhost,
     1904                                            (void *)servername)) {
     1905                ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c,
     1906                              "SSL virtual host for servername %s found",
     1907                              servername);
     1908                return SSL_TLSEXT_ERR_OK;
     1909            }
     1910            else {
     1911                ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c,
     1912                              "No matching SSL virtual host for servername "
     1913                              "%s found (using default/first virtual host)",
     1914                              servername);
     1915                return SSL_TLSEXT_ERR_ALERT_WARNING;
     1916            }
     1917        }
     1918    }
     1919
     1920    return SSL_TLSEXT_ERR_NOACK;
     1921}
     1922
     1923/*
     1924 * Find a (name-based) SSL virtual host where either the ServerName
     1925 * or one of the ServerAliases matches the supplied name (to be used
     1926 * with ap_vhost_iterate_given_conn())
     1927 */
     1928static int ssl_find_vhost(void *servername, conn_rec *c, server_rec *s)
     1929{
     1930    SSLSrvConfigRec *sc;
     1931    SSL *ssl;
     1932    BOOL found = FALSE;
     1933    apr_array_header_t *names;
     1934    int i;
     1935
     1936    /* check ServerName */
     1937    if (!strcasecmp(servername, s->server_hostname)) {
     1938        found = TRUE;
     1939    }
     1940
     1941    /*
     1942     * if not matched yet, check ServerAlias entries
     1943     * (adapted from vhost.c:matches_aliases())
     1944     */
     1945    if (!found) {
     1946        names = s->names;
     1947        if (names) {
     1948            char **name = (char **)names->elts;
     1949            for (i = 0; i < names->nelts; ++i) {
     1950                if (!name[i])
     1951                    continue;
     1952                if (!strcasecmp(servername, name[i])) {
     1953                    found = TRUE;
     1954                    break;
     1955                }
     1956            }
     1957        }
     1958    }
     1959
     1960    /* if still no match, check ServerAlias entries with wildcards */
     1961    if (!found) {
     1962        names = s->wild_names;
     1963        if (names) {
     1964            char **name = (char **)names->elts;
     1965            for (i = 0; i < names->nelts; ++i) {
     1966                if (!name[i])
     1967                    continue;
     1968                if (!ap_strcasecmp_match(servername, name[i])) {
     1969                    found = TRUE;
     1970                    break;
     1971                }
     1972            }
     1973        }
     1974    }
     1975
     1976    /* set SSL_CTX (if matched) */
     1977    if (found && (ssl = ((SSLConnRec *)myConnConfig(c))->ssl) &&
     1978        (sc = mySrvConfig(s))) {
     1979        SSL_set_SSL_CTX(ssl, sc->server->ssl_ctx);
     1980        /*
     1981         * SSL_set_SSL_CTX() only deals with the server cert,
     1982         * so we need to duplicate a few additional settings
     1983         * from the ctx by hand
     1984         */
     1985        SSL_set_options(ssl, SSL_CTX_get_options(ssl->ctx));
     1986        if ((SSL_get_verify_mode(ssl) == SSL_VERIFY_NONE) ||
     1987            (SSL_num_renegotiations(ssl) == 0)) {
     1988           /*
     1989            * Only initialize the verification settings from the ctx
     1990            * if they are not yet set, or if we're called when a new
     1991            * SSL connection is set up (num_renegotiations == 0).
     1992            * Otherwise, we would possibly reset a per-directory
     1993            * configuration which was put into effect by ssl_hook_Access.
     1994            */
     1995            SSL_set_verify(ssl, SSL_CTX_get_verify_mode(ssl->ctx),
     1996                           SSL_CTX_get_verify_callback(ssl->ctx));
     1997        }
     1998
     1999        /*
     2000         * We also need to make sure that the correct mctx
     2001         * (accessed through the c->base_server->module_config vector)
     2002         * is assigned to the connection - the CRL callback e.g.
     2003         * makes use of it for retrieving its store (mctx->crl).
     2004         * Since logging in callbacks uses c->base_server in many
     2005         * cases, it also ensures that these messages are routed
     2006         * to the proper log.
     2007         */
     2008        c->base_server = s;
     2009
     2010        /*
     2011         * There is one special filter callback, which is set
     2012         * very early depending on the base_server's log level.
     2013         * If this is not the first vhost we're now selecting
     2014         * (and the first vhost doesn't use APLOG_DEBUG), then
     2015         * we need to set that callback here.
     2016         */
     2017        if (c->base_server->loglevel >= APLOG_DEBUG) {
     2018            BIO_set_callback(SSL_get_rbio(ssl), ssl_io_data_cb);
     2019            BIO_set_callback_arg(SSL_get_rbio(ssl), (void *)ssl);
     2020        }
     2021
     2022        return 1;
     2023    }
     2024
     2025    return 0;
     2026}
     2027#endif
  • httpd-2.2.x/modules/ssl/ssl_toolkit_compat.h

    typedef void (*modssl_popfree_fn)(char * 
    264264#define SSL_SESS_CACHE_NO_INTERNAL  SSL_SESS_CACHE_NO_INTERNAL_LOOKUP
    265265#endif
    266266
     267#ifndef OPENSSL_NO_TLSEXT
     268#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME
     269#define OPENSSL_NO_TLSEXT
     270#endif
     271#endif
     272
    267273#endif /* SSL_TOOLKIT_COMPAT_H */
    268274
    269275/** @} */
Note: See TracBrowser for help on using the repository browser.