apache file requests and parsing

0

I have just run into an interesting situation at work that shot to hell my understanding of how apache2 executes php files.

I was under the impression that apache2 would determine the correct file type and run it through the correct file parser. This would allow the parser to do the actual execution, and because of that it was my understanding that the php files being executed by apache only needed read rights.

example:

take a simple php file with 744 rights

#!/usr/bin/php
<?php
echo "test";
?>

executing that with ./test.php issues a permission denied.

but executing it with /usr/bin/php test.php works fine.

change the rights to 755 and it executes correctly with ./test.php

This seems to be the same thing that is happening when apache executes the file. it is returning a forbidden error.

so finally.. here comes the questions.

How does apache actually handle and pass off requests for files?

How does it hand the file to the correct parser?

Why does it need execute rights? Obviously the parser isnt only reading the file as I originally anticipated.

Be gentle please.. I THOUGHT I knew this stuff.

steve

Posted 2012-05-15T21:16:14.910

Reputation: 612

Who owns the file, you, root, or the Apache user (usually www-data)? – Breakthrough – 2012-05-15T21:41:59.413

Answers

1

1) The execute perms on the file mean nothing to apache. That's just for the kernel to know how to execute the file if you try to exec it (say, through the shell). As long as you have read perms where apache can read it, you're fine.

EDIT the read perms were the important thing - apache needs execute perms on the directories all the way up to the root. For a directory, execute means searchable, and apache needs search perms on the directory to look for the file.

2) Apache doesn't 'pass off' the files. It doesn't execute them. You have an embedded interpreter in apache that can handle PHP files. This happens within the apache process. It gets configured this way:

You add the module:

LoadModule php5_module        libexec/libphp5.so

The module is compiled/created to know how to deal with parsing php. It is linked with the php interpreter, and basically consists of glue code for PHP to talk to apache, in the manner apache expects. The PHP module specifically knows how to deal with two MIME types, application/x-httpd-php and application/x-httpd-php-source. So, now you have to tell apache how to connect php files to the module. This is typically done with:

<IfModule mod_php5.c>
   AddType application/x-httpd-php .php
   AddType application/x-httpd-php-source .phps
</IfModule>

So, now we told apache to pass .php files to the PHP processor. Is going by suffix the only way? No, you could configure any directories to have all PHP files, or the entire server. But this makes the most sense. Also, notice that we don't care about the shebang line (#!/usr/bin/php). We're configured for file extension only.

3) OK, so why do you have the forbidden error? I don't know. There are many reasons why this could be. Have you checked the error log? Do you have the proper perms on the filesystem directory, where the apache process can read dirs all the way up to root? Do you have the proper perms in the config files? I'd check the error logs.

SECOND EDIT

I think I understand your confusion...

There are two ways of generating dynamic content through apache. One is through an embedded interpreter, like PHP. Perl and python are also common embedded interpreters. The webserver has the interpreter loading into the httpd process, using a glue module (mod_php, mod_perl, etc). The code is not "executed" but it is loaded, parsed and interpreted within the httpd process.

The second way is through a CGI script. In this case, apache does execute the file. The glue in this case is environment variables (apache sets some flags) and possibly standard input to the script. To send back to apache, you send content on standard out, which apache adds light decorations and sends to the client, and you send errors on stderr, which apache appends to it's error_log. The CGI spec dictates the rules on how this "glue" works. In this case, you are executing a file, so the execute permissions on the file are important to apache.

CGI is less common than it used to be. The advantages of CGI are that it's an isolated process from the webserver. It can't cause any damage to it (well, as long as parses the output securely). The disadvantages are the isolation. I need to fork/exec for every run (though there are some schemes called fastCGI that help this). PHP (among some others) also has a different coding model, where you add a bit of code to HTML, instead of writing a huge script and pushing out HTML from there. This makes it easier for most people to write, which is a big part of why PHP is so popular on the web.

Rich Homolka

Posted 2012-05-15T21:16:14.910

Reputation: 27 121

That makes plenty of sense. What I don't understand is the forbidden error. permissions were 744 recursively through the directory. It did indeed need me to set it to 755 before it started functioning. – steve – 2012-05-15T21:50:50.810

1@steve If the DIRECTORY perms don't have execute bit, then there is a problem in 'searching' files. Then i could see your issue, apache couldn't find the file due to directory perms. The file perms only need to be readable. – Rich Homolka – 2012-05-15T21:57:19.003

@steve Ha, thanks, but not so sure about that. just been around for a while. I've been using apache since 1996 or so, possibly a bit earlier. Installing webservers in general since 1993. – Rich Homolka – 2012-05-15T22:14:40.060