From: Stefan Eissing
Date: Thu, 3 Sep 2015 12:45:26 +0000 (+0000)
Subject: changed Protocols default to http/1.1 only, updated documentation, changed ap_select_...
X-Git-Tag: 2.5.0-alpha~2873
X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=379f9d4d3389d312751eb4596c4b4c6112da6452;p=apache
changed Protocols default to http/1.1 only, updated documentation, changed ap_select_protocol() to return NULL when no protocol could be agreed upon
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1701005 13f79535-47bb-0310-9956-ffa450edef68
---
diff --git a/docs/manual/mod/core.xml b/docs/manual/mod/core.xml
index 8455834303..a1bfd58191 100644
--- a/docs/manual/mod/core.xml
+++ b/docs/manual/mod/core.xml
@@ -3714,6 +3714,7 @@ Protocol https
Protocols
Protocols available for a server/virtual host
Protocols protocol ...
+ Protocols http/1.1
server configvirtual host
Only available from Apache 2.4.17 and later.
@@ -3722,15 +3723,16 @@ Protocol https
server/virtual host. The list determines the allowed protocols
a client may negotiate for this server/host.
- You only need to set protocols if you want to limit the available
- protocols for a server/host. By default, all supported protocols
- are available to a client.
+ You need to set protocols if you want to extend the available
+ protocols for a server/host. By default, only the http/1.1 protocol
+ (which includes the compatibility with 1.0 and 0.9 clients) is
+ allowed.
- For example, if you want to support only HTTP/1.1 for a server, even
- though HTTP/2 is available, just specify this protocol only:
+ For example, if you want to support HTTP/2 for a server with TLS,
+ specify:
- Protocols http/1.1
+ Protocols h2 http/1.1
Valid protocols are http/1.1
for http and https connections,
@@ -3755,7 +3757,7 @@ Protocol https
ProtocolsHonorOrder
Protocols available for a server/virtual host
ProtocolsHonorOrder On|Off
- ProtocolsHonorOrder Off
+ ProtocolsHonorOrder On
server configvirtual host
Only available from Apache 2.4.17 and later.
@@ -3763,12 +3765,13 @@ Protocol https
This directive specifies if the server should honor the order in which
the Protocols directive lists protocols.
- By default, a client supplies a list of supported protocols and the server
- selects an available one from that list in the given order.
+ If configured Off, the client supplied list order of protocols has
+ precedence over the order in the server configuration.
- With ProtocolsHonorOrder set to on
, the
- client ordering does not matter and only the ordering in the server
- settings influences the outcome of the protocol negotiation.
+ With ProtocolsHonorOrder set to on
+ (default), the client ordering does not matter and only the ordering
+ in the server settings influences the outcome of the protocol
+ negotiation.
Protocols
diff --git a/include/http_protocol.h b/include/http_protocol.h
index 06f32f12c9..3867b3458d 100644
--- a/include/http_protocol.h
+++ b/include/http_protocol.h
@@ -786,13 +786,17 @@ AP_DECLARE_HOOK(const char *,protocol_get,(const conn_rec *c))
/**
* Select a protocol for the given connection and optional request. Will return
* the protocol identifier selected which may be the protocol already in place
- * on the connection. The server may ignore the choices given.
+ * on the connection. The selected protocol will be NULL if non of the given
+ * choices could be agreed upon (e.g. no proposal as made).
+ *
+ * A special case is where the choices itself is NULL (instead of empty). In
+ * this case there are no restrictions imposed on protocol selection.
*
* @param c The current connection
* @param r The current request or NULL
* @param s The server/virtual host selected
* @param choices A list of protocol identifiers, normally the clients whishes
- * @return The selected protocol
+ * @return The selected protocol or NULL if no protocol could be agreed upon
*/
AP_DECLARE(const char *) ap_select_protocol(conn_rec *c, request_rec *r,
server_rec *s,
diff --git a/modules/ssl/ssl_engine_kernel.c b/modules/ssl/ssl_engine_kernel.c
index 60865b7ae8..b9abb196f9 100644
--- a/modules/ssl/ssl_engine_kernel.c
+++ b/modules/ssl/ssl_engine_kernel.c
@@ -2173,6 +2173,7 @@ int ssl_callback_alpn_select(SSL *ssl,
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;
@@ -2210,8 +2211,9 @@ int ssl_callback_alpn_select(SSL *ssl,
*/
init_vhost(c, ssl);
- *out = (const unsigned char *)ap_select_protocol(c, NULL, sslconn->server,
- client_protos);
+ proposed = (const unsigned char *)ap_select_protocol(c, NULL, sslconn->server,
+ client_protos);
+ *out = 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)
diff --git a/server/core.c b/server/core.c
index b16267bc77..7c752b1658 100644
--- a/server/core.c
+++ b/server/core.c
@@ -433,6 +433,7 @@ static void *merge_core_dir_configs(apr_pool_t *a, void *basev, void *newv)
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));
@@ -5303,7 +5304,7 @@ static int core_upgrade_handler(request_rec *r)
if (offers && offers->nelts > 0) {
const char *protocol = ap_select_protocol(c, r, r->server,
offers);
- if (strcmp(protocol, ap_get_protocol(c))) {
+ 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. */
diff --git a/server/protocol.c b/server/protocol.c
index 014957adfa..3abd4d22be 100644
--- a/server/protocol.c
+++ b/server/protocol.c
@@ -1982,53 +1982,77 @@ AP_DECLARE(const char *) ap_select_protocol(conn_rec *c, request_rec *r,
apr_array_header_t *choices)
{
apr_pool_t *pool = r? r->pool : c->pool;
- apr_array_header_t *proposals;
- const char *protocol = NULL, *existing = ap_get_protocol(c);
core_server_config *conf = ap_get_core_module_config(s->module_config);
+ const char *protocol = NULL, *existing = ap_get_protocol(c);;
+ 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, ','),
+ p, choices?
+ apr_array_pstrcat(pool, choices, ',') : "NULL",
s->server_hostname);
}
- proposals = apr_array_make(pool, choices->nelts+1, sizeof(char *));
+ proposals = apr_array_make(pool, choices? choices->nelts+1 : 5,
+ sizeof(char *));
ap_run_protocol_propose(c, r, s, choices, proposals);
if (proposals->nelts > 0) {
int i;
- apr_array_header_t *prefs = ((conf->protocols_honor_order > 0
- && conf->protocols->nelts > 0)?
- conf->protocols : choices);
+ apr_array_header_t *prefs = NULL;
+
+ /* Default for protocols_honor_order is 'on' or != 0 */
+ if (conf->protocols_honor_order == 0 && choices && choices->nelts > 0) {
+ prefs = choices;
+ }
+ else {
+ prefs = conf->protocols;
+ }
/* If the existing protocol has not been proposed, but is a choice,
* add it to the proposals implicitly.
*/
- if (!ap_array_str_contains(proposals, existing)
+ if (choices
+ && !ap_array_str_contains(proposals, existing)
&& ap_array_str_contains(choices, existing)) {
APR_ARRAY_PUSH(proposals, const char*) = existing;
}
-
+
/* Select the most preferred protocol */
if (APLOGcdebug(c)) {
ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c,
- "select protocol, proposals=%s preferences=%s",
+ "select protocol, proposals=%s preferences=%s configured=%s",
apr_array_pstrcat(pool, proposals, ','),
- apr_array_pstrcat(pool, prefs, ','));
+ 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 (conf->protocols->nelts > 0
- && !ap_array_str_contains(conf->protocols, p)) {
- /* not a permitted protocol here */
- continue;
- }
- else if (!protocol
- || (protocol_cmp(prefs, protocol, p) < 0)) {
- /* none selected yet or this on has preference */
- protocol = p;
+ if (conf->protocols->nelts <= 0) {
+ /* nothing configured, by default, we only allow http/1.1 here.
+ * For now...
+ */
+ return (ap_array_str_contains(proposals, AP_PROTOCOL_HTTP1)?
+ AP_PROTOCOL_HTTP1 : NULL);
+ }
+ else {
+ for (i = 0; i < proposals->nelts; ++i) {
+ const char *p = APR_ARRAY_IDX(proposals, i, const char *);
+ if (conf->protocols->nelts <= 0 && !strcmp(AP_PROTOCOL_HTTP1, p)) {
+ /* nothing configured, by default, we only allow http/1.1 here.
+ * For now...
+ */
+ continue;
+ }
+ 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;
+ }
}
}
}
@@ -2037,7 +2061,7 @@ AP_DECLARE(const char *) ap_select_protocol(conn_rec *c, request_rec *r,
protocol? protocol : "(none)");
}
- return protocol? protocol : existing;
+ return protocol;
}
AP_DECLARE(apr_status_t) ap_switch_protocol(conn_rec *c, request_rec *r,