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