12

I am looking for a way to use a PHP script to control access to resources in Apache. I want to have access control that does not depend on the target resource; i.e. it will work for html, files, other scripts and cgi programs, just as an "Allow from" or "Deny from" directive would do -- except using custom logic.

I've looked at several ways to try to manage this:

  1. Use an apache module like mod_auth_script (ok but this module is old and I assume does not scale well)
  2. Use FastCGI directive FastCgiAccessChecker
  3. Create my own apache module to invoke php and do whatever I need

Of these #2 looked most promising, and also most portable given the popularity of FastCGI. So, I managed to swap out the usual linux php module and get php working via fastcgi instead. It was harder than on Windows but got it to work eventually as an external server, i.e. using Apache directive

FastCGIExternalServer /var/www/html/thing -host 192.168.0.11:9000

and starting php daemon

php-cgi -q -b 192.168.0.11:9000 &

The trouble came in trying to find a way to invoke a PHP script using FastCgiAccessChecker.

I've tried various ways to try to pass in the script name I want to run by changing the filename in the FastCGIExternalServer and/or FastCgiAccessChecker directives -- doesn't work. I've also tried starting php-cgi with a script specifier, i.e.

php-cgi -q -b 192.168.0.11:9000 -f /var/www/html/thing/access.php &

Nothing works. I can tell apache recognizes my directives, sort of, because when I include FastCgiAccessChecker then visit a php page, content-type changes to text/plain and I lose the first ~8000 bytes of content from the page served if it's a script (no idea why). But it does not call the PHP script I want to run.

As far as I can figure, what is happening is that FastCgiAccessChecker assumes that the specified fastcgi server is compiled specifically to act as an access checker. There is no way to tell the fastcgi server (PHP in my case) what script to run to do the access check.

I've searched the web and as far as I can tell no one has ever tried to use a PHP script for this before, or no one has written about it.

So my question: what should I be doing? I can see a few possibilities:

1) I am missing something, and there is some magic way to make FastCgiAccessChecker do what I want: run a PHP script to control apache access control

2) I write my own FastCGI server in c and embed PHP, so I can specify the PHP script I want to run (I spent a few minutes looking in to this; it looks complicated and scary, and I haven't worked in c since 1995)

3) I give up on FastCGI and write an apache module to call my PHP script directly to control access. (Also looks complicated; and this technique would require a new process to be spawned for every request to exec PHP.)

Does anyone have any advice, either on how to get FastCGI to do what I want, or a (reasonably) simple alternative to FastCGI?

Thanks for anything you can suggest

Achronos
  • 143
  • 6

4 Answers4

8

My approach to these types of situations is to use mod_xsendfile in combination with mod_rewrite. These may not appear to do what you want a first, but if you:

  1. Use mod_rewrite rules to create a front controller (a single PHP script that handles all incoming requests).
  2. Determine what file is being requested by looking at the contents of $_SERVER (probably $_SERVER['PATH_INFO']).
  3. Insert your access control / security layer here.
  4. Use mod_xsendfile to send the contents of the file, if security passes.

You can essentially implement any security system you want in this manner.

mod_xsendfile essentially just sends a file in the exact same manner that Apache would, had the file been accessed directly. It's stable and works great in every situation I've thrown at it. It should also 'just work' without a huge burden of setup, which you seem to be struggling with a little.

ezzatron
  • 779
  • 6
  • 15
2

Thanks for the responses! I quite like ezzatron's technique, that should work with any Apache with no custom tools needed.

As it happens I ended up going with my #3 option before I read any of the replies:

I wrote an Apache module to do the job. It farms out access control to any document apache can serve, using a subrequest -- so it works for any script language or CGI program. For a typical PHP configuration using php_module or fastcgi, this scales quite well because no extra process is needed.

It turns out Apache's module API is not too hard to use, and I guess C is like riding a bike -- you never really forget how.

Achronos
  • 143
  • 6
0

You probably want to look into shell_exec() and system(). These will let you execute linux shell cmds as long as you have it enabled in your cfg. Also, for FastCGI I recommend you install php5-fpm. Pretty easy to do # apt-get install php5-fpm

Timothy Perez
  • 20,154
  • 8
  • 51
  • 39
  • Hello Timothy, thank you for your response. What I need is a way to tell Apache to use a PHP script to decide whether to allow access to a page. FastCGI is actually working fine for me, it's just there is no way I can see to get the directive `FastCGIAccessChecker` to work for PHP. – Achronos Aug 22 '11 at 13:48
0

I'm currently working on a similar problem - in my situation I needed to set the (authenticated) remote user in PHP. Put simply, you push the session cookie and authenticated username into memcache (have a look at the couchdb version for a very scalable system) from your PHP script, then the mod sets the user in Apache and can apply the information using the standard Apache acces control rules.

This avoids the overhead of starting additional processes/wrapping all access in PHP code.

See question and answers to Populating remote user in apache log files from PHP session

Community
  • 1
  • 1
symcbean
  • 47,736
  • 6
  • 59
  • 94