php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Doc Bug #43817 opendir() fails on Windows directories with parent directory unaccessible
Submitted: 2008-01-11 12:23 UTC Modified: 2021-10-04 15:25 UTC
Votes:55
Avg. Score:4.3 ± 0.9
Reproduced:47 of 47 (100.0%)
Same Version:18 (38.3%)
Same OS:21 (44.7%)
From: losd at mail dot dk Assigned:
Status: Verified Package: Streams related
PHP Version: 5.3.0beta1 OS: win32 only - Windows Server 2003
Private report: No CVE-ID: None
 [2008-01-11 12:23 UTC] losd at mail dot dk
Description:
------------
If the parent directory of a Windows network share is not accessible, you are still able to access subdirectories if given explicit permission.

However, PHP has trouble with the first accessible directory below an inaccessible directory. This is not a problem for the accessible dir's  subdirs, though.

Scenario:
C:/Test/NoAccess/  -- Not accessible
   Access/        -- Accesible from here
      yyyyyyy.txt
      Subdir/
         xxxxxxx.txt

The problem has been found with opendir(), is_dir() and is_readable(). All directory functions are probably affected.

No workarounds has been found so far (suggestions appreciated).

Reproduce code:
---------------
<?php
if ($handle = opendir("C:/Test/NoAccess/Access/Subdir")) {
	echo "Opened dir C:/Test/NoAccess/Access/Subdir<br/>";
	while (false !== ($file = readdir($handle)))
		echo"File: $file<br/>";
	closedir($handle);
} else {
	echo "Hmmmm, can't open directory, is it accessible?<br/>";
}
echo "<br/>";
if ($handle = opendir("C:/Test/NoAccess/Access")) {
	echo "Opened directory C:/Test/NoAccess/Access<br/>";
	while (false !== ($file = readdir($handle)))
		echo"File: $file<br/>";
	closedir($handle);
} else {
	echo "Hmmmm, can't open directory, is it accessible?<br/>";
}
?>

Expected result:
----------------
Opened dir C:/Test/NoAccess/Access/Subdir
File: .
File: ..
File: xxxxxxx.txt

Opened dir C:/Test/NoAccess/Access
File: .
File: ..
File: yyyyyyy.txt
File: Subdir




Actual result:
--------------
Opened dir C:/Test/NoAccess/Access/Subdir
File: .
File: ..
File: xxxxxxx.txt


Warning: opendir(C:/Test/NoAccess/Access) [function.opendir]: failed to open dir: No such file or directory in C:\Inetpub\wwwroot\pm2\opendir.php on line 13
Hmmmm, can't open directory, is it accessible?

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2008-01-11 13:36 UTC] losd at mail dot dk
Temporary workaround found, but only if there is a known subdirectory inside the top accessible directory:

opendir("C:/Test/NoAccess/Access/Subdir/..");
 [2008-03-01 01:10 UTC] danielc@php.net
I am experiencing this issue as well, but on local directories, not network shares.  My OS is Windows XP Pro.  The opendir() functionality works correctly in release 5.2.1.  The functionality is broken in releases 5.2.2 through 5.2.5, plus the 526-php5.2-win32-200802292130 and php5.3-win32-200802201330 snapshots.
 [2008-03-01 09:09 UTC] losd at mail dot dk
Doh, sorry, thought I could edit the original text. Just delete that comment.

But yes, as Daniel correctly points out, it's all Windows permission handling (As my reproduce code also shows), not just related to network shares... I experienced it in one at first, I guess that's why it stuck in my brain.
 [2008-08-12 09:42 UTC] dmitry@php.net
Fixed in CVS HEAD and PHP_5_3.
 [2009-02-03 15:31 UTC] danielc@php.net
This problem still exists in 5.3.0 beta 1 (http://windows.php.net/downloads/qa/php-5.3.0beta1-Win32-VC6-x86.zip)
 [2009-02-03 17:36 UTC] danielc@php.net
Changing version from 5.2.5 to 5.3.0beta1 to facilitate this getting fixed before the next release.
 [2009-03-02 20:01 UTC] pajoye@php.net
I can now reproduce it on XP, but not on 2008/Vista/win7.

I have to investigate deeper :P
 [2009-03-02 20:09 UTC] pajoye@php.net
Also see #42832
 [2009-06-20 11:39 UTC] pajoye@php.net
Can't reproduce it with RC4, please try again with 5.3.0RC4.
 [2009-06-28 01:00 UTC] php-bugs at lists dot php dot net
No feedback was provided for this bug for over a week, so it is
being suspended automatically. If you are able to provide the
information that was originally requested, please do so and change
the status of the bug back to "Open".
 [2010-03-29 00:12 UTC] danielc@php.net
-Status: No Feedback +Status: Assigned
 [2010-03-29 00:12 UTC] danielc@php.net
Still exists for me under the official release of PHP 5.3.0 on an XP SP3 machine.
 [2010-03-29 00:27 UTC] pajoye@php.net
-Status: Assigned +Status: Feedback
 [2010-03-29 00:27 UTC] pajoye@php.net
Please try with 5.3.2
 [2010-04-05 01:45 UTC] danielc@php.net
-Status: Feedback +Status: Assigned
 [2010-04-05 01:45 UTC] danielc@php.net
I just installed 5.3.2.  The regression has gotten worse.  Now the "Subdir/.." workaround fails too:

Warning: opendir(C:/Dir/Subdir/..,C:/Dir/Subdir/..) [function.opendir]: Access is denied. (code: 5)...
 [2010-04-05 01:59 UTC] pajoye@php.net
Nothing has changed in 5.2/3.x about that. The problem may come from the tsrm's real path which tries to access all parent directories to cache them.

I have to investigate why it fails on XP (and on on 2003 for your right?) but not on more recent versions.
 [2010-04-08 16:36 UTC] danielc@php.net
That makes sense.  I'm on XP.  Thanks.  If you need quicker feedback, shoot me an email or assign the bug to me.
 [2011-01-29 00:11 UTC] asankel at yahoo dot com
Same problem with PHP 5.3.5 on Windows 2008 with IIS 7.

Workaround is to add "\." to the end of the path and then PHP doesn't attempt to access the parent directories at all. For example, change "d:\files\directory\test" to "d:\files\directory\test\."
 [2011-01-29 00:22 UTC] asankel at yahoo dot com
Never mind on the workaround. Was related to some fastcgi caching. If you are running fastcgi the parent directory check is only done the first time. If it has access the first time it won't check the parent directory for further accesses.
 [2011-02-01 22:42 UTC] asankel at yahoo dot com
UPDATE: This problem does not occur with php-5.2.17-nts-Win32-VC6-x86 so you can use it as a workaround.
 [2012-07-18 06:53 UTC] denis at morozov dot tk
W2008R2x64+PHP5.3.8.: have got the same error+
In my case is_dir() is not affected,
but opendir() fails.
Directory is in the root of system disk, directories inside wwwroot are not affected.
If started from CMD with Admin - no error, error comes only in case of IUSR-IIS calls.
IN:
$dir="E:\\temp\\";
$dh=opendir($dir);
OUT:
PHP Warning:  opendir(E:\temp\,E:\temp\) [<a href='function.opendir'>function.opendir</a>]: Отказано в доступе. (code: 5) in E:\inetpub\dm\iPrinter\dir.php
 [2012-10-18 11:49 UTC] y dot korotia at hotmail dot com
are you going to fix it for Windows or not?

I've wasted about 4 hours because of this bug!

installed ZendServer with 5.3x

To access folder I must give access to its parent. what a f..?
 [2013-01-10 12:34 UTC] pajoye@php.net
Quick notice to help to understand the problem describe here:

The main problem here is that FindFirstFile requires access to all elements of a 
given path, which is not the case here.

To work around this limitation while keeping the realpath cache working nicely is 
not that easy.
 [2013-01-14 11:26 UTC] pajoye@php.net
Ok, the actual issue is about setting the right permissions.

It is possible to block read&write and other operations but the read of the 
attribute of a given path must be allowed. It is used by almost all file 
functions    (Find*, GetLong/ShortPathName, etc.). 

Without the permissions allowing to read attributes, we won't be able to fetch 
the actual name (ie: c:\Foo is given but the actual name is c:\fOo). We used the 
actual to store it in the real cache and avoid to have to lower case all paths 
before each file operation.

Can you try to set the perms correctly and tell me if it works out for you? 
Should work on any windows supported version.
 [2013-01-16 06:42 UTC] d at hp23c dot dk
In Windows, it _does not matter_ if it is C:\fOo or c:\foo. If you do not lowercase (or uppercase, or whatever) to compare, it is a bug.
 [2013-01-16 09:20 UTC] pajoye@php.net
It does matter. The reasons are:

1. Windows support case sensitive filesystems (in any modern versions)
2. the real path stat cache is case sensitive, for portability and performance, 
by design.

However, no matter how the case is, you have to set the attributes permissions. 
If it is not allowed to read the attributes, php won't be able to load that file 
or path. And again, it has absolutely nothing do with case sensitive paths.

Last but not least, if you see the bug status, it is still open as a bug, but it 
is about other issues caused by FindFirstFile, not the case sensitivity.
 [2013-03-05 12:08 UTC] mindless at mindless999 dot net
Issue still exists in 5.3.22

Workaround is to give the user under which the website is running (advanced) "list folder / read data" permissions on the parent folder.
this is the only permission required.
 [2013-03-05 12:12 UTC] pajoye@php.net
@mindless at mindless999 dot net

That's correct, I forgot to add this info to this bug report (present in another 
one). It is required to allow the underlying Windows API to get through the 
directories while it won't allow the user to access it.
 [2015-01-22 19:13 UTC] scott at phphq dot net
This bug still exists in php 5.4.36. win32 - Windows Server 2003, iis6. I can readfile, chdir but if I try to read the files (scandir, opendir, DirectoryIterator) I get an access denied error.

C:/Website/ -- Not accessible
C:/Website/public_html  -- Accessible
C:/Website/public_html/etc...  -- Accessible

User has correct permission to C:/Website but no permissions for access on C:/.
 [2016-11-08 11:03 UTC] knagis at miga dot lv
I have the same problem on Windows Server 2012 R2 and both PHP 5.6.24 and PHP 7.0.9. In my case the DirectoryIterator::__construct was failing with Access is denied. (code: 5)
 [2016-12-28 04:02 UTC] kthprog at gmail dot com
I have the same problems. PHP 7.1 NTS on IIS ...10? Running Windows 10. The workaround appending a subdir + .. worked for me.
 [2017-10-24 07:36 UTC] kalle@php.net
-Status: Assigned +Status: Open -Assigned To: pajoye +Assigned To:
 [2018-04-22 01:38 UTC] rujjinjakka at rocketmail dot com
Same problem with PHP 7.1.1 with Windows NT build 7601 (Windows 7 Ultimate Edition Service Pack 1) i586

It looks like chmod does not work either. I noticed that IIS does not have direct permission to access the file. Maybe to have access to the file, the direct editing is necessary. I used the Chmod ( chmod 777 ) for the file, but it was only applied in the directory, not being applicable to the files inside that directory.
In my case, it was a case of file import by form  (move_uploaded_file($tmp_name, $prev)). 

$prev =  $dir. "/" .basename( $filename );
if(move_uploaded_file($tmp_name, $prev)){
    echo "Success!". $prev
}

The file is copied but is not displayed in previews. The file does not have the permissions for the IIS_IUSRS user.
 [2018-04-22 07:46 UTC] spam2 at rhsoft dot net
outside the windows world this is normal behavior and php aims to behave as identical as possible on every platform 

it's bad allow access deep in the tree just because somewhere are permissions wrong and in case of a script running on a web server say thank you for the increased security, either the access was not intended or set proper permissions
 [2021-09-23 15:08 UTC] cmb@php.net
-Status: Open +Status: Verified -Type: Bug +Type: Documentation Problem
 [2021-09-23 15:08 UTC] cmb@php.net
For opendir(), all parent folders need at least read data/list
directory (RA) rights; for some other operations more permissions
might be needed, but read and execute access (RX) sjould be
sufficient in any case.  This is by design, and while it may not
be explicitly documented for all file functions, the realpath()
docs already state:

| The running script must have executable permissions on all
| directories in the hierarchy, otherwise realpath() will return
| false.

What may be more surprising is that fileperms() on a folder with
RA rights yields 0777, although that folder isn't writable, and
is_writable() returns false.  This is because is_writable() also
does an actual access() like check, while stat() does not, for
perfomance reasons.  That might be worth documenting as well.
 [2021-10-04 15:25 UTC] cmb@php.net
-Package: Directory function related +Package: Streams related
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Tue Nov 05 01:01:29 2024 UTC