Working With Permissions In PHP, Part 2

A Note on Permissions and PHP

Before I begin to discuss the PHP permission functions, I will explain some common permission-related problems which occur with PHP scripts. Like all applications in a Unix environment, PHP programs are run on behalf of a particular user. If a PHP script is executed from the command line (for instance, as a shell script), it will run with the permissions of the user who started the script. For web servers, however, your PHP scripts run as the same user as the web server runs as. Under most system configurations, web servers run as the user nobody, which has minimal permissions to access the file system.

Although it can be more difficult to work under this situation at times, it’s strongly recommended that PHP never be ran via a web server in any other manner for security reasons. A much more reasonable solution is to create directories where PHP will be accessing files and assign it to the same group to which the PHP script belongs.

Permissions with PHP

In my last column, I discussed three separate commands to manipulate Unix file permissions. The first of these commands was chown, which had to be run by a super-user (such as root) and changes the owner of a file. The second command, chgrp, changes the group to which a particular file belongs, as long as the user running chgrp is a member of the new group. Finally, the last command is chmod, which allows any user to modify the permissions of a file owned by the user.

In PHP, these three commands (chown, chgrp, and chmod) have almost direct counterparts in the form of PHP functions. For instance, where Unix has the chown command, PHP has a chown() function with the following syntax:

chown($filename, $newuser)

$filename refers to the file that is being modified, and $newuser is the username of the new owner. When executed this function returns a boolean value which indicates whether PHP was successful in changing the owner of the file. As with the Unix chown command, the chown() function cannot be successfully executed by a script unless the script is running with super-user privileges.

Like the chown command, the chgrp command also has a counterpart in the chgrp() PHP function. Their syntax is almost identical:

chgrp($filename, $newgroup)

The $filename parameter is the file to modify and $newgroup is the name of the group to make the file a member of. This function also returns a boolean value indicating the success or failure of the group change. Unlike chown(), the chgrp() function can be used to change the group of a file as long as the group that PHP belongs to is also a member of that group.

The following script, which illustrates the use of these functions, brings together the PHP directory object discussed in a previous article with today’s discussion. It attempts to change the owner of all the files in the /tmp/ directory to php and the group of all of the files to phpgroup:

<?php $dir = dir(“/tmp/”); while(($file = $dir->read()) !== false) { chown($filename, “php”); chgrp($filename, “phpgroup”); } $dir->close(); ?>

The third and final command is chmod. chmod sets the permission values for the three permission levels (user, group, and global) via a numeric value representing the desired permissions. A complete list of the permissions, their associated numeric values, and their use, can be found in my last column. In PHP, changing permission values for a file is done through the chmod() function with the following syntax:

chmod($filename, $permissions)

Again, $filename represents the file to modify and $permissions represents the new permission value. These numbers are not standard decimal values. The Unix permission system is based on numeric values rooted in base 8 (octal) rather than the standard decimal base 10. Hence, when passing a value to $permissions it is necessary to prefix a leading zero to the value to mark it as an octal value. To demonstrate this function in a more practical application, the following short script attempts to open a file for reading. If the initial attempt to open the file for reading fails, PHP will attempt to modify the permissions of the file and open the file again:

<?php $fr = fopen(“myfile.txt”, ‘r’); if(!$fr) { /* Must be 0444 (octal), NOT just 444 */ if(!chmod(“myfile.txt”, 0444)) { echo “Error — couldn’t open myfile.txt for reading!”; exit; } else { $fr = fopen(“myfile.txt”, ‘r’); } } $myvalue = fgets($fr, 1024); fclose($fr); ?>

As should be obvious from this short program, because the three system calls demonstrated here all return a value indicating their success or failure, these results should always be checked. Assuming that system calls always succeed is a recipe for disaster

We’re Done!

There is much more to permissions and the file system than can be discussed here. If you have questions, consult the PHP Manual.