From 72e86de68770c06cea23e6513e670704bba5f227 Mon Sep 17 00:00:00 2001 From: Kirill A. Korinskiy Date: Wed, 25 Mar 2009 20:11:48 +0300 Subject: [PATCH] Implement generic variables $urlencode_ and $urldecode_ for get urlencode/urldecode of value of variable. Cc: catap@catap.ru Raw value of arguments from request string can help for XSS. --- src/http/ngx_http_variables.c | 134 +++++++++++++++++++++++++++++++++++++++++ 1 files changed, 134 insertions(+), 0 deletions(-) diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c index 22f213cf6157ab5b99e481835acf9a394ef21919..035f6cc4687d20646d156d0ed58a303aef76b8d8 100644 --- a/src/http/ngx_http_variables.c +++ b/src/http/ngx_http_variables.c @@ -31,6 +31,10 @@ static ngx_int_t ngx_http_variable_cookie(ngx_http_request_t *r, static ngx_int_t ngx_http_variable_ssi(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); #endif +static ngx_int_t ngx_http_variable_urlencode(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_urldecode(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_variable_argument(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); @@ -530,6 +534,24 @@ ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name, ngx_uint_t key, } #endif + if (ngx_strncmp(name->data, "urlencode_", 10) == 0) { + + if (ngx_http_variable_urlencode(r, vv, (uintptr_t) name) == NGX_OK) { + return vv; + } + + return NULL; + } + + if (ngx_strncmp(name->data, "urldecode_", 10) == 0) { + + if (ngx_http_variable_urldecode(r, vv, (uintptr_t) name) == NGX_OK) { + return vv; + } + + return NULL; + } + if (ngx_strncmp(name->data, "arg_", 4) == 0) { if (ngx_http_variable_argument(r, vv, (uintptr_t) name) == NGX_OK) { @@ -831,6 +853,104 @@ ngx_http_variable_ssi(ngx_http_request_t *r, ngx_http_variable_value_t *v, static ngx_int_t +ngx_http_variable_urlencode(ngx_http_request_t *r, ngx_http_variable_value_t *v, + uintptr_t data) +{ + ngx_str_t *name = (ngx_str_t *) data; + + ngx_str_t sub_name; + + ngx_uint_t key; + + ngx_http_variable_value_t *vv; + + sub_name.len = name->len - (sizeof("urlencode_") - 1); + sub_name.data = name->data + sizeof("urlencode_") - 1; + + key = ngx_hash_strlow(sub_name.data, sub_name.data, sub_name.len); + + vv = ngx_http_get_variable(r, &sub_name, key, 0); + + if (vv == NULL || !vv->valid) { + return NGX_ERROR; + } + + if (vv->not_found) { + v->not_found = 1; + return NGX_OK; + } + + v->len = vv->len + + 2 * ngx_escape_uri(NULL, vv->data, vv->len, NGX_ESCAPE_ARGS); + + v->data = ngx_palloc(r->pool, v->len); + if (v->data == NULL) { + v->not_found = 1; + return NGX_OK; + } + + (void) ngx_escape_uri(v->data, vv->data, vv->len, NGX_ESCAPE_ARGS); + + v->valid = 1; + v->not_found = 0; + v->no_cacheable = vv->no_cacheable; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_variable_urldecode(ngx_http_request_t *r, ngx_http_variable_value_t *v, + uintptr_t data) +{ + ngx_str_t *name = (ngx_str_t *) data; + + u_char *dst, *src; + ngx_str_t sub_name; + ngx_uint_t key; + + ngx_http_variable_value_t *vv; + + sub_name.len = name->len - (sizeof("urldecode_") - 1); + sub_name.data = name->data + sizeof("urldecode_") - 1; + + key = ngx_hash_strlow(sub_name.data, sub_name.data, sub_name.len); + + vv = ngx_http_get_variable(r, &sub_name, key, 0); + + if (vv == NULL || !vv->valid) { + return NGX_ERROR; + } + + if (vv->not_found) { + v->not_found = 1; + return NGX_OK; + } + + v->len = vv->len; + + v->data = ngx_palloc(r->pool, v->len); + if (v->data == NULL) { + v->not_found = 1; + return NGX_OK; + } + + dst = v->data; + src = vv->data; + + ngx_unescape_uri(&dst, &src, vv->len, NGX_ESCAPE_ARGS); + + v->len = dst - v->data; + + v->valid = 1; + v->not_found = 0; + v->no_cacheable = vv->no_cacheable; + + return NGX_OK; +} + + +static ngx_int_t ngx_http_variable_argument(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { @@ -1789,6 +1909,20 @@ ngx_http_variables_init_vars(ngx_conf_t *cf) } #endif + if (ngx_strncmp(v[i].name.data, "urlencode_", 10) == 0) { + v[i].get_handler = ngx_http_variable_urlencode; + v[i].data = (uintptr_t) &v[i].name; + + continue; + } + + if (ngx_strncmp(v[i].name.data, "urldecode_", 10) == 0) { + v[i].get_handler = ngx_http_variable_urldecode; + v[i].data = (uintptr_t) &v[i].name; + + continue; + } + if (ngx_strncmp(v[i].name.data, "arg_", 4) == 0) { v[i].get_handler = ngx_http_variable_argument; v[i].data = (uintptr_t) &v[i].name; -- 1.6.2