PHP, "Permissions", and "Safe Mode"

PHP's Mode of Operation

How PHP is set up on a given server can vary considerably, and is apparently--to judge by the available material on the subject--considered complex. It isn't as bad as all that, provided one doesn't have to first dig out from under a rubble-heap of misunderstanding and false information. Let's try to get it clear here for once and for all, then deal with what you can do about your own situation (I assume you're reading this because yours is a setup that is problematic for the package and, on at install attempt, produced a Warning! message).

There are two different relevant properties that a directory or file on your host server can have (quite aside from its name and location): "permissions" and "ownership". The two are closely related but distinct.

"Ownership" reflects who created the file or directory on that server: that entity is its "owner". Every user on a shared server has a unique UID (User ID), and the server software keeps track of which things were made by which UID ("making" includes uploading): each file and directory has a "stamp" recording its ownership.

"Permissions" exist only on UNIX-based (including Linux-based) servers. UNIX systems are all, from the ground up, designed as multi-user systems, and so the operating system has a way to sort out who can do what to what files or directories.

Let's elaborate on these things, then apply that knowledge to PHP operation.

What "Permissions" Are

(If you already have a decent grasp of file permissions on UNIX-type systems, just skip down to the next heading on this page.)

On UNIX-type systems--which includes most servers--files and directories each have an attribute called "permissions". There are three kinds of actions for which there are distinct permissions, the three forming a set:

  • Read: the ability to read the file.

  • Write: the ability to write to (or delete) the file.

  • eXecute: for files, the ability to execute it if it is an executable; for directories, the ability to change to (enter) that directory or to get any information on files in it.

Moreover, there are separate sets of permissions for each of three kinds of user: the "owner" of the file (as previously discussed), some "group" of users, to whom the owner must belong; and everyone in the known universe. This complicated system is integral to and necessary for security reasons on inherently multi-user like *NIX systems. But managing it can be a colossal pain in the elbow for individual users.

(We will not deal much here with "groups"; a "group" is a defined set of several users--typically related in some way, such as all working on some one project--of whom the owner of the file is one.)

First, let me explain briefly how you usually see and set permissions on a server: normally, you use your ftp software, for both seeing and changing. If you don't already know how to do that, poke about in your ftp software's options, especially in the "File" or "View" areas, looking for words like "permissions" or "access rights". You should soon find how to display those things.

Permissions are commonly displayed in one of two forms, as a 9-character alpha string or as a three- or four-digit code. The alpha form is easiest to read and understand; it will look something like rwxr-xr--, where first three characters are your access rights (in this example, read, write, and execute), the second three are your group's rights (here read and execute, with a hyphen signifying the "write" permission not possessed), and the last three are the rights of "everyone", who here has read-only permissions.

The numeric form is not much harder (if it is four digits, the leading one is zero and can be ignored). Here, the three digits each encode the permissions of one of the three groups, again in left-to-right order as you--your group--everyone. Each of the numerals is actually an octal (base-8) number whose value signifies the three bits that make it up and which signify the permissions:

0644 (or just 644) = 110 100 100 in binary

In this example, the first pattern is thus READ-WRITE-noexecute, and the other two are each READ-nowrite-noexecute. Simple, actually.

Your ftp software can not only display those permissions, it can change them for you. You'll need to discover how for yourself, based on your particular ftp setup, but it's probably in the Files menus. (Note that you can, as logic suggests, only change permissions on files or directories for which you have write access! But files that you upload and files or directories that you create are owned by you, and should default at their creation to giving you, their owner, at least read and write permissions.)

PHP and Permissions

The central fact to grasp is that to your host's server software and operating system, "PHP" is a distinct "user". It is a process, a piece of software executing, using your PHP "scripts" as its input. The crucial corollary is that to the host PHP is not you--even though the script files it is running (or trying to run) were created--on that server--by you and are "owned" permissions-wise by you. To the server, PHP is just another user, and one who is neither you, nor--almost surely--a user in your "group". (On most servers, the PHP process is explicitly identified as "nobody", or sometimes as "www", whereas you are typically identified by your name.)

Thus, in the simplest state of affairs, PHP, in the course of running any scripts you have uploaded, has the same file permissions as "everybody". If you want PHP to be able to make directories or read files or write files or do other such file- and directory-related things, you have to--in this simple scenario--make sure that you have set permissions appropriately for "everyone" to be able to do the needed things.

(Many PHP scripts do not need to make or delete or modify files or directories--they act on input fed them by the HTTP URL request and deliver output direct to the calling browser--and, for such scripts, file permissions are thus irrelevant.)

But affairs are not usually as simple as just described. There are two factors that can change the simplicity of the situation: PHP's dire "safe mode", which much complicates things, and "cgi wrappers", which much simplify things.

PHP and "Safe Mode"

PHP'S "safe mode" is a bad attempted solution for some security concerns. That is not my opinion, it is that of those who designed PHP; in the online PHP Manual itself, the very first statement under "safe mode" is--

The PHP safe mode is an attempt to solve the shared-server security problem. It is architecturally incorrect to try to solve this problem at the PHP level . . . .

But they did anyway, faute de mieux--and thereby created a colossal pain in the elbow for PHP users. Many hosts seem of the opinion that without "safe mode" on Satan would seize control of their servers in microseconds; many more, who certainly sound like they know their apples (and their servers) regard safe mode as a pathetic joke that serves mainly to complicate the lives of legitimate users, but which is as Kleenex to dedicated hackers. Be all that as it may, "safe mode" is a common and painful fact of server life.

The web is chock-full of messages from people asking for PHP "workarounds" for safe mode, which shows just how wonderfully popular it is with users. ("You mean I created a directory I can't write to?" as one put it.)

The crux is set forth in this quotation from the PHP Manual: "When safe_mode is on, PHP checks to see if the owner of the current script matches the owner of the file to be operated on by a file function." That doesn't sound so terrible, till you recall that, to the server, PHP ain't you, and you ain't PHP.

This goes beyond mere "permissions", and into identity questions: who "owns" a given file? It is not enough to give the whole wide world permission to do things to or with a file: PHP in Safe Mode goes beyond, and says "If you didn't make it, you can't break it--I don't care if whoever did make it says you can, nyah, nyah, so there." And it is the phantom "nobody" who wants to do things with what the system calls--since you ftp-uploaded them--your files. That part is right: it's referring to a PHP process that is running scripts you own as "nobody" that is the pointed barb of the shafting you're getting. The ever-dreaded "Permission denied" error shows.

Let me say this again, because there is so much misinformation propagated on the subject: with PHP's "safe mode" on, appropriate permissions are a necessary but not sufficient condition for file operations.

What in reality this boils down to is that file and subdirectory operations are nearly impossible for PHP with "safe mode" on. If you upload a data file, none of your PHP scripts can operate on it, no matter how complete the permissions--even a full 0777--because you own the file, and, again, you're not PHP and PHP is not you.

One might think that a PHP script could create all its own directories and data files (even other PHP scripts) from scratch and then operate on them as their owner, but that is trying to pull yourself up by your bootstraps: to make any initial directories or files whatever, the script would first have to be able to operate within (have eXecute rights for) some one directory. If you, not PHP, made all your directories (always the initial case), there is not--cannot be--any such directory within which PHP can operate, nor can PHP be used make one. If "safe mode" is on, no PHP script that needs to work with files can function: that is why the web is chock-full of moans and whines from frustrated would-be users of so many php-based packages. (Google it up for yourself.)

The worst of it is this: most hosts who set PHP's "safe mode" On by default do not allow you to turn it Off. (PHP has internal functions that nominally can turn "safe mode" off, but the server host can impose over-rides that forbid those functions to operate.) That makes no less, nor more, sense than "safe mode" itself: if a host is sufficiently paranoid to believe that "safe mode" actually accomplishes something useful, that host will not want users to be able to decide for themselves on the matter.

There is one possibility that I am unable to test, because my host is not among the number who force Safe Mode on their users. That possibility is to place a PHP "safe-mode-off" command in one's .htaccess file:

php_flag safe_mode off

My belief, which is not certain, is that your host still has to have set things up so that you are empowered to affect Safe Mode in this way, but it has been reported to have worked when operations from within a PHP script did not.

The PHP Manual (for system installers, not PHP users) says on this point When [running] PHP as an Apache module, you can also change the configuration settings using directives in Apache configuration files and .htaccess files (You will need "AllowOverride Options" or "AllowOverride All" privileges) If your host has defaulted Safe Mode to On but left the appropriate Overrides in effect, the .htaccess file line above should work. (It may not work from within scripts because by the time PHP reads in a script and starts to run it, it is probably too late to change "safe mode"--the "safe-mode-on" state will block such action from within a script, whereas the .htaccess line is read in before PHP starts to work with the script.

If you are getting the feeling that all this is more complication than seems justified, you are scarcely alone. Fortunately, for all the grief that the ill-named "safe mode" brings (as one user put it, "I guess it's 'safe' because you can't do anything at all under it"), there is a remedy offered by many hosts that not only cleans up the safe-mode mess, but even drastically simplifies basic "permissions" issues. That remedy is a "cgi-bin wrapper" for PHP.

PHP and "Wrappers"

A "wrapper" is a process that "wraps around" another process. In particular, a cgi-bin wrapper for PHP "wraps around" PHP and runs PHP as a sort of sub-component of itself. What is accomplished by that is two things: one, the wrapper can do some security-related things that are not our concern here (but which accomplish much or perhaps more of what "safe mode" was meant for); but two, a wrapper makes PHP look to the server software like it's whoever is the "owner" of the actual PHP script it is running. That cuts the Gordian knot of "safe mode" and "permissions" at one stroke.

This is critical information, so let me restate it: when you "run" a PHP script on a shared server on which cgi-bin wrapping of PHP is enabled, the old bugaboo is gone: now, PHP is you (assuming that "you" own--created or uploaded--the script PHP is running. That is PHP Heaven. You do not need to set "everyone" permissions artificially high, because PHP is you, and thus has all your permissions--and "safe mode" is immaterial because PHP is you, and thus is the "owner" of any files or directories you (or it) made or make.

It is hard to see why not every host server offers cgi-bin PHP wrappers, but some do not. And many that do offer them do not supply them by default: you have to ask if they're available and, if so, for them to be enabled (or for instructions on what you have to do to enable them).

It is my firm personal belief that if your host cannot supply you with a cgi wrapper for PHP, and yet insists on imposing "Safe Mode" on you, you really, really should change hosts--not just for that alone, though it is a good reason, but because it says a lot about your host and that host's abilities and attitudes. I have no incentive--I am not a "reseller" of host services--but if you find you are in that situation, I much recommend Pair Networks, who, not incidentally, were the first host to offer a cgi-bin wrapper for PHP, and who make switching hosts easy (and often run offers with discount incentives for switching).

Practical PHP: What You Can and Should Do

I assume that you are reading this docfile because when you tried to install this package, the installer gave you back a message along the lines of:

Warning! This package will apparently not work for you!

This script has detected that PHP "Safe Mode" is On, but you do not seem to have cgi wrapping of PHP in place (the "interface" read was --------------, not "CGI".

(Where ----------- will probably be Apache.)

So where do you go from there?

There are two routes onward--one to getting "safe mode" turned Off, and the other to getting a cgi-bin wrapper in place--and you can try either or, better, both.

Getting PHP Wrappers

If the installer reported that your interface is not CGI, the first step is to see if cgi wrappers are available from your host, and the easiest way to do that is to ask--by email or, better, by telephone. Make sure that your host understands exactly what you're asking: "Is there any way to enable a cgi-bin 'wrapper' for PHP on my site?"

If the answer is "Yes", get very exact instructions on what you need to do (if anything, and there probably will be some stuff) to enable it. (On my host, I needed to modify my .htaccess file, create a local cgi-bin directory, and put a wrapper file--supplied by my host--into that directory.) Do whatever things you are told to, then re-try the installer. If it runs, you are home free, not only for this package but for any php-based package (and there are many useful ones, of all sorts, out there). And if the installer then works, you can abandon this docfile and return to the Installation docfile.

(In fact, given wrapped PHP, Safe Mode becomes an antique, and as the number of hosts offering wrapped cgi increases--with many not bothering to impose "Safe Mode" on wrapped users--there is a real possibility that "Safe Mode" will eventually disappear from PHP--some PHP experts have been advocating its removal for a while now.)

If your host cannot enable cgi wrappers for PHP, remember my earlier advice about switching hosts and Pair Networks. But, for now at least, you can also try getting "safe mode" turned off.

Turning Off PHP "Safe Mode"

First, explicitly ask your host if there is any way in which PHP's "safe mode" can be turned off for your site. If the answer is "Yes", well, there you are. The package automatically sets its file and directory permissions to give "everyone" complete access (which is no material dimunition in safety, as only someone logged on to your site as you can access those files at all anyway). With "safe mode" off, you are able to proceed, if in a less-than-ideal way (ideal is cgi-wrapped), and can return to the Installation docfile.

If your host says "No", that is probably the end, but you can try one last thing, that line cited earlier, in your .htaccess file. Just download your current .htaccess file, make a safety backup (named, say, BKUP.htaccess), edit into .htaccess the line--

php_flag safe_mode off

--upload the modified file (as an ASCII transfer), and try the installer again. You might just get lucky through a backdoor your host doesn't realize is open. (Which would be yet another incentive to leave that host!)

And in the End . . . .

If none of that will get the installer to run past its Warning! stop, well, I'm sorry, this package will not work for you. Delete anything you put up on your server (including the install directory) and that's that.

But, in that case (and at the risk of sounding like a broken record), you really, really should be considering leaving your present host. This is not the seven arcana of the Kaballah: running PHP in a way that allows file operations is a pretty basic ability, and if your host cannot supply you with that ability, then that host is (to borrow Lord Kelvin's words) "of a meagre and unsatisfactory kind."

If you have these, or any, problems with this package and want to talk about it with me, email or, better, telephone me and let's talk it over and see what we can do together. My email address is, and my toll-free line--please call only between 1 p.m. and 10 p.m. Pacific Time--is 1 (800) 995-4080. My name is Eric Walker.