| [683] | 1 | httpd-2.2.8-sni.patch - server name indication support for Apache 2.2 | 
|---|
|  | 2 | (see RFC 4366, "Transport Layer Security (TLS) Extensions") | 
|---|
|  | 3 |  | 
|---|
|  | 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) | 
|---|
|  | 6 |  | 
|---|
|  | 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"). | 
|---|
|  | 11 |  | 
|---|
|  | 12 | Index: httpd-2.2.x/modules/ssl/ssl_private.h | 
|---|
|  | 13 | =================================================================== | 
|---|
|  | 14 | --- httpd-2.2.x/modules/ssl/ssl_private.h       (revision 627519) | 
|---|
|  | 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" | 
|---|
|  | 24 | @@ -555,6 +556,9 @@ | 
|---|
|  | 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 | =================================================================== | 
|---|
|  | 36 | --- httpd-2.2.x/modules/ssl/ssl_engine_init.c   (revision 627519) | 
|---|
|  | 37 | +++ httpd-2.2.x/modules/ssl/ssl_engine_init.c   (working copy) | 
|---|
|  | 38 | @@ -355,6 +355,33 @@ | 
|---|
|  | 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, | 
|---|
|  | 72 | @@ -687,6 +714,9 @@ | 
|---|
|  | 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 |  | 
|---|
|  | 82 | @@ -1038,7 +1068,11 @@ | 
|---|
|  | 83 | if ((ps = (server_rec *)apr_hash_get(table, key, klen))) { | 
|---|
|  | 84 | ap_log_error(APLOG_MARK, APLOG_WARNING, 0, | 
|---|
|  | 85 | base_server, | 
|---|
|  | 86 | +#ifdef OPENSSL_NO_TLSEXT | 
|---|
|  | 87 | "Init: SSL server IP/port conflict: " | 
|---|
|  | 88 | +#else | 
|---|
|  | 89 | +                         "Init: SSL server IP/port overlap: " | 
|---|
|  | 90 | +#endif | 
|---|
|  | 91 | "%s (%s:%d) vs. %s (%s:%d)", | 
|---|
|  | 92 | ssl_util_vhostid(p, s), | 
|---|
|  | 93 | (s->defn_name ? s->defn_name : "unknown"), | 
|---|
|  | 94 | @@ -1055,8 +1089,14 @@ | 
|---|
|  | 95 |  | 
|---|
|  | 96 | if (conflict) { | 
|---|
|  | 97 | ap_log_error(APLOG_MARK, APLOG_WARNING, 0, base_server, | 
|---|
|  | 98 | +#ifdef OPENSSL_NO_TLSEXT | 
|---|
|  | 99 | "Init: You should not use name-based " | 
|---|
|  | 100 | "virtual hosts in conjunction with SSL!!"); | 
|---|
|  | 101 | +#else | 
|---|
|  | 102 | +                     "Init: Name-based SSL virtual hosts only " | 
|---|
|  | 103 | +                     "work for clients with TLS server name indication " | 
|---|
|  | 104 | +                     "support (RFC 4366)"); | 
|---|
|  | 105 | +#endif | 
|---|
|  | 106 | } | 
|---|
|  | 107 | } | 
|---|
|  | 108 |  | 
|---|
|  | 109 | Index: httpd-2.2.x/modules/ssl/ssl_engine_vars.c | 
|---|
|  | 110 | =================================================================== | 
|---|
|  | 111 | --- httpd-2.2.x/modules/ssl/ssl_engine_vars.c   (revision 627519) | 
|---|
|  | 112 | +++ httpd-2.2.x/modules/ssl/ssl_engine_vars.c   (working copy) | 
|---|
|  | 113 | @@ -320,6 +320,12 @@ | 
|---|
|  | 114 | else if (ssl != NULL && strcEQ(var, "COMPRESS_METHOD")) { | 
|---|
|  | 115 | result = ssl_var_lookup_ssl_compress_meth(ssl); | 
|---|
|  | 116 | } | 
|---|
|  | 117 | +#ifndef OPENSSL_NO_TLSEXT | 
|---|
|  | 118 | +    else if (ssl != NULL && strcEQ(var, "TLS_SNI")) { | 
|---|
|  | 119 | +        result = apr_pstrdup(p, SSL_get_servername(ssl, | 
|---|
|  | 120 | +                                                   TLSEXT_NAMETYPE_host_name)); | 
|---|
|  | 121 | +    } | 
|---|
|  | 122 | +#endif | 
|---|
|  | 123 | return result; | 
|---|
|  | 124 | } | 
|---|
|  | 125 |  | 
|---|
|  | 126 | Index: httpd-2.2.x/modules/ssl/ssl_engine_kernel.c | 
|---|
|  | 127 | =================================================================== | 
|---|
|  | 128 | --- httpd-2.2.x/modules/ssl/ssl_engine_kernel.c (revision 627519) | 
|---|
|  | 129 | +++ httpd-2.2.x/modules/ssl/ssl_engine_kernel.c (working copy) | 
|---|
|  | 130 | @@ -31,6 +31,9 @@ | 
|---|
|  | 131 | #include "ssl_private.h" | 
|---|
|  | 132 |  | 
|---|
|  | 133 | static void ssl_configure_env(request_rec *r, SSLConnRec *sslconn); | 
|---|
|  | 134 | +#ifndef OPENSSL_NO_TLSEXT | 
|---|
|  | 135 | +static int ssl_find_vhost(void *servername, conn_rec *c, server_rec *s); | 
|---|
|  | 136 | +#endif | 
|---|
|  | 137 |  | 
|---|
|  | 138 | /* | 
|---|
|  | 139 | *  Post Read Request Handler | 
|---|
|  | 140 | @@ -39,6 +42,9 @@ | 
|---|
|  | 141 | { | 
|---|
|  | 142 | SSLConnRec *sslconn = myConnConfig(r->connection); | 
|---|
|  | 143 | SSL *ssl; | 
|---|
|  | 144 | +#ifndef OPENSSL_NO_TLSEXT | 
|---|
|  | 145 | +    const char *servername; | 
|---|
|  | 146 | +#endif | 
|---|
|  | 147 |  | 
|---|
|  | 148 | if (!sslconn) { | 
|---|
|  | 149 | return DECLINED; | 
|---|
|  | 150 | @@ -87,6 +93,14 @@ | 
|---|
|  | 151 | if (!ssl) { | 
|---|
|  | 152 | return DECLINED; | 
|---|
|  | 153 | } | 
|---|
|  | 154 | +#ifndef OPENSSL_NO_TLSEXT | 
|---|
|  | 155 | +    if (!r->hostname && | 
|---|
|  | 156 | +        (servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name))) { | 
|---|
|  | 157 | +        /* Use the SNI extension as the hostname if no Host: header was sent */ | 
|---|
|  | 158 | +        r->hostname = apr_pstrdup(r->pool, servername); | 
|---|
|  | 159 | +        ap_update_vhost_from_headers(r); | 
|---|
|  | 160 | +    } | 
|---|
|  | 161 | +#endif | 
|---|
|  | 162 | SSL_set_app_data2(ssl, r); | 
|---|
|  | 163 |  | 
|---|
|  | 164 | /* | 
|---|
|  | 165 | @@ -997,6 +1011,9 @@ | 
|---|
|  | 166 | SSLDirConfigRec *dc = myDirConfig(r); | 
|---|
|  | 167 | apr_table_t *env = r->subprocess_env; | 
|---|
|  | 168 | char *var, *val = ""; | 
|---|
|  | 169 | +#ifndef OPENSSL_NO_TLSEXT | 
|---|
|  | 170 | +    const char *servername; | 
|---|
|  | 171 | +#endif | 
|---|
|  | 172 | STACK_OF(X509) *peer_certs; | 
|---|
|  | 173 | SSL *ssl; | 
|---|
|  | 174 | int i; | 
|---|
|  | 175 | @@ -1018,6 +1035,13 @@ | 
|---|
|  | 176 | /* the always present HTTPS (=HTTP over SSL) flag! */ | 
|---|
|  | 177 | apr_table_setn(env, "HTTPS", "on"); | 
|---|
|  | 178 |  | 
|---|
|  | 179 | +#ifndef OPENSSL_NO_TLSEXT | 
|---|
|  | 180 | +    /* add content of SNI TLS extension (if supplied with ClientHello) */ | 
|---|
|  | 181 | +    if ((servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name))) { | 
|---|
|  | 182 | +        apr_table_set(env, "SSL_TLS_SNI", servername); | 
|---|
|  | 183 | +    } | 
|---|
|  | 184 | +#endif | 
|---|
|  | 185 | + | 
|---|
|  | 186 | /* standard SSL environment variables */ | 
|---|
|  | 187 | if (dc->nOptions & SSL_OPT_STDENVVARS) { | 
|---|
|  | 188 | for (i = 0; ssl_hook_Fixup_vars[i]; i++) { | 
|---|
|  | 189 | @@ -1810,3 +1834,136 @@ | 
|---|
|  | 190 | } | 
|---|
|  | 191 | } | 
|---|
|  | 192 |  | 
|---|
|  | 193 | +#ifndef OPENSSL_NO_TLSEXT | 
|---|
|  | 194 | +/* | 
|---|
|  | 195 | + * This callback function is executed when OpenSSL encounters an extended | 
|---|
|  | 196 | + * client hello with a server name indication extension ("SNI", cf. RFC 4366). | 
|---|
|  | 197 | + */ | 
|---|
|  | 198 | +int ssl_callback_ServerNameIndication(SSL *ssl, int *al, modssl_ctx_t *mctx) | 
|---|
|  | 199 | +{ | 
|---|
|  | 200 | +    const char *servername = | 
|---|
|  | 201 | +                SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); | 
|---|
|  | 202 | + | 
|---|
|  | 203 | +    if (servername) { | 
|---|
|  | 204 | +        conn_rec *c = (conn_rec *)SSL_get_app_data(ssl); | 
|---|
|  | 205 | +        if (c) { | 
|---|
|  | 206 | +            if (ap_vhost_iterate_given_conn(c, ssl_find_vhost, | 
|---|
|  | 207 | +                                            (void *)servername)) { | 
|---|
|  | 208 | +                ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, | 
|---|
|  | 209 | +                              "SSL virtual host for servername %s found", | 
|---|
|  | 210 | +                              servername); | 
|---|
|  | 211 | +                return SSL_TLSEXT_ERR_OK; | 
|---|
|  | 212 | +            } | 
|---|
|  | 213 | +            else { | 
|---|
|  | 214 | +                ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, | 
|---|
|  | 215 | +                              "No matching SSL virtual host for servername " | 
|---|
|  | 216 | +                              "%s found (using default/first virtual host)", | 
|---|
|  | 217 | +                              servername); | 
|---|
|  | 218 | +                return SSL_TLSEXT_ERR_ALERT_WARNING; | 
|---|
|  | 219 | +            } | 
|---|
|  | 220 | +        } | 
|---|
|  | 221 | +    } | 
|---|
|  | 222 | + | 
|---|
|  | 223 | +    return SSL_TLSEXT_ERR_NOACK; | 
|---|
|  | 224 | +} | 
|---|
|  | 225 | + | 
|---|
|  | 226 | +/* | 
|---|
|  | 227 | + * Find a (name-based) SSL virtual host where either the ServerName | 
|---|
|  | 228 | + * or one of the ServerAliases matches the supplied name (to be used | 
|---|
|  | 229 | + * with ap_vhost_iterate_given_conn()) | 
|---|
|  | 230 | + */ | 
|---|
|  | 231 | +static int ssl_find_vhost(void *servername, conn_rec *c, server_rec *s) | 
|---|
|  | 232 | +{ | 
|---|
|  | 233 | +    SSLSrvConfigRec *sc; | 
|---|
|  | 234 | +    SSL *ssl; | 
|---|
|  | 235 | +    BOOL found = FALSE; | 
|---|
|  | 236 | +    apr_array_header_t *names; | 
|---|
|  | 237 | +    int i; | 
|---|
|  | 238 | + | 
|---|
|  | 239 | +    /* check ServerName */ | 
|---|
|  | 240 | +    if (!strcasecmp(servername, s->server_hostname)) { | 
|---|
|  | 241 | +        found = TRUE; | 
|---|
|  | 242 | +    } | 
|---|
|  | 243 | + | 
|---|
|  | 244 | +    /* | 
|---|
|  | 245 | +     * if not matched yet, check ServerAlias entries | 
|---|
|  | 246 | +     * (adapted from vhost.c:matches_aliases()) | 
|---|
|  | 247 | +     */ | 
|---|
|  | 248 | +    if (!found) { | 
|---|
|  | 249 | +        names = s->names; | 
|---|
|  | 250 | +        if (names) { | 
|---|
|  | 251 | +            char **name = (char **)names->elts; | 
|---|
|  | 252 | +            for (i = 0; i < names->nelts; ++i) { | 
|---|
|  | 253 | +                if (!name[i]) | 
|---|
|  | 254 | +                    continue; | 
|---|
|  | 255 | +                if (!strcasecmp(servername, name[i])) { | 
|---|
|  | 256 | +                    found = TRUE; | 
|---|
|  | 257 | +                    break; | 
|---|
|  | 258 | +                } | 
|---|
|  | 259 | +            } | 
|---|
|  | 260 | +        } | 
|---|
|  | 261 | +    } | 
|---|
|  | 262 | + | 
|---|
|  | 263 | +    /* if still no match, check ServerAlias entries with wildcards */ | 
|---|
|  | 264 | +    if (!found) { | 
|---|
|  | 265 | +        names = s->wild_names; | 
|---|
|  | 266 | +        if (names) { | 
|---|
|  | 267 | +            char **name = (char **)names->elts; | 
|---|
|  | 268 | +            for (i = 0; i < names->nelts; ++i) { | 
|---|
|  | 269 | +                if (!name[i]) | 
|---|
|  | 270 | +                    continue; | 
|---|
|  | 271 | +                if (!ap_strcasecmp_match(servername, name[i])) { | 
|---|
|  | 272 | +                    found = TRUE; | 
|---|
|  | 273 | +                    break; | 
|---|
|  | 274 | +                } | 
|---|
|  | 275 | +            } | 
|---|
|  | 276 | +        } | 
|---|
|  | 277 | +    } | 
|---|
|  | 278 | + | 
|---|
|  | 279 | +    /* set SSL_CTX (if matched) */ | 
|---|
|  | 280 | +    if (found && (ssl = ((SSLConnRec *)myConnConfig(c))->ssl) && | 
|---|
|  | 281 | +        (sc = mySrvConfig(s))) { | 
|---|
|  | 282 | +        SSL_set_SSL_CTX(ssl, sc->server->ssl_ctx); | 
|---|
|  | 283 | +        /* | 
|---|
|  | 284 | +         * SSL_set_SSL_CTX() only deals with the server cert, | 
|---|
|  | 285 | +         * so we need to duplicate a few additional settings | 
|---|
|  | 286 | +         * from the ctx by hand | 
|---|
|  | 287 | +         */ | 
|---|
|  | 288 | +        SSL_set_options(ssl, SSL_CTX_get_options(ssl->ctx)); | 
|---|
|  | 289 | +        if ((SSL_get_verify_mode(ssl) == SSL_VERIFY_NONE) || | 
|---|
|  | 290 | +            (SSL_num_renegotiations(ssl) == 0)) { | 
|---|
|  | 291 | +           /* | 
|---|
|  | 292 | +            * Only initialize the verification settings from the ctx | 
|---|
|  | 293 | +            * if they are not yet set, or if we're called when a new | 
|---|
|  | 294 | +            * SSL connection is set up (num_renegotiations == 0). | 
|---|
|  | 295 | +            * Otherwise, we would possibly reset a per-directory | 
|---|
|  | 296 | +            * configuration which was put into effect by ssl_hook_Access. | 
|---|
|  | 297 | +            */ | 
|---|
|  | 298 | +            SSL_set_verify(ssl, SSL_CTX_get_verify_mode(ssl->ctx), | 
|---|
|  | 299 | +                           SSL_CTX_get_verify_callback(ssl->ctx)); | 
|---|
|  | 300 | +        } | 
|---|
|  | 301 | + | 
|---|
|  | 302 | +        /* | 
|---|
|  | 303 | +         * We also need to make sure that the correct mctx is | 
|---|
|  | 304 | +         * assigned to the connection - the CRL callback e.g. | 
|---|
|  | 305 | +         * makes use of it for retrieving its store (mctx->crl). | 
|---|
|  | 306 | +         * Since logging in callbacks uses c->base_server in many | 
|---|
|  | 307 | +         * cases, it also ensures that these messages are routed | 
|---|
|  | 308 | +         * to the proper log. And finally, there is one special | 
|---|
|  | 309 | +         * filter callback, which is set very early depending on the | 
|---|
|  | 310 | +         * base_server's log level. If this is not the first vhost | 
|---|
|  | 311 | +         * we're now selecting (and the first vhost doesn't use | 
|---|
|  | 312 | +         * APLOG_DEBUG), then we need to set that callback here. | 
|---|
|  | 313 | +         */ | 
|---|
|  | 314 | +        c->base_server = s; | 
|---|
|  | 315 | +        if (c->base_server->loglevel >= APLOG_DEBUG) { | 
|---|
|  | 316 | +            BIO_set_callback(SSL_get_rbio(ssl), ssl_io_data_cb); | 
|---|
|  | 317 | +            BIO_set_callback_arg(SSL_get_rbio(ssl), (void *)ssl); | 
|---|
|  | 318 | +        } | 
|---|
|  | 319 | + | 
|---|
|  | 320 | +        return 1; | 
|---|
|  | 321 | +    } | 
|---|
|  | 322 | + | 
|---|
|  | 323 | +    return 0; | 
|---|
|  | 324 | +} | 
|---|
|  | 325 | +#endif | 
|---|
|  | 326 | Index: httpd-2.2.x/modules/ssl/ssl_toolkit_compat.h | 
|---|
|  | 327 | =================================================================== | 
|---|
|  | 328 | --- httpd-2.2.x/modules/ssl/ssl_toolkit_compat.h        (revision 627519) | 
|---|
|  | 329 | +++ httpd-2.2.x/modules/ssl/ssl_toolkit_compat.h        (working copy) | 
|---|
|  | 330 | @@ -264,6 +264,12 @@ | 
|---|
|  | 331 | #define SSL_SESS_CACHE_NO_INTERNAL  SSL_SESS_CACHE_NO_INTERNAL_LOOKUP | 
|---|
|  | 332 | #endif | 
|---|
|  | 333 |  | 
|---|
|  | 334 | +#ifndef OPENSSL_NO_TLSEXT | 
|---|
|  | 335 | +#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME | 
|---|
|  | 336 | +#define OPENSSL_NO_TLSEXT | 
|---|
|  | 337 | +#endif | 
|---|
|  | 338 | +#endif | 
|---|
|  | 339 | + | 
|---|
|  | 340 | #endif /* SSL_TOOLKIT_COMPAT_H */ | 
|---|
|  | 341 |  | 
|---|
|  | 342 | /** @} */ | 
|---|