Module mod_suffixSuffix-based access control

Summary

This is a small Apache module that will grant access to files on the webserver based on their suffix. It will only allow files to be seen if their suffix is explicitly listed in the module's configuration. Attempts to get other files will either be blocked by sending a 403 (FORBIDDEN) status code or redirected to another page.

If you're working on a large website and you're editing your files in place you might be confronted with a lot of backup files that various editors leave behind - like index.html~ (Emacs) or index.html.bak (UltraEdit).
This can be a problem if you're using server-side scripting languages like Embperl or PHP: Malicious users might try to open foobar.php.bak instead of foobar.php and peek at your code to see things they shouldn't see (like bad programming style or - even worse - the password to your database).

mod_suffix tries to solve this problem by blocking access to all files that do not end with a pre-defined suffix. This might seem paranoid but at least it is a rather fast and secure method. Also, it should be flexible enough for most cases.

mod_suffix has been tested successfully with Apache 1.3.9 on FreeBSD 3.3 and Apache 1.3.12 on Linux 2.2.14 but I think it should work with all recent Apache releases and on all supported platforms. Please let me know about your attempts (whether successful or not) with other operating systems or other versions of Apache.

You'll need a working C compiler and its associated utilities, of course. If you've built your Apache from a source distribution you almost certainly have one... :)

There are at least two ways to install this module. Which one is appropriate depends on your Apache installation.

The easy way: If your Apache is compiled with support for dynamically loadable modules (also called DSO support), you'll just have to find out where apxs is located. Go to the directory where you unpacked the mod_suffix.c source file and let apxs do the work:

/usr/local/apache/bin/apxs -c -i -a mod_suffix.c

This will build mod_suffix.so as a shared object (the -c option), install the module in the right place (-i) and add the LoadModule directive to your httpd.conf file (-a). See the apxs manual page for details about these and other command line options.

If you don't know if you have DSO support, don't worry - apxs will complain in case you haven't. You can also check beforehand by letting Apache list all compiled-in modules with httpd -l. If mod_so.c is one of them, you're lucky.

The hard way:
Without DSO support you will have to rebuild Apache to use mod_suffix. (You might consider building it with DSO support this time...) Create a new directory like, say, site underneath the src/modules directory in Apache's source tree and put the mod_suffix.c file there. Now configure Apache with

As always, there's more than one way to do it. Here are two that work without mod_suffix:

1. If you know that you'll only have a couple of "bad" suffixes, you can single them out with a <FilesMatch> section and use the standard module mod_access to deny access. This solution won't work very well if you have many developers and everybody uses his favorite text editor, though. (In other words: We're talking about the opposite direction here. We're banning a couple of file extensions and let all others go through while mod_suffix blocks all file extensions except for a few chosen ones.)

2. You can achieve about the same effect with mod_rewrite and something like

but using mod_rewrite for this task is like trying to club
someone to death with a loaded Uzi - as Larry Wall might say. mod_rewrite can do almost anything to a URL that you can image but it also is nearly ten times bigger than mod_suffix and probably a lot slower than a specialized tool that can do only one thing.

If you know a way to achieve the same results with standard Apache modules, please let me know. (I only wrote mod_suffix because I couldn't find an easier solution.)

Update (October 2, 2000): There is a solution using the standard mod_access module that does almost exactly the same thing that my module does. Consider code like the following in your http.conf file:

<Directory /usr/local/apache/htdocs>
ErrorDocument 403 http://my.server.com/error.html
order deny,allow
deny from all
<FilesMatch "\.(html?|jpe?g|gif)$">
order deny,allow
allow from all
</FilesMatch>
</Directory>

This code (provided by Benjamin Schwenk) renders my module almost superfluous. I will nevertheless keep this page online as it was a nice experience for me working with the Apache API. Also, mod_suffix might still be the preferred solution if you're publishing a lot of directory URLs with or without trailing slashes (see SuffixControlIgnoreDotless below - Benjamin's solution won't allow you to access something like http://myserver.com/vacation/, you'll have to say http://myserver.com/vacation/index.html explicitly) or if you have a complicated setup and want to to keep your http.conf file lean.

mod_suffix will always ignore URLs that end with a slash because they usually designate directories and not files. It will, however, block URLs like http://www.foo.com/bar by default because bar could be a file. If SuffixControlIgnoreDotless is on, mod_suffix will ignore (i.e., let through) all URLs that do not have a dot after the last slash.

In other words - this is (almost...) like adding the empty string to SuffixControlList... :)

If this directive is set to on, the current scope will inherit the mod_suffix settings from the parent scope by the following rules: All extensions listed in the SuffixControlList will be added to the parent's list of allowed extensions. All other settings will be inherited from the parent if they are not explicitly overwritten in the child's scope.

If this directive is set to off, the parent scope will be completely ignored.

The virtual host 1.2.3.4 will ignore files with the extensions html, htm, jpg, and gif. It will inherit the SuffixControlLog off setting from the main server but it will not inherit the redirection target because it has been explicitly overwritten.

THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY
EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
OF THE POSSIBILITY OF SUCH DAMAGE.