Seite 1 von 1

Linux/Unix Benutzer Authentifizieren

Verfasst: Dienstag 2. August 2005, 13:56
von mauser
hi,

ich würde gerne meine user authentifizieren, also ihr passwort anhand der /etc/passwd überprüfen. nun habe ich aber shadow passwörter, desshalb kann ich das pwd modul nicht nutzen. kennt jemand eine möglichkeit, wie das trotzdem geschehen könnte ?
mfg
mauser

Re: Linux/Unix Benutzer Authentifizieren

Verfasst: Dienstag 2. August 2005, 14:37
von gerold
mauser hat geschrieben:ich würde gerne meine user authentifizieren
Hi mauser!

Unter Linux läuft so etwas normalerweise über PAM.

Das PyPAM-Projekt ist zwar schon etwas in die Jahre gekommen, vielleicht helfen folgende Links trotzdem weiter.

http://www.pangalactic.org/PyPAM/
http://www.kernel.org/pub/linux/libs/pam/
http://mail.python.org/pipermail/python ... 00187.html

Python-PAM (leider findet man nicht viel Informationen darüber):
http://packages.debian.org/testing/python/python-pam
http://lists.debian.org/debian-devel-m6 ... 00071.html

mfg
Gerold
:-)

Verfasst: Dienstag 2. August 2005, 14:50
von gerold

Verfasst: Dienstag 2. August 2005, 15:46
von Gast
hi gerold,

danke schonmal für deine antworten. ich hatte auch schon an pam gedacht, aber ich hatte eben erhofft das es noch eine einfachere möglichkeit gibt die ich übersehen hatte. normalerweise wird sich das programm an einen ldap-server wenden, aber ich wollte als alternative noch die passwd sache anbieten, falls jemand nicht python-ldap installiert hat.
und genau das ist halt auch der grund, warum ich eigentlich nicht noch eine externe library nutzen will..
aber ich werds mir mal überlegen, schliesslich gibts ja auch ein debian packet dazu was die installation dann sehr einfach macht.
mfg
mauser

Verfasst: Dienstag 2. August 2005, 17:01
von gerold
Anonymous hat geschrieben: ich hatte auch schon an pam gedacht, aber ich hatte eben erhofft das es noch eine einfachere möglichkeit gibt die ich übersehen hatte.
Hi mauser!

Es gibt da schon noch eine Möglichkeit, die untergräbt aber den Sinn und Zweck der shadow-Datei. Du kannst einer Gruppe lesenden Zugriff auf die shadow-Datei geben und damit wie in diesem Dokument http://www.python.org/doc/2.4.1/lib/module-crypt.html erklärt, eine Authentifizierung durchführen. Statt das verschlüsselte Passwort aus der passwd zu holen, musst du es halt aus der shadow-Datei holen. Das dürfte nicht wirklich schwierig sein.

Nachteil:
Sobald ein Benutzer lesenden Zugriff auf die shadow-Datei hat, ist es für diesen angemeldeten Benutzer möglich Brute-Force Attacken auf die Shadow-Datei los zu lassen.

mfg
Gerold
:-)

Verfasst: Dienstag 2. August 2005, 19:40
von Leonidas
Gerold, du meisnt ein vom User eingegebenes Passwort du verschlüsseln mit crypt und es dann mit dem in der shadow zu vergleichen? Ich glaube zumindest Debian hat eine Option mit der die Passwörter als MD5 Hashes gespeichert werden (ab Sarge Standard soweit ich weiß), also hat man wieder eine Fallunterscheidung.

Verfasst: Dienstag 2. August 2005, 21:09
von gerold
Leonidas hat geschrieben: Ich glaube zumindest Debian hat eine Option mit der die Passwörter als MD5 Hashes gespeichert werden (ab Sarge Standard soweit ich weiß), also hat man wieder eine Fallunterscheidung.
Hi Leonidas!

An das hätte ich doch fast nicht mehr gedacht. Das mit den verschiedenen Verschlüsselungsmethoden wirkt sich sehr erschwerend auf die Sache aus. Ich hatte bei einigen Distributionen zusätzlich die Möglichkeit Blowfish auszuwählen. :(

Vielleicht fällt noch jemandem eine einfachere Möglichkeit ein, aber bis jetzt glaube ich, dass die Verwendung von python-pam die Einfachste Variante ist. Das (Debian) Beispiel unter /usr/share/doc/python2.3-pam/examples scheint recht einfach zu funktionieren. Leider kann ich python-pam nur für Debian finden. Was mich gerade verwundert ist -- dass ich kein Gentoo-Ebuild für python-pam finde, wo es doch sonst immer für alles ein Ebuild gibt.

lg
Gerold
:-)

Verfasst: Dienstag 2. August 2005, 21:37
von Leonidas
gerold hat geschrieben:An das hätte ich doch fast nicht mehr gedacht. Das mit den verschiedenen Verschlüsselungsmethoden wirkt sich sehr erschwerend auf die Sache aus. Ich hatte bei einigen Distributionen zusätzlich die Möglichkeit Bluefish auszuwählen. :(
Bluefish? Oder meinst du eher Blowfish bzw. Twofish? Das scheint mir aber nicht so das wahre zu sein, denn es ist sicherer ein Passwort zu hashen statt es zu verschlüsseln, da dann das Passwort bekannt sein müsste und somit die Passwörter auch entschlüsselbar sind. Dagegen sollte man gehashte Passworter auch mit den Modulen md5 für MD5 oder sha für SHA1 in Python herstellen können. Von dem her ist es vermutlich etwas fuselarbeit, aber durchaus machbar.
gerold hat geschrieben:Vielleicht fällt noch jemandem eine einfachere Möglichkeit ein, aber bis jetzt glaube ich, dass die Verwendung von python-pam die Einfachste Variante ist. Das (Debian) Beispiel unter /usr/share/doc/python2.3-pam/examples scheint recht einfach zu funktionieren. Leider kann ich python-pam nur für Debian finden. Was mich gerade verwundert ist -- dass ich kein Gentoo-Ebuild für python-pam finde, wo es doch sonst immer für alles ein Ebuild gibt.
Ich habe das gefühl, dass es keinen Upstream von python-pam mehr gibt, die aktuellste Version gibts bei den Debian Sourcen.

Die Homepage von Robin Riggs, dem Author existiert jedoch noch.

Verfasst: Mittwoch 3. August 2005, 07:55
von gerold
Leonidas hat geschrieben: Bluefish? Oder meinst du eher Blowfish
Hi Leonidas!

Blowfish oder Bluefish -- da gibt es doch *fast* keinen Unterschied :wink: :D

lg
Gerold
:-)

Verfasst: Mittwoch 3. August 2005, 11:46
von Leonidas
Na auch für Blowfish Passwörter gibt es eine Lösung: Pycrypto oder wenn man lieber puren Python Code hat und die Geschwindigkeit nicht so ausschlaggebend ist Concordias Blowfish oder OCNs Blowfish. Jedoch habe ich keine Ahnung mit welchem Passwort man die Passwörter denn verschlüsseln sollte, das Passwort entfällt ja bei MD5.

Dieses Blowfish-Shadow Teil kommt hierher und eine Kompatible Methode wurde wie ich gelesen habe auch in OpenBSD verwendet. Es gibt auch eine Einleitung wie man LFS mit Blowfish verkuppelt.. da sollten sich schon informationen finden lassen, wei man solche Passworter gegen die /etc/shadow verifizieren kann.

Edit: Das Teil nennt sich in OpenBSD bcrypt und scheint recht komplex zu sein.

Verfasst: Mittwoch 3. August 2005, 12:00
von ProgChild
Das muss doch auch irgendwie leichter gehen. Ich weis nur, dass der vsftpd einmal eine Authenzifizierung mit PAM und eine ohne macht. Falls jemand mal die Zeit hat sich den Source Code vorzunehmen...

Verfasst: Mittwoch 3. August 2005, 20:27
von Gast
ich habe gerade mal "su" näher unter die lupe genommen, um zu sehen wie das tool intern arbeitet. ein schneller versuch mit strace zeigt, das dort auch versucht wird auf die shadow datei zuzugreifen. am anfang werden auch viele crypto libs geladen. danach wird versucht, /etc/shadow zu öffnen, was aber fehlschlägt. dann wird anscheinend pam zur finalen anwendung herangezogen. also: an pam führt wohl nix vorbei. mich irritiert nur, das die python-pam bindings so schlecht verbreitet sind.
mfg
mauser

Verfasst: Mittwoch 3. August 2005, 21:11
von jens
Leonidas hat geschrieben:Concordias Blowfish oder OCNs Blowfish
Spontan gefällt mir Concordias Blowfish besser. Der Quellencode sieht wesendlich aufgeräumter auf...
Jemand eine Ahnung wieviel langsamer die sind???

Verfasst: Mittwoch 3. August 2005, 21:59
von Leonidas
jens hat geschrieben:Jemand eine Ahnung wieviel langsamer die sind???
Ich habe grad nichtmal eine Ahnung wie man die genau nutzen kann um überhaupt etwas Benchmarkmäßiges aufzustellen :idea:

Verfasst: Donnerstag 4. August 2005, 06:27
von jens
Hä??? Bei Concordias Blowfish ist doch unten direkt ein Beispiel:

Code: Alles auswählen

if __name__ == '__main__':
	key = 'This is a test key'
	cipher = Blowfish (key)

	print "Testing encryption:"
	xl = 123456
	xr = 654321
	print "\tPlain text: (%s, %s)" %(xl, xr)
	cl, cr = cipher.cipher (xl, xr, cipher.ENCRYPT)
	print "\tCrypted is: (%s, %s)" %(cl, cr)
	dl, dr = cipher.cipher (cl, cr, cipher.DECRYPT)
	print "\tUnencrypted is: (%s, %s)" %(dl, dr)

	print "Testing buffer encrypt:"
	text = 'testtest'
	print "\tText: %s" %text
	crypted = cipher.encrypt (text)
	print "\tEncrypted: %s" %crypted
	decrypted = cipher.decrypt (crypted)
	print "\tDecrypted: %s" %decrypted
Ausgabe:

Code: Alles auswählen

Testing encryption:
	Plain text: (123456, 654321)
	Crypted is: (1009721363, 1921430063)
	Unencrypted is: (123456, 654321)
Testing buffer encrypt:
	Text: testtest
	Encrypted: ý»(–Ž»
	Decrypted: testtest

Verfasst: Donnerstag 4. August 2005, 09:49
von Leonidas
Ich weiß.. aber verstehs halt einfach nicht.
Es ist doch so: wenn du etwas mit Blowfish verschlüsseln willst, dann wirst du nach einem Passwort gefragt. Aber Concordia mag noch:
xl is the upper 32-bits and xr is the lower 32-bits.
Die Demo geht zwar von irgendwelchen Werten aus, aber sagt nicht warum.

Verfasst: Donnerstag 4. August 2005, 12:01
von jens
Ich glaube jetzt weiß ich was zu meinst...

In den Methoden encrypt und decrypt werden xl, xr bzw. cl, cr erzeugt. z.B.:

Code: Alles auswählen

		# Use big endianess since that's what everyone else uses
		xl = ord (data[3]) | (ord (data[2]) << 8) | (ord (data[1]) << 16) | (ord (data[0]) << 24)
		xr = ord (data[7]) | (ord (data[6]) << 8) | (ord (data[5]) << 16) | (ord (data[4]) << 24)
Die Daten werden also zerlegt... (in Höher- und Niederwertige Bits ?!?!)

Doof ist, das es nur mit der Blockgröße von 8 Bytes funktioniert :( Leider gibt es aber keine Methode, damit Daten, die unterschiedlich lang sind, automatisch in 8 Byte Blöcke aufgeteilt bzw. zusammen gesetzt werden.

Ich dachte ursprünglich das ich das Modul für PyLucid nutzten könnte. Dafür brauche ich aber die Unterstützung für das Ver- und Endschlüsseln von Daten variabler Länge...

Verfasst: Donnerstag 4. August 2005, 12:35
von jens
Ich hab mir mal eine Funktion geschrieben, die Daten in 8-Bytes Blöcke aufteilt. Wenn die Daten nicht gerade durch 8 Teilbar sind, werden hinten NULL-Bytes drangehangen:

Code: Alles auswählen

    def mkblocks ( self, data ):
        datalen = len(data)

        # Nächste Blockgröße in der data reinpaßt
        blocklen = int( math.ceil( datalen/8.0 ) ) * 8

        # data auffüllen, damit es exakt in die Blockgröße reinpaßt
        data += "\x00" * (blocklen - datalen)

        # in Blöcke von 8 Bytes aufteilen
        return re.findall( ".{8}", data )
Das geht doch mit sicherheit noch einfacher, oder??? Siehe hier: http://www.python-forum.de/viewtopic.php?t=3693

Die original Methoden encrypt() und decrypt() hab ich umbenannt in _encrypt() und _decrypt()... Die folgenden Methoden nehmen dann Daten in variabler Länge entgegen:

Code: Alles auswählen

    def encrypt (self, data):
        result = ""
        for block in self.mkblocks( data ):
            result += self._encrypt( block )
        return result

    def decrypt( self, data ):
        result = ""
        for block in self.mkblocks( data ):
            result += self._decrypt( block )
        return result.rstrip("\x00")
Dumm wäre natürlich, wenn die zu verschlüßelten Daten am Ende NULL-Bytes enthalten würde, dann würden die von rstrip() beim decrypten weggeschnitten... :cry:

Verfasst: Dienstag 9. August 2005, 22:44
von Leonidas
Grad noch beim surfen gefunden: md5crypt.