What is the purpose of using umask(0); in php?
I have seen this a few times, and cant figure out from the documentation what it precisely does.
Can someone explain this and when it would be useful to use?
Setting the umask to 0000 (or just 0) means that newly created files or directories created will have no privileges initially revoked. In other words, a umask of zero will cause all files to be created as 0666 or world-writable. Directories created while umask is 0 will be 0777.
Usually when you see umask(0) it should be followed directly by a call to chmod() to explicitly set the permissions needed on the newly created file or directory to something other than world-writable.
Use caution when setting the umask to zero! This can be dangerous and is mostly only useful for creating files which must be later written to by the web server, when the web server runs as a different user that a "real" user who will also need to be able to modify the files created by the web server. Otherwise, the system's default umask is likely to be something like 0022, writable by the file owner but not others. In that case, if you logged into the machine under a normal user account, the file created by the web server under PHP would not be writable by you.
Rather than creating world-writable files, it is generally a better idea to manage the directories the web server is writing to more explicitly. If the files created inside a directory should have certain group permissions, it may be advisable to set the sgid bit on the directory so new files inside it inherit group ownership. Users needing access to the file should be members of the group having access to it. This is much more secure than creating world-readable, world-writable files.
php > umask(0);
// Should get created as 666
php > touch('file1.txt');
// "2" perms revoked from group, others, gets created as 644
php > umask(022);
php > touch('file2.txt');
// All revoked (2,4) from group, others, gets created as 600
php > umask(066);
php > touch('file3.txt');
-rw-rw-rw- 1 me group 0 Aug 24 15:34 file1.txt
-rw-r--r-- 1 me group 0 Aug 24 15:35 file2.txt
-rw------- 1 me group 0 Aug 24 15:37 file3.txt
The umask is basically a default setting for creating files. In essence it is safer to turn your default chmod on and then write the file than write it and then chmod it (some say). At the end of the day the time between finishing writing the file and running chmod would be miliseconds at best so I am sceptical about this.
umask() sets PHP's umask to mask & 0777 and returns the old umask
It basically sets default write permissions to whatever you put in on OS's such as Linux and then returns the old one so you can reset it back. This applies to the PHP process itself.
The comments on the doc page: http://php.net/manual/en/function.umask.php will clarify by example.
Related
I have been trying to change the permissions of new session files. According to this page, I need to change the mode in the session_save_path configuration in the php.ini file. I have changed it to 0777, the default is 0600. New session files are still being created with 0600 permissions. I have checked, the correct php.ini is loaded and the changes are saved. I have configured it like: 0;0777;/var/lib/php/sessions (N;MODE;/path). Can someone explain to me why the files are still created with 0600 permissions, while I have configured it to 0777?
The files are stored in /var/lib/php/sessions and I'm using Codeigniter.
The /var/lib/php/sessions/ directory typically has the "sticky" bit set on it -
drwx-wx-wt 2 root root 4096 Oct 15 11:21 /var/lib/php/sessions/
This is done via chmod 1733. Remember that using the setuid/setgid/sticky bits on a directory effect how files are created (default owner/group and permissions) in that directory and any sub-directory, regardless of system umask values, etc.
From this page - http://www.filepermissions.com/articles/sticky-bit-suid-and-sgid - which is part of a 3 article series on *nix file permissions which is pretty good.
A Sticky Bit, is a special setting within file permissions that helps
limit access beyond what normal file permissions are capable of. In
short, a Sticky Bit ensures only the owner of the file / directory is
able to delete or rename the file. However it should be noted that
root is able to edit and delete the file as well.
With the mode of 1733 the session data files can't be read by others on the system. This is a Good Thing.
Why do you want world readable session storage?
Edit -
If you really want to break it, create a new directory w/ appropriate permissions and change the session storage path to use that directory. Note that there may be an internal check in PHP that will make it refuse to store session data in a place it considers "insecure", much like SSH refusing to use keys w/ insecure permissions.
When using the move_uploaded_file() function in PHP I get the error:
Warning: move_uploaded_file(...): failed to open stream: Permission denied in ...
On my server I have the public_html permissions like:
drwxr-sr-x 7 user www-data 4096 Apr 27 17:48 public_html
Which is recursively through-out the directory.
Have you got any ideas why this might not be working? Or what I can do to help me find out why this is not working.
The system
The server is actually a cluster where the files are on a NAS and the php is on the cluster. I am performing all the permission commands on the device of the NAS as that is where the user FTP's to.
User www-data can not write to public_html directory. Use chmod on your public_html to give www-data write permission:
chmod 775 public_html -R
First off, the SUID and SGID only make sense when used with executable files.
From http://www.codecoffee.com/tipsforlinux/articles/028.html :
SUID (Set User ID) Bit
[...] in case I have an application whose owner is ' root ' and it has its SUID bit set, then when I run this application as a normal user, that application would still run as root. Since the SUID bit tells Linux that the the User ID root is set for this application and whenever this application executes it must execute as if root was executing it (since root owns this file)
SGID (Set Group ID) bit
Just like SUID, setting the SGID bit for a file sets your group ID to the file's group while the file is executing. IT is really useful in case you have a real multi-user setup where users access each others files. As a single homeuser I haven't really found a lot of use for SGID. But the basic concept is the same as the SUID, the files whose SGID bit are set would be used as if they belong to that group rather than to that user alone.
So if none of your web files need to be executed as a normal process, it is best to leave the SGID alone.
Finally if you didn't change your web server's security context, it (most probably, as you didn't mention any paths) tries to move a file which is located in a directory www-data can only read. To move a file you need write access to the directories where the file is and will be moved to. So www-data should be given write access to
the directory where the file lands in the first place (by default: /tmp, in which case nothing's to be done)
the destination directory, where it is intended to be moved to.
I've always used the following codes to create a folder on a Apache server but recently on one of the server I've got permission denied error.
if(!is_dir('img/user/'.$id))
{
mkdir('img/user/'.$id, 0777, true);
chmod('img/user/'.$id, 0777);
}
On internet I found that to upload directory for httpd it needs to have write permissions like this:
drwxrwxrwx 2 user staff 512 Jan 07 12:32 uploads/
Where is this permission set? I do not direct access to the server. Is there any alternatively?
You never want to set permissions to be world writable if you can avoid it, or even readable for that matter. 0770 would be a better option, if still a little broad. The main point is that the folder(s) in question need to be writable by the webserver user. For instance, on many webhosts apache will be run by the user nobody, so a more appropriate permission would look like this:
drwxrwx--- 2 nobody nobody 512 Jan 07 12:32 uploads/
Now, there is a problem if you can't get direct access to set permissions yourself except through PHP, because some web hosts will disallow your ability to run chmod or other permissions or ownership modifications from within PHP. That said, if you're using cPanel (and likely other hosting systems do this as well) you can use the online file manager to accomplish what you want by browsing to the appropriate directory and using change permissions located at the top of the page.
So, ultimately, here's what you need: If you need to be able to create a directory in a particular place, you need to make sure that place is writable by the web server. In your example, that means that you need to set appropriate permissions on img/user first before you attempt to create img/user/$id. That means that img/user either must have permissions of 0770 and must be owned by nobody:nobody (either user or group would work in this context, you don't need both), or it must have permissions of 0777. Then, when you create your specific user directory, you can do it like so:
if(!is_dir('img/user/'.$id))
{
mkdir('img/user/'.$id, 0770, true);
}
... because it will already be owned by the appropriate user and you'll already have write access to it simply because your webserver created it in the first place.
If you can't find a non-PHP way to do it, then you'll have to get your webhost to help.
PHP runs as user: www-data in group: www-data (Ubuntu) or something else depending of the server OS.
You can ask your provider to set the right access on maps / files if you cannot do it yourself by FTP.
Scratching my head on this one, seems so basic.
I've got a PHP based content management system for our website written by a contractor. One feature is the ability to upload images to be displayed in various places on the website (like a product gallery). All such uploaded images are stored in a particular directory called "attachments".
drwxrwsr-x 4 www ftpusers 4096 Oct 10 14:47 attachments
As you can see I've got the setgid bit set on that dir so that any files written will have the group that users (like FTP user) who need access to those files will able to modify/overwrite them. I've set the umask for Apache so that it will write files as group writable.
When I try this with ANY user in the system by creating a new file in that directory, it correctly inherits the group of the parent. When a new file is created through PHP running in Apache, it always has the apache.apache ownership. Apache seems to be ignoring the setgid bit, which I didn't think it could do as this was done by the file system. Here is one file I uploaded:
-rw-rw-r-- 1 apache apache 30536 Oct 10 14:43 209
I can't test as the apache user directly as it doesn't have a login shell specified (for obvious security reasons).
I can get the same permissions capability by adding the ftpusers group to the apache group, but this doesn't seem wise from a security perspective.
I did find one thing that seemed like it might be related - php safe mode, which I've verified is off in /etc/php.ini, although I'm not positive I found the php.ini file that mod_php in apache is using. The php script is using move_uploaded_file(); as far as I can tell, nothing fancy with permissions is being done in the php code.
My best guess would be that this is an intentional limitations for security, but I can't find anything that seems to indicate that is the case.
Running CentOS 5.6 with Apache 2.2.17 and php 5.2.16.
Anyone have a clue?
When you upload a file it is created in the dir specified by the PHP's "upload_tmp_dir" setting. Then move_uploaded_file() moves it to your target dir. It maintains the permissions given to it upon creation and not those of the target directory you move the file to.
So you want the tmp dir to have the permissions you want, basically those you've given to your target dir. Then it will be created with the setgid having effect and the move will keep them.
IIRC "upload_tmp_dir" is not available in .htaccess so if you cannot change this setting or the permissions given to the dir then you will need to do it another way.
I have a script (Joomla) that creates files and directories on the server. The problem is that it creates them under owner 99 99 (nobody) and after I can't delete or modify them by FTP without the help of the server admin.
I think that is move_uploaded_file function of php.
Is there any solution of this problem by the WHM or by the server admin? Can I modify the default owner in ftp?
What happens is the HTTP server is ran by a user called "nobody", and your FTP user is another one. When the upload occurs, the HTTP server creates the file under its username, and your FTP user has no permission to write (or delete) these files.
The easiest way to fix this (but not really secure) is to add both users in a same group, and change the file permissions to allow users of the same group to read/write on these files.
Your admin should take care of it, but you'll have to call chmod() to change the permissions of your uploaded files.
Explaining it better:
The linux/unix file permissions are composed by permissions of user (u), group (g) and others (o).
I'll only cover 3 types of file permisions here, which are read (r), write (w) and execute (x). So, you end up having something like this:
-rw-rw---x 1 jweyrich staff 12288 Oct 24 00:22 avatar.png
The first rw- is the permission (read/write) of the USER that owns the file (jweyrich).
The second rw- is the permission (read/write) of the GROUP that owns the file (staff).
The --x at the end are the permissions (execute) of the OTHERS users..
Your PHP scripts run as "nobody" user (and by, let's say, "nobody" group), so every file you create from your PHP will be owned by the "nobody" user (and his group). A user can be part of one or more groups.
To solve the permission problem, your FTP user and the "nobody" must be in a common group, let's say the admin put your user in the "nobody".
Once they're in the same group, your PHP script has to give "rw" (read/write) permissions to the "nobody" group members. To do so:
chmod("path_to_your_file", 0770);
The 0770 is equivalent to "u+rwx,g+rwx,o-rwx" , which I explain here:
u+rwx = for user (owner, which is "nobody"), give read/write/execute permissions
u+rwx = for group (which is also "nobody"), give read/write/execute permissions
o-rxw = for others, remove the read/write/execute permissions
After that, your FTP user, which is now part of the "nobody" group, will have read//write access to the uploaded files, and thus can also delete the files. It would look like this:
-rwxrwx--- 1 nobody nobody 12288 Oct 24 00:22 avatar.png
It's not the ideal introduction to unix file permissions, but I hope this helps.
The user that PHP runs under - nobody - is set by the system administrator. There's nothing you can do about that.
You can try chown() to change the file's owner if you know the FTP user's ID. Usually though, you will not be allowed to do this from within PHP.
Depending on the group situation on the server, it could be that if you use chmod to change the file's access rights after the file has been uploaded, the FTP account can access the file:
Try this first:
chmod($uploaded_file, 0660); // owner+group read+write
If that doesn't work, try this:
chmod($uploaded_file, 0666); // global read+write
one of these should make the file usable by the FTP account.
The 0666 is highly discouraged because other users on the server could write into your files, but in some configurations, it's the only way to get going.