Search

Recent

Tags

Restricting directory in Apache per logged in user

Filed under tips & tricks, hacks on feb 09, 2010

Sometimes you wonder why such seemingly simple problems have to end up in such complex solutions. For example Apache‘s mod_rewrite. The engine allows for parameter substitution in the RewriteCond and RewriteRule options, but its use is restricted to the left hand argument. Apache states: Remember: CondPattern is a perl compatible regular expression with some additions.

There are plenty examples of people with similar issues, I’ve also seen a few upstream patches to the Apache source tree, but apparently they never made it to an Apache release.

Well, four hours, a lot of frustration and some rage later, we came to a solution thanks to jink:

# Restrict /home/* to /home/%{REMOTE_USER} access only
RewriteEngine On
RewriteCond %{REQUEST_URI} ^/home/(?:|README\.x?html?|index\..+)$
RewriteRule ^.* - [L]
RewriteCond %{LA-U:REMOTE_USER} ^(.+)
RewriteCond %1:/home/$1 !^([^:]+):/home/\1$
RewriteRule ^/home/([^/]+) - [F,L]

You want me to explain this? Right, here we go.

Firstly, we want /home/ still to be accessible, so the user can enlist its own directory, we do this simply by comparing to the REQUEST_URI:

RewriteCond %{REQUEST_URI} ^/home/(?:|README\.x?html?|index\..+)$
RewriteRule ^.* - [L]

Now for the interesting part, Apache uses %{LA-U:...} construction to allow the mod_rewrite parser to prefetch these variables before evaluating the rewrite chain. We store the result of the REMOTE_USER value in %1. Apache on the %{LA-U:...} construction:

%{LA-U:variable} can be used for look-aheads which perform an internal (URL-based) sub-request to determine the final value of variable. This can be used to access variable for rewriting which is not available at the current stage, but will be set in a later phase.

For instance, to rewrite according to the REMOTE_USER variable from within the per-server context (httpd.conf file) you must use %{LA-U:REMOTE_USER} - this variable is set by the authorization phases, which come after the URL translation phase (during which mod_rewrite operates).

Secondly, we append :/home/.* to the REMOTE_USER part stored in %1, and compare this to a regular expression. If there is no match, the RewriteRule kicks in and throws a HTTP 403 Forbidden. Simple…. right? </sarcasm>:

RewriteCond %{LA-U:REMOTE_USER} ^(.+)
RewriteCond %1:/home/$1 !^([^:]+):/home/\1$
RewriteRule ^/home/([^/]+) - [F,L]

Combined with mod_dav this gives me the possibility to give a per-user share to authenticated users, I wanted to provide an access method to files which are accessible on any platform from any network. As most providers and network operators allow HTTP(S), WebDAV seems like a logical choice. As icing on the cake, Mac OSX supports WebDAV access natively (by entering the URL in Finder’s network connect), also iCalendar and other tools allow for WebDAV access which provides a great way to publish your calendars to a trusted source!

A full Virtual Host example reads:

<VirtualHost *:80>
    ServerName docs.maze.io
    DocumentRoot /export/docs
    <Directory /export/docs>
        # No .htaccess allowed
        AllowOverride None

        # Authenticate through LDAP
        AuthBasicProvider ldap
        AuthLDAPBindDN "userid=apache,dc=maze,dc=io"
        AuthLDAPBindPassword "secret"
        AuthLDAPURL "ldaps://ldap.net.maze.io/dc=maze,dc=io"
        AuthLDAPGroupAttribute memberUid
        AuthLDAPGroupAttributeIsDN off
        Require ldap-group cn=docs,ou=Groups,dc=maze,dc=io
        AuthType basic
        AuthName "docs area"

        # Enable WebDAV
        DAV On
    </Directory>

    # Restrict /home/* to /home/%{REMOTE_USER} access only
    RewriteEngine On
    RewriteCond %{REQUEST_URI} ^/home/(?:|README\.x?html?|index\..+)$
    RewriteRule ^.* - [L]
    RewriteCond %{LA-U:REMOTE_USER} ^(.+)
    RewriteCond %1:/home/$1 !^([^:]+):/home/\1$
    RewriteRule ^/home/([^/]+) - [F,L]
</VirtualHost>

Add to

Post your feedback

You can use this form to leave your feedback. Your insights are always appreciated.

Tools

View document source in text/plain