|
||||||||||||||||||||||||||||||||||||||||||||||||
Menu
Distributions (131)
Software (10844)
|
Java (22) - omezování práv I.Minule jsme načítali objektové třídy za běhu programu. To je činnost
potenciálně velmi nebezpečná, proto je žádoucí (nejen) v takovém případě omezit
práva kódu získanému zvnějšku. Podívejme se, jak se to dělá.
Bezpečnost předevšímSpustíme-li normální javovskou aplikaci, běží ve výchozím nastavení s maximálními právy. Veškerý obsažený kód má tedy právo dělat si v systému cokoliv (samozřejmě s ohledem na práva v operačním systému). V minulém dílu seriálu jsme načítali třídy za běhu programu, vytvářeli instance těchto tříd a spouštěli je. Co by se stalo, kdyby nám někdo zlomyslně podstrčil třídu, která by obsahovala nějaký škodlivý kód? Odpověď je jasná - záleželo by pouze na tvůrci programu, jaké "potěšení" by nám připravil. Systém mu je zcela k dispozici a může tedy zcela nerušeně třeba smazat obsah domovského adresáře. Základním pravidlem je absolutní nedůvěra ke kódu získanému odněkud zvenku (z webového serveru apod.). Kód zkrátka nesmí mít možnost něco zlého provést. A jak mu tuto možnost odejmout, na to se nyní podíváme. Hlídač v systémuK vynucení bezpečnostních omezení si přizveme na pomoc "hlídače" (budeme pro něj používat termín security manager). Hlídač bude schvalovat všechny potenciálně nebezpečné operace, a povolí jen takové, které budou odpovídat určeným bezpečnostním pravidlům.
Hlídač je v Javě představován třídou
Lze používat přímo třídu Povolení ... máš?
Termín "povolení" (permission) je dalším z pojmů, které nás velice zajímají.
Zde ho představuje třída
Mezi potomky třídy
Důležitou otázkou je, jak schválení probíhá. Třída
Ještě dodám, že existují také třídy Bezpečnostní modelJavovský bezpečnostní model je založen na doménách. Každá doména vlastní povolení pro určitý rozsah operací (který je dán aktuálním nastavením bezpečnostní politiky). Programový kód (třída, instance) nemůže získat vyšší práva tím, že zavolá kód z jiné domény (ani tím, že je z této domény volán). Domény se dělí do dvou kategorií - aplikační a systémové. Přístup k prostředkům systému je povolen pouze v systémových doménách (běžně je pouze jediná). Důležitou skutečností je, že při průchodu různými doménami má kód oprávnění odpovídající jejich průniku - tedy jen ta oprávnění, která má ve všech doménách. Protože by samozřejmě jakékoli omezení v celém řetězci volání bránilo používat systémové prostředky a jiné potenciálně nebezpečné věci, existuje řešení: označit nějaký kód jako privilegovaný. Jak se to dělá, k tomu se vrátíme za chvíli. Implicitní mechanismus kontroly
Původně (ve verzích JDK 1.0 a 1.1) byl bezpečnostní model jednoduchý a
přímočarý, což se s příchodem další verze změnilo. Nyní máme k dispozici
implicitní kontrolní mechanismus, který provádí kontrolu oprávnění
v případech, kdy se nepoužije přímo security manager. Poskytuje ho třída
Podívejme se na to, jak se to dělá v praxi. Máme kus kódu, který potřebuje
číst ze souboru SecurityManager sm = System.getSecurityManager(); Permission p = new FilePermission("/etc/passwd", "read"); if (sm != null) { sm.checkPermission(p); sm.checkRead("/etc/passwd"); } AccessController.checkPermission(p);
V příkladu jsou uvedeny tři cesty, jak se ověřují oprávnění. První je získání
aktuální instance security managera, vytvoření instance třídy Hlavní výhodou tohoto postupu je, že se nemusí nic zvláštního programovat. Všechno máme k dispozici, a záleží pak na nastavení bezpečnostní politiky, co všechno kódu umožníme provádět. Privilegovaný kód
Kus kódu, který by se měl provádět se zvláštní úrovní oprávnění (s vyšší, než
by odpovídalo příslušným bezpečnostním doménám), je nutné označit jako
privilegovaný. Dělá se to typicky javovským způsobem - tedy vytvořením
instance implementace rozhraní Privilegovaný kód poběží s oprávněním domény, ze které byl přímo zavolán - předchozí domény v řetězci volání se neberou v úvahu. Použití přiblíží příklad: PrivilegedAction<Boolean> pa = new PrivilegedAction<Boolean>() { public Boolean run() { try { System.loadLibrary("mylibrary"); return new Boolean(true); } catch (Throwable e) { // musíme chytit i UnsatisfiedLinkError return new Boolean(false); } } }; if (AccessController.doPrivileged(pa).booleanValue()) { ... // nějaký kód závislý na načtení knihovny }
Příklad ukazuje načtení knihovny do systému použitím privilegovaného kódu.
Vytvoří se instance anonymní třídy vzniklé implementací Bezpečnostní kontext
Za normálních okolností se bezpečnostní kontroly vztahují ke vláknu, které
určitý kód provádí. To není vždy úplně nejvhodnější - někdy může být potřeba
poskytnout pro konkrétní účely vláknu jiná (typicky vyšší) oprávnění.
Proto existuje třída Asi bude nejlepší si to ukázat na příkladu. Máme dvě vlákna, jedno druhému poskytne svůj kontext, a to ho použije ke kontrole oprávnění: public class MyThread extends Thread { private AccessControlContext ctx = null; public void setContext(AccessControlContext ctx) { this.ctx = ctx; } public void run() { ... Permission p = new SocketPermission("nejaka.adresa.com:12345", "connect"); try { if (ctx != null) ctx.checkPermission(p); // ověření povolení podle kontextu else AccessController.checkPermission(p); // není nenastaven kontext ... // právo pro přístup do sítě } catch (SecurityException e) { ... // zákaz přístupu do sítě } ... } } ... MyThread t = getWorkerThread(); // získání přístupu k pracovnímu vláknu t.setContext(AccessController.getContext()); ... Máme vlákno, které vykonává nějaké služební činnosti pro ostatní vlákna. Během této činnosti se potřebuje připojit někam do sítě, na což ovšem nemusí mít oprávnění. Proto mu vlákno, které na využití služeb má zájem, poskytne svůj kontext. Pokud v rámci tohoto kontextu existuje příslušné oprávnění, je přístup do sítě umožněn, jinak nikoliv. Nezíská-li vlákno cizí kontext, provede se ověření standardním způsobem. Příklad je samozřejmě velmi jednoduchý a naivní, skutečná implementace by byla složitější. Ještě důležitá poznámka - nově vytvořené vlákno dědí automaticky bezpečnostní kontext svého rodiče. To znamená, že se ho týkají všechna omezení daná doménami, kterými rodič prošel. Pokud by tomu tak nebylo, mohlo by to znamenat nepříjemné riziko. Proto implementace vytváření vláken zajišťuje, aby vlákno získalo bezpečnostní kontext od svého rodiče. Ztělesnění domény
Byla řeč o bezpečnostních doménách - každý si tedy může klást otázku, jak
jsou tyto domény vyjádřeny. K tomu máme třídu K čemu je to dobré? Všimněte si zejména, že zde figuruje zavaděč tříd. Právě ten totiž určuje, do které domény bude načtený kód patřit (a zkonstruuje i instanci objektu domény). V závislosti na použitém zavaděči se tak může - i pro stejný kód - velmi lišit množina oprávnění, kterou bude kód disponovat. Jak omezit práva?Dostali jsme se do bodu, kdy máme k dispozici celý aparát pro kontrolu oprávnění, víme, jak pracuje, takže ještě zbývá určit, co komu povolíme. Protože je to poměrně rozsáhlá záležitost, podíváme se na to příště. Budeme se zabývat hlavně zavaděči tříd a nastavováním bezpečnostní politiky, ale dostaneme se i k problematice podepisování kódu, což je další z metod posilování bezpečnosti při současném zjednodušení práce.
|
Search Software
Search Google
|
||||||||||||||||||||||||||||||||||||||||||||||
©Pavel Kysilka - 2003-2024 | maillinuxsoft.cz | Design: www.megadesign.cz |