diff options
author | Valentin Bartenev <vbart@nginx.com> | 2019-09-16 20:17:42 +0300 |
---|---|---|
committer | Valentin Bartenev <vbart@nginx.com> | 2019-09-16 20:17:42 +0300 |
commit | 64be8717bdc2f0f8f11cbb8d18a0f96d2c24c6d3 (patch) | |
tree | 1539675a0756c9356719fd6b679eabea840983dc | |
parent | b5394c39568d9895d5c84862e7a209b76f98bea9 (diff) | |
download | unit-64be8717bdc2f0f8f11cbb8d18a0f96d2c24c6d3.tar.gz unit-64be8717bdc2f0f8f11cbb8d18a0f96d2c24c6d3.tar.bz2 |
Configuration: added ability to access object members with slashes.
Now URI encoding can be used to escape "/" in the request path:
GET /config/listeners/unix:%2Fpath%2Fto%2Fsocket/
-rw-r--r-- | src/nxt_conf.c | 15 | ||||
-rw-r--r-- | src/nxt_controller.c | 2 | ||||
-rw-r--r-- | src/nxt_http_parse.c | 30 | ||||
-rw-r--r-- | src/nxt_http_parse.h | 3 | ||||
-rw-r--r-- | src/nxt_string.c | 56 | ||||
-rw-r--r-- | src/nxt_string.h | 2 |
6 files changed, 104 insertions, 4 deletions
diff --git a/src/nxt_conf.c b/src/nxt_conf.c index 57870838..ff82e1d2 100644 --- a/src/nxt_conf.c +++ b/src/nxt_conf.c @@ -416,10 +416,13 @@ static void nxt_conf_path_next_token(nxt_conf_path_parse_t *parse, nxt_conf_value_t * nxt_conf_get_path(nxt_conf_value_t *value, nxt_str_t *path) { + u_char *end; nxt_str_t token; nxt_int_t index; nxt_conf_path_parse_t parse; + u_char buf[256]; + parse.start = path->start; parse.end = path->start + path->length; parse.last = 0; @@ -436,6 +439,18 @@ nxt_conf_get_path(nxt_conf_value_t *value, nxt_str_t *path) return NULL; } + if (nxt_slow_path(token.length > 256)) { + return NULL; + } + + end = nxt_decode_uri(buf, token.start, token.length); + if (nxt_slow_path(end == NULL)) { + return NULL; + } + + token.length = end - buf; + token.start = buf; + switch (value->type) { case NXT_CONF_VALUE_OBJECT: diff --git a/src/nxt_controller.c b/src/nxt_controller.c index 49afbe46..86ba1246 100644 --- a/src/nxt_controller.c +++ b/src/nxt_controller.c @@ -478,6 +478,8 @@ nxt_controller_conn_init(nxt_task_t *task, void *obj, void *data) return; } + r->parser.encoded_slashes = 1; + b = nxt_buf_mem_alloc(c->mem_pool, 1024, 0); if (nxt_slow_path(b == NULL)) { nxt_controller_conn_free(task, c, NULL); diff --git a/src/nxt_http_parse.c b/src/nxt_http_parse.c index 8b4bf47c..945f4e93 100644 --- a/src/nxt_http_parse.c +++ b/src/nxt_http_parse.c @@ -1046,12 +1046,25 @@ nxt_http_parse_complex_target(nxt_http_request_parse_t *rp) if (ch >= '0' && ch <= '9') { ch = (u_char) ((high << 4) + ch - '0'); - if (ch == '%' || ch == '#') { + if (ch == '%') { state = sw_normal; - *u++ = ch; + *u++ = '%'; + + if (rp->encoded_slashes) { + *u++ = '2'; + *u++ = '5'; + } + + continue; + } + + if (ch == '#') { + state = sw_normal; + *u++ = '#'; continue; + } - } else if (ch == '\0') { + if (ch == '\0') { return NXT_HTTP_PARSE_INVALID; } @@ -1067,8 +1080,17 @@ nxt_http_parse_complex_target(nxt_http_request_parse_t *rp) state = sw_normal; *u++ = ch; continue; + } + + if (ch == '/' && rp->encoded_slashes) { + state = sw_normal; + *u++ = '%'; + *u++ = '2'; + *u++ = p[-1]; /* 'f' or 'F' */ + continue; + } - } else if (ch == '+') { + if (ch == '+') { rp->plus_in_target = 1; } diff --git a/src/nxt_http_parse.h b/src/nxt_http_parse.h index 42189182..e42ec9a4 100644 --- a/src/nxt_http_parse.h +++ b/src/nxt_http_parse.h @@ -68,6 +68,9 @@ struct nxt_http_request_parse_s { unsigned space_in_target:1; /* target with "+" */ unsigned plus_in_target:1; + + /* Preserve encoded '/' (%2F) and '%' (%25). */ + unsigned encoded_slashes:1; }; diff --git a/src/nxt_string.c b/src/nxt_string.c index 7d8c1ce3..4d3b3954 100644 --- a/src/nxt_string.c +++ b/src/nxt_string.c @@ -451,3 +451,59 @@ nxt_strvers_match(u_char *version, u_char *prefix, size_t length) return 0; } + + +u_char * +nxt_decode_uri(u_char *dst, u_char *src, size_t length) +{ + u_char *end, ch; + uint8_t d0, d1; + + static const uint8_t hex[256] + nxt_aligned(32) = + { + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 16, 16, 16, 16, 16, 16, + 16, 10, 11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 10, 11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + }; + + nxt_prefetch(&hex['0']); + + end = src + length; + + while (src < end) { + ch = *src++; + + if (ch == '%') { + if (nxt_slow_path(end - src < 2)) { + return NULL; + } + + d0 = hex[*src++]; + d1 = hex[*src++]; + + if (nxt_slow_path((d0 | d1) >= 16)) { + return NULL; + } + + ch = (d0 << 4) + d1; + } + + *dst++ = ch; + } + + return dst; +} diff --git a/src/nxt_string.h b/src/nxt_string.h index 22a63a17..56d7316b 100644 --- a/src/nxt_string.h +++ b/src/nxt_string.h @@ -168,5 +168,7 @@ NXT_EXPORT nxt_int_t nxt_strverscmp(const u_char *s1, const u_char *s2); NXT_EXPORT nxt_bool_t nxt_strvers_match(u_char *version, u_char *prefix, size_t length); +NXT_EXPORT u_char *nxt_decode_uri(u_char *dst, u_char *src, size_t length); + #endif /* _NXT_STRING_H_INCLUDED_ */ |