httpd-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From j..@apache.org
Subject svn commit: r1688474 [17/21] - in /httpd/httpd/trunk/modules/http2: ./ m4/ mod-h2.xcodeproj/ mod-h2.xcodeproj/project.xcworkspace/ mod-h2.xcodeproj/project.xcworkspace/xcshareddata/ mod-h2.xcodeproj/xcuserdata/ mod-h2.xcodeproj/xcuserdata/sei.xcuserdat...
Date Tue, 30 Jun 2015 15:26:19 GMT
Added: httpd/httpd/trunk/modules/http2/sandbox/httpd/patches/httpd-2.4.12-alpn-v5.patch
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/sandbox/httpd/patches/httpd-2.4.12-alpn-v5.patch?rev=1688474&view=auto
==============================================================================
--- httpd/httpd/trunk/modules/http2/sandbox/httpd/patches/httpd-2.4.12-alpn-v5.patch (added)
+++ httpd/httpd/trunk/modules/http2/sandbox/httpd/patches/httpd-2.4.12-alpn-v5.patch Tue Jun 30 15:26:16 2015
@@ -0,0 +1,605 @@
+diff -ru modules/ssl/mod_ssl.c modules/ssl/mod_ssl.c
+--- modules/ssl/mod_ssl.c	2015-06-17 15:09:03.000000000 +0200
++++ modules/ssl/mod_ssl.c	2015-06-17 15:52:41.000000000 +0200
+@@ -273,6 +273,12 @@
+ 		"OpenSSL configuration command")
+ #endif
+ 
++#ifdef HAVE_TLS_ALPN
++    SSL_CMD_SRV(ALPNPreference, ITERATE,
++                "Preference in Application-Layer Protocol Negotiation (ALPN), "
++                "protocols are chosen in the specified order")
++#endif
++
+     /* Deprecated directives. */
+     AP_INIT_RAW_ARGS("SSLLog", ap_set_deprecated, NULL, OR_ALL,
+       "SSLLog directive is no longer supported - use ErrorLog."),
+@@ -372,6 +378,7 @@
+     sslconn = apr_pcalloc(c->pool, sizeof(*sslconn));
+ 
+     sslconn->server = c->base_server;
++    sslconn->vhost_selected = 0;
+     sslconn->verify_depth = UNSET;
+ 
+     myConnConfigSet(c, sslconn);
+@@ -423,12 +430,44 @@
+     return 1;
+ }
+ 
++static int modssl_register_alpn(conn_rec *c,
++                               ssl_alpn_propose_protos advertisefn,
++                               ssl_alpn_proto_negotiated negotiatedfn)
++{
++#ifdef HAVE_TLS_ALPN
++    SSLConnRec *sslconn = myConnConfig(c);
++    
++    if (!sslconn) {
++        return DECLINED;
++    }
++    
++    if (!sslconn->alpn_proposefns) {
++        sslconn->alpn_proposefns =
++        apr_array_make(c->pool, 5, sizeof(ssl_alpn_propose_protos));
++        sslconn->alpn_negofns =
++        apr_array_make(c->pool, 5, sizeof(ssl_alpn_proto_negotiated));
++    }
++    
++    if (advertisefn)
++        APR_ARRAY_PUSH(sslconn->alpn_proposefns, ssl_alpn_propose_protos) =
++            advertisefn;
++    if (negotiatedfn)
++        APR_ARRAY_PUSH(sslconn->alpn_negofns, ssl_alpn_proto_negotiated) =
++            negotiatedfn;
++    
++    return OK;
++#else
++    return DECLINED;
++#endif
++}
++
+ int ssl_init_ssl_connection(conn_rec *c, request_rec *r)
+ {
+     SSLSrvConfigRec *sc;
+     SSL *ssl;
+     SSLConnRec *sslconn = myConnConfig(c);
+     char *vhost_md5;
++    int rc;
+     modssl_ctx_t *mctx;
+     server_rec *server;
+ 
+@@ -585,6 +624,7 @@
+ 
+     APR_REGISTER_OPTIONAL_FN(ssl_proxy_enable);
+     APR_REGISTER_OPTIONAL_FN(ssl_engine_disable);
++    APR_REGISTER_OPTIONAL_FN(modssl_register_alpn);
+ 
+     ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "ssl",
+                               AUTHZ_PROVIDER_VERSION,
+diff -ru modules/ssl/mod_ssl.h modules/ssl/mod_ssl.h
+--- modules/ssl/mod_ssl.h	2015-06-17 15:09:03.000000000 +0200
++++ modules/ssl/mod_ssl.h	2015-06-17 15:10:39.000000000 +0200
+@@ -63,5 +63,46 @@
+ 
+ APR_DECLARE_OPTIONAL_FN(int, ssl_engine_disable, (conn_rec *));
+ 
++/** The alpn_propose_proto callback allows other modules to propose
++ * the name of the protocol that will be chosen during the
++ * Application-Layer Protocol Negotiation (ALPN) portion of the SSL handshake.
++ * The callback is given the connection and a list of NULL-terminated
++ * protocol strings as supported by the client.  If this client_protos is 
++ * non-empty, it must pick its preferred protocol from that list. Otherwise
++ * it should add its supported protocols in order of precedence.
++ * The callback should not yet modify the connection or install any filters
++ * as its proposal(s) may be overridden by another callback or server 
++ * configuration. 
++ * It should return OK or, to prevent further processing of (other modules') 
++ * callbacks, return DONE.
++ */
++typedef int (*ssl_alpn_propose_protos)(conn_rec *connection,
++                                    apr_array_header_t *client_protos,
++                                    apr_array_header_t *proposed_protos);
++
++/** The alpn_proto_negotiated callback allows other modules to discover
++ * the name of the protocol that was chosen during the Application-Layer
++ * Protocol Negotiation (ALPN) portion of the SSL handshake.  
++ * The callback is given the connection, a
++ * non-NUL-terminated string containing the protocol name, and the
++ * length of the string; it should do something appropriate
++ * (i.e. insert or remove filters) and return OK. To prevent further
++ * processing of (other modules') callbacks, return DONE. */
++typedef int (*ssl_alpn_proto_negotiated)(conn_rec *connection,
++                                        const char *proto_name,
++                                        apr_size_t proto_name_len);
++
++/* An optional function which can be used to register a pair of callbacks 
++ * for ALPN handling.
++ * This optional function should be invoked from a pre_connection hook 
++ * which runs *after* mod_ssl.c's pre_connection hook.  The function returns 
++ * OK if the callbacks are registered, or DECLINED otherwise (for example if 
++ * mod_ssl does not support ALPN).
++ */
++APR_DECLARE_OPTIONAL_FN(int, modssl_register_alpn,
++                        (conn_rec *conn,
++                         ssl_alpn_propose_protos proposefn,
++                         ssl_alpn_proto_negotiated negotiatedfn));
++
+ #endif /* __MOD_SSL_H__ */
+ /** @} */
+diff -ru modules/ssl/ssl_engine_config.c modules/ssl/ssl_engine_config.c
+--- modules/ssl/ssl_engine_config.c	2015-06-17 15:09:03.000000000 +0200
++++ modules/ssl/ssl_engine_config.c	2015-06-17 15:10:39.000000000 +0200
+@@ -159,6 +159,9 @@
+     SSL_CONF_CTX_set_flags(mctx->ssl_ctx_config, SSL_CONF_FLAG_CERTIFICATE);
+     mctx->ssl_ctx_param = apr_array_make(p, 5, sizeof(ssl_ctx_param_t));
+ #endif
++#ifdef HAVE_TLS_ALPN
++    mctx->ssl_alpn_pref = apr_array_make(p, 5, sizeof(const char *));
++#endif
+ }
+ 
+ static void modssl_ctx_init_proxy(SSLSrvConfigRec *sc,
+@@ -298,6 +301,9 @@
+ #ifdef HAVE_SSL_CONF_CMD
+     cfgMergeArray(ssl_ctx_param);
+ #endif
++#ifdef HAVE_TLS_ALPN
++    cfgMergeArray(ssl_alpn_pref);
++#endif
+ }
+ 
+ static void modssl_ctx_cfg_merge_proxy(apr_pool_t *p,
+@@ -1869,6 +1875,16 @@
+ }
+ #endif
+ 
++#ifdef HAVE_TLS_ALPN
++const char *ssl_cmd_SSLALPNPreference(cmd_parms *cmd, void *dcfg,
++                                      const char *protocol)
++{
++    SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
++    APR_ARRAY_PUSH(sc->server->ssl_alpn_pref, const char *) = protocol;
++    return NULL;
++}
++#endif
++
+ #ifdef HAVE_SRP
+ 
+ const char *ssl_cmd_SSLSRPVerifierFile(cmd_parms *cmd, void *dcfg,
+diff -ru modules/ssl/ssl_engine_init.c modules/ssl/ssl_engine_init.c
+--- modules/ssl/ssl_engine_init.c	2015-06-17 15:09:03.000000000 +0200
++++ modules/ssl/ssl_engine_init.c	2015-06-17 15:10:39.000000000 +0200
+@@ -623,6 +623,11 @@
+     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,
+diff -ru modules/ssl/ssl_engine_io.c modules/ssl/ssl_engine_io.c
+--- modules/ssl/ssl_engine_io.c	2015-06-17 15:09:03.000000000 +0200
++++ modules/ssl/ssl_engine_io.c	2015-06-17 15:10:39.000000000 +0200
+@@ -28,6 +28,7 @@
+                                   core keeps dumping.''
+                                             -- Unknown    */
+ #include "ssl_private.h"
++#include "mod_ssl.h"
+ #include "apr_date.h"
+ 
+ /*  _________________________________________________________________
+@@ -297,6 +298,9 @@
+     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 +1416,37 @@
+         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;
++        int n;
++        
++        if (sslconn->alpn_negofns) {
++            SSL_get0_alpn_selected(inctx->ssl, &next_proto, &next_proto_len);
++            ap_log_cerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, f->c,
++                          APLOGNO(02836) "SSL negotiated protocol: '%s'",
++                          (next_proto && next_proto_len)?
++                         apr_pstrmemdup(f->c->pool, (const char *)next_proto,
++                              next_proto_len) : "(null)");
++            for (n = 0; n < sslconn->alpn_negofns->nelts; n++) {
++                ssl_alpn_proto_negotiated fn =
++                APR_ARRAY_IDX(sslconn->alpn_negofns, n, ssl_alpn_proto_negotiated);
++                
++                if (fn(f->c, (const char *)next_proto, next_proto_len) == DONE)
++                break;
++            }
++        }
++        inctx->alpn_finished = 1;
++    }
++#endif
++
+     return APR_SUCCESS;
+ }
+ 
+@@ -1893,6 +1928,9 @@
+     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
+diff -ru modules/ssl/ssl_engine_kernel.c modules/ssl/ssl_engine_kernel.c
+--- modules/ssl/ssl_engine_kernel.c	2015-06-17 15:09:03.000000000 +0200
++++ modules/ssl/ssl_engine_kernel.c	2015-06-17 15:53:25.000000000 +0200
+@@ -29,6 +29,7 @@
+                                   time I was too famous.''
+                                             -- Unknown                */
+ #include "ssl_private.h"
++#include "mod_ssl.h"
+ #include "util_md5.h"
+ 
+ static void ssl_configure_env(request_rec *r, SSLConnRec *sslconn);
+@@ -1889,55 +1890,69 @@
+ }
+ 
+ #ifdef HAVE_TLSEXT
++apr_status_t ssl_select_vhost(conn_rec *c)
++{
++    SSLConnRec *sslconn = myConnConfig(c);
++    const char *servername;
++    
++    if (sslconn == NULL || sslconn->ssl == NULL) {
++        return APR_EINVAL;
++    }
++    else if (sslconn->vhost_selected) {
++        return APR_SUCCESS;
++    }
++    
++    servername = SSL_get_servername(sslconn->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);
++            sslconn->vhost_selected = 1;
++            return APR_SUCCESS;
++        }
++        else {
++            ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(02044)
++                          "No matching SSL virtual host for servername "
++                          "%s found (using default/first virtual host)",
++                          servername);
++            /*
++             * RFC 6066 section 3 says "It is NOT RECOMMENDED to send
++             * a warning-level unrecognized_name(112) alert, because
++             * the client's behavior in response to warning-level alerts
++             * is unpredictable."
++             *
++             * To maintain backwards compatibility in mod_ssl, we
++             * no longer send any alert (neither warning- nor fatal-level),
++             * i.e. we take the second action suggested in RFC 6066:
++             * "If the server understood the ClientHello extension but
++             * does not recognize the server name, the server SHOULD take
++             * one of two actions: either abort the handshake by sending
++             * a fatal-level unrecognized_name(112) alert or continue
++             * the handshake."
++             */
++        }
++    }
++    else {
++        ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(02645)
++                      "Server name not provided via TLS extension "
++                      "(using default/first virtual host)");
++    }
++    
++    return APR_NOTFOUND;
++}
+ /*
+  * 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)
+ {
+-    const char *servername =
+-                SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
+     conn_rec *c = (conn_rec *)SSL_get_app_data(ssl);
+-
+-    if (c) {
+-        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;
+-            }
+-            else {
+-                ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(02044)
+-                              "No matching SSL virtual host for servername "
+-                              "%s found (using default/first virtual host)",
+-                              servername);
+-                /*
+-                 * RFC 6066 section 3 says "It is NOT RECOMMENDED to send
+-                 * a warning-level unrecognized_name(112) alert, because
+-                 * the client's behavior in response to warning-level alerts
+-                 * is unpredictable."
+-                 *
+-                 * To maintain backwards compatibility in mod_ssl, we
+-                 * no longer send any alert (neither warning- nor fatal-level),
+-                 * i.e. we take the second action suggested in RFC 6066:
+-                 * "If the server understood the ClientHello extension but
+-                 * does not recognize the server name, the server SHOULD take
+-                 * one of two actions: either abort the handshake by sending
+-                 * a fatal-level unrecognized_name(112) alert or continue
+-                 * the handshake."
+-                 */
+-            }
+-        }
+-        else {
+-            ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(02645)
+-                          "Server name not provided via TLS extension "
+-                          "(using default/first virtual host)");
+-        }
+-    }
+-
+-    return SSL_TLSEXT_ERR_NOACK;
++    apr_status_t status;
++    
++    status = ssl_select_vhost(c);
++    return (status == APR_SUCCESS)? SSL_TLSEXT_ERR_OK : SSL_TLSEXT_ERR_NOACK;
+ }
+ 
+ /*
+@@ -2136,6 +2151,159 @@
+ }
+ #endif /* HAVE_TLS_SESSION_TICKETS */
+ 
++#ifdef HAVE_TLS_ALPN
++static int ssl_array_index(apr_array_header_t *array,
++                           const char *s)
++{
++    int i;
++    for (i = 0; i < array->nelts; i++) {
++        const char *p = APR_ARRAY_IDX(array, i, const char*);
++        if (!strcmp(p, s)) {
++            return i;
++        }
++    }
++    return -1;
++}
++
++/*
++ * Compare two ALPN protocol proposal. Result is similar to strcmp():
++ * 0 gives same precedence, >0 means proto1 is prefered.
++ */
++static int ssl_cmp_alpn_protos(modssl_ctx_t *ctx,
++                               const char *proto1,
++                               const char *proto2)
++{
++    /* TODO: we should have a mod_ssl configuration parameter. */
++    if (ctx && ctx->ssl_alpn_pref) {
++        int index1 = ssl_array_index(ctx->ssl_alpn_pref, proto1);
++        int index2 = ssl_array_index(ctx->ssl_alpn_pref, proto2);
++        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((const char *)proto1, (const char *)proto2);
++}
++
++/*
++ * This callback function is executed when the TLS Application Layer
++ * Protocol Negotiate 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);
++    server_rec *s       = mySrvFromConn(c);
++    SSLSrvConfigRec *sc = mySrvConfig(s);
++    modssl_ctx_t *mctx  = myCtxConfig(sslconn, sc);
++    const char *alpn_http1 = "http/1.1";
++    apr_array_header_t *client_protos;
++    apr_array_header_t *proposed_protos;
++    int i;
++    size_t len;
++
++    /* If the connection object is not available,
++     * then there's nothing for us to do. */
++    if (c == NULL) {
++        return SSL_TLSEXT_ERR_OK;
++    }
++    
++    /* Make sure that we set the correct vhost based on SNI servername
++     * information. This is supposed to be done by the SNI callback, but
++     * currently the ssl libs call the ALPN callback *before* the SNI one.
++     */
++    ssl_select_vhost(c);
++    
++    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 identier 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;
++    }
++    
++    proposed_protos = apr_array_make(c->pool, client_protos->nelts+1,
++                                     sizeof(char *));
++    
++    if (sslconn->alpn_proposefns != NULL) {
++        /* Invoke our alpn_propos_proto hooks, giving other modules a chance to
++         * propose protocol names for selection. We might have several such
++         * hooks installed and if two make a proposal, we need to give 
++         * preference to one.
++         */
++        for (i = 0; i < sslconn->alpn_proposefns->nelts; i++) {
++            ssl_alpn_propose_protos fn =
++                APR_ARRAY_IDX(sslconn->alpn_proposefns, i,
++                              ssl_alpn_propose_protos);
++            
++            if (fn(c, client_protos, proposed_protos) == DONE)
++                break;
++        }
++    }
++
++    if (proposed_protos->nelts <= 0) {
++        /* Regardless of installed hooks, the http/1.1 protocol is always
++         * supported by us. Choose it if none other matches. */
++        if (ssl_array_index(client_protos, alpn_http1) < 0) {
++            ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(02839)
++                          "none of the client ALPN protocols are supported");
++            return SSL_TLSEXT_ERR_ALERT_FATAL;
++        }
++        *out = (const unsigned char*)alpn_http1;
++        *outlen = (unsigned char)strlen(alpn_http1);
++        return SSL_TLSEXT_ERR_OK;
++    }
++    
++    /* Now select the most preferred protocol from the proposals. */
++    *out = APR_ARRAY_IDX(proposed_protos, 0, const unsigned char *);
++    for (i = 1; i < proposed_protos->nelts; ++i) {
++        const char *proto = APR_ARRAY_IDX(proposed_protos, i, const char*);
++        /* Do we prefer it over existing candidate? */
++        if (ssl_cmp_alpn_protos(mctx, (const char *)*out, proto) < 0) {
++            *out = (const unsigned char*)proto;
++        }
++    }
++    
++    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
++
+ #ifdef HAVE_SRP
+ 
+ int ssl_callback_SRPServerParams(SSL *ssl, int *ad, void *arg)
+diff -ru modules/ssl/ssl_private.h modules/ssl/ssl_private.h
+--- modules/ssl/ssl_private.h	2015-06-17 15:09:03.000000000 +0200
++++ modules/ssl/ssl_private.h	2015-06-17 15:52:15.000000000 +0200
+@@ -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 */
+@@ -443,6 +448,12 @@
+                      * connection */
+     } reneg_state;
+ 
++#ifdef HAVE_TLS_ALPN
++    /* Poor man's inter-module optional hooks for ALPN. */
++    apr_array_header_t *alpn_proposefns; /* list of ssl_alpn_propose_protos callbacks */
++    apr_array_header_t *alpn_negofns; /* list of ssl_alpn_proto_negotiated callbacks. */
++#endif
++    int vhost_selected;
+     server_rec *server;
+ } SSLConnRec;
+ 
+@@ -622,6 +633,10 @@
+     SSL_CONF_CTX *ssl_ctx_config; /* Configuration context */
+     apr_array_header_t *ssl_ctx_param; /* parameters to pass to SSL_CTX */
+ #endif
++  
++#ifdef HAVE_TLS_ALPN
++  apr_array_header_t *ssl_alpn_pref; /* protocol names in order of preference */
++#endif
+ } modssl_ctx_t;
+ 
+ struct SSLSrvConfigRec {
+@@ -748,6 +763,10 @@
+ const char *ssl_cmd_SSLOpenSSLConfCmd(cmd_parms *cmd, void *dcfg, const char *arg1, const char *arg2);
+ #endif
+ 
++#ifdef HAVE_TLS_ALPN
++const char *ssl_cmd_SSLALPNPreference(cmd_parms *cmd, void *dcfg, const char *protocol);
++#endif
++
+ #ifdef HAVE_SRP
+ const char *ssl_cmd_SSLSRPVerifierFile(cmd_parms *cmd, void *dcfg, const char *arg);
+ const char *ssl_cmd_SSLSRPUnknownUserSeed(cmd_parms *cmd, void *dcfg, const char *arg);
+@@ -789,6 +808,7 @@
+ void         ssl_callback_DelSessionCacheEntry(SSL_CTX *, SSL_SESSION *);
+ void         ssl_callback_Info(const SSL *, int, int);
+ #ifdef HAVE_TLSEXT
++apr_status_t ssl_select_vhost(conn_rec *c);
+ int          ssl_callback_ServerNameIndication(SSL *, int *, modssl_ctx_t *);
+ #endif
+ #ifdef HAVE_TLS_SESSION_TICKETS
+@@ -796,6 +816,12 @@
+                                        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);

Added: httpd/httpd/trunk/modules/http2/sandbox/httpd/patches/httpd-2.4.x-alpn-v4.patch
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/sandbox/httpd/patches/httpd-2.4.x-alpn-v4.patch?rev=1688474&view=auto
==============================================================================
--- httpd/httpd/trunk/modules/http2/sandbox/httpd/patches/httpd-2.4.x-alpn-v4.patch (added)
+++ httpd/httpd/trunk/modules/http2/sandbox/httpd/patches/httpd-2.4.x-alpn-v4.patch Tue Jun 30 15:26:16 2015
@@ -0,0 +1,535 @@
+Index: CHANGES
+===================================================================
+--- CHANGES	(revision 1681752)
++++ CHANGES	(working copy)
+@@ -12,6 +12,12 @@ Changes with Apache 2.4.13
+      calls r:wsupgrade() can cause a child process crash. 
+      [Edward Lu <Chaosed0 gmail.com>]
+ 
++  *) mod_ssl: add ALPN support by allowing other modules to register callbacks
++     for negotiation of the application layer protocol.  PR 52210.
++     [Matthew Steele <mdsteele google com>, Joe Orton, Jim Jagielski,
++      Stefan Eissing <stefan eissing org>, Rainer Jung, Ruediger Pluem,
++      Kaspar Brand]
++
+   *) mod_ssl OCSP Stapling: Don't block initial handshakes while refreshing
+      the OCSP response for a different certificate.  mod_ssl has an additional
+      global mutex, "ssl-stapling-refresh".  PR 57131 (partial fix).
+Index: docs/manual/mod/mod_ssl.xml
+===================================================================
+--- docs/manual/mod/mod_ssl.xml	(revision 1681752)
++++ docs/manual/mod/mod_ssl.xml	(working copy)
+@@ -2659,4 +2659,32 @@ SSLOpenSSLConfCmd SignatureAlgorithms RSA+SHA384:E
+ </usage>
+ </directivesynopsis>
+ 
++<directivesynopsis>
++<name>SSLALPNPreference</name>
++<description>Configure protocol preference for Application-Layer Protocol Negotiation (RFC 7301)</description>
++<syntax>SSLALPNPreference <em>protocol-id</em> ...</syntax>
++<contextlist><context>server config</context>
++<context>virtual host</context></contextlist>
++<compatibility>Available if using OpenSSL 1.0.2 or later</compatibility>
++
++<usage>
++<p>This directive overrides preferences by implementations of application-layer
++protocols during negotiation. Protocol IDs must be specified in terms of the
++"Identification Sequence" from IANA's Application-Layer Protocol
++Negotiation (ALPN) Protocol IDs registry. The protocol specified first gets
++precedence over later or unspecified protocols. This list is evaluated
++against client capabilities.</p>
++
++<example><title>Examples</title>
++<highlight language="config">
++SSLALPNPreference h2 spdy/3
++</highlight>
++<p>For clients which support both protocols, <code>h2</code> will be selected. For
++clients which only support <code>spdy/3</code>, that one will be chosen. If a client
++supports only protocol X and there is support for X in httpd, the
++negotiation will select X.</p>
++</example>
++</usage>
++</directivesynopsis>
++
+ </modulesynopsis>
+Index: modules/ssl/mod_ssl.c
+===================================================================
+--- modules/ssl/mod_ssl.c	(revision 1681752)
++++ modules/ssl/mod_ssl.c	(working copy)
+@@ -273,6 +273,12 @@ static const command_rec ssl_config_cmds[] = {
+                 "OpenSSL configuration command")
+ #endif
+ 
++#ifdef HAVE_TLS_ALPN
++    SSL_CMD_SRV(ALPNPreference, ITERATE,
++                "Preference in Application-Layer Protocol Negotiation (ALPN), "
++                "protocols are chosen in the specified order")
++#endif
++
+     /* Deprecated directives. */
+     AP_INIT_RAW_ARGS("SSLLog", ap_set_deprecated, NULL, OR_ALL,
+       "SSLLog directive is no longer supported - use ErrorLog."),
+@@ -426,6 +432,37 @@ int ssl_engine_disable(conn_rec *c)
+     return 1;
+ }
+ 
++static int modssl_register_alpn(conn_rec *c,
++                               ssl_alpn_propose_protos advertisefn,
++                               ssl_alpn_proto_negotiated negotiatedfn)
++{
++#ifdef HAVE_TLS_ALPN
++    SSLConnRec *sslconn = myConnConfig(c);
++
++    if (!sslconn) {
++        return DECLINED;
++    }
++
++    if (!sslconn->alpn_proposefns) {
++        sslconn->alpn_proposefns =
++            apr_array_make(c->pool, 5, sizeof(ssl_alpn_propose_protos));
++        sslconn->alpn_negofns =
++            apr_array_make(c->pool, 5, sizeof(ssl_alpn_proto_negotiated));
++    }
++
++    if (advertisefn)
++        APR_ARRAY_PUSH(sslconn->alpn_proposefns, ssl_alpn_propose_protos) =
++            advertisefn;
++    if (negotiatedfn)
++        APR_ARRAY_PUSH(sslconn->alpn_negofns, ssl_alpn_proto_negotiated) =
++            negotiatedfn;
++
++    return OK;
++#else
++    return DECLINED;
++#endif
++}
++
+ int ssl_init_ssl_connection(conn_rec *c, request_rec *r)
+ {
+     SSLSrvConfigRec *sc;
+@@ -588,6 +625,7 @@ static void ssl_register_hooks(apr_pool_t *p)
+ 
+     APR_REGISTER_OPTIONAL_FN(ssl_proxy_enable);
+     APR_REGISTER_OPTIONAL_FN(ssl_engine_disable);
++    APR_REGISTER_OPTIONAL_FN(modssl_register_alpn);
+ 
+     ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "ssl",
+                               AUTHZ_PROVIDER_VERSION,
+Index: modules/ssl/mod_ssl.h
+===================================================================
+--- modules/ssl/mod_ssl.h	(revision 1681752)
++++ modules/ssl/mod_ssl.h	(working copy)
+@@ -63,5 +63,46 @@ APR_DECLARE_OPTIONAL_FN(int, ssl_proxy_enable, (co
+ 
+ APR_DECLARE_OPTIONAL_FN(int, ssl_engine_disable, (conn_rec *));
+ 
++/** The alpn_propose_proto callback allows other modules to propose
++ * the name of the protocol that will be chosen during the
++ * Application-Layer Protocol Negotiation (ALPN) portion of the SSL handshake.
++ * The callback is given the connection and a list of NULL-terminated
++ * protocol strings as supported by the client.  If this client_protos is 
++ * non-empty, it must pick its preferred protocol from that list. Otherwise
++ * it should add its supported protocols in order of precedence.
++ * The callback should not yet modify the connection or install any filters
++ * as its proposal(s) may be overridden by another callback or server 
++ * configuration. 
++ * It should return OK or, to prevent further processing of (other modules') 
++ * callbacks, return DONE.
++ */
++typedef int (*ssl_alpn_propose_protos)(conn_rec *connection,
++                                       apr_array_header_t *client_protos,
++                                       apr_array_header_t *proposed_protos);
++
++/** The alpn_proto_negotiated callback allows other modules to discover
++ * the name of the protocol that was chosen during the Application-Layer
++ * Protocol Negotiation (ALPN) portion of the SSL handshake.  
++ * The callback is given the connection, a
++ * non-NUL-terminated string containing the protocol name, and the
++ * length of the string; it should do something appropriate
++ * (i.e. insert or remove filters) and return OK. To prevent further
++ * processing of (other modules') callbacks, return DONE. */
++typedef int (*ssl_alpn_proto_negotiated)(conn_rec *connection,
++                                         const char *proto_name,
++                                         apr_size_t proto_name_len);
++
++/* An optional function which can be used to register a pair of callbacks 
++ * for ALPN handling.
++ * This optional function should be invoked from a pre_connection hook 
++ * which runs *after* mod_ssl.c's pre_connection hook.  The function returns 
++ * OK if the callbacks are registered, or DECLINED otherwise (for example if 
++ * mod_ssl does not support ALPN).
++ */
++APR_DECLARE_OPTIONAL_FN(int, modssl_register_alpn,
++                        (conn_rec *conn,
++                         ssl_alpn_propose_protos proposefn,
++                         ssl_alpn_proto_negotiated negotiatedfn));
++
+ #endif /* __MOD_SSL_H__ */
+ /** @} */
+Index: modules/ssl/ssl_engine_config.c
+===================================================================
+--- modules/ssl/ssl_engine_config.c	(revision 1681752)
++++ modules/ssl/ssl_engine_config.c	(working copy)
+@@ -161,6 +161,9 @@ static void modssl_ctx_init(modssl_ctx_t *mctx, ap
+     SSL_CONF_CTX_set_flags(mctx->ssl_ctx_config, SSL_CONF_FLAG_CERTIFICATE);
+     mctx->ssl_ctx_param = apr_array_make(p, 5, sizeof(ssl_ctx_param_t));
+ #endif
++#ifdef HAVE_TLS_ALPN
++    mctx->ssl_alpn_pref = apr_array_make(p, 5, sizeof(const char *));
++#endif
+ }
+ 
+ static void modssl_ctx_init_proxy(SSLSrvConfigRec *sc,
+@@ -305,6 +308,9 @@ static void modssl_ctx_cfg_merge(apr_pool_t *p,
+ #ifdef HAVE_SSL_CONF_CMD
+     cfgMergeArray(ssl_ctx_param);
+ #endif
++#ifdef HAVE_TLS_ALPN
++    cfgMergeArray(ssl_alpn_pref);
++#endif
+ }
+ 
+ static void modssl_ctx_cfg_merge_proxy(apr_pool_t *p,
+@@ -1890,6 +1896,16 @@ const char *ssl_cmd_SSLOpenSSLConfCmd(cmd_parms *c
+ }
+ #endif
+ 
++#ifdef HAVE_TLS_ALPN
++const char *ssl_cmd_SSLALPNPreference(cmd_parms *cmd, void *dcfg,
++                                      const char *protocol)
++{
++    SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
++    APR_ARRAY_PUSH(sc->server->ssl_alpn_pref, const char *) = protocol;
++    return NULL;
++}
++#endif
++
+ #ifdef HAVE_SRP
+ 
+ const char *ssl_cmd_SSLSRPVerifierFile(cmd_parms *cmd, void *dcfg,
+Index: modules/ssl/ssl_engine_init.c
+===================================================================
+--- modules/ssl/ssl_engine_init.c	(revision 1681752)
++++ modules/ssl/ssl_engine_init.c	(working copy)
+@@ -625,6 +625,10 @@ static void ssl_init_ctx_callbacks(server_rec *s,
+     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,
+Index: modules/ssl/ssl_engine_io.c
+===================================================================
+--- modules/ssl/ssl_engine_io.c	(revision 1681752)
++++ modules/ssl/ssl_engine_io.c	(working copy)
+@@ -28,6 +28,7 @@
+                                   core keeps dumping.''
+                                             -- Unknown    */
+ #include "ssl_private.h"
++#include "mod_ssl.h"
+ #include "apr_date.h"
+ 
+ /*  _________________________________________________________________
+@@ -297,6 +298,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 +1416,40 @@ static apr_status_t ssl_io_filter_input(ap_filter_
+         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;
++        int n;
++
++        if (sslconn->alpn_negofns) {
++            SSL_get0_alpn_selected(inctx->ssl, &next_proto, &next_proto_len);
++            ap_log_cerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, f->c,
++                          APLOGNO(02836) "ALPN selected protocol: '%s'",
++                          (next_proto && next_proto_len) ?
++                              apr_pstrmemdup(f->c->pool,
++                                             (const char *)next_proto,
++                                             next_proto_len) :
++                              "(null)");
++            for (n = 0; n < sslconn->alpn_negofns->nelts; n++) {
++                ssl_alpn_proto_negotiated fn =
++                    APR_ARRAY_IDX(sslconn->alpn_negofns, n,
++                                  ssl_alpn_proto_negotiated);
++
++                if (fn(f->c, (const char *)next_proto, next_proto_len) == DONE)
++                    break;
++            }
++        }
++        inctx->alpn_finished = 1;
++    }
++#endif
++
+     return APR_SUCCESS;
+ }
+ 
+@@ -1893,6 +1931,9 @@ static void ssl_io_input_add_filter(ssl_filter_ctx
+     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
+Index: modules/ssl/ssl_engine_kernel.c
+===================================================================
+--- modules/ssl/ssl_engine_kernel.c	(revision 1681752)
++++ modules/ssl/ssl_engine_kernel.c	(working copy)
+@@ -29,6 +29,7 @@
+                                   time I was too famous.''
+                                             -- Unknown                */
+ #include "ssl_private.h"
++#include "mod_ssl.h"
+ #include "util_md5.h"
+ 
+ static void ssl_configure_env(request_rec *r, SSLConnRec *sslconn);
+@@ -2149,6 +2150,152 @@ int ssl_callback_SessionTicket(SSL *ssl,
+ }
+ #endif /* HAVE_TLS_SESSION_TICKETS */
+ 
++#ifdef HAVE_TLS_ALPN
++static int ssl_array_index(apr_array_header_t *array, const char *s)
++{
++    int i;
++    for (i = 0; i < array->nelts; i++) {
++        const char *p = APR_ARRAY_IDX(array, i, const char *);
++        if (!strcmp(p, s)) {
++            return i;
++        }
++    }
++    return -1;
++}
++
++/*
++ * Compare two ALPN protocol proposal. Result is similar to strcmp():
++ * 0 gives same precedence, >0 means proto1 is preferred.
++ */
++static int ssl_cmp_alpn_protos(modssl_ctx_t *ctx,
++                               const char *proto1,
++                               const char *proto2)
++{
++    if (ctx && ctx->ssl_alpn_pref) {
++        int index1 = ssl_array_index(ctx->ssl_alpn_pref, proto1);
++        int index2 = ssl_array_index(ctx->ssl_alpn_pref, proto2);
++        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((const char *)proto1, (const char *)proto2);
++}
++
++/*
++ * 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);
++    server_rec *s = mySrvFromConn(c);
++    SSLSrvConfigRec *sc = mySrvConfig(s);
++    modssl_ctx_t *mctx = myCtxConfig(sslconn, sc);
++    const char *alpn_http1 = "http/1.1";
++    apr_array_header_t *client_protos;
++    apr_array_header_t *proposed_protos;
++    int i;
++    size_t len;
++
++    /* 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;
++    }
++
++    proposed_protos = apr_array_make(c->pool, client_protos->nelts+1,
++                                     sizeof(char *));
++
++    if (sslconn->alpn_proposefns != NULL) {
++        /* Invoke our alpn_propose functions, giving other modules a chance to
++         * propose protocol names for selection. We might have several such
++         * functions installed and if two make a proposal, we need to give
++         * preference to one.
++         */
++        for (i = 0; i < sslconn->alpn_proposefns->nelts; i++) {
++            ssl_alpn_propose_protos fn =
++                APR_ARRAY_IDX(sslconn->alpn_proposefns, i,
++                              ssl_alpn_propose_protos);
++
++            if (fn(c, client_protos, proposed_protos) == DONE)
++                break;
++        }
++    }
++
++    if (proposed_protos->nelts <= 0) {
++        /* Regardless of installed hooks, the http/1.1 protocol is always
++         * supported by us. Choose it if none other matches. */
++        if (ssl_array_index(client_protos, alpn_http1) < 0) {
++            ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(02839)
++                          "none of the client ALPN protocols are supported");
++            return SSL_TLSEXT_ERR_ALERT_FATAL;
++        }
++        *out = (const unsigned char*)alpn_http1;
++        *outlen = (unsigned char)strlen(alpn_http1);
++        return SSL_TLSEXT_ERR_OK;
++    }
++
++    /* Now select the most preferred protocol from the proposals. */
++    *out = APR_ARRAY_IDX(proposed_protos, 0, const unsigned char *);
++    for (i = 1; i < proposed_protos->nelts; ++i) {
++        const char *proto = APR_ARRAY_IDX(proposed_protos, i, const char *);
++        /* Do we prefer it over existing candidate? */
++        if (ssl_cmp_alpn_protos(mctx, (const char *)*out, proto) < 0) {
++            *out = (const unsigned char *)proto;
++        }
++    }
++
++    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)
+Index: modules/ssl/ssl_private.h
+===================================================================
+--- modules/ssl/ssl_private.h	(revision 1681752)
++++ modules/ssl/ssl_private.h	(working copy)
+@@ -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 */
+@@ -443,6 +448,12 @@ typedef struct {
+                      * connection */
+     } reneg_state;
+ 
++#ifdef HAVE_TLS_ALPN
++    /* Poor man's inter-module optional hooks for ALPN. */
++    apr_array_header_t *alpn_proposefns; /* list of ALPN propose callbacks */
++    apr_array_header_t *alpn_negofns; /* list of ALPN negotiation callbacks. */
++#endif
++
+     server_rec *server;
+ } SSLConnRec;
+ 
+@@ -624,6 +635,10 @@ typedef struct {
+     SSL_CONF_CTX *ssl_ctx_config; /* Configuration context */
+     apr_array_header_t *ssl_ctx_param; /* parameters to pass to SSL_CTX */
+ #endif
++  
++#ifdef HAVE_TLS_ALPN
++  apr_array_header_t *ssl_alpn_pref; /* list of ALPN protocol IDs */
++#endif
+ } modssl_ctx_t;
+ 
+ struct SSLSrvConfigRec {
+@@ -750,6 +765,10 @@ const char *ssl_cmd_SSLOCSPEnable(cmd_parms *cmd,
+ const char *ssl_cmd_SSLOpenSSLConfCmd(cmd_parms *cmd, void *dcfg, const char *arg1, const char *arg2);
+ #endif
+ 
++#ifdef HAVE_TLS_ALPN
++const char *ssl_cmd_SSLALPNPreference(cmd_parms *cmd, void *dcfg, const char *protocol);
++#endif
++
+ #ifdef HAVE_SRP
+ const char *ssl_cmd_SSLSRPVerifierFile(cmd_parms *cmd, void *dcfg, const char *arg);
+ const char *ssl_cmd_SSLSRPUnknownUserSeed(cmd_parms *cmd, void *dcfg, const char *arg);
+@@ -798,6 +817,12 @@ int         ssl_callback_SessionTicket(SSL *, unsi
+                                        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);
+Index: .
+===================================================================
+--- .	(revision 1681752)
++++ .	(working copy)
+
+Property changes on: .
+___________________________________________________________________
+Modified: svn:mergeinfo
+   Merged /httpd/httpd/trunk:r1332643,1487772,1670397,1670434,1670436,1670578,1670738,1675459,1676004,1676709,1681741,1681746

Added: httpd/httpd/trunk/modules/http2/sandbox/httpd/patches/httpd-alpn-v4-v5.patch
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/sandbox/httpd/patches/httpd-alpn-v4-v5.patch?rev=1688474&view=auto
==============================================================================
--- httpd/httpd/trunk/modules/http2/sandbox/httpd/patches/httpd-alpn-v4-v5.patch (added)
+++ httpd/httpd/trunk/modules/http2/sandbox/httpd/patches/httpd-alpn-v4-v5.patch Tue Jun 30 15:26:16 2015
@@ -0,0 +1,148 @@
+diff -ru modules/ssl/ssl_engine_kernel.c modules/ssl/ssl_engine_kernel.c
+--- modules/ssl/ssl_engine_kernel.c	2015-06-17 16:55:27.000000000 +0200
++++ modules/ssl/ssl_engine_kernel.c	2015-06-17 16:55:46.000000000 +0200
+@@ -1890,55 +1890,69 @@
+ }
+ 
+ #ifdef HAVE_TLSEXT
++apr_status_t ssl_select_vhost(conn_rec *c)
++{
++    SSLConnRec *sslconn = myConnConfig(c);
++    const char *servername;
++    
++    if (sslconn == NULL || sslconn->ssl == NULL) {
++        return APR_EINVAL;
++    }
++    else if (sslconn->vhost_selected) {
++        return APR_SUCCESS;
++    }
++    
++    servername = SSL_get_servername(sslconn->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);
++            sslconn->vhost_selected = 1;
++            return APR_SUCCESS;
++        }
++        else {
++            ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(02044)
++                          "No matching SSL virtual host for servername "
++                          "%s found (using default/first virtual host)",
++                          servername);
++            /*
++             * RFC 6066 section 3 says "It is NOT RECOMMENDED to send
++             * a warning-level unrecognized_name(112) alert, because
++             * the client's behavior in response to warning-level alerts
++             * is unpredictable."
++             *
++             * To maintain backwards compatibility in mod_ssl, we
++             * no longer send any alert (neither warning- nor fatal-level),
++             * i.e. we take the second action suggested in RFC 6066:
++             * "If the server understood the ClientHello extension but
++             * does not recognize the server name, the server SHOULD take
++             * one of two actions: either abort the handshake by sending
++             * a fatal-level unrecognized_name(112) alert or continue
++             * the handshake."
++             */
++        }
++    }
++    else {
++        ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(02645)
++                      "Server name not provided via TLS extension "
++                      "(using default/first virtual host)");
++    }
++    
++    return APR_NOTFOUND;
++}
+ /*
+  * 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)
+ {
+-    const char *servername =
+-                SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
+     conn_rec *c = (conn_rec *)SSL_get_app_data(ssl);
+-
+-    if (c) {
+-        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;
+-            }
+-            else {
+-                ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(02044)
+-                              "No matching SSL virtual host for servername "
+-                              "%s found (using default/first virtual host)",
+-                              servername);
+-                /*
+-                 * RFC 6066 section 3 says "It is NOT RECOMMENDED to send
+-                 * a warning-level unrecognized_name(112) alert, because
+-                 * the client's behavior in response to warning-level alerts
+-                 * is unpredictable."
+-                 *
+-                 * To maintain backwards compatibility in mod_ssl, we
+-                 * no longer send any alert (neither warning- nor fatal-level),
+-                 * i.e. we take the second action suggested in RFC 6066:
+-                 * "If the server understood the ClientHello extension but
+-                 * does not recognize the server name, the server SHOULD take
+-                 * one of two actions: either abort the handshake by sending
+-                 * a fatal-level unrecognized_name(112) alert or continue
+-                 * the handshake."
+-                 */
+-            }
+-        }
+-        else {
+-            ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(02645)
+-                          "Server name not provided via TLS extension "
+-                          "(using default/first virtual host)");
+-        }
+-    }
+-
+-    return SSL_TLSEXT_ERR_NOACK;
++    apr_status_t status;
++    
++    status = ssl_select_vhost(c);
++    return (status == APR_SUCCESS)? SSL_TLSEXT_ERR_OK : SSL_TLSEXT_ERR_NOACK;
+ }
+ 
+ /*
+@@ -2209,6 +2223,12 @@
+         return SSL_TLSEXT_ERR_OK;
+     }
+     
++    /* Make sure that we set the correct vhost based on SNI servername
++     * information. This is supposed to be done by the SNI callback, but
++     * currently the ssl libs call the ALPN callback *before* the SNI one.
++     */
++    ssl_select_vhost(c);
++    
+     if (inlen == 0) {
+         // someone tries to trick us?
+         ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(02837)
+diff -ru modules/ssl/ssl_private.h modules/ssl/ssl_private.h
+--- modules/ssl/ssl_private.h	2015-06-17 16:55:27.000000000 +0200
++++ modules/ssl/ssl_private.h	2015-06-17 16:55:46.000000000 +0200
+@@ -453,7 +453,7 @@
+     apr_array_header_t *alpn_proposefns; /* list of ssl_alpn_propose_protos callbacks */
+     apr_array_header_t *alpn_negofns; /* list of ssl_alpn_proto_negotiated callbacks. */
+ #endif
+-
++    int vhost_selected;
+     server_rec *server;
+ } SSLConnRec;
+ 
+@@ -808,6 +808,7 @@
+ void         ssl_callback_DelSessionCacheEntry(SSL_CTX *, SSL_SESSION *);
+ void         ssl_callback_Info(const SSL *, int, int);
+ #ifdef HAVE_TLSEXT
++apr_status_t ssl_select_vhost(conn_rec *c);
+ int          ssl_callback_ServerNameIndication(SSL *, int *, modssl_ctx_t *);
+ #endif
+ #ifdef HAVE_TLS_SESSION_TICKETS

Added: httpd/httpd/trunk/modules/http2/sandbox/httpd/patches/httpd-npn.unified.diff.patch
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/sandbox/httpd/patches/httpd-npn.unified.diff.patch?rev=1688474&view=auto
==============================================================================
--- httpd/httpd/trunk/modules/http2/sandbox/httpd/patches/httpd-npn.unified.diff.patch (added)
+++ httpd/httpd/trunk/modules/http2/sandbox/httpd/patches/httpd-npn.unified.diff.patch Tue Jun 30 15:26:16 2015
@@ -0,0 +1,366 @@
+diff -ru modules/ssl/mod_ssl.c modules/ssl/mod_ssl.c
+--- modules/ssl/mod_ssl.c	2015-04-27 17:41:19.000000000 +0200
++++ modules/ssl/mod_ssl.c	2015-04-27 17:45:56.000000000 +0200
+@@ -273,7 +273,7 @@
+ 		"OpenSSL configuration command")
+ #endif
+ 
+-#ifdef HAVE_TLS_ALPN
++#if defined(HAVE_TLS_ALPN) || defined(HAVE_TLS_NPN)
+     SSL_CMD_SRV(ALPNPreference, ITERATE,
+                 "Preference in Application-Layer Protocol Negotiation (ALPN), "
+                 "protocols are chosen in the specified order")
+@@ -429,6 +429,37 @@
+     return 1;
+ }
+ 
++static int modssl_register_npn(conn_rec *c, 
++                               ssl_npn_advertise_protos advertisefn,
++                               ssl_npn_proto_negotiated negotiatedfn)
++{
++#if defined(HAVE_TLS_ALPN) || defined(HAVE_TLS_NPN)
++    SSLConnRec *sslconn = myConnConfig(c);
++
++    if (!sslconn) {
++        return DECLINED;
++    }
++
++    if (!sslconn->npn_advertfns) {
++        sslconn->npn_advertfns = 
++            apr_array_make(c->pool, 5, sizeof(ssl_npn_advertise_protos));
++        sslconn->npn_negofns = 
++            apr_array_make(c->pool, 5, sizeof(ssl_npn_proto_negotiated));
++    }
++
++    if (advertisefn)
++        APR_ARRAY_PUSH(sslconn->npn_advertfns, ssl_npn_advertise_protos) =
++            advertisefn;
++    if (negotiatedfn)
++        APR_ARRAY_PUSH(sslconn->npn_negofns, ssl_npn_proto_negotiated) =
++            negotiatedfn;
++
++    return OK;
++#else
++    return DECLINED;
++#endif
++}
++
+ static int modssl_register_alpn(conn_rec *c,
+                                ssl_alpn_propose_protos advertisefn,
+                                ssl_alpn_proto_negotiated negotiatedfn)
+@@ -623,6 +653,7 @@
+ 
+     APR_REGISTER_OPTIONAL_FN(ssl_proxy_enable);
+     APR_REGISTER_OPTIONAL_FN(ssl_engine_disable);
++    APR_REGISTER_OPTIONAL_FN(modssl_register_npn);
+     APR_REGISTER_OPTIONAL_FN(modssl_register_alpn);
+ 
+     ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "ssl",
+diff -ru modules/ssl/mod_ssl.h modules/ssl/mod_ssl.h
+--- modules/ssl/mod_ssl.h	2015-04-27 17:41:19.000000000 +0200
++++ modules/ssl/mod_ssl.h	2015-04-27 17:45:56.000000000 +0200
+@@ -63,6 +63,41 @@
+ 
+ APR_DECLARE_OPTIONAL_FN(int, ssl_engine_disable, (conn_rec *));
+ 
++/** The npn_advertise_protos callback allows another modules to add
++ * entries to the list of protocol names advertised by the server
++ * during the Next Protocol Negotiation (NPN) portion of the SSL
++ * handshake.  The callback is given the connection and an APR array;
++ * it should push one or more char*'s pointing to NUL-terminated
++ * strings (such as "http/1.1" or "spdy/2") onto the array and return
++ * OK.  To prevent further processing of (other modules') callbacks,
++ * return DONE. */
++typedef int (*ssl_npn_advertise_protos)(conn_rec *connection, 
++                                        apr_array_header_t *protos);
++
++/** The npn_proto_negotiated callback allows other modules to discover
++ * the name of the protocol that was chosen during the Next Protocol
++ * Negotiation (NPN) portion of the SSL handshake.  Note that this may
++ * be the empty string (in which case modules should probably assume
++ * HTTP), or it may be a protocol that was never even advertised by
++ * the server.  The callback is given the connection, a
++ * non-NUL-terminated string containing the protocol name, and the
++ * length of the string; it should do something appropriate
++ * (i.e. insert or remove filters) and return OK.  To prevent further
++ * processing of (other modules') callbacks, return DONE. */
++typedef int (*ssl_npn_proto_negotiated)(conn_rec *connection, 
++                                        const char *proto_name,
++                                        apr_size_t proto_name_len);
++
++/* An optional function which can be used to register a pair of
++ * callbacks for NPN handling.  This optional function should be
++ * invoked from a pre_connection hook which runs *after* mod_ssl.c's
++ * pre_connection hook.  The function returns OK if the callbacks are
++ * register, or DECLINED otherwise (for example if mod_ssl does not
++ * support NPN).  */
++APR_DECLARE_OPTIONAL_FN(int, modssl_register_npn, (conn_rec *conn, 
++                                                   ssl_npn_advertise_protos advertisefn,
++                                                   ssl_npn_proto_negotiated negotiatedfn));
++
+ /** The alpn_propose_proto callback allows other modules to propose
+  * the name of the protocol that will be chosen during the
+  * Application-Layer Protocol Negotiation (ALPN) portion of the SSL handshake.
+diff -ru modules/ssl/ssl_engine_config.c modules/ssl/ssl_engine_config.c
+--- modules/ssl/ssl_engine_config.c	2015-04-27 17:41:19.000000000 +0200
++++ modules/ssl/ssl_engine_config.c	2015-04-27 17:45:56.000000000 +0200
+@@ -159,7 +159,7 @@
+     SSL_CONF_CTX_set_flags(mctx->ssl_ctx_config, SSL_CONF_FLAG_CERTIFICATE);
+     mctx->ssl_ctx_param = apr_array_make(p, 5, sizeof(ssl_ctx_param_t));
+ #endif
+-#ifdef HAVE_TLS_ALPN
++#if defined(HAVE_TLS_ALPN) || defined(HAVE_TLS_NPN)
+     mctx->ssl_alpn_pref = apr_array_make(p, 5, sizeof(const char *));
+ #endif
+ }
+@@ -301,7 +301,7 @@
+ #ifdef HAVE_SSL_CONF_CMD
+     cfgMergeArray(ssl_ctx_param);
+ #endif
+-#ifdef HAVE_TLS_ALPN
++#if defined(HAVE_TLS_ALPN) || defined(HAVE_TLS_NPN)
+     cfgMergeArray(ssl_alpn_pref);
+ #endif
+ }
+@@ -1875,7 +1875,7 @@
+ }
+ #endif
+ 
+-#ifdef HAVE_TLS_ALPN
++#if defined(HAVE_TLS_ALPN) || defined(HAVE_TLS_NPN)
+ const char *ssl_cmd_SSLALPNPreference(cmd_parms *cmd, void *dcfg,
+                                       const char *protocol)
+ {
+diff -ru modules/ssl/ssl_engine_init.c modules/ssl/ssl_engine_init.c
+--- modules/ssl/ssl_engine_init.c	2015-04-27 17:41:19.000000000 +0200
++++ modules/ssl/ssl_engine_init.c	2015-04-27 17:45:56.000000000 +0200
+@@ -628,6 +629,11 @@
+     SSL_CTX_set_alpn_select_cb(
+        ctx, ssl_callback_alpn_select, NULL);
+ #endif
++
++#ifdef HAVE_TLS_NPN
++    SSL_CTX_set_next_protos_advertised_cb(
++        ctx, ssl_callback_AdvertiseNextProtos, NULL);
++#endif
+ }
+ 
+ static apr_status_t ssl_init_ctx_verify(server_rec *s,
+diff -ru modules/ssl/ssl_engine_io.c modules/ssl/ssl_engine_io.c
+--- modules/ssl/ssl_engine_io.c	2015-04-27 17:41:19.000000000 +0200
++++ modules/ssl/ssl_engine_io.c	2015-04-27 17:45:56.000000000 +0200
+@@ -298,7 +298,8 @@
+     apr_pool_t *pool;
+     char buffer[AP_IOBUFSIZE];
+     ssl_filter_ctx_t *filter_ctx;
+-#ifdef HAVE_TLS_ALPN
++#if defined(HAVE_TLS_ALPN) || defined(HAVE_TLS_NPN)
++    int npn_finished;  /* 1 if NPN has finished, 0 otherwise */
+     int alpn_finished;  /* 1 if ALPN has finished, 0 otherwise */
+ #endif
+ } bio_filter_in_ctx_t;
+@@ -1447,6 +1446,37 @@
+     }
+ #endif
+ 
++#ifdef HAVE_TLS_NPN
++    /* By this point, Next Protocol Negotiation (NPN) 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
++     * npn_proto_negotiated_hook. */
++    if (!inctx->npn_finished) {
++        SSLConnRec *sslconn = myConnConfig(f->c);
++        const unsigned char *next_proto = NULL;
++        unsigned next_proto_len = 0;
++        int n;
++
++        if (sslconn->npn_negofns) {
++            SSL_get0_next_proto_negotiated(
++                inctx->ssl, &next_proto, &next_proto_len);
++            ap_log_cerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, f->c,
++                          APLOGNO(02306) "SSL NPN negotiated protocol: '%*s'",
++                          next_proto_len, (const char*)next_proto);
++            
++            for (n = 0; n < sslconn->npn_negofns->nelts; n++) {
++                ssl_npn_proto_negotiated fn = 
++                    APR_ARRAY_IDX(sslconn->npn_negofns, n, ssl_npn_proto_negotiated);
++                
++                if (fn(f->c, (const char *)next_proto, next_proto_len) == DONE)
++                    break;
++            }
++        }
++            
++        inctx->npn_finished = 1;
++    }
++#endif
++
+     return APR_SUCCESS;
+ }
+ 
+@@ -1928,9 +1958,8 @@
+     inctx->block = APR_BLOCK_READ;
+     inctx->pool = c->pool;
+     inctx->filter_ctx = filter_ctx;
+-#ifdef HAVE_TLS_ALPN
++    inctx->npn_finished = 0;
+     inctx->alpn_finished = 0;
+-#endif
+ }
+ 
+ /* The request_rec pointer is passed in here only to ensure that the
+diff -ru modules/ssl/ssl_engine_kernel.c modules/ssl/ssl_engine_kernel.c
+--- modules/ssl/ssl_engine_kernel.c	2015-04-27 17:41:19.000000000 +0200
++++ modules/ssl/ssl_engine_kernel.c	2015-04-27 17:45:56.000000000 +0200
+@@ -2283,6 +2282,96 @@
+     return SSL_TLSEXT_ERR_OK;
+ }
+ #endif
++#if defined(HAVE_TLS_NPN)
++/*
++ * This callback function is executed when SSL needs to decide what protocols
++ * to advertise during Next Protocol Negotiation (NPN).  It must produce a
++ * string in wire format -- a sequence of length-prefixed strings -- indicating
++ * the advertised protocols.  Refer to SSL_CTX_set_next_protos_advertised_cb
++ * in OpenSSL for reference.
++ */
++int ssl_callback_AdvertiseNextProtos(SSL *ssl, const unsigned char **data_out,
++                                     unsigned int *size_out, void *arg)
++{
++    conn_rec *c = (conn_rec*)SSL_get_app_data(ssl);
++    SSLConnRec *sslconn = myConnConfig(c);
++    apr_array_header_t *protos;
++    int num_protos;
++    unsigned int size;
++    int i;
++    unsigned char *data;
++    unsigned char *start;
++
++    *data_out = NULL;
++    *size_out = 0;
++
++    /* If the connection object is not available, or there are no NPN
++     * hooks registered, then there's nothing for us to do. */
++    if (c == NULL || sslconn->npn_advertfns == NULL) {
++        return SSL_TLSEXT_ERR_OK;
++    }
++
++    /* Invoke our npn_advertise_protos hook, giving other modules a chance to
++     * add alternate protocol names to advertise. */
++    protos = apr_array_make(c->pool, 0, sizeof(char *));
++    for (i = 0; i < sslconn->npn_advertfns->nelts; i++) {
++        ssl_npn_advertise_protos fn = 
++            APR_ARRAY_IDX(sslconn->npn_advertfns, i, ssl_npn_advertise_protos);
++        
++        if (fn(c, protos) == DONE)
++            break;
++    }
++    num_protos = protos->nelts;
++
++    /* We now have a list of null-terminated strings; we need to concatenate
++     * them together into a single string, where each protocol name is prefixed
++     * by its length.  First, calculate how long that string will be. */
++    size = 0;
++    for (i = 0; i < num_protos; ++i) {
++        const char *string = APR_ARRAY_IDX(protos, i, const char*);
++        unsigned int length = strlen(string);
++        /* If the protocol name is too long (the length must fit in one byte),
++         * then log an error and skip it. */
++        if (length > 255) {
++            ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(02307)
++                          "SSL NPN protocol name too long (length=%u): %s",
++                          length, string);
++            continue;
++        }
++        /* Leave room for the length prefix (one byte) plus the protocol name
++         * itself. */
++        size += 1 + length;
++    }
++
++    /* If there is nothing to advertise (either because no modules added
++     * anything to the protos array, or because all strings added to the array
++     * were skipped), then we're done. */
++    if (size == 0) {
++        return SSL_TLSEXT_ERR_OK;
++    }
++
++    /* Now we can build the string.  Copy each protocol name string into the
++     * larger string, prefixed by its length. */
++    data = apr_palloc(c->pool, size * sizeof(unsigned char));
++    start = data;
++    for (i = 0; i < num_protos; ++i) {
++        const char *string = APR_ARRAY_IDX(protos, i, const char*);
++        apr_size_t length = strlen(string);
++        if (length > 255)
++            continue;
++        *start = (unsigned char)length;
++        ++start;
++        memcpy(start, string, length * sizeof(unsigned char));
++        start += length;
++    }
++
++    /* Success. */
++    *data_out = data;
++    *size_out = size;
++    return SSL_TLSEXT_ERR_OK;
++}
++
++#endif /* HAVE_TLS_NPN */
+ 
+ #ifdef HAVE_SRP
+ 
+diff -ru modules/ssl/ssl_private.h modules/ssl/ssl_private.h
+--- modules/ssl/ssl_private.h	2015-04-27 17:41:19.000000000 +0200
++++ modules/ssl/ssl_private.h	2015-04-27 17:45:56.000000000 +0200
+@@ -176,6 +176,11 @@
+ #endif
+ #endif
+ 
++/* Next Protocol Negotiation */
++#if !defined(OPENSSL_NO_NEXTPROTONEG) && defined(OPENSSL_NPN_NEGOTIATED)
++#define HAVE_TLS_NPN
++#endif
++
+ /* Secure Remote Password */
+ #if !defined(OPENSSL_NO_SRP) && defined(SSL_CTRL_SET_TLS_EXT_SRP_USERNAME_CB)
+ #define HAVE_SRP
+@@ -448,6 +453,12 @@
+                      * connection */
+     } reneg_state;
+ 
++#ifdef HAVE_TLS_NPN
++    /* Poor man's inter-module optional hooks for NPN. */
++    apr_array_header_t *npn_advertfns; /* list of ssl_npn_advertise_protos callbacks */
++    apr_array_header_t *npn_negofns; /* list of ssl_npn_proto_negotiated callbacks. */
++#endif
++
+ #ifdef HAVE_TLS_ALPN
+     /* Poor man's inter-module optional hooks for ALPN. */
+     apr_array_header_t *alpn_proposefns; /* list of ssl_alpn_propose_protos callbacks */
+@@ -634,7 +645,7 @@
+     apr_array_header_t *ssl_ctx_param; /* parameters to pass to SSL_CTX */
+ #endif
+   
+-#ifdef HAVE_TLS_ALPN
++#if defined(HAVE_TLS_ALPN) || defined(HAVE_TLS_NPN)
+   apr_array_header_t *ssl_alpn_pref; /* protocol names in order of preference */
+ #endif
+ } modssl_ctx_t;
+@@ -763,7 +774,7 @@
+ const char *ssl_cmd_SSLOpenSSLConfCmd(cmd_parms *cmd, void *dcfg, const char *arg1, const char *arg2);
+ #endif
+ 
+-#ifdef HAVE_TLS_ALPN
++#if defined(HAVE_TLS_ALPN) || defined(HAVE_TLS_NPN)
+ const char *ssl_cmd_SSLALPNPreference(cmd_parms *cmd, void *dcfg, const char *protocol);
+ #endif
+ 
+@@ -820,6 +831,9 @@
+                              unsigned char *outlen, const unsigned char *in,
+                              unsigned int inlen, void *arg);
+ #endif
++#ifdef HAVE_TLS_NPN
++int ssl_callback_AdvertiseNextProtos(SSL *ssl, const unsigned char **data, unsigned int *len, void *arg);
++#endif
+ 
+ /**  Session Cache Support  */
+ apr_status_t ssl_scache_init(server_rec *, apr_pool_t *);

Added: httpd/httpd/trunk/modules/http2/sandbox/httpd/patches/openssl-1.0.2-alpn.patch
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/sandbox/httpd/patches/openssl-1.0.2-alpn.patch?rev=1688474&view=auto
==============================================================================
--- httpd/httpd/trunk/modules/http2/sandbox/httpd/patches/openssl-1.0.2-alpn.patch (added)
+++ httpd/httpd/trunk/modules/http2/sandbox/httpd/patches/openssl-1.0.2-alpn.patch Tue Jun 30 15:26:16 2015
@@ -0,0 +1,64 @@
+diff -ur openssl-1.0.2c.orig/ssl/t1_lib.c openssl-1.0.2c/ssl/t1_lib.c
+--- openssl-1.0.2c.orig/ssl/t1_lib.c	2015-06-12 16:51:27.000000000 +0200
++++ openssl-1.0.2c/ssl/t1_lib.c	2015-06-23 09:29:51.000000000 +0200
+@@ -1974,6 +1974,8 @@
+ }
+ 
+ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p,
++                                       const unsigned char **palpn,
++                                       unsigned short *palpn_len,
+                                        unsigned char *d, int n, int *al)
+ {
+     unsigned short type;
+@@ -2360,7 +2362,7 @@
+ # ifndef OPENSSL_NO_NEXTPROTONEG
+         else if (type == TLSEXT_TYPE_next_proto_neg &&
+                  s->s3->tmp.finish_md_len == 0 &&
+-                 s->s3->alpn_selected == NULL) {
++                 *palpn == NULL) {
+             /*-
+              * We shouldn't accept this extension on a
+              * renegotiation.
+@@ -2384,8 +2386,9 @@
+ 
+         else if (type == TLSEXT_TYPE_application_layer_protocol_negotiation &&
+                  s->ctx->alpn_select_cb && s->s3->tmp.finish_md_len == 0) {
+-            if (tls1_alpn_handle_client_hello(s, data, size, al) != 0)
+-                return 0;
++            /* Store extension location for later processing */
++            *palpn = data;
++            *palpn_len = size;
+ # ifndef OPENSSL_NO_NEXTPROTONEG
+             /* ALPN takes precedence over NPN. */
+             s->s3->next_proto_neg_seen = 0;
+@@ -2469,6 +2472,8 @@
+                                  int n)
+ {
+     int al = -1;
++    const unsigned char *alpn = NULL;
++    unsigned short alpn_len = 0;
+     unsigned char *ptmp = *p;
+     /*
+      * Internally supported extensions are parsed first so SNI can be handled
+@@ -2476,7 +2481,7 @@
+      * switch the parent context using SSL_set_SSL_CTX and custom extensions
+      * need to be handled by the new SSL_CTX structure.
+      */
+-    if (ssl_scan_clienthello_tlsext(s, p, d, n, &al) <= 0) {
++    if (ssl_scan_clienthello_tlsext(s, p, &alpn, &alpn_len, d, n, &al) <= 0) {
+         ssl3_send_alert(s, SSL3_AL_FATAL, al);
+         return 0;
+     }
+@@ -2492,6 +2497,12 @@
+         return 0;
+     }
+ 
++    if (alpn != NULL) {
++        if (tls1_alpn_handle_client_hello(s, alpn, alpn_len, &al) != 0) {
++            ssl3_send_alert(s, SSL3_AL_FATAL, al);
++            return 0;
++        }
++    }
+     return 1;
+ }
+ 

Added: httpd/httpd/trunk/modules/http2/sandbox/httpd/patches/sni_misdirect.patch
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/sandbox/httpd/patches/sni_misdirect.patch?rev=1688474&view=auto
==============================================================================
--- httpd/httpd/trunk/modules/http2/sandbox/httpd/patches/sni_misdirect.patch (added)
+++ httpd/httpd/trunk/modules/http2/sandbox/httpd/patches/sni_misdirect.patch Tue Jun 30 15:26:16 2015
@@ -0,0 +1,45 @@
+diff -ru ../httpd-2.4.12.orig/include/httpd.h ./include/httpd.h
+--- ../httpd-2.4.12.orig/include/httpd.h	2014-08-22 20:18:08.000000000 +0200
++++ ./include/httpd.h	2015-06-11 17:05:49.000000000 +0200
+@@ -518,6 +518,7 @@
+ #define HTTP_UNSUPPORTED_MEDIA_TYPE          415
+ #define HTTP_RANGE_NOT_SATISFIABLE           416
+ #define HTTP_EXPECTATION_FAILED              417
++#define HTTP_MISDIRECTED_REQUEST             421
+ #define HTTP_UNPROCESSABLE_ENTITY            422
+ #define HTTP_LOCKED                          423
+ #define HTTP_FAILED_DEPENDENCY               424
+diff -ru ../httpd-2.4.12.orig/modules/http/http_protocol.c ./modules/http/http_protocol.c
+--- ../httpd-2.4.12.orig/modules/http/http_protocol.c	2014-10-16 23:42:45.000000000 +0200
++++ ./modules/http/http_protocol.c	2015-06-11 17:04:49.000000000 +0200
+@@ -135,7 +135,7 @@
+     NULL, /* 418 */
+     NULL, /* 419 */
+     NULL, /* 420 */
+-    NULL, /* 421 */
++    "421 Misdirected Request",
+     "422 Unprocessable Entity",
+     "423 Locked",
+     "424 Failed Dependency",
+@@ -1296,6 +1296,9 @@
+     case HTTP_NETWORK_AUTHENTICATION_REQUIRED:
+         return("<p>The client needs to authenticate to gain\n"
+                "network access.</p>\n");
++    case HTTP_MISDIRECTED_REQUEST:
++        return("<p>The client needs to use a new connection for this \n"
++                   "request as it does not match the SNI name used.</p>\n");
+     default:                    /* HTTP_INTERNAL_SERVER_ERROR */
+         /*
+          * This comparison to expose error-notes could be modified to
+diff -ru ../httpd-2.4.12.orig/modules/ssl/ssl_engine_kernel.c ./modules/ssl/ssl_engine_kernel.c
+--- ../httpd-2.4.12.orig/modules/ssl/ssl_engine_kernel.c	2015-06-10 11:46:00.000000000 +0200
++++ ./modules/ssl/ssl_engine_kernel.c	2015-06-11 16:58:34.000000000 +0200
+@@ -203,7 +203,7 @@
+                 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;
++                return HTTP_MISDIRECTED_REQUEST;
+             }
+         }
+         else if (((sc->strict_sni_vhost_check == SSL_ENABLED_TRUE)

Added: httpd/httpd/trunk/modules/http2/sandbox/nghttp2/Makefile
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/sandbox/nghttp2/Makefile?rev=1688474&view=auto
==============================================================================
--- httpd/httpd/trunk/modules/http2/sandbox/nghttp2/Makefile (added)
+++ httpd/httpd/trunk/modules/http2/sandbox/nghttp2/Makefile Tue Jun 30 15:26:16 2015
@@ -0,0 +1,239 @@
+# Copyright 2015 greenbytes GmbH (https://www.greenbytes.de)
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+NGHTTP2_VERSION = 1.0.4
+NGHTTP2_DIR     = nghttp2-$(NGHTTP2_VERSION)
+NGHTTP2_TAR     = $(NGHTTP2_DIR).tar.gz
+NGHTTP2_URL     = https://github.com/tatsuhiro-t/nghttp2/releases/download/v$(NGHTTP2_VERSION)/$(NGHTTP2_TAR)
+
+NGHTTP2_CONF_ENV=
+NGHTTP2_DEPS    =
+NGHTTP2_CONF    = --prefix=$(BLD_PREFIX) --enable-app
+
+ZLIB_VERSION    = 1.2.8
+ZLIB_DIR        = zlib-$(ZLIB_VERSION)
+ZLIB_TAR        = $(ZLIB_DIR).tar.gz
+ZLIB_URL        = http://zlib.net/$(ZLIB_TAR)
+
+LIBEV_VERSION    = 4.19
+LIBEV_DIR        = libev-$(LIBEV_VERSION)
+LIBEV_TAR        = $(LIBEV_DIR).tar.gz
+LIBEV_URL        = http://dist.schmorp.de/libev/$(LIBEV_TAR)
+LIBEV_CONF_ENV   += PKG_CONFIG_PATH=$(BLD_PREFIX)/lib/pkgconfig \
+    LDFLAGS=-L$(BLD_PREFIX)/lib CFLAGS=-I$(BLD_PREFIX)/include
+
+LIBEVENT_VERSION = 2.0.22-stable
+LIBEVENT_DIR     = libevent-$(LIBEVENT_VERSION)
+LIBEVENT_TAR     = $(LIBEVENT_DIR).tar.gz
+LIBEVENT_URL     = https://github.com/libevent/libevent/releases/download/release-2.0.22-stable/$(LIBEVENT_TAR)
+LIBEVENT_CONF_ENV += PKG_CONFIG_PATH=$(BLD_PREFIX)/lib/pkgconfig \
+    LDFLAGS=-L$(BLD_PREFIX)/lib CFLAGS=-I$(BLD_PREFIX)/include
+
+GEN             = gen
+INST_DIR        = ../install
+BLD_PREFIX      = $(shell dirname $$PWD)/install
+
+CURL_OPTS       = --progress-bar
+
+OS              = $(shell uname -s)
+
+
+NGHTTP2_CONF_ENV += PKG_CONFIG_PATH=$(BLD_PREFIX)/lib/pkgconfig \
+    LDFLAGS=-L$(BLD_PREFIX)/lib CFLAGS=-I$(BLD_PREFIX)/include
+
+
+# For OS X, we drag our own zlib in as the one installed is not
+# recognized by nghttp2 configure.
+# On other OS, we expect a proper zlib/zlib-dev installation
+#
+ifeq ($(OS),Darwin)
+    # we need our own zlib
+    NGHTTP2_DEPS  += $(INST_DIR)/.zlib-installed $(INST_DIR)/.libev-installed
+else
+ifneq (,$(wildcard $(INST_DIR)/lib/pkgconfig/openssl.pc))
+    NGHTTP2_DEPS  += $(INST_DIR)/.libevent-installed
+endif
+endif
+
+all: install
+
+dirs:
+	@mkdir -p $(GEN)/build
+
+clean:
+	@rm -rf $(GEN)/$(NGHTTP2_DIR)
+
+distclean:
+	@rm -rf $(GEN)
+
+distdir:
+	@mkdir -p $(distdir)
+	@tar cf - Makefile patches | (cd $(distdir) && tar xf - )
+
+install:  $(INST_DIR)/.nghttp2-installed
+
+
+################################################################################
+# Install the local nghttp2
+#
+$(INST_DIR)/.nghttp2-installed:  $(GEN)/$(NGHTTP2_DIR)/.nghttp2-built
+	@echo -n installing nghttp2 locally...
+	@cd $(GEN)/$(NGHTTP2_DIR)/ && make install >> ../build.log
+	@echo done.
+	@touch $(INST_DIR)/.nghttp2-installed
+
+
+################################################################################
+# Build the local nghttp2
+#
+$(GEN)/$(NGHTTP2_DIR)/.nghttp2-built: \
+		$(GEN)/$(NGHTTP2_DIR)/.nghttp2-configured
+	@echo -n building nghttp2...
+	@cd $(GEN)/$(NGHTTP2_DIR)/ && make >> ../build.log
+	@echo done.
+	@touch $(GEN)/$(NGHTTP2_DIR)/.nghttp2-built
+
+################################################################################
+# Configure the local nghttp2 sources
+#
+$(GEN)/$(NGHTTP2_DIR)/.nghttp2-configured: \
+		$(NGHTTP2_DEPS) \
+		$(GEN)/$(NGHTTP2_DIR)/.nghttp2-patched
+	@echo -n configuring nghttp2...
+	cd $(GEN)/$(NGHTTP2_DIR)/ && \
+	$(NGHTTP2_CONF_ENV) ./configure $(NGHTTP2_CONF) >> ../build.log
+	@echo done.
+	@touch $(GEN)/$(NGHTTP2_DIR)/.nghttp2-configured
+
+################################################################################
+# Patch the local nghtp2 sources
+#
+$(GEN)/$(NGHTTP2_DIR)/.nghttp2-patched: \
+		$(GEN)/$(NGHTTP2_DIR)/.nghttp2-extracted
+	@touch $(GEN)/$(NGHTTP2_DIR)/.nghttp2-patched
+
+################################################################################
+# Extract nghttp2 source tree
+#
+$(GEN)/$(NGHTTP2_DIR)/.nghttp2-extracted: \
+		$(GEN)/$(NGHTTP2_TAR)
+	@rm -rf $(GEN)/$(NGHTTP2_DIR)
+	@echo -n extracting nghttp2 packages...
+	@cd $(GEN) && tar xfz $(NGHTTP2_TAR)
+	@echo done.
+	@touch $(GEN)/$(NGHTTP2_DIR)/.nghttp2-extracted
+
+################################################################################
+# Retrieve nghttp2 sources
+#
+$(GEN)/$(NGHTTP2_TAR):
+	@mkdir -p $(GEN)
+	curl $(CURL_OPTS) -L $(NGHTTP2_URL) > $(GEN)/$(NGHTTP2_TAR)
+
+
+################################################################################
+# Build + install a local libevent library (if needed)
+#
+$(INST_DIR)/.libevent-installed: \
+		$(GEN)/$(LIBEVENT_DIR)/.libevent-built
+	@echo -n installing libevent locally...
+	@cd $(GEN)/$(LIBEVENT_DIR) && make install >> ../build.log
+	@echo done.
+	@touch $(INST_DIR)/.libevent-installed
+
+$(GEN)/$(LIBEVENT_DIR)/.libevent-built: \
+		$(GEN)/$(LIBEVENT_DIR)/.libevent-configured
+	@echo -n building libevent locally...
+	@cd $(GEN)/$(LIBEVENT_DIR) && make >> ../build.log
+	@echo done.
+	@touch $(GEN)/$(LIBEVENT_DIR)/.libevent-built
+
+$(GEN)/$(LIBEVENT_DIR)/.libevent-configured: \
+        	$(GEN)/$(LIBEVENT_DIR)/.libevent-extracted
+	@echo -n configuring libevent...
+	@cd $(GEN)/$(LIBEVENT_DIR) && $(LIBEVENT_CONF_ENV) ./configure --prefix=$(BLD_PREFIX) --with-sysroot=$(BLD_PREFIX)
+	@echo done.
+	@touch $(GEN)/$(LIBEVENT_DIR)/.libevent-configured
+
+$(GEN)/$(LIBEVENT_DIR)/.libevent-extracted: \
+        $(GEN)/$(LIBEVENT_TAR)
+	@rm -rf $(GEN)/$(LIBEVENT_DIR)
+	@echo -n downloading and extracting libevent...
+	@cd gen; tar xfz $(LIBEVENT_TAR)
+	@echo done.
+	@touch $(GEN)/$(LIBEVENT_DIR)/.libevent-extracted
+
+$(GEN)/$(LIBEVENT_TAR):
+	@mkdir -p $(GEN)
+	curl $(CURL_OPTS) -L $(LIBEVENT_URL) > $(GEN)/$(LIBEVENT_TAR)
+
+################################################################################
+# Build + install a local libev library (if needed)
+#
+$(INST_DIR)/.libev-installed: \
+		$(GEN)/$(LIBEV_DIR)/.libev-built
+	@echo -n installing libev locally...
+	@cd $(GEN)/$(LIBEV_DIR) && make install >> ../build.log
+	@echo done.
+	@touch $(INST_DIR)/.libev-installed
+
+$(GEN)/$(LIBEV_DIR)/.libev-built: \
+		$(GEN)/$(LIBEV_DIR)/.libev-configured
+	@echo -n building libev locally...
+	@cd $(GEN)/$(LIBEV_DIR) && make >> ../build.log
+	@echo done.
+	@touch $(GEN)/$(LIBEV_DIR)/.libev-built
+
+$(GEN)/$(LIBEV_DIR)/.libev-configured: $(GEN)/$(LIBEV_TAR)
+	@rm -rf $(GEN)/$(LIBEV_DIR)
+	@cd $(GEN) && tar xfz $(LIBEV_TAR)
+	@echo -n configuring libev...
+	@cd $(GEN)/$(LIBEV_DIR) && $(LIBEV_CONF_ENV) ./configure --prefix=$(BLD_PREFIX)
+	@echo done.
+	@touch $(GEN)/$(LIBEV_DIR)/.libev-configured
+
+$(GEN)/$(LIBEV_TAR):
+	@mkdir -p $(GEN)
+	curl $(CURL_OPTS) -L $(LIBEV_URL) > $(GEN)/$(LIBEV_TAR)
+
+################################################################################
+# Build + install a local zlib library (if needed)
+#
+$(INST_DIR)/.zlib-installed: \
+		$(GEN)/$(ZLIB_DIR)/.zlib-built
+	@echo -n installing zlib locally...
+	@cd $(GEN)/$(ZLIB_DIR) && make install >> ../build.log
+	@echo done.
+	@touch $(INST_DIR)/.zlib-installed
+
+$(GEN)/$(ZLIB_DIR)/.zlib-built: \
+		$(GEN)/$(ZLIB_DIR)/.zlib-configured
+	@echo -n building zlib locally...
+	@cd $(GEN)/$(ZLIB_DIR) && make >> ../build.log
+	@echo done.
+	@touch $(GEN)/$(ZLIB_DIR)/.zlib-built
+
+$(GEN)/$(ZLIB_DIR)/.zlib-configured: $(GEN)/$(ZLIB_TAR)
+	@rm -rf $(GEN)/$(ZLIB_DIR)
+	@cd $(GEN) && tar xfz $(ZLIB_TAR)
+	@echo -n configuring zlib...
+	@cd $(GEN)/$(ZLIB_DIR) && ./configure --prefix=$(BLD_PREFIX)
+	@echo done.
+	@touch $(GEN)/$(ZLIB_DIR)/.zlib-configured
+
+$(GEN)/$(ZLIB_TAR):
+	@mkdir -p $(GEN)
+	curl $(CURL_OPTS) -L $(ZLIB_URL) > $(GEN)/$(ZLIB_TAR)
+



Mime
View raw message