Apache-Authentication modifizieren/unterdrücken

Roogley

New Member
Nabend,

Infos:
Code:
- Serversoftware: Apache 2.2
- mods-enabled: actions alias auth_basic authn_file authnz_external authz_default authz_groupfile authz_host authz_user autoindex cband cgid dbd dir env fastcgi_ispcp headers ldap mime negotiation rewrite setenvif status suexec
- mods-available: actions alias asis auth_basic auth_digest authn_alias authn_anon authn_dbd authn_dbm authn_default authn_file authnz_external authnz_ldap authz_dbm authz_default authz_groupfile authz_host authz_owner authz_user autoindex cache cband cern_meta cgid cgi charset_lite dav_fs dav dav_lock dbd deflate dir disk_cache dump_io env expires ext_filter fastcgi_ispcp fastcgi file_cache filter headers ident imagemap include info ldap log_forensic mem_cache mime mime_magic negotiation proxy_ajp proxy_balancer proxy_connect proxy_ftp proxy_http proxy rewrite setenvif speling ssl status suexec unique_id userdir usertrack version vhost_alias

könnte mir jemand einen Tip geben, wie ich das folgende realisieren könnte?
Ich möchte einen Webnutzer authentifizieren. Dies mache ich über mod_authnz_external, und das klappt auch super. Einziges Problem* ist, dass Onkel Apache automatisch den 401er (Authorization required) raushaut. Ich würde dies gerne unterbinden. Ziel ist es, dass mod_authnz_external, bzw. mein Script, die Authentifizierung auch ohne Authorization-Header vornimmt.
Meine ursprüngliche Lösungsidee war, über mod_headers einen Authorization-Header hinzuzufügen. Aber leider werden die auth-mods ausgeführt, BEVOR mod_headers zum Zuge kommt.
Gibt es einen Ausweg, abgesehen davon, ein eigenes Auth-Modul zu schreiben? Dafür sind meine C-Kenntnisse dann doch etwas zu beschränkt...

Zusammengefasst:
Ich möchte, dass ein über mod_authnz_external angegebenes Script zur Authentifizierung und Authorisierung herangezogen wird, egal, ob der Client einen Authorization-Header sendet, oder nicht. Sofern er keinen sendet, soll mod_authnz_external dem Script einfach "leere" Werte übergeben.

Grüße
Roogley

*Ich weiß, it's not a bug, it's a feature...
 
Aber leider werden die auth-mods ausgeführt, BEVOR mod_headers zum Zuge kommt.
Auch wenn du den Header explizit early setzt?
Gibt es einen Ausweg, abgesehen davon, ein eigenes Auth-Modul zu schreiben?
Das vorhandene mod_auth_basic.c zurechtbiegen;)
Code:
if (!auth_line) {
        note_basic_auth_failure(r);
        return HTTP_UNAUTHORIZED;
    }
Da den User setzen und OK zurückgeben.

*Ich weiß, it's not a bug, it's a feature...
Wenn im Request nichts von einer Authentifizierung steht macht es IMHO auch keinen Sinn darauf zu prüfen. Bist du sicher das du das so haben willst?
 
Das macht insofern Sinn, dass ich nicht anhand von User und Passwort authentifizieren möchte, sondern anhand Request-URI, IP und Zeit. Und das macht das Script bis jetzt fabelhaft. Ich muss nur immer IRGENDWAS übergeben, und das Fenster zur Eingabe von Username und Passwort ist ein wenig stressend, zumal das Ding später ein paar User mehr versorgen soll. Genauso habe ich versucht, Usernamen und Passwort direkt in der URL zu übergeben, aber da fragt zumindest Kollege Firefox den User, ob das denn mit rechten Dingen zugehen würde ;)

Ich werde deine Tips mal ausprobieren, und das Ergebnis hier 'reineditieren.

Edith: Leider bringen weder
Code:
RequestHeader set Authorization "Basic MToy" early
noch
Code:
RequestHeader add Authorization "Basic MToy" early
den gewünschten Erfolg :/
Ich werde mal versuchen, das Auth-Modul umzubiegen. Einziges Problem dabei: Ich müsste es von einem .htaccess-/httpd.conf-Befehl abhängig machen, damit es nicht auf dem gesamten Server gillt, auf dem ich AuthType basic nutze ;)
Aber vielleicht kriege ich das sogar hin :D

Grüße
Roogley
 
Last edited by a moderator:
Das macht insofern Sinn, dass ich nicht anhand von User und Passwort authentifizieren möchte, sondern anhand Request-URI, IP und Zeit.
Dann hat das aber nichts mehr mit HTTP Authentifizierung zu tun und dafür fühlen sich die Apache Auth* Module zu recht nicht zuständig. Wenn du mit einer RewriteRule die IP in die URI einbaust kannst du mit RewriteMap/External Rewriting Program den Request überprüfen und entsprechend weiterleiten. Die Lösung wäre auch deutlich schneller weil das externe Programm dann nicht bei jedem Request neu gestartet werden müsste :)
 
Die Lösung wäre auch deutlich schneller weil das externe Programm dann nicht bei jedem Request neu gestartet werden müsste :)
Neu gestartet werden bei jedem Request müsste er auch, da wie gesagt die Abfrage auch die Zeit miteinbezieht. Das Script, welches die "externe" Authentifizierung übernimmt, soll einer IP für x Sekunden (bspw. 60) den Zugang zu einer Datei gewähren. Außerdem soll es möglich sein, gerade DURCH das angeben von HTTP-Authorization, dies im Script erkennen zu können, und evtl anders zu verfahren (trotz abgelaufener Zeit Zugang gewähren o. ä.).

Um nochmal zur Modifikation von mod_auth_basic zu kommen:
Nicht einmal der folgende Code erfüllt meinen Wunsch:
Code:
        if(!auth_line) {
                auth_line = "Authorization: Basic bm9ib2R5OlthbnkgcGFzc3dvcmRd";
        }
Kann es sein, dass mod_authnz_external eine eigene Verarbeitung dafür besitzt? Würde mich zwar wundern, da er ja als AuthBasicProvider geladen wird, aber in Anbetracht der Tatsache, dass o. g. Code nicht funktioniert...

... muss ich scheinbar auf dem Holzweg sein, weil wenn ich in der selben Funktion
Code:
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "112: Auth line was %s", auth_line);
angebe, erhalte ich trotzdem keinen Error...

Nur am Rande: Ich habe auch versucht, ob sich etwas mit mod_rewrite machen lässt, habe es gem. Doku eingerichtet, und komme mit RewriteLogLevel 5 bis hier:
Code:
192.168.5.3 - - [31/Aug/2008:14:58:52 +0200] [mdsandbox.lan/sid#75bc38][rid#7dc938/initial] (5) map lookup FAILED: map=dlauth key=bla6

Edit: Entwarnung, vermutlich hab ichs. Wenn ja, werde ich den Source natürlich posten...

Grüße
Roogley
 
Last edited by a moderator:
[Zuallererst: Sorry für Doppelpost, aber mein letzter Post ist meine Meinung nach schon unübersichtlich genug!]

Es ist vollbracht! :)

Hier die Modifikationen:
typedef struct { ... } auth_basic_config_rec
wird abgeändert zu:
Code:
typedef struct {
    authn_provider_list *providers;
    char *dir;
    int authoritative;
    int auth_required;
} auth_basic_config_rec;

static void *create_auth_basic_dir_config
wird abgeändert zu:
Code:
static void *create_auth_basic_dir_config(apr_pool_t *p, char *d)
{
    auth_basic_config_rec *conf = apr_pcalloc(p, sizeof(*conf));

    conf->dir = d;
    /* Any failures are fatal. */
    conf->authoritative = 1;
    conf->auth_required = 1;

    return conf;
}

static const command_rec auth_basic_cmds[]
wird abgeändert zu:
Code:
static const command_rec auth_basic_cmds[] =
{
    AP_INIT_ITERATE("AuthBasicProvider", add_authn_provider, NULL, OR_AUTHCFG,
                    "specify the auth providers for a directory or location"),
    AP_INIT_FLAG("AuthBasicAuthoritative", ap_set_flag_slot,
                 (void *)APR_OFFSETOF(auth_basic_config_rec, authoritative),
                 OR_AUTHCFG,
                 "Set to 'Off' to allow access control to be passed along to "
                 "lower modules if the UserID is not known to this module"),
    AP_INIT_FLAG("AuthBasicAuthRequired", ap_set_flag_slot,
                 (void *)APR_OFFSETOF(auth_basic_config_rec, auth_required),
                 OR_AUTHCFG,
                 "Set to 'Off' skips asking for user and password if not "
                 "specified and assumes user nobody:[any password] as "
                 "authorization data."),
    {NULL}
};

und in
static int get_basic_auth
wird zwischen
Code:
    auth_line = apr_table_get(r->headers_in, (PROXYREQ_PROXY == r->proxyreq)
                                              ? "Proxy-Authorization"
                                              : "Authorization");
und
Code:
    if (!auth_line) {
        note_basic_auth_failure(r);
        return HTTP_UNAUTHORIZED;
    }
der folgende Code eingefügt:
Code:
        if(!auth_line && !conf->auth_required) {
                *user = "nobody\0";
                *pw = "nopassword\0";
                r->user = (char *) *user;
                return OK;
        }

Jetzt ist über die .htaccess und den Parameter
AuthBasicAuthRequired On/Off [Standard: On]
die Funktionalität (de)aktiviert werden.

Wobei mir noch eine kleine Frage bleibt: Sind die Nullbytes bei *user und *pw essentiell?

Grüße
Roogley
 
Last edited by a moderator:
Ok, jetzt hast du den Apache httpd schon gepatched, aber ich hätte von Anfang an die Authentifizierung einfach komplett mit einem eigenen Skript abgefackelt, ohne mod_auth*.
 
Neu gestartet werden bei jedem Request müsste er auch, da wie gesagt die Abfrage auch die Zeit miteinbezieht.
Bei der RewriteMap bekommt das Programm die URIs zeilenweise per Standardeingabe und läuft dauerhaft. Deshalb muss bei jeder neuen Zeile/URI und nicht bei jedem Start die Zeit abgefragt werden.
Außerdem soll es möglich sein, gerade DURCH das angeben von HTTP-Authorization, dies im Script erkennen zu können, und evtl anders zu verfahren (trotz abgelaufener Zeit Zugang gewähren o. ä.).
Die Authorization Zeile auch noch in die URI einzubauen ist nicht so schwer ;)
Ich habe auch versucht, ob sich etwas mit mod_rewrite machen lässt, habe es gem. Doku eingerichtet, und komme mit RewriteLogLevel 5 bis hier:
Bei mir funktioniert es (auch wenn das Skript unnötigerweise als root gestartet wird:(), aber wenn du mit deiner Lösung zufrieden bist spar ich mir unnötige Ratschläge:D
Roger Wilco said:
ich hätte von Anfang an die Authentifizierung einfach komplett mit einem eigenen Skript abgefackelt
Möglich das es ein reiner Downloadserver ohne (f)cgis/mod_php werden soll.
 
Last edited by a moderator:
Möglich das es ein reiner Downloadserver ohne (f)cgis/mod_php werden soll.
Kein renier Downloadserver, aber wie du richtig vermutest,will ich den Zugriff auf Downloads beschränken nach dem einfachen Schema, wie viele One-Click-Hoster vorgehen:
- User öffnet eine Vorbereitungsseite
- Countdown startet
- Download beginnt.
Und die gesamte Verarbeitung der Downloads über extern laufen zu lassen ist insofern problematisch, dass es doch ein großer Ressourcenfresser ist. Der Apache ist so programmiert, dass er Dateitransfers möglichst effektiv ausführt, was man von Scriptsprachen (PHP/Perl) oder selbstkreierten Programmen meist nicht behaupten kann. Alternative Lösungen würden mich natürlich trotzdem insofern interessieren, alsdass ich dieses Wissen bei zukünftigen Projekten verwenden könnte ;)

Grüße
Roogley
 
Alternative Lösungen würden mich natürlich trotzdem insofern interessieren, alsdass ich dieses Wissen bei zukünftigen Projekten verwenden könnte ;)
Mit dem lighttpd würde ich einfach mod_secdownload verwenden.

Beim Apache httpd kannst du einfach mal nach Sendfile bzw. X-Sendfile (durch mod_xsendfile) suchen, um Dateien effizient an den Client liefern zu lassen.
 
Back
Top