Sep 132014
 

Es kommt häufig vor, dass man beim Apache nicht gegen eine htpasswd-Datei authentifizieren möchte, sondern das gegen eine MySQL-Datenbank erledigen möchte. Unter Ubuntu muss zu diesem Zweck das Paket libaprutil1-dbd-mysql installiert werden:

sudo apt-get install libaprutil1-dbd-mysql

Danach müssen die passenden Module aktiviert werden. Der Restart kann erfolgen, wenn die Konfiguration angepasst wurde:

sudo a2enmod authn_dbd

Für die Datenbank sollte ein eigener DB-User eingerichtet werden, der nur Lesezugriff auf die Tabelle mit den Passwörtern hat. In unserem Beispiel heißt die Tabelle User und hat mindestens zwei Spalten names login und password. Die Spalte password sollte das verschlüsselte (Warnung) Passwort enthalten. Für den Apache ergeben sich für die Basic Authentication folgende Bedingungen für den Inhalt der password-Spalte:

  1. Plain Text Passwort (sehr unsicher (!))
    Hier steht das Passwort im Klartext in der Spalte. Davon ist dringend (!) abzuraten!
  2. SHA1 Passwort (SHA1 gilt inzwischen als weich (!))
    Dabei wird das SHA1-gehashte Passwort als Base64 enkodiert und „{SHA}“ vorangestellt. Also z.B.: {SHA}YusNsXhRioN2sjZ2wmOesnMsC+g=
  3. MD5 Passwort (unsicher (!))
    Dabei wird das MD5-gehashte Passwort als Base64 enkodiert und „$apr1“ vorangestellt. Also z.B.: $apr1$KJJD/S8O$rY.oEVoZ.wovVwDnu1qUK1
  4. crypt
    Diese Methode greift unter Linux auf die crypt()-Funktion der libcrypt zu. Hiermit lassen sich MD5, blowfish, SHA1, SHA-256 uns SHA-512 realisieren.

Anzeige:


Welche Methode Apache benutzt hängt also von dem einzelnen Passwort ab, so wie es in der Datenbank steht. Es lassen sich also die Passwort-Formate mischen. Mit der crypt-Variante kann man auf SHA-512 zurückgreifen. Das in der Datenbank hinterlegte Format lautet:

$6$<salt>$<40-byte-hash>

Ich will hier zwei Methoden vorstellen, wie man einen SHA-512 mit crypt-Format für die Datenbank erzeugen kann: erstens mit C und zweitens mit Java.

SHA-512 mit C

Unter Linux lässt sich unter Verwendung der crypt()-Methode, die auch Apache verwendet, ein Text mit SHA-512 hashen. Die Methode nimmt ein Passwort und ein Salt. Dem Salt wird die Hashing-Methode in "$"-Zeichen vorangestellt. Für SHA-256 ist das $5$ und für SHA-512 $6$ vorangestellt. Das folgende Code-Beispiel erzeugt einen gehashten Text aus dem Passwort „test“ und dem Salt „1234„, den der Apache verarbeiten kann:

#define _XOPEN_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
 
int main(int argc, char *argv[])
{
    const char *salt = "$6$1234$";
    const char *pass = "test";
    char *result = crypt(pass, salt);
 
    printf("%s\n", result);
    return EXIT_SUCCESS;
}

Das Programm muss noch kompiliert und ausgeführt werden:

gcc crypt.c -o crypt -lcrypt
./crypt

Als Ausgabe erfolgt:

$6$1234$RtjH4vyYsWBTNKMNb.n8pesSjKQm4e/mTwC8kGIX4G29pNGyRUWvUETb/z1emQuQ8R6h6kou8eriOKZ0j2IAi0

SHA-512 mit Java

Für Java benötigt man die Apache Commons Codec. In ihr ist eine zu Linux kompatible crypt()-Methode in der Klasse org.apache.commons.codec.digest.Crypt enthalten. Der Aufruf ist zu der mit C kompatibel und sieht im Vergleich so aus:

import org.apache.commons.codec.digest.Crypt;
...
    public static String encrypt()
    {
        return Crypt.crypt("test", "$6$1234$");
    }
...

Anzeige:


Konfiguration im Apache

Die Konfiguration besteht aus zwei Teilen

  1. Die Kontaktdaten zur Datenbank
  2. Die Konfiguration der Basic Authentication

Die Kontaktdaten zur Datenbank müssen zwingend außerhalb der Location– bzw. Directory-Tags stehen. Die Konfiguration der Basic Authentication selbst ist einfach. Neben der üblichen Kommandos AuthType, AuthName und Require muss nur der AuthBasicProvider und die DB-Query mittels AuthDBUserPWQuery angegeben werden. Der User wird über das %s in der Query ersetzt. Das Passwort wird mit dem ersten Ergebnis der ersten Spalte verglichen. Apache wandelt das Passwort automatisch in das Format um, wie das Passwort in der Datenbank hinterlegt ist. So können sogar gemischte Werte in der Tabelle hinterlegt werden.

...
<IfModule mod_dbd.c>
        DBDriver mysql
        DBDParams "host=<DB-Host> dbname=<DB-Name> user=<DB-User> pass=<password>"
</IfModule>
...
<Location ...> oder <Directory ...>
        AuthType Basic
        AuthName "Authentifizierter Bereich"
        AuthUserFile /dev/null
                 
        <IfModule mod_authn_dbd.c>
                AuthBasicProvider dbd
                AuthDBDUserPWQuery "SELECT u.password FROM User u WHERE user.login = %s"
                Require valid-user
        </IfModule>
</Location> oder </Directory>
...

Die Werte DB-Host, DB-Name, DB-User und password müssen den eigenen Gegebenheiten angepasst werden. Nachdem die Module aktiviert und der Apache konfiguriert wurde, muss er neu gestartet werden:

sudo service apache2 restart

Authentifizierung über Rollen

Das Modul mod_authn_dbd ermöglicht auch das Login über Rollen. Dazu muss statt einem Require valid-user ein Require dbd-group konfiguriert werden. Zusätzlich muss eine Query zum Ermitteln der Rolle eines Users konfiguriert werden. Dabei handelt es sich um eine Mapping-Tabelle, die vom User auf eine Gruppe zielt:

...
<Location ...> oder <Directory ...>
        ...
        Require dbd-group 
        AuthzDBDQuery "SELECT ur.group FROM UserRole ur WHERE ur.user = %s"
        ...
</Location> oder </Directory>
...

Alternative: mod_auth_mysql

Alternativ kann man auch das Modul mod_auth_mysql benutzen. Leider wird es nur bis Apache 2.2 unterstützt, so dass ich hier nicht näher auf die Konfiguration eingehe.

Referenzen: