Teach ngx_http_parse_unsafe_uri() how to unescape URIs.

This fixes handling of escaped URIs in X-Accel-Redirect (ticket #316),
SSI (ticket #240), and DAV.
This commit is contained in:
Ruslan Ermilov 2013-12-23 18:12:00 +04:00
parent 336bcb22d1
commit f7ff5e65d0
2 changed files with 60 additions and 17 deletions

View File

@ -1982,8 +1982,6 @@ static ngx_int_t
ngx_http_ssi_include(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
ngx_str_t **params)
{
u_char *dst, *src;
size_t len;
ngx_int_t rc, key;
ngx_str_t *uri, *file, *wait, *set, *stub, args;
ngx_buf_t *b;
@ -2054,18 +2052,6 @@ ngx_http_ssi_include(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
return rc;
}
dst = uri->data;
src = uri->data;
ngx_unescape_uri(&dst, &src, uri->len, NGX_UNESCAPE_URI);
len = (uri->data + uri->len) - src;
if (len) {
dst = ngx_movemem(dst, src, len);
}
uri->len = dst - uri->data;
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"ssi include: \"%V\"", uri);

View File

@ -1780,11 +1780,13 @@ ngx_int_t
ngx_http_parse_unsafe_uri(ngx_http_request_t *r, ngx_str_t *uri,
ngx_str_t *args, ngx_uint_t *flags)
{
u_char ch, *p;
size_t len;
u_char ch, *p, *src, *dst;
size_t len;
ngx_uint_t quoted;
len = uri->len;
p = uri->data;
quoted = 0;
if (len == 0 || p[0] == '?') {
goto unsafe;
@ -1800,6 +1802,11 @@ ngx_http_parse_unsafe_uri(ngx_http_request_t *r, ngx_str_t *uri,
ch = *p++;
if (ch == '%') {
quoted = 1;
continue;
}
if (usual[ch >> 5] & (1 << (ch & 0x1f))) {
continue;
}
@ -1809,7 +1816,7 @@ ngx_http_parse_unsafe_uri(ngx_http_request_t *r, ngx_str_t *uri,
args->data = p;
uri->len -= len;
return NGX_OK;
break;
}
if (ch == '\0') {
@ -1828,6 +1835,56 @@ ngx_http_parse_unsafe_uri(ngx_http_request_t *r, ngx_str_t *uri,
}
}
if (quoted) {
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"escaped URI: \"%V\"", uri);
src = uri->data;
dst = ngx_pnalloc(r->pool, uri->len);
if (dst == NULL) {
return NGX_ERROR;
}
uri->data = dst;
ngx_unescape_uri(&dst, &src, uri->len, 0);
uri->len = dst - uri->data;
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"unescaped URI: \"%V\"", uri);
len = uri->len;
p = uri->data;
if (p[0] == '.' && len > 1 && p[1] == '.'
&& (len == 2 || ngx_path_separator(p[2])))
{
goto unsafe;
}
for ( /* void */ ; len; len--) {
ch = *p++;
if (ch == '\0') {
goto unsafe;
}
if (ngx_path_separator(ch) && len > 2) {
/* detect "/../" and "/.." */
if (p[0] == '.' && p[1] == '.'
&& (len == 3 || ngx_path_separator(p[2])))
{
goto unsafe;
}
}
}
}
return NGX_OK;
unsafe: