From 4912d050eb6e3bf4e7f594c63ed353a7752de7a1 Mon Sep 17 00:00:00 2001 From: Maurits van der Schee Date: Fri, 7 Mar 2014 00:54:22 +0100 Subject: [PATCH 1/8] Added set commands for base64url and expired --- config | 4 +- src/ngx_http_set_base64url.c | 49 +++++++++++++++++++++++ src/ngx_http_set_base64url.h | 18 +++++++++ src/ngx_http_set_expired.c | 29 ++++++++++++++ src/ngx_http_set_expired.h | 7 ++++ src/ngx_http_set_misc_module.c | 49 +++++++++++++++++++++++ t/base64url.t | 71 ++++++++++++++++++++++++++++++++++ t/expired.t | 67 ++++++++++++++++++++++++++++++++ 8 files changed, 292 insertions(+), 2 deletions(-) create mode 100644 src/ngx_http_set_base64url.c create mode 100644 src/ngx_http_set_base64url.h create mode 100644 src/ngx_http_set_expired.c create mode 100644 src/ngx_http_set_expired.h create mode 100644 t/base64url.t create mode 100644 t/expired.t diff --git a/config b/config index 4f046aa..74313df 100755 --- a/config +++ b/config @@ -7,8 +7,8 @@ fi ngx_addon_name=ngx_http_set_misc_module HTTP_AUX_FILTER_MODULES="$HTTP_AUX_FILTER_MODULES ngx_http_set_misc_module" -NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/src/ngx_http_set_base32.c $ngx_addon_dir/src/ngx_http_set_default_value.c $ngx_addon_dir/src/ngx_http_set_hashed_upstream.c $ngx_addon_dir/src/ngx_http_set_quote_sql.c $ngx_addon_dir/src/ngx_http_set_quote_json.c $ngx_addon_dir/src/ngx_http_set_unescape_uri.c $ngx_addon_dir/src/ngx_http_set_misc_module.c $ngx_addon_dir/src/ngx_http_set_escape_uri.c $ngx_addon_dir/src/ngx_http_set_hash.c $ngx_addon_dir/src/ngx_http_set_local_today.c $ngx_addon_dir/src/ngx_http_set_hex.c $ngx_addon_dir/src/ngx_http_set_base64.c $ngx_addon_dir/src/ngx_http_set_random.c $ngx_addon_dir/src/ngx_http_set_secure_random.c $ngx_addon_dir/src/ngx_http_set_rotate.c" -NGX_ADDON_DEPS="$NGX_ADDON_DEPS $ngx_addon_dir/src/ddebug.h $ngx_addon_dir/src/ngx_http_set_default_value.h $ngx_addon_dir/src/ngx_http_set_hashed_upstream.h $ngx_addon_dir/src/ngx_http_set_quote_sql.h $ngx_addon_dir/src/ngx_http_set_quote_json.h $ngx_addon_dir/src/ngx_http_set_unescape_uri.h $ngx_addon_dir/src/ngx_http_set_escape_uri.h $ngx_addon_dir/src/ngx_http_set_hash.h $ngx_addon_dir/src/ngx_http_set_local_today.h $ngx_addon_dir/src/ngx_http_set_hex.h $ngx_addon_dir/src/ngx_http_set_base64.h $ngx_addon_dir/src/ngx_http_set_random.h $ngx_addon_dir/src/ngx_http_set_rotate.h $ngx_addon_dir/src/ngx_http_set_secure_random.h $ngx_addon_dir/src/ngx_http_set_misc_module.h" +NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/src/ngx_http_set_base32.c $ngx_addon_dir/src/ngx_http_set_default_value.c $ngx_addon_dir/src/ngx_http_set_hashed_upstream.c $ngx_addon_dir/src/ngx_http_set_quote_sql.c $ngx_addon_dir/src/ngx_http_set_quote_json.c $ngx_addon_dir/src/ngx_http_set_unescape_uri.c $ngx_addon_dir/src/ngx_http_set_misc_module.c $ngx_addon_dir/src/ngx_http_set_escape_uri.c $ngx_addon_dir/src/ngx_http_set_expired.c $ngx_addon_dir/src/ngx_http_set_hash.c $ngx_addon_dir/src/ngx_http_set_local_today.c $ngx_addon_dir/src/ngx_http_set_hex.c $ngx_addon_dir/src/ngx_http_set_base64.c $ngx_addon_dir/src/ngx_http_set_base64url.c $ngx_addon_dir/src/ngx_http_set_random.c $ngx_addon_dir/src/ngx_http_set_secure_random.c $ngx_addon_dir/src/ngx_http_set_rotate.c" +NGX_ADDON_DEPS="$NGX_ADDON_DEPS $ngx_addon_dir/src/ddebug.h $ngx_addon_dir/src/ngx_http_set_default_value.h $ngx_addon_dir/src/ngx_http_set_hashed_upstream.h $ngx_addon_dir/src/ngx_http_set_quote_sql.h $ngx_addon_dir/src/ngx_http_set_quote_json.h $ngx_addon_dir/src/ngx_http_set_unescape_uri.h $ngx_addon_dir/src/ngx_http_set_escape_uri.h $ngx_addon_dir/src/ngx_http_set_expired.h $ngx_addon_dir/src/ngx_http_set_hash.h $ngx_addon_dir/src/ngx_http_set_local_today.h $ngx_addon_dir/src/ngx_http_set_hex.h $ngx_addon_dir/src/ngx_http_set_base64.h $ngx_addon_dir/src/ngx_http_set_base64url.h $ngx_addon_dir/src/ngx_http_set_random.h $ngx_addon_dir/src/ngx_http_set_rotate.h $ngx_addon_dir/src/ngx_http_set_secure_random.h $ngx_addon_dir/src/ngx_http_set_misc_module.h" if [ $USE_OPENSSL = YES ]; then NGX_ADDON_DEPS="$NGX_ADDON_DEPS $ngx_addon_dir/src/ngx_http_set_hmac.h" diff --git a/src/ngx_http_set_base64url.c b/src/ngx_http_set_base64url.c new file mode 100644 index 0000000..3e42948 --- /dev/null +++ b/src/ngx_http_set_base64url.c @@ -0,0 +1,49 @@ +#ifndef DDEBUG +#define DDEBUG 0 +#endif +#include "ddebug.h" + +#include +#include "ngx_http_set_base64url.h" + +ngx_int_t +ngx_http_set_misc_set_decode_base64url(ngx_http_request_t *r, ngx_str_t *res, + ngx_http_variable_value_t *v) +{ + + ngx_str_t src; + + src.len = v->len; + src.data = v->data; + + res->len = ngx_base64url_decoded_length(v->len); + ndk_palloc_re(res->data, r->pool, res->len); + + if (ngx_decode_base64url(res, &src) != NGX_OK) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "set_decode_base64url: invalid value"); + return NGX_ERROR; + } + + return NGX_OK; +} + + +ngx_int_t +ngx_http_set_misc_set_encode_base64url(ngx_http_request_t *r, ngx_str_t *res, + ngx_http_variable_value_t *v) +{ + + ngx_str_t src; + + src.len = v->len; + src.data = v->data; + + res->len = ngx_base64url_encoded_length(v->len); + ndk_palloc_re(res->data, r->pool, res->len); + + ngx_encode_base64url(res, &src); + + return NGX_OK; +} + diff --git a/src/ngx_http_set_base64url.h b/src/ngx_http_set_base64url.h new file mode 100644 index 0000000..190df59 --- /dev/null +++ b/src/ngx_http_set_base64url.h @@ -0,0 +1,18 @@ +#include +#include +#include + +#ifndef ngx_base64url_decoded_length +#define ngx_base64url_decoded_length(len) ((((len + 3) / 4) * 3) - (len % 4 ? 4 - len % 4 : 0)) +#endif + +#ifndef ngx_base64url_encoded_length +#define ngx_base64url_encoded_length(len) ((((len + 2) / 3) * 4) + (len % 3 ? len % 3 + 1 : 0)) +#endif + +ngx_int_t ngx_http_set_misc_set_encode_base64url(ngx_http_request_t *r, + ngx_str_t *res, ngx_http_variable_value_t *v); + +ngx_int_t ngx_http_set_misc_set_decode_base64url(ngx_http_request_t *r, + ngx_str_t *res, ngx_http_variable_value_t *v); + diff --git a/src/ngx_http_set_expired.c b/src/ngx_http_set_expired.c new file mode 100644 index 0000000..0b8102c --- /dev/null +++ b/src/ngx_http_set_expired.c @@ -0,0 +1,29 @@ +#ifndef DDEBUG +#define DDEBUG 0 +#endif +#include "ddebug.h" + +#include + +#include "ngx_http_set_expired.h" + +ngx_int_t +ngx_http_set_misc_set_expired(ngx_http_request_t *r, ngx_str_t *res, + ngx_http_variable_value_t *v) +{ + ngx_http_variable_value_t *expires; + time_t now, deadline; + + expires = v; + dd("expires=%.*s",(int) expires->len, expires->data); + + now = ngx_time(); + deadline = ngx_atotm(expires->data, expires->len); + dd("now=%lld, deadline=%lld", (long long) now, (long long) deadline); + + res->len = 1; + ndk_palloc_re(res->data, r->pool, res->len); + res->data = (u_char*) ((deadline && now < deadline) ? "0" : "1"); + + return NGX_OK; + } diff --git a/src/ngx_http_set_expired.h b/src/ngx_http_set_expired.h new file mode 100644 index 0000000..11e4449 --- /dev/null +++ b/src/ngx_http_set_expired.h @@ -0,0 +1,7 @@ +#include +#include +#include + +ngx_int_t ngx_http_set_misc_set_expired(ngx_http_request_t *r, + ngx_str_t *res, ngx_http_variable_value_t *v); + diff --git a/src/ngx_http_set_misc_module.c b/src/ngx_http_set_misc_module.c index c57aac7..7bc26cf 100755 --- a/src/ngx_http_set_misc_module.c +++ b/src/ngx_http_set_misc_module.c @@ -12,10 +12,12 @@ #include "ngx_http_set_quote_sql.h" #include "ngx_http_set_quote_json.h" #include "ngx_http_set_escape_uri.h" +#include "ngx_http_set_expired.h" #include "ngx_http_set_local_today.h" #include "ngx_http_set_hash.h" #include "ngx_http_set_hex.h" #include "ngx_http_set_base64.h" +#include "ngx_http_set_base64url.h" #if NGX_OPENSSL #include "ngx_http_set_hmac.h" #endif @@ -47,6 +49,21 @@ static ndk_set_var_t ngx_http_set_misc_set_decode_base64_filter = { }; +static ndk_set_var_t ngx_http_set_misc_set_encode_base64url_filter = { + NDK_SET_VAR_VALUE, + (void *) ngx_http_set_misc_set_encode_base64url, + 1, + NULL +}; + +static ndk_set_var_t ngx_http_set_misc_set_decode_base64url_filter = { + NDK_SET_VAR_VALUE, + (void *) ngx_http_set_misc_set_decode_base64url, + 1, + NULL +}; + + static ndk_set_var_t ngx_http_set_misc_set_decode_hex_filter = { NDK_SET_VAR_VALUE, (void *) ngx_http_set_misc_set_decode_hex, @@ -70,6 +87,7 @@ static ndk_set_var_t ngx_http_set_misc_set_hmac_sha1_filter = { 2, NULL }; + #endif @@ -108,6 +126,12 @@ static ndk_set_var_t ngx_http_set_misc_escape_uri_filter = { NULL }; +static ndk_set_var_t ngx_http_set_misc_set_expired_filter = { + NDK_SET_VAR_VALUE, + (void *) ngx_http_set_misc_set_expired, + 1, + NULL +}; static ndk_set_var_t ngx_http_set_misc_decode_base32_filter = { NDK_SET_VAR_VALUE, @@ -214,6 +238,22 @@ static ngx_command_t ngx_http_set_misc_commands[] = { 0, &ngx_http_set_misc_set_decode_base64_filter }, + { ngx_string ("set_encode_base64url"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF + |NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE12, + ndk_set_var_value, + 0, + 0, + &ngx_http_set_misc_set_encode_base64url_filter + }, + { ngx_string ("set_decode_base64url"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF + |NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE12, + ndk_set_var_value, + 0, + 0, + &ngx_http_set_misc_set_decode_base64url_filter + }, { ngx_string ("set_decode_hex"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF |NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE12, @@ -279,6 +319,15 @@ static ngx_command_t ngx_http_set_misc_commands[] = { 0, &ngx_http_set_misc_escape_uri_filter }, + { + ngx_string ("set_expired"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF + |NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE12, + ndk_set_var_value, + 0, + 0, + &ngx_http_set_misc_set_expired_filter + }, { ngx_string ("set_quote_sql_str"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF diff --git a/t/base64url.t b/t/base64url.t new file mode 100644 index 0000000..c0e5908 --- /dev/null +++ b/t/base64url.t @@ -0,0 +1,71 @@ +# vi:filetype= + +use lib 'lib'; +use Test::Nginx::Socket; + +#repeat_each(3); + +plan tests => repeat_each() * 2 * blocks(); + +no_long_string(); + +run_tests(); + +#no_diff(); + +__DATA__ + +=== TEST 1: base64 encode binary +--- config + location /bar { + set_decode_hex $out "f8f9fafbfcfdfeff"; + set_encode_base64 $out; + echo $out; + } +--- request + GET /bar +--- response_body ++Pn6+/z9/v8= + + + +=== TEST 2: base64 decode binary +--- config + location /bar { + set_decode_base64 $out "+Pn6+/z9/v8="; + set_encode_hex $out; + echo $out; + } +--- request + GET /bar +--- response_body +f8f9fafbfcfdfeff + + + +=== TEST 3: base64url encode binary (url safe) +--- config + location /bar { + set_decode_hex $out "f8f9fafbfcfdfeff"; + set_encode_base64url $out; + echo $out; + } +--- request + GET /bar +--- response_body +-Pn6-_z9_v8 + + + +=== TEST 4: base64url decode binary (url safe) +--- config + location /bar { + set_decode_base64url $out "-Pn6-_z9_v8"; + set_encode_hex $out; + echo $out; + } +--- request + GET /bar +--- response_body +f8f9fafbfcfdfeff + diff --git a/t/expired.t b/t/expired.t new file mode 100644 index 0000000..585bf2c --- /dev/null +++ b/t/expired.t @@ -0,0 +1,67 @@ +# vi:filetype= + +use lib 'lib'; +use Test::Nginx::Socket; + +#repeat_each(3); + +plan tests => repeat_each() * 2 * blocks(); + +no_long_string(); + +run_tests(); + +#no_diff(); + +__DATA__ + +=== TEST 1: expired for 1970-01-01 00:00:00 +--- config + location /bar { + set_expired $expired 0; + echo $expired; + } +--- request + GET /bar +--- response_body +1 + + + +=== TEST 2: expired for 1970-01-01 00:00:01 +--- config + location /bar { + set_expired $expired 1; + echo $expired; + } +--- request + GET /bar +--- response_body +1 + + + +=== TEST 3: expired for 2020-01-01 00:00:00 +--- config + location /bar { + set_expired $expired 1577836800; + echo $expired; + } +--- request + GET /bar +--- response_body +0 + + + +=== TEST 4: expired for 9999-01-01 00:00:00 +--- config + location /bar { + set_expired $expired 253370764800; + echo $expired; + } +--- request + GET /bar +--- response_body +0 + From fd8b98877ad1c7005407899160b5f804075a8275 Mon Sep 17 00:00:00 2001 From: Maurits van der Schee Date: Mon, 10 Mar 2014 13:36:25 +0100 Subject: [PATCH 2/8] Adjustments made after review by agentzh --- src/ngx_http_set_base64url.c | 32 +++++++++++++++++++++++++++++--- src/ngx_http_set_base64url.h | 4 ++++ src/ngx_http_set_expired.h | 4 ++++ src/ngx_http_set_misc_module.c | 1 - 4 files changed, 37 insertions(+), 4 deletions(-) diff --git a/src/ngx_http_set_base64url.c b/src/ngx_http_set_base64url.c index 3e42948..d85d310 100644 --- a/src/ngx_http_set_base64url.c +++ b/src/ngx_http_set_base64url.c @@ -3,14 +3,14 @@ #endif #include "ddebug.h" -#include +#include #include "ngx_http_set_base64url.h" + ngx_int_t ngx_http_set_misc_set_decode_base64url(ngx_http_request_t *r, ngx_str_t *res, ngx_http_variable_value_t *v) { - ngx_str_t src; src.len = v->len; @@ -19,11 +19,26 @@ ngx_http_set_misc_set_decode_base64url(ngx_http_request_t *r, ngx_str_t *res, res->len = ngx_base64url_decoded_length(v->len); ndk_palloc_re(res->data, r->pool, res->len); +#if defined(nginx_version) && nginx_version >= 1005010 if (ngx_decode_base64url(res, &src) != NGX_OK) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "set_decode_base64url: invalid value"); return NGX_ERROR; } +#else + u_int i; + for (i=0;iconnection->log, 0, + "set_decode_base64url: invalid value"); + return NGX_ERROR; + } +#endif return NGX_OK; } @@ -33,7 +48,6 @@ ngx_int_t ngx_http_set_misc_set_encode_base64url(ngx_http_request_t *r, ngx_str_t *res, ngx_http_variable_value_t *v) { - ngx_str_t src; src.len = v->len; @@ -42,7 +56,19 @@ ngx_http_set_misc_set_encode_base64url(ngx_http_request_t *r, ngx_str_t *res, res->len = ngx_base64url_encoded_length(v->len); ndk_palloc_re(res->data, r->pool, res->len); +#if defined(nginx_version) && nginx_version >= 1005010 ngx_encode_base64url(res, &src); +#else + ngx_encode_base64(res, &src); + u_int i; + for (i=0;ilen;i++) { + switch (res->data[i]) { + case '+': res->data[i]='-'; break; + case '/': res->data[i]='_'; break; + case '=': res->len--; break; + } + } +#endif return NGX_OK; } diff --git a/src/ngx_http_set_base64url.h b/src/ngx_http_set_base64url.h index 190df59..e8aeb06 100644 --- a/src/ngx_http_set_base64url.h +++ b/src/ngx_http_set_base64url.h @@ -1,3 +1,6 @@ +#ifndef NGX_HTTP_SET_BASE64URL +#define NGX_HTTP_SET_BASE64URL + #include #include #include @@ -16,3 +19,4 @@ ngx_int_t ngx_http_set_misc_set_encode_base64url(ngx_http_request_t *r, ngx_int_t ngx_http_set_misc_set_decode_base64url(ngx_http_request_t *r, ngx_str_t *res, ngx_http_variable_value_t *v); +#endif /* NGX_HTTP_SET_BASE64URL */ diff --git a/src/ngx_http_set_expired.h b/src/ngx_http_set_expired.h index 11e4449..d6d67ca 100644 --- a/src/ngx_http_set_expired.h +++ b/src/ngx_http_set_expired.h @@ -1,3 +1,6 @@ +#ifndef NGX_HTTP_SET_EXPIRED +#define NGX_HTTP_SET_EXPIRED + #include #include #include @@ -5,3 +8,4 @@ ngx_int_t ngx_http_set_misc_set_expired(ngx_http_request_t *r, ngx_str_t *res, ngx_http_variable_value_t *v); +#endif /* NGX_HTTP_SET_EXPIRED */ diff --git a/src/ngx_http_set_misc_module.c b/src/ngx_http_set_misc_module.c index 7bc26cf..6faffd5 100755 --- a/src/ngx_http_set_misc_module.c +++ b/src/ngx_http_set_misc_module.c @@ -87,7 +87,6 @@ static ndk_set_var_t ngx_http_set_misc_set_hmac_sha1_filter = { 2, NULL }; - #endif From b51046bb9e6def7c55eb3ee8b1b3cfdaffe7178f Mon Sep 17 00:00:00 2001 From: Maurits van der Schee Date: Mon, 10 Mar 2014 23:32:21 +0100 Subject: [PATCH 3/8] More adjustments made after review by agentzh --- src/ngx_http_set_base64url.c | 16 +++++++++++----- src/ngx_http_set_expired.c | 7 +++++-- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/ngx_http_set_base64url.c b/src/ngx_http_set_base64url.c index d85d310..30bcf49 100644 --- a/src/ngx_http_set_base64url.c +++ b/src/ngx_http_set_base64url.c @@ -11,13 +11,17 @@ ngx_int_t ngx_http_set_misc_set_decode_base64url(ngx_http_request_t *r, ngx_str_t *res, ngx_http_variable_value_t *v) { - ngx_str_t src; + u_int i; + ngx_str_t src; src.len = v->len; src.data = v->data; res->len = ngx_base64url_decoded_length(v->len); - ndk_palloc_re(res->data, r->pool, res->len); + res->data = ngx_palloc(r->pool, res->len); + if (res->data == NULL) { + return NGX_ERROR; + } #if defined(nginx_version) && nginx_version >= 1005010 if (ngx_decode_base64url(res, &src) != NGX_OK) { @@ -26,7 +30,6 @@ ngx_http_set_misc_set_decode_base64url(ngx_http_request_t *r, ngx_str_t *res, return NGX_ERROR; } #else - u_int i; for (i=0;ilen; src.data = v->data; res->len = ngx_base64url_encoded_length(v->len); - ndk_palloc_re(res->data, r->pool, res->len); + res->data = ngx_palloc(r->pool, res->len); + if (res->data == NULL) { + return NGX_ERROR; + } #if defined(nginx_version) && nginx_version >= 1005010 ngx_encode_base64url(res, &src); #else ngx_encode_base64(res, &src); - u_int i; for (i=0;ilen;i++) { switch (res->data[i]) { case '+': res->data[i]='-'; break; diff --git a/src/ngx_http_set_expired.c b/src/ngx_http_set_expired.c index 0b8102c..17db8a9 100644 --- a/src/ngx_http_set_expired.c +++ b/src/ngx_http_set_expired.c @@ -22,8 +22,11 @@ ngx_http_set_misc_set_expired(ngx_http_request_t *r, ngx_str_t *res, dd("now=%lld, deadline=%lld", (long long) now, (long long) deadline); res->len = 1; - ndk_palloc_re(res->data, r->pool, res->len); - res->data = (u_char*) ((deadline && now < deadline) ? "0" : "1"); + res->data = ngx_palloc(r->pool, res->len); + if (res->data == NULL) { + return NGX_ERROR; + } + res->data[0] = (u_char) ((deadline && now < deadline) ? '0' : '1'); return NGX_OK; } From 29b18d23e6abf2be4f4ee72d10c7bb24e62e3b43 Mon Sep 17 00:00:00 2001 From: Maurits van der Schee Date: Tue, 11 Mar 2014 01:13:33 +0100 Subject: [PATCH 4/8] Updated documentation as requested. --- README.markdown | 83 ++++++++++++++++++++++++++++++++++++++ doc/HttpSetMiscModule.wiki | 71 ++++++++++++++++++++++++++++++++ 2 files changed, 154 insertions(+) diff --git a/README.markdown b/README.markdown index 5cddd89..721b790 100644 --- a/README.markdown +++ b/README.markdown @@ -29,6 +29,8 @@ Table of Contents * [set_decode_base32](#set_decode_base32) * [set_encode_base64](#set_encode_base64) * [set_decode_base64](#set_decode_base64) + * [set_encode_base64url](#set_encode_base64url) + * [set_decode_base64url](#set_decode_base64url) * [set_encode_hex](#set_encode_hex) * [set_decode_hex](#set_decode_hex) * [set_sha1](#set_sha1) @@ -38,6 +40,7 @@ Table of Contents * [set_secure_random_alphanum](#set_secure_random_alphanum) * [set_secure_random_lcalpha](#set_secure_random_lcalpha) * [set_rotate](#set_rotate) + * [set_expired](#set_expired) * [set_local_today](#set_local_today) * [set_formatted_gmt_time](#set_formatted_gmt_time) * [set_formatted_local_time](#set_formatted_local_time) @@ -136,6 +139,15 @@ location /base64 { # $b == 'abcde' } +location /base64url { + set $a 'abcde'; + set_encode_base64url $a; + set_decode_base64url $b $a; + + # now $a == 'YWJjZGU' and + # $b == 'abcde' +} + location /hex { set $a 'abcde'; set_encode_hex $a; @@ -177,6 +189,24 @@ location /signature { echo $signature; } +# GET /secure?e=1394493753&s=HkADYytcoQQzqbjQX33k_ZBB_DQ +# returns 403 when signature on expire time is not correct OR +# when expire time is passed. See: HttpSecureLinkModule. +# This example has a valid signed expiry at 2030-01-01. Output: +# "OK" +location /secure { + set_hmac_sha1 $signature 'secret-key' $arg_e; + set_encode_base64url $signature; + if ($signature != $arg_s) { + return 403; + } + set_expired $expired $arg_e; + if ($expired) { + return 403; + } + echo "OK"; +} + location = /rand { set $from 3; set $to 15; @@ -627,6 +657,42 @@ Similar to the [set_encode_base64](#set_encode_base64) directive, but does exact [Back to TOC](#table-of-contents) +set_encode_base64url +-------------------- +**syntax:** *set_encode_base64url $dst <src>* + +**syntax:** *set_encode_base64url $dst* + +**default:** *no* + +**context:** *location, location if* + +**phase:** *rewrite* + +**category:** *ndk_set_var_value* + +Similar to the [set_encode_base64](#set_encode_base64) directive, but uses URL safe base64 variant, '+' becomes '-', '/' becomes '_' and there is no padding with '=' characters. + +[Back to TOC](#table-of-contents) + +set_decode_base64url +-------------------- +**syntax:** *set_decode_base64url $dst <src>* + +**syntax:** *set_decode_base64url $dst* + +**default:** *no* + +**context:** *location, location if* + +**phase:** *rewrite* + +**category:** *ndk_set_var_value* + +Similar to the [set_encode_base64url](#set_encode_base64url) directive, but does exactly the the opposite operation, .i.e, decoding a base64url digest into its original form. + +[Back to TOC](#table-of-contents) + set_encode_hex -------------- **syntax:** *set_encode_hex $dst <src>* @@ -1010,6 +1076,23 @@ This directive was first introduced in the `v0.22rc7` release. [Back to TOC](#table-of-contents) +set_expired +----------- +**syntax:** *set_expired $dst <timestamp>* + +**default:** *no* + +**context:** *location, location if* + +**phase:** *rewrite* + +Sets `$dst` to either `1` or `0`, dependent on whether or not the +timestamp as defined in `timestamp` (seconds since 1970-01-01 00:00:00) is or is not in the past. + +Behind the scene, this directive utilizes the `ngx_time` API in the Nginx core, so usually no syscall is involved due to the time caching mechanism in the Nginx core. + +[Back to TOC](#table-of-contents) + set_local_today --------------- **syntax:** *set_local_today $dst* diff --git a/doc/HttpSetMiscModule.wiki b/doc/HttpSetMiscModule.wiki index 59a5f76..8c68cd1 100644 --- a/doc/HttpSetMiscModule.wiki +++ b/doc/HttpSetMiscModule.wiki @@ -84,6 +84,15 @@ This document describes ngx_set_misc [https://github.com/agentzh/set-misc-nginx- # $b == 'abcde' } + location /base64url { + set $a 'abcde'; + set_encode_base64url $a; + set_decode_base64url $b $a; + + # now $a == 'YWJjZGU' and + # $b == 'abcde' + } + location /hex { set $a 'abcde'; set_encode_hex $a; @@ -125,6 +134,24 @@ This document describes ngx_set_misc [https://github.com/agentzh/set-misc-nginx- echo $signature; } + # GET /secure?e=1394493753&s=HkADYytcoQQzqbjQX33k_ZBB_DQ + # returns 403 when signature on expire time is not correct OR + # when expire time is passed. See: HttpSecureLinkModule. + # This example has a valid signed expiry at 2030-01-01. Output: + # "OK" + location /secure { + set_hmac_sha1 $signature 'secret-key' $arg_e; + set_encode_base64url $signature; + if ($signature != $arg_s) { + return 403; + } + set_expired $expired $arg_e; + if ($expired) { + return 403; + } + echo "OK"; + } + location = /rand { set $from 3; set $to 15; @@ -518,6 +545,36 @@ This directive can be invoked by [[HttpLuaModule]]'s [[HttpLuaModule#ndk.set_var Similar to the [[#set_encode_base64|set_encode_base64]] directive, but does exactly the the opposite operation, .i.e, decoding a base64 digest into its original form. +== set_encode_base64url == +'''syntax:''' ''set_encode_base64url $dst '' + +'''syntax:''' ''set_encode_base64url $dst'' + +'''default:''' ''no'' + +'''context:''' ''location, location if'' + +'''phase:''' ''rewrite'' + +'''category:''' ''ndk_set_var_value'' + +Similar to the [[#set_encode_base64|set_encode_base64]] directive, but uses URL safe base64 variant, '+' becomes '-', '/' becomes '_' and there is no padding with '=' characters. + +== set_decode_base64url == +'''syntax:''' ''set_decode_base64url $dst '' + +'''syntax:''' ''set_decode_base64url $dst'' + +'''default:''' ''no'' + +'''context:''' ''location, location if'' + +'''phase:''' ''rewrite'' + +'''category:''' ''ndk_set_var_value'' + +Similar to the [[#set_encode_base64url|set_encode_base64url]] directive, but does exactly the the opposite operation, .i.e, decoding a base64url digest into its original form. + == set_encode_hex == '''syntax:''' ''set_encode_hex $dst '' @@ -862,6 +919,20 @@ And accessing /rotate will also output integer sequence 0, 1, 2, 3, This directive was first introduced in the v0.22rc7 release. +== set_expired == +'''syntax:''' ''set_expired $dst '' + +'''default:''' ''no'' + +'''context:''' ''location, location if'' + +'''phase:''' ''rewrite'' + +Sets $dst to either 1 or 0, dependent on whether or not the +timestamp as defined in timestamp (seconds since 1970-01-01 00:00:00) is or is not in the past. + +Behind the scene, this directive utilizes the ngx_time API in the Nginx core, so usually no syscall is involved due to the time caching mechanism in the Nginx core. + == set_local_today == '''syntax:''' ''set_local_today $dst'' From 02e12a363d8ec93b65d07fb147f798d690e683ad Mon Sep 17 00:00:00 2001 From: Maurits van der Schee Date: Tue, 11 Mar 2014 01:40:50 +0100 Subject: [PATCH 5/8] Updated the plain text README accordingly --- README | 167 +++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 156 insertions(+), 11 deletions(-) diff --git a/README b/README index 18adfc5..b490b45 100644 --- a/README +++ b/README @@ -6,9 +6,9 @@ Name installation instructions. Version - This document describes ngx_set_misc v0.22 - () released on 8 - September 2013. + This document describes ngx_set_misc v0.24 + () released on 10 + January 2014. Synopsis location /foo { @@ -84,6 +84,15 @@ Synopsis # $b == 'abcde' } + location /base64url { + set $a 'abcde'; + set_encode_base64url $a; + set_decode_base64url $b $a; + + # now $a == 'YWJjZGU' and + # $b == 'abcde' + } + location /hex { set $a 'abcde'; set_encode_hex $a; @@ -125,6 +134,24 @@ Synopsis echo $signature; } + # GET /secure?e=1394493753&s=HkADYytcoQQzqbjQX33k_ZBB_DQ + # returns 403 when signature on expire time is not correct OR + # when expire time is passed. See: HttpSecureLinkModule. + # This example has a valid signed expiry at 2030-01-01. Output: + # "OK" + location /secure { + set_hmac_sha1 $signature 'secret-key' $arg_e; + set_encode_base64url $signature; + if ($signature != $arg_s) { + return 403; + } + set_expired $expired $arg_e; + if ($expired) { + return 403; + } + echo "OK"; + } + location = /rand { set $from 3; set $to 15; @@ -545,6 +572,40 @@ Directives opposite operation, .i.e, decoding a base64 digest into its original form. + set_encode_base64url + syntax: *set_encode_base64url $dst * + + syntax: *set_encode_base64url $dst* + + default: *no* + + context: *location, location if* + + phase: *rewrite* + + category: *ndk_set_var_value* + + Similar to the set_encode_base64 directive, but uses URL safe base64 + variant, '+' becomes '-', '/' becomes '_' and there is no padding with + '=' characters. + + set_decode_base64url + syntax: *set_decode_base64url $dst * + + syntax: *set_decode_base64url $dst* + + default: *no* + + context: *location, location if* + + phase: *rewrite* + + category: *ndk_set_var_value* + + Similar to the set_encode_base64url directive, but does exactly the the + opposite operation, .i.e, decoding a base64url digest into its original + form. + set_encode_hex syntax: *set_encode_hex $dst * @@ -824,7 +885,7 @@ Directives then request "GET /test" will output a string like "ivVVRP2DGaAqDmdf3Rv4ZDJ7k0gOfASz". - This function depends on the presence of the "/dev/urandom" device, + This functionality depends on the presence of the "/dev/urandom" device, available on most UNIX-like systems. See also set_secure_random_lcalpha and set_random. @@ -856,7 +917,7 @@ Directives then request "GET /test" will output a string like "kcuxcddktffsippuekhshdaclaquiusj". - This function depends on the presence of the "/dev/urandom" device, + This functionality depends on the presence of the "/dev/urandom" device, available on most UNIX-like systems. This directive was first introduced in the "v0.22rc8" release. @@ -914,6 +975,23 @@ Directives This directive was first introduced in the "v0.22rc7" release. + set_expired + syntax: *set_expired $dst * + + default: *no* + + context: *location, location if* + + phase: *rewrite* + + Sets $dst to either 1 or 0, dependent on whether or not the timestamp as + defined in "timestamp" (seconds since 1970-01-01 00:00:00) is or is not + in the past. + + Behind the scene, this directive utilizes the "ngx_time" API in the + Nginx core, so usually no syscall is involved due to the time caching + mechanism in the Nginx core. + set_local_today syntax: *set_local_today $dst* @@ -943,6 +1021,70 @@ Directives Nginx core, so usually no syscall is involved due to the time caching mechanism in the Nginx core. + set_formatted_gmt_time + syntax: *set_formatted_gmt_time $res <time-format>* + + default: *no* + + context: *location, location if* + + phase: *rewrite* + + Set a formatted GMT time to variable $res (as the first argument) using + the format string in the second argument. + + All the conversion specification notations in the standard C function + "strftime" are supported, like %Y (for 4-digit years) and %M (for + minutes in decimal). See http://linux.die.net/man/3/strftime for a + complete list of conversion specification symbols. + + Below is an example: + + location = /t { + set_formatted_gmt_time $timestr "%a %b %e %H:%M:%S %Y GMT"; + echo $timestr; + } + + Accessing "/t" yields the output + + Fri Dec 13 15:34:37 2013 GMT + + This directive was first added in the 0.23 release. + + See also set_formatted_local_time. + + set_formatted_local_time + syntax: *set_formatted_local_time $res <time-format>* + + default: *no* + + context: *location, location if* + + phase: *rewrite* + + Set a formatted local time to variable $res (as the first argument) + using the format string in the second argument. + + All the conversion specification notations in the standard C function + "strftime" are supported, like %Y (for 4-digit years) and %M (for + minutes in decimal). See http://linux.die.net/man/3/strftime for a + complete list of conversion specification symbols. + + Below is an example: + + location = /t { + set_formatted_local_time $timestr "%a %b %e %H:%M:%S %Y %Z"; + echo $timestr; + } + + Accessing "/t" yields the output + + Fri Dec 13 15:42:15 2013 PST + + This directive was first added in the 0.23 release. + + See also set_formatted_gmt_time. + Caveats Do not use $arg_PARAMETER, $cookie_COOKIE, $http_HEADER or other special variables defined in the Nginx core module as the target variable in @@ -959,12 +1101,12 @@ Installation below: Grab the nginx source code from nginx.org (), for - example, the version 1.4.2 (see nginx compatibility), and then build the + example, the version 1.5.8 (see nginx compatibility), and then build the source with this module: - wget 'http://nginx.org/download/nginx-1.4.2.tar.gz' - tar -xzvf nginx-1.4.2.tar.gz - cd nginx-1.4.2/ + wget 'http://nginx.org/download/nginx-1.5.8.tar.gz' + tar -xzvf nginx-1.5.8.tar.gz + cd nginx-1.5.8/ # Here we assume you would install you nginx under /opt/nginx/. ./configure --prefix=/opt/nginx \ @@ -987,7 +1129,9 @@ Installation Compatibility The following versions of Nginx should work with this module: - * 1.4.x (last tested: 1.4.2) + * 1.5.x (last tested: 1.5.8) + + * 1.4.x (last tested: 1.4.4) * 1.2.x (last tested: 1.2.9) @@ -1057,7 +1201,8 @@ Author is encouraged to improve this page as well. Copyright & License - Copyright (C) 2009-2013, Yichun Zhang (章亦春) . + Copyright (C) 2009-2014, Yichun Zhang (章亦春) , + CloudFlare Inc. This module is licensed under the terms of the BSD license. From 70c2e2a5465000df2c742dd595ecec0bc4e768e2 Mon Sep 17 00:00:00 2001 From: Maurits van der Schee Date: Thu, 13 Mar 2014 15:15:22 +0100 Subject: [PATCH 6/8] Added ip_matches directive and documentation --- README | 45 +++++++++++++++--- README.markdown | 47 ++++++++++++++++--- config | 4 +- doc/HttpSetMiscModule.wiki | 44 +++++++++++++++--- src/ngx_http_set_ip_matches.c | 85 ++++++++++++++++++++++++++++++++++ src/ngx_http_set_ip_matches.h | 11 +++++ src/ngx_http_set_misc_module.c | 17 ++++++- t/ip_matches.t | 45 ++++++++++++++++++ 8 files changed, 276 insertions(+), 22 deletions(-) create mode 100644 src/ngx_http_set_ip_matches.c create mode 100644 src/ngx_http_set_ip_matches.h create mode 100644 t/ip_matches.t diff --git a/README b/README index b490b45..6e5a9c3 100644 --- a/README +++ b/README @@ -134,13 +134,13 @@ Synopsis echo $signature; } - # GET /secure?e=1394493753&s=HkADYytcoQQzqbjQX33k_ZBB_DQ - # returns 403 when signature on expire time is not correct OR - # when expire time is passed. See: HttpSecureLinkModule. - # This example has a valid signed expiry at 2030-01-01. Output: - # "OK" + # GET /secure?e=1893456000&n=MC4wLjAuMC8w&s=CyTCGzrXeRqq9_MvY1hm6ZvqwmY + # returns 403 when signature on the arguments is not correct OR + # when expire time is passed or network does not match. + # It is an alternative to the HttpSecureLinkModule in Nginx. + # This example has expiry "2030-01-01" and network "0.0.0.0/0". location /secure { - set_hmac_sha1 $signature 'secret-key' $arg_e; + set_hmac_sha1 $signature 'secret-key' "$arg_e&$arg_n"; set_encode_base64url $signature; if ($signature != $arg_s) { return 403; @@ -149,6 +149,11 @@ Synopsis if ($expired) { return 403; } + set_decode_base64url $network $arg_n; + set_ip_matches $ip_matches $network $remote_ip; + if ($ip_matches = 0) { + return 403; + } echo "OK"; } @@ -821,6 +826,34 @@ Directives (usually by passing the "--with-http_ssl_module" option to the "./configure" script). + set_ip_matches + syntax: *set_ip_matches $dst * + + default: *no* + + context: *location, location if* + + phase: *rewrite* + + Sets $dst to either 1 or 0, dependent on whether or not the IP address + (either IPv4 or IPv6) as defined in "ip" matches the network defined in + "network". The network can be specified as a single IP address or using + CIDR notation. + + For instance, + + location /test { + set_ip_matches $r1 10.0.0.0/8 10.0.2.101; + set_ip_matches $r2 10.0.0.0/24 10.0.2.101; + echo "r1=$r1, r2=$r2"; + } + + then request "GET /test" will output "r1=1, r2=0". + + This directive looks a lot like the "allow" directive, but it executes + in the "rewrite" phase and allows for custom handling of matches and + mismatches. + set_random syntax: *set_random $res * diff --git a/README.markdown b/README.markdown index 721b790..3447d36 100644 --- a/README.markdown +++ b/README.markdown @@ -36,6 +36,7 @@ Table of Contents * [set_sha1](#set_sha1) * [set_md5](#set_md5) * [set_hmac_sha1](#set_hmac_sha1) + * [set_ip_matches](#set_ip_matches) * [set_random](#set_random) * [set_secure_random_alphanum](#set_secure_random_alphanum) * [set_secure_random_lcalpha](#set_secure_random_lcalpha) @@ -189,13 +190,13 @@ location /signature { echo $signature; } -# GET /secure?e=1394493753&s=HkADYytcoQQzqbjQX33k_ZBB_DQ -# returns 403 when signature on expire time is not correct OR -# when expire time is passed. See: HttpSecureLinkModule. -# This example has a valid signed expiry at 2030-01-01. Output: -# "OK" +# GET /secure?e=1893456000&n=MC4wLjAuMC8w&s=CyTCGzrXeRqq9_MvY1hm6ZvqwmY +# returns 403 when signature on the arguments is not correct OR +# when expire time is passed or network does not match. +# It is an alternative to the HttpSecureLinkModule in Nginx. +# This example has expiry "2030-01-01" and network "0.0.0.0/0". location /secure { - set_hmac_sha1 $signature 'secret-key' $arg_e; + set_hmac_sha1 $signature 'secret-key' "$arg_e&$arg_n"; set_encode_base64url $signature; if ($signature != $arg_s) { return 403; @@ -204,6 +205,11 @@ location /secure { if ($expired) { return 403; } + set_decode_base64url $network $arg_n; + set_ip_matches $ip_matches $network $remote_ip; + if ($ip_matches = 0) { + return 403; + } echo "OK"; } @@ -912,6 +918,35 @@ This directive requires the OpenSSL library enabled in your Nignx build (usually [Back to TOC](#table-of-contents) +set_ip_matches +-------------- +**syntax:** *set_ip_matches $dst <network> <ip>* + +**default:** *no* + +**context:** *location, location if* + +**phase:** *rewrite* + +Sets `$dst` to either `1` or `0`, dependent on whether or not the IP address (either IPv4 or IPv6) as defined in `ip` matches the network defined in `network`. The network can be specified as a single IP address or using CIDR notation. + +For instance, + +```nginx + +location /test { + set_ip_matches $r1 10.0.0.0/8 10.0.2.101; + set_ip_matches $r2 10.0.0.0/24 10.0.2.101; + echo "r1=$r1, r2=$r2"; +} +``` + +then request `GET /test` will output `r1=1, r2=0`. + +This directive looks a lot like the "allow" directive, but it executes in the "rewrite" phase and allows for custom handling of matches and mismatches. + +[Back to TOC](#table-of-contents) + set_random ---------- **syntax:** *set_random $res <from> <to>* diff --git a/config b/config index 74313df..26efd92 100755 --- a/config +++ b/config @@ -7,8 +7,8 @@ fi ngx_addon_name=ngx_http_set_misc_module HTTP_AUX_FILTER_MODULES="$HTTP_AUX_FILTER_MODULES ngx_http_set_misc_module" -NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/src/ngx_http_set_base32.c $ngx_addon_dir/src/ngx_http_set_default_value.c $ngx_addon_dir/src/ngx_http_set_hashed_upstream.c $ngx_addon_dir/src/ngx_http_set_quote_sql.c $ngx_addon_dir/src/ngx_http_set_quote_json.c $ngx_addon_dir/src/ngx_http_set_unescape_uri.c $ngx_addon_dir/src/ngx_http_set_misc_module.c $ngx_addon_dir/src/ngx_http_set_escape_uri.c $ngx_addon_dir/src/ngx_http_set_expired.c $ngx_addon_dir/src/ngx_http_set_hash.c $ngx_addon_dir/src/ngx_http_set_local_today.c $ngx_addon_dir/src/ngx_http_set_hex.c $ngx_addon_dir/src/ngx_http_set_base64.c $ngx_addon_dir/src/ngx_http_set_base64url.c $ngx_addon_dir/src/ngx_http_set_random.c $ngx_addon_dir/src/ngx_http_set_secure_random.c $ngx_addon_dir/src/ngx_http_set_rotate.c" -NGX_ADDON_DEPS="$NGX_ADDON_DEPS $ngx_addon_dir/src/ddebug.h $ngx_addon_dir/src/ngx_http_set_default_value.h $ngx_addon_dir/src/ngx_http_set_hashed_upstream.h $ngx_addon_dir/src/ngx_http_set_quote_sql.h $ngx_addon_dir/src/ngx_http_set_quote_json.h $ngx_addon_dir/src/ngx_http_set_unescape_uri.h $ngx_addon_dir/src/ngx_http_set_escape_uri.h $ngx_addon_dir/src/ngx_http_set_expired.h $ngx_addon_dir/src/ngx_http_set_hash.h $ngx_addon_dir/src/ngx_http_set_local_today.h $ngx_addon_dir/src/ngx_http_set_hex.h $ngx_addon_dir/src/ngx_http_set_base64.h $ngx_addon_dir/src/ngx_http_set_base64url.h $ngx_addon_dir/src/ngx_http_set_random.h $ngx_addon_dir/src/ngx_http_set_rotate.h $ngx_addon_dir/src/ngx_http_set_secure_random.h $ngx_addon_dir/src/ngx_http_set_misc_module.h" +NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/src/ngx_http_set_base32.c $ngx_addon_dir/src/ngx_http_set_default_value.c $ngx_addon_dir/src/ngx_http_set_hashed_upstream.c $ngx_addon_dir/src/ngx_http_set_quote_sql.c $ngx_addon_dir/src/ngx_http_set_quote_json.c $ngx_addon_dir/src/ngx_http_set_unescape_uri.c $ngx_addon_dir/src/ngx_http_set_misc_module.c $ngx_addon_dir/src/ngx_http_set_escape_uri.c $ngx_addon_dir/src/ngx_http_set_expired.c $ngx_addon_dir/src/ngx_http_set_hash.c $ngx_addon_dir/src/ngx_http_set_local_today.c $ngx_addon_dir/src/ngx_http_set_hex.c $ngx_addon_dir/src/ngx_http_set_ip_matches.c $ngx_addon_dir/src/ngx_http_set_base64.c $ngx_addon_dir/src/ngx_http_set_base64url.c $ngx_addon_dir/src/ngx_http_set_random.c $ngx_addon_dir/src/ngx_http_set_secure_random.c $ngx_addon_dir/src/ngx_http_set_rotate.c" +NGX_ADDON_DEPS="$NGX_ADDON_DEPS $ngx_addon_dir/src/ddebug.h $ngx_addon_dir/src/ngx_http_set_default_value.h $ngx_addon_dir/src/ngx_http_set_hashed_upstream.h $ngx_addon_dir/src/ngx_http_set_quote_sql.h $ngx_addon_dir/src/ngx_http_set_quote_json.h $ngx_addon_dir/src/ngx_http_set_unescape_uri.h $ngx_addon_dir/src/ngx_http_set_escape_uri.h $ngx_addon_dir/src/ngx_http_set_expired.h $ngx_addon_dir/src/ngx_http_set_hash.h $ngx_addon_dir/src/ngx_http_set_local_today.h $ngx_addon_dir/src/ngx_http_set_hex.h $ngx_addon_dir/src/ngx_http_set_ip_matches.h $ngx_addon_dir/src/ngx_http_set_base64.h $ngx_addon_dir/src/ngx_http_set_base64url.h $ngx_addon_dir/src/ngx_http_set_random.h $ngx_addon_dir/src/ngx_http_set_rotate.h $ngx_addon_dir/src/ngx_http_set_secure_random.h $ngx_addon_dir/src/ngx_http_set_misc_module.h" if [ $USE_OPENSSL = YES ]; then NGX_ADDON_DEPS="$NGX_ADDON_DEPS $ngx_addon_dir/src/ngx_http_set_hmac.h" diff --git a/doc/HttpSetMiscModule.wiki b/doc/HttpSetMiscModule.wiki index 8c68cd1..8d1617e 100644 --- a/doc/HttpSetMiscModule.wiki +++ b/doc/HttpSetMiscModule.wiki @@ -134,13 +134,13 @@ This document describes ngx_set_misc [https://github.com/agentzh/set-misc-nginx- echo $signature; } - # GET /secure?e=1394493753&s=HkADYytcoQQzqbjQX33k_ZBB_DQ - # returns 403 when signature on expire time is not correct OR - # when expire time is passed. See: HttpSecureLinkModule. - # This example has a valid signed expiry at 2030-01-01. Output: - # "OK" + # GET /secure?e=1893456000&n=MC4wLjAuMC8w&s=CyTCGzrXeRqq9_MvY1hm6ZvqwmY + # returns 403 when signature on the arguments is not correct OR + # when expire time is passed or network does not match. + # It is an alternative to the HttpSecureLinkModule in Nginx. + # This example has expiry "2030-01-01" and network "0.0.0.0/0". location /secure { - set_hmac_sha1 $signature 'secret-key' $arg_e; + set_hmac_sha1 $signature 'secret-key' "$arg_e&$arg_n"; set_encode_base64url $signature; if ($signature != $arg_s) { return 403; @@ -149,9 +149,14 @@ This document describes ngx_set_misc [https://github.com/agentzh/set-misc-nginx- if ($expired) { return 403; } + set_decode_base64url $network $arg_n; + set_ip_matches $ip_matches $network $remote_ip; + if ($ip_matches = 0) { + return 403; + } echo "OK"; } - + location = /rand { set $from 3; set $to 15; @@ -772,6 +777,31 @@ Please note that we're using [[HttpEchoModule]]'s [[HttpEchoModule#echo|echo dir This directive requires the OpenSSL library enabled in your Nignx build (usually by passing the --with-http_ssl_module option to the ./configure script). +== set_ip_matches == +'''syntax:''' ''set_ip_matches $dst '' + +'''default:''' ''no'' + +'''context:''' ''location, location if'' + +'''phase:''' ''rewrite'' + +Sets $dst to either 1 or 0, dependent on whether or not the IP address (either IPv4 or IPv6) as defined in ip matches the network defined in network. The network can be specified as a single IP address or using CIDR notation. + +For instance, + + + location /test { + set_ip_matches $r1 10.0.0.0/8 10.0.2.101; + set_ip_matches $r2 10.0.0.0/24 10.0.2.101; + echo "r1=$r1, r2=$r2"; + } + + +then request GET /test will output r1=1, r2=0. + +This directive looks a lot like the "allow" directive, but it executes in the "rewrite" phase and allows for custom handling of matches and mismatches. + == set_random == '''syntax:''' ''set_random $res '' diff --git a/src/ngx_http_set_ip_matches.c b/src/ngx_http_set_ip_matches.c new file mode 100644 index 0000000..dd257b6 --- /dev/null +++ b/src/ngx_http_set_ip_matches.c @@ -0,0 +1,85 @@ +#ifndef DDEBUG +#define DDEBUG 1 +#endif +#include "ddebug.h" + +#include + +#include "ngx_http_set_ip_matches.h" + +ngx_int_t +ngx_http_set_misc_set_ip_matches(ngx_http_request_t *r, ngx_str_t *res, + ngx_http_variable_value_t *v) +{ + ngx_http_variable_value_t *network_var, *ip_var; + ngx_str_t network_str, ip_str; + ngx_cidr_t network, ip; + size_t len; + u_char *ip_addr, *ip_mask, *network_addr, *network_mask, result; + u_int i; + + network_var = v; + ip_var = v+1; + + network_str.len = network_var->len; + network_str.data = network_var->data; + + ip_str.len = ip_var->len; + ip_str.data = ip_var->data; + + if (ngx_ptocidr(&network_str, &network) == NGX_ERROR) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "network: invalid address or cidr"); + return NGX_ERROR; + } + + if (ngx_ptocidr(&ip_str, &ip) == NGX_ERROR) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "ip: invalid address"); + return NGX_ERROR; + } + + if (network.family != ip.family) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "IPv4 and IPv6 cannot be mixed"); + return NGX_ERROR; + } + + switch (ip.family) { + case AF_INET: + len = 4; + ip_addr = (u_char *) &ip.u.in.addr; + ip_mask = (u_char *) &ip.u.in.mask; + network_addr = (u_char *) &network.u.in.addr; + network_mask = (u_char *) &network.u.in.mask; + break; + case AF_INET6: + len = 16; + ip_addr = ip.u.in6.addr.__in6_u.__u6_addr8; + ip_mask = ip.u.in6.mask.__in6_u.__u6_addr8; + network_addr = network.u.in6.addr.__in6_u.__u6_addr8; + network_mask = network.u.in6.mask.__in6_u.__u6_addr8; + break; + default: + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "invalid address family"); + return NGX_ERROR; + } + + for (i=0;iconnection->log, 0, "ip: cidr notation not allowed"); + return NGX_ERROR; + } + } + + result = 0; + for (i=0;ilen = 1; + res->data = ngx_palloc(r->pool, res->len); + if (res->data == NULL) { + return NGX_ERROR; + } + res->data[0] = result==0 ? '1' : '0'; + + return NGX_OK; + } diff --git a/src/ngx_http_set_ip_matches.h b/src/ngx_http_set_ip_matches.h new file mode 100644 index 0000000..987f19a --- /dev/null +++ b/src/ngx_http_set_ip_matches.h @@ -0,0 +1,11 @@ +#ifndef NGX_HTTP_SET_IP_MATCHES +#define NGX_HTTP_SET_IP_MATCHES + +#include +#include +#include + +ngx_int_t ngx_http_set_misc_set_ip_matches(ngx_http_request_t *r, + ngx_str_t *res, ngx_http_variable_value_t *v); + +#endif /* NGX_HTTP_SET_IP_MATCHES */ diff --git a/src/ngx_http_set_misc_module.c b/src/ngx_http_set_misc_module.c index 6faffd5..35d6d07 100755 --- a/src/ngx_http_set_misc_module.c +++ b/src/ngx_http_set_misc_module.c @@ -18,6 +18,7 @@ #include "ngx_http_set_hex.h" #include "ngx_http_set_base64.h" #include "ngx_http_set_base64url.h" +#include "ngx_http_set_ip_matches.h" #if NGX_OPENSSL #include "ngx_http_set_hmac.h" #endif @@ -79,6 +80,12 @@ static ndk_set_var_t ngx_http_set_misc_set_encode_hex_filter = { NULL }; +static ndk_set_var_t ngx_http_set_misc_set_ip_matches_filter = { + NDK_SET_VAR_MULTI_VALUE, + (void *) ngx_http_set_misc_set_ip_matches, + 2, + NULL +}; #if NGX_OPENSSL static ndk_set_var_t ngx_http_set_misc_set_hmac_sha1_filter = { @@ -89,7 +96,6 @@ static ndk_set_var_t ngx_http_set_misc_set_hmac_sha1_filter = { }; #endif - #ifndef NGX_HTTP_SET_HASH static ndk_set_var_t ngx_http_set_misc_set_md5_filter = { NDK_SET_VAR_VALUE, @@ -363,6 +369,15 @@ static ngx_command_t ngx_http_set_misc_commands[] = { 0, NULL }, + { + ngx_string ("set_ip_matches"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF + |NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE3, + ndk_set_var_multi_value, + 0, + 0, + &ngx_http_set_misc_set_ip_matches_filter + }, { ngx_string("set_hashed_upstream"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF diff --git a/t/ip_matches.t b/t/ip_matches.t new file mode 100644 index 0000000..c5fc43a --- /dev/null +++ b/t/ip_matches.t @@ -0,0 +1,45 @@ +# vi:filetype= + +use lib 'lib'; +use Test::Nginx::Socket; + +#repeat_each(3); + +plan tests => repeat_each() * 2 * blocks(); + +no_long_string(); + +run_tests(); + +#no_diff(); + +__DATA__ + +=== TEST 1: IP 10.1.0.101 matches 10.0.0.0/8 +--- config + location /bar { + set_ip_matches $ip_matches 10.0.0.0/8 10.1.0.101; + echo $ip_matches; + } +--- request + GET /bar +--- response_body +1 + + + +=== TEST 2: IP 10.1.0.101 does not match 10.0.0.0/24 +--- config + location /bar { + set_ip_matches $ip_matches 10.0.0.0/24 10.1.0.101; + echo $ip_matches; + } +--- request + GET /bar +--- response_body +0 + + + + + From e8aaed4079a145c5fd7b413d4e70c810bbd8acd1 Mon Sep 17 00:00:00 2001 From: Maurits van der Schee Date: Thu, 13 Mar 2014 15:47:38 +0100 Subject: [PATCH 7/8] Improved test cases --- t/ip_matches.t | 77 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 74 insertions(+), 3 deletions(-) diff --git a/t/ip_matches.t b/t/ip_matches.t index c5fc43a..9e4e87b 100644 --- a/t/ip_matches.t +++ b/t/ip_matches.t @@ -15,7 +15,7 @@ run_tests(); __DATA__ -=== TEST 1: IP 10.1.0.101 matches 10.0.0.0/8 +=== TEST 1: IPv4 address matches IPv4 CIDR --- config location /bar { set_ip_matches $ip_matches 10.0.0.0/8 10.1.0.101; @@ -28,7 +28,7 @@ __DATA__ -=== TEST 2: IP 10.1.0.101 does not match 10.0.0.0/24 +=== TEST 2: IPv4 address does not match IPv4 CIDR --- config location /bar { set_ip_matches $ip_matches 10.0.0.0/24 10.1.0.101; @@ -40,6 +40,77 @@ __DATA__ 0 +=== TEST 3: IPv4 address matches IPv4 address +--- config + location /bar { + set_ip_matches $ip_matches 10.1.0.101 10.1.0.101; + echo $ip_matches; + } +--- request + GET /bar +--- response_body +1 + + + +=== TEST 4: IPv4 address does not match IPv4 address +--- config + location /bar { + set_ip_matches $ip_matches 10.1.0.102 10.1.0.101 ; + echo $ip_matches; + } +--- request + GET /bar +--- response_body +0 + + + +=== TEST 5: IPv6 address matches IPv6 CIDR +--- config + location /bar { + set_ip_matches $ip_matches 3ffe::/16 3ffe:1900:4545:3:200:f8ff::67cf; + echo $ip_matches; + } +--- request + GET /bar +--- response_body +1 - + + +=== TEST 6: IPv6 address does not match IPv6 CIDR +--- config + location /bar { + set_ip_matches $ip_matches 3fff::/16 3ffe:1900:4545:3:200:f8ff::67cf; + echo $ip_matches; + } +--- request + GET /bar +--- response_body +0 + + +=== TEST 7: IPv6 address matches IPv6 address +--- config + location /bar { + set_ip_matches $ip_matches 3ffe:1900:4545:3:200:f8ff::67cf 3ffe:1900:4545:3:200:f8ff::67cf; + echo $ip_matches; + } +--- request + GET /bar +--- response_body +1 + + +=== TEST 7: IPv6 address does not match IPv6 address +--- config + location /bar { + set_ip_matches $ip_matches 3ffe:1900:4545:3:200:f8ff::67d0 3ffe:1900:4545:3:200:f8ff::67cf; + echo $ip_matches; + } +--- request + GET /bar +--- response_body +0 From 8fce20cdf99dfcff58a8fa0aa6ed35829a7c6175 Mon Sep 17 00:00:00 2001 From: Maurits van der Schee Date: Thu, 13 Mar 2014 15:54:37 +0100 Subject: [PATCH 8/8] Forgot to reset DDEBUG flag --- src/ngx_http_set_ip_matches.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ngx_http_set_ip_matches.c b/src/ngx_http_set_ip_matches.c index dd257b6..d667dd7 100644 --- a/src/ngx_http_set_ip_matches.c +++ b/src/ngx_http_set_ip_matches.c @@ -1,5 +1,5 @@ #ifndef DDEBUG -#define DDEBUG 1 +#define DDEBUG 0 #endif #include "ddebug.h"