User und Gruppen, Prozesse und Dateien

Heute im Irc stellte eine Teilnehmerin den folgenden Fragenschwall:
Wie finde ich eigentlich heraus, was für Gruppen es auf einem Linuxsystem gibt? Wie füge ich da jemanden hinzu? Lege ich den zuerst als User an, ganz normal? Und: Wenn ich einen Ordner anlege, der nur für eine bestimmte Gruppe zugänglich sein soll, mache ich das doch über File Permissions, oder habe ich falsch gedacht?
Die offensichtliche Antwort, das Nachsehen in /etc/group
,
funktioniert bei modernen Unixen nicht mehr zwingend, denn
Gruppendefinitionen können nicht nur in lokalen Dateien stehen,
sondern auch aus dem NIS, dem NIS+, einem LDAP oder einem Active
Directory kommen.
Die folgenden Dinge wurden mit Suse Linux 10.0 getestet, sollten so aber auch auf Solaris funktionieren.
Name Service Switch
Genauer gesagt haben moderne Unixe ein Subsystem namens Name Service Switch. Der Name Service Switch erlaubt es dem System, für Benutzer, Gruppen, Hostnamen, Protokolle, Service und noch ein paar Dinge beliebige Datenquellen zu verwenden, für die vorgefertige Module existieren.
Der Name Service Switch wird durch die Datei
/etc/nsswitch.conf
gesteuert. Dort findet man für jede
Datenbasis (passwd, group, hosts, …) einen einzeiligen
Eintrag. Nach dem Namen der Datenbasis werden durch Leerzeichen
getrennt die Namen der Datenquellen aufgelistet, und zwar in der
Reihenfolge, in der sie durchsucht werden sollen.
passwd: files nis
shadow: files nis
group: files nis
hosts: files dns
Diese Beispielkonfiguration holt ihre Benutzerdaten für Passwd-
und Shadow-Datei sowie die Gruppen aus den lokalen Dateien und
danach aus dem NIS, und sie ermittelt Hostnamen aus der lokalen
/etc/hosts
und danach aus dem DNS.
Die Syntax für die /etc/nsswitch.conf
ist noch ein wenig
komplizierter. Zwischen den Einträgen für Datenquellen können in
eckigen Klammern nämlich noch Anweisungen für das Verhalten in
Fehlerfällen stehen. Auf diese Weise sind Setups möglich, die
ihre Daten normalerweise NUR aus dem NIS ziehen, aber aus den
lokalen Dateien, falls das NIS einmal nicht erreichbar sein
sollte.
Die Datenbasen des Name Service Switch lassen sich mit dem
Kommando getent
testen. getent group
listet zum Beispiel die
gesamte group
-Datenbasis auf, getent group disk
listet nur
den Eintrag für die Gruppe disk
auf.
Wir merken uns:
In einem modernen Unix mit Name Service Switch ist es also falsch, eine Liste der Gruppen des Systems durch Auslesen von
/etc/group
zu erzeugen. Stattdessen muß die Liste mitgetent group
erzeugt werden.
Das Interface des Name Service Switch ist read-only. Es erlaubt nicht die virtualisierte Erzeugung von Gruppen. Schreibzugriffe müssen also weiterhin manuell in die richtige Datenbank geroutet werden, also in eine lokale Datei oder in ein LDAP geschrieben werden.
Prozesse und Dateien
User und Gruppen sind nur dann von Bedeutung, wenn sie auch vom Systemteilen verwendet werden. Systemteile sind Subjekte, also Prozesse, und Objekte, also Dateien.
Ein Prozeß in Unix hat eine effektive User-ID und eine effektive primäre Gruppen-ID. Er kann außerdem eine Reihe von weiteren sekundären Gruppen-IDs enthalten.
Das Kommando “id” listet die User- und Gruppen-IDs eines Benutzers:
kris@dhcp-179:~> id -a
uid=1000(kris) gid=100(users) Gruppen=16(dialout),33(video),100(users)
Der Benutzer kris hat also die User-ID 1000 und die primäre Gruppen-ID 100. Er gehört außerdem den Gruppen 16 (dialout) und 33 (video) an.
Wenn dieser Prozeß eine Datei erzeugt, dann gehört diese Datei ebenfalls dem Benutzer 1000 (kris) und sie wird standardmäßig (“System V Semantik”) der Gruppe 100 (users) angehören, denn dies sind die primäre User- und Gruppen-ID dieses Prozesses.
Es gibt eine andere Betriebsart für Dateisysteme (“BSD Semantik”), bei der neu angelegte Dateien nicht die primäre Gruppe des anlegenden Prozesses erben, sondern die Gruppe des unmittelbar übergeordneten Verzeichnisses. Man kann das ext2-Dateisystem komplett auf BSD-Semantik umstellen, indem man es mit der Option “grpid” (alternativ “bsdgroups”) mounted - der Default ist “nogrpid” (alternativ “sysvgroups”). In der Betriebsart “nogrpid” kann man für ein einzelnes Verzeichnis BSD Semantik wählen, indem man das SGID-Bit an dem Verzeichnis setzt. Hier ein Beispiel:
dhcp-179:~ # lvcreate -l 10 -n test system
Logical volume "test" created
dhcp-179:~ # mke2fs -q /dev/system/test
dhcp-179:~ # mount -o nogrpid /dev/mapper/system-test /export/test
dhcp-179:~ # mkdir /export/test/bla /export/test/fasel
dhcp-179:~ # chown kris:video /export/test/bla /export/test/fasel
dhcp-179:~ # chmod g+s /export/test/fasel
dhcp-179:~ # su - kris
kris@dhcp-179:~> cd /export/test
kris@dhcp-179:/export/test> touch bla/eins fasel/zwei
kris@dhcp-179:/export/test> ls -l bla/eins fasel/zwei
-rw-r--r-- 1 kris users 0 2005-11-01 18:59 bla/eins
-rw-r--r-- 1 kris video 0 2005-11-01 18:59 fasel/zwei
kris@dhcp-179:/export/test> ls -ld bla fasel
drwxr-xr-x 2 kris video 1024 2005-11-01 18:59 bla
drwxr-sr-x 2 kris video 1024 2005-11-01 18:59 fasel
In diesem Beispiel wird das logical Volume test
in der Volume
Group system
angelegt und mit dem ext2-Dateisystem formatiert.
Das Dateisystem wird mit der Option nogrpid
als /export/test
gemountet, was der Default für ext2 ist (und bei reiserfs
unveränderlich immer der Fall ist).
In /export/test
werden die Verzeichnisse bla
und fasel
anlegt
und beide auf kris:video
gesetzt. An fasel
wird zusätzlich noch
das SGID-Bit gesetzt.
Legt der User kris:users
nun in bla
und fasel
jeweils eine Datei
an, wird die Datei in bla
(System V Semantik, bzw. nogrpid) der
Gruppe users angehören. Die Datei in fasel
(BSD Semantik, durch
+s umgeschaltet) erbt ihre Gruppenzugehörigkeit jedoch vom
übergeordneten Verzeichnis, gehört also kris:video
.
Dasselbe Beispiel wie oben für ein Dateisystem, das mit grpid
gemountet wurde, ergibt dann das folgende Bild:
kris@dhcp-179:/export/test> touch bla/eins fasel/zwei
kris@dhcp-179:/export/test> ls -ld bla fasel
drwxr-xr-x 2 kris video 1024 2005-11-01 19:04 bla
drwxr-sr-x 2 kris video 1024 2005-11-01 19:04 fasel
kris@dhcp-179:/export/test> ls -l bla/eins fasel/zwei
-rw-r--r-- 1 kris video 0 2005-11-01 19:04 bla/eins
-rw-r--r-- 1 kris video 0 2005-11-01 19:04 fasel/zwei
Das SGID-Bit am Verzeichnis hat dann also keine Wirkung mehr, weil das Dateisystem an sich hier schon BSD-Semantik hat.
Reiserfs kennt die Optionen grpid
und nogrpid
nicht und
verhält sich immer wie ein ext2-Dateissystem mit nogrpid
.
Wie kann man nun ein Verzeichnis einer Gruppe schenken? Nun, das geht einfach mit chgrp:
kris@dhcp-179:~> mkdir keks
kris@dhcp-179:~> chgrp video keks
kris@dhcp-179:~> chgrp disk keks
chgrp: Ändern der Gruppe für „keks“: Die Operation ist nicht erlaubt
kris@dhcp-179:~> chgrp users keks
Offenbar kann man ein Verzeichnis nur Gruppen schenken, denen man selbst angehört. Das ist deswegen so, weil Unix die Zuordnung von Quotas zu Benutzern und zu Gruppen erlaubt. Indem man eine Datei einer Gruppe schenkt, belastet die Datei die Quota der Gruppe und natürlich darf man nur die Quota einer Gruppe belasten, der man auch angehört.
Wenn man eine Datei in einem Verzeichnis mit BSD-Semantik anlegt, dann erbt diese Datei jedoch immer die Gruppe des Verzeichnisses, selbst dann, wenn der Benutzer, der die Datei anlegt, nicht dieser Gruppe angehört - hier kann dann ein fremder Benutzer die Quota einer Gruppe belasten, der er nicht angehört. Es ist also Aufgabe einer Gruppe, die Zugriffsrechte an ihren Verzeichnissen so zu setzen, daß dort nicht fremde Leute Daten ablegen können und so die Quota der Gruppe belasten.
Es ist außerdem möglich (wenn auch unwahrscheinlich), daß ein Benutzer so eine Datei anlegen kann, die er später nicht mehr lesen darf.
Das Szenario ist konstruiert, aber technisch möglich:
## Kris legt ein Verzeichnis an
kris@dhcp-179:~> mkdir keks
kris@dhcp-179:~> chmod a+rwx,g+s keks
kris@dhcp-179:~> chgrp video keks
kris@dhcp-179:~> ls -ld keks
drwxrwsrwx 2 kris video 48 2005-11-01 19:17 keks
## kdebuild legt dort eine Datei an
kdebuild@dhcp-179:/home/kris/keks> umask 0727
kdebuild@dhcp-179:/home/kris/keks> touch bla
kdebuild@dhcp-179:/home/kris/keks> ls -l bla
----r----- 1 kdebuild video 0 2005-11-01 19:18 bla
kdebuild@dhcp-179:/home/kris/keks> cat bla
cat: bla: Keine Berechtigung
Das ist für ein Rechtesystem eine unschöne Situation. Fällt jemandem ein sinnvoller Anwendungszweck für diese Eigenschaft des Unix-Rechtesystems ein?
Wir merken uns:
Um ein Verzeichnis zu erzeugen, auf das nur eine bestimmte Gruppe Zugriff hat, legen wir das Verzeichnis an und schenken es der Gruppe mit
chgrp
, dann setzen wir die Zugriffsrechte aufrwxrwx---
oder ähnlich.Wenn wir außerdem das SGID-Bit am Verzeichnis mit
chmod g+s …
setzen, werden auch alle Dateien im Verzeichnis der Gruppe gehören. Um ein Verzeichnis einer Gruppe schenken zu können, muß man selbst Mitglied der Gruppe sein.
Zugriffsrechte an Dateien
In den letzten 30 Jahren war es in Unix immer so, daß eine Datei einen Eigentümer und eine Eigentümer-Gruppe hatte. Rechte wurden für den Eigentümer und die Eigentümer-Gruppe vergeben. Prozesse hatten ebenfalls einen Eigentümer und eine Gruppe, und Unix hat stur den folgenden simplen Test durchgeführt, um zu bestimmen, welche Rechte für eine Datei gelten:
- Stimmen der Datei-Eigentümer und der Prozeß-Eigentümer überein? Wenn ja, dann gelten die User-Rechte, also das erste rwx-Tripel. Das ist selbst dann der Fall, wenn in einem anderen Tripel bessere Rechte definiert sind.
- Stimmen die Datei-Eigentümergruppe und eine der primären oder sekundären Gruppen eines Prozesses überein? Wenn ja, dann gelten die Gruppen-Rechte, also das zweite rwx-Tripel. Das ist selbst dann der Fall, wenn im 3. Tripel bessere Rechte definiert sind.
- In allen anderen Fällen gelten die Rechte aus dem 3. Tripel.
Access Control Lists (ACLs)
Mit modernen Unixen ist es jedoch alles viel komplizierter geworden, denn nun können im Prinzip an einer Datei selber auch viele Benutzer- und Gruppenrechte kleben.
Zum Glück nicht per Default.
Damit die Lage kompliziert wird, muß man das betreffende
Dateisystem mit der Option acl
mounten. Im Beispiel erzeugen
wir zur Abwechslung mal ein reiserfs und mounten dies mit der
passenden Option. Mit den Kommandos getfacl
und setfacl
(“get
and set a file access control list”) können wir dann lustig
individuelle Zugriffsrechte vergeben.
dhcp-179:~ # lvcreate -l 10 -n test system
Logical volume "test" created
dhcp-179:~ # mkreiserfs -q /dev/system/test
mkreiserfs 3.6.18 (2003 www.namesys.com)
dhcp-179:~ # mount -o acl /dev/mapper/system-test /export/test
dhcp-179:~ # cd /export/test
dhcp-179:/export/test # touch keks
dhcp-179:/export/test # chmod 000 keks
dhcp-179:/export/test # setfacl -m u:kris:rwx,mask::rwx,g:video:rwx,u:kdebuild:rx keks
dhcp-179:/export/test # ls -l keks
----rwx---+ 1 root root 0 Nov 1 19:26 keks
dhcp-179:/export/test # getfacl keks
# file: keks
# owner: root
# group: root
user::---
user:kris:rwx
user:kdebuild:r-x
group::---
group:video:rwx
mask::rwx
other::---
Eine Datei mit einer ACL wird von ls mit einem “+"-Zeichen markiert. Statt den Rechten der Gruppe werden dann im zweiten Tripel die Rechte der Mask angezeigt.
Die Mask limitiert alle anderen Zugriffsrechte an der Datei ausgenommen den Eigentümer und Others. Sie legt also quasi die maximalen Rechte fest, die irgendjemand außer dem Eigentümer an der Datei haben kann, wenn er nicht die Defaultrechte bekommt.
Dies ist ein Kompatibilitätsmechanismus, der meistens das korrekte Verhalten von Programmen bewirken soll, die nichts von Zugriffsrechten wissen - sie bekommen durch Auslesen des zweiten Rechtetripels einen etwas optimistischen View auf die Rechte, die sie wahrscheinlich haben werden. :)
Das Kommando setfacl
kann jetzt die Rechte an einer Datei
modifizieren. Die Option -m
(modify) bewirkt das.
Im Beispiel werden Rechte für Benutzer (“u:”) und Gruppen (“g:”) sowie eine Mask (“m:”) definiert.
Liest man die ACL mit getfacl aus, wird recht schnell deutlich, was hier geschieht:
Der Eigentümer der Datei hat an ihr keine Rechte, der User kris hat die Rechte rwx, der User kdebuild hat die Rechte rx, die Defaultgruppe hat keine Rechte, die Gruppe video hat die Rechte rwx, und die Maske schränkt die Rechte von kris, kdebuild, video und der Defaultgruppe nicht ein.
Der Rest der Welt hat keine Rechte an dieser Datei.
Wir merken uns:
Dateisysteme, die mit der Option “acl” gemounted wurden, können beliebig komplizierte Rechteregeln pro Datei haben. Es ist mit einem “+” an der Datei zu erkennen, ob dies der Fall ist. Diese ACLs können mit setfacl editiert und mit getfacl gelesen werden.
ACLs an Verzeichnissen
Um die Sache noch komplizierter zu machen, haben Verzeichnisse zwei ACLs:
- Eine normale wie wir sie schon kennen, die für das Verzeichnis selber gilt,
- eine default ACL, die für alle Verzeichnisse und Dateien gilt, die in dem Verzeichnis erzeugt werden.
Werte für die Default-ACL werden festgelegt, indem man sie beim “setfacl” mit “d:” prefixed, also “d:u:kris:rwx”, “d:g:video:rwx” und “dⓜ️:rwx”.
TL;DR
Wir merken uns:
In den allermeisten Fällen tut das Unix-Rechtesystem mit den drei Tripeln “ugo” und den drei Rechten “rwx” genau das, was man von ihm will.
Sehr selten braucht man was komplizierteres, und dann steht es zur Verfügung.
Selbst dann ist das Rechtesystem von Unix noch einfacher und übersichtlicher zu warten als das von Windows, getreu dem Motto “Simple things should be simple, and complex things should be possible.”