source: server/common/patches/httpd-2.2.8-sni.patch @ 686

Last change on this file since 686 was 683, checked in by andersk, 15 years ago
Add SNI support to the httpd package.
File size: 11.7 KB
RevLine 
[683]1httpd-2.2.8-sni.patch - server name indication support for Apache 2.2
2(see RFC 4366, "Transport Layer Security (TLS) Extensions")
3
4based on a patch from the EdelKey project
5(http://www.edelweb.fr/EdelKey/files/apache-2.2.0+0.9.9+servername.patch)
6
7Needs openssl-SNAP-20060330 / OpenSSL 0.9.8f or later
8to work properly (ftp://ftp.openssl.org/snapshot/). The 0.9.8 versions
9must be configured explicitly for TLS extension support at compile time
10("./config enable-tlsext").
11
12Index: 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 *);
34Index: 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 
109Index: 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 
126Index: 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
326Index: 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 /** @} */
Note: See TracBrowser for help on using the repository browser.