POSIX ACL

A Unix/Linux szerverek üzemeltetése wikiből
(Változatok közti eltérés)
a (Hozzáférési ACL: átdolgozás 2)
(Az ACL-ek felépítése és működése: a linux viselkedése bug)
 
(egy szerkesztő 22 közbeeső változata nincs mutatva)
1. sor: 1. sor:
Írta: Tevesz Ágnes, 2009. december.
+
Írta: Tevesz Ágnes és Korn András, 2009. december. Utolsó jelentős módosítás: 2012. november.
   
 
A POSIX ACL (hozzáférés-vezérlési listák) a hagyományos unixos fájlrendszer-jogosultságrendszer kiterjesztése. Olyan jogosultság-konstrukciók is leírhatók a segítségével, amelyek a hagyományos jogosultságrendszerrel nem: pl. hogy egy adott fájlt egy csoport tagjai írhassák és olvashassák, egy másik csoport tagjai csak olvashassák, a többiek pedig se ne írhassák, se ne olvashassák.
 
A POSIX ACL (hozzáférés-vezérlési listák) a hagyományos unixos fájlrendszer-jogosultságrendszer kiterjesztése. Olyan jogosultság-konstrukciók is leírhatók a segítségével, amelyek a hagyományos jogosultságrendszerrel nem: pl. hogy egy adott fájlt egy csoport tagjai írhassák és olvashassák, egy másik csoport tagjai csak olvashassák, a többiek pedig se ne írhassák, se ne olvashassák.
5. sor: 5. sor:
 
== Bevezetés ==
 
== Bevezetés ==
   
Azok a rendszerek, amelyek támogatják/megvalósítják a POSIX- szabványokat (Portable Operating System Interface), általában egy egyszerű, de hatékony fájl-jogosultsági modellt használnak. Minden fájlhoz három jogosultsághalmaz tartozik: külön megadható, milyen jogai legyenek a fájl tulajdonosának, a fájlt birtokló csoportnak és rajtuk kívül mindenk másnak. A három jogosultsághalmaz három-három bitből áll: ezek az olvasás (r), az írás (w) és végrehajtás (x) jogát reprezentálják. Az így kapott jogokat, minden fájl illetve könyvtár esetében, kilenc biten tudjuk tárolni. Megadható ezen felül a ''felhasználói azonosító beállítása'' (set user id), a ''csoportazonosító beállítása'' (set group id) és a ''ragadós'' (sticky) bit is.
+
Azok a rendszerek, amelyek támogatják/megvalósítják a POSIX-szabványokat (Portable Operating System Interface), általában egy egyszerű, de hatékony [[Tervezői_döntések_a_Unixban#A_f.C3.A1jlok_jogosults.C3.A1grendszere|fájl-jogosultsági modell]]t használnak. Minden fájlhoz három jogosultsághalmaz tartozik: külön megadható, milyen jogai legyenek a fájl tulajdonosának, a fájlt birtokló csoportnak és rajtuk kívül mindenk másnak. A három jogosultsághalmaz három-három bitből áll: ezek az olvasás (r), az írás (w) és végrehajtás (x) jogát reprezentálják. Az így kapott jogokat, minden fájl illetve könyvtár esetében, kilenc biten tudjuk tárolni. Megadható ezen felül a ''felhasználói azonosító beállítása'' (set user id), a ''csoportazonosító beállítása'' (set group id) és a ''ragadós'' (sticky) bit is.
   
Az összetett feladatok ellátására ez a modell nem biztosított elég lehetőséget, ezért indították a POSIX 1003.1e fejlesztését és így született meg az ACL (Access Control List) szabványtervezet, amely azonban sosem vált szabvánnyá és már valószínűleg nem is fog. A jövő útja valószínűleg az [http://www.suse.de/~agruen/nfs4acl/ NFSv4 ACL]-eké, de ezeket jelen sorok írásakor csak a szabad unix-féleségek közül csak a [http://en.wikipedia.org/wiki/Access_control_list#Filesystem_ACLs FreeBSD és az OpenSolaris támogatja], míg az 1003.1e szerinti ACL-eket a Linux is; ráadásul a megvalósítás kiforrottnak tekinthető, és a felhasználói programok oldaláról is megvan a szükséges támogatás, úgyhogy még érdemes ezzel az ACL-rendszerrel foglalkozni.
+
Az összetett feladatok ellátására ez a modell nem biztosított elég lehetőséget, ezért indították a POSIX 1003.1e fejlesztését és így született meg az ACL (Access Control List) szabványtervezet, amely azonban sosem vált szabvánnyá és már valószínűleg nem is fog. A jövő útja valószínűleg az [http://wiki.linux-nfs.org/wiki/index.php/ACLs NFSv4 ACL]-eké, de ezeket jelen sorok írásakor (2009. végén) a szabad unix-féleségek közül csak a [http://en.wikipedia.org/wiki/Access_control_list#Filesystem_ACLs FreeBSD és az IllumOS támogatja], míg az 1003.1e szerinti ACL-eket a Linux is; ráadásul a megvalósítás kiforrottnak tekinthető, és a felhasználói programok oldaláról is megvan a szükséges támogatás, úgyhogy még érdemes ezzel az ACL-rendszerrel foglalkozni. (Egy némileg [http://www.suse.de/~agruen/nfs4acl/ elavult NFSv4 ACL patch létezik Linuxhoz is]; ennek a fejlesztése "[http://www.bestbits.at/richacl/ Richacl]" néven folytatódik.)
   
== Az ACL-ek felépítése ==
+
== Az ACL-ek felépítése és működése ==
   
Egy ACL bejegyzések sokaságából épül fel (ACE). Egy ACL-bejegyzés három információt tartalmaz:
+
Egy ACL bejegyzések sokaságából épül fel (ACE, access control entry). Egy ACL-bejegyzés három információt tartalmaz:
   
 
* A bejegyzés típusa. A következő típusok léteznek (zárójelben a típusok kódja -- a későbbiekben a rövidség érdekében gyakran a kóddal fogok hivatkozni a bejegyzéstípusokra):
 
* A bejegyzés típusa. A következő típusok léteznek (zárójelben a típusok kódja -- a későbbiekben a rövidség érdekében gyakran a kóddal fogok hivatkozni a bejegyzéstípusokra):
65. sor: 65. sor:
 
Minden ACL kötelezően tartalmaz egy USER_OBJ, egy GROUP_OBJ és egy OTHER típusú bejegyzést. Azokat az ACL-eket, amelyek ezen a három bithármason kívül további elemeket is tartalmaznak, kiterjesztett vagy bővített ACL-eknek hívjuk. Ezek tartalmaznak egy ''mask'' bejegyzést illetve megnevezett felhasználókat és csoportokat is. Más szavakkal: ha egy ACL-ben szerepel GROUP vagy USER típusú (tehát konkrét felhasználóra vagy konkrét csoportra vonatkozó) bejegyzés, akkor kötelezően tartalmaz egy MASK típusú bejegyzést is; a MASK bejegyzés minden egyéb esetben opcionális.
 
Minden ACL kötelezően tartalmaz egy USER_OBJ, egy GROUP_OBJ és egy OTHER típusú bejegyzést. Azokat az ACL-eket, amelyek ezen a három bithármason kívül további elemeket is tartalmaznak, kiterjesztett vagy bővített ACL-eknek hívjuk. Ezek tartalmaznak egy ''mask'' bejegyzést illetve megnevezett felhasználókat és csoportokat is. Más szavakkal: ha egy ACL-ben szerepel GROUP vagy USER típusú (tehát konkrét felhasználóra vagy konkrét csoportra vonatkozó) bejegyzés, akkor kötelezően tartalmaz egy MASK típusú bejegyzést is; a MASK bejegyzés minden egyéb esetben opcionális.
   
A maszk a jogosultságok elbírálásakor jut szerephez. Ha egy processz megpróbál megnyitni egy olyan fájlt amelyhez bővített ACL tartozik, egy jogosultságvizsgáló algoritmus fut le, amelynek a működése a következőképpen foglalható össze:
+
A maszk a jogosultságok elbírálásakor jut szerephez. Ha egy processz megpróbál megnyitni egy olyan fájlt, amelyhez bővített ACL tartozik, egy jogosultságvizsgáló algoritmus fut le, amelynek a működése a következőképpen foglalható össze:
   
 
# Ha a processz effektív UID-ja megegyezik a fájl tulajdonosáéval, akkor a USER_OBJ bejegyzésben megadott jogosultságbitek az érvényesek.
 
# Ha a processz effektív UID-ja megegyezik a fájl tulajdonosáéval, akkor a USER_OBJ bejegyzésben megadott jogosultságbitek az érvényesek.
# Egyéb esetben a processz effektív UID-jára, effektív GID-jára és kiegészítő csoportjaira vonatkozó ACL-bejegyzésekben megadott jogosultságokat VAGY kapcsolatba hozzuk egymással, az eredményt pedig ÉS kapcsolatba hozzuk a maszkkal. Az így kapott jogosultságbiteket tekintjük érvényesnek; ha ezek lehetővé teszik a fájl megnyitását, akkor az sikerül, ha nem, akkor nem.
+
# Ha nem egyezik, és van a processz effektív UID-jára vonatkozó USER típusú ACL-bejegyzés, az ebben szereplő jogosultságbitek és a maszk ÉS kapcsolata az irányadó, kivéve, ha a maszk üres ("---"), mert akkor az OTHER bejegyzés az irányadó.
  +
#* Ez azt jelenti, hogy az OTHER-ben beállított engedélyek felülírhatják a nevesített user ACL-ekben levő tiltásokat!
  +
# Ha nincs ilyen bejegyzés, és a processz effektív GID-ja megegyezik a fájl tulajdonoscsoportjával, akkor a GROUP_OBJ bejegyzésben megadott jogosultságbitek az irányadóak. A maszk nem jut szerephez.
  +
# Ha nem egyezik meg, akkor, ha a maszk nem üres, a processz effektív GID-jára és kiegészítő csoportjaira vonatkozó ACL-bejegyzésekben megadott jogosultságokat VAGY kapcsolatba hozzuk egymással, az eredményt ÉS kapcsolatba hozzuk a maszkkal, és így kapott jogosultságbiteket tekintjük irányadónak; ha ezek lehetővé teszik a fájl megnyitását, akkor az sikerül, ha nem, akkor nem.
  +
# Ha a maszk üres volt, akkor az OTHER-ben levő jogosultságbitek az irányadóak.
  +
#* Vagyis: az OTHER-ben megadott engedély megint erősebb, mint bármiféle tiltás!
  +
# Ha nincs ilyen ACL-bejegyzés, akkor az OTHER típusú bejegyzésben szereplő jogosultságbitek jutnak érvényre.
   
Vegyük észre, hogy ez azt jelenti, hogy az engedélyező ACL-bejegyzések "erősebbek" a tiltóknál.
+
Vegyük észre, hogy ez azt jelenti, hogy az azonos típusú ACL-bejegyzések közül az engedélyezők "erősebbek" a tiltóknál, az OTHER-ben megadott engedélyek pedig üres maszk esetén "mindent visznek", kivéve, ha az effektiv UID ill. GID egyezik a tulajdonossal ill. tulajdonoscsoporttal. Intuitív, ugye? :) (Ez valószínűleg bug a Linuxban; a Solaris 9 üres maszk esetén is "helyesen" viselkedik. Ha lesz időm, jelentem, hátha megjavítják.)
  +
  +
Megjegyzés: az itt leírt algoritmus az, amelyet a Linux ténylegesen megvalósítani látszik; az <tt>acl(5)</tt> manpage által leírt algoritmus nem pontosan ez. Nem világos, hogy az implementáció vagy a dokumentáció hibás.
   
 
Az alábbi táblázat egy egyszerű példán kersztül szemlélteti a maszk működését:
 
Az alábbi táblázat egy egyszerű példán kersztül szemlélteti a maszk működését:
79. sor: 79. sor:
 
!Jogok
 
!Jogok
 
|-
 
|-
|konkrét felhasználó
+
|konkrét csoport
|user:név:rw-
+
|group:név:r-x
 
|r-x
 
|r-x
 
|-
 
|-
92. sor: 92. sor:
 
|}
 
|}
   
Ha valamilyen hagyományos, tehát ACL-eket nem támogató eszközzel kérdezzük le egy fájl jogosultságbitjeit, valahogyan meg kell bennük jeleníteni az ACL által reprezentált jogokat is; tehát szükségünk van egy leképezésre, ami az ACL tartalmát hagyományos unixos jogosultságbitekre képezi le. Egy ilyen leképezés természetesen nem lehet bijekció, hiszen az ACL-nek nagyobb a kifejezőereje, mint a jogosultságbiteknek; de egyértelmű azért lehet. A következő megoldást találták ki:
+
=== ACL leképezése hagyományos jogosultságbitekre ===
   
# A tulajdonos jogosultságbitjei megegyeznek a USER_OBJ típusú ACL-bejegyzés tartalmával.
+
Ha valamilyen hagyományos, tehát ACL-eket nem támogató eszközzel kérdezzük le egy fájl jogosultságbitjeit, valahogyan meg kell bennük jeleníteni az ACL által reprezentált jogokat is; tehát szükségünk van egy leképezésre, ami az ACL tartalmát hagyományos unixos jogosultságbitekre képezi le. Egy ilyen leképezés természetesen nem lehet bijekció, hiszen az ACL-nek nagyobb a kifejezőereje, mint a jogosultságbiteknek; de egyértelmű azért lehet.
# Az "egyéb" jogosultságbitjei megegyeznek az OTHER típusú ACL-bejegyzés tartalmával.
+
  +
<small>Ha fontos lenne, hogy a programok a lekérdezett jogosultságbitek alapján maguk is eldönthessék, van-e joguk írni vagy olvasni egy fájlt, akkor a leképezésnek "személyre szabottnak" kellene lennie, tehát a futó processz EUID-ja, EGID-ja és csoporttagságai ismeretében olyan jogosultságbiteket kellene prezentálni, amelyek az effektív hozzáférési jogosultságokat tükrözik. Tehát például, ha egy fájl ACL-je <tt>u::rwx,g::r--,g:csop1:rw,o::---,m::rwx</tt> (vagyis csak a tulajdonos és a csop1 csoport számára írható), akkor azon processzeknek, amelyek EGID-ja nem egyezik meg a tulajdonoscsoportéval, de tagjai a <tt>csop1</tt> csoportnak, azt kellene mutatnunk, hogy az "other" bitcsoport értéke rw. Szerencsére azonban erre szinte soha ''nincs'' szükség, mivel a programoknak alapvetően nem feladata a kernelben amúgy is meglevő jogosultságkezelés reimplementálása (ez mindenképpen csak tökéletlenül sikerülhetne, hiszen lehetetlen transzcendentális módon megállapítani, milyen műveleteket engedélyezne a kernel; vagyis, amíg meg nem próbálunk meg egy műveletet végrehajtani, nem tudjuk megbízhatóan eldönteni, van-e hozzá jogunk).</small>
  +
  +
A POSIX ACL jogosultságbitekre való leképezésére a következő megoldást találták ki:
  +
  +
# A tulajdonos jogosultságbitjei megegyeznek a USER_OBJ típusú ACL-bejegyzés tartalmával (ez elég természetes).
  +
# Az "egyéb" jogosultságbitjei megegyeznek az OTHER típusú ACL-bejegyzés tartalmával (szintén elég természetes).
 
# A tulajdonoscsoport látszólagos jogosultságbitjei a következőképpen állnak elő:
 
# A tulajdonoscsoport látszólagos jogosultságbitjei a következőképpen állnak elő:
## Ha van MASK típusú bejegyzés az ACL-ben, akkor a tulajdonoscsoport látszólagos jogai a maszk értékével egyeznek meg.
+
## Ha van MASK típusú bejegyzés az ACL-ben, akkor a tulajdonoscsoport látszólagos jogai a maszk értékével egyeznek meg. Ez egyáltalán nem intuitív, és pl. a <tt>find(1) -perm</tt>-et is át tudja verni.
 
## Ha nincs MASK típusú bejegyzés az ACL-ben, akkor a tulajdonoscsoport jogai a GROUP_OBJ típusú bejegyzés értékével egyeznek meg.
 
## Ha nincs MASK típusú bejegyzés az ACL-ben, akkor a tulajdonoscsoport jogai a GROUP_OBJ típusú bejegyzés értékével egyeznek meg.
   
104. sor: 104. sor:
 
Alapértelmezés szerint, amikor módosítjuk az ACL-t egy fájlon vagy könyvtáron, a maszk újraszámolódik és a nevesített felhasználókra és csoportokra vonatkozó jogosultságok összességének VAGY-kapcsolatával fog megegyezni; így, ha pl. egy <tt>ls -l</tt> kimenetét nézzük, képet kapunk arról, legfeljebb milyen jogokat osztottunk ki ACL-ek formájában.
 
Alapértelmezés szerint, amikor módosítjuk az ACL-t egy fájlon vagy könyvtáron, a maszk újraszámolódik és a nevesített felhasználókra és csoportokra vonatkozó jogosultságok összességének VAGY-kapcsolatával fog megegyezni; így, ha pl. egy <tt>ls -l</tt> kimenetét nézzük, képet kapunk arról, legfeljebb milyen jogokat osztottunk ki ACL-ek formájában.
   
Azt is jó tudni, hogy a fent leírt leképezés igazából nem a jogok kiolvasásakor, hanem a fájlrendszerben történő rögzítésükkor történik meg (hiszen az inode-ban adottak a jogosultságbitekhez tartozó mezők, ahová valamilyen értéket be kell írni). Ez azért fontos, mert előfordulhatnak (és elő is fordulnak) olyan hibák, amikor a tulajdonoscsoport jogait tartalmazó mezőbe valami miatt nem a maszk értéke kerül (vagy fordítva), és amíg nem nézzük meg közelről a teljes ACL-t, csak tanácstalanul vakarjuk a fejünket és nem értjük, miért nem működnek az ACL-lel beállított jogok. Jelen sorok írásakor pl. az <tt>xfsrestore</tt> állít be nullás maszkot úgy, hogy azt az értéket, amelynek a maszkban szerepelnie kellene, a tulajdonoscsoport jogosultságaihoz azért beírja. Így ránézésre látszólag minden rendben van, a gyakorlatban viszont nem jut érvényre az ACL, mert minden bitet kimaszkolunk belőle.
+
Azt is jó tudni, hogy a fent leírt leképezés igazából nem a jogok kiolvasásakor, hanem a fájlrendszerben történő rögzítésükkor történik meg (hiszen az inode-ban adottak a jogosultságbitekhez tartozó mezők, ahová valamilyen értéket mindenképpen be kell írni). Ez azért fontos, mert előfordulhatnak (és elő is fordulnak) olyan hibák, amikor a tulajdonoscsoport jogait tartalmazó mezőbe valami miatt nem a maszk értéke kerül (vagy fordítva), és amíg nem nézzük meg közelről a teljes ACL-t, csak tanácstalanul vakarjuk a fejünket és nem értjük, miért nem működnek az ACL-lel beállított jogok. Jelen sorok írásakor (2009. végén) pl. az <tt>xfsrestore</tt> állít be nullás maszkot úgy, hogy azt az értéket, amelynek a maszkban szerepelnie kellene, a tulajdonoscsoport jogosultságaihoz azért beírja. Így ránézésre látszólag minden rendben van, a gyakorlatban viszont nem jut érvényre az ACL, mert minden bitet kimaszkolunk belőle.
  +
  +
Példa:
  +
  +
<pre>
  +
% setfacl -m g::rwx,m::--- test
  +
% ls -la test
  +
-rw----r--+ 1 root root 0 Nov 20 18:26 test
  +
% getfacl test
  +
# file: test
  +
# owner: root
  +
# group: root
  +
user::rw-
  +
group::rwx #effective:---
  +
mask::---
  +
other::r--
  +
  +
% chmod 720 test
  +
% ls -la test
  +
-rwx-w----+ 1 root root 0 Nov 20 18:26 test*
  +
%getfacl test
  +
# file: test
  +
# owner: root
  +
# group: root
  +
user::rwx
  +
group::rwx #effective:-w-
  +
mask::-w-
  +
other::---
  +
</pre>
  +
  +
* A tulajdonoscsoportnak minden joga megvan, de ezeket a jogokat a maszk kimaszkolja.
  +
* Az ls kimenetében a maszkot látjuk, nem a tulajdonoscsoport jogait.
  +
* A chmod a maszkot állította át, nem a tulajdonoscsoport jogait.
   
 
== Hozzáférési ACL ==
 
== Hozzáférési ACL ==
110. sor: 110. sor:
 
Az eddigiekben bemutatott ACL-ek segítségével viszonylag finoman szabályozhatjuk, hogy létező fájlrendszer-objektumokhoz való hozzáféréskor mely felhasználóknak és mely csoportoknak milyen jogai legyenek. Az ilyen típusú ACL-eket hozzáférési ACL-nek hívják.
 
Az eddigiekben bemutatott ACL-ek segítségével viszonylag finoman szabályozhatjuk, hogy létező fájlrendszer-objektumokhoz való hozzáféréskor mely felhasználóknak és mely csoportoknak milyen jogai legyenek. Az ilyen típusú ACL-eket hozzáférési ACL-nek hívják.
   
Nézzünk egy példát. Állítsuk az ''umask''unkat 033-ra; ezzel az újonnan létrehozott fájlok és könyvtárak jogosultságbitjeiből kimaszkoltuk a tulajdonoscsoport és az egyéb végrehajtási és írási jogát (1-es ill. 2-es bit; a 4-es az olvasás).
+
Nézzünk egy példát. Állítsuk az ''umask''unkat 003-ra; ezzel az újonnan létrehozott fájlok és könyvtárak jogosultságbitjeiből kimaszkoltuk az "egyéb" végrehajtási és írási jogát (1-es ill. 2-es bit; a 4-es az olvasás).
   
 
<pre>
 
<pre>
umask 033
+
% umask 003
mkdir konyvtar
+
% mkdir konyvtar
ls -dl konyvtar
+
% ls -dl konyvtar
drwxr--r-- [...] júzer csoport [...] konyvtar
+
drwxrwxr-- [...] júzer csoport [...] konyvtar
 
</pre>
 
</pre>
 
A pontok helyén levő információk most nem fontosak.
 
A pontok helyén levő információk most nem fontosak.
 
Most írassuk ki a <tt>getfacl</tt> paranccsal az ACL-t. A <tt>getfacl</tt> paranccsal megjeleníthetjük egy fájl nevét, tulajdonosát, csoportját és a hozzá tartozó ACL-t.
 
Most írassuk ki a <tt>getfacl</tt> paranccsal az ACL-t. A <tt>getfacl</tt> paranccsal megjeleníthetjük egy fájl nevét, tulajdonosát, csoportját és a hozzá tartozó ACL-t.
 
<pre>
 
<pre>
getfacl konyvtar
+
% getfacl konyvtar
 
# file: konyvtar
 
# file: konyvtar
 
# owner: júzer
 
# owner: júzer
 
# group: csoport
 
# group: csoport
 
user::rwx
 
user::rwx
group::r--
+
group::rwx
 
other::r--
 
other::r--
 
</pre>
 
</pre>
132. sor: 132. sor:
 
Nézzük meg, hogy hogyan tudnánk egy megnevezett felhasználónak, mondjuk Bobnak jogokat biztosítani. Mivel Bobot szeretjük, olvasási, írási és végrehajtási jogot is adunk neki. A <tt>-m</tt> paraméter segítségével tudjuk módosítani a jogokat.
 
Nézzük meg, hogy hogyan tudnánk egy megnevezett felhasználónak, mondjuk Bobnak jogokat biztosítani. Mivel Bobot szeretjük, olvasási, írási és végrehajtási jogot is adunk neki. A <tt>-m</tt> paraméter segítségével tudjuk módosítani a jogokat.
 
<pre>
 
<pre>
setfacl -m u:bob:rwx konyvtar
+
% setfacl -m u:bob:rwx konyvtar
getfacl konyvtar
+
% getfacl konyvtar
 
# file: konyvtar
 
# file: konyvtar
 
# owner: júzer
 
# owner: júzer
139. sor: 139. sor:
 
user::rwx
 
user::rwx
 
user:bob:rwx
 
user:bob:rwx
group::r--
+
group::rwx
 
mask::rwx
 
mask::rwx
 
other::r--
 
other::r--
146. sor: 146. sor:
 
(Vegyük észre, hogy azt, hogy <tt>user:bob:rwx</tt> rövidíthettük úgy, hogy <tt>u:bob:rwx</tt>.)
 
(Vegyük észre, hogy azt, hogy <tt>user:bob:rwx</tt> rövidíthettük úgy, hogy <tt>u:bob:rwx</tt>.)
   
Itt megjelenik ugyebár a Bob nevű felhasználó bejegyzése és a ''mask'' típusú bejegyzés. A ''mask'' bejegyzés automatikusan létrejön, ha szükséges, és nem adtuk meg külön. Ahogy már említettem, a maszk alapértelmezés szerint a nevesített felhasználókra és csoportokra vonatkozó jogosultságok összességének VAGY-kapcsolatával fog megegyezni, így biztosan nem maszkol egyetlen jogot sem. Ha megnézzük az <tt>ls -dl konyvtar</tt> parancs kimenetét, a következőt láthatjuk:
+
Itt megjelenik ugyebár a Bob nevű felhasználó bejegyzése és a ''mask'' típusú bejegyzés. A ''mask'' bejegyzés automatikusan létrejön, ha szükséges, és nem adtuk meg külön. Ahogy már említettem, a maszk alapértelmezés szerint a nevesített felhasználókra és csoportokra, valamint a tulajdonoscsoportra vonatkozó jogosultságok összességének VAGY-kapcsolatával fog megegyezni, így biztosan nem maszkol egyetlen jogot sem. Ha megnézzük az <tt>ls -dl konyvtar</tt> parancs kimenetét, a következőt láthatjuk:
 
<pre>
 
<pre>
 
drwxrwx---+ [...] júzer csoport [...] konyvtar
 
drwxrwx---+ [...] júzer csoport [...] konyvtar
 
</pre>
 
</pre>
Itt a + jel azt mutatja, hogy ''konyvtar''hoz tartozik bővített ACL. Látszik az is, hogy a ''mask'' bejegyzés tartalma jelenik meg a tulajdonoscsoport jogai helyén; ez azért hasznos, mert a ''mask'' az ACL-ek által biztosított jogok felső korlátja. ''Csoport'' jogai még mindig csak az olvasásra korlátozódnak.
+
Itt a + jel azt mutatja, hogy ''konyvtar''hoz tartozik bővített ACL. Ugyan nem látszik, de most már a ''mask'' bejegyzés tartalma jelenik meg a tulajdonoscsoport jogai helyén; ez elvileg azért hasznos, mert a ''mask'' az ACL-ek által biztosított jogok felső korlátja.
   
 
Ha megpróbáljuk módosítani a tulajdonoscsoport jogait a <tt>chmod</tt> segítségével <tt>r-x</tt>-re, akkor a következő történik:
 
Ha megpróbáljuk módosítani a tulajdonoscsoport jogait a <tt>chmod</tt> segítségével <tt>r-x</tt>-re, akkor a következő történik:
 
<pre>
 
<pre>
chmod g-w konyvtar
+
% chmod g-w konyvtar
ls -dl konyvtar
+
% ls -dl konyvtar
 
drwxr-x---+ [...] júzer csoport [...] konyvtar
 
drwxr-x---+ [...] júzer csoport [...] konyvtar
getfacl --omit-header konyvtar
+
% getfacl --omit-header konyvtar
 
user::rwx
 
user::rwx
user:bob:rwx #az érvényesülő jogok:r-x
+
user:bob:rwx #effective:r-x
group::r--
+
group::rwx #effective:r-x
 
mask::r-x
 
mask::r-x
 
other::---
 
other::---
 
</pre>
 
</pre>
Ezen a példán látható a ''mask'' hatása: maszkolja a Bob felhasználó egyes jogait. Ha a <tt>chmod</tt>-dal visszaadnánk az írási jogot, akkor csak a Bob felhasználó tudná újra írni a könyvtárat, tehát a tulajdonoscsoport jogait ez nem érintené.
+
Ezen a példán látható a ''mask'' hatása: maszkolja a Bob felhasználó és a tulajdonoscsoport egyes jogait.
   
= Alapértelmezett ACL =
+
Most vegyük el a tulajdonoscsoport írási és végrehajtási jogát a maszk újraszámolása nélkül, majd chmoddal állítsunk be 2770-es jogokat:
Alapértelmezett ACL egy fájlrendszer objektum jogait úgy adja meg, hogy a létrehozásakor, a saját szülőkönyvtára jogait automatikusan örökíti a fájlrendszer objektumra. Ezekhez az ACL-ekhez csak könyvtárakat társíthatunk. Ha egy könyvtárba egy újabb könyvtárat hozunk létre, akkor a szülőkönyvtár úgy örökíti az alapértelmezett ACL-jét, hogy azt új könyvtár alapértelmezett és hozzáférési ACL-ként is átveszi. Ha egy fájlobjektumot hozunk létre, akkor az az alapértelmezett ACL-t hozzáférési ACL-ként örökli.
+
<pre>
  +
% setfacl -n -m g::r konyvtar
  +
% chmod 2770 konyvtar
  +
% ls -dl konyvtar
  +
drwxrws---+ [...] júzer csoport [...] konyvtar
  +
% getfacl konyvtar
  +
# file: konyvtar
  +
# owner: júzer
  +
# group: csoport
  +
# flags: -s-
  +
user::rwx
  +
user:bob:rwx
  +
group::r--
  +
mask::rwx
  +
other::---
  +
</pre>
  +
Látszik, hogy
  +
* hiába adna a 2770-es bitkombináció írási és végrehajtási jogot a tulajdonoscsoportnak, csak a maszk módosult;
  +
* a getfacl kimenetében megjelent az, hogy <tt>flags: -s-</tt>, ami azt jelenti, hogy a setgid bit be van állítva.
  +
A setgidnek igazából semmi köze az ACL-hez; csak azért van ott, hogy az ACL-ek könnyen lementhetőek és helyreállíthatóak legyenek anélkül, hogy a setuid/setgid/sticky bitek állapota elveszne. A getfacl segítségével ugyanis rekurzívan is kilistázhatjuk egy egész könyvtárfa összes ACL-jét, a setfacl pedig a getfacl kimenetét olvasva vissza tudja ezeket állítani; ha a getfacl kimenete nem tartalmazná a setuid/setgid/sticky bitet, akkor szinte használhatatlan lenne. [http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=270099 Sajnos évekig ez volt a helyzet.]
   
Új könyvtár vagy fájl létrehozásakor, az örökölt hozzáférési ACL-ek jogait tovább módosítja a mode paraméter. A mode kilenc biten kódolja, a tulajdonos, a csoport és az egyéb osztály jogait. A tényleges jogokat az ACL és a mode AND kapcsolataként értelmezhetjük. Ha a szülőkönyvtárnak nincs alapértelmezett ACL-je, az új fájl jogai a POSIX.1 alapján kerülnek kiosztásra. A fájl tényleges jogait úgy kapjuk, hogy a mode jogaiból kivonjuk az umask jogait. Ha létezik alapértelmezett ACL akkor az umask paramétereit a rendszer figyelmen kívül hagyja.
+
== Alapértelmezett ACL ==
   
== Péda alapértelmezett ACL-re ==
+
A hozzáférési ACL-eken túlmenően ún. alapértelmezett ACL-eket is használhatunk. Ha egy könyvtárhoz tartozik alapértelmezett ACL, akkor az adott könyvtárban ''újonnan'' létrehozott valamennyi fájlrendszer-objektum hozzáférési ACL-ként ezt az alapértelmezett ACL-t örökli (az új alkönyvtárak alapértelmezett ACL-ként is).
A „getfacl” paranccsal megjeleníthetjük egy fájl nevét, tulajdonosát, csoportját és az ACL-t, ha a könyvtárnak van alapértelmezett ACL-je, akkor a „getfacl” azt is megmutatja. A „setfacl” paranccsal tudjuk beállítani az ACL-eket a fájlokon és könyvtárakon.
+
Itt hozzáadunk egy alapértelmezett ACL-t a konyvtar könyvtárhoz.
+
Új fájlrendszer-objektum létrehozásakor, ha a szülőkönyvtárnak van alapértelmezett ACL-je, az alábbi történik:
  +
  +
* Az új objektum hozzáférési ACL-ként megkapja a szülőkönyvtár alapértelmezett ACL-jét.
  +
* Ezután a maszkot kivéve az összes ACL-bejegyzésből törlődik minden olyan bit, amely az objektumot létrehozó rendszerhívásnak átadott <tt>mode</tt> paraméterben (ami a létrehozandó objektum jogosultságbitjeit tartalmazza) nincs beállítva.
  +
* Az ''umask'' nem jut szerephez!
  +
  +
Lássunk egy példát! A <tt>setfacl</tt> paranccsal kétféleképpen is beállíthatunk default ACL-t; az alábbi két parancssor ekvivalens:
 
<pre>
 
<pre>
setfacl -d -m group:valami:r-x konyvtar
+
setfacl -d -m g:csoport2:r-x konyvtar
  +
setfacl -m d:g:csoport2:r-x konyvtar
 
</pre>
 
</pre>
A „getfacl” segítségével pedig megnézhetjük a módosításokat.
+
  +
(Linuxon az <tt>r-x</tt> helyett írhatunk csak simán <tt>rx</tt>-et is, de pl. Solarison nem: ott mindig pontosan három karakterrel kell megadnunk a jogosultságbiteket.)
  +
  +
A második forma előnye akkor mutatkozik meg, ha egyszerre akarunk hozzáférési és alapértelmezett ACL-t is létrehozni; a <tt>setfacl -m</tt> után ugyanis vesszővel elválasztva több ACL-elemet is felsorolhatunk, és a második szintaxis lehetővé teszi az alapértelmezett és a hozzáférési ACL-ek keverését, míg az első nem.
  +
  +
Nézzük meg, mit csináltunk!
 
<pre>
 
<pre>
 
getfacl konyvtar
 
getfacl konyvtar
 
# file: konyvtar
 
# file: konyvtar
# owner: ember
+
# owner: júzer
# group: csapat
+
# group: csoport
 
user::rwx
 
user::rwx
 
user:bob:rwx
 
user:bob:rwx
 
group::r-x
 
group::r-x
group:valami:rwx
 
 
mask::rwx
 
mask::rwx
 
other::---
 
other::---
 
default:user::rwx
 
default:user::rwx
 
default:group::r-x
 
default:group::r-x
default:group:valami:r-x
+
default:group:csoport2:r-x
 
default:mask::r-x
 
default:mask::r-x
 
default:other::---
 
default:other::---
 
</pre>
 
</pre>
Az alapértelmezett ACL elé a „default:” előtagot illeszti, a hozzáférési ACL e felett látható, előtag nélkül. Ezt a formátumot a POSIX.1e mutatja, ez Solarison és Linuxon látható így, a POSIX 1003.2c szabvány csak a hozzáférési ACL-t mutatná és az alapértelmezett ACL előhívásához a „getfacl” parancshoz egy „-d” paramétert kéne adnunk. Az alapértelmezett ACL bejegyzések közül mi csak a valami csoport bejegyzését definiáltuk, a többit automatikusan átvette a hozzáférési ACL-ek közül. Ez csak Linux rendszerek tulajdonsága, egyéb rendszereken meg kéne adnunk az alapértelmezett ACL minden bejegyzését.
 
   
Ha egy alkönyvtárt hozunk létre a könyvtárba a „mkdir” paranccsal, ami 0777-es „mode” paraméterrel hozza létre könyvtárunkat, akkor a következőképp öröklődnek a jogok. Ha a „mode” paraméter megváltoztatásával a jogokat redukáljuk, akkor az ACL bejegyzések jogai közül is törlődnek az adott jogok.
+
A default ACL megjelenítésével és működésével kapcsolatban vannak különbségek az egyes implementációk között; pl. elképzelhető, hogy a default ACL-t csak akkor látjuk, ha <tt>-d</tt> kapcsolóval hívjuk meg a <tt>getfacl</tt>. Azt is vegyük észre, hogy a Linux automatikusan létrehozott a hozzáférési ACL alapján néhány alapértelmezett ACL-bejegyzést; ez sem feltétlenül történik ugyanígy minden más oprendszeren.
Egy alkönyvtárt készítve nézzük, hogyan öröklődnek a jogok.
+
  +
Hozzunk most létre egy alkönyvtárat az <tt>mkdir</tt> paranccsal! Az <tt>mkdir(1)</tt> program 0777-es ''mode'' paraméterrel hívja meg az <tt>mkdir()</tt> rendszerhívást. Lássuk, milyen ACL-t kap az uj alkönyvtár:
 
<pre>
 
<pre>
 
mkdir konyvtar/alkonyvtar
 
mkdir konyvtar/alkonyvtar
 
getfacl konyvtar/alkonyvtar
 
getfacl konyvtar/alkonyvtar
 
# file: konyvtar/alkonyvtar
 
# file: konyvtar/alkonyvtar
# owner: ember
+
# owner: júzer
# group: csapat
+
# group: csoport
 
user::rwx
 
user::rwx
 
group::r-x
 
group::r-x
group:valami:r-x
+
group:csoport2:r-x
 
mask::r-x
 
mask::r-x
 
other::---
 
other::---
 
default:user::rwx
 
default:user::rwx
 
default:group::r-x
 
default:group::r-x
default:group:valami:r-x
+
default:group:csoport2:r-x
 
default:mask::r-x
 
default:mask::r-x
 
default:other::---
 
default:other::---
 
</pre>
 
</pre>
Látható, hogy az új könyvtár az ACL-t mint hozzáférési és alapértelmezett ACL-t is örökölte. Ebben az esetben nem változtattunk a „mode” paraméteren.
+
Látható, hogy az új könyvtár az ACL-t mint hozzáférési és alapértelmezett ACL-t is örökölte.
   
= Hozzáférést ellenőrző algoritmus =
+
== Alkalmazási példák ==
Amikor egy folyamat megpróbál hozzáférni egy fájlrendszer objektumhoz, akkor először kiválasztja azt az ACL-t ami leginkább megegyezik a folyamat jogaival, majd leellenőrzi, hogy a bejegyzés tartalmazza-e a kellő jogokat. Egy folyamat több mint egy csoportnak lehet tagja, tehát több mint egy csoport bejegyzésére lehet igaz, hogy tartalmazza a megfelelő jogokat.
 
Először tehát megvizsgálja, hogy melyik bejegyzés írja le legjobban a folyamat jogait. Majd a hozzáférést ellenőrző algoritmus ebben a sorrendben ellenőrzi az ACL bejegyzéseket:
 
#tulajdonos
 
#megnevezett felhasználó
 
#tulajdonoscsoport
 
#megnevezett csoport
 
#egyéb
 
Utoljára megvizsgálja, hogy ha talált egyező bejegyzést, az rendelkezik-e a megfelelő jogokkal.
 
   
= Példa alkalmazásokkal való használatra =
+
Tegyük fel, hogy van egy SSL-kulcsunk. Nem szeretnénk, hogy bárki elolvashassa, kivéve a webszervert. A webszerver a <tt>www-data</tt> nevű felhasználó jogaival fut. Ha a <tt>www-data</tt> felhasználó tulajdonába helyezzük a fájlt, akkor ő el tudja rajta állítani a jogokat is, amit nem szeretnénk; ACL-lel viszont megoldhatjuk, hogy a <tt>root</tt> tulajdonában maradjon, de a <tt>www-data</tt> is el tudja olvasni a tartalmát anélkül, hogy a jogokat elállíthatná. ACL nélküli megoldás is van: legyen saját csoportja a <tt>www-data</tt> usernek, és birtokolja ez a csoport az SSL-kulcsot. Ha csak a csoportnak van rá olvasási joga, akkor nem tudja elállítani a jogokat.
Az ACL-ek segítségével képesek programok „jogokat kapni” azáltal, hogy olyan felhasználó neve alatt indulnak el, akinek joga van bizonyos fájlok kiterjedtebb körű használatához. A többi felhasználónak lehet, hogy kevesebb jogot biztosítunk, mint a programnak, vagyis annak a felhasználónak, akinek a nevében a program fut. Erre nagyon jó példa az apache webszerver indítása és működtetése. Indítunk „root”-ként egy apache-ot és a httpd.conf-ban mondjuk az „apache”-ot adjuk meg mint felhasználót, amelynek a nevében indul. Ekkor az apache egyes részei mint „root”, más részei mint „apache” fognak futni.
+
<pre>
+
Ha víruskeresőt futtatunk a bejövő leveleken, általában különböző felhasználóként fut a levelezőszerver és a víruskereső. Azt szeretnénk, ha a levelezőszerver által létrehozott fájlok a víruskereső számára is olvashatóak lennének, de senki más számára nem lennének olvashatóak. Megtehetjük, hogy egy olyan könyvtárba tesszük ezeket a fájlokat, amelyen olyan alapértelmezett ACL van, amely a víruskeresős felhasználónak olvasási jogot biztosít. ACL nélkül megoldás: helyezzük közös csoportba ezt a két felhasználót, és az adott könyvtár legyen ennek a csoportnak a tulajdona, valamint setgid-es. Az is szükséges, hogy a levelezőszerver umaskja megfelelő legyen, tehát ne maszkolja ki a csoport olvasási jogát.
ps axuwww | grep httpd
+
root … /usr/sbin/httpd
+
== Potenciális ZH-kérdések ==
apache … … … /usr/sbin/httpd
+
apache /usr/sbin/httpd
+
* Milyen elemekből áll(hat) egy POSIX ACL? (A szimbolikus azonosítók nem kellenek betű szerint, csak a szerepük/funkciójuk.)
</pre>
+
* Mik a 100-as UID-val, 200-as GID-dal futó, 300-as és 400-as kiegészítő csoporttagsággal rendelkező processz effektív jogai azon a fájlon, amelynek a POSIX ACL-je az alábbi bejegyzéseket tartalmazza? (És itt jönne egy getfacl-kimenet.)
Nézzük meg, milyen jogai vannak az apache-nak, tegyük fel, hogy létezik az index.html.
+
* Mondjon példát olyan jogosultság-specifikációra, amely hagyományos unixos jogosultságokkal nem írható le ésszerűen, de POSIX ACL-ekkel igen!
<pre>
+
* Hogyan (és milyen esetekben) lehet a POSIX ACL-ek látszólag szükséges alkalmazását mégis elkerülni és hagyományos unixos jogosultságokkal ugyanazt a hatást elérni? Mutassa ezt be egy példán! (Segítség: lehet, hogy csak ésszerűtlen megoldás van.)
ls -lah /var/www/html/index.html
+
* Használható-e POSIX ACL arra, hogy egy csoport összes tagja számára mindenképpen biztosítsunk hozzáférést egy könyvtár tartalmához, akkor is, ha a csoport tagjai nem működnek ebben együtt? Miért?
-rw-r--r--. apache apache /var/www/html/index.html
+
* Mit látunk az <tt>ls -l</tt> kimenetében a jogosultságbitek helyén olyan könyvtárbejegyzések esetében, amelyekhez bővített POSIX ACL tartozik?
</pre>
 
Vegyük ismét Bob nevű felhasználónkat, akit most meg szeretnénk fosztani az olvasási jogától, de nem csak őt, hanem az összes többi felhasználót is.
 
<pre>
 
chmod o-r /var/www/html/index.html
 
ls -lah /var/www/html/index.html
 
-rw-r-----. … apache apache … /var/www/html/index.html
 
</pre>
 
Ekkor ugyebár, az apache még mindig tud írni és olvasni is, de Bob és az összes többi felhasználó már nem. Tehát a fájlhoz csak „root”-ként és „apache”-ként férhetünk hozzá, plusz a böngészőn keresztül olvashatjuk. Megtehetjük ennek az ellenkezőjét is, tehát adhatunk jogot Bobnak, de a többi felhasználónak nem. Ez pont a webszervereknél fontos, mivel, egy oldal tulajdonosa feltölthet fájlokat, módosíthatja a saját oldalát, de más oldalaihoz nem kap hozzáférést, illetve mások nem módosíthatják az ő oldalát.
 

A lap jelenlegi, 2012. november 20., 23:36-kori változata

Írta: Tevesz Ágnes és Korn András, 2009. december. Utolsó jelentős módosítás: 2012. november.

A POSIX ACL (hozzáférés-vezérlési listák) a hagyományos unixos fájlrendszer-jogosultságrendszer kiterjesztése. Olyan jogosultság-konstrukciók is leírhatók a segítségével, amelyek a hagyományos jogosultságrendszerrel nem: pl. hogy egy adott fájlt egy csoport tagjai írhassák és olvashassák, egy másik csoport tagjai csak olvashassák, a többiek pedig se ne írhassák, se ne olvashassák.

Tartalomjegyzék

[szerkesztés] 1 Bevezetés

Azok a rendszerek, amelyek támogatják/megvalósítják a POSIX-szabványokat (Portable Operating System Interface), általában egy egyszerű, de hatékony fájl-jogosultsági modellt használnak. Minden fájlhoz három jogosultsághalmaz tartozik: külön megadható, milyen jogai legyenek a fájl tulajdonosának, a fájlt birtokló csoportnak és rajtuk kívül mindenk másnak. A három jogosultsághalmaz három-három bitből áll: ezek az olvasás (r), az írás (w) és végrehajtás (x) jogát reprezentálják. Az így kapott jogokat, minden fájl illetve könyvtár esetében, kilenc biten tudjuk tárolni. Megadható ezen felül a felhasználói azonosító beállítása (set user id), a csoportazonosító beállítása (set group id) és a ragadós (sticky) bit is.

Az összetett feladatok ellátására ez a modell nem biztosított elég lehetőséget, ezért indították a POSIX 1003.1e fejlesztését és így született meg az ACL (Access Control List) szabványtervezet, amely azonban sosem vált szabvánnyá és már valószínűleg nem is fog. A jövő útja valószínűleg az NFSv4 ACL-eké, de ezeket jelen sorok írásakor (2009. végén) a szabad unix-féleségek közül csak a FreeBSD és az IllumOS támogatja, míg az 1003.1e szerinti ACL-eket a Linux is; ráadásul a megvalósítás kiforrottnak tekinthető, és a felhasználói programok oldaláról is megvan a szükséges támogatás, úgyhogy még érdemes ezzel az ACL-rendszerrel foglalkozni. (Egy némileg elavult NFSv4 ACL patch létezik Linuxhoz is; ennek a fejlesztése "Richacl" néven folytatódik.)

[szerkesztés] 2 Az ACL-ek felépítése és működése

Egy ACL bejegyzések sokaságából épül fel (ACE, access control entry). Egy ACL-bejegyzés három információt tartalmaz:

  • A bejegyzés típusa. A következő típusok léteznek (zárójelben a típusok kódja -- a későbbiekben a rövidség érdekében gyakran a kóddal fogok hivatkozni a bejegyzéstípusokra):
    1. tulajdonos (ACL_USER_OBJ);
    2. egyéb konkrét felhasználó (ACL_USER);
    3. tulajdonoscsoport (ACL_GROUP_OBJ);
    4. egyéb konkrét csoport (ACL_GROUP);
    5. maszk (ACL_MASK) - ezzel a USER, a GROUP_OBJ és a GROUP típusú ACL-ek által megadott jogokból kimaszkolhatunk bizonyos biteket, l. később;
    6. mindenki más (ACL_OTHER).
  • Annak a csoportnak vagy felhasználónak a neve, amelyikre az adott bejegyzés vonatkozik; ez lehet
    • üres, vagy
    • egy konkrét felhasználó vagy csoport.
  • Az adott felhasználóhoz vagy csoporthoz rendelt jogok:
    • a szokásos r/w/x bit formájában.

A szintaxis a következő:

<acl típusa>:<név>:<jogok>

Az alábbi táblázat az egyes bejegyzéstípusok szintaxisát részletesebben is bemutatja:

Típus Kód Szöveges forma
ACL-bejegyzéstípusok
tulajdonos ACL_USER_OBJ user::rwx
konkrét felhasználó ACL_USER user:név:rwx
tulajdonoscsoport ACL_GROUP_OBJ group::rwx
konkrét csoport ACL_GROUP group:név:rwx
maszk ACL_MASK mask::rwx
egyéb ACL_OTHER other::rwx

Minden ACL kötelezően tartalmaz egy USER_OBJ, egy GROUP_OBJ és egy OTHER típusú bejegyzést. Azokat az ACL-eket, amelyek ezen a három bithármason kívül további elemeket is tartalmaznak, kiterjesztett vagy bővített ACL-eknek hívjuk. Ezek tartalmaznak egy mask bejegyzést illetve megnevezett felhasználókat és csoportokat is. Más szavakkal: ha egy ACL-ben szerepel GROUP vagy USER típusú (tehát konkrét felhasználóra vagy konkrét csoportra vonatkozó) bejegyzés, akkor kötelezően tartalmaz egy MASK típusú bejegyzést is; a MASK bejegyzés minden egyéb esetben opcionális.

A maszk a jogosultságok elbírálásakor jut szerephez. Ha egy processz megpróbál megnyitni egy olyan fájlt, amelyhez bővített ACL tartozik, egy jogosultságvizsgáló algoritmus fut le, amelynek a működése a következőképpen foglalható össze:

  1. Ha a processz effektív UID-ja megegyezik a fájl tulajdonosáéval, akkor a USER_OBJ bejegyzésben megadott jogosultságbitek az érvényesek.
  2. Ha nem egyezik, és van a processz effektív UID-jára vonatkozó USER típusú ACL-bejegyzés, az ebben szereplő jogosultságbitek és a maszk ÉS kapcsolata az irányadó, kivéve, ha a maszk üres ("---"), mert akkor az OTHER bejegyzés az irányadó.
    • Ez azt jelenti, hogy az OTHER-ben beállított engedélyek felülírhatják a nevesített user ACL-ekben levő tiltásokat!
  3. Ha nincs ilyen bejegyzés, és a processz effektív GID-ja megegyezik a fájl tulajdonoscsoportjával, akkor a GROUP_OBJ bejegyzésben megadott jogosultságbitek az irányadóak. A maszk nem jut szerephez.
  4. Ha nem egyezik meg, akkor, ha a maszk nem üres, a processz effektív GID-jára és kiegészítő csoportjaira vonatkozó ACL-bejegyzésekben megadott jogosultságokat VAGY kapcsolatba hozzuk egymással, az eredményt ÉS kapcsolatba hozzuk a maszkkal, és így kapott jogosultságbiteket tekintjük irányadónak; ha ezek lehetővé teszik a fájl megnyitását, akkor az sikerül, ha nem, akkor nem.
  5. Ha a maszk üres volt, akkor az OTHER-ben levő jogosultságbitek az irányadóak.
    • Vagyis: az OTHER-ben megadott engedély megint erősebb, mint bármiféle tiltás!
  6. Ha nincs ilyen ACL-bejegyzés, akkor az OTHER típusú bejegyzésben szereplő jogosultságbitek jutnak érvényre.

Vegyük észre, hogy ez azt jelenti, hogy az azonos típusú ACL-bejegyzések közül az engedélyezők "erősebbek" a tiltóknál, az OTHER-ben megadott engedélyek pedig üres maszk esetén "mindent visznek", kivéve, ha az effektiv UID ill. GID egyezik a tulajdonossal ill. tulajdonoscsoporttal. Intuitív, ugye? :) (Ez valószínűleg bug a Linuxban; a Solaris 9 üres maszk esetén is "helyesen" viselkedik. Ha lesz időm, jelentem, hátha megjavítják.)

Megjegyzés: az itt leírt algoritmus az, amelyet a Linux ténylegesen megvalósítani látszik; az acl(5) manpage által leírt algoritmus nem pontosan ez. Nem világos, hogy az implementáció vagy a dokumentáció hibás.

Az alábbi táblázat egy egyszerű példán kersztül szemlélteti a maszk működését:

Típus Szöveges forma Jogok
konkrét csoport group:név:r-x r-x
mask mask::rw- rw-
Effektív jogok r--

[szerkesztés] 2.1 ACL leképezése hagyományos jogosultságbitekre

Ha valamilyen hagyományos, tehát ACL-eket nem támogató eszközzel kérdezzük le egy fájl jogosultságbitjeit, valahogyan meg kell bennük jeleníteni az ACL által reprezentált jogokat is; tehát szükségünk van egy leképezésre, ami az ACL tartalmát hagyományos unixos jogosultságbitekre képezi le. Egy ilyen leképezés természetesen nem lehet bijekció, hiszen az ACL-nek nagyobb a kifejezőereje, mint a jogosultságbiteknek; de egyértelmű azért lehet.

Ha fontos lenne, hogy a programok a lekérdezett jogosultságbitek alapján maguk is eldönthessék, van-e joguk írni vagy olvasni egy fájlt, akkor a leképezésnek "személyre szabottnak" kellene lennie, tehát a futó processz EUID-ja, EGID-ja és csoporttagságai ismeretében olyan jogosultságbiteket kellene prezentálni, amelyek az effektív hozzáférési jogosultságokat tükrözik. Tehát például, ha egy fájl ACL-je u::rwx,g::r--,g:csop1:rw,o::---,m::rwx (vagyis csak a tulajdonos és a csop1 csoport számára írható), akkor azon processzeknek, amelyek EGID-ja nem egyezik meg a tulajdonoscsoportéval, de tagjai a csop1 csoportnak, azt kellene mutatnunk, hogy az "other" bitcsoport értéke rw. Szerencsére azonban erre szinte soha nincs szükség, mivel a programoknak alapvetően nem feladata a kernelben amúgy is meglevő jogosultságkezelés reimplementálása (ez mindenképpen csak tökéletlenül sikerülhetne, hiszen lehetetlen transzcendentális módon megállapítani, milyen műveleteket engedélyezne a kernel; vagyis, amíg meg nem próbálunk meg egy műveletet végrehajtani, nem tudjuk megbízhatóan eldönteni, van-e hozzá jogunk).

A POSIX ACL jogosultságbitekre való leképezésére a következő megoldást találták ki:

  1. A tulajdonos jogosultságbitjei megegyeznek a USER_OBJ típusú ACL-bejegyzés tartalmával (ez elég természetes).
  2. Az "egyéb" jogosultságbitjei megegyeznek az OTHER típusú ACL-bejegyzés tartalmával (szintén elég természetes).
  3. A tulajdonoscsoport látszólagos jogosultságbitjei a következőképpen állnak elő:
    1. Ha van MASK típusú bejegyzés az ACL-ben, akkor a tulajdonoscsoport látszólagos jogai a maszk értékével egyeznek meg. Ez egyáltalán nem intuitív, és pl. a find(1) -perm-et is át tudja verni.
    2. Ha nincs MASK típusú bejegyzés az ACL-ben, akkor a tulajdonoscsoport jogai a GROUP_OBJ típusú bejegyzés értékével egyeznek meg.

Ugyanez a leképezés fordítva is működik: ha a chmod paranccsal vagy az azonos nevű rendszerhívással állítjuk a jogosultságbiteket, akkor a csoportra vonatkozó bitek a maszk típusú bejegyzésbe íródnak bele, ha van ilyen a fájlon. Erre jó odafigyelni, mert esetleg nem ezt szeretnénk. Ha ugyanis töröljük valamelyik bitet a maszkból, akkor természetesen hiába szerepel az a bit valamelyik nevesített felhasználóra vagy csoportra vonatkozó bejegyzésben, nem fog érvényre jutni.

Alapértelmezés szerint, amikor módosítjuk az ACL-t egy fájlon vagy könyvtáron, a maszk újraszámolódik és a nevesített felhasználókra és csoportokra vonatkozó jogosultságok összességének VAGY-kapcsolatával fog megegyezni; így, ha pl. egy ls -l kimenetét nézzük, képet kapunk arról, legfeljebb milyen jogokat osztottunk ki ACL-ek formájában.

Azt is jó tudni, hogy a fent leírt leképezés igazából nem a jogok kiolvasásakor, hanem a fájlrendszerben történő rögzítésükkor történik meg (hiszen az inode-ban adottak a jogosultságbitekhez tartozó mezők, ahová valamilyen értéket mindenképpen be kell írni). Ez azért fontos, mert előfordulhatnak (és elő is fordulnak) olyan hibák, amikor a tulajdonoscsoport jogait tartalmazó mezőbe valami miatt nem a maszk értéke kerül (vagy fordítva), és amíg nem nézzük meg közelről a teljes ACL-t, csak tanácstalanul vakarjuk a fejünket és nem értjük, miért nem működnek az ACL-lel beállított jogok. Jelen sorok írásakor (2009. végén) pl. az xfsrestore állít be nullás maszkot úgy, hogy azt az értéket, amelynek a maszkban szerepelnie kellene, a tulajdonoscsoport jogosultságaihoz azért beírja. Így ránézésre látszólag minden rendben van, a gyakorlatban viszont nem jut érvényre az ACL, mert minden bitet kimaszkolunk belőle.

Példa:

% setfacl -m g::rwx,m::--- test
% ls -la test
-rw----r--+  1 root root    0 Nov 20 18:26 test
% getfacl test
# file: test
# owner: root
# group: root
user::rw-
group::rwx                      #effective:---
mask::---
other::r--

% chmod 720 test
% ls -la test
-rwx-w----+ 1 root root 0 Nov 20 18:26 test*
%getfacl test
# file: test
# owner: root
# group: root
user::rwx
group::rwx                      #effective:-w-
mask::-w-
other::---
  • A tulajdonoscsoportnak minden joga megvan, de ezeket a jogokat a maszk kimaszkolja.
  • Az ls kimenetében a maszkot látjuk, nem a tulajdonoscsoport jogait.
  • A chmod a maszkot állította át, nem a tulajdonoscsoport jogait.

[szerkesztés] 3 Hozzáférési ACL

Az eddigiekben bemutatott ACL-ek segítségével viszonylag finoman szabályozhatjuk, hogy létező fájlrendszer-objektumokhoz való hozzáféréskor mely felhasználóknak és mely csoportoknak milyen jogai legyenek. Az ilyen típusú ACL-eket hozzáférési ACL-nek hívják.

Nézzünk egy példát. Állítsuk az umaskunkat 003-ra; ezzel az újonnan létrehozott fájlok és könyvtárak jogosultságbitjeiből kimaszkoltuk az "egyéb" végrehajtási és írási jogát (1-es ill. 2-es bit; a 4-es az olvasás).

% umask 003
% mkdir konyvtar
% ls -dl konyvtar
drwxrwxr-- [...] júzer csoport [...] konyvtar

A pontok helyén levő információk most nem fontosak. Most írassuk ki a getfacl paranccsal az ACL-t. A getfacl paranccsal megjeleníthetjük egy fájl nevét, tulajdonosát, csoportját és a hozzá tartozó ACL-t.

% getfacl konyvtar
# file: konyvtar
# owner: júzer
# group: csoport
user::rwx
group::rwx
other::r--

Az utolsó három sor a szokásos unixos jogosultságbiteket reprezentáló ACL-bejegyzéseket mutatja. Nézzük meg, hogy hogyan tudnánk egy megnevezett felhasználónak, mondjuk Bobnak jogokat biztosítani. Mivel Bobot szeretjük, olvasási, írási és végrehajtási jogot is adunk neki. A -m paraméter segítségével tudjuk módosítani a jogokat.

% setfacl -m u:bob:rwx konyvtar
% getfacl konyvtar
# file: konyvtar
# owner: júzer
# group: csoport
user::rwx
user:bob:rwx
group::rwx
mask::rwx
other::r--

(Vegyük észre, hogy azt, hogy user:bob:rwx rövidíthettük úgy, hogy u:bob:rwx.)

Itt megjelenik ugyebár a Bob nevű felhasználó bejegyzése és a mask típusú bejegyzés. A mask bejegyzés automatikusan létrejön, ha szükséges, és nem adtuk meg külön. Ahogy már említettem, a maszk alapértelmezés szerint a nevesített felhasználókra és csoportokra, valamint a tulajdonoscsoportra vonatkozó jogosultságok összességének VAGY-kapcsolatával fog megegyezni, így biztosan nem maszkol egyetlen jogot sem. Ha megnézzük az ls -dl konyvtar parancs kimenetét, a következőt láthatjuk:

drwxrwx---+ [...] júzer csoport [...] konyvtar

Itt a + jel azt mutatja, hogy konyvtarhoz tartozik bővített ACL. Ugyan nem látszik, de most már a mask bejegyzés tartalma jelenik meg a tulajdonoscsoport jogai helyén; ez elvileg azért hasznos, mert a mask az ACL-ek által biztosított jogok felső korlátja.

Ha megpróbáljuk módosítani a tulajdonoscsoport jogait a chmod segítségével r-x-re, akkor a következő történik:

% chmod g-w konyvtar
% ls -dl konyvtar
drwxr-x---+ [...] júzer csoport [...] konyvtar
% getfacl --omit-header konyvtar
user::rwx
user:bob:rwx            #effective:r-x
group::rwx              #effective:r-x
mask::r-x
other::---

Ezen a példán látható a mask hatása: maszkolja a Bob felhasználó és a tulajdonoscsoport egyes jogait.

Most vegyük el a tulajdonoscsoport írási és végrehajtási jogát a maszk újraszámolása nélkül, majd chmoddal állítsunk be 2770-es jogokat:

% setfacl -n -m g::r konyvtar
% chmod 2770 konyvtar
% ls -dl konyvtar
drwxrws---+ [...] júzer csoport [...] konyvtar
% getfacl konyvtar
# file: konyvtar
# owner: júzer
# group: csoport
# flags: -s-
user::rwx
user:bob:rwx
group::r--
mask::rwx
other::---

Látszik, hogy

  • hiába adna a 2770-es bitkombináció írási és végrehajtási jogot a tulajdonoscsoportnak, csak a maszk módosult;
  • a getfacl kimenetében megjelent az, hogy flags: -s-, ami azt jelenti, hogy a setgid bit be van állítva.

A setgidnek igazából semmi köze az ACL-hez; csak azért van ott, hogy az ACL-ek könnyen lementhetőek és helyreállíthatóak legyenek anélkül, hogy a setuid/setgid/sticky bitek állapota elveszne. A getfacl segítségével ugyanis rekurzívan is kilistázhatjuk egy egész könyvtárfa összes ACL-jét, a setfacl pedig a getfacl kimenetét olvasva vissza tudja ezeket állítani; ha a getfacl kimenete nem tartalmazná a setuid/setgid/sticky bitet, akkor szinte használhatatlan lenne. Sajnos évekig ez volt a helyzet.

[szerkesztés] 4 Alapértelmezett ACL

A hozzáférési ACL-eken túlmenően ún. alapértelmezett ACL-eket is használhatunk. Ha egy könyvtárhoz tartozik alapértelmezett ACL, akkor az adott könyvtárban újonnan létrehozott valamennyi fájlrendszer-objektum hozzáférési ACL-ként ezt az alapértelmezett ACL-t örökli (az új alkönyvtárak alapértelmezett ACL-ként is).

Új fájlrendszer-objektum létrehozásakor, ha a szülőkönyvtárnak van alapértelmezett ACL-je, az alábbi történik:

  • Az új objektum hozzáférési ACL-ként megkapja a szülőkönyvtár alapértelmezett ACL-jét.
  • Ezután a maszkot kivéve az összes ACL-bejegyzésből törlődik minden olyan bit, amely az objektumot létrehozó rendszerhívásnak átadott mode paraméterben (ami a létrehozandó objektum jogosultságbitjeit tartalmazza) nincs beállítva.
  • Az umask nem jut szerephez!

Lássunk egy példát! A setfacl paranccsal kétféleképpen is beállíthatunk default ACL-t; az alábbi két parancssor ekvivalens:

 
setfacl -d -m g:csoport2:r-x konyvtar
setfacl -m d:g:csoport2:r-x konyvtar

(Linuxon az r-x helyett írhatunk csak simán rx-et is, de pl. Solarison nem: ott mindig pontosan három karakterrel kell megadnunk a jogosultságbiteket.)

A második forma előnye akkor mutatkozik meg, ha egyszerre akarunk hozzáférési és alapértelmezett ACL-t is létrehozni; a setfacl -m után ugyanis vesszővel elválasztva több ACL-elemet is felsorolhatunk, és a második szintaxis lehetővé teszi az alapértelmezett és a hozzáférési ACL-ek keverését, míg az első nem.

Nézzük meg, mit csináltunk!

getfacl konyvtar
# file: konyvtar
# owner: júzer
# group: csoport
user::rwx
user:bob:rwx
group::r-x
mask::rwx
other::---
default:user::rwx
default:group::r-x
default:group:csoport2:r-x
default:mask::r-x
default:other::---

A default ACL megjelenítésével és működésével kapcsolatban vannak különbségek az egyes implementációk között; pl. elképzelhető, hogy a default ACL-t csak akkor látjuk, ha -d kapcsolóval hívjuk meg a getfacl. Azt is vegyük észre, hogy a Linux automatikusan létrehozott a hozzáférési ACL alapján néhány alapértelmezett ACL-bejegyzést; ez sem feltétlenül történik ugyanígy minden más oprendszeren.

Hozzunk most létre egy alkönyvtárat az mkdir paranccsal! Az mkdir(1) program 0777-es mode paraméterrel hívja meg az mkdir() rendszerhívást. Lássuk, milyen ACL-t kap az uj alkönyvtár:

mkdir konyvtar/alkonyvtar
getfacl konyvtar/alkonyvtar
# file: konyvtar/alkonyvtar
# owner: júzer
# group: csoport
user::rwx
group::r-x
group:csoport2:r-x
mask::r-x
other::---
default:user::rwx
default:group::r-x
default:group:csoport2:r-x
default:mask::r-x
default:other::---

Látható, hogy az új könyvtár az ACL-t mint hozzáférési és alapértelmezett ACL-t is örökölte.

[szerkesztés] 5 Alkalmazási példák

Tegyük fel, hogy van egy SSL-kulcsunk. Nem szeretnénk, hogy bárki elolvashassa, kivéve a webszervert. A webszerver a www-data nevű felhasználó jogaival fut. Ha a www-data felhasználó tulajdonába helyezzük a fájlt, akkor ő el tudja rajta állítani a jogokat is, amit nem szeretnénk; ACL-lel viszont megoldhatjuk, hogy a root tulajdonában maradjon, de a www-data is el tudja olvasni a tartalmát anélkül, hogy a jogokat elállíthatná. ACL nélküli megoldás is van: legyen saját csoportja a www-data usernek, és birtokolja ez a csoport az SSL-kulcsot. Ha csak a csoportnak van rá olvasási joga, akkor nem tudja elállítani a jogokat.

Ha víruskeresőt futtatunk a bejövő leveleken, általában különböző felhasználóként fut a levelezőszerver és a víruskereső. Azt szeretnénk, ha a levelezőszerver által létrehozott fájlok a víruskereső számára is olvashatóak lennének, de senki más számára nem lennének olvashatóak. Megtehetjük, hogy egy olyan könyvtárba tesszük ezeket a fájlokat, amelyen olyan alapértelmezett ACL van, amely a víruskeresős felhasználónak olvasási jogot biztosít. ACL nélkül megoldás: helyezzük közös csoportba ezt a két felhasználót, és az adott könyvtár legyen ennek a csoportnak a tulajdona, valamint setgid-es. Az is szükséges, hogy a levelezőszerver umaskja megfelelő legyen, tehát ne maszkolja ki a csoport olvasási jogát.

[szerkesztés] 6 Potenciális ZH-kérdések

  • Milyen elemekből áll(hat) egy POSIX ACL? (A szimbolikus azonosítók nem kellenek betű szerint, csak a szerepük/funkciójuk.)
  • Mik a 100-as UID-val, 200-as GID-dal futó, 300-as és 400-as kiegészítő csoporttagsággal rendelkező processz effektív jogai azon a fájlon, amelynek a POSIX ACL-je az alábbi bejegyzéseket tartalmazza? (És itt jönne egy getfacl-kimenet.)
  • Mondjon példát olyan jogosultság-specifikációra, amely hagyományos unixos jogosultságokkal nem írható le ésszerűen, de POSIX ACL-ekkel igen!
  • Hogyan (és milyen esetekben) lehet a POSIX ACL-ek látszólag szükséges alkalmazását mégis elkerülni és hagyományos unixos jogosultságokkal ugyanazt a hatást elérni? Mutassa ezt be egy példán! (Segítség: lehet, hogy csak ésszerűtlen megoldás van.)
  • Használható-e POSIX ACL arra, hogy egy csoport összes tagja számára mindenképpen biztosítsunk hozzáférést egy könyvtár tartalmához, akkor is, ha a csoport tagjai nem működnek ebben együtt? Miért?
  • Mit látunk az ls -l kimenetében a jogosultságbitek helyén olyan könyvtárbejegyzések esetében, amelyekhez bővített POSIX ACL tartozik?
Személyes eszközök