Search code examples
mysql.htaccessapache2webdavauthz

authz_dbd, multi user authentication and individual folders through .htaccess


Intro

Our apache2 setup serves files from a wide variety of folders using webdav, and use authz_dbd to communicate with a mysql database (this part works without problems).

Summary: Apache2, mod_authz_dbd, mod_authn_dbd, mysql, enabling webdav, multi user environment (iot nodes).

However... some of these folders are user specific.

folder1              admins
+--subfolder1.1      admins+some other folk+user1
+--subfolder1.2      admins+again other folk+user1
folder2
+--subfolder 2.1     same as 1.1 but with user2
+--subfolder 2.2     as1.2.. but..user2

We use dbd-groups with wildcards, similar to this:

location /var/www/html/*/subfolder1.1 
 require dbd-group read

And normally wrote all in the vhosts file

(require user.. )

The problem

This becomes too large, we need another fix.

We cannot use .htaccess files in combination with dbd groups (dbd groups are not allowed in .htacces). Our debian (jessy) does not allow the other mysql apache2 mods.

The combination of .htaccess files with dbd's mysql authorization does not work (dbd groups are not allowed in .htaccess). Our debian server does not allow other mysql apache2 mods (like mod_auth_mysql).

How can I combine mysql authorization with the folder specific users?


Solution

  • Ok, i believe ive cracked it:

    Technique

    Apache natively support for named groupes and backreferances. The capture group can be employed to identify the folder (and with this the user).

    How does this work;

    every subdir with of the hosted directory (/var/www/web) Beginning with M and containing at least three decimals (M\d{3,}) <- the capture group. This is stored in a variable ( sitedir)

    eg.

    /var/www/web/M1234/etc. sitedir=M1234
    /var/www/web/M1234567/test/ANY other directory sitedir=M1234567
    

    In my case I match the user with the directory name require user %{env:MATCH_SITEDIR}

    Be very aware to use the queries outside the require directives (as shown below).

    Using cascaded RequireAny/Requireall other requirements can be made (requirements on dbd groups, ip ristrictions etc).

    Drawbacks

    The capture group might allow for multiple folders with an Mcode. This can be mitigated by adapting the capture group.

    The captured foldername cannot be used inside the query (it does not allow this) This would have been even nicer, but it does not work...(the variable is considered plain text).

    working example

       <DirectoryMatch /var/www/web/(?<sitedir>(M\d{3,}))>
            AuthDBDUserPWQuery "SELECT password FROM mysql_auth WHERE username = %s"
            AuthzDBDQuery "SELECT groups FROM mysql_auth WHERE username = %s"
            <RequireAny>
                    Require user %{env:MATCH_SITEDIR}
                    <RequireAll>
                        Require valid-user
                        Require ip 10.0.0.0/16
                        <RequireAny>
                            Require dbd-group internal
                            Require dbd-group write
                        </RequireAny>
                    </RequireAll>
            </RequireAny>   
       </DirectoryMatch>