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

Last change on this file since 1102 was 1102, checked in by mitchb, 13 years ago
Update to current version of the 2.2.x SNI patch
File size: 20.8 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")
    
    Last updated 2009-04-08
    
    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/). OpenSSL versions
    prior to 0.9.8j 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_NewSessionCacheEntry(SSL 
    562563SSL_SESSION *ssl_callback_GetSessionCacheEntry(SSL *, unsigned char *, int, int *);
    563564void         ssl_callback_DelSessionCacheEntry(SSL_CTX *, SSL_SESSION *);
    564565void         ssl_callback_LogTracingState(MODSSL_INFO_CB_ARG_TYPE, int, int);
     566#ifndef OPENSSL_NO_TLSEXT
     567int          ssl_callback_ServerNameIndication(SSL *, int *, modssl_ctx_t *);
     568#endif
    565569
    566570/**  Session Cache Support  */
    567571void         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_rec *s, 
    358358    }
    359359}
    360360
     361#ifndef OPENSSL_NO_TLSEXT
     362static void ssl_init_ctx_tls_extensions(server_rec *s,
     363                                        apr_pool_t *p,
     364                                        apr_pool_t *ptemp,
     365                                        modssl_ctx_t *mctx)
     366{
     367    /*
     368     * Configure TLS extensions support
     369     */
     370    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
     371                 "Configuring TLS extension handling");
     372
     373    /*
     374     * Server name indication (SNI)
     375     */
     376    if (!SSL_CTX_set_tlsext_servername_callback(mctx->ssl_ctx,
     377                          ssl_callback_ServerNameIndication) ||
     378        !SSL_CTX_set_tlsext_servername_arg(mctx->ssl_ctx, mctx)) {
     379        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
     380                     "Unable to initialize TLS servername extension "
     381                     "callback (incompatible OpenSSL version?)");
     382        ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, s);
     383        ssl_die();
     384    }
     385}
     386#endif
     387
    361388static void ssl_init_ctx_protocol(server_rec *s,
    362389                                  apr_pool_t *p,
    363390                                  apr_pool_t *ptemp,
    static void ssl_init_ctx(server_rec *s, 
    690717    if (mctx->pks) {
    691718        /* XXX: proxy support? */
    692719        ssl_init_ctx_cert_chain(s, p, ptemp, mctx);
     720#ifndef OPENSSL_NO_TLSEXT
     721        ssl_init_ctx_tls_extensions(s, p, ptemp, mctx);
     722#endif
    693723    }
    694724}
    695725
    void ssl_init_CheckServers(server_rec *base_server 
    10391069        klen = strlen(key);
    10401070
    10411071        if ((ps = (server_rec *)apr_hash_get(table, key, klen))) {
    1042             ap_log_error(APLOG_MARK, APLOG_WARNING, 0,
     1072            ap_log_error(APLOG_MARK,
     1073#ifdef OPENSSL_NO_TLSEXT
     1074                         APLOG_WARNING,
     1075#else
     1076                         APLOG_DEBUG,
     1077#endif
     1078                         0,
    10431079                         base_server,
     1080#ifdef OPENSSL_NO_TLSEXT
    10441081                         "Init: SSL server IP/port conflict: "
     1082#else
     1083                         "Init: SSL server IP/port overlap: "
     1084#endif
    10451085                         "%s (%s:%d) vs. %s (%s:%d)",
    10461086                         ssl_util_vhostid(p, s),
    10471087                         (s->defn_name ? s->defn_name : "unknown"),
    void ssl_init_CheckServers(server_rec *base_server 
    10581098
    10591099    if (conflict) {
    10601100        ap_log_error(APLOG_MARK, APLOG_WARNING, 0, base_server,
     1101#ifdef OPENSSL_NO_TLSEXT
    10611102                     "Init: You should not use name-based "
    10621103                     "virtual hosts in conjunction with SSL!!");
     1104#else
     1105                     "Init: Name-based SSL virtual hosts only "
     1106                     "work for clients with TLS server name indication "
     1107                     "support (RFC 4366)");
     1108#endif
    10631109    }
    10641110}
    10651111
  • httpd-2.2.x/modules/ssl/ssl_engine_vars.c

    static char *ssl_var_lookup_ssl(apr_pool_t *p, con 
    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 ((servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name))) {
     98        char *host, *scope_id;
     99        apr_port_t port;
     100        apr_status_t rv;
     101
     102        /*
     103         * The SNI extension supplied a hostname. So don't accept requests
     104         * with either no hostname or a different hostname.
     105         */
     106        if (!r->hostname) {
     107            ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
     108                        "Hostname %s provided via SNI, but no hostname"
     109                        " provided in HTTP request", servername);
     110            return HTTP_BAD_REQUEST;
     111        }
     112        rv = apr_parse_addr_port(&host, &scope_id, &port, r->hostname, r->pool);
     113        if (rv != APR_SUCCESS || scope_id) {
     114            return HTTP_BAD_REQUEST;
     115        }
     116        if (strcmp(host, servername)) {
     117            ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
     118                        "Hostname %s provided via SNI and hostname %s provided"
     119                        " via HTTP are different", servername, host);
     120            return HTTP_BAD_REQUEST;
     121        }
     122    }
     123#endif
    90124    SSL_set_app_data2(ssl, r);
    91125
    92126    /*
    int ssl_hook_Access(request_rec *r) 
    252286     *   has to enable this via ``SSLOptions +OptRenegotiate''. So we do no
    253287     *   implicit optimizations.
    254288     */
    255     if (dc->szCipherSuite) {
     289    if (dc->szCipherSuite || (r->server != r->connection->base_server)) {
    256290        /* remember old state */
    257291
    258292        if (dc->nOptions & SSL_OPT_OPTRENEGOTIATE) {
    int ssl_hook_Access(request_rec *r) 
    267301        }
    268302
    269303        /* configure new state */
    270         if (!modssl_set_cipher_list(ssl, dc->szCipherSuite)) {
     304        if ((dc->szCipherSuite || sc->server->auth.cipher_suite) &&
     305            !modssl_set_cipher_list(ssl, dc->szCipherSuite ?
     306                                         dc->szCipherSuite :
     307                                         sc->server->auth.cipher_suite)) {
    271308            ap_log_error(APLOG_MARK, APLOG_WARNING, 0,
    272309                         r->server,
    273310                         "Unable to reconfigure (per-directory) "
    int ssl_hook_Access(request_rec *r) 
    334371            sk_SSL_CIPHER_free(cipher_list_old);
    335372        }
    336373
    337         /* tracing */
    338374        if (renegotiate) {
     375#ifdef SSL_OP_CIPHER_SERVER_PREFERENCE
     376            if (sc->cipher_server_pref == TRUE) {
     377                SSL_set_options(ssl, SSL_OP_CIPHER_SERVER_PREFERENCE);
     378            }
     379#endif
     380            /* tracing */
    339381            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
    340382                         "Reconfigured cipher suite will force renegotiation");
    341383        }
    int ssl_hook_Access(request_rec *r) 
    353395     * currently active/remembered verify depth (because this means more
    354396     * restriction on the certificate chain).
    355397     */
    356     if (dc->nVerifyDepth != UNSET) {
    357         /* XXX: doesnt look like sslconn->verify_depth is actually used */
    358         if (!(n = sslconn->verify_depth)) {
    359             sslconn->verify_depth = n = sc->server->auth.verify_depth;
    360         }
    361 
    362         /* determine whether a renegotiation has to be forced */
    363         if (dc->nVerifyDepth < n) {
    364             renegotiate = TRUE;
    365             ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
    366                          "Reduced client verification depth will force "
    367                          "renegotiation");
    368         }
     398    n = sslconn->verify_depth;
     399    sslconn->verify_depth = (dc->nVerifyDepth != UNSET) ?
     400                            dc->nVerifyDepth : sc->server->auth.verify_depth;
     401    if ((sslconn->verify_depth < n) ||
     402        ((n == 0) && (sc->server->auth.verify_depth == 0))) {
     403        renegotiate = TRUE;
     404        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
     405                     "Reduced client verification depth will force "
     406                     "renegotiation");
    369407    }
    370408
    371409    /*
    int ssl_hook_Access(request_rec *r) 
    382420     * verification but at least skip the I/O-intensive renegotation
    383421     * handshake.
    384422     */
    385     if (dc->nVerifyClient != SSL_CVERIFY_UNSET) {
     423    if ((dc->nVerifyClient != SSL_CVERIFY_UNSET) ||
     424        (sc->server->auth.verify_mode != SSL_CVERIFY_UNSET)) {
    386425        /* remember old state */
    387426        verify_old = SSL_get_verify_mode(ssl);
    388427        /* configure new state */
    389428        verify = SSL_VERIFY_NONE;
    390429
    391         if (dc->nVerifyClient == SSL_CVERIFY_REQUIRE) {
     430        if ((dc->nVerifyClient == SSL_CVERIFY_REQUIRE) ||
     431            (sc->server->auth.verify_mode == SSL_CVERIFY_REQUIRE)) {
    392432            verify |= SSL_VERIFY_PEER_STRICT;
    393433        }
    394434
    395435        if ((dc->nVerifyClient == SSL_CVERIFY_OPTIONAL) ||
    396             (dc->nVerifyClient == SSL_CVERIFY_OPTIONAL_NO_CA))
     436            (dc->nVerifyClient == SSL_CVERIFY_OPTIONAL_NO_CA) ||
     437            (sc->server->auth.verify_mode == SSL_CVERIFY_OPTIONAL) ||
     438            (sc->server->auth.verify_mode == SSL_CVERIFY_OPTIONAL_NO_CA))
    397439        {
    398440            verify |= SSL_VERIFY_PEER;
    399441        }
    int ssl_hook_Access(request_rec *r) 
    491533                     "Changed client verification locations will force "
    492534                     "renegotiation");
    493535    }
     536#else
     537#ifndef OPENSSL_NO_TLSEXT
     538#define MODSSL_CFG_CA_NE(f, sc1, sc2) \
     539    (sc1->server->auth.f && \
     540     (!sc2->server->auth.f || \
     541      sc2->server->auth.f && strNE(sc1->server->auth.f, sc2->server->auth.f)))
     542
     543    /* If we're handling a request for a vhost other than the default one,
     544     * then we need to make sure that client authentication is properly
     545     * enforced. For clients supplying an SNI extension, the peer certificate
     546     * verification has happened in the handshake already (and r->server
     547     * has been set to r->connection->base_server). For non-SNI requests,
     548     * an additional check is needed here. If client authentication is
     549     * configured as mandatory, then we can only proceed if the CA list
     550     * doesn't have to be changed (SSL_set_cert_store() would be required
     551     * for this).
     552     */
     553    if ((r->server != r->connection->base_server) &&
     554        (verify & SSL_VERIFY_FAIL_IF_NO_PEER_CERT) &&
     555        renegotiate &&
     556        !(SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name))) {
     557        SSLSrvConfigRec *bssc = mySrvConfig(r->connection->base_server);
     558
     559        if (MODSSL_CFG_CA_NE(ca_cert_file, sc, bssc) ||
     560            MODSSL_CFG_CA_NE(ca_cert_path, sc, bssc)) {
     561            ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
     562                 "Non-default virtual host with SSLVerify set to 'require' "
     563                 "and VirtualHost-specific CA certificate list is only "
     564                 "supported for clients with TLS server name indication "
     565                 "(SNI) support");
     566            return HTTP_FORBIDDEN;
     567        }
     568    }
     569#endif /* OPENSSL_NO_TLSEXT */
    494570#endif /* HAVE_SSL_SET_CERT_STORE */
    495571
    496572    /* If a renegotiation is now required for this location, and the
    int ssl_hook_Access(request_rec *r) 
    675751        /*
    676752         * Finally check for acceptable renegotiation results
    677753         */
    678         if (dc->nVerifyClient != SSL_CVERIFY_NONE) {
    679             BOOL do_verify = (dc->nVerifyClient == SSL_CVERIFY_REQUIRE);
     754        if ((dc->nVerifyClient != SSL_CVERIFY_NONE) ||
     755            (sc->server->auth.verify_mode != SSL_CVERIFY_NONE)) {
     756            BOOL do_verify = ((dc->nVerifyClient == SSL_CVERIFY_REQUIRE) ||
     757                              (sc->server->auth.verify_mode == SSL_CVERIFY_REQUIRE));
    680758
    681759            if (do_verify && (SSL_get_verify_result(ssl) != X509_V_OK)) {
    682760                ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
    int ssl_hook_Fixup(request_rec *r) 
    10061084    SSLDirConfigRec *dc = myDirConfig(r);
    10071085    apr_table_t *env = r->subprocess_env;
    10081086    char *var, *val = "";
     1087#ifndef OPENSSL_NO_TLSEXT
     1088    const char *servername;
     1089#endif
    10091090    STACK_OF(X509) *peer_certs;
    10101091    SSL *ssl;
    10111092    int i;
    int ssl_hook_Fixup(request_rec *r) 
    10271108    /* the always present HTTPS (=HTTP over SSL) flag! */
    10281109    apr_table_setn(env, "HTTPS", "on");
    10291110
     1111#ifndef OPENSSL_NO_TLSEXT
     1112    /* add content of SNI TLS extension (if supplied with ClientHello) */
     1113    if ((servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name))) {
     1114        apr_table_set(env, "SSL_TLS_SNI", servername);
     1115    }
     1116#endif
     1117
    10301118    /* standard SSL environment variables */
    10311119    if (dc->nOptions & SSL_OPT_STDENVVARS) {
    10321120        for (i = 0; ssl_hook_Fixup_vars[i]; i++) {
    int ssl_callback_SSLVerify(int ok, X509_STORE_CTX 
    11751263    SSL *ssl = X509_STORE_CTX_get_ex_data(ctx,
    11761264                                          SSL_get_ex_data_X509_STORE_CTX_idx());
    11771265    conn_rec *conn      = (conn_rec *)SSL_get_app_data(ssl);
    1178     server_rec *s       = conn->base_server;
    11791266    request_rec *r      = (request_rec *)SSL_get_app_data2(ssl);
     1267    server_rec *s       = r ? r->server : conn->base_server;
    11801268
    11811269    SSLSrvConfigRec *sc = mySrvConfig(s);
    11821270    SSLDirConfigRec *dc = r ? myDirConfig(r) : NULL;
    int ssl_callback_SSLVerify(int ok, X509_STORE_CTX 
    12991387
    13001388int ssl_callback_SSLVerify_CRL(int ok, X509_STORE_CTX *ctx, conn_rec *c)
    13011389{
    1302     server_rec *s       = c->base_server;
     1390    SSL *ssl = X509_STORE_CTX_get_ex_data(ctx,
     1391                                          SSL_get_ex_data_X509_STORE_CTX_idx());
     1392    request_rec *r      = (request_rec *)SSL_get_app_data2(ssl);
     1393    server_rec *s       = r ? r->server : c->base_server;
    13031394    SSLSrvConfigRec *sc = mySrvConfig(s);
    13041395    SSLConnRec *sslconn = myConnConfig(c);
    13051396    modssl_ctx_t *mctx  = myCtxConfig(sslconn, sc);
    void ssl_callback_LogTracingState(MODSSL_INFO_CB_A 
    18191910    }
    18201911}
    18211912
     1913#ifndef OPENSSL_NO_TLSEXT
     1914/*
     1915 * This callback function is executed when OpenSSL encounters an extended
     1916 * client hello with a server name indication extension ("SNI", cf. RFC 4366).
     1917 */
     1918int ssl_callback_ServerNameIndication(SSL *ssl, int *al, modssl_ctx_t *mctx)
     1919{
     1920    const char *servername =
     1921                SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
     1922
     1923    if (servername) {
     1924        conn_rec *c = (conn_rec *)SSL_get_app_data(ssl);
     1925        if (c) {
     1926            if (ap_vhost_iterate_given_conn(c, ssl_find_vhost,
     1927                                            (void *)servername)) {
     1928                ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c,
     1929                              "SSL virtual host for servername %s found",
     1930                              servername);
     1931                return SSL_TLSEXT_ERR_OK;
     1932            }
     1933            else {
     1934                ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c,
     1935                              "No matching SSL virtual host for servername "
     1936                              "%s found (using default/first virtual host)",
     1937                              servername);
     1938                return SSL_TLSEXT_ERR_ALERT_WARNING;
     1939            }
     1940        }
     1941    }
     1942
     1943    return SSL_TLSEXT_ERR_NOACK;
     1944}
     1945
     1946/*
     1947 * Find a (name-based) SSL virtual host where either the ServerName
     1948 * or one of the ServerAliases matches the supplied name (to be used
     1949 * with ap_vhost_iterate_given_conn())
     1950 */
     1951static int ssl_find_vhost(void *servername, conn_rec *c, server_rec *s)
     1952{
     1953    SSLSrvConfigRec *sc;
     1954    SSL *ssl;
     1955    BOOL found = FALSE;
     1956    apr_array_header_t *names;
     1957    int i;
     1958
     1959    /* check ServerName */
     1960    if (!strcasecmp(servername, s->server_hostname)) {
     1961        found = TRUE;
     1962    }
     1963
     1964    /*
     1965     * if not matched yet, check ServerAlias entries
     1966     * (adapted from vhost.c:matches_aliases())
     1967     */
     1968    if (!found) {
     1969        names = s->names;
     1970        if (names) {
     1971            char **name = (char **)names->elts;
     1972            for (i = 0; i < names->nelts; ++i) {
     1973                if (!name[i])
     1974                    continue;
     1975                if (!strcasecmp(servername, name[i])) {
     1976                    found = TRUE;
     1977                    break;
     1978                }
     1979            }
     1980        }
     1981    }
     1982
     1983    /* if still no match, check ServerAlias entries with wildcards */
     1984    if (!found) {
     1985        names = s->wild_names;
     1986        if (names) {
     1987            char **name = (char **)names->elts;
     1988            for (i = 0; i < names->nelts; ++i) {
     1989                if (!name[i])
     1990                    continue;
     1991                if (!ap_strcasecmp_match(servername, name[i])) {
     1992                    found = TRUE;
     1993                    break;
     1994                }
     1995            }
     1996        }
     1997    }
     1998
     1999    /* set SSL_CTX (if matched) */
     2000    if (found && (ssl = ((SSLConnRec *)myConnConfig(c))->ssl) &&
     2001        (sc = mySrvConfig(s))) {
     2002        SSL_set_SSL_CTX(ssl, sc->server->ssl_ctx);
     2003        /*
     2004         * SSL_set_SSL_CTX() only deals with the server cert,
     2005         * so we need to duplicate a few additional settings
     2006         * from the ctx by hand
     2007         */
     2008        SSL_set_options(ssl, SSL_CTX_get_options(ssl->ctx));
     2009        if ((SSL_get_verify_mode(ssl) == SSL_VERIFY_NONE) ||
     2010            (SSL_num_renegotiations(ssl) == 0)) {
     2011           /*
     2012            * Only initialize the verification settings from the ctx
     2013            * if they are not yet set, or if we're called when a new
     2014            * SSL connection is set up (num_renegotiations == 0).
     2015            * Otherwise, we would possibly reset a per-directory
     2016            * configuration which was put into effect by ssl_hook_Access.
     2017            */
     2018            SSL_set_verify(ssl, SSL_CTX_get_verify_mode(ssl->ctx),
     2019                           SSL_CTX_get_verify_callback(ssl->ctx));
     2020        }
     2021
     2022        /*
     2023         * We also need to make sure that the correct mctx
     2024         * (accessed through the c->base_server->module_config vector)
     2025         * is assigned to the connection - the CRL callback e.g.
     2026         * makes use of it for retrieving its store (mctx->crl).
     2027         * Since logging in callbacks uses c->base_server in many
     2028         * cases, it also ensures that these messages are routed
     2029         * to the proper log.
     2030         */
     2031        c->base_server = s;
     2032
     2033        /*
     2034         * There is one special filter callback, which is set
     2035         * very early depending on the base_server's log level.
     2036         * If this is not the first vhost we're now selecting
     2037         * (and the first vhost doesn't use APLOG_DEBUG), then
     2038         * we need to set that callback here.
     2039         */
     2040        if (c->base_server->loglevel >= APLOG_DEBUG) {
     2041            BIO_set_callback(SSL_get_rbio(ssl), ssl_io_data_cb);
     2042            BIO_set_callback_arg(SSL_get_rbio(ssl), (void *)ssl);
     2043        }
     2044
     2045        return 1;
     2046    }
     2047
     2048    return 0;
     2049}
     2050#endif
  • httpd-2.2.x/modules/ssl/ssl_toolkit_compat.h

    typedef void (*modssl_popfree_fn)(char *data); 
    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.