| [1102] | 1 | httpd-2.2.x-sni.patch - server name indication support for Apache 2.2 | 
|---|
|  | 2 | (see RFC 4366, "Transport Layer Security (TLS) Extensions") | 
|---|
| [683] | 3 |  | 
|---|
| [1102] | 4 | Last updated 2009-04-08 | 
|---|
| [683] | 5 |  | 
|---|
| [1102] | 6 | based on a patch from the EdelKey project | 
|---|
|  | 7 | (http://www.edelweb.fr/EdelKey/files/apache-2.2.0+0.9.9+servername.patch) | 
|---|
| [683] | 8 |  | 
|---|
| [1102] | 9 | Needs openssl-SNAP-20060330 / OpenSSL 0.9.8f or later | 
|---|
|  | 10 | to work properly (ftp://ftp.openssl.org/snapshot/). OpenSSL versions | 
|---|
|  | 11 | prior to 0.9.8j must be configured explicitly for TLS extension support | 
|---|
|  | 12 | at compile time ("./config enable-tlsext"). | 
|---|
|  | 13 |  | 
|---|
| [683] | 14 | Index: httpd-2.2.x/modules/ssl/ssl_private.h | 
|---|
|  | 15 | =================================================================== | 
|---|
| [1102] | 16 | --- httpd-2.2.x/modules/ssl/ssl_private.h       (revision 763153) | 
|---|
| [683] | 17 | +++ httpd-2.2.x/modules/ssl/ssl_private.h       (working copy) | 
|---|
|  | 18 | @@ -35,6 +35,7 @@ | 
|---|
|  | 19 | #include "http_connection.h" | 
|---|
|  | 20 | #include "http_request.h" | 
|---|
|  | 21 | #include "http_protocol.h" | 
|---|
|  | 22 | +#include "http_vhost.h" | 
|---|
|  | 23 | #include "util_script.h" | 
|---|
|  | 24 | #include "util_filter.h" | 
|---|
|  | 25 | #include "util_ebcdic.h" | 
|---|
| [1102] | 26 | @@ -562,6 +563,9 @@ int          ssl_callback_NewSessionCacheEntry(SSL | 
|---|
| [683] | 27 | SSL_SESSION *ssl_callback_GetSessionCacheEntry(SSL *, unsigned char *, int, int *); | 
|---|
|  | 28 | void         ssl_callback_DelSessionCacheEntry(SSL_CTX *, SSL_SESSION *); | 
|---|
|  | 29 | void         ssl_callback_LogTracingState(MODSSL_INFO_CB_ARG_TYPE, int, int); | 
|---|
|  | 30 | +#ifndef OPENSSL_NO_TLSEXT | 
|---|
|  | 31 | +int          ssl_callback_ServerNameIndication(SSL *, int *, modssl_ctx_t *); | 
|---|
|  | 32 | +#endif | 
|---|
|  | 33 |  | 
|---|
|  | 34 | /**  Session Cache Support  */ | 
|---|
|  | 35 | void         ssl_scache_init(server_rec *, apr_pool_t *); | 
|---|
|  | 36 | Index: httpd-2.2.x/modules/ssl/ssl_engine_init.c | 
|---|
|  | 37 | =================================================================== | 
|---|
| [1102] | 38 | --- httpd-2.2.x/modules/ssl/ssl_engine_init.c   (revision 763153) | 
|---|
| [683] | 39 | +++ httpd-2.2.x/modules/ssl/ssl_engine_init.c   (working copy) | 
|---|
| [1102] | 40 | @@ -358,6 +358,33 @@ static void ssl_init_server_check(server_rec *s, | 
|---|
| [683] | 41 | } | 
|---|
|  | 42 | } | 
|---|
|  | 43 |  | 
|---|
|  | 44 | +#ifndef OPENSSL_NO_TLSEXT | 
|---|
|  | 45 | +static void ssl_init_ctx_tls_extensions(server_rec *s, | 
|---|
|  | 46 | +                                        apr_pool_t *p, | 
|---|
|  | 47 | +                                        apr_pool_t *ptemp, | 
|---|
|  | 48 | +                                        modssl_ctx_t *mctx) | 
|---|
|  | 49 | +{ | 
|---|
|  | 50 | +    /* | 
|---|
|  | 51 | +     * Configure TLS extensions support | 
|---|
|  | 52 | +     */ | 
|---|
|  | 53 | +    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, | 
|---|
|  | 54 | +                 "Configuring TLS extension handling"); | 
|---|
|  | 55 | + | 
|---|
|  | 56 | +    /* | 
|---|
|  | 57 | +     * Server name indication (SNI) | 
|---|
|  | 58 | +     */ | 
|---|
|  | 59 | +    if (!SSL_CTX_set_tlsext_servername_callback(mctx->ssl_ctx, | 
|---|
|  | 60 | +                          ssl_callback_ServerNameIndication) || | 
|---|
|  | 61 | +        !SSL_CTX_set_tlsext_servername_arg(mctx->ssl_ctx, mctx)) { | 
|---|
|  | 62 | +        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, | 
|---|
|  | 63 | +                     "Unable to initialize TLS servername extension " | 
|---|
|  | 64 | +                     "callback (incompatible OpenSSL version?)"); | 
|---|
|  | 65 | +        ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, s); | 
|---|
|  | 66 | +        ssl_die(); | 
|---|
|  | 67 | +    } | 
|---|
|  | 68 | +} | 
|---|
|  | 69 | +#endif | 
|---|
|  | 70 | + | 
|---|
|  | 71 | static void ssl_init_ctx_protocol(server_rec *s, | 
|---|
|  | 72 | apr_pool_t *p, | 
|---|
|  | 73 | apr_pool_t *ptemp, | 
|---|
| [1102] | 74 | @@ -690,6 +717,9 @@ static void ssl_init_ctx(server_rec *s, | 
|---|
| [683] | 75 | if (mctx->pks) { | 
|---|
|  | 76 | /* XXX: proxy support? */ | 
|---|
|  | 77 | ssl_init_ctx_cert_chain(s, p, ptemp, mctx); | 
|---|
|  | 78 | +#ifndef OPENSSL_NO_TLSEXT | 
|---|
|  | 79 | +        ssl_init_ctx_tls_extensions(s, p, ptemp, mctx); | 
|---|
|  | 80 | +#endif | 
|---|
|  | 81 | } | 
|---|
|  | 82 | } | 
|---|
|  | 83 |  | 
|---|
| [1102] | 84 | @@ -1039,9 +1069,19 @@ void ssl_init_CheckServers(server_rec *base_server | 
|---|
| [816] | 85 | klen = strlen(key); | 
|---|
|  | 86 |  | 
|---|
| [683] | 87 | if ((ps = (server_rec *)apr_hash_get(table, key, klen))) { | 
|---|
| [816] | 88 | -            ap_log_error(APLOG_MARK, APLOG_WARNING, 0, | 
|---|
|  | 89 | +            ap_log_error(APLOG_MARK, | 
|---|
|  | 90 | +#ifdef OPENSSL_NO_TLSEXT | 
|---|
|  | 91 | +                         APLOG_WARNING, | 
|---|
|  | 92 | +#else | 
|---|
|  | 93 | +                         APLOG_DEBUG, | 
|---|
|  | 94 | +#endif | 
|---|
|  | 95 | +                         0, | 
|---|
| [683] | 96 | base_server, | 
|---|
|  | 97 | +#ifdef OPENSSL_NO_TLSEXT | 
|---|
|  | 98 | "Init: SSL server IP/port conflict: " | 
|---|
|  | 99 | +#else | 
|---|
|  | 100 | +                         "Init: SSL server IP/port overlap: " | 
|---|
|  | 101 | +#endif | 
|---|
|  | 102 | "%s (%s:%d) vs. %s (%s:%d)", | 
|---|
|  | 103 | ssl_util_vhostid(p, s), | 
|---|
|  | 104 | (s->defn_name ? s->defn_name : "unknown"), | 
|---|
| [1102] | 105 | @@ -1058,8 +1098,14 @@ void ssl_init_CheckServers(server_rec *base_server | 
|---|
| [683] | 106 |  | 
|---|
|  | 107 | if (conflict) { | 
|---|
|  | 108 | ap_log_error(APLOG_MARK, APLOG_WARNING, 0, base_server, | 
|---|
|  | 109 | +#ifdef OPENSSL_NO_TLSEXT | 
|---|
|  | 110 | "Init: You should not use name-based " | 
|---|
|  | 111 | "virtual hosts in conjunction with SSL!!"); | 
|---|
|  | 112 | +#else | 
|---|
|  | 113 | +                     "Init: Name-based SSL virtual hosts only " | 
|---|
|  | 114 | +                     "work for clients with TLS server name indication " | 
|---|
|  | 115 | +                     "support (RFC 4366)"); | 
|---|
|  | 116 | +#endif | 
|---|
|  | 117 | } | 
|---|
|  | 118 | } | 
|---|
|  | 119 |  | 
|---|
|  | 120 | Index: httpd-2.2.x/modules/ssl/ssl_engine_vars.c | 
|---|
|  | 121 | =================================================================== | 
|---|
| [1102] | 122 | --- httpd-2.2.x/modules/ssl/ssl_engine_vars.c   (revision 763153) | 
|---|
| [683] | 123 | +++ httpd-2.2.x/modules/ssl/ssl_engine_vars.c   (working copy) | 
|---|
| [1102] | 124 | @@ -320,6 +320,12 @@ static char *ssl_var_lookup_ssl(apr_pool_t *p, con | 
|---|
| [683] | 125 | else if (ssl != NULL && strcEQ(var, "COMPRESS_METHOD")) { | 
|---|
|  | 126 | result = ssl_var_lookup_ssl_compress_meth(ssl); | 
|---|
|  | 127 | } | 
|---|
|  | 128 | +#ifndef OPENSSL_NO_TLSEXT | 
|---|
|  | 129 | +    else if (ssl != NULL && strcEQ(var, "TLS_SNI")) { | 
|---|
|  | 130 | +        result = apr_pstrdup(p, SSL_get_servername(ssl, | 
|---|
|  | 131 | +                                                   TLSEXT_NAMETYPE_host_name)); | 
|---|
|  | 132 | +    } | 
|---|
|  | 133 | +#endif | 
|---|
|  | 134 | return result; | 
|---|
|  | 135 | } | 
|---|
|  | 136 |  | 
|---|
|  | 137 | Index: httpd-2.2.x/modules/ssl/ssl_engine_kernel.c | 
|---|
|  | 138 | =================================================================== | 
|---|
| [1102] | 139 | --- httpd-2.2.x/modules/ssl/ssl_engine_kernel.c (revision 763153) | 
|---|
| [683] | 140 | +++ httpd-2.2.x/modules/ssl/ssl_engine_kernel.c (working copy) | 
|---|
|  | 141 | @@ -31,6 +31,9 @@ | 
|---|
|  | 142 | #include "ssl_private.h" | 
|---|
|  | 143 |  | 
|---|
|  | 144 | static void ssl_configure_env(request_rec *r, SSLConnRec *sslconn); | 
|---|
|  | 145 | +#ifndef OPENSSL_NO_TLSEXT | 
|---|
|  | 146 | +static int ssl_find_vhost(void *servername, conn_rec *c, server_rec *s); | 
|---|
|  | 147 | +#endif | 
|---|
|  | 148 |  | 
|---|
|  | 149 | /* | 
|---|
|  | 150 | *  Post Read Request Handler | 
|---|
| [816] | 151 | @@ -39,6 +42,9 @@ int ssl_hook_ReadReq(request_rec *r) | 
|---|
| [683] | 152 | { | 
|---|
|  | 153 | SSLConnRec *sslconn = myConnConfig(r->connection); | 
|---|
|  | 154 | SSL *ssl; | 
|---|
|  | 155 | +#ifndef OPENSSL_NO_TLSEXT | 
|---|
|  | 156 | +    const char *servername; | 
|---|
|  | 157 | +#endif | 
|---|
|  | 158 |  | 
|---|
|  | 159 | if (!sslconn) { | 
|---|
|  | 160 | return DECLINED; | 
|---|
| [1102] | 161 | @@ -87,6 +93,34 @@ int ssl_hook_ReadReq(request_rec *r) | 
|---|
| [683] | 162 | if (!ssl) { | 
|---|
|  | 163 | return DECLINED; | 
|---|
|  | 164 | } | 
|---|
|  | 165 | +#ifndef OPENSSL_NO_TLSEXT | 
|---|
| [1102] | 166 | +    if ((servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name))) { | 
|---|
|  | 167 | +        char *host, *scope_id; | 
|---|
|  | 168 | +        apr_port_t port; | 
|---|
|  | 169 | +        apr_status_t rv; | 
|---|
|  | 170 | + | 
|---|
|  | 171 | +        /* | 
|---|
|  | 172 | +         * The SNI extension supplied a hostname. So don't accept requests | 
|---|
|  | 173 | +         * with either no hostname or a different hostname. | 
|---|
|  | 174 | +         */ | 
|---|
|  | 175 | +        if (!r->hostname) { | 
|---|
|  | 176 | +            ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, | 
|---|
|  | 177 | +                        "Hostname %s provided via SNI, but no hostname" | 
|---|
|  | 178 | +                        " provided in HTTP request", servername); | 
|---|
|  | 179 | +            return HTTP_BAD_REQUEST; | 
|---|
|  | 180 | +        } | 
|---|
|  | 181 | +        rv = apr_parse_addr_port(&host, &scope_id, &port, r->hostname, r->pool); | 
|---|
|  | 182 | +        if (rv != APR_SUCCESS || scope_id) { | 
|---|
|  | 183 | +            return HTTP_BAD_REQUEST; | 
|---|
|  | 184 | +        } | 
|---|
|  | 185 | +        if (strcmp(host, servername)) { | 
|---|
|  | 186 | +            ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, | 
|---|
|  | 187 | +                        "Hostname %s provided via SNI and hostname %s provided" | 
|---|
|  | 188 | +                        " via HTTP are different", servername, host); | 
|---|
|  | 189 | +            return HTTP_BAD_REQUEST; | 
|---|
|  | 190 | +        } | 
|---|
| [683] | 191 | +    } | 
|---|
|  | 192 | +#endif | 
|---|
|  | 193 | SSL_set_app_data2(ssl, r); | 
|---|
|  | 194 |  | 
|---|
|  | 195 | /* | 
|---|
| [1102] | 196 | @@ -252,7 +286,7 @@ int ssl_hook_Access(request_rec *r) | 
|---|
| [816] | 197 | *   has to enable this via ``SSLOptions +OptRenegotiate''. So we do no | 
|---|
|  | 198 | *   implicit optimizations. | 
|---|
|  | 199 | */ | 
|---|
|  | 200 | -    if (dc->szCipherSuite) { | 
|---|
|  | 201 | +    if (dc->szCipherSuite || (r->server != r->connection->base_server)) { | 
|---|
|  | 202 | /* remember old state */ | 
|---|
|  | 203 |  | 
|---|
|  | 204 | if (dc->nOptions & SSL_OPT_OPTRENEGOTIATE) { | 
|---|
| [1102] | 205 | @@ -267,7 +301,10 @@ int ssl_hook_Access(request_rec *r) | 
|---|
| [816] | 206 | } | 
|---|
|  | 207 |  | 
|---|
|  | 208 | /* configure new state */ | 
|---|
|  | 209 | -        if (!modssl_set_cipher_list(ssl, dc->szCipherSuite)) { | 
|---|
| [1102] | 210 | +        if ((dc->szCipherSuite || sc->server->auth.cipher_suite) && | 
|---|
|  | 211 | +            !modssl_set_cipher_list(ssl, dc->szCipherSuite ? | 
|---|
|  | 212 | +                                         dc->szCipherSuite : | 
|---|
|  | 213 | +                                         sc->server->auth.cipher_suite)) { | 
|---|
| [816] | 214 | ap_log_error(APLOG_MARK, APLOG_WARNING, 0, | 
|---|
|  | 215 | r->server, | 
|---|
|  | 216 | "Unable to reconfigure (per-directory) " | 
|---|
| [1102] | 217 | @@ -334,8 +371,13 @@ int ssl_hook_Access(request_rec *r) | 
|---|
| [816] | 218 | sk_SSL_CIPHER_free(cipher_list_old); | 
|---|
|  | 219 | } | 
|---|
|  | 220 |  | 
|---|
|  | 221 | -        /* tracing */ | 
|---|
|  | 222 | if (renegotiate) { | 
|---|
|  | 223 | +#ifdef SSL_OP_CIPHER_SERVER_PREFERENCE | 
|---|
|  | 224 | +            if (sc->cipher_server_pref == TRUE) { | 
|---|
|  | 225 | +                SSL_set_options(ssl, SSL_OP_CIPHER_SERVER_PREFERENCE); | 
|---|
|  | 226 | +            } | 
|---|
|  | 227 | +#endif | 
|---|
|  | 228 | +            /* tracing */ | 
|---|
|  | 229 | ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, | 
|---|
|  | 230 | "Reconfigured cipher suite will force renegotiation"); | 
|---|
|  | 231 | } | 
|---|
| [1102] | 232 | @@ -353,19 +395,15 @@ int ssl_hook_Access(request_rec *r) | 
|---|
| [816] | 233 | * currently active/remembered verify depth (because this means more | 
|---|
|  | 234 | * restriction on the certificate chain). | 
|---|
|  | 235 | */ | 
|---|
|  | 236 | -    if (dc->nVerifyDepth != UNSET) { | 
|---|
| [1102] | 237 | -        /* XXX: doesnt look like sslconn->verify_depth is actually used */ | 
|---|
|  | 238 | -        if (!(n = sslconn->verify_depth)) { | 
|---|
|  | 239 | -            sslconn->verify_depth = n = sc->server->auth.verify_depth; | 
|---|
|  | 240 | -        } | 
|---|
|  | 241 | - | 
|---|
|  | 242 | -        /* determine whether a renegotiation has to be forced */ | 
|---|
|  | 243 | -        if (dc->nVerifyDepth < n) { | 
|---|
|  | 244 | -            renegotiate = TRUE; | 
|---|
|  | 245 | -            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, | 
|---|
|  | 246 | -                         "Reduced client verification depth will force " | 
|---|
|  | 247 | -                         "renegotiation"); | 
|---|
|  | 248 | -        } | 
|---|
|  | 249 | +    n = sslconn->verify_depth; | 
|---|
|  | 250 | +    sslconn->verify_depth = (dc->nVerifyDepth != UNSET) ? | 
|---|
|  | 251 | +                            dc->nVerifyDepth : sc->server->auth.verify_depth; | 
|---|
|  | 252 | +    if ((sslconn->verify_depth < n) || | 
|---|
|  | 253 | +        ((n == 0) && (sc->server->auth.verify_depth == 0))) { | 
|---|
|  | 254 | +        renegotiate = TRUE; | 
|---|
|  | 255 | +        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, | 
|---|
|  | 256 | +                     "Reduced client verification depth will force " | 
|---|
|  | 257 | +                     "renegotiation"); | 
|---|
|  | 258 | } | 
|---|
| [816] | 259 |  | 
|---|
| [1102] | 260 | /* | 
|---|
|  | 261 | @@ -382,18 +420,22 @@ int ssl_hook_Access(request_rec *r) | 
|---|
| [816] | 262 | * verification but at least skip the I/O-intensive renegotation | 
|---|
|  | 263 | * handshake. | 
|---|
|  | 264 | */ | 
|---|
|  | 265 | -    if (dc->nVerifyClient != SSL_CVERIFY_UNSET) { | 
|---|
|  | 266 | +    if ((dc->nVerifyClient != SSL_CVERIFY_UNSET) || | 
|---|
|  | 267 | +        (sc->server->auth.verify_mode != SSL_CVERIFY_UNSET)) { | 
|---|
|  | 268 | /* remember old state */ | 
|---|
|  | 269 | verify_old = SSL_get_verify_mode(ssl); | 
|---|
|  | 270 | /* configure new state */ | 
|---|
|  | 271 | verify = SSL_VERIFY_NONE; | 
|---|
|  | 272 |  | 
|---|
|  | 273 | -        if (dc->nVerifyClient == SSL_CVERIFY_REQUIRE) { | 
|---|
|  | 274 | +        if ((dc->nVerifyClient == SSL_CVERIFY_REQUIRE) || | 
|---|
|  | 275 | +            (sc->server->auth.verify_mode == SSL_CVERIFY_REQUIRE)) { | 
|---|
|  | 276 | verify |= SSL_VERIFY_PEER_STRICT; | 
|---|
|  | 277 | } | 
|---|
|  | 278 |  | 
|---|
|  | 279 | if ((dc->nVerifyClient == SSL_CVERIFY_OPTIONAL) || | 
|---|
|  | 280 | -            (dc->nVerifyClient == SSL_CVERIFY_OPTIONAL_NO_CA)) | 
|---|
|  | 281 | +            (dc->nVerifyClient == SSL_CVERIFY_OPTIONAL_NO_CA) || | 
|---|
|  | 282 | +            (sc->server->auth.verify_mode == SSL_CVERIFY_OPTIONAL) || | 
|---|
|  | 283 | +            (sc->server->auth.verify_mode == SSL_CVERIFY_OPTIONAL_NO_CA)) | 
|---|
|  | 284 | { | 
|---|
|  | 285 | verify |= SSL_VERIFY_PEER; | 
|---|
|  | 286 | } | 
|---|
| [1102] | 287 | @@ -491,6 +533,40 @@ int ssl_hook_Access(request_rec *r) | 
|---|
| [816] | 288 | "Changed client verification locations will force " | 
|---|
|  | 289 | "renegotiation"); | 
|---|
|  | 290 | } | 
|---|
|  | 291 | +#else | 
|---|
|  | 292 | +#ifndef OPENSSL_NO_TLSEXT | 
|---|
|  | 293 | +#define MODSSL_CFG_CA_NE(f, sc1, sc2) \ | 
|---|
|  | 294 | +    (sc1->server->auth.f && \ | 
|---|
|  | 295 | +     (!sc2->server->auth.f || \ | 
|---|
|  | 296 | +      sc2->server->auth.f && strNE(sc1->server->auth.f, sc2->server->auth.f))) | 
|---|
|  | 297 | + | 
|---|
|  | 298 | +    /* If we're handling a request for a vhost other than the default one, | 
|---|
|  | 299 | +     * then we need to make sure that client authentication is properly | 
|---|
|  | 300 | +     * enforced. For clients supplying an SNI extension, the peer certificate | 
|---|
|  | 301 | +     * verification has happened in the handshake already (and r->server | 
|---|
|  | 302 | +     * has been set to r->connection->base_server). For non-SNI requests, | 
|---|
|  | 303 | +     * an additional check is needed here. If client authentication is | 
|---|
|  | 304 | +     * configured as mandatory, then we can only proceed if the CA list | 
|---|
|  | 305 | +     * doesn't have to be changed (SSL_set_cert_store() would be required | 
|---|
|  | 306 | +     * for this). | 
|---|
|  | 307 | +     */ | 
|---|
|  | 308 | +    if ((r->server != r->connection->base_server) && | 
|---|
|  | 309 | +        (verify & SSL_VERIFY_FAIL_IF_NO_PEER_CERT) && | 
|---|
|  | 310 | +        renegotiate && | 
|---|
|  | 311 | +        !(SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name))) { | 
|---|
|  | 312 | +        SSLSrvConfigRec *bssc = mySrvConfig(r->connection->base_server); | 
|---|
|  | 313 | + | 
|---|
|  | 314 | +        if (MODSSL_CFG_CA_NE(ca_cert_file, sc, bssc) || | 
|---|
|  | 315 | +            MODSSL_CFG_CA_NE(ca_cert_path, sc, bssc)) { | 
|---|
|  | 316 | +            ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | 
|---|
|  | 317 | +                 "Non-default virtual host with SSLVerify set to 'require' " | 
|---|
|  | 318 | +                 "and VirtualHost-specific CA certificate list is only " | 
|---|
|  | 319 | +                 "supported for clients with TLS server name indication " | 
|---|
|  | 320 | +                 "(SNI) support"); | 
|---|
|  | 321 | +            return HTTP_FORBIDDEN; | 
|---|
|  | 322 | +        } | 
|---|
|  | 323 | +    } | 
|---|
|  | 324 | +#endif /* OPENSSL_NO_TLSEXT */ | 
|---|
|  | 325 | #endif /* HAVE_SSL_SET_CERT_STORE */ | 
|---|
|  | 326 |  | 
|---|
|  | 327 | /* If a renegotiation is now required for this location, and the | 
|---|
| [1102] | 328 | @@ -675,8 +751,10 @@ int ssl_hook_Access(request_rec *r) | 
|---|
| [816] | 329 | /* | 
|---|
|  | 330 | * Finally check for acceptable renegotiation results | 
|---|
|  | 331 | */ | 
|---|
|  | 332 | -        if (dc->nVerifyClient != SSL_CVERIFY_NONE) { | 
|---|
|  | 333 | -            BOOL do_verify = (dc->nVerifyClient == SSL_CVERIFY_REQUIRE); | 
|---|
|  | 334 | +        if ((dc->nVerifyClient != SSL_CVERIFY_NONE) || | 
|---|
|  | 335 | +            (sc->server->auth.verify_mode != SSL_CVERIFY_NONE)) { | 
|---|
|  | 336 | +            BOOL do_verify = ((dc->nVerifyClient == SSL_CVERIFY_REQUIRE) || | 
|---|
|  | 337 | +                              (sc->server->auth.verify_mode == SSL_CVERIFY_REQUIRE)); | 
|---|
|  | 338 |  | 
|---|
|  | 339 | if (do_verify && (SSL_get_verify_result(ssl) != X509_V_OK)) { | 
|---|
|  | 340 | ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, | 
|---|
| [1102] | 341 | @@ -1006,6 +1084,9 @@ int ssl_hook_Fixup(request_rec *r) | 
|---|
| [683] | 342 | SSLDirConfigRec *dc = myDirConfig(r); | 
|---|
|  | 343 | apr_table_t *env = r->subprocess_env; | 
|---|
|  | 344 | char *var, *val = ""; | 
|---|
|  | 345 | +#ifndef OPENSSL_NO_TLSEXT | 
|---|
|  | 346 | +    const char *servername; | 
|---|
|  | 347 | +#endif | 
|---|
|  | 348 | STACK_OF(X509) *peer_certs; | 
|---|
|  | 349 | SSL *ssl; | 
|---|
|  | 350 | int i; | 
|---|
| [1102] | 351 | @@ -1027,6 +1108,13 @@ int ssl_hook_Fixup(request_rec *r) | 
|---|
| [683] | 352 | /* the always present HTTPS (=HTTP over SSL) flag! */ | 
|---|
|  | 353 | apr_table_setn(env, "HTTPS", "on"); | 
|---|
|  | 354 |  | 
|---|
|  | 355 | +#ifndef OPENSSL_NO_TLSEXT | 
|---|
|  | 356 | +    /* add content of SNI TLS extension (if supplied with ClientHello) */ | 
|---|
|  | 357 | +    if ((servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name))) { | 
|---|
|  | 358 | +        apr_table_set(env, "SSL_TLS_SNI", servername); | 
|---|
|  | 359 | +    } | 
|---|
|  | 360 | +#endif | 
|---|
|  | 361 | + | 
|---|
|  | 362 | /* standard SSL environment variables */ | 
|---|
|  | 363 | if (dc->nOptions & SSL_OPT_STDENVVARS) { | 
|---|
|  | 364 | for (i = 0; ssl_hook_Fixup_vars[i]; i++) { | 
|---|
| [1102] | 365 | @@ -1175,8 +1263,8 @@ int ssl_callback_SSLVerify(int ok, X509_STORE_CTX | 
|---|
| [816] | 366 | SSL *ssl = X509_STORE_CTX_get_ex_data(ctx, | 
|---|
|  | 367 | SSL_get_ex_data_X509_STORE_CTX_idx()); | 
|---|
|  | 368 | conn_rec *conn      = (conn_rec *)SSL_get_app_data(ssl); | 
|---|
|  | 369 | -    server_rec *s       = conn->base_server; | 
|---|
|  | 370 | request_rec *r      = (request_rec *)SSL_get_app_data2(ssl); | 
|---|
|  | 371 | +    server_rec *s       = r ? r->server : conn->base_server; | 
|---|
|  | 372 |  | 
|---|
|  | 373 | SSLSrvConfigRec *sc = mySrvConfig(s); | 
|---|
|  | 374 | SSLDirConfigRec *dc = r ? myDirConfig(r) : NULL; | 
|---|
| [1102] | 375 | @@ -1299,7 +1387,10 @@ int ssl_callback_SSLVerify(int ok, X509_STORE_CTX | 
|---|
| [816] | 376 |  | 
|---|
|  | 377 | int ssl_callback_SSLVerify_CRL(int ok, X509_STORE_CTX *ctx, conn_rec *c) | 
|---|
|  | 378 | { | 
|---|
|  | 379 | -    server_rec *s       = c->base_server; | 
|---|
|  | 380 | +    SSL *ssl = X509_STORE_CTX_get_ex_data(ctx, | 
|---|
|  | 381 | +                                          SSL_get_ex_data_X509_STORE_CTX_idx()); | 
|---|
|  | 382 | +    request_rec *r      = (request_rec *)SSL_get_app_data2(ssl); | 
|---|
|  | 383 | +    server_rec *s       = r ? r->server : c->base_server; | 
|---|
|  | 384 | SSLSrvConfigRec *sc = mySrvConfig(s); | 
|---|
|  | 385 | SSLConnRec *sslconn = myConnConfig(c); | 
|---|
|  | 386 | modssl_ctx_t *mctx  = myCtxConfig(sslconn, sc); | 
|---|
| [1102] | 387 | @@ -1819,3 +1910,141 @@ void ssl_callback_LogTracingState(MODSSL_INFO_CB_A | 
|---|
| [683] | 388 | } | 
|---|
|  | 389 | } | 
|---|
|  | 390 |  | 
|---|
|  | 391 | +#ifndef OPENSSL_NO_TLSEXT | 
|---|
|  | 392 | +/* | 
|---|
|  | 393 | + * This callback function is executed when OpenSSL encounters an extended | 
|---|
|  | 394 | + * client hello with a server name indication extension ("SNI", cf. RFC 4366). | 
|---|
|  | 395 | + */ | 
|---|
|  | 396 | +int ssl_callback_ServerNameIndication(SSL *ssl, int *al, modssl_ctx_t *mctx) | 
|---|
|  | 397 | +{ | 
|---|
|  | 398 | +    const char *servername = | 
|---|
|  | 399 | +                SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); | 
|---|
|  | 400 | + | 
|---|
|  | 401 | +    if (servername) { | 
|---|
|  | 402 | +        conn_rec *c = (conn_rec *)SSL_get_app_data(ssl); | 
|---|
|  | 403 | +        if (c) { | 
|---|
|  | 404 | +            if (ap_vhost_iterate_given_conn(c, ssl_find_vhost, | 
|---|
|  | 405 | +                                            (void *)servername)) { | 
|---|
|  | 406 | +                ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, | 
|---|
|  | 407 | +                              "SSL virtual host for servername %s found", | 
|---|
|  | 408 | +                              servername); | 
|---|
|  | 409 | +                return SSL_TLSEXT_ERR_OK; | 
|---|
|  | 410 | +            } | 
|---|
|  | 411 | +            else { | 
|---|
|  | 412 | +                ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, | 
|---|
|  | 413 | +                              "No matching SSL virtual host for servername " | 
|---|
|  | 414 | +                              "%s found (using default/first virtual host)", | 
|---|
|  | 415 | +                              servername); | 
|---|
|  | 416 | +                return SSL_TLSEXT_ERR_ALERT_WARNING; | 
|---|
|  | 417 | +            } | 
|---|
|  | 418 | +        } | 
|---|
|  | 419 | +    } | 
|---|
|  | 420 | + | 
|---|
|  | 421 | +    return SSL_TLSEXT_ERR_NOACK; | 
|---|
|  | 422 | +} | 
|---|
|  | 423 | + | 
|---|
|  | 424 | +/* | 
|---|
|  | 425 | + * Find a (name-based) SSL virtual host where either the ServerName | 
|---|
|  | 426 | + * or one of the ServerAliases matches the supplied name (to be used | 
|---|
|  | 427 | + * with ap_vhost_iterate_given_conn()) | 
|---|
|  | 428 | + */ | 
|---|
|  | 429 | +static int ssl_find_vhost(void *servername, conn_rec *c, server_rec *s) | 
|---|
|  | 430 | +{ | 
|---|
|  | 431 | +    SSLSrvConfigRec *sc; | 
|---|
|  | 432 | +    SSL *ssl; | 
|---|
|  | 433 | +    BOOL found = FALSE; | 
|---|
|  | 434 | +    apr_array_header_t *names; | 
|---|
|  | 435 | +    int i; | 
|---|
|  | 436 | + | 
|---|
|  | 437 | +    /* check ServerName */ | 
|---|
|  | 438 | +    if (!strcasecmp(servername, s->server_hostname)) { | 
|---|
|  | 439 | +        found = TRUE; | 
|---|
|  | 440 | +    } | 
|---|
|  | 441 | + | 
|---|
|  | 442 | +    /* | 
|---|
|  | 443 | +     * if not matched yet, check ServerAlias entries | 
|---|
|  | 444 | +     * (adapted from vhost.c:matches_aliases()) | 
|---|
|  | 445 | +     */ | 
|---|
|  | 446 | +    if (!found) { | 
|---|
|  | 447 | +        names = s->names; | 
|---|
|  | 448 | +        if (names) { | 
|---|
|  | 449 | +            char **name = (char **)names->elts; | 
|---|
|  | 450 | +            for (i = 0; i < names->nelts; ++i) { | 
|---|
|  | 451 | +                if (!name[i]) | 
|---|
|  | 452 | +                    continue; | 
|---|
|  | 453 | +                if (!strcasecmp(servername, name[i])) { | 
|---|
|  | 454 | +                    found = TRUE; | 
|---|
|  | 455 | +                    break; | 
|---|
|  | 456 | +                } | 
|---|
|  | 457 | +            } | 
|---|
|  | 458 | +        } | 
|---|
|  | 459 | +    } | 
|---|
|  | 460 | + | 
|---|
|  | 461 | +    /* if still no match, check ServerAlias entries with wildcards */ | 
|---|
|  | 462 | +    if (!found) { | 
|---|
|  | 463 | +        names = s->wild_names; | 
|---|
|  | 464 | +        if (names) { | 
|---|
|  | 465 | +            char **name = (char **)names->elts; | 
|---|
|  | 466 | +            for (i = 0; i < names->nelts; ++i) { | 
|---|
|  | 467 | +                if (!name[i]) | 
|---|
|  | 468 | +                    continue; | 
|---|
|  | 469 | +                if (!ap_strcasecmp_match(servername, name[i])) { | 
|---|
|  | 470 | +                    found = TRUE; | 
|---|
|  | 471 | +                    break; | 
|---|
|  | 472 | +                } | 
|---|
|  | 473 | +            } | 
|---|
|  | 474 | +        } | 
|---|
|  | 475 | +    } | 
|---|
|  | 476 | + | 
|---|
|  | 477 | +    /* set SSL_CTX (if matched) */ | 
|---|
|  | 478 | +    if (found && (ssl = ((SSLConnRec *)myConnConfig(c))->ssl) && | 
|---|
|  | 479 | +        (sc = mySrvConfig(s))) { | 
|---|
|  | 480 | +        SSL_set_SSL_CTX(ssl, sc->server->ssl_ctx); | 
|---|
|  | 481 | +        /* | 
|---|
|  | 482 | +         * SSL_set_SSL_CTX() only deals with the server cert, | 
|---|
|  | 483 | +         * so we need to duplicate a few additional settings | 
|---|
|  | 484 | +         * from the ctx by hand | 
|---|
|  | 485 | +         */ | 
|---|
|  | 486 | +        SSL_set_options(ssl, SSL_CTX_get_options(ssl->ctx)); | 
|---|
|  | 487 | +        if ((SSL_get_verify_mode(ssl) == SSL_VERIFY_NONE) || | 
|---|
|  | 488 | +            (SSL_num_renegotiations(ssl) == 0)) { | 
|---|
|  | 489 | +           /* | 
|---|
|  | 490 | +            * Only initialize the verification settings from the ctx | 
|---|
|  | 491 | +            * if they are not yet set, or if we're called when a new | 
|---|
|  | 492 | +            * SSL connection is set up (num_renegotiations == 0). | 
|---|
|  | 493 | +            * Otherwise, we would possibly reset a per-directory | 
|---|
|  | 494 | +            * configuration which was put into effect by ssl_hook_Access. | 
|---|
|  | 495 | +            */ | 
|---|
|  | 496 | +            SSL_set_verify(ssl, SSL_CTX_get_verify_mode(ssl->ctx), | 
|---|
|  | 497 | +                           SSL_CTX_get_verify_callback(ssl->ctx)); | 
|---|
|  | 498 | +        } | 
|---|
|  | 499 | + | 
|---|
|  | 500 | +        /* | 
|---|
| [816] | 501 | +         * We also need to make sure that the correct mctx | 
|---|
|  | 502 | +         * (accessed through the c->base_server->module_config vector) | 
|---|
|  | 503 | +         * is assigned to the connection - the CRL callback e.g. | 
|---|
| [683] | 504 | +         * makes use of it for retrieving its store (mctx->crl). | 
|---|
|  | 505 | +         * Since logging in callbacks uses c->base_server in many | 
|---|
|  | 506 | +         * cases, it also ensures that these messages are routed | 
|---|
| [816] | 507 | +         * to the proper log. | 
|---|
| [683] | 508 | +         */ | 
|---|
|  | 509 | +        c->base_server = s; | 
|---|
| [816] | 510 | + | 
|---|
|  | 511 | +        /* | 
|---|
|  | 512 | +         * There is one special filter callback, which is set | 
|---|
|  | 513 | +         * very early depending on the base_server's log level. | 
|---|
|  | 514 | +         * If this is not the first vhost we're now selecting | 
|---|
|  | 515 | +         * (and the first vhost doesn't use APLOG_DEBUG), then | 
|---|
|  | 516 | +         * we need to set that callback here. | 
|---|
|  | 517 | +         */ | 
|---|
| [683] | 518 | +        if (c->base_server->loglevel >= APLOG_DEBUG) { | 
|---|
|  | 519 | +            BIO_set_callback(SSL_get_rbio(ssl), ssl_io_data_cb); | 
|---|
|  | 520 | +            BIO_set_callback_arg(SSL_get_rbio(ssl), (void *)ssl); | 
|---|
|  | 521 | +        } | 
|---|
|  | 522 | + | 
|---|
|  | 523 | +        return 1; | 
|---|
|  | 524 | +    } | 
|---|
|  | 525 | + | 
|---|
|  | 526 | +    return 0; | 
|---|
|  | 527 | +} | 
|---|
|  | 528 | +#endif | 
|---|
|  | 529 | Index: httpd-2.2.x/modules/ssl/ssl_toolkit_compat.h | 
|---|
|  | 530 | =================================================================== | 
|---|
| [1102] | 531 | --- httpd-2.2.x/modules/ssl/ssl_toolkit_compat.h        (revision 763153) | 
|---|
| [683] | 532 | +++ httpd-2.2.x/modules/ssl/ssl_toolkit_compat.h        (working copy) | 
|---|
| [1102] | 533 | @@ -264,6 +264,12 @@ typedef void (*modssl_popfree_fn)(char *data); | 
|---|
| [683] | 534 | #define SSL_SESS_CACHE_NO_INTERNAL  SSL_SESS_CACHE_NO_INTERNAL_LOOKUP | 
|---|
|  | 535 | #endif | 
|---|
|  | 536 |  | 
|---|
|  | 537 | +#ifndef OPENSSL_NO_TLSEXT | 
|---|
|  | 538 | +#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME | 
|---|
|  | 539 | +#define OPENSSL_NO_TLSEXT | 
|---|
|  | 540 | +#endif | 
|---|
|  | 541 | +#endif | 
|---|
|  | 542 | + | 
|---|
|  | 543 | #endif /* SSL_TOOLKIT_COMPAT_H */ | 
|---|
|  | 544 |  | 
|---|
|  | 545 | /** @} */ | 
|---|