@@ -558,17 +558,71 @@ AP_DECLARE(int) ap_directory_walk(request_rec *r)
558558 && (!r -> path_info || !* r -> path_info )))
559559 && (cache -> dir_conf_tested == sec_ent )
560560 && (strcmp (entry_dir , cache -> cached ) == 0 )) {
561+
562+ int familiar = 0 ;
563+
561564 /* Well this looks really familiar! If our end-result (per_dir_result)
562565 * didn't change, we have absolutely nothing to do :)
563566 * Otherwise (as is the case with most dir_merged/file_merged requests)
564567 * we must merge our dir_conf_merged onto this new r->per_dir_config.
565568 */
566569 if (r -> per_dir_config == cache -> per_dir_result ) {
567- return OK ;
570+ familiar = 1 ;
568571 }
569572
570- if (r -> per_dir_config == cache -> dir_conf_merged ) {
573+ else if (r -> per_dir_config == cache -> dir_conf_merged ) {
571574 r -> per_dir_config = cache -> per_dir_result ;
575+ familiar = 1 ;
576+ }
577+ if (familiar ) {
578+ apr_finfo_t thisinfo ;
579+ int res ;
580+ allow_options_t opts ;
581+ core_dir_config * this_dir ;
582+
583+ this_dir = ap_get_module_config (r -> per_dir_config , & core_module );
584+ opts = this_dir -> opts ;
585+ /*
586+ * If Symlinks are allowed in general we do not need the following
587+ * check.
588+ */
589+ if (!(opts & OPT_SYM_LINKS )) {
590+ rv = apr_stat (& thisinfo , r -> filename ,
591+ APR_FINFO_MIN | APR_FINFO_NAME | APR_FINFO_LINK ,
592+ r -> pool );
593+ /*
594+ * APR_INCOMPLETE is as fine as result as APR_SUCCESS as we
595+ * have added APR_FINFO_NAME to the wanted parameter of
596+ * apr_stat above. On Unix platforms this means that apr_stat
597+ * is always going to return APR_INCOMPLETE in the case that
598+ * the call to the native stat / lstat did not fail.
599+ */
600+ if ((rv != APR_INCOMPLETE ) && (rv != APR_SUCCESS )) {
601+ /*
602+ * This should never happen, because we did a stat on the
603+ * same file, resolving a possible symlink several lines
604+ * above. Therefore do not make a detailed analysis of rv
605+ * in this case for the reason of the failure, just bail out
606+ * with a HTTP_FORBIDDEN in case we hit a race condition
607+ * here.
608+ */
609+ ap_log_rerror (APLOG_MARK , APLOG_ERR , rv , r ,
610+ "access to %s failed; stat of '%s' failed." ,
611+ r -> uri , r -> filename );
612+ return r -> status = HTTP_FORBIDDEN ;
613+ }
614+ if (thisinfo .filetype == APR_LNK ) {
615+ /* Is this a possibly acceptable symlink? */
616+ if ((res = resolve_symlink (r -> filename , & thisinfo ,
617+ opts , r -> pool )) != OK ) {
618+ ap_log_rerror (APLOG_MARK , APLOG_ERR , 0 , r ,
619+ "Symbolic link not allowed "
620+ "or link target not accessible: %s" ,
621+ r -> filename );
622+ return r -> status = res ;
623+ }
624+ }
625+ }
572626 return OK ;
573627 }
574628
0 commit comments