Az előző bejegyzésemben gyorsan elintéztem azt a kérdést, hogy hogyan tudjuk a Network Manager appletet működésre bírni (a probléma az volt, hogy a wifi hálózatokhoz nem engedett csatlakozni).
Ezzel kapcsolatosan jutott eszembe, hogy talán a policykitről is írhatnék, ugyanis elrettentő neve ellenére egy agyhalottan egyszerű dologról van szó, de amíg anno utána nem olvastam, én is azt hittem, hogy ez valami grsecurity-vel felérő dolog.
MI az a Policykit és hogyan működik?
Ezt a toolt a Freedesktop.org hozta létre, és elméletben minden Linux desktop ennek megfelelően kell működjön. Röviden: A bejelentkezett felhasználók munkameneteihez (session-jeihez) rendelhetők hozzá bizonyos, biztonsággal kapcsolatos jogok: melyik felhasználó tud felcsatolni hordozható médiát, melyik tudja leállítani a gépet stb. Alapvetően kétféle session-t különböztet meg: az aktív session felhasználója a gép (vagy legalábbis egy rádugott konzol) előtt ül (tehát helyben jelentkezett be akár konzolon, akár X-be), az ún. inaktív session pedig a távolról bejelentkezett felhasználókat (SSH, VNC, X session stb) jelenti.
Az, hogy mihez adunk jogot, a Policykit terminológiájával "Action"-nek hívják. Ezeket akár ki is listázhatjuk a pkaction parancs kiadásával:
org.freedesktop.color-manager.create-device
...
org.freedesktop.upower.hibernate
org.freedesktop.upower.qos.cancel-request
org.freedesktop.upower.qos.request-latency
org.freedesktop.upower.qos.request-latency-persistent
org.freedesktop.upower.qos.set-minimum-latency
org.freedesktop.upower.suspend
Ha a --verbose kapcsolóval hívjuk a parancsot, kis leírást is kapunk az egyes akciókhoz.
Nade honnan bújnak elő ezek az Action-ök, és hogyan tudja egy alkalmazás, hogy neki eszerint kell múkodnie?
Mi az a D-Bus?
Mint az köztudott, a több alkalmazást egyszerre futtató környezetekben elég hamar felmerült az igény, hogy ezek az alkalmazások szabványos felületeken egymással kommunikálni tudjanak. Kezdetben a rendszerek elképesztően jól elvoltak a socket, named pipe vagy osztott memória használattal - ezeket most helyszűke miatt nem fejtem ki bővebben, mint ahogy a különféle message queuing rendszereket (pl. CORBA) sem. Az egyik legújabb darab pl. a SOAP, elvégre az is távoli alkalmazáshívó protokoll. Mint látjuk tehát, rengeteg megvalósítás van, amely több-kevesebb sikerrel terjedt el a különféle operációs rendszereken és programozási nyelveken.
Az egészet úgy kell elképzelni, mint a csőpostát: egy alkalmazás (vagy oprendszer démon) egy másiknak (vagy többnek) címezve behajít egy üzenetet egy csőbe, a cső másik végén kiesik az üzenet, a cél alkalmazás kikapja és feldolgozza. Példa: egy alkalmazás üzenetet szeretne megjeleníteni egy lufiban, hát küld egy üzenetet a notification-daemonnak.
Amikor úgy döntöttek az okosok, hogy "egységesíteni kéne má' pár dolgot Linux desktop ügybe'", létrehozták a Freedesktop.org-ot, és ők rukkoltak elő a D-Bus nevű, szintén processzek közötti kommunikációt megvalósító protokollal is, amelyet kifejezetten Linux Desktopokhoz írtak. A DBus olyan jól sikerült, hogy a Gnome és a KDE is váltott a saját megoldásáról (Corba/Bonobo és DCOP) az egységesítés érdekében - hála érte. A többi, kisebb desktop pedig ha akarta, ha nem, követnie kellett a fő irányt.
A Dbus két mechanizmust használ, az egyik a libdbus, amely az 1-1 kommunikációt hivatott szolgáltatni (magyarul 2 processz kommunikál), és a dbus-daemon, amelynek segítségével az alkalmazások eseményekre tudnak figyelni, vagy megkereshetik egymást. A buszon való kommunikáció titkosított.
Ennyi fejtágítás után talán már érthető, hogy van az upower daemon, ami az energiagazdálkodással kapcsolatos eseményeket kezeli, van a polkitd, amelyik megmondja, mihez van joga a bejelentkezett felhasználónak, és van az lxsession-logout, vagyis az a kis ablak, amely az LXDE kilépésekor megjelenik, és felajánlja, hogy "logout", "suspend" vagy "hibernate". Mivel kézzel is ki tudjuk adni a dbus-os üzeneteket, tegyünk egy próbát:
dbus-send --print-reply --system --dest=org.freedesktop
Error org.freedesktop.UPower.GeneralError: not authorized
Hopszi, ez nem nyerő. Azt már tudjuk, hogy az lxde-logout mit küld a buszon, de mit lép erre az UPower? Belekukkantottam a forrásba, és úgy látom, hogy a up_daemon_suspend_allowed funkcióban ismét egy DBus hívás következik, ami a polkitd-t megkérdezi, hogy mehet-e a dolog. Tehát ez egy tovagyűrűző híváslánc, melynek végén a polkitd azt mondja, hogy "no-no, Seňor". A kérdés már csak az, hogy mi alapján mondja ezt.
Hogyan lehet jogokat állítani a Polkittel?
Szóval, hol is vannak ezek az áksönök megadva? A megfejtés a /usr/share/polkit-1/actions könyvtár. Nézzük most meg csak a /usr/share/polkit-1/actions/org.freedesktop.upower.policy tartalmát:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE policyconfig PUBLIC
"-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
"http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd">
<policyconfig>
<vendor>The UPower Project</vendor>
<vendor_url>http://upower.freedesktop.org/</vendor_url>
<icon_name>system-suspend</icon_name>
<action id="org.freedesktop.upower.suspend">
<description>Suspend the system</description>
<description xml:lang="fr">Mettre le système en veille</description>
<description xml:lang="it">Sospende il sistema</description>
<description xml:lang="pl">Wstrzymanie systemu</description>
<description xml:lang="sv">Försätt systemet i vänteläge</description>
<message>Authentication is required to suspend the system</message>
<message xml:lang="fr">Vous devez vous identifier pour mettre le système en veille</message>
<message xml:lang="it">È richiesto autenticarsi per sospendere il sistema</message>
<message xml:lang="pl">Wymagane jest uwierzytelnienie, aby wstrzymać system</message>
<message xml:lang="sv">Autentisering krävs för att försätta systemet i vänteläge</message>
<defaults>
<allow_inactive>no</allow_inactive>
<allow_active>yes</allow_active>
</defaults>
</action>
Hát ez csodálatos, XML-ben van...! :-) A lényeget kiemeltem pirossal. Igazából három dolgot lehet megadni, és azt négyféleképpen (nyugi, nagyon egyszerű az egész és a végére kiderül majd, hogy még csak XML-t sem kell szerkeszteni):
- allow_any - mindenkire vonatkozó jogok
- allow_inactive - távolról bejelentkezett felhasználóra vonatkozó jogok
- allow_active - ... mindenkinek a fantáziájára bízom :-)
Illetve a megadható négy érték, ami valójában hat (az első kettőt hadd ne magyarázzam... :-) ):
- no
- yes
- auth_self - A felhasználónak, aki elindította a kérést, authentikálnia kell magát (minden alkalommal)
- auth_self_keep - Ugyanaz, mint auth_self, de egy darabig megjegyzi és nem kér minden alkalommal jelszót
- auth_admin - Adminisztratív felhasználó (root) azonosítás szükséges (minden alkalommal)
- auth_admin_keep - Ez megint csak egyértelmű
Nos, már tudjuk, hogy mit lehet és mivel kapcsolatban, egyetlen kérdés a hol?
Policykit szabályok szerkesztése
Az egyszerűség kedvéért nem a /usr/share/... alatt praktikus szerkeszteni a jogokat, mert azok az alapértelmezéseket tartalmazzák és az nincs is bennük, hogy melyik felhasználóra vagy -csoportra van megadva. Helyette van a /etc/polkit-1/localauthority/ könyvtár, ami további alkönyvtárakat tartalmaz, amik fogalmam sincs, miért vannak, én tippre az 50-local.d-be pakoltam a saját vackaimat.
Összefoglaló
Minden szónál szebb egy ábra:
A továbbiakban feladom házi feladatként, hogy milyen fájlt, hol és milyen tartalommal kell létrehozni ahhoz, hogy minden helyben bejelentkezett felhasználónak jelszó nélkül működjön a Suspend (alvás) funkció az LXDE kilépő panelről. Aki úgy érzi, nem tudja megugrani, annak azért közreadom a megoldást, mindenki más hunyja be a szemét most:
cat /etc/polkit-1/localauthority/50-local.d/org.freedesktop.upower.suspend
[Suspend to RAM]
Identity=unix-user:*
Action=org.freedesktop.upower.suspend
ResultActive=yes
(A unix-user helyett lehet unix-group-ot is használni, és a * helyett szűkíteni az adott névre.)
Ezzel megoldódott a sleep problémám. Ez persze még fikarcnyit sem gyorsított a boot folyamaton, és nem is tette biztonságosabbá az előzőekben felrajzolt beállításokat, de haladunk előre szépen.