| [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) || | 
|---|
 | 216 | +        (sc->server->auth.verify_depth != UNSET)) { | 
|---|
 | 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 |  /** @} */ | 
|---|