POSIX ACL
Írta: Tevesz Ágnes, 2009. december.
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 |
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 csak a szabad unix-féleségek közül csak a 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.
2 Az ACL-ek felépítése
Egy ACL bejegyzések sokaságából épül fel (ACE). 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):
- 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
- ü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 |
---|---|---|
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:
- 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.
Vegyük észre, hogy ez azt jelenti, hogy az engedélyező ACL-bejegyzések "erősebbek" a tiltóknál.
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 felhasználó | user:név:rw- | r-x |
mask | mask::rw- | rw- |
Effektív jogok | r-- |
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:
- A tulajdonos jogosultságbitjei megegyeznek a USER_OBJ típusú ACL-bejegyzés tartalmával.
- Az "egyéb" jogosultságbitjei megegyeznek az OTHER típusú ACL-bejegyzés tartalmával.
- 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 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 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 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.
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 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).
umask 033 mkdir konyvtar ls -dl konyvtar drwxr--r-- [...] user 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 az ACL-t.
getfacl konyvtar # file: konyvtar # owner: ember # group: csapat user::rwx group::r-- other::r--
Az utolsó három sor a felhasználói osztályok ACL bejegyzéseit 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 user:bob:rwx konyvtar getfacl konyvtar # file: konyvtar # owner: ember # group: csapat user::rwx user:bob:rwx group::r-- mask::rwx other::r--
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.
drwxrwx---+ ... ember csapat ... konyvtar
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.
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.
chmod g-w konyvtar ls -dl konyvtar drwxr-x---+ ... ember csapat ... konyvtar getfacl --omit-header konyvtar user::rwx user:bob:rwx #az érvényesülő jogok:r-x group::r-- mask::r-x other::---
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é.
4 Alapértelmezett ACL
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.
4.1 Péda alapértelmezett ACL-re
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.
setfacl -d -m group:valami:r-x konyvtar
A „getfacl” segítségével pedig megnézhetjük a módosításokat.
getfacl konyvtar # file: konyvtar # owner: ember # group: csapat user::rwx user:bob:rwx group::r-x group:valami:rwx mask::rwx other::--- default:user::rwx default:group::r-x default:group:valami:r-x default:mask::r-x default:other::---
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. Egy alkönyvtárt készítve nézzük, hogyan öröklődnek a jogok.
mkdir konyvtar/alkonyvtar getfacl konyvtar/alkonyvtar # file: konyvtar/alkonyvtar # owner: ember # group: csapat user::rwx group::r-x group:valami:r-x mask::r-x other::--- default:user::rwx default:group::r-x default:group:valami: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. Ebben az esetben nem változtattunk a „mode” paraméteren.
5 Hozzáférést ellenőrző algoritmus
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.
6 Példa alkalmazásokkal való használatra
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.
ps axuwww | grep httpd root … … … /usr/sbin/httpd apache … … … /usr/sbin/httpd apache … … … /usr/sbin/httpd
Nézzük meg, milyen jogai vannak az apache-nak, tegyük fel, hogy létezik az index.html.
ls -lah /var/www/html/index.html -rw-r--r--. … apache apache … /var/www/html/index.html
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.
chmod o-r /var/www/html/index.html ls -lah /var/www/html/index.html -rw-r-----. … apache apache … /var/www/html/index.html
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.