POSIX ACL

A Unix/Linux szerverek üzemeltetése wikiből
A lap korábbi változatát látod, amilyen KornAndras (vitalap | szerkesztései) 2009. december 31., 17:05-kor történt szerkesztése után volt.

Í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):
    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. 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:

  1. A tulajdonos jogosultságbitjei megegyeznek a USER_OBJ típusú ACL-bejegyzés tartalmával.
  2. Az "egyéb" jogosultságbitjei megegyeznek az OTHER típusú ACL-bejegyzés tartalmával.
  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.
    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 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:

  1. tulajdonos
  2. megnevezett felhasználó
  3. tulajdonoscsoport
  4. megnevezett csoport
  5. 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.

Személyes eszközök