diff options
| author | Igor Sysoev <igor@sysoev.ru> | 2010-09-02 14:59:26 +0000 |
|---|---|---|
| committer | Jonathan Kolb <jon@b0g.us> | 2010-09-02 14:59:26 +0000 |
| commit | 616bf64240e18b8e6b8b4e324b96b1c2a4aaba91 (patch) | |
| tree | 3d76fc5f2d858068620e2b416ee117e895be1262 /src/http | |
| parent | 38d235c14a102c581abb19ee241de7f5a8b0c2b7 (diff) | |
| download | nginx-616bf64240e18b8e6b8b4e324b96b1c2a4aaba91.tar.gz | |
Changes with nginx 0.8.50 02 Sep 2010v0.8.50
*) Feature: the "secure_link", "secure_link_md5", and
"secure_link_expires" directives of the ngx_http_secure_link_module.
*) Feature: the -q switch.
Thanks to Gena Makhomed.
*) Bugfix: worker processes may got caught in an endless loop during
reconfiguration, if a caching was used; the bug had appeared in
0.8.48.
*) Bugfix: in the "gzip_disable" directive.
Thanks to Derrick Petzold.
*) Bugfix: nginx/Windows could not send stop, quit, reopen, and reload
signals to a process run in other session.
Diffstat (limited to 'src/http')
| -rw-r--r-- | src/http/modules/ngx_http_secure_link_module.c | 199 | ||||
| -rw-r--r-- | src/http/modules/perl/nginx.pm | 2 | ||||
| -rw-r--r-- | src/http/ngx_http_cache.h | 3 | ||||
| -rw-r--r-- | src/http/ngx_http_core_module.c | 14 | ||||
| -rw-r--r-- | src/http/ngx_http_file_cache.c | 8 | ||||
| -rw-r--r-- | src/http/ngx_http_script.c | 36 | ||||
| -rw-r--r-- | src/http/ngx_http_script.h | 3 |
7 files changed, 247 insertions, 18 deletions
diff --git a/src/http/modules/ngx_http_secure_link_module.c b/src/http/modules/ngx_http_secure_link_module.c index 2f9351d91..24af22bd7 100644 --- a/src/http/modules/ngx_http_secure_link_module.c +++ b/src/http/modules/ngx_http_secure_link_module.c @@ -11,10 +11,23 @@ typedef struct { - ngx_str_t secret; + ngx_http_complex_value_t *variable; + ngx_http_complex_value_t *md5; + ngx_str_t secret; + ngx_flag_t expires; } ngx_http_secure_link_conf_t; +typedef struct { + ngx_str_t expires; +} ngx_http_secure_link_ctx_t; + + +static ngx_int_t ngx_http_secure_link_old_variable(ngx_http_request_t *r, + ngx_http_secure_link_conf_t *conf, ngx_http_variable_value_t *v, + uintptr_t data); +static ngx_int_t ngx_http_secure_link_expires_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); static void *ngx_http_secure_link_create_conf(ngx_conf_t *cf); static char *ngx_http_secure_link_merge_conf(ngx_conf_t *cf, void *parent, void *child); @@ -23,6 +36,27 @@ static ngx_int_t ngx_http_secure_link_add_variables(ngx_conf_t *cf); static ngx_command_t ngx_http_secure_link_commands[] = { + { ngx_string("secure_link"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_http_set_comlex_value_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_secure_link_conf_t, variable), + NULL }, + + { ngx_string("secure_link_md5"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_http_set_comlex_value_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_secure_link_conf_t, md5), + NULL }, + + { ngx_string("secure_link_expires"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_secure_link_conf_t, expires), + NULL }, + { ngx_string("secure_link_secret"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ngx_conf_set_str_slot, @@ -65,27 +99,124 @@ ngx_module_t ngx_http_secure_link_module = { }; -static ngx_str_t ngx_http_secure_link = ngx_string("secure_link"); +static ngx_str_t ngx_http_secure_link_name = ngx_string("secure_link"); +static ngx_str_t ngx_http_secure_link_expires_name = + ngx_string("secure_link_expires"); static ngx_int_t ngx_http_secure_link_variable(ngx_http_request_t *r, - ngx_http_variable_value_t *v, uintptr_t data) + ngx_http_variable_value_t *v, uintptr_t data) { - u_char *p, *start, *end, *last; - size_t len; - ngx_int_t n; - ngx_uint_t i; - ngx_md5_t md5; + u_char *p, *last; + ngx_str_t val, hash; + time_t expires; + ngx_md5_t md5; + ngx_http_secure_link_ctx_t *ctx; ngx_http_secure_link_conf_t *conf; - u_char hash[16]; + u_char hash_buf[16], md5_buf[16]; conf = ngx_http_get_module_loc_conf(r, ngx_http_secure_link_module); - if (conf->secret.len == 0) { + if (conf->secret.len) { + return ngx_http_secure_link_old_variable(r, conf, v, data); + } + + if (conf->variable == NULL || conf->md5 == NULL) { + goto not_found; + } + + if (ngx_http_complex_value(r, conf->variable, &val) != NGX_OK) { + return NGX_ERROR; + } + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "secure link: \"%V\"", &val); + + last = val.data + val.len; + + p = ngx_strlchr(val.data, last, ','); + expires = 0; + + if (p) { + val.len = p++ - val.data; + + if (conf->expires) { + expires = ngx_atotm(p, last - p); + if (expires <= 0) { + goto not_found; + } + + ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_secure_link_ctx_t)); + if (ctx == NULL) { + return NGX_ERROR; + } + + ngx_http_set_ctx(r, ctx, ngx_http_secure_link_module); + + ctx->expires.len = last - p; + ctx->expires.data = p; + } + } + + if (val.len > 24) { + goto not_found; + } + + hash.len = 16; + hash.data = hash_buf; + + if (ngx_decode_base64url(&hash, &val) != NGX_OK) { + goto not_found; + } + + if (hash.len != 16) { goto not_found; } + if (ngx_http_complex_value(r, conf->md5, &val) != NGX_OK) { + return NGX_ERROR; + } + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "secure link md5: \"%V\"", &val); + + ngx_md5_init(&md5); + ngx_md5_update(&md5, val.data, val.len); + ngx_md5_final(md5_buf, &md5); + + if (ngx_memcmp(hash_buf, md5_buf, 16) != 0) { + goto not_found; + } + + v->data = (u_char *) ((expires && expires < ngx_time()) ? "0" : "1"); + v->len = 1; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + + return NGX_OK; + +not_found: + + v->not_found = 1; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_secure_link_old_variable(ngx_http_request_t *r, + ngx_http_secure_link_conf_t *conf, ngx_http_variable_value_t *v, + uintptr_t data) +{ + u_char *p, *start, *end, *last; + size_t len; + ngx_int_t n; + ngx_uint_t i; + ngx_md5_t md5; + u_char hash[16]; + p = &r->unparsed_uri.data[1]; last = r->unparsed_uri.data + r->unparsed_uri.len; @@ -145,6 +276,29 @@ not_found: } +static ngx_int_t +ngx_http_secure_link_expires_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + ngx_http_secure_link_ctx_t *ctx; + + ctx = ngx_http_get_module_ctx(r, ngx_http_secure_link_module); + + if (ctx) { + v->len = ctx->expires.len; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = ctx->expires.data; + + } else { + v->not_found = 1; + } + + return NGX_OK; +} + + static void * ngx_http_secure_link_create_conf(ngx_conf_t *cf) { @@ -158,9 +312,13 @@ ngx_http_secure_link_create_conf(ngx_conf_t *cf) /* * set by ngx_pcalloc(): * - * conf->secret = { 0, NULL } + * conf->variable = NULL; + * conf->md5 = NULL; + * conf->secret = { 0, NULL }; */ + conf->expires = NGX_CONF_UNSET; + return conf; } @@ -173,6 +331,16 @@ ngx_http_secure_link_merge_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_str_value(conf->secret, prev->secret, ""); + if (conf->variable == NULL) { + conf->variable = prev->variable; + } + + if (conf->md5 == NULL) { + conf->md5 = prev->md5; + } + + ngx_conf_merge_value(conf->expires, prev->expires, 0); + return NGX_CONF_OK; } @@ -182,12 +350,19 @@ ngx_http_secure_link_add_variables(ngx_conf_t *cf) { ngx_http_variable_t *var; - var = ngx_http_add_variable(cf, &ngx_http_secure_link, NGX_HTTP_VAR_NOHASH); + var = ngx_http_add_variable(cf, &ngx_http_secure_link_name, 0); if (var == NULL) { return NGX_ERROR; } var->get_handler = ngx_http_secure_link_variable; + var = ngx_http_add_variable(cf, &ngx_http_secure_link_expires_name, 0); + if (var == NULL) { + return NGX_ERROR; + } + + var->get_handler = ngx_http_secure_link_expires_variable; + return NGX_OK; } diff --git a/src/http/modules/perl/nginx.pm b/src/http/modules/perl/nginx.pm index bbde69a2f..5eeb1c753 100644 --- a/src/http/modules/perl/nginx.pm +++ b/src/http/modules/perl/nginx.pm @@ -48,7 +48,7 @@ our @EXPORT = qw( HTTP_INSUFFICIENT_STORAGE ); -our $VERSION = '0.8.49'; +our $VERSION = '0.8.50'; require XSLoader; XSLoader::load('nginx', $VERSION); diff --git a/src/http/ngx_http_cache.h b/src/http/ngx_http_cache.h index 1a23e4620..b511a0b91 100644 --- a/src/http/ngx_http_cache.h +++ b/src/http/ngx_http_cache.h @@ -43,7 +43,8 @@ typedef struct { unsigned error:10; unsigned exists:1; unsigned updating:1; - /* 12 unused bits */ + unsigned deleting:1; + /* 11 unused bits */ ngx_file_uniq_t uniq; time_t expire; diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c index 6a11a8724..d29d20844 100644 --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -3111,8 +3111,8 @@ ngx_http_core_create_loc_conf(ngx_conf_t *cf) clcf->gzip_http_version = NGX_CONF_UNSET_UINT; #if (NGX_PCRE) clcf->gzip_disable = NGX_CONF_UNSET_PTR; - clcf->gzip_disable_msie6 = 3; #endif + clcf->gzip_disable_msie6 = 3; #endif return clcf; @@ -3788,13 +3788,19 @@ ngx_http_core_root(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) n = ngx_http_script_variables_count(&clcf->root); ngx_memzero(&sc, sizeof(ngx_http_script_compile_t)); + sc.variables = n; + +#if (NGX_PCRE) + if (alias && clcf->regex) { + n = 1; + } +#endif if (n) { sc.cf = cf; sc.source = &clcf->root; sc.lengths = &clcf->root_lengths; sc.values = &clcf->root_values; - sc.variables = n; sc.complete_lengths = 1; sc.complete_values = 1; @@ -4384,7 +4390,7 @@ ngx_http_gzip_disable(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) for (i = 1; i < cf->args->nelts; i++) { - if (ngx_strcmp(value[1].data, "msie6") == 0) { + if (ngx_strcmp(value[i].data, "msie6") == 0) { clcf->gzip_disable_msie6 = 1; continue; } @@ -4394,7 +4400,7 @@ ngx_http_gzip_disable(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) return NGX_CONF_ERROR; } - rc.pattern = value[1]; + rc.pattern = value[i]; rc.options = NGX_REGEX_CASELESS; if (ngx_regex_compile(&rc) != NGX_OK) { diff --git a/src/http/ngx_http_file_cache.c b/src/http/ngx_http_file_cache.c index d14a7c5e6..0d97e94ec 100644 --- a/src/http/ngx_http_file_cache.c +++ b/src/http/ngx_http_file_cache.c @@ -582,6 +582,7 @@ ngx_http_file_cache_exists(ngx_http_file_cache_t *cache, ngx_http_cache_t *c) fcn->uses = 1; fcn->count = 1; fcn->updating = 0; + fcn->deleting = 0; renew: @@ -1102,6 +1103,10 @@ ngx_http_file_cache_expire(ngx_http_file_cache_t *cache) continue; } + if (fcn->deleting) { + continue; + } + p = ngx_hex_dump(key, (u_char *) &fcn->node.key, sizeof(ngx_rbtree_key_t)); len = NGX_HTTP_CACHE_KEY_LEN - sizeof(ngx_rbtree_key_t); @@ -1153,6 +1158,7 @@ ngx_http_file_cache_delete(ngx_http_file_cache_t *cache, ngx_queue_t *q, *p = '\0'; fcn->count++; + fcn->deleting = 1; ngx_shmtx_unlock(&cache->shpool->mutex); len = path->name.len + 1 + path->len + 2 * NGX_HTTP_CACHE_KEY_LEN; @@ -1168,6 +1174,7 @@ ngx_http_file_cache_delete(ngx_http_file_cache_t *cache, ngx_queue_t *q, ngx_shmtx_lock(&cache->shpool->mutex); fcn->count--; + fcn->deleting = 0; } if (fcn->count == 0) { @@ -1431,6 +1438,7 @@ ngx_http_file_cache_add(ngx_http_file_cache_t *cache, ngx_http_cache_t *c) fcn->error = 0; fcn->exists = 1; fcn->updating = 0; + fcn->deleting = 0; fcn->uniq = c->uniq; fcn->valid_sec = c->valid_sec; fcn->body_start = c->body_start; diff --git a/src/http/ngx_http_script.c b/src/http/ngx_http_script.c index 1474f3245..503c0f058 100644 --- a/src/http/ngx_http_script.c +++ b/src/http/ngx_http_script.c @@ -211,6 +211,42 @@ ngx_http_compile_complex_value(ngx_http_compile_complex_value_t *ccv) } +char * +ngx_http_set_comlex_value_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + char *p = conf; + + ngx_str_t *value; + ngx_http_complex_value_t **cv; + ngx_http_compile_complex_value_t ccv; + + cv = (ngx_http_complex_value_t **) (p + cmd->offset); + + if (*cv != NULL) { + return "duplicate"; + } + + *cv = ngx_palloc(cf->pool, sizeof(ngx_http_complex_value_t)); + if (*cv == NULL) { + return NGX_CONF_ERROR; + } + + value = cf->args->elts; + + ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); + + ccv.cf = cf; + ccv.value = &value[1]; + ccv.complex_value = *cv; + + if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { + return NGX_CONF_ERROR; + } + + return NGX_CONF_OK; +} + + ngx_int_t ngx_http_test_predicates(ngx_http_request_t *r, ngx_array_t *predicates) { diff --git a/src/http/ngx_http_script.h b/src/http/ngx_http_script.h index d741ceabb..c1288b77a 100644 --- a/src/http/ngx_http_script.h +++ b/src/http/ngx_http_script.h @@ -207,6 +207,9 @@ void ngx_http_script_flush_complex_value(ngx_http_request_t *r, ngx_int_t ngx_http_complex_value(ngx_http_request_t *r, ngx_http_complex_value_t *val, ngx_str_t *value); ngx_int_t ngx_http_compile_complex_value(ngx_http_compile_complex_value_t *ccv); +char * ngx_http_set_comlex_value_slot(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); + ngx_int_t ngx_http_test_predicates(ngx_http_request_t *r, ngx_array_t *predicates); |
