--- t/apache2-2.2.9/server/request.c 2008-05-12 18:05:03.000000000 +0200 +++ apache2-2.2.9/server/request.c 2008-09-19 14:54:37.000000000 +0200 @@ -472,6 +472,7 @@ walk_cache_t *cache; char *entry_dir; apr_status_t rv; + apr_finfo_t saved_finfo; /* XXX: Better (faster) tests needed!!! * @@ -520,8 +521,11 @@ * types of failure, such as APR_ENOTDIR. We can do something * with APR_ENOENT, knowing that the path is good. */ + saved_finfo = r->finfo; if (!r->finfo.filetype || r->finfo.filetype == APR_LNK) { rv = apr_stat(&r->finfo, r->filename, APR_FINFO_MIN, r->pool); + if (!saved_finfo.filetype) + saved_finfo = r->finfo; /* some OSs will return APR_SUCCESS/APR_REG if we stat * a regular file but we have '/' at the end of the name; @@ -563,19 +567,46 @@ * 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; - } + int res = !OK; + ap_conf_vector_t *old_config = NULL; - if (r->per_dir_config == cache->dir_conf_merged) { + if (r->per_dir_config == cache->per_dir_result) { + res = OK; + } + else if (r->per_dir_config == cache->dir_conf_merged) { r->per_dir_config = cache->per_dir_result; - return OK; + res = OK; } - - if (cache->walked->nelts) { + else if (cache->walked->nelts) { + /* Need to do this now rather than later so that + * ap_allow_options(r) gives the right result. + */ now_merged = ((walk_walked_t*)cache->walked->elts) [cache->walked->nelts - 1].merged; + old_config = r->per_dir_config; + r->per_dir_config = ap_merge_per_dir_configs(r->pool, + r->per_dir_config, + now_merged); } + + if (saved_finfo.filetype == APR_LNK) { + /* Is this a possibly acceptable symlink? + */ + if ((res = resolve_symlink(r->filename, &saved_finfo, + ap_allow_options(r), r->pool)) != OK) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + "Symbolic link not allowed " + "or link target not accessible: %s", + r->filename); + /* we error out, so undo merge */ + if (old_config) + r->per_dir_config = old_config; + return r->status = res; + } + } + + if (res == OK) + return res; } else { /* We start now_merged from NULL since we want to build @@ -1808,7 +1839,7 @@ && rnew->filename[fdirlen] && ap_strchr_c(rnew->filename + fdirlen, '/') == NULL) { apr_status_t rv; - if (ap_allow_options(rnew) & OPT_SYM_LINKS) { + if (ap_allow_options(r) & OPT_SYM_LINKS) { if (((rv = apr_stat(&rnew->finfo, rnew->filename, APR_FINFO_MIN, rnew->pool)) != APR_SUCCESS) && (rv != APR_INCOMPLETE)) {