I cannot manage to set the SGID bit from PHP.
I have this directory:
4 drwxrwsr-x 12 www-data mygroup 4096 Oct 7 16:05 mydir
Note the SGID bit. So, if I simply create a directory into it from the shell with mkdir test, I get
4 drwxr-sr-x 2 myuser mygroup 4096 Oct 7 16:22 test
Note that the SGID bit is inherited. But I would want it group writable (which my umask 22 does not allow) so I can simply chmod 02775 test and I am perfectly happy:
4 drwxrwsr-x 2 myuser mygroup 4096 Oct 7 16:22 test
Now I would like to do the same from a PHP script. Naturally, I would expect this to work:
mkdir("/mydir/test2");
chmod("/mydir/test2", 02775);
But it does not and I get this instead (the SGID is reset):
4 drwxrwxr-x 2 www-data mygroup 4096 Oct 7 16:30 test2
Here are a couple of other useful experiments:
mkdir("/mydir/test3");
mkdir("/mydir/test4");
passthru("chmod 02775 '/mydir/test4'");
mkdir("/mydir/test5");
passthru("chmod g+w '/mydir/test5'");
The results are
4 drwxr-sr-x 2 www-data mygroup 4096 Oct 7 16:39 test3
4 drwxrwxr-x 2 www-data mygroup 4096 Oct 7 16:39 test4
4 drwxrwxr-x 2 www-data mygroup 4096 Oct 7 17:06 test5
Interestingly, mkdir() alone has preserved the SGID, but chmod() resets it, even through passthru().
I know that the PHP manual says for chmod that the command expects only three octal digits, but I read also this stackoverflow question and it looks like the manual contains obsolete information and others can affect the SGID. Besides, it should not affect the passthru() versions, should it? The same stackoverflow question mentions something about chmod() needing to be "the last to be called" after chown() and chgrp(), but I am not using any of those.
What am I doing wrong?
In the end, the only way I could find to obtain the permissions I need is to profit of the correct behaviour of mkdir() and avoid calling chmod() which appears to reset the SGID bit no matter what. The only way I can think of doing this is to change the umask with umask():
$myumask = umask(2);
mkdir("/mydir/test6");
umask($myumask);
This appears to work fine:
4 drwxrwsr-x 2 www-data mygroup 4096 Oct 9 14:22 test6
This leaves me with the issue raised in the note of https://www.php.net/manual/en/function.umask.php: that all threads of a multithreaded webserver share the same umask, obviously leading to undesired and unpredictable behaviour. Luckily, in my case, I could ascertain that all directory creations are done in a monothreaded context (essentially, on the first test run of a script) and thus I feel safe. Hence, this is a useful workaround but not a general solution.
Is this running on a web server, or just as a CLI script? If CLI, user or root?
Also, why directories? SGID is used on program files, to allow a user to run a program/script as another user, like "sudo". Have you tried testing this on files rather than directories?
Related
I'm having a problem with getting a shell command to clear a specific product cache because the permissions in the cache folder are strictly restricted to www-data. For example, folder /var/cache/mage--a files are like these:
-rw------- 1 www-data www-data 7646 Mar 4 11:20 mage---c54_PRODUCT_CACHE_123
-rw------- 1 www-data www-data 184 Mar 4 11:20 mage---internal-metadatas---c54_PRODUCT_CACHE_123
So when the shell command runs, it calls Mage::app()->cleanCache('PRODUCT_CACHE_123'), which triggers down to _fileGetContents function defined in lib/Zend/Cache/Backend/File.php and it's unable to open the meta file in /var/cache/mage--a due to the permissions listed above.
Does anyone have a suggested fix for this?
I ended up using Redis for caches instead. This helped solve the problem as i don't need to set up file permissions for the cache folder anymore.
I have this simple code
mkdir('Users', 0775);
but when I go into my directory this is what I see
drwxr-xr-x 4 www-data www-data 1M Jun 11 16:30 Users
I expect to see
drwxrwxr-x 4 www-data www-data 1M Jun 11 16:30 Users
What could be messing up my permissions?
umask might be affecting your script. You can try to temporarily modify it via PHP: http://php.net/manual/en/function.umask.php
$old = umask(0);
mkdir('Users', 0775);
umask($old);
You could also try to change the permissions after the directory is created:
mkdir('Users');
chmod('Users', 0775);
… which is recommended on multithreaded web servers.
If you use
mkdir('Users')
chmod('Users', 0775)
That could solve your problem, however, keep in mind that mode is ignored on windows, but you can change the permissions with chmod. See mode is ignored on Windows.
I have a PHP script on my web server that uses a private key so my directory structure looks like this
-- script.php
-- private-key
-- lib/
What permissions should I set my private-key file too so that it can be used by script.php but not by anyone else. I've tried setting the permission as 664, is that correct?
Setting your permissions as 664 means that anyone can read the file. For a private key file, you should at least remove last 4 (660). I would probably make the owner the user that is running script.php and then set the permissions to 400.
If your file permissions look something like this:
user#host:~$ ls -l
-rwxr-xr-x 3 apache apache 4096 Jan 6 15:32 script.php
-rwxr-xr-x 2 apache apache 4096 Dec 13 11:25 private-key
drwxr-xr-x 14 apache apache 4096 Dec 13 15:03 lib/
Then something like this would be more secure:
chown apache:apache private-key
chmod 400 private-key
This will make it so the only user that can read the file is the apache user.
To make life a little easier for you, you might want to add a group and fiddle with the group permissions so that your user can edit the file as well.
I have searched the web for possible solutions but it seems to make me more and more stuck.
Once a file is created by PHP that file cannot be deleted, other files in the same directory can be deleted.
If a directory is created by PHP the whole directory cannot be used by FTP, I can see the files in that directory, but cannot delete, modify or upload to this directory.
I do see a lot of these questions here but mostly they involve permission problems, in this case all permissions, umask and attributes are the same as a file that can be deleted on through FTP.
I also thought it might be that the file is in use, however this is not the case, (lsof results empty, killing apache and nginx, which normally releases the file did not help either).
The server is running PLESK 11.0.9
FTP server is ProFTPD.
Is this some limitation that is caused by PHP, PLESK or is it in ProFTPD itself?
I hope you can help me with it, as I'm quite getting frustrated.
If you have any questions that might help in answering this question, feel free to ask :).
[ EDIT ]
Some more details why I think it is not a permission problem.
[root#srv domains]# lsattr
-------------e- ./test
-------------e- ./test2
[root#srv domains]# ls -als
total 32
4 drwxrwxrwx. 7 user0041 psacln 4096 Mar 22 06:41 .
4 drwxr-x---. 12 user0041 psaserv 4096 Mar 22 07:28 ..
4 drwxrwxrwx. 2 user0041 psacln 4096 Mar 22 06:30 test
4 drwxrwxrwx. 2 user0041 psacln 4096 Mar 22 06:34 test2
[root#srv domains]# lsof test
[root#srv domains]#
I cannot do anything with the directory test through ftp, but I can do anything with the directory test2
test has been created with mkdir command of php, while test2 has been created through ssh, and has been chowned to the right user.
Also I removed some unrelated entries from the outputs
More information about the user proftpd runs when logged in:
[root#srv domains]# ps aux | grep ftp
10000 8508 0.5 0.0 152192 3684 ? SNs 08:37 0:00 proftpd: user0041 - x: IDLE
[root#srv domains]# cat /etc/passwd | grep 10000
user0041:x:10000:505::/var/www/vhosts/domain.ltd:/bin/false
For privacy matters I have changed the domain name to domain.ltd.
Looks like your FTP user doesn't have permissions to delete anything created by the user that PHP is running as. You'll need to contact your hosting company regarding this.
most likely a user permission problem. but it could help if you posted some use case with more details describing what exactly are you doing (file names,process,...)
Is there a way to set php running under apache to create folders with the folder owned by the owner of the program that creates it instead of being owned by apache?
Using word press it creates new folders to upload into but these are owned by apache.apache and not by the site that they are running in. This also happens using ostickets. For now we have to SSH into the server and chmod the folder, but it would seem there would be a setting somewhere to override the ownership outside of any program that does it.
Safe_mode is turn on on your server. The function mkdir() creates folder with owner ("apache", "none", ..) that different of the current script owner. And scripts couldn't upload (move, copy) files into that folder with another owner (that is not like current script owner).
Disable safe_mode and that would be work.
See http://php.net/manual/en/features.safe-mode.php for details.
P.S. With enable safe_mode you can't use chmod() function in php.
Another way is to put the apache user and the "customer users" in a new group. Additional the directory should use the sticky bit SGID so each new file got the group assignment to this new group. This way the webserver and the "customer users" can work with the files without any problems
[17:57] progman#proglap /tmp/test $ ls -al /tmp/test
total 9
drwxrwsr-x 2 root users 48 Apr 1 17:55 .
drwxrwxrwt 36 root root 9264 Apr 1 17:53 ..
As you see the directory got the stick bit SGID and the owner is the "users" group in which I (progman) am. No if another user adds a file the group automatically get set to this group
[17:55] proglap ~ # touch /tmp/test/x
This is executed from root. Now we get:
[17:57] progman#proglap /tmp/test $ ls -la /tmp/test
total 9
drwxrwsr-x 2 root users 72 Apr 1 17:59 .
drwxrwxrwt 36 root root 9264 Apr 1 17:53 ..
-rw-r--r-- 1 root users 0 Apr 1 17:59 x
As you see the added file is from root, but the group is set to users and this way I can remove it
[18:00] progman#proglap /tmp/test $ rm x
rm: remove write-protected regular empty file `x'? y
[18:01] progman#proglap /tmp/test $ ls -la /tmp/test
total 9
drwxrwsr-x 2 root users 48 Apr 1 18:01 .
drwxrwxrwt 36 root root 9264 Apr 1 17:53 ..
Keep in mind that you still need to change the chmod if you want to edit the file as rw-r--r-- is just group read access. But changing the chmod, maybe even working with umask, is better than dealing with root-access and using chown.
Not directly, no. You can't "give away" ownership of a file to another user, unless you're root. You could investigate using the "AssignUserID" apache directive to force that particular vhost to run as a particular user/group. With that Apache/PHP would create any files with the appropriate ownership
Check out PHP chown() function