diff src/http/ngx_http_core_module.c @ 664:f5b859b2f097 NGINX_1_1_16

nginx 1.1.16 *) Change: the simultaneous subrequest limit has been raised to 200. *) Feature: the "from" parameter of the "disable_symlinks" directive. *) Feature: the "return" and "error_page" directives can be used to return 307 redirections. *) Bugfix: a segmentation fault might occur in a worker process if the "resolver" directive was used and there was no "error_log" directive specified at global level. Thanks to Roman Arutyunyan. *) Bugfix: a segmentation fault might occur in a worker process if the "proxy_http_version 1.1" or "fastcgi_keep_conn on" directives were used. *) Bugfix: memory leaks. Thanks to Lanshun Zhou. *) Bugfix: in the "disable_symlinks" directive. *) Bugfix: on ZFS filesystem disk cache size might be calculated incorrectly; the bug had appeared in 1.0.1. *) Bugfix: nginx could not be built by the icc 12.1 compiler. *) Bugfix: nginx could not be built by gcc on Solaris; the bug had appeared in 1.1.15.
author Igor Sysoev <http://sysoev.ru>
date Wed, 29 Feb 2012 00:00:00 +0400
parents e5fa0a4a7d27
children bf8b55a5ac89
line wrap: on
line diff
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -76,6 +76,10 @@ static ngx_uint_t ngx_http_gzip_quantity
 static char *ngx_http_gzip_disable(ngx_conf_t *cf, ngx_command_t *cmd,
     void *conf);
 #endif
+#if (NGX_HAVE_OPENAT)
+static char *ngx_http_disable_symlinks(ngx_conf_t *cf, ngx_command_t *cmd,
+    void *conf);
+#endif
 
 static char *ngx_http_core_lowat_check(ngx_conf_t *cf, void *post, void *data);
 static char *ngx_http_core_pool_size(ngx_conf_t *cf, void *post, void *data);
@@ -187,18 +191,6 @@ static ngx_str_t  ngx_http_gzip_private 
 #endif
 
 
-#if (NGX_HAVE_OPENAT)
-
-static ngx_conf_enum_t  ngx_http_core_disable_symlinks[] = {
-    { ngx_string("off"), NGX_DISABLE_SYMLINKS_OFF },
-    { ngx_string("if_not_owner"), NGX_DISABLE_SYMLINKS_NOTOWNER },
-    { ngx_string("on"), NGX_DISABLE_SYMLINKS_ON },
-    { ngx_null_string, 0 }
-};
-
-#endif
-
-
 static ngx_command_t  ngx_http_core_commands[] = {
 
     { ngx_string("variables_hash_max_size"),
@@ -779,11 +771,11 @@ static ngx_command_t  ngx_http_core_comm
 #if (NGX_HAVE_OPENAT)
 
     { ngx_string("disable_symlinks"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
-      ngx_conf_set_enum_slot,
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12,
+      ngx_http_disable_symlinks,
       NGX_HTTP_LOC_CONF_OFFSET,
-      offsetof(ngx_http_core_loc_conf_t, disable_symlinks),
-      &ngx_http_core_disable_symlinks },
+      0,
+      NULL },
 
 #endif
 
@@ -1320,9 +1312,11 @@ ngx_http_core_try_files_phase(ngx_http_r
         of.test_only = 1;
         of.errors = clcf->open_file_cache_errors;
         of.events = clcf->open_file_cache_events;
-#if (NGX_HAVE_OPENAT)
-        of.disable_symlinks = clcf->disable_symlinks;
-#endif
+
+        if (ngx_http_set_disable_symlinks(r, clcf, &path, &of) != NGX_OK) {
+            ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
+            return NGX_OK;
+        }
 
         if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
             != NGX_OK)
@@ -1824,8 +1818,11 @@ ngx_http_send_response(ngx_http_request_
         return NGX_HTTP_INTERNAL_SERVER_ERROR;
     }
 
-    if (status >= NGX_HTTP_MOVED_PERMANENTLY && status <= NGX_HTTP_SEE_OTHER) {
-
+    if (status == NGX_HTTP_MOVED_PERMANENTLY
+        || status == NGX_HTTP_MOVED_TEMPORARILY
+        || status == NGX_HTTP_SEE_OTHER
+        || status == NGX_HTTP_TEMPORARY_REDIRECT)
+    {
         ngx_http_clear_location(r);
 
         r->headers_out.location = ngx_list_push(&r->headers_out.headers);
@@ -2642,6 +2639,56 @@ ngx_http_cleanup_add(ngx_http_request_t 
 }
 
 
+ngx_int_t
+ngx_http_set_disable_symlinks(ngx_http_request_t *r,
+    ngx_http_core_loc_conf_t *clcf, ngx_str_t *path, ngx_open_file_info_t *of)
+{
+#if (NGX_HAVE_OPENAT)
+    u_char     *p;
+    ngx_str_t   from;
+
+    of->disable_symlinks = clcf->disable_symlinks;
+
+    if (clcf->disable_symlinks_from == NULL) {
+        return NGX_OK;
+    }
+
+    if (ngx_http_complex_value(r, clcf->disable_symlinks_from, &from)
+        != NGX_OK)
+    {
+        return NGX_ERROR;
+    }
+
+    if (from.len == 0
+        || from.len > path->len
+        || ngx_memcmp(path->data, from.data, from.len) != 0)
+    {
+        return NGX_OK;
+    }
+
+    if (from.len == path->len) {
+        of->disable_symlinks = NGX_DISABLE_SYMLINKS_OFF;
+        return NGX_OK;
+    }
+
+    p = path->data + from.len;
+
+    if (*p == '/') {
+        of->disable_symlinks_from = from.len;
+        return NGX_OK;
+    }
+
+    p--;
+
+    if (*p == '/') {
+        of->disable_symlinks_from = from.len - 1;
+    }
+#endif
+
+    return NGX_OK;
+}
+
+
 static char *
 ngx_http_core_server(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy)
 {
@@ -3372,6 +3419,7 @@ ngx_http_core_create_loc_conf(ngx_conf_t
 
 #if (NGX_HAVE_OPENAT)
     clcf->disable_symlinks = NGX_CONF_UNSET_UINT;
+    clcf->disable_symlinks_from = NGX_CONF_UNSET_PTR;
 #endif
 
     return clcf;
@@ -3656,6 +3704,8 @@ ngx_http_core_merge_loc_conf(ngx_conf_t 
 #if (NGX_HAVE_OPENAT)
     ngx_conf_merge_uint_value(conf->disable_symlinks, prev->disable_symlinks,
                               NGX_DISABLE_SYMLINKS_OFF);
+    ngx_conf_merge_ptr_value(conf->disable_symlinks_from,
+                             prev->disable_symlinks_from, NULL);
 #endif
 
     return NGX_CONF_OK;
@@ -4791,6 +4841,100 @@ ngx_http_gzip_disable(ngx_conf_t *cf, ng
 #endif
 
 
+#if (NGX_HAVE_OPENAT)
+
+static char *
+ngx_http_disable_symlinks(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+    ngx_http_core_loc_conf_t *clcf = conf;
+
+    ngx_str_t                         *value;
+    ngx_uint_t                         i;
+    ngx_http_compile_complex_value_t   ccv;
+
+    if (clcf->disable_symlinks != NGX_CONF_UNSET_UINT) {
+        return "is duplicate";
+    }
+
+    value = cf->args->elts;
+
+    for (i = 1; i < cf->args->nelts; i++) {
+
+        if (ngx_strcmp(value[i].data, "off") == 0) {
+            clcf->disable_symlinks = NGX_DISABLE_SYMLINKS_OFF;
+            continue;
+        }
+
+        if (ngx_strcmp(value[i].data, "if_not_owner") == 0) {
+            clcf->disable_symlinks = NGX_DISABLE_SYMLINKS_NOTOWNER;
+            continue;
+        }
+
+        if (ngx_strcmp(value[i].data, "on") == 0) {
+            clcf->disable_symlinks = NGX_DISABLE_SYMLINKS_ON;
+            continue;
+        }
+
+        if (ngx_strncmp(value[i].data, "from=", 5) == 0) {
+            value[i].len -= 5;
+            value[i].data += 5;
+
+            ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
+
+            ccv.cf = cf;
+            ccv.value = &value[i];
+            ccv.complex_value = ngx_palloc(cf->pool,
+                                           sizeof(ngx_http_complex_value_t));
+            if (ccv.complex_value == NULL) {
+                return NGX_CONF_ERROR;
+            }
+
+            if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
+                return NGX_CONF_ERROR;
+            }
+
+            clcf->disable_symlinks_from = ccv.complex_value;
+
+            continue;
+        }
+
+        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                           "invalid parameter \"%V\"", &value[i]);
+        return NGX_CONF_ERROR;
+    }
+
+    if (clcf->disable_symlinks == NGX_CONF_UNSET_UINT) {
+        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                           "\"%V\" must have \"off\", \"on\" "
+                           "or \"if_not_owner\" parameter",
+                           &cmd->name);
+        return NGX_CONF_ERROR;
+    }
+
+    if (cf->args->nelts == 2) {
+        clcf->disable_symlinks_from = NULL;
+        return NGX_CONF_OK;
+    }
+
+    if (clcf->disable_symlinks_from == NGX_CONF_UNSET_PTR) {
+        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                           "duplicate parameters \"%V %V\"",
+                           &value[1], &value[2]);
+        return NGX_CONF_ERROR;
+    }
+
+    if (clcf->disable_symlinks == NGX_DISABLE_SYMLINKS_OFF) {
+        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                           "\"from=\" cannot be used with \"off\" parameter");
+        return NGX_CONF_ERROR;
+    }
+
+    return NGX_CONF_OK;
+}
+
+#endif
+
+
 static char *
 ngx_http_core_lowat_check(ngx_conf_t *cf, void *post, void *data)
 {