POSIX ACL

A Unix/Linux szerverek üzemeltetése wikiből
(Változatok közti eltérés)
a (kisebb átdolgozás)
(Az ACL-ek felépítése és működése: a linux viselkedése bug)
 
(egy szerkesztő 29 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:
+
** user/group/other/mask.
+
* 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):
  +
*# tulajdonos (ACL_USER_OBJ);
  +
*# egyéb konkrét felhasználó (ACL_USER);
  +
*# tulajdonoscsoport (ACL_GROUP_OBJ);
  +
*# egyéb konkrét csoport (ACL_GROUP);
  +
*# 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;
  +
*# mindenki más (ACL_OTHER).
 
* Annak a csoportnak vagy felhasználónak a neve, amelyikre az adott bejegyzés vonatkozik; ez lehet
 
* Annak a csoportnak vagy felhasználónak a neve, amelyikre az adott bejegyzés vonatkozik; ez lehet
 
** üres, vagy
 
** üres, vagy
23. sor: 23. sor:
 
<pre><acl típusa>:<név>:<jogok></pre>
 
<pre><acl típusa>:<név>:<jogok></pre>
   
A minimális ACL csak a ''tulajdonos'', a ''tulajdonoscsoport'' és az ''egyéb'' jogait leíró elemeket tartalmazza, amelyek a fájlok és könyvtárak szokásos jogosultsági bitjeinek felelnek meg. Azokat az ACL-eket, amelyek ezen a három bithármason kívül további elemeket is tartalmaznak, kiterjesztett ACL-eknek hívjuk. Ezek tartalmaznak egy ''mask'' bejegyzést illetve megnevezett felhasználókat és csoportokat is.
+
Az alábbi táblázat az egyes bejegyzéstípusok szintaxisát részletesebben is bemutatja:
   
A következőképpen épülnek fel az ACL bejegyzések típusai. Minden bejegyzés tartalmazza, hogy melyik felhasználóra vagy csoportra érvényes önmaga illetve azt, hogy milyen jogokkal rendelkezik, az adott osztályban.
 
 
{| class="wikitable" border="1" align="center"
 
{| class="wikitable" border="1" align="center"
 
! Típus
 
! Típus
  +
! Kód
 
! Szöveges forma
 
! Szöveges forma
 
|+ align="bottom" | '''ACL-bejegyzéstípusok'''
 
|+ align="bottom" | '''ACL-bejegyzéstípusok'''
 
|-
 
|-
 
|tulajdonos
 
|tulajdonos
  +
|ACL_USER_OBJ
 
|user::rwx
 
|user::rwx
 
|-
 
|-
|megnevezett felhasználó
+
|konkrét felhasználó
  +
|ACL_USER
 
|user:név:rwx
 
|user:név:rwx
 
|-
 
|-
 
|tulajdonoscsoport
 
|tulajdonoscsoport
  +
|ACL_GROUP_OBJ
 
|group::rwx
 
|group::rwx
 
|-
 
|-
|megnevezett csoport
+
|konkrét csoport
  +
|ACL_GROUP
 
|group:név:rwx
 
|group:név:rwx
 
|-
 
|-
 
|maszk
 
|maszk
  +
|ACL_MASK
 
|mask::rwx
 
|mask::rwx
 
|-
 
|-
 
|egyéb
 
|egyéb
|other::rwx</pre>
+
|ACL_OTHER
|-
+
|other::rwx
|}
 
Ezek a megnevezett csoport és megnevezett felhasználói bejegyzések mind a csoport (group) osztály alá tartoznak, ami tartalmazza a tulajdonoscsoport (owning group) bejegyzést is, eredetileg ugyebár csak ezt tartalmazta a hagyományos jogosultsági rendszer. Eltérően a POSIX.1 jogosultsági modelltől, a csoport osztály tartalmazhat tehát különböző jogokat magába foglaló ACL bejegyzéseket így önmagában a csoport osztály jogai nem kell, hogy megmutassák az összes ACL bejegyzés részletes jogait. Ezzel a csoport osztály jogait egy felső korlátként értelmezhetjük, ez a felső határ lehetővé teszi, hogy a POSIX.1-es alkalmazások, melyek nem ismerik az ACL-t, nem fognak hirtelen extra jogokat biztosítani, amikor az ACL elérhetővé válik.
 
A minimális ACL-eknél a csoport (group) osztály jogai megegyeznek a tulajdonoscsoport jogaival. Ezzel szemben a kiterjesztett ACL-eknél a csoport (group) osztály tartalmazhatja egyéb felhasználók és csoportok bejegyzéseit is. Ennek lényeges problémája, hogy ezek a bejegyzések tartalmazhatnak olyan jogokat, melyekkel a tulajdonoscsoport nincs felruházva, tehát a tulajdonoscsoport (owning group) bejegyzésében található jogok eltérnek a csoport (group) osztály jogaitól. Ennek elkerülése miatt vezették be az úgynevezett mask bejegyzést. A minimális ACL-ekkel a csoport osztály jogai megegyeztek a tulajdonoscsoport bejegyzésének jogaival, míg a kiterjesztett ACL-eknél a csoport osztály jogai a mask bejegyzés jogaival egyeznek meg.
 
{| class="wikitable" border="1" align="center"
 
|+ align="bottom" | '''Minimális ACL'''
 
|tulajdonos
 
|user::rw-
 
|→
 
|rw-
 
|tulajdonos osztály
 
|-
 
|tulajdonoscsoport
 
|group::r--
 
|→
 
|r--
 
|csoport osztály
 
|-
 
|egyéb
 
|other::---
 
|→
 
| ---
 
|egyéb osztály
 
 
|-
 
|-
 
|}
 
|}
   
{| border="1" align="center" class="wikitable"
+
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.
|+ align="bottom" | '''Kiterjesztett ACL'''
+
|tulajdonos
+
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:
|user::rwx
+
|→
+
# 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.
|rwx
+
# 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ó.
|tulajdonos osztály
+
#* 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.
|megnevezett felhasználó
+
# 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.
|user:név:rw-
+
# Ha a maszk üres volt, akkor az OTHER-ben levő jogosultságbitek az irányadóak.
|rowspan="3"|→
+
#* Vagyis: az OTHER-ben megadott engedély megint erősebb, mint bármiféle tiltás!
|rowspan="3"|rw-
+
# Ha nincs ilyen ACL-bejegyzés, akkor az OTHER típusú bejegyzésben szereplő jogosultságbitek jutnak érvényre.
|rowspan="3"|csoport osztály
+
|-
+
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.)
|tulajdonoscsoport
+
|group::r--
+
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.
|-
 
|maszk
 
|mask::rw-
 
|-
 
|egyéb
 
|other::---
 
|→
 
| ---
 
|egyéb osztály
 
|-
 
|}
 
   
Kiterjesztett ACL-ek esetében a mask bejegyzésnek és a csoport osztály egy tagjának a bejegyzésének is tartalmaznia kell egy adott jogot ahhoz, hogy az ténylegesen is érvényesüljön. A csoport osztályba nem tartozik bele a tulajdonos és az egyéb bejegyzése, az ő jogaik nincsenek maszkolva.
+
Az alábbi táblázat egy egyszerű példán kersztül szemlélteti a maszk működését:
   
 
{| border="1" align="center" class="wikitable"
 
{| border="1" align="center" class="wikitable"
76. sor: 79. sor:
 
!Jogok
 
!Jogok
 
|-
 
|-
|megnevezett felhasználó
+
|konkrét csoport
|user:név:rw-
+
|group:név:r-x
 
|r-x
 
|r-x
 
|-
 
|-
84. sor: 87. sor:
 
|rw-
 
|rw-
 
|-
 
|-
|colspan="2" align="center" |'''Tényleges jogok'''
+
|colspan="2" align="center" |'''Effektív jogok'''
 
|r--
 
|r--
 
|-
 
|-
 
|}
 
|}
   
Ha egy alkalmazás (például a chmod segítségével) megváltoztatja a tulajdonos, csoport vagy az egyéb osztály jogait, akkor a megfelelő ACL bejegyzés is megváltozik. Hasonlóan amikor egy alkalmazás megváltoztatja egy ACL bejegyzés jogait ami az egyik osztályra mutat, akkor az osztály jogai megváltoznak.
+
=== ACL leképezése hagyományos jogosultságbitekre ===
= Hozzáférési ACL =
+
Az eddigiekben végignéztük, hogy az ACL-ek segítségével hogyan tudunk megadni aktuálisan hozzáférési jogokat egy fájlrendszer objektumhoz. Ezt nevezzük hozzáférési ACL-eknek.
+
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.
  +
  +
<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ő:
  +
## 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.
  +
  +
Ugyanez a leképezés fordítva is működik: ha a <tt>chmod</tt> 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 <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 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:
   
== Példa hozzáférési ACL-re ==
 
Nézzünk példát erre úgy, hogy használjuk az „umask” parancsot. Ezzel meg tudjuk határozni, hogy mely jogok legyenek maszkolva, ha új könyvtárat hozunk létre. Ha az „umask” értéke „033”, akkor ezzel maszkoltuk a tulajdonoscsoport és az egyéb végrehajtási és olvasási jogát.
 
 
<pre>
 
<pre>
umask 033
+
% setfacl -m g::rwx,m::--- test
mkdir konyvtar
+
% ls -la test
ls -dl konyvtar
+
-rw----r--+ 1 root root 0 Nov 20 18:26 test
drwxr--r-- ... ember csapat ... konyvtar
+
% 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>
 
</pre>
A pontok helyén számunkra most felesleges információk vannak.
+
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 az ACL-t.
+
* 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 ==
  +
  +
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 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>
getfacl konyvtar
+
% umask 003
  +
% mkdir konyvtar
  +
% ls -dl konyvtar
  +
drwxrwxr-- [...] júzer csoport [...] konyvtar
  +
</pre>
  +
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.
  +
<pre>
  +
% getfacl konyvtar
 
# file: konyvtar
 
# file: konyvtar
# owner: ember
+
# owner: júzer
# group: csapat
+
# group: csoport
 
user::rwx
 
user::rwx
group::r--
+
group::rwx
 
other::r--
 
other::r--
 
</pre>
 
</pre>
Az utolsó három sor a felhasználói osztályok ACL bejegyzéseit mutatja.
+
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.
+
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 user:bob:rwx konyvtar
+
% setfacl -m u:bob:rwx konyvtar
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--
+
group::rwx
 
mask::rwx
 
mask::rwx
 
other::r--
 
other::r--
 
</pre>
 
</pre>
Itt megjelenik ugyebár a Bob nevű felhasználó bejegyzése és a mask bejegyzés. A „mask” bejegyzés automatikusan létrejön, ha szükséges, de nem adtuk meg külön. Ez a bejegyzés automatikusan a csoport osztály bejegyzéseinek az OR kapcsolatára állítódik, így biztosan nem maszkol egyetlen jogot sem. Ha megnézzük az „ls -dl konyvtar” paranccsal a következőt láthatjuk.
+
  +
(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, 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---+ ... ember csapat ... konyvtar
+
drwxrwx---+ [...] júzer csoport [...] konyvtar
 
</pre>
 
</pre>
Itt a + jel azt mutatja, hogy kiterjesztett ACL-lel van dolgunk. Látszik az is, hogy a mask bejegyzés jogait helyettesíti a tulajdonoscsoport osztály jogait, ezáltal a mask mint a jogok egy felső korlátja jelenik meg. A „group” 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 „group” jogait a „chmod” segítségével „r-x”-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---+ ... ember csapat ... 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, képes maszkolni a Bob felhasználó egyes jogait. Ha a „chmod”-dal visszaadnánk az írási jogot, akkor csak a Bob felhasználó tudná újra írni a fájlokat, tehát a „group”-ot ez nem érintené.
+
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:
  +
<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.]
  +
  +
== 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).
   
= Alapértelmezett ACL =
+
Ú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:
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.
 
   
Ú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.
+
* 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!
   
== Péda alapértelmezett ACL-re ==
+
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:
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.
 
 
<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