summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--STATUS2
-rw-r--r--include/http_protocol.h7
-rw-r--r--modules/http/http_request.c2
-rw-r--r--modules/http2/h2_request.c2
-rw-r--r--server/protocol.c20
-rw-r--r--server/util.c70
6 files changed, 78 insertions, 25 deletions
diff --git a/STATUS b/STATUS
index 16e969091d..27b349e67a 100644
--- a/STATUS
+++ b/STATUS
@@ -178,7 +178,7 @@ OLD ISSUES THAT WERE THOUGHT TO BE SHOWSTOPPERS FOR 2.4 BUT OBVIOUSLY WEREN'T:
clearly wrong, and even if so, it doesn't seem like a
showstopper.
- * the edge connection filter cannot be removed
+ * the edge connection filter cannot be removed
http://marc.theaimsgroup.com/?l=apache-httpd-dev&m=105366252619530&w=2
http://mail-archives.apache.org/mod_mbox/httpd-dev/200501.mbox/%3C41E30B42.4060202@stason.org%3E
jerenkrantz asks: Why should this block a release?
diff --git a/include/http_protocol.h b/include/http_protocol.h
index 9c9cb952b2..38eef396a3 100644
--- a/include/http_protocol.h
+++ b/include/http_protocol.h
@@ -96,6 +96,13 @@ AP_DECLARE(void) ap_get_mime_headers(request_rec *r);
AP_DECLARE(void) ap_get_mime_headers_core(request_rec *r,
apr_bucket_brigade *bb);
+/**
+ * Run post_read_request hook and validate.
+ * @param r The current request
+ * @return OK or HTTP_...
+ */
+AP_DECLARE(int) ap_post_read_request(request_rec *r);
+
/* Finish up stuff after a request */
/**
diff --git a/modules/http/http_request.c b/modules/http/http_request.c
index a5fdaf44f9..5327dd0e04 100644
--- a/modules/http/http_request.c
+++ b/modules/http/http_request.c
@@ -690,7 +690,7 @@ static request_rec *internal_internal_redirect(const char *new_uri,
* to do their thing on internal redirects as well. Perhaps this is a
* misnamed function.
*/
- if ((access_status = ap_run_post_read_request(new))) {
+ if ((access_status = ap_post_read_request(new))) {
ap_die(access_status, new);
return NULL;
}
diff --git a/modules/http2/h2_request.c b/modules/http2/h2_request.c
index 7c9f38a26a..54721c45af 100644
--- a/modules/http2/h2_request.c
+++ b/modules/http2/h2_request.c
@@ -383,7 +383,7 @@ request_rec *h2_create_request_rec(const h2_request *req, conn_rec *c)
ap_add_input_filter_handle(ap_http_input_filter_handle,
NULL, r, r->connection);
- if ((access_status = ap_run_post_read_request(r))) {
+ if ((access_status = ap_post_read_request(r))) {
/* Request check post hooks failed. An example of this would be a
* request for a vhost where h2 is disabled --> 421.
*/
diff --git a/server/protocol.c b/server/protocol.c
index c4dc7b5763..ece88fea14 100644
--- a/server/protocol.c
+++ b/server/protocol.c
@@ -1595,7 +1595,7 @@ request_rec *ap_read_request(conn_rec *conn)
/* we may have switched to another server */
apply_server_config(r);
- if ((access_status = ap_run_post_read_request(r))) {
+ if ((access_status = ap_post_read_request(r))) {
goto die;
}
@@ -1650,6 +1650,24 @@ ignore:
return NULL;
}
+AP_DECLARE(int) ap_post_read_request(request_rec *r)
+{
+ int status;
+
+ if ((status = ap_run_post_read_request(r))) {
+ return status;
+ }
+
+ /* Enforce http(s) only scheme for non-forward-proxy requests */
+ if (!r->proxyreq
+ && r->parsed_uri.scheme
+ && ap_cstr_casecmp(r->parsed_uri.scheme, ap_http_scheme(r)) != 0) {
+ return HTTP_BAD_REQUEST;
+ }
+
+ return OK;
+}
+
/* if a request with a body creates a subrequest, remove original request's
* input headers which pertain to the body which has already been read.
* out-of-line helper function for ap_set_sub_req_protocol.
diff --git a/server/util.c b/server/util.c
index d3f3ac63c0..82b5a50198 100644
--- a/server/util.c
+++ b/server/util.c
@@ -1735,36 +1735,50 @@ AP_DECLARE(char *) ap_get_token(apr_pool_t *p, const char **accept_line,
return token;
}
+#define IS_TOKEN_SEP(c) ((c) == ',' || (c) == ';')
/* find http tokens, see the definition of token from RFC2068 */
AP_DECLARE(int) ap_find_token(apr_pool_t *p, const char *line, const char *tok)
{
const unsigned char *start_token;
const unsigned char *s;
+ apr_size_t tlen;
- if (!line)
+ tlen = strlen(tok);
+ if (!line || !tlen)
return 0;
s = (const unsigned char *)line;
for (;;) {
- /* find start of token, skip all stop characters */
- while (*s && TEST_CHAR(*s, T_HTTP_TOKEN_STOP)) {
+ /* find start of token */
+ while (apr_isspace(*s) || IS_TOKEN_SEP(*s)) {
++s;
}
if (!*s) {
return 0;
}
- start_token = s;
- /* find end of the token */
- while (*s && !TEST_CHAR(*s, T_HTTP_TOKEN_STOP)) {
- ++s;
- }
- if (!ap_cstr_casecmpn((const char *)start_token, (const char *)tok,
- s - start_token)) {
- return 1;
+ if (!TEST_CHAR(*s, T_HTTP_TOKEN_STOP)) {
+ /* find end of token */
+ start_token = s;
+ do {
+ ++s;
+ } while (!TEST_CHAR(*s, T_HTTP_TOKEN_STOP));
+
+ if (tlen == (apr_size_t)(s - start_token)) {
+ /* only spaces up to the next token separator */
+ while (apr_isspace(*s)) {
+ ++s;
+ }
+ if ((!*s || IS_TOKEN_SEP(*s))
+ && !ap_cstr_casecmpn((const char *)start_token,
+ (const char *)tok, tlen)) {
+ return 1;
+ }
+ }
}
- if (!*s) {
- return 0;
+ /* advance to the next token */
+ while (*s && !IS_TOKEN_SEP(*s)) {
+ ++s;
}
}
}
@@ -1772,23 +1786,37 @@ AP_DECLARE(int) ap_find_token(apr_pool_t *p, const char *line, const char *tok)
static const char *find_last_token(apr_pool_t *p, const char *line,
const char *tok)
{
- int llen, tlen, lidx;
+ apr_size_t llen, tlen;
+ apr_ssize_t lidx;
if (!line)
return NULL;
- llen = strlen(line);
tlen = strlen(tok);
- lidx = llen - tlen;
+ if (!tlen)
+ return NULL;
- if (lidx < 0 ||
- (lidx > 0 && !(apr_isspace(line[lidx - 1]) || line[lidx - 1] == ',')))
+ llen = strlen(line);
+ while (llen > 0 && apr_isspace(line[llen - 1]))
+ --llen;
+ lidx = llen - tlen;
+ if (lidx < 0)
return NULL;
- if (ap_cstr_casecmpn(&line[lidx], tok, tlen) == 0) {
- return &line[lidx];
+ if (lidx > 0) {
+ apr_size_t i = lidx - 1;
+ do {
+ if (line[i] == ',')
+ break;
+ if (!apr_isspace(line[i]))
+ return NULL;
+ } while (i--);
}
- return NULL;
+
+ if (ap_cstr_casecmpn(&line[lidx], tok, tlen) != 0)
+ return NULL;
+
+ return &line[lidx];
}
AP_DECLARE(int) ap_find_last_token(apr_pool_t *p, const char *line,