summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorValentin Bartenev <vbart@nginx.com>2019-09-16 20:17:42 +0300
committerValentin Bartenev <vbart@nginx.com>2019-09-16 20:17:42 +0300
commit64be8717bdc2f0f8f11cbb8d18a0f96d2c24c6d3 (patch)
tree1539675a0756c9356719fd6b679eabea840983dc
parentb5394c39568d9895d5c84862e7a209b76f98bea9 (diff)
downloadunit-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.c15
-rw-r--r--src/nxt_controller.c2
-rw-r--r--src/nxt_http_parse.c30
-rw-r--r--src/nxt_http_parse.h3
-rw-r--r--src/nxt_string.c56
-rw-r--r--src/nxt_string.h2
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_ */