Forum Moderators: phranque

Message Too Old, No Replies

.htaccess: ban all but selected files AND allow an index file

         

abelikoff

11:00 pm on Feb 18, 2005 (gmt 0)

10+ Year Member



Hello everyone -

I'm trying to create an .htaccess file that could be distributed as part of a PHP-based web application. I would like this file to be as much location-independent as possible as I cannot assume any particular location, this webapp would be installed in.

My .htaccess file is supposed to enforce the following simple rules:

1. Access is allowed to a handlful of PHP files in the top directory.
2. Access to all other files and subdirectories is banned.
3. Default Index is set to main.php, so that people could run the app via [myserver.com...] or [myserver.com...] (note traling slash) without specifying the php file directly.

A brute force approach to such configuration resulted in the following file:


DirectoryIndex list.php

<Files *>
Order deny,allow
Deny from All
</Files>

<FilesMatch "^$">
Order allow,deny
Allow from All
</FilesMatch>

<FilesMatch "^myapp$">
Order allow,deny
Allow from All
</FilesMatch>

<Files *.php>
Order allow,deny
Allow from All
</Files>

The two [u]FilesMatch[/u] rules are introduced to make the configuration handle requests for [myserver.com...] or [myserver.com...] gracefully. Without them the damn thing would reject such request (even though requests for the index file mentioned explicitly via [myserver.com...] did work).

What bothers me is the fact that now my .htaccess is way too coupled with the directory name. Could anyone suggest a better way to enforce the rules above without doing such tricks?

Thanks in advance.

jdMorgan

2:54 am on Feb 19, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



abelikoff,

Welcome to WebmasterWorld!

Hmmm... I'm not sure I understand your concern completely. Among other things, I'm not sure which names you are using in your post for files and which are for directories. A few notes:

<Files> and <FilesMatch> are directory-insensitive; The test applies only to the filename, not a full pathname.

<FilesMatch> uses regular expressions, so the construct "<Filesmatch (^$¦^myapp$)>" would be valid, saving you a repeated <Filesmatch> section. (You will have to replace the broken pipe "¦" character with a solid pipe before use; Posting on this board modifies that pipe character.)

We've had discussions here before that lead me to believe that only one <Order> directive should be present in an .htaccess file. Otherwise, unexpected results can follow.

Set it up with one Order directive and a global Deny from All, then create exceptions within the <FilesMatch> containers.

You can place .htaccess code in the directory along with your files, and that code will only affect that directory and its subdirectories.

Taking the above into consideration, perhaps you can provide a few more details...

Jim

abelikoff

9:23 pm on Feb 21, 2005 (gmt 0)

10+ Year Member



Hello Jim -

I'm sorry if I am not clear. What I mean is the following structure:

myapp/
- main.php
- another.php
- foo.php
- .htaccess
- mysecretfile.dta
- private_notes.txt
- doc/
----- README.txt
----- .svn/
---------- entries

Given this structure, I would like to ensure that only a handful of files are visible, while other files AND directories are not. Furthermore, I would like to make main.php a default index.

Below are several scenarios with desired outcomes:
1. [mysite.com...] --> main.php
2. [mysite.com...] --> main.php
3. [mysite.com...] --> main.php
4. [mysite.com...] --> foo.php
5. [mysite.com...] --> ERROR
6. [mysite.com...] --> ERROR
7. [mysite.com...] --> ERROR

The point here is that I want to make visible as little as possible because things happen and I can mistakenly leave some important file or directory around. Or, I could screw up and forget to upload main.php (in which case I'd rather have the user get an error instead of the directory index).

With the configuration mentioned above, I am almost there. The only culprit is the handling of the translation of the "application directory" URL into the default index (scenarios ##1,2). Looks like File rules are preventing me from doing so. :-(

Maybe there is a simpler way of achieving the objectives I mentioned?

Thanks in advance,
-- Sasha

jdMorgan

4:24 am on Feb 22, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Well, working from your example list of desired results, I'd suggest:

Order Deny,Allow
Deny from All
<FilesMatch "(myapp¦main¦foo)\.php$">
Allow from All
</FilesMatch>

Replace the broken pipe "¦" character with solid pipe characters before use!

Jim

abelikoff

3:43 pm on Feb 23, 2005 (gmt 0)

10+ Year Member



Hello Jim - thank you for your help. Unfortunately, this still doesn't resolve the original problem: it does not allow me to set a directory index and handle it properly.

Even when I add DirectoryIndex main.php it would still prohibit me from accessing the URL without the last file component (doesn't matter whether it is with a trailing slash or without it). The scenarios ## 1,2 from the list above don't work.

So far, the configuration in my original message is the best I've got, even though it's long and it does depend upon the directory name where it is placed... :-(

-- Sasha

jdMorgan

6:25 pm on Feb 23, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Sorry, I missed those first two cases. My main purpose is to demostrate that you don't need a bunch of <Files> containers to do this. The following may be closer to correct (and short):

Order Deny,Allow
Deny from All
<FilesMatch "^$¦myapp$¦(myapp¦main¦foo)\.php$">
Allow from All
</FilesMatch>

Replace the broken pipe "¦" character with solid pipe characters before use!

Jim

abelikoff

8:48 pm on Feb 23, 2005 (gmt 0)

10+ Year Member



Yep - that's what I have after contracting the original example into a single regexp. :-)

My issue with this is that the original requirements (which I consider to be common sense) lead to a really non-obvious regular expression after some trial and error. Worse, the result is coupled with the deployment location name.

All of this could be avoided if Apache first applied the index URL production rules (producing an [mysite.com...] as a resulting URL for scenarios 1,2) and then the access restrictions.

Interestingly, not too many people ask the same question around the net. Maybe I'm just too paranoid...

In any case - thank you very much, Jim, for your help.
-- Sasha

jdMorgan

9:05 pm on Feb 23, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Well, you could use mod_rewrite to fix the first two cases (expand them to the canonical URL-path), and then apply the restrictions. Whether this worked would depend on the invocation order of mod_access and mod_rewrite. Or you could do the whole thing in mod_rewrite to make it simpler. And... you could set up 'myapp' as an alias for the actual directory, and then just change the rewriterule in one place if that would help with the deployment problem.

Jim