]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
PR 45959
authorJim Jagielski <jim@apache.org>
Mon, 12 Jan 2009 13:53:43 +0000 (13:53 +0000)
committerJim Jagielski <jim@apache.org>
Mon, 12 Jan 2009 13:53:43 +0000 (13:53 +0000)
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.2.x@733754 13f79535-47bb-0310-9956-ffa450edef68

STATUS
server/request.c

diff --git a/STATUS b/STATUS
index ef004e512b41f226e67488f78852a130ec726a6c..6c911767c158662ef98556408ad25083424599eb 100644 (file)
--- a/STATUS
+++ b/STATUS
@@ -130,14 +130,6 @@ PATCHES ACCEPTED TO BACKPORT FROM TRUNK:
     http://svn.apache.org/viewvc?view=rev&revision=732504
     +1: niq, rpluem, jim
 
-  * core: fix symlink checking in directory walk
-    PR 45959
-      trunk:
-        r423886, r425057, r425394, r490920, r491297
-      2.2.x:
-        http://people.apache.org/~niq/patches/45959
-    +1: niq, rpluem, jim
-
 
 PATCHES PROPOSED TO BACKPORT FROM TRUNK:
   [ New proposals should be added at the end of the list ]
index fe4026a3616bdcdd8738a0e6726bf98ad171d21a..6ca30f926477b121a2a41ae8d818a1f6ddf42ab1 100644 (file)
@@ -558,17 +558,71 @@ AP_DECLARE(int) ap_directory_walk(request_rec *r)
                 && (!r->path_info || !*r->path_info)))
         && (cache->dir_conf_tested == sec_ent)
         && (strcmp(entry_dir, cache->cached) == 0)) {
+
+        int familiar = 0;
+
         /* Well this looks really familiar!  If our end-result (per_dir_result)
          * didn't change, we have absolutely nothing to do :)
          * Otherwise (as is the case with most dir_merged/file_merged requests)
          * we must merge our dir_conf_merged onto this new r->per_dir_config.
          */
         if (r->per_dir_config == cache->per_dir_result) {
-            return OK;
+            familiar = 1;
         }
 
-        if (r->per_dir_config == cache->dir_conf_merged) {
+        else if (r->per_dir_config == cache->dir_conf_merged) {
             r->per_dir_config = cache->per_dir_result;
+            familiar = 1;
+        }
+        if (familiar) {
+            apr_finfo_t thisinfo;
+            int res;
+            allow_options_t opts;
+            core_dir_config *this_dir;
+
+            this_dir = ap_get_module_config(r->per_dir_config, &core_module);
+            opts = this_dir->opts;
+            /*
+             * If Symlinks are allowed in general we do not need the following
+             * check.
+             */
+            if (!(opts & OPT_SYM_LINKS)) {
+                rv = apr_stat(&thisinfo, r->filename,
+                              APR_FINFO_MIN | APR_FINFO_NAME | APR_FINFO_LINK,
+                              r->pool);
+                /*
+                 * APR_INCOMPLETE is as fine as result as APR_SUCCESS as we
+                 * have added APR_FINFO_NAME to the wanted parameter of
+                 * apr_stat above. On Unix platforms this means that apr_stat
+                 * is always going to return APR_INCOMPLETE in the case that
+                 * the call to the native stat / lstat did not fail.
+                 */
+                if ((rv != APR_INCOMPLETE) && (rv != APR_SUCCESS)) {
+                    /*
+                     * This should never happen, because we did a stat on the
+                     * same file, resolving a possible symlink several lines
+                     * above. Therefore do not make a detailed analysis of rv
+                     * in this case for the reason of the failure, just bail out
+                     * with a HTTP_FORBIDDEN in case we hit a race condition
+                     * here.
+                     */
+                    ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
+                                  "access to %s failed; stat of '%s' failed.",
+                                  r->uri, r->filename);
+                    return r->status = HTTP_FORBIDDEN;
+                }
+                if (thisinfo.filetype == APR_LNK) {
+                    /* Is this a possibly acceptable symlink? */
+                    if ((res = resolve_symlink(r->filename, &thisinfo,
+                                               opts, r->pool)) != OK) {
+                        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+                                      "Symbolic link not allowed "
+                                      "or link target not accessible: %s",
+                                      r->filename);
+                        return r->status = res;
+                    }
+                }
+            }
             return OK;
         }