httpd-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ic...@apache.org
Subject svn commit: r1701655 [4/4] - in /httpd/httpd/branches/2.4.17-protocols-http2: ./ build/ docs/conf/ docs/conf/extra/ docs/manual/mod/ include/ modules/ modules/http/ modules/http2/ modules/http2/m4/ modules/http2/mod-h2.xcodeproj/ modules/http2/mod_h2/ ...
Date Mon, 07 Sep 2015 17:37:21 GMT
Copied: httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_worker.c (from r1690248,
httpd/httpd/trunk/modules/http2/h2_worker.c)
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_worker.c?p2=httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_worker.c&p1=httpd/httpd/trunk/modules/http2/h2_worker.c&r1=1690248&r2=1701655&rev=1701655&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_worker.c (original)
+++ httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_worker.c Mon Sep  7 17:37:19
2015
@@ -26,7 +26,7 @@
 #include "h2_task.h"
 #include "h2_worker.h"
 
-static void *execute(apr_thread_t *thread, void *wctx)
+static void* APR_THREAD_FUNC execute(apr_thread_t *thread, void *wctx)
 {
     h2_worker *worker = (h2_worker *)wctx;
     apr_status_t status = APR_SUCCESS;
@@ -41,7 +41,8 @@ static void *execute(apr_thread_t *threa
                                APR_PROTO_TCP, worker->pool);
     if (status != APR_SUCCESS) {
         ap_log_perror(APLOG_MARK, APLOG_ERR, status, worker->pool,
-                      "h2_worker(%d): alloc socket", worker->id);
+                      APLOGNO(02948) "h2_worker(%d): alloc socket", 
+                      worker->id);
         worker->worker_done(worker, worker->ctx);
         return NULL;
     }
@@ -79,6 +80,7 @@ h2_worker *h2_worker_create(int id,
 {
     apr_allocator_t *allocator = NULL;
     apr_pool_t *pool = NULL;
+    h2_worker *w;
     
     apr_status_t status = apr_allocator_create(&allocator);
     if (status != APR_SUCCESS) {
@@ -91,7 +93,7 @@ h2_worker *h2_worker_create(int id,
     }
     apr_allocator_owner_set(allocator, pool);
 
-    h2_worker *w = apr_pcalloc(pool, sizeof(h2_worker));
+    w = apr_pcalloc(pool, sizeof(h2_worker));
     if (w) {
         APR_RING_ELEM_INIT(w, link);
         

Propchange: httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_worker.c
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_worker.h
------------------------------------------------------------------------------
    svn:eol-style = native

Copied: httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_workers.c (from r1690248,
httpd/httpd/trunk/modules/http2/h2_workers.c)
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_workers.c?p2=httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_workers.c&p1=httpd/httpd/trunk/modules/http2/h2_workers.c&r1=1690248&r2=1701655&rev=1701655&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_workers.c (original)
+++ httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_workers.c Mon Sep  7 17:37:19
2015
@@ -238,11 +238,13 @@ static apr_status_t h2_workers_start(h2_
 h2_workers *h2_workers_create(server_rec *s, apr_pool_t *pool,
                               int min_size, int max_size)
 {
+    apr_status_t status;
+    h2_workers *workers;
     AP_DEBUG_ASSERT(s);
     AP_DEBUG_ASSERT(pool);
-    apr_status_t status = APR_SUCCESS;
+    status = APR_SUCCESS;
 
-    h2_workers *workers = apr_pcalloc(pool, sizeof(h2_workers));
+    workers = apr_pcalloc(pool, sizeof(h2_workers));
     if (workers) {
         workers->s = s;
         workers->pool = pool;
@@ -341,7 +343,7 @@ void h2_workers_set_max_idle_secs(h2_wor
 {
     if (idle_secs <= 0) {
         ap_log_error(APLOG_MARK, APLOG_WARNING, 0, workers->s,
-                     "h2_workers: max_worker_idle_sec value of %d"
+                     APLOGNO(02962) "h2_workers: max_worker_idle_sec value of %d"
                      " is not valid, ignored.", idle_secs);
         return;
     }

Propchange: httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_workers.c
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/h2_workers.h
------------------------------------------------------------------------------
    svn:eol-style = native

Copied: httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/mod_h2.c (from r1690248,
httpd/httpd/trunk/modules/http2/mod_h2.c)
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/mod_h2.c?p2=httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/mod_h2.c&p1=httpd/httpd/trunk/modules/http2/mod_h2.c&r1=1690248&r2=1701655&rev=1701655&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/mod_h2.c (original)
+++ httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/mod_h2.c Mon Sep  7 17:37:19
2015
@@ -31,8 +31,7 @@
 #include "h2_config.h"
 #include "h2_ctx.h"
 #include "h2_h2.h"
-#include "h2_alpn.h"
-#include "h2_upgrade.h"
+#include "h2_switch.h"
 #include "h2_version.h"
 
 
@@ -94,14 +93,14 @@ static int h2_post_config(apr_pool_t *p,
             break;
         case H2_MPM_UNKNOWN:
             /* ??? */
-            ap_log_error( APLOG_MARK, APLOG_ERR, 0, s,
+            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
                          "post_config: mpm type unknown");
             break;
     }
     
     status = h2_h2_init(p, s);
     if (status == APR_SUCCESS) {
-        status = h2_alpn_init(p, s);
+        status = h2_switch_init(p, s);
     }
     
     return status;
@@ -116,23 +115,18 @@ static void h2_child_init(apr_pool_t *po
     apr_status_t status = h2_conn_child_init(pool, s);
     if (status != APR_SUCCESS) {
         ap_log_error(APLOG_MARK, APLOG_ERR, status, s,
-                      "initializing connection handling");
+                     APLOGNO(02949) "initializing connection handling");
     }
 }
 
-const char *h2_get_protocol(conn_rec *c)
-{
-    return h2_ctx_pnego_get(h2_ctx_get(c));
-}
-
 /* Install this module into the apache2 infrastructure.
  */
 static void h2_hooks(apr_pool_t *pool)
 {
-    ap_log_perror(APLOG_MARK, APLOG_INFO, 0, pool, "installing hooks");
-    
     static const char *const mod_ssl[] = { "mod_ssl.c", NULL};
     
+    ap_log_perror(APLOG_MARK, APLOG_INFO, 0, pool, "installing hooks");
+    
     /* Run once after configuration is set, but before mpm children initialize.
      */
     ap_hook_post_config(h2_post_config, mod_ssl, NULL, APR_HOOK_MIDDLE);
@@ -142,16 +136,11 @@ static void h2_hooks(apr_pool_t *pool)
     ap_hook_child_init(h2_child_init, NULL, NULL, APR_HOOK_MIDDLE);
 
     h2_h2_register_hooks();
-    h2_alpn_register_hooks();
-    h2_upgrade_register_hooks();
+    h2_switch_register_hooks();
     h2_task_register_hooks();
 
     h2_alt_svc_register_hooks();
     
-    /* We offer a function to other modules that lets them retrieve
-     * the h2 protocol used on a connection (if any).
-     */
-    APR_REGISTER_OPTIONAL_FN(h2_get_protocol);
 }
 
 

Propchange: httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/mod_h2.c
------------------------------------------------------------------------------
    svn:eol-style = native

Copied: httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/mod_h2.h (from r1690248,
httpd/httpd/trunk/modules/http2/mod_h2.h)
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/mod_h2.h?p2=httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/mod_h2.h&p1=httpd/httpd/trunk/modules/http2/mod_h2.h&r1=1690248&r2=1701655&rev=1701655&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/mod_h2.h (original)
+++ httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/mod_h2.h Mon Sep  7 17:37:19
2015
@@ -16,13 +16,4 @@
 #ifndef mod_h2_mod_h2_h
 #define mod_h2_mod_h2_h
 
-const char *h2_get_protocol(conn_rec *c);
-
-
-/** 
- * An optional function which returns the h2 protocol used on the given
- * connection and NULL if no h2* protocol is active on it.
- */
-APR_DECLARE_OPTIONAL_FN(const char *, h2_get_protocol, (conn_rec*));
-
 #endif

Propchange: httpd/httpd/branches/2.4.17-protocols-http2/modules/http2/mod_h2.h
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: httpd/httpd/branches/2.4.17-protocols-http2/modules/ssl/ssl_engine_init.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.17-protocols-http2/modules/ssl/ssl_engine_init.c?rev=1701655&r1=1701654&r2=1701655&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.17-protocols-http2/modules/ssl/ssl_engine_init.c (original)
+++ httpd/httpd/branches/2.4.17-protocols-http2/modules/ssl/ssl_engine_init.c Mon Sep  7 17:37:19
2015
@@ -625,6 +625,10 @@ static void ssl_init_ctx_callbacks(serve
     SSL_CTX_set_tmp_dh_callback(ctx,  ssl_callback_TmpDH);
 
     SSL_CTX_set_info_callback(ctx, ssl_callback_Info);
+
+#ifdef HAVE_TLS_ALPN
+    SSL_CTX_set_alpn_select_cb(ctx, ssl_callback_alpn_select, NULL);
+#endif
 }
 
 static apr_status_t ssl_init_ctx_verify(server_rec *s,

Modified: httpd/httpd/branches/2.4.17-protocols-http2/modules/ssl/ssl_engine_io.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.17-protocols-http2/modules/ssl/ssl_engine_io.c?rev=1701655&r1=1701654&r2=1701655&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.17-protocols-http2/modules/ssl/ssl_engine_io.c (original)
+++ httpd/httpd/branches/2.4.17-protocols-http2/modules/ssl/ssl_engine_io.c Mon Sep  7 17:37:19
2015
@@ -297,6 +297,9 @@ typedef struct {
     apr_pool_t *pool;
     char buffer[AP_IOBUFSIZE];
     ssl_filter_ctx_t *filter_ctx;
+#ifdef HAVE_TLS_ALPN
+    int alpn_finished;  /* 1 if ALPN has finished, 0 otherwise */
+#endif
 } bio_filter_in_ctx_t;
 
 /*
@@ -1412,6 +1415,42 @@ static apr_status_t ssl_io_filter_input(
         APR_BRIGADE_INSERT_TAIL(bb, bucket);
     }
 
+#ifdef HAVE_TLS_ALPN
+    /* By this point, Application-Layer Protocol Negotiation (ALPN) should be 
+     * completed (if our version of OpenSSL supports it). If we haven't already, 
+     * find out which protocol was decided upon and inform other modules 
+     * by calling alpn_proto_negotiated_hook. 
+     */
+    if (!inctx->alpn_finished) {
+        SSLConnRec *sslconn = myConnConfig(f->c);
+        const unsigned char *next_proto = NULL;
+        unsigned next_proto_len = 0;
+        const char *protocol;
+        int n;
+
+        SSL_get0_alpn_selected(inctx->ssl, &next_proto, &next_proto_len);
+        if (next_proto && next_proto_len) {
+            protocol = apr_pstrmemdup(f->c->pool, (const char *)next_proto,
+                                       next_proto_len);
+            ap_log_cerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, f->c,
+                          APLOGNO(02836) "ALPN selected protocol: '%s'",
+                          protocol);
+            
+            if (strcmp(protocol, ap_get_protocol(f->c))) {
+                status = ap_switch_protocol(f->c, NULL, sslconn->server,
+                                            protocol);
+                if (status != APR_SUCCESS) {
+                    ap_log_cerror(APLOG_MARK, APLOG_ERR, status, f->c,
+                                  APLOGNO(02908) "protocol switch to '%s' failed",
+                                  protocol);
+                    return status;
+                }
+            }
+        }
+        inctx->alpn_finished = 1;
+    }
+#endif
+
     return APR_SUCCESS;
 }
 
@@ -1893,6 +1932,9 @@ static void ssl_io_input_add_filter(ssl_
     inctx->block = APR_BLOCK_READ;
     inctx->pool = c->pool;
     inctx->filter_ctx = filter_ctx;
+#ifdef HAVE_TLS_ALPN
+    inctx->alpn_finished = 0;
+#endif
 }
 
 /* The request_rec pointer is passed in here only to ensure that the

Modified: httpd/httpd/branches/2.4.17-protocols-http2/modules/ssl/ssl_engine_kernel.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.17-protocols-http2/modules/ssl/ssl_engine_kernel.c?rev=1701655&r1=1701654&r2=1701655&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.17-protocols-http2/modules/ssl/ssl_engine_kernel.c (original)
+++ httpd/httpd/branches/2.4.17-protocols-http2/modules/ssl/ssl_engine_kernel.c Mon Sep  7
17:37:19 2015
@@ -199,11 +199,18 @@ int ssl_hook_ReadReq(request_rec *r)
             if (rv != APR_SUCCESS || scope_id) {
                 return HTTP_BAD_REQUEST;
             }
-            if (strcasecmp(host, servername)) {
+            if (strcasecmp(host, servername) 
+                || !sslconn->server 
+                || !ssl_util_vhost_matches(host, sslconn->server)) {
+                /* 
+                 * We are really not in Kansas anymore...
+                 * The request hostname does not match the SNI and does not
+                 * select the virtual host that was selected by the SNI.
+                 */
                 ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, APLOGNO(02032)
-                            "Hostname %s provided via SNI and hostname %s provided"
-                            " via HTTP are different", servername, host);
-                return HTTP_BAD_REQUEST;
+                             "Hostname %s provided via SNI and hostname %s provided"
+                             " via HTTP are different", servername, host);
+                return HTTP_MISDIRECTED_REQUEST;
             }
         }
         else if (((sc->strict_sni_vhost_check == SSL_ENABLED_TRUE)
@@ -1903,23 +1910,29 @@ void ssl_callback_Info(const SSL *ssl, i
 
 #ifdef HAVE_TLSEXT
 /*
- * This callback function is executed when OpenSSL encounters an extended
+ * This function sets the virtual host from an extended
  * client hello with a server name indication extension ("SNI", cf. RFC 6066).
  */
-int ssl_callback_ServerNameIndication(SSL *ssl, int *al, modssl_ctx_t *mctx)
+static apr_status_t init_vhost(conn_rec *c, SSL *ssl)
 {
-    const char *servername =
-                SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
-    conn_rec *c = (conn_rec *)SSL_get_app_data(ssl);
-
+    const char *servername;
+    
     if (c) {
+        SSLConnRec *sslcon = myConnConfig(c);
+        
+        if (sslcon->server != c->base_server) {
+            /* already found the vhost */
+            return APR_SUCCESS;
+        }
+        
+        servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
         if (servername) {
             if (ap_vhost_iterate_given_conn(c, ssl_find_vhost,
                                             (void *)servername)) {
                 ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(02043)
                               "SSL virtual host for servername %s found",
                               servername);
-                return SSL_TLSEXT_ERR_OK;
+                return APR_SUCCESS;
             }
             else {
                 ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(02044)
@@ -1949,8 +1962,20 @@ int ssl_callback_ServerNameIndication(SS
                           "(using default/first virtual host)");
         }
     }
+    
+    return APR_NOTFOUND;
+}
 
-    return SSL_TLSEXT_ERR_NOACK;
+/*
+ * This callback function is executed when OpenSSL encounters an extended
+ * client hello with a server name indication extension ("SNI", cf. RFC 6066).
+ */
+int ssl_callback_ServerNameIndication(SSL *ssl, int *al, modssl_ctx_t *mctx)
+{
+    conn_rec *c = (conn_rec *)SSL_get_app_data(ssl);
+    apr_status_t status = init_vhost(c, ssl);
+    
+    return (status == APR_SUCCESS)? SSL_TLSEXT_ERR_OK : SSL_TLSEXT_ERR_NOACK;
 }
 
 /*
@@ -1962,50 +1987,10 @@ static int ssl_find_vhost(void *serverna
 {
     SSLSrvConfigRec *sc;
     SSL *ssl;
-    BOOL found = FALSE;
-    apr_array_header_t *names;
-    int i;
+    BOOL found;
     SSLConnRec *sslcon;
 
-    /* check ServerName */
-    if (!strcasecmp(servername, s->server_hostname)) {
-        found = TRUE;
-    }
-
-    /*
-     * if not matched yet, check ServerAlias entries
-     * (adapted from vhost.c:matches_aliases())
-     */
-    if (!found) {
-        names = s->names;
-        if (names) {
-            char **name = (char **)names->elts;
-            for (i = 0; i < names->nelts; ++i) {
-                if (!name[i])
-                    continue;
-                if (!strcasecmp(servername, name[i])) {
-                    found = TRUE;
-                    break;
-                }
-            }
-        }
-    }
-
-    /* if still no match, check ServerAlias entries with wildcards */
-    if (!found) {
-        names = s->wild_names;
-        if (names) {
-            char **name = (char **)names->elts;
-            for (i = 0; i < names->nelts; ++i) {
-                if (!name[i])
-                    continue;
-                if (!ap_strcasecmp_match(servername, name[i])) {
-                    found = TRUE;
-                    break;
-                }
-            }
-        }
-    }
+    found = ssl_util_vhost_matches(servername, s);
 
     /* set SSL_CTX (if matched) */
     sslcon = myConnConfig(c);
@@ -2149,6 +2134,80 @@ int ssl_callback_SessionTicket(SSL *ssl,
 }
 #endif /* HAVE_TLS_SESSION_TICKETS */
 
+
+#ifdef HAVE_TLS_ALPN
+/*
+ * This callback function is executed when the TLS Application-Layer
+ * Protocol Negotiation Extension (ALPN, RFC 7301) is triggered by the Client
+ * Hello, giving a list of desired protocol names (in descending preference) 
+ * to the server.
+ * The callback has to select a protocol name or return an error if none of
+ * the clients preferences is supported.
+ * The selected protocol does not have to be on the client list, according
+ * to RFC 7301, so no checks are performed.
+ * The client protocol list is serialized as length byte followed by ASCII
+ * characters (not null-terminated), followed by the next protocol name.
+ */
+int ssl_callback_alpn_select(SSL *ssl,
+                             const unsigned char **out, unsigned char *outlen,
+                             const unsigned char *in, unsigned int inlen,
+                             void *arg)
+{
+    conn_rec *c = (conn_rec*)SSL_get_app_data(ssl);
+    SSLConnRec *sslconn = myConnConfig(c);
+    apr_array_header_t *client_protos;
+    const char *proposed;
+    size_t len;
+    int i;
+
+    /* If the connection object is not available,
+     * then there's nothing for us to do. */
+    if (c == NULL) {
+        return SSL_TLSEXT_ERR_OK;
+    }
+
+    if (inlen == 0) {
+        // someone tries to trick us?
+        ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(02837)
+                      "ALPN client protocol list empty");
+        return SSL_TLSEXT_ERR_ALERT_FATAL;
+    }
+
+    client_protos = apr_array_make(c->pool, 0, sizeof(char *));
+    for (i = 0; i < inlen; /**/) {
+        unsigned int plen = in[i++];
+        if (plen + i > inlen) {
+            // someone tries to trick us?
+            ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(02838)
+                          "ALPN protocol identifier too long");
+            return SSL_TLSEXT_ERR_ALERT_FATAL;
+        }
+        APR_ARRAY_PUSH(client_protos, char *) =
+            apr_pstrndup(c->pool, (const char *)in+i, plen);
+        i += plen;
+    }
+
+    /* The order the callbacks are invoked from TLS extensions is, unfortunately
+     * not defined and older openssl versions do call ALPN selection before
+     * they callback the SNI. We need to make sure that we know which vhost
+     * we are dealing with so we respect the correct protocols.
+     */
+    init_vhost(c, ssl);
+    
+    proposed = ap_select_protocol(c, NULL, sslconn->server, client_protos);
+    *out = (const unsigned char *)(proposed? proposed : ap_get_protocol(c));
+    len = strlen((const char*)*out);
+    if (len > 255) {
+        ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(02840)
+                      "ALPN negotiated protocol name too long");
+        return SSL_TLSEXT_ERR_ALERT_FATAL;
+    }
+    *outlen = (unsigned char)len;
+
+    return SSL_TLSEXT_ERR_OK;
+}
+#endif /* HAVE_TLS_ALPN */
+
 #ifdef HAVE_SRP
 
 int ssl_callback_SRPServerParams(SSL *ssl, int *ad, void *arg)

Modified: httpd/httpd/branches/2.4.17-protocols-http2/modules/ssl/ssl_private.h
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.17-protocols-http2/modules/ssl/ssl_private.h?rev=1701655&r1=1701654&r2=1701655&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.17-protocols-http2/modules/ssl/ssl_private.h (original)
+++ httpd/httpd/branches/2.4.17-protocols-http2/modules/ssl/ssl_private.h Mon Sep  7 17:37:19
2015
@@ -182,6 +182,11 @@
 #include <openssl/srp.h>
 #endif
 
+/* ALPN Protocol Negotiation */
+#if defined(TLSEXT_TYPE_application_layer_protocol_negotiation)
+#define HAVE_TLS_ALPN
+#endif
+
 #endif /* !defined(OPENSSL_NO_TLSEXT) && defined(SSL_set_tlsext_host_name) */
 
 /* mod_ssl headers */
@@ -798,6 +803,12 @@ int         ssl_callback_SessionTicket(S
                                        EVP_CIPHER_CTX *, HMAC_CTX *, int);
 #endif
 
+#ifdef HAVE_TLS_ALPN
+int ssl_callback_alpn_select(SSL *ssl, const unsigned char **out,
+                             unsigned char *outlen, const unsigned char *in,
+                             unsigned int inlen, void *arg);
+#endif
+
 /**  Session Cache Support  */
 apr_status_t ssl_scache_init(server_rec *, apr_pool_t *);
 void         ssl_scache_status_register(apr_pool_t *p);
@@ -856,6 +867,8 @@ BOOL         ssl_util_path_check(ssl_pat
 void         ssl_util_thread_setup(apr_pool_t *);
 int          ssl_init_ssl_connection(conn_rec *c, request_rec *r);
 
+BOOL         ssl_util_vhost_matches(const char *servername, server_rec *s);
+
 /**  Pass Phrase Support  */
 apr_status_t ssl_load_encrypted_pkey(server_rec *, apr_pool_t *, int,
                                      const char *, apr_array_header_t **);

Modified: httpd/httpd/branches/2.4.17-protocols-http2/modules/ssl/ssl_util.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.17-protocols-http2/modules/ssl/ssl_util.c?rev=1701655&r1=1701654&r2=1701655&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.17-protocols-http2/modules/ssl/ssl_util.c (original)
+++ httpd/httpd/branches/2.4.17-protocols-http2/modules/ssl/ssl_util.c Mon Sep  7 17:37:19
2015
@@ -60,6 +60,52 @@ char *ssl_util_vhostid(apr_pool_t *p, se
     return id;
 }
 
+/*
+ * Return TRUE iff the given servername matches the server record when
+ * selecting virtual hosts.
+ */
+BOOL ssl_util_vhost_matches(const char *servername, server_rec *s)
+{
+    apr_array_header_t *names;
+    int i;
+    
+    /* check ServerName */
+    if (!strcasecmp(servername, s->server_hostname)) {
+        return TRUE;
+    }
+    
+    /*
+     * if not matched yet, check ServerAlias entries
+     * (adapted from vhost.c:matches_aliases())
+     */
+    names = s->names;
+    if (names) {
+        char **name = (char **)names->elts;
+        for (i = 0; i < names->nelts; ++i) {
+            if (!name[i])
+                continue;
+            if (!strcasecmp(servername, name[i])) {
+                return TRUE;
+            }
+        }
+    }
+    
+    /* if still no match, check ServerAlias entries with wildcards */
+    names = s->wild_names;
+    if (names) {
+        char **name = (char **)names->elts;
+        for (i = 0; i < names->nelts; ++i) {
+            if (!name[i])
+                continue;
+            if (!ap_strcasecmp_match(servername, name[i])) {
+                return TRUE;
+            }
+        }
+    }
+    
+    return FALSE;
+}
+
 apr_file_t *ssl_util_ppopen(server_rec *s, apr_pool_t *p, const char *cmd,
                             const char * const *argv)
 {

Modified: httpd/httpd/branches/2.4.17-protocols-http2/os/win32/BaseAddr.ref
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.17-protocols-http2/os/win32/BaseAddr.ref?rev=1701655&r1=1701654&r2=1701655&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.17-protocols-http2/os/win32/BaseAddr.ref (original)
+++ httpd/httpd/branches/2.4.17-protocols-http2/os/win32/BaseAddr.ref Mon Sep  7 17:37:19
2015
@@ -127,3 +127,5 @@ mod_optional_fn_import.so   0x70BC0000
 mod_optional_hook_export.so 0x70BD0000    0x00010000
 mod_optional_hook_import.so 0x70BE0000    0x00010000
 mod_authnz_fcgi.so          0x70BF0000    0x00020000
+mod_h2.so                   0x70D00000    0x00020000
+>>>>>>> .merge-right.r1698023

Modified: httpd/httpd/branches/2.4.17-protocols-http2/server/core.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.17-protocols-http2/server/core.c?rev=1701655&r1=1701654&r2=1701655&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.17-protocols-http2/server/core.c (original)
+++ httpd/httpd/branches/2.4.17-protocols-http2/server/core.c Mon Sep  7 17:37:19 2015
@@ -423,6 +423,7 @@ static void *merge_core_dir_configs(apr_
 static void *create_core_server_config(apr_pool_t *a, server_rec *s)
 {
     core_server_config *conf;
+    const char **np;
     int is_virtual = s->is_virtual;
 
     conf = (core_server_config *)apr_pcalloc(a, sizeof(core_server_config));
@@ -468,6 +469,9 @@ static void *create_core_server_config(a
 
     conf->trace_enable = AP_TRACE_UNSET;
 
+    conf->protocols = apr_array_make(a, 5, sizeof(const char *));
+    conf->protocols_honor_order = -1;
+    
     return (void *)conf;
 }
 
@@ -518,6 +522,12 @@ static void *merge_core_server_configs(a
                            ? virt->merge_trailers
                            : base->merge_trailers;
 
+    conf->protocols = ((virt->protocols->nelts > 0)? 
+                       virt->protocols : base->protocols);
+    conf->protocols_honor_order = ((virt->protocols_honor_order < 0)?
+                                       base->protocols_honor_order :
+                                       virt->protocols_honor_order);
+    
     return conf;
 }
 
@@ -3692,6 +3702,48 @@ static const char *set_trace_enable(cmd_
     return NULL;
 }
 
+static const char *set_protocols(cmd_parms *cmd, void *dummy,
+                                 const char *arg)
+{
+    core_server_config *conf =
+    ap_get_core_module_config(cmd->server->module_config);
+    const char **np;
+    const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE);
+
+    if (err) {
+        return err;
+    }
+    
+    np = (const char **)apr_array_push(conf->protocols);
+    *np = arg;
+
+    return NULL;
+}
+
+static const char *set_protocols_honor_order(cmd_parms *cmd, void *dummy,
+                                             const char *arg)
+{
+    core_server_config *conf =
+    ap_get_core_module_config(cmd->server->module_config);
+    const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE);
+    
+    if (err) {
+        return err;
+    }
+    
+    if (strcasecmp(arg, "on") == 0) {
+        conf->protocols_honor_order = 1;
+    }
+    else if (strcasecmp(arg, "off") == 0) {
+        conf->protocols_honor_order = 0;
+    }
+    else {
+        return "ProtocolsHonorOrder must be 'on' or 'off'";
+    }
+    
+    return NULL;
+}
+
 static apr_hash_t *errorlog_hash;
 
 static int log_constant_item(const ap_errorlog_info *info, const char *arg,
@@ -4205,6 +4257,11 @@ AP_INIT_TAKE1("TraceEnable", set_trace_e
               "'on' (default), 'off' or 'extended' to trace request body content"),
 AP_INIT_FLAG("MergeTrailers", set_merge_trailers, NULL, RSRC_CONF,
               "merge request trailers into request headers or not"),
+AP_INIT_ITERATE("Protocols", set_protocols, NULL, RSRC_CONF,
+                "Controls which protocols are allowed"),
+AP_INIT_TAKE1("ProtocolsHonorOrder", set_protocols_honor_order, NULL, RSRC_CONF,
+              "'off' (default) or 'on' to respect given order of protocols, "
+              "by default the client specified order determines selection"),
 { NULL }
 };
 
@@ -4936,6 +4993,61 @@ static void core_dump_config(apr_pool_t
     }
 }
 
+static int core_upgrade_handler(request_rec *r)
+{
+    conn_rec *c = r->connection;
+    const char *upgrade = apr_table_get(r->headers_in, "Upgrade");
+
+    if (upgrade && *upgrade) {
+        const char *conn = apr_table_get(r->headers_in, "Connection");
+        if (ap_find_token(r->pool, conn, "upgrade")) {
+            apr_array_header_t *offers = NULL;
+            const char *err;
+            
+            err = ap_parse_token_list_strict(r->pool, upgrade, &offers, 0);
+            if (err) {
+                ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02910)
+                              "parsing Upgrade header: %s", err);
+                return DECLINED;
+            }
+            
+            if (offers && offers->nelts > 0) {
+                const char *protocol = ap_select_protocol(c, r, r->server,
+                                                          offers);
+                if (protocol && strcmp(protocol, ap_get_protocol(c))) {
+                    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02909)
+                                  "Upgrade selects '%s'", protocol);
+                    /* Let the client know what we are upgrading to. */
+                    apr_table_clear(r->headers_out);
+                    apr_table_setn(r->headers_out, "Upgrade", protocol);
+                    apr_table_setn(r->headers_out, "Connection", "Upgrade");
+                    
+                    r->status = HTTP_SWITCHING_PROTOCOLS;
+                    r->status_line = ap_get_status_line(r->status);
+                    ap_send_interim_response(r, 1);
+
+                    ap_switch_protocol(c, r, r->server, protocol);
+
+                    /* make sure httpd closes the connection after this */
+                    c->keepalive = AP_CONN_CLOSE;
+                    return DONE;
+                }
+            }
+        }
+    }
+    
+    return DECLINED;
+}
+
+static int core_upgrade_storage(request_rec *r)
+{
+    if ((r->method_number == M_OPTIONS) && r->uri && (r->uri[0]
== '*') &&
+        (r->uri[1] == '\0')) {
+        return core_upgrade_handler(r);
+    }
+    return DECLINED;
+}
+
 static void register_hooks(apr_pool_t *p)
 {
     errorlog_hash = apr_hash_make(p);
@@ -4958,10 +5070,12 @@ static void register_hooks(apr_pool_t *p
     ap_hook_check_config(core_check_config,NULL,NULL,APR_HOOK_FIRST);
     ap_hook_test_config(core_dump_config,NULL,NULL,APR_HOOK_FIRST);
     ap_hook_translate_name(ap_core_translate,NULL,NULL,APR_HOOK_REALLY_LAST);
+    ap_hook_map_to_storage(core_upgrade_storage,NULL,NULL,APR_HOOK_REALLY_FIRST);
     ap_hook_map_to_storage(core_map_to_storage,NULL,NULL,APR_HOOK_REALLY_LAST);
     ap_hook_open_logs(ap_open_logs,NULL,NULL,APR_HOOK_REALLY_FIRST);
     ap_hook_child_init(core_child_init,NULL,NULL,APR_HOOK_REALLY_FIRST);
     ap_hook_child_init(ap_logs_child_init,NULL,NULL,APR_HOOK_MIDDLE);
+    ap_hook_handler(core_upgrade_handler,NULL,NULL,APR_HOOK_REALLY_FIRST);
     ap_hook_handler(default_handler,NULL,NULL,APR_HOOK_REALLY_LAST);
     /* FIXME: I suspect we can eliminate the need for these do_nothings - Ben */
     ap_hook_type_checker(do_nothing,NULL,NULL,APR_HOOK_REALLY_LAST);

Modified: httpd/httpd/branches/2.4.17-protocols-http2/server/protocol.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.17-protocols-http2/server/protocol.c?rev=1701655&r1=1701654&r2=1701655&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.17-protocols-http2/server/protocol.c (original)
+++ httpd/httpd/branches/2.4.17-protocols-http2/server/protocol.c Mon Sep  7 17:37:19 2015
@@ -67,6 +67,9 @@ APR_HOOK_STRUCT(
     APR_HOOK_LINK(http_scheme)
     APR_HOOK_LINK(default_port)
     APR_HOOK_LINK(note_auth_failure)
+    APR_HOOK_LINK(protocol_propose)
+    APR_HOOK_LINK(protocol_switch)
+    APR_HOOK_LINK(protocol_get)
 )
 
 AP_DECLARE_DATA ap_filter_rec_t *ap_old_write_func = NULL;
@@ -1790,6 +1793,150 @@ AP_DECLARE(void) ap_send_interim_respons
     apr_brigade_destroy(x.bb);
 }
 
+/*
+ * Compare two protocol identifier. Result is similar to strcmp():
+ * 0 gives same precedence, >0 means proto1 is preferred.
+ */
+static int protocol_cmp(const apr_array_header_t *preferences,
+                        const char *proto1,
+                        const char *proto2)
+{
+    if (preferences && preferences->nelts > 0) {
+        int index1 = ap_array_str_index(preferences, proto1, 0);
+        int index2 = ap_array_str_index(preferences, proto2, 0);
+        if (index2 > index1) {
+            return (index1 >= 0) ? 1 : -1;
+        }
+        else if (index1 > index2) {
+            return (index2 >= 0) ? -1 : 1;
+        }
+    }
+    /* both have the same index (mabye -1 or no pref configured) and we compare
+     * the names so that spdy3 gets precedence over spdy2. That makes
+     * the outcome at least deterministic. */
+    return strcmp(proto1, proto2);
+}
+
+AP_DECLARE(const char *) ap_get_protocol(conn_rec *c)
+{
+    const char *protocol = ap_run_protocol_get(c);
+    return protocol? protocol : AP_PROTOCOL_HTTP1;
+}
+
+AP_DECLARE(const char *) ap_select_protocol(conn_rec *c, request_rec *r, 
+                                            server_rec *s,
+                                            const apr_array_header_t *choices)
+{
+    apr_pool_t *pool = r? r->pool : c->pool;
+    core_server_config *conf = ap_get_core_module_config(s->module_config);
+    const char *protocol = NULL, *existing;
+    apr_array_header_t *proposals;
+
+    if (APLOGcdebug(c)) {
+        const char *p = apr_array_pstrcat(pool, conf->protocols, ',');
+        ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, 
+                      "select protocol from %s, choices=%s for server %s", 
+                      p, apr_array_pstrcat(pool, choices, ','),
+                      s->server_hostname);
+    }
+
+    if (conf->protocols->nelts <= 0) {
+        /* nothing configured, by default, we only allow http/1.1 here.
+         * For now...
+         */
+        if (ap_array_str_contains(choices, AP_PROTOCOL_HTTP1)) {
+            return AP_PROTOCOL_HTTP1;
+        }
+        else {
+            return NULL;
+        }
+    }
+
+    proposals = apr_array_make(pool, choices->nelts + 1, sizeof(char *));
+    ap_run_protocol_propose(c, r, s, choices, proposals);
+
+    /* If the existing protocol has not been proposed, but is a choice,
+     * add it to the proposals implicitly.
+     */
+    existing = ap_get_protocol(c);
+    if (!ap_array_str_contains(proposals, existing)
+        && ap_array_str_contains(choices, existing)) {
+        APR_ARRAY_PUSH(proposals, const char*) = existing;
+    }
+
+    if (proposals->nelts > 0) {
+        int i;
+        const apr_array_header_t *prefs = NULL;
+
+        /* Default for protocols_honor_order is 'on' or != 0 */
+        if (conf->protocols_honor_order == 0 && choices->nelts > 0) {
+            prefs = choices;
+        }
+        else {
+            prefs = conf->protocols;
+        }
+
+        /* Select the most preferred protocol */
+        if (APLOGcdebug(c)) {
+            ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, 
+                          "select protocol, proposals=%s preferences=%s configured=%s", 
+                          apr_array_pstrcat(pool, proposals, ','),
+                          apr_array_pstrcat(pool, prefs, ','),
+                          apr_array_pstrcat(pool, conf->protocols, ','));
+        }
+        for (i = 0; i < proposals->nelts; ++i) {
+            const char *p = APR_ARRAY_IDX(proposals, i, const char *);
+            if (!ap_array_str_contains(conf->protocols, p)) {
+                /* not a configured protocol here */
+                continue;
+            }
+            else if (!protocol 
+                     || (protocol_cmp(prefs, protocol, p) < 0)) {
+                /* none selected yet or this one has preference */
+                protocol = p;
+            }
+        }
+    }
+    if (APLOGcdebug(c)) {
+        ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, "selected protocol=%s", 
+                      protocol? protocol : "(none)");
+    }
+
+    return protocol;
+}
+
+AP_DECLARE(apr_status_t) ap_switch_protocol(conn_rec *c, request_rec *r, 
+                                            server_rec *s,
+                                            const char *protocol)
+{
+    const char *current = ap_get_protocol(c);
+    int rc;
+    
+    if (!strcmp(current, protocol)) {
+        ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, c, APLOGNO(02906)
+                      "already at it, protocol_switch to %s", 
+                      protocol);
+        return APR_SUCCESS;
+    }
+    
+    rc = ap_run_protocol_switch(c, r, s, protocol);
+    switch (rc) {
+        case DECLINED:
+            ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(02907)
+                          "no implementation for protocol_switch to %s", 
+                          protocol);
+            return APR_ENOTIMPL;
+        case OK:
+        case DONE:
+            return APR_SUCCESS;
+        default:
+            ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(02905)
+                          "unexpected return code %d from protocol_switch to %s"
+                          , rc, protocol);
+            return APR_EOF;
+    }    
+}
+
 
 AP_IMPLEMENT_HOOK_VOID(pre_read_request,
                        (request_rec *r, conn_rec *c),
@@ -1805,3 +1952,14 @@ AP_IMPLEMENT_HOOK_RUN_FIRST(unsigned sho
 AP_IMPLEMENT_HOOK_RUN_FIRST(int, note_auth_failure,
                             (request_rec *r, const char *auth_type),
                             (r, auth_type), DECLINED)
+AP_IMPLEMENT_HOOK_RUN_ALL(int,protocol_propose,
+                          (conn_rec *c, request_rec *r, server_rec *s,
+                           const apr_array_header_t *offers,
+                           apr_array_header_t *proposals), 
+                          (c, r, s, offers, proposals), OK, DECLINED)
+AP_IMPLEMENT_HOOK_RUN_FIRST(int,protocol_switch,
+                            (conn_rec *c, request_rec *r, server_rec *s,
+                             const char *protocol), 
+                            (c, r, s, protocol), DECLINED)
+AP_IMPLEMENT_HOOK_RUN_FIRST(const char *,protocol_get,
+                            (const conn_rec *c), (c), NULL)

Modified: httpd/httpd/branches/2.4.17-protocols-http2/server/util.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.17-protocols-http2/server/util.c?rev=1701655&r1=1701654&r2=1701655&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.17-protocols-http2/server/util.c (original)
+++ httpd/httpd/branches/2.4.17-protocols-http2/server/util.c Mon Sep  7 17:37:19 2015
@@ -1451,6 +1451,95 @@ AP_DECLARE(int) ap_find_etag_weak(apr_po
     return find_list_item(p, line, tok, AP_ETAG_WEAK);
 }
 
+/* Grab a list of tokens of the format 1#token (from RFC7230) */
+AP_DECLARE(const char *) ap_parse_token_list_strict(apr_pool_t *p,
+                                                const char *str_in,
+                                                apr_array_header_t **tokens,
+                                                int skip_invalid)
+{
+    int in_leading_space = 1;
+    int in_trailing_space = 0;
+    int string_end = 0;
+    const char *tok_begin;
+    const char *cur;
+
+    if (!str_in) {
+        return NULL;
+    }
+
+    tok_begin = cur = str_in;
+
+    while (!string_end) {
+        const unsigned char c = (unsigned char)*cur;
+
+        if (!TEST_CHAR(c, T_HTTP_TOKEN_STOP) && c != '\0') {
+            /* Non-separator character; we are finished with leading
+             * whitespace. We must never have encountered any trailing
+             * whitespace before the delimiter (comma) */
+            in_leading_space = 0;
+            if (in_trailing_space) {
+                return "Encountered illegal whitespace in token";
+            }
+        }
+        else if (c == ' ' || c == '\t') {
+            /* "Linear whitespace" only includes ASCII CRLF, space, and tab;
+             * we can't get a CRLF since headers are split on them already,
+             * so only look for a space or a tab */
+            if (in_leading_space) {
+                /* We're still in leading whitespace */
+                ++tok_begin;
+            }
+            else {
+                /* We must be in trailing whitespace */
+                ++in_trailing_space;
+            }
+        }
+        else if (c == ',' || c == '\0') {
+            if (!in_leading_space) {
+                /* If we're out of the leading space, we know we've read some
+                 * characters of a token */
+                if (*tokens == NULL) {
+                    *tokens = apr_array_make(p, 4, sizeof(char *));
+                }
+                APR_ARRAY_PUSH(*tokens, char *) =
+                    apr_pstrmemdup((*tokens)->pool, tok_begin,
+                                   (cur - tok_begin) - in_trailing_space);
+            }
+            /* We're allowed to have null elements, just don't add them to the
+             * array */
+
+            tok_begin = cur + 1;
+            in_leading_space = 1;
+            in_trailing_space = 0;
+            string_end = (c == '\0');
+        }
+        else {
+            /* Encountered illegal separator char */
+            if (skip_invalid) {
+                /* Skip to the next separator */
+                const char *temp;
+                temp = ap_strchr_c(cur, ',');
+                if(!temp) {
+                    temp = ap_strchr_c(cur, '\0');
+                }
+
+                /* Act like we haven't seen a token so we reset */
+                cur = temp - 1;
+                in_leading_space = 1;
+                in_trailing_space = 0;
+            }
+            else {
+                return apr_psprintf(p, "Encountered illegal separator "
+                                    "'\\x%.2x'", (unsigned int)c);
+            }
+        }
+
+        ++cur;
+    }
+
+    return NULL;
+}
+
 /* Retrieve a token, spacing over it and returning a pointer to
  * the first non-white byte afterwards.  Note that these tokens
  * are delimited by semis and commas; and can also be delimited
@@ -3005,3 +3094,28 @@ AP_DECLARE(char *) ap_get_exec_line(apr_
 
     return apr_pstrndup(p, buf, k);
 }
+
+AP_DECLARE(int) ap_array_str_index(const apr_array_header_t *array, 
+                                   const char *s,
+                                   int start)
+{
+    if (start >= 0) {
+        int i;
+        
+        for (i = start; i < array->nelts; i++) {
+            const char *p = APR_ARRAY_IDX(array, i, const char *);
+            if (!strcmp(p, s)) {
+                return i;
+            }
+        }
+    }
+    
+    return -1;
+}
+
+AP_DECLARE(int) ap_array_str_contains(const apr_array_header_t *array, 
+                                      const char *s)
+{
+    return (ap_array_str_index(array, s, 0) >= 0);
+}
+



Mime
View raw message