M A S A R Y K O V A U N I V E R Z I T A F A K U L T A I N F O R M A T I K Y Rozšíření bezpečnostních politik v Javě o zamítavá pravidla D I P L O M O V Á P R Á C E Bc. Ondřej Lukáš Brno, p o d z i m 2013 Prohlášení Prohlašuji, že tato diplomová práce je mým původním autorským dílem, které jsem vypracoval samostatně. Všechny zdroje, prameny a literaturu, které jsem při vypracování používal nebo z nich čerpal, v práci řádně cituji s uvedením úplného odkazu na příslušný zdroj. Bc. Ondřej Lukáš Vedoucí práce: RNDr. Adam Rambousek ii Poděkování Chtěl bych poděkovat Mgr. Josefovi Cackovi za jeho cenné rady a připomínky při vypracování diplomové práce a za všechen čas, který věnoval pečlivému dohledu na její vývoj. iii Shrnutí Cílem práce je rozšíření bezpečnostní politiky pro Java Security Manager se zaměřením na zamítavá pravidla. Práce bude obsahovat analýzu současné implementace bezpečnostních pravidel v Javě a budou navržena možná rozšíření bezpečnostní politiky. Pro navržené řešení bude implementován Java Security Manager a Access Controller, současně bude navržen a implementován formát souboru s definicí bezpečnostních politik s důrazem na zpětnou kompatibilitu. Součástí práce bude porovnání výkonu implementace se standardní implementací Java Security Manager v různých verzích JVM. Zdrojové kódy budou poskytnuty pod licencí G N U LGPL. iv Klíčová slova Java, bezpečnost, bezpečnostní politika, zamítavé pravidlo, autorizace, Java Security, Security Manager, Policy, policy file v Obsah 1 Úvod 3 2 Základní pojmy 5 3 Řízení přístupu v Javě ~ 3.1 Security Manager 8 3.2 Metoda implies 10 3.3 Třída Permission 11 3.4 Bezpečnostní politika 12 3.4.1 Třída Policy 13 3.4.2 Třída PolicyFile 13 3.4.3 Soubor s konfigurací bezpečnostní politiky 14 3.5 Třídy spojené s autorizací 15 3.5.1 AccessController a AccessControllerContext 15 3.5.2 PermissionCollection a Permissions 18 3.5.3 CodeSource 18 3.5.4 ProtectionDomain 19 3.6 Standardní průběh autorizace 20 3.7 Chráněné objekty 21 4 Možnosti rozšíření bezpečnostních politik o zamítavá pravidla 22 4.1 Z pohledu uživatele 22 4.1.1 Zamítavý prvek 22 4.1.2 Definice chování zamítavých pravidel 22 4.1.3 Konflikty grant a deny prvků 23 4.1.4 Způsoby řešení konfliktů 24 4.2 Z pohledu implementace 25 4.2.1 Reprezentace zamítavého pravidla 26 4.2.2 Dvouprůchodová kontrola přístupu 26 4.2.3 Použití jedné kolekce 28 4.2.4 Negativní alternativa AllPermission 29 5 Výhody a nevýhody použití zamítavých pravidel 30 5.1 Porovnání vlastností 30 5.1.1 Snadnost zápisu a snadnost použití 30 5.1.2 Časová náročnost inicializace a dotazu 31 5.1.3 Vyjadřovací schopnost 32 5.2 Polemika s odbornou literaturou 33 5.3 Celkové zhodnocení výhod a nevýhod 33 5.3.1 Výhody 34 5.3.2 Nevýhody 34 1 5.3.3 Výhody a nevýhody závislé na bezpečnostní politice 35 5.4 Vyhodnocení výhod a nevýhod 35 6 Návrh řešení 36 6.1 Návrh tříd SecurityManager, AccessController 36 6.2 Návrh třídy s bezpečnostní politikou 37 6.3 Návrh souboru s konfigurací bezpečnostní politiky 37 7 Implementace 39 7.1 Použité nástroje 39 7.1.1 Apache Ma ven 39 7.1.2 Git 40 7.2 Balíky a třídy 40 7.2.1 Balík net.sourceforge.prograde.sm 40 7.2.2 Balík net.sourceforge.prograde.policyparser 41 7.2.3 Balík net.sourceforge.prograde.policy 41 7.2.4 Balík net.sourceforge.prograde.debug 44 7.3 Nedostatky implementace 44 7.4 Řízení bezpečnosti pomocí třídy ProgradeSecurityManager . 46 7.5 Testovaní aplikace 46 7.6 Budoucí vývoj knihovny 47 8 Porovnání výkonů bezpečnostních politik 48 8.1 Porovnávací scénáře 48 8.2 Získání výsledků scénářů 50 8.3 Výsledky a jejich vyhodnocení 50 8.3.1 Oracle Java 1.6 51 8.3.2 Oracle Java 1.7 51 8.3.3 OpenJDKl.6 52 8.3.4 OpenJDK1.7 52 8.3.5 IBM Java 6 53 8.3.6 IBM Java 7 53 8.3.7 Znázornění výsledků 54 8.3.8 Vyhodnocení 56 9 Závěr 57 A Vyzkoušení funkčnosti knihovny Prograde 58 A . l Sestavení a spuštění aplikace progradeSimpleTestingProject 58 B Slovník pojmů 62 C Obsah přiloženého C D 63 2 1 Úvod Během posledních dvou desítek let došlo k velkému rozmachu informačních technologií. S tímto vývojem je však spojena i negativní stránka, která mimo jiné obnáší častější útoky na počítačové aplikace. Z tohoto důvodu je žádoucí aplikace lépe chránit před neoprávněnými přístupy. Programovací jazyk Java umožňuje různé kontroly přístupu k různým částem každé aplikace. Jednou z možností kontroly je řízení přístupu k citlivým zdrojům aplikace na základě bezpečnostní politiky a její konfigurace. Ve standardní Javě je použita bezpečnostní politika umožňující definovat, ke kterému z citlivých zdrojů je povolen přístup (na základě vlastností spouštěného kódu). Pro velkou část aplikací je tato bezpečnostní politika spojená s přístupem k citlivým zdrojům dostatečná, nicméně mohou existovat případy, kdy je její zápis značně náročný nebo nám neumožňuje plně vyjádřit potřebné podmínky přístupu. Jednou z možností, jak bezpečnostní politiku v Javě rozšířit, je zavést mimo pravidel, která definují, ke kterému z citlivých zdrojů můžeme přistoupit, také jejich protipól, tedy pravidla, která zakazují přístup, takzvaná zamítavá pravidla. Nicméně tato oblast není zatím nikterak probádána, a je proto nutné nejdříve navrhnout možné způsoby fungování zamítavých pravidel a vypořádat se s kombinací obou možných přístupů. Je také potřeba porovnat výkon současné implementace bezpečnostních politik a nově vznikající implementace umožňující použití zamítavých pravidel. Cílem této práce je takovou bezpečnostní politiku navrhnout a rozhodnout, zda její použití v Javě přináší zlepšení výkonu. Ve druhé kapitole této diplomové práce se krátce zabývám potřebnými definicemi základních pojmů, jejichž znalost je nutná pro pochopení následného textu. Třetí kapitola je věnována průzkumu tříd a konceptů spojených se standardní implementací bezpečnostní politiky v Javě. Je probrána každá zajímavá třída a vysvětlen průběh řízení přístupu k citlivým zdrojům na základě povolujících podmínek. Čtvrtá a pátá kapitola se týká návrhu a použití zamítavých pravidel. Nejprve se zabývám možnostmi rozšíření současného konceptu bezpečnostní politiky v Javě o zamítavá pravidla, a to jak z pohledu nastavení konfigurace bezpečnostní politiky uživatelem, tak z pohledu následné možné implementace. Dále rozebírám výhody a nevýhody použití zamítavých bezpečnostních pravidel. Šestá a sedmá kapitola jsou věnovány návrhu, implementaci a testování 3 1. Ú V O D řešení, na kterém lze snadno ukázat výhody použití zamítavých pravidel. Jedná se o rozšíření bezpečnostních politik v Javě knihovnou nazvanou Pro- grade. Osmá kapitola se týká samotného porovnání standardní bezpečnostní politiky a knihovny Prograde z hlediska výhody použití zamítavých pravidel. Obsahuje také grafy přehledně zobrazující získané informace. V závěrečné kapitole shrnuji získané poznatky a rozhoduji, zda je výhodné zabývat se dále konceptem bezpečnostní politiky se zamítavými pravidly v Javě. 4 2 Základní pojmy Autentizace je proces, během něhož se prověřuje identita subjektu žádajícího o přístup k systému. Autentizaci lze provádět na základě určité znalosti (například heslo), určitého vlastnictví (například klíč), určité vlastnosti (pro uživatele se může jednat o nějakou biometriku) nebo jejich kombinací. [5] Autorizace je proces, během něhož je subjektu přiřazena množina práv v systému, na jejichž základě je mu umožněn přístup do jeho různých částí. [6] Bezpečnost je vlastnost nějakého prvku (například programu) určující ochranu před neoprávněnou manipulací s daty a informacemi, a také před jejich poškozením či ztrátou. Bezpečnostní politika je soubor bezpečnostních zásad a pravidel definující možnosti přístupu k citlivým zdrojům systému. Její striktní dodržování je základním krokem pro správně fungující bezpečnost aplikace.[6] Zamítavým pravidlem se ve spojení s bezpečnostní politikou rozumí takové pravidlo, které zamezuje přístupu k určitému zdroji. Kryptografie je věda zabývající se algoritmy pro šifrování a dešifrování informací - k tomuto procesu je použita také jistá informace nazývaná klíč. Kryptografické algoritmy se podle způsobu použití klíčů dělí do dvou skupin: • Symetrická kryptografie - pro šifrování i dešifrování informace je použit stejný kryptografický klíč. • Asymetrická kryptografie - pro šifrování je použit jiný klíč než pro dešifrování. Klíč sloužící pro zašifrování se nazývá veřejným klíčem a klíč sloužící pro dešifrování označujeme jako soukromý klíč. [5] Digitální podpis je speciálním typem asymetrické kryptografie, kdy je chráněná informace nejprve podepsána za pomoci soukromého klíče, tedy je provedeno zašifrování pomocí asymetrické kryptografie, a informace poté může být kýmkoliv ověřena (kýmkoliv ve smyslu kdokoliv z množiny lidí mající přístup k veřejnému klíči), tedy dešifrována. Tímto procesem lze zaručit, že daná chráněná informace opravdu pochází od určitého zdroje.[6] 5 2. Z Á K L A D N Í P O J M Y Certifikát je veřejný klíč uživatele podepsaný soukromým klíčem důvěryhodné třetí strany. Právě pomocí certifikátu lze ověřit digitální podpis. Certifikát zaručuje, že daný uživatel je opravdu uživatelem, za kterého se vy­ dáváno] Keystore (česky úložiště klíčů) je typ databáze sloužící pro bezpečné uložení certifikátů a klíčů. Pro práci s keystore lze použít nástroj k e y t o o l umožňující správu a vytváření klíčů. [7] 6 3 Řízení přístupu v Javě Řízení přístupu je v Javě vykonáváno pomocí kooperace standardních Java tříd (SecurityManager, P e r m i s s i o n atdv viz níže) a nadstavby Java Authentication and Authorization Service (zkráceně JAAS). Tradiční Java prováděla řízení přístupu na základě informací, odkud pochází zdrojový kód a kým je podepsán, což se ukázalo jako nedostatečné. Pomocí JAAS bylo možné řídit se i informací, kdo daný kód spouští (jenž se nazývá subjekt), a proto se od Javy verze 1.4 stal JAAS její standardní součástí. Autentizace probíhá pomocí přihlašovacích modulů1 , které se podle definovaných pravidel pokouší autentizovat daný subjekt. Pokud přihlášení proběhne úspěšně, jsou subjektu přiřazeny instance třídy P r i n c i p a l (reprezentující nějaké identity subjektu, přičemž jednomu subjektu může být přiřazeno více instancí P r i n c i p a l , příkladem může být uživatelské jméno) z balíku Java . s e c u r i t y , dále v textu označené jen P r i n c i p a l , a Credentials (programátorem napsané třídy reprezentující nějaké vlastnosti, často spojené se třídou P r i n c i p a l , například heslo). Ve vztahu k tématu této práce je to vše, co potřebujeme o autentizaci v Javě vědět. [23] Autorizace v Javě využívá několik zajímavých tříd, které budou probrány v následujících podkapitolách. Teprve poté bude ukázán samotný průběh autorizace. Pro snazší orientaci v textu přidávám zjednodušené vysvětlení některých tříd (přesněji jsou popsány dále v textu): • java . s e c u r i t y . P e r m i s s i o n (dále jen Permission) - třída používaná pro reprezentaci povolení přístupu k citlivé proměnné. • java . s e c u r i t y . CodeSource (dále jen CodeSource) - třída reprezentující zdroj kódu a tvořená U R L adresou a certifikáty daného zdroje kódu. • java . s e c u r i t y . P r o t e c t i o n D o m a i n (dále jen P r o t e c t i o n D o main) - třída reprezentující chráněnou doménu každé třídy, tedy spojující CodeSource s množinou objektů Permission. Dále může obsahovat informace o přiřazených objektech P r i n c i p a l a použitý C l a s s L o a d e r 2 . 1. anglicky Login Module 2. objekt použitý pro načtení třídy pro použití v JVM 7 3. Ř Í Z E N Í P Ř Í S T U P U v J A V Ě 3.1 Security Manager Třída java . l a n g . SecurityManager (dále jen SecurityManager) je součástí JDK již od verze JDK 1.0. Původní SecurityManager z JDK 1.0 měl definováno velké množství kontrolních metod (ve tvaru checkXXX (argument, . . . )), jejichž chování nebylo vzájemně nijak provázáno. Díky tomu byla implementace vlastní třídy rozšiřující SecurityManager poměrně náročná, protože bylo nutné řešit každý typ kontroly zvlášť. Dalším problémem bylo těsné propojení mezi třídou SecurityManager a samotnou bezpečnostní politikou, kdy změna bezpečnostní politiky znamenala nutnost změnit i SecurityManager. Z těchto důvodů se větších změn funkce Security Manageru dočkala ve verzi JDK 1.2, kdy byla představena třída java . s e c u r i t y . A c c e s s C o n t r o l l e r (dále A c c e s s C o n t r o l l e r ) , která přebírá podstatnou část její funkcionality. Standardní S e c u r i t y M a nager ji využívá pro rozhodování, zda povolit nebo zakázat přístup k citlivému zdroji aplikace, nicméně v jeho rozšířeních to nemusí být pravidlem. Dále byla představena metoda checkPermission, kterou využívají všechny bývalé checkXXX metody pro rozhodnutí, zda povolit přístup k citlivému zdroji. Hlavním důvodem jejich zachování ve třídě S e c u r i t y M a nager je zpětná kompatibilita. Security Manager je hlavním prvkem při vynucování bezpečnostních politik v Javě. Jeho hlavním úkolem je rozhodování o povolení/zamítnutí přístupů k citlivým zdrojům aplikace. Aby mohla být bezpečnostní politika dodržována pro celou aplikaci stejně, platí pravidlo, že v J V M (Java Virtual Machine) je pro rozhodování o přístupu použit vždy nejvýše jeden objekt třídy SecurityManager. V případě, že SecurityManager není nastaven, není vynucována žádná bezpečnostní politika a tím pádem jsou všechny operace, jindy řízené bezpečnostní politikou, povolené. Většina metod třídy SecurityManager nese název ve tvaru checkXXX (argument, . . . ). Jejich chování je prakticky stejné - uvnitř metody je vytvořen objekt třídy P e r m i s s i o n s požadovanými parametry, a poté je vyvolánanejdůležitější metoda třídy SecurityManager - checkPermiss i o n (Permission perm) .Ve standardní implementaci třídy S e c u r i t y Manager je její chování prosté, pouze zavolá metodu checkPermission (Permission perm) třídy A c c e s s C o n t r o l l e r , na kterou tak předeleguje rozhodnutí o povolení nebo zamítnutí daného požadavku. Výsledek rozhodování závisí na dané bezpečnostní politice a aktuálním kontextu a projeví se následujícím chováním: • požadavek je povolen - metoda bezchybně skončí 8 3. Ř Í Z E N Í P Ř Í S T U P U v J A V Ě • požadavek je zamítnut - je vyvolána výjimka S e c u r i t y E x c e p t i o n Typický příklad použití metody checkPermission může být následující (pro provedení metody doSomething () potřebujeme mít povolenou permission třídy SomePermission se jménem name): SecurityManager s e c u r i t y = System.getSecurityManager(); i f (security != null) { SomePermission p = new SomePermission(name); security.checkPermission(p); } doSomething(); Nejdříve se tato část programu snaží získat objekt typu S e c u r i t y M a nager. V případě, kdy jej neobdrží, znamená to, že SecurityManager není nastaven a může být provedena doSomething (). Pokud je S e c u r i tyManager získán, je vytvořena instance třídy SomePermission, která je předána metodě checkPermission, pomocí které zjistí, zda je tento přístup k citlivému zdroji povolen. V případě, že ano, tak může být provedena metoda doSomething () . V opačném případě je vyvolána výjimka S e c u r i t y E x c e p t i o n . Další zajímavou metodou je g e t S e c u r i t y C o n t e x t (), používaná pro uchování aktuálního prováděného kontextu v objektu, který může být později mimo jiné předán dvouparametrové metodě checkPermission (Permission perm, Object c o n t e x t ) , která se chová podobně jako c h e c k P e r m i s s i o n (Permission perm) s tím rozdílem, že rozhodnutí o povolení/zamítnutí požadavku je prováděno na předaném kontextu, nikoliv na kontextu aktuálním. Za zmínku stojí také nativní metoda getClassContext (), která vrací pole objektů typu C l a s s na základě aktuálního stacku3 . Pomocí tohoto pole můžeme určit pořadí, ve kterém byly dané třídy a metody volány, což může být užitečné při rozhodování, zda povolit přístup k citlivým zdrojům. SecurityManager není pro běh programu standardně nastaven, do J V M může být přidán dvěma způsoby: • Nastavením systémové proměnné java . s e c u r i t y . manager před spuštěním programu. Pokud je tato proměnná použita bez přiřazené hodnoty, použije se standardní SecurityManager. Vlastní SecurityManager můžeme nastavit pomocí přiřazení celého jména třídy (rozšiřující SecurityManager) do výše zmíněné systémové proměn­ né. 3. stack (česky zásobník volání) je seznam volaných tříd a metod seřazený podle toho, jak byly volány 9 3. Ř Í Z E N Í P Ř Í S T U P U v J A V Ě • Z kódu aplikace pomocí statické metody setSecurityManager (SecurityManager sm) třídy System. Pokud je S e c u r i t y M a n a ger v J V M nastaven, musí bezpečnostní politika umožňovat jeho nové nastavení, tedy povolovat java . lang . RuntimePermission se jménem " s e t S e c u r i t y M a n a g e r " (pokud je SecurityManager zároveň i vytvářen, je potřeba také java . l a n g . RuntimePermission se jménem " createSecurityManager "). Zda-li je SecurityManager pro aplikaci nastaven, můžeme zjistit pomocí statické metody třídy System, System. getSecurityManager (), která vrací používanou instanci třídy SecurityManager v případě, kdy je pro aplikaci již nastaven nebo hodnotu nu 11, pokud nastaven není. [1] [3] [8] 3.2 Metoda implies Jedná se o jednu z nejdůležitějších metod v bezpečnosti v Javě. Metoda je definována pro třídy spojené s řízením přístupu k citlivým zdrojům (například pro třídy P e r m i s s i o n , ProtectionDomain nebo CodeSource) a její chování je principiálně podobné dobře známé metodě equals třídy java . l a n g . Ob ject. U i m p l i e s nás však nezajímá, zda jsou objekty stejné, ale zda daný objekt implikuje jiný objekt, tedy zda parametr metody „platí" v případě, když „platí" instance třídy, na které metodu voláme. Metodu i m p l i e s voláme pomocí: ob j 1.imp1i e s(ob j 2) ; a matematicky ji můžeme přepsat na: objl => obj 2 V případě, že objekt, na kterém je volána metoda i m p l i e s implikuje daný parametr, je vráceno true, v opačném případě f a l š e . Příklad: Pro ukázku funkce metody i m p l i e s můžeme použít U R L adresu (ta se může v praxi vyskytovat například při použití metody i m p l i e s ve třídě CodeSource nebo pro vyhodnocení metody i m p l i e s třídy java . i o . F i l e P e r m i s s i o n ) . Symbol '*' zde znamená zástupný znak. Mějme tedy dvě cesty: 10 3. Ř Í Z E N Í P Ř Í S T U P U v J A V Ě p a t h l = / p a t h / t o / f i l e . t x t path2=/path/to/* pak výsledkem metody i m p l i e s bude: pathl.implies(path2) = false path2.implies(pathl) = true 3.3 Třída Permission Abstraktní třída P e r m i s s i o n je základním stavebním kamenem autorizace v Javě. Tato třída reprezentuje povolení k práci s určitým citlivým zdrojem. Tím může být například zápis do souboru, čtení systémové proměnné atd. Každá třída v Javě, která ji rozšiřuje, má povinně definované jméno a v některých případech i akci. Každá instance třídy P e r m i s s i o n je pak určena svým typem (tj. třídou, která rozšiřuje třídu Permission), jménem a případně akcí. Jménem může být libovolný řetězec, akcí pak upřesňující požadavek, říkající, co má daná P e r m i s s i o n povoleno. Jako příklad uvádím P e r m i s s i o n pro čtení a zápis do souboru f oo . t x t s jejími vlastnostmi (jméno instance F i 1 eP e rmi s s i o n je shodné s cestou k danému souboru) a dále také P e r m i s s i o n bez akce, kterou může být například S e c u r i t y P e r m i s s i o n pro povolení nastavení vlastní bezpečnostní politiky: [9] Typ: java.io.FilePermission java.security.SecurityPermission Jméno: foo.txt setPolicy Akce: read, write Objekty třídy P e r m i s s i o n jsou v Javě používány ve dvou případech: [2] • Oprávnění přidělené - v bezpečnostní politice, při určení akcí, jež jsou danou politikou povoleny • Oprávnění vyžadované - bývají vytvářeny v metodách, které se pomocí Security Manageru dotazují, zda je ona vzniklá P e r m i s s i o n nastavenou bezpečnostní politikou povolena. Každá P e r m i s s i o n musí mimo jiné povinně definovat abstraktní metodu i m p l i e s , a dále také metodu g e t A c t i o n s , která vrací seznam akcí v kanonickém pořadí. Mezi zajímavé podtřídy třídy P e r m i s s i o n patří třídy:[2] 11 3. Ř Í Z E N Í P Ř Í S T U P U v J A V Ě • Java . s e c u r i t y . B a s i c P e r m i s s i o n (dále j e n B a s i c P e r m i s s i o n ) - abstraktní třída, která je rozšířena třídami, které používají stejnou konvenci pro jména jako Ba s i cP e rmi s s i o n - jejich jménem je přímo jméno citlivého zdroje. Příkladem rozšíření B a s i c P e r m i s s i o n mohou být S e c u r i t y P e r m i s s i o n a PropertyPermission.[24] • java . s e c u r i t y . A l l P e r m i s s i o n (dálejen A l l P e r m i s s i o n ) -třída reprezentující možnost, kdy chceme garantovat přístup ke všem citlivým zdrojům aplikace, tedy kdy chceme garantovat všechny možné Permission. Metoda i m p l i e s třídy A l l P e r m i s s i o n tedy vždy vrací true. Objekt A l l P e r m i s s i o n se získává zavoláním bezparametrického konstruktoru. Jméno této P e r m i s s i o n nehraje žádnou roli.[10] • java . s e c u r i t y . U n r e s o l v e d P e r m i s s i o n (dálejen U n r e s o l v e d Permission) - třída používaná při načítání podtříd třídy P e r m i s s i o n pro jejich použití v aplikaci. Každá třída rozšiřující třídu P e r m i s s i o n , která není obsažená ve standardní Java knihovně, je nejdříve uložena v podobě U n r e s o l v e d P e r m i s s i o n a samotný objekt této třídy je vytvořen až při prvním pokusu o jeho volání (takto je v různých implementacích Javy, z důvodů zvýšení výkonu aplikace, zacházeno i se třídami rozšiřující třídu Permission). V objektu Unr e s o l v e d P e r m i s s i o n je mimo běžného jména a akce uložen taky řetězec s typem dané P e r m i s s i o n (tedy s jejím plným jménem), pomocí kterého je pak instance třídy vytvořena a objekt U n r e s o l v e d P e r m i s s i o n je zahozen. Třída U n r e s o l v e d P e r m i s s i o n slouží pro uchování informace o jiné P e r m i s s i o n , proto její metoda i m p l i e s vždy vrací false.[11] 3.4 Bezpečnostní politika Na pojem bezpečnostní politika může být v Javě nahlíženo ze dvou úhlů pohledu. Jednak se jedná o abstraktní třídu java . s e c u r i t y . P o l i c y , dále jen P o l i c y , která definuje způsob řízení přístupu k citlivým zdrojům. V případě, že je v aplikaci použit její potomek z OpenJDK, sun. s e c u r i t y , p r o v i d e r . P o l i c y F i l e (dále jen P o l i c y F i l e ) , může se pak za bezpečnostní politiku považovat také správně utvořený soubor (viz níže) definující konfiguraci bezpečnostní politiky, tj. ke kterým citlivým zdrojům aplikace je danou politikou povolen přístup. 12 3. Ř Í Z E N Í P Ř Í S T U P U v J A V Ě 3.4.1 Třída Policy Stejně jako u třídy SecurityManager může být v jedné J V M použit nejvýše jeden objekt třídy P o l i c y . Jeho nastavení lze provést přímo ze zdrojového kódu aplikace pomocí statické metody třídy P o l i c y s e t P o l i c y ( P o l i c y p) a obdobně může být získán pomocí metody g e t P o l i c y () . V případě, kdy není žádná P o l i c y v J V M nastavena, může být metoda g e t P o l i c y O taktéž použita pro nahrání standardní implementace třídy P o l i c y , která je určena na základě proměnné p o l i c y . p r o v i d e r ze souboru /lib/security/java.security. Třída P o l i c y také definuje, jak je definice bezpečnostní politiky získána. Uložení konfigurace bezpečnostní politiky záleží na požadavcích implementace podtřídy třídy P o l i c y , může být například uchovávána v textovém souboru nebo v databázi. Mezi důležité metody tradičně patří abstraktní metoda i m p l i e s a dále metoda r e f resh, sloužící k načtení nebo obnovení bezpečnostní politiky z jejího úložiště.[12] 3.4.2 Třída PolicyFile sun . s e c u r i t y . p r o v i d e r . P o l i c y F i l e je třída z OpenJDK rozšiřující třídu P o l i c y a definující způsob práce s bezpečnostní politikou. Běžný princip prosazování bezpečnostní politiky (tedy zda je přístup ke konkrétnímu citlivému zdroji aplikace povolen) je v P o l i c y F i l e následující:[13] 1. nejdříve je zavolána metoda i m p l i e s , která v případě třídy P o l i c y dostává dva parametry • ProtectionDomain, na které chceme zjišťovat, zda máme přístup povolen • Permission, určující zdroj, ke kterému chceme přistoupit 2. metoda získá z bezpečnostní politiky pomocí ProtectionDomain objekt třídy java . s e c u r i t y . P e r m i s s i o n C o l l e c t i o n (dále jen P e r m i s s i o n C o l l e c t i o n ) relevantní pro danou P r o t e c t i o n D o main. V rámci optimalizace je použita mapa, uchovávající již hledané ProtectionDomain spolu s jejich P e r m i s s i o n C o l l e c t i o n . Tím pádem je pro každou ProtectionDomain vytvářena P e r m i s s i o n C o l l e c t i o n pouze jednou. 3. je zavolána metoda i m p l i e s získané P e r m i s s i o n C o l l e c t i o n , jejíž výsledek je výsledkem celého volání metody i m p l i e s na objektu P o l i c y F i l e 13 3. Ř Í Z E N Í P Ř Í S T U P U v J A V Ě 3.4.3 Soubor s konfigurací bezpečnostní politiky Standardní P o l i c y F i l e používá pro definici bezpečnostní politiky ASCII textový soubor, který může být vytvořen klasickou cestou jako běžný textový soubor nebo může být použit grafický program Policy Tool, sloužící speciálně k tomuto účelu. Soubor je pro Java aplikaci určen pomocí systémové proměnné j a v a . s e c u r i t y . p o l i c y , jejíž hodnotu je nutno nastavit na cestu k tomuto souboru. V případě, že proměnná není použita, tak je bezpečnostní politika načtena pomocí proměnných p o l i c y . u r l . n ze souboru java . h o m e / l i b / s e c u r i t y / java . s e c u r i t y . Tento soubor může obsahovat větší množství takových proměnných, řazených od 1 do i , a v tomto případě jsou použity všechny. Každý soubor s konfigurací bezpečnostní politiky může obsahovat prvek uvedený klíčovým slovem keystore. Pomocí něj je odkazována databáze s uloženými bezpečnostními klíči používaná pro zbytek souboru. Pomocí prvku uvozeného klíčovým slovem keystorePasswordURL je definována cesta k heslu pro dané úložiště. Definice úložiště klíčů se může vyskytovat kdekoliv v bezpečnostním souboru vyjma obsahu grant prvku. Pokud bude v souboru více prvků keystore/keystorePasswordURL, použije bezpečnostní politika první takové a zbylé ignoruje. Úložiště klíčů nemusí být definováno vůbec, pak ale nesmí být ve zbytku souboru použita žádná klíčová slova signedBy (viz níže), která pracují právě s úložištěm klíčů a certifikátů. Syntaxe prvku keystore je následující: keystore " u r l _ u l o z i s t e " , " t y p _ u l o z i s t e " , "poskytovatel_uloziste"; keystorePasswordURL "url_k_heslu"; Slova u r l _ u l o z i st e a u r l _ k _ h e s l u jsou nahrazeny cestou k daným souborům, t y p _ u l o z i s t e je typ daného keystore a p o s k y t o v a t e l _ u l o ž i ste je jeho poskytovatel (který poskytuje například bezpečnostní algoritmy, generování klíčů atd.). Povinné jsou pouze URL adresy. Nejpodstatnější částí souboru s bezpečnostní politikou jsou grant prvky. Každý takový prvek definuje, jaké akce jsou povoleny pro daný zdroj kódu (reprezentovanému třídou CodeSource), kterému v souboru s bezpečnostní politikou odpovídají klíčová slova codebase a signedBy. Codebase obsahuje U R L adresu, odkud zdrojový kód pochází. V této U R L může být použit zástupný symbol /*, reprezentující libovolný soubor ve složce, nebo symbol / -, reprezentující libovolný soubor ve složce i ve všech podsložkách. SignedBy obsahuje jména uživatelů (v definovaném keystore), kterými má být zdrojový kód podepsán. Posledním klíčovým slovem 14 3. Ř Í Z E N Í P Ř Í S T U P U v J A V Ě použitým v definici grant prvku je p r i n c i p a l , pomocí nějž můžeme nastavit platnost grant prvku pouze pro určité instance třídy P r i n c i p a l (například pro konkrétní uživatele). U všech názvů prvků nezáleží na velikosti písmen. Uvnitř každého grant prvku jsou obsaženy definice konkrétních Permission, tedy povolení k práci s určitým citlivým zdrojem. Toto povolení je uvedeno klíčovým slovem p e r m i s s i o n a dále má definována pole jméno třídy Permission, jméno daného objektu třídy P e r m i s s i o n a akce povolené pro tento objekt. Ke každé definici p e r m i s s i o n se může pojit také prvek signedBy, říkající, že přímo daná třída P e r m i s s i o n musí být podepsána danými uživateli. Syntaxe grant prvku v bezpečnostním souboru je následující: grant signedBy "jmena_podepisujicich", CodeBase "URL", p r i n c i p a l n a z e v _ t r i d y _ P r i n c i p a l "jmeno_konkretniho_objektu"; { permission nazev_tridy_Permission "jmeno_objektu_Permission", "akce", signedBy "jmena_podepisujicich"; }; Všechny signedBy, CodeBase a p r i n c i p a l jsou nepovinné a nezáleží na jejich pořadí. Prvek p r i n c i p a l může mít libovolný počet výskytů, mezi kterými je vztah definovaný pomocí logického „a" (tj. AND). V případě, že nějaké z těchto klíčových slov definováno není, pak na něm platnost grant prvku nezávisí (tj. je pro něj splněna). Definice každého grant prvku obsahuje 0 a více prvků p e r m i s s i o n . V souboru s bezpečnostní politikou může být použita expanze vlastností (anglicky property expansion). Je pro ní použit tvar: $ {vlastnost} a můžeme pomocí ní zpřístupnit například domovskou složku.[14][3] 3.5 Třídy spojené s autorizací 3.5.1 AccessController a AccessControllerContext Jedná se o třídy pro řízení přístupu k citlivým zdrojům aplikace. Obě jsou označeny klíčovým slovem f i n a l , není tedy možné je rozšířit. Třída A c c e s s C o n t r o l l e r má pouze privátní konstruktor. Práce s ní je prováděna pomocí statických metod a používá se v následujících třech situacích: 15 3. Ř Í Z E N Í P Ř Í S T U P U v J A V Ě • při rozhodování zda povolit nebo zamítnout přístup k citlivému zdroji • při provádění části kódu v privilegovaném stavu • pro získání současného stavu4 bezpečnostního kontextu Rozhodování o povolení přístupu je stejně jako ve třídě S e c u r i t y Manager prováděno metodou c h e c k P e r m i s s i o n (Permission perm) - pokud je přístup povolen, metoda se pouze tiše vrátí, pokud není, je vyvolána výjimka. Jedná se o statickou metodu, kterou ve standardní implementaci bezpečnosti v Javě používá právě SecurityManager pro své rozhodnutí. Tato metoda může být volána libovolnou třídou, čímž se z rozhodování o povolení přístupu odstraní Security Manager, což může při nesprávném použití vést ke špatnému chování bezpečnosti aplikace. Přístup k citlivému zdroji aplikace je povolen pouze tehdy, pokud je přístup povolen pro každou chráněnou doménu z aktuálního bezpečnostního kontextu (ten je získán pomocí nativní privátní metody třídy A c c e s s C o n t r o l l e r ) . Jedinou výjimku tvoří kód označený jako privilegovaný, kdy je k povolení přístupu nutné pouze povolení k privilegované části (a ke zděděnému bezpečnostnímu kontextu, viz níže). Zjednodušené ověření, zda přístup k citlivému zdroji povolit, či nikoliv, probíhá následujícím způsobem: Označme volání metod v aktuálním kontextu postupně za sebou, jak byla volána od 1 do m, kde m označuje volání metody checkPermission. Pak je výsledek určen pomocí následujícího algoritmu: i = m; while ( i > 0) { i f (chráněna doména i neraa povoleny přistup) throw new AccessControlException; i f ( v o l a j i c i i j e označen jako privilegovaný) break; i = i - 1; } return; Algoritmus však ještě není úplný. Při vytváření nového vlákna aplikace je pomocí třídy java . s e c u r i t y . A c c e s s C o n t r o l C o n t e x t (dálevtextu jen Acces sControlContext) uchován aktuální bezpečnostní kontext, který je označen jako zděděný kontext. Při každém provedení metody v privilegovaném stavu je kontrolováno, zda je daná permission povolena také tímto zděděným kontextem. Platí tedy, že pro získání přístupu k citlivému zdroji musí být tento přístup garantován také pro zděděný kontext, a tím 4. v angličtině snapshot 16 3. Ř Í Z E N Í P Ř Í S T U P U v J A V Ě pádem rekurzivně i pro všechny zděděné kontexty rodičů. Výše zmíněný algoritmus ve svém plném znění tedy vypadá následujícím způsobem: i = m; while ( i > 0) { i f (chráněna doména i neraa povoleny přistup) throw new AccessControlException; i f ( v o l a j i c i i j e označen jako privilegovaný) break; i = i - 1; } zkontroluj povoleni pro zdedený bezpecnostni kontext; return; Provedení metody v privilegovaném stavu je umožněno pomocí nativní metody d o P r i v i l e g e d třídy A c c e s s C o n t r o l l e r . Ta může být volána buď na aktuálním kontextu, a nebo jí může být předán kontext pomocí třídy A c c e s s C o n t r o l C o n t e x t . Důležitým parametrem je P r i v i l e g e d A c t i o n 5 . Jedná se o rozhraní, které definuje jedinou metodu - run (). Metoda d o P r i v i l e g e d , pak provede run () metodu v privilegovaném stavu. V případě, že potřebujeme získat nějakou hodnotu, může ji vracet metoda run () a následně metoda d o P r i v i l e g e d . Pokud pro nás není návratová hodnota důležitá, může metoda run () jednoduše vracet hodnotu n u l l . Použití d o P r i v i l e g e d metody v kóduje následující: S t r i n g javaHome = AccessController.doPrivileged( new PrivilegedAction() { public S t r i n g run () { return System.getProperty("java.home"); } }); Pokud má být metoda volána v nějakém kontextu, je tento kontext předán jako druhý parametr metody d o P r i v i l e g e d . S označením kódu jako privilegovaný by mělo být zacházeno s rozvahou - označena by měla být jen ta část, která nutně musí být provedena v privilegovaném stavu. V opačném případě hrozí, že budou povoleny i akce, které by daná bezpečnostní politika měla zamítnout. Posledním využitím třídy A c c e s s C o n t r o l l e r je získání současného bezpečnostního kontextu. K tomuto účelu slouží metoda getContext (), jenž vrací objekt typu A c c e s s C o n t r o l C o n t e x t obsahující aktuální kontext. [15] [2] 5. případně PrivilegedExceptionAction, lišící se pouze tím, že její metoda run () vyvolává výjimku 17 3. Ř Í Z E N Í P Ř Í S T U P U v J A V Ě Třída A c c e s s C o n t r o l C o n t e x t j e používána pro určení přístupu k citlivým zdrojům z kontextu, který reprezentuje. K tomuto účelu používá vlastní metodu checkPermission, jejíž chování je prakticky stejné jako u třídy A c c e s s C o n t r o l l e r s rozdílem, že je prováděna na onom kontextu. Může také obsahovat objekt typu DomainCombiner sloužící k vytváření nových chráněných domén na základě nějakých již existujících. [16] 3.5.2 PermissionCollection a Permissions Abstraktní třída P e r m i s s i o n C o l l e c t i o n reprezentuje kolekci objektů třídy P e r m i s s i o n . Hlavní myšlenkou je utvořit uskupení, na kterém půjde efektivně zavolat metoda i m p l i e s (Permission p e r m i s s i o n ) , ověřující, zda některá z obsažených P e r m i s s i o n v kolekci implikuje danou P e r mission. Metoda je abstraktní a je tedy čistě v režii rozšiřující podtřídy, jak je tato operace vykonávána. Dalšími důležitými metodami jsou taktéž abstraktní add (Permission p e r m i s s i o n ) , pro přidání nového objektu třídy P e r m i s s i o n do kolekce, a elements () vracející enumeraci všech P e r m i s s i o n z kolekce. Pokud uchováváme v kolekci P e r m i s s i o n jednoho typu, je instance podtřídy P e r m i s s i o n C o l l e c t i o n vytvořena pomocí metody n e w P e r m i s s i o n C o l l e c t i o n zavolané na dané P e r m i s sion. Takto vytvořená kolekce bude homogenní a umožní nám tedy efektivně pracovat pouze s jedním typem objektů třídy Permission.[17] Java . s e c u r i t y . P e r m i s s i o n s (dále jen Permissions) je třída rozšiřující třídu P e r m i s s i o n C o l l e c t i o n . Její nejdůležitější vlastností je heterogennost. Pracuje tedy s objekty třídy P e r m i s s i o n , které nemusí být stejného typu. Implementace třídy je opět uzpůsobena efektivnímu použití metody i m p l i e s (Permission p e r m i s s i o n ) . P e r m i s s i o n s obsahuje více kolekcí typu P e r m i s s i o n C o l l e c t i o n , tím pádem je při ověřování, zda objekt třídy P e r m i s s i o n s implikuje danou P e r m i s s i o n , nejdříve zjištěn typ této P e r m i s s i o n a následně je provedena metoda i m p l i e s vnitřní kolekce P e r m i s s i o n C o l l e c t i o n , která obsahuje pouze objekty P e r m i s s i o n tohoto typu. V případě, že daná kolekce není v Permissions obsažena, je pro její inicializaci opět zavolána metoda newPermissionC o l l e c t i o n dané Permission.[18][1] 3.5.3 CodeSource V bezpečnosti v Javě nám nemusí stačit znát místo, ze kterého je daný zdrojový kód načten. Důležitou může být také informace, jaké jsou s ním spojeny certifikáty, případně kým byl podepsán. Z toho důvodu je zave- 18 3. Ř Í Z E N Í P Ř Í S T U P U v J A V Ě dena třída CodeSource, která k cestě ke zdrojovému kódu, reprezentovanému třídou U R L , přidává buďto pole certifikátů (reprezentované třídou java . s e c u r i t y . c e r t . C e r t i f i c a t e ) , pojících se k danému zdrojovému kódu, a nebo pole určující, kým byl zdrojový kód podepsán (třída j a v a . s e c u r i t y . CodeSigner). CodeSource samozřejmě obsahuje metodu i m p l i e s (CodeSource cs), sloužící pro určení, zda CodeSource implikuje daný CodeSource. Třídy z Java API nemají CodeSource definovaný, jeho hodnota je tedy null.[19][l] 3.5.4 ProtectionDomain Každá třída v Javě je spojena s právě jedním objektem třídy P r o t e c t i o n Domain. Účelem této třídy je mimo jiné zjednodušení procesu definice, ke kterým citlivým zdrojům mají všechny objekty pocházející ze stejného zdroje přístup. Implementace je provedena především pomocí tříd CodeSource (reprezentující zdroj kódu) a P e r m i s s i o n C o l l e c t i o n (obsahující množinu objektů typu Permission). Dále může být nastaven C l a s s Loader a pole objektů typu P r i n c i p a l pojících se k dané chráněné do­ méně. ProtectionDomain je nejčastěji vytvářena při načítání třídou C l a s sLoader, kdy je ke každé načtené třídě zhotovena i její chráněná doména. V tomto případě obsahuje daná P e r m i s s i o n C o l l e c t i o n pouze statickou množinu objektů P e r m i s s i o n , tedy takovou, která není načítána ze souboru (nebo jiných úložišť) s konfigurací bezpečnostní politiky. Tato statická množina obsahuje ve standardní bezpečnosti v Javě: • pro třídy z Java API povolení všech přístupů k citlivým zdrojům, reprezentováno třídou A l l P e r m i s s i o n • pro jiné třídy F i l e P e r m i s s i o n se jménem zdroje kódu a akcí "read", tedy možnost číst soubor, ze kterého třída pochází, a dále pak RuntimePermission se jménem "exitVM", sloužící pro možnost ukončení JVM. Jakmile je objekt typu ProtectionDomain jednou vytvořen, není možné jej už dále modifikovat. Metoda i m p l i e s má v této třídě dva způsoby chování. Závisí na tom, zdaje P e r m i s s i o n C o l l e c t i o n dané ProtectionDomain statická nebo dynamická. Pro statickou volá metodu i m p l i e s na své P e r m i s s i o n C o l l e c t i o n . V případě, kdy je dynamická, tak získá objekt P o l i c y a metodu i m p l i e s volá na něm, přičemž jí předává sama sebe a zkoumanou P e r m i s s i o n . 19 3. Ř Í Z E N Í P Ř Í S T U P U v J A V Ě Objekt třídy ProtectionDomain můžeme pro každou třídu získat pomocí statické metody třídy C l a s s getProtectionDomain (). Pokud je v aplikaci nastaven Security Manager, je nutné, aby byla bezpečnostní politikou povolena RuntimePermission se jménem " g e t P r o t e c t i o n D o main ".[20][1][2] 3.6 Standardní průběh autorizace Na základě výše popsané analýzy autorizace v Javě můžu ukázat její standardní průběh: 1. Zavoláním metody System. getSecurityManager () je získán SecurityManager. V případě, že je n u l l , autorizace neprobíhá a přístup k citlivému zdroji je tedy povolen. Naopak, pokud je objekt třídy SecurityManager získán, následuje jeden z těchto kroků: l.a Je vytvořena Permi s s i o n pojící se k onomu citlivému zdroji, ke kterému chceme přistoupit, a je předána jako parametr metodě checkPermission dříve získaného Security Manageru. l.b Je zavolána metoda checkXXX ze třídy SecurityManager, která vytvoří předem danou P e r m i s s i o n (pro různé checkXXX různou Permission), a poté volá metodu checkPermission, které tuto P e r m i s s i o n předá jako parametr. 2. Metoda checkPermission ze třídy SecurityManager pouze zavolá metodu checkPermission třídy A c c e s s C o n t r o l l e r , které předá onu Permission. 3. A c c e s s C o n t r o l l e r získá pomocí nativní metody objekt typu A c c e s s C o n t r o l C o n t e x t , na němž volá opět metodu checkPermiss i o n s danou P e r m i s s i o n . 4. Metoda checkPermission třídy A c c e s s C o n t r o l C o n t e x t volána každém prvku kontextu (což jsou objekty typu ProtectionDomain), pokud není n u l l , metodu i m p l i e s vracející hodnotu typu boolean. V případě, že některá část kontextu vrací f a l š e , je zde vyvolána výjimka, pomocí které A c c e s s C o n t r o l l e r a SecurityManager zjistí, že P e r m i s s i o n byla zamítnuta. Následující body jsou provedeny na každém prvku bezpečnostního kontextu: 20 3. Ř Í Z E N Í P Ř Í S T U P U v J A V Ě 4.1. V metodě i m p l i e s třídy ProtectionDomain je získán objekt P o l i c y a zavolána jeho metoda i m p l i e s s předanými parametry - touto ProtectionDomain a zkoumanou Permission. 4.2. Pomocí předané ProtectionDomain v metodě i m p l i e s získá třída P o l i c y ze své vnitřně uložené mapy objekt typu P e r m i s s i o n C o l l e c t i o n (který obsahuje P e r m i s s i o n získané ze souboru s konfigurací bezpečnostní politiky). N a této P e r m i s s i o n C o l l e c t i o n je pak zavolána metoda i m p l i e s , jejíž výsledek je pak výsledkem celého volání. 3.7 Chráněné objekty V Javě může být pomocí bezpečnostní politiky řízen také přístup k programátorem vybraným objektům. K tomuto účelu slouží třída java . sec u r i t y . G u a r d e d O b j e c t a rozhraní j a v a . s e c u r i t y . G u a r d . Rozhraní Guard reprezentuje hlídání přístupu k nějakému objektu. K tomuto účelu slouží jediná metoda, kterou rozhraní udává - checkGuard (Ob j e c t ob ject) . Je čistě na vůli programátora, jakým způsobem rozhraní implementuje, jednou z možností je však využití třídy S e c u r i t y Manager a tím pádem řízení přístupu k nějakému objektu na základě dané bezpečnostní politiky. Metoda se chová obdobně jako checkPermission ve třídě SecurityManager - v případě, že je přístup povolen, metoda se pouze tiše vrátí, v případě, že přístup k objektu povolen není, je vyvolána výjimka SecurityException.[21] Pomocí třídy GuardedOb j e c t můžeme chránit přístup k jinému konkrétnímu objektu. Třída zastřešuje spojení instance objektu a implementace rozhraní Guard. Jakmile je vytvořena instance GuardedOb j e c t , je k jejímu objektu možno přistupovat pomocí její metody getOb j e c t (), která v případě povolení přístupu (na základě metody checkGuard třídy implementující Guard) vrací hlídaný objekt, v opačném případě vyvolá výjimku SecurityException.[22][2] 21 4 Možnosti rozšíření bezpečnostních politik o zamítavá pravidla Na způsoby rozšíření bezpečnostních politik v Javě můžeme nahlížet ze dvou různých úhlů pohledu. Jednak se jedná o možnosti samotné implementace funkcionality spojené s tímto rozšířením, a dále je také potřeba probrat, jakým způsobem bude moci uživatel pracovat s nově vzniklou politikou a jejími zamítavými pravidly. 4.1 Z pohledu uživatele Jedním z požadavků na tuto diplomovou práci je zpětná kompatibilita s původními bezpečnostními politikami z Javy. Z tohoto důvodu se v této podkapitole budu věnovat především úpravám standardního souboru s konfigurací bezpečnostních politik, nicméně všechna rozšíření jsou s mírnými úpravami aplikovatelná i na další možné způsoby uložení konfigurace bezpečnostní politiky. 4.1.1 Zamítavý prvek Standardní soubor s konfigurací bezpečnostní politiky používá pro rozhodování o přístupu pouze grant prvky určující, k jakým zdrojům je garantován přístup. Stěžejním rozšířením syntaxe tohoto souboru je zavedení nového zamítavého prvku, umožňujícího naopak zakázat přístup k nějakému citlivému zdroji. Tento prvek můžeme uvést klíčovým slovem deny1 . V praxi se jedná o stejný prvek jako grant prvek i s jeho atributy - může nás zajímat, odkud zdrojový kód pochází, kým je podepsán, kdo jej spouští a samozřejmě je mu přiřazena množina prvků permission (také se stejnými atributy jako při použití u grant prvku). Syntaxe deny prvku může být tedy stejná jako syntaxe grant prvku, atributy spojené s původem kódu a jeho spouštěním mají pro tento prvek stejný význam, pouze význam množiny prvků permission je přesně opačný, tedy definují, ke kterým citlivým zdrojům je zakázán přístup.[14] 4.1.2 Definice chování zamítavých pravidel Při zavedení deny prvků vzniká problém, který je potřeba vyřešit: Grant i deny prvky pracují nad stejnou množinou atributů a mohou mít tedy vzá- 1. deny znamená anglicky upřít 22 4. M O Ž N O S T I R O Z Š Í Ř E N Í B E Z P E Č N O S T N Í C H P O L I T I K O Z A M Í T A V Á P R A V I D L A jemně stejné působiště. Pokud tento případ nastane a grant a deny prvek budou obsahovat také nějaký stejný prvek permission (případně prvek permission z grant prvku bude podmnožinou nebo nadmnožinou prvku permission z deny prvku), dostáváme spor, kdy k jednomu citlivému zdroji máme přístup jak povolen, tak zakázán. K vyřešení tohoto konfliktu musí bezpečnostní politika explicitně definovat, zda mají vyšší váhu grant nebo deny pravidla. Ve standardní Javě se dá základní algoritmus řízení přístupu definovat následující větou: Přístup je garantován právě tehdy, když každá chráněná doména v aktuálním kontextu má garantovánu danou permission. [2] Standardní Java nepočítá s použitím zamítavých pravidel a v souvislosti s jejich použitím tato věta ztrácí platnost a bude nutné ji upravit (a to i v závislosti na vyšší váze grant nebo deny pravidel). Pomocí úpravy této věty mohu definovat chování přístupu k citlivému zdroji s použitím zamítavých pravidel. V případě, že vyšší váhu mají deny pravidla, definuji chování bezpečnostní politiky takto: Přístup je garantován právě tehdy, když každá chráněná doména v aktuálním kontextu má garantovánu danou permission a zároveň ji nemá zamítnutou. V případě vyšší váhy grant pravidel definuji chování takto: Přístup je garantován právě tehdy, když každá chráněná doména v aktuálním kontextu, která má zamítnutou danou permission, ji má zároveň i garantovánu. V dalším textu budu tyto dvě věty považovat za definice chování bezpečnostní politiky se zamítavými pravidly. Všechny bezpečnostní politiky pracující se standardní implementací bezpečnostní politiky v Javě používají definici s vyšší vahou deny pravidel. 4.1.3 Konflikty grant a deny prvků Konflikty grant a deny prvků vznikají v případě, kdy je přístup k citlivému zdroji zároveň povolen i zamítnut. Následující tabulka ukazuje výsledky rozhodování daných žádostí o přístup a také jaké problémy musíme řešit: 23 4. M O Ž N O S T I R O Z Š Í Ř E N Í B E Z P E Č N O S T N Í C H P O L I T I K O Z A M Í T A V Á P R A V I D L A deny obsahuje neobsahuje grant obsahuje Problém A povolit neobsahuje zakázat Problém B Pokud je obsažen pouze jeden z prvků, je rozhodování o povolení/zamítnutí přístupu triviální a pro oba přístupy stejné. Problémy A a B musí být rozhodnuty pomocí určené přednosti grant/deny pravidel, tedy použité definici chování bezpečnostní politiky, přičemž rozhodnutí problému A je taktéž triviální: • Přednost mají deny prvky - zamítni přístup. • Přednost mají grant prvky - povol přístup. Zajímavější je problém B, kdy aplikace žádá o přístup k citlivému zdroji, který není v dané bezpečnostní politice zmíněn. Vyřešíme jej podle definice následujícím způsobem: • Přednost mají deny prvky - přístup je povolen právě tehdy, když je daná permission garantována a zároveň není zamítnuta, což v tomto případě neplatí, z tohoto důvodu je přístup zamítnut. • Přednost mají grant prvky - přístup je povolen, když je každé zamítavé pravidlo zároveň i povoleno, což platí, protože dané permission se netýká žádné pravidlo, přístup je tedy povolen. V závislosti na způsobu definice chování bezpečnostní politiky mohu říci následující: Použití pravidla ze skupiny pravidel s vyšší vahou má vliv na výsledek rozhodování pouze pokud je v konfliktu s nějakým pravidlem ze skupiny pravidel s nižší vahou. Toto tvrzení lze použít i při řešení Problému B, u kterého vidíme, že pro bezpečnostní politiku používající vyšší váhu deny prvků je v iniciálním stavu každé pravidlo zakázáno - tedy do té chvíle, dokud jej negarantuje nějaký grant prvek, nemá význam jej opětovně zamítat (obdobně pro bezpečnostní politiku s vyšší vahou grant prvků, kdy máme v iniciálním stavu všechny přístupy povoleny). 4.1.4 Způsoby řešení konfliktů Konflikty mohou být řešeny buď stejně pro celou bezpečnostní politiku, a nebo různě pro jednotlivá pravidla. 24 4. M O Ž N O S T I R O Z Š Í Ř E N Í B E Z P E Č N O S T N Í C H P O L I T I K O Z A M Í T A V Á P R A V I D L A Snazší a přehlednější cestou je řešení všech konfliktů v celé bezpečnostní politice stejně. Pro předání informace, která pravidla mají přednost, můžeme použít dva různé způsoby: • Zavést nějaké klíčové slovo použité přímo v konfiguraci bezpečnostní politiky a definující, zda mají přednost grant nebo deny prvky. Výhodou je možnost spojení nastavení přednosti pro konkrétní bezpečnostní politiku přímo s její konfigurací. • Zavést systémovou proměnnou, jejíž hodnota může být nastavena při spuštění aplikace. Výhodou je možnost jednoduché změny přednosti pro každé volání aplikace. S ohledem na zpětnou kompatibilitu se standardní konfigurací bezpečnostní politiky je nutné, aby v případě nepoužití proměnné v souboru nebo nedefinování systémové proměnné byla její předdefinovaná hodnota nastavena na použití bezpečnostní politiky upřednostňující deny pravidla (jinak není zaručeno, že se stejný soubor s konfigurací bezpečnostní politiky bude chovat stejně ve standardní bezpečnostní politice v Javě a v bezpečnostní politice používající zamítavá pravidla). Konflikty mohou být také řešeny pro každý grant a deny prvek zvlášť. Toho lze dosáhnout například rozšířením konfigurace bezpečnostní politiky o možnost nastavit prioritu pro každé pravidlo. Tímto se však jednoznačně neřeší problém, jak se má bezpečnostní politika zachovat v případě, kdy budou mít oba prvky nastavenou stejnou prioritu. Opět by bylo zapotřebí definovat nějakou proměnnou, která určí chování prvků se stejnou prioritou pro celou konfiguraci stejně (tj. která by se chovala podobně jako výše popsaná varianta, týkala by se však pouze stejných priorit). Pomocí tohoto způsobu řešení konfliktů lze pracovat i se situacemi, které ve variantě jednoho typu řešení pro celý soubor nelze definovat. Například konflikt, kdy je jeden grant prvek v rozporu se dvěma různými deny prvky, může být řešen pro každý prvek jinak. Nicméně se domnívám, že tato situace je již příliš specifická a její použití značně ztěžuje definici běžné konfigurace bezpečnostní politiky, proto se zaměřím na způsob vypořádání se s konflikty v celé aplikaci stejně. 4.2 Z pohledu implementace Při rozboru problematiky rozšíření řízení přístupu o zamítavá pravidla je nutné zamyslet se nad tím, jakými možnými způsoby může být toto rozšíření provedeno na úrovni kódu. Je potřeba zavést nové struktury a pozměnit 25 4. M O Ž N O S T I R O Z Š Í Ř E N Í B E Z P E Č N O S T N Í C H P O L I T I K O Z A M Í T A V Á P R A V I D L A stávající algoritmy. V této podkapitole budou nastíněna možná řešení tohoto problému. 4.2.1 Reprezentace zamítavého pravidla Zamítavé pravidlo je v principu stejný bezpečnostní prvek jako pravidlo umožňující přístup k citlivému zdroji, pouze funkcionalita je přesně opačná. Nicméně parametry toho pravidla jsou stejné. Pro reprezentaci pravidel umožňujících přístup jsou v Javě použity třídy, které rozšiřují třídu P e r mission. S touto třídou by bylo vhodné pracovat i pro reprezentaci zamítavých pravidel. Nabízí se dvě různé jednoduché možnosti, jak této třídy využít: • Můžeme zavést rozhraní N e g a t i v e P e r m i s s i o n , které nedefinuje žádnou metodu. Dále pro každou třídu rozšiřující třídu P e r m i s s i o n vytvoříme třídu reprezentující zamítavé pravidlo, která bude původní třídu rozšiřovat a zároveň implementovat rozhraní N e g a t i v e Permission. Pomocí něj pak můžeme určit, že se jedná o negativní reprezentaci rozhodování o přístupu. • Pro reprezentaci zamítavých pravidel můžeme použít přímo třídy rozšiřující P e r m i s s i o n a používané pro povolení přístupu. Fakt, jestli se každý konkrétní objekt P e r m i s s i o n týká povolení či zamítnutí přístupu, pak budeme řešit v závislosti na struktuře, ve které bude uchován. Vhodnější pro použití mi připadá druhý přístup, kdy sice může při špatné implementaci hrozit možná záměna pravidla o povolení a zamítnutí přístupu, nicméně mi to připadá jako schůdnější varianta, než pro každé rozšíření třídy P e r m i s s i o n ( a t o i pro rozšíření nepocházející přímo z JDK, ale i od programátorů vlastních Permission) vytvářet jejich negativní variantu. Toto horší řešení navíc předpokládá, že každá nově vytvořená a použitá třída P e r m i s s i o n bude taktéž implementovat svou negativní variantu, což mi přijde zbytečné vynucovat. 4.2.2 Dvouprůchodová kontrola přístupu Ve standardní Javě je pouze jedna možnost ovlivnění přístupu - jeho povolení pomocí určené permission. Z tohoto důvodu mohou být obecně všechna tato povolení jednoduše uložena v nějaké struktuře, ve které nám stačí jeden průchod na zkontrolování, zda je v ní potřebná permission obsažena. 26 4. M O Ž N O S T I R O Z Š Í Ř E N Í B E Z P E Č N O S T N Í C H P O L I T I K O Z A M Í T A V Á P R A V I D L A Při zavedení zamítavých pravidel můžeme, vedle struktury zahrnující povolení o přístupu, zavést další strukturu obsahující pouze tato zamítavá pravidla. V základní podobě pak pro rozhodnutí o přístupu můžeme použít algoritmus, který projde obě struktury a na základě nalezených povolení/ zamítnutí rozhodne o umožnění přístupu k citlivému zdroji. Průchod obou struktur však nemusí být vždy nutný. Použitý algoritmus lze upravit na základě použité definice pro chování řízení přístupu se zamítavými pravidly. • Přednost mají deny prvky - v případě zamítnutí přístupu může stačit projít pouze jednu ze struktur. Můžeme použít jeden z následujících dvou algoritmů: a) Algoritmus nejprve projde strukturu obsahující zamítavá pravidla. Pokud nalezne pravidlo, které určuje zamítnutí daného přístupu k citlivé proměnné, nemá bezpečnostní politika žádný prostředek, jak tento přístup povolit (plyne z definice). Z tohoto důvodu může algoritmus přístup zamítnout bez ohledu na obsah struktury obsahující povolení k přístupu (a tedy bez nutnosti jejího průchodu). Pokud však zamítavé pravidlo nenalezne, je samozřejmě nutné projít i tuto strukturu a rozhodnutí o přístupu bude záležet už jen na ní. b) Algoritmus nejprve prochází grant pravidla a v případě nenalezení příslušného povolení je přístup zamítnut bez nutnosti zkoumání druhé struktury. • Přednost mají grant prvky - v případě povolení přístupu může stačit projít pouze jednu ze struktur. Algoritmus bude pracovat obdobně jako pro deny prvky a opět můžeme použít jeden z následujících al­ goritmů: a) Nejprve je prozkoumána struktura obsahující grant prvky a v případě nalezení povolení o přístupu je přístup povolen, nezávisle na obsahu struktury se zamítavými pravidly. V opačném případě je opět nutné pro určení přístupu projít také druhou struk­ turu. b) Algoritmus nejprve prochází deny pravidla a v případě nenalezení příslušného zamítnutí je přístup povolen bez nutnosti zkoumání druhé struktury. Průchod pouze jednou strukturou může vést ke snížení času pro rozhodnutí o povolení nebo zamítnutí přístupu. Problémem je však určení, kterou 27 4. M O Ž N O S T I R O Z Š Í Ř E N Í B E Z P E Č N O S T N Í C H P O L I T I K O Z A M Í T A V Á P R A V I D L A strukturu procházet nejdříve - může nastat situace, kdy je při správném určení nutné projít pouze jednu strukturu, naopak při špatném obě dvě. Tento problém bohužel nelze jednoznačně rozhodnout, můžeme však vytvořit různé heuristiky, na základě kterých může být rozhodování učiněno. Vytvořená heuristika může používat například statistiky o povolení/zamítnutí přístupu a na jejich základě se rozhodovat, kterou strukturu procházet dříve, může být také konfigurovatelná přímo bezpečnostní politikou atd. Je však nutné si uvědomit, že řešení heuristiky probíhá v nenulovém čase, a tudíž může být její použití kontraproduktivní. V praxi by měla být použita jen u bezpečnostních politik, kde se velikost obou struktur výrazně liší, v opačném případě může být použito striktní rozhodování, kdy vždy procházíme nejprve jednu určenou strukturu. 4.2.3 Použití jedné kolekce Jak bylo popsáno výše v kapitole o řízení přístupu, abstraktní třída P e r m i s s i o n C o l l e c t i o n má reprezentovat kolekci prvků P e r m i s s i o n a umožnit na ní snadné zavolání metody i m p l i e s . Tento princip by se dal obdobně aplikovat na nově vytvořenou kolekci. Jednalo by se o strukturu zpracovávající grant i deny prvky a transformující je vnitřně do nově vzniklých objektů fungujících podobně jako třída P e r m i s s i o n (musely by však navíc obsahovat parametr určující, zda se jedná o povolující nebo zamítající permission). Díky tvrzení z konce podkapitoly 4.2.3 Konflikty grant a deny prvků je zřejmé, že v závislosti na vyšší váze pravidel v použité bezpečnostní politice je nutné řešit pouze pravidla s nižší vahou a konflikty. A právě konflikty je nutné přetransformovat do nově vzniklých objektů tak, aby každý jednoznačně vyjadřoval, co povoluje/zamítá bez další nutnosti řešit tento konflikt. Pravidla s nižší vahou mohou být pouze jednoduše přepsána do této nové formy. Tyto objekty by pak byly uloženy v kolekci ve vzniklé struktuře. Struktura by měla definovat metodu i m p l i e s , pomocí které by bylo možné rozhodnout o povolení/zamítnutí přístupu k citlivému zdroji pomocí jednoho průchodu. Výhodou tohoto přístupu je nutnost pouze jednoho průchodu strukturou, nicméně její vytvoření a následná údržba bude pravděpodobně obnášet daleko náročnější režii a časovou náročnost než použití dvou struktur obsahujících odděleně grant permission a deny permission. 28 4. M O Ž N O S T I R O Z Š Í Ř E N Í B E Z P E Č N O S T N Í C H P O L I T I K O Z A M Í T A V Á P R A V I D L A 4.2.4 Negativní alternativa AllPermission Se zavedením zamítavých pravidel v bezpečnostní politice nastává otázka, jestli není nutné vytvořit negativní alternativu ke třídě A l l P e r m i s s i o n třídu, která naopak bude zakazovat všechen přístup. Ve standardní Javě je pomocí A l l P e r m i s s i o n garantován přístup ke všem citlivým zdrojům a naopak možnost zakázat všechen přístup je možné řešit triviálně pomocí nepřiřazení žádné permission. Vlastnost jednoduše povolit/zakázat všechny přístupy chceme zachovat i při použití zamítavých pravidel. Bezpečnostní politika s vyšší vahou zamítavých pravidel má stejné možnosti nastavení jako výše zmíněná politika ve standardní Javě, musíme tedy řešit především politiku s vyšší vahou grant pravidel. Mohlo by se zdát, že k tomu účelu může být vhodně použita negativní alternativa AI IP e r mi s s i on, efektivnější je však použít zamítavé pravidlo s permission A l l P e r m i s s i o n . Pomocí něj můžeme zakázat všechny přístupy i v politice, ve které mají grant pravidla přednost. V této politice můžeme povolit přístup ke všem zdrojům nepoužitím žádné permission. Negativní alternativa A l l P e r m i ss i o n by tedy nepřinášela žádnou novou vyjadřovací schopnost, a proto myslím, že je vhodné ji nezavádět. 29 5 Výhody a nevýhody použití zamítavých pravidel Jedním z hlavních důvodů pro zavedení zamítavých pravidel je možnost striktně zakázat přístup k nějakému citlivému zdroji. Toto rozšíření sebou však nese i jistá úskalí, která by měla být předem zhodnocena. Stejně tak je dobré si uvědomit, které vlastnosti bezpečnostních politik použitím zamítavých pravidel získáme. Pomocí vyhodnocení těchto výhod a nevýhod použití zamítavých pravidel získáme jasnější přehled o tom, zda použít v konkrétní bezpečnostní politice zamítavá pravidla nebo dokonce jestli je možnost bezpečnostních politik se zamítavými pravidly v Javě vůbec potřebná. 5.1 Porovnání vlastností Vlastnosti bezpečnostních politik, kterými má význam se zaobírat ve vztahu k rozšíření o zamítavá pravidla, jsem rozdělil do tří kategorií, z nichž každá kategorie bude probrána zvlášť: • snadnost zápisu a snadnost použití • časová náročnost inicializace a dotazu • vyjadřovací schopnost 5.1.1 Snadnost zápisu a snadnost použití Vlastnosti snadnost zápisu a snadnost použití se týkají čistě práce uživatele s bezpečnostní politikou a nemají žádný vliv na chod samotné aplikace. Tím pádem jsou oba pojmy spojeny pouze s konfigurací bezpečnostní politiky. Pojmy lze chápat následujícím způsobem: • snadnost zápisu - každé pravidlo o přístupu lze bezpečnostní politice jednoduše zadat • snadnost použití - při vytváření i čtení konfigurace bezpečnostní politiky je snadno patrné, jak se bude daná bezpečnostní politika chovat Snadnost zápisu v bezpečnostních politikách ve standardní Javě a při použití zamítavých pravidel se na první pohled prakticky neliší. Zamítavá pravidla definují nový prvek deny, jehož zápis je totožný se zápisem grant prvku, pouze funkce je opačná. Případné použití nového prvku určujícího, zda má vyšší váhu grant nebo deny pravidlo, zápis také nikterak 30 5. VÝHODY A NEVÝHODY POUŽITÍ ZAMÍTAVÝCH PRAVIDEL výrazně nezhorší. Toto se však týká přímo práce se souborem konfigurace bezpečnostní politiky pomocí textového editoru. Problém nastává při použití specializovaného nástroje Policy Tool1 , jenž je přizpůsobený pouze pro vytváření standardních bezpečnostních politik. Z tohoto důvodu je tento program v jeho současné podobě nemožné použít, nicméně se nabízí možnost vytvořit vlastní program pro ulehčení práce s bezpečnostní politikou se zamítavými pravidly, případně se pokusit rozšířit přímo nástroj Policy Tool. Snadnost použití při práci se zamítavými pravidly tvoří podstatně větší problém než snadnost zápisu. Hlavním důvodem jsou možné konflikty mezi grant a deny prvky. Zatímco při pohledu na standardní soubor s konfigurací bezpečnostní politiky stačí k rozhodnutí o povolení přístupu najít jedinou permission, která přístup povoluje, při použití zamítavých pravidel je nutné projít i zbytek souboru, zda není permission také zamítnuta. Toto de facto znamená, že pro určení kteréhokoliv rozhodnutí o přístupu je nutné zanalyzovat chování všech prvků v konfiguračním souboru. Daleko náročnější je také vytvoření nové konfigurace bezpečnostní politiky. N a rozdíl od standardních politik, kdy pouze povolujeme přístup (tedy nemusíme uvažovat i jiné důsledky každého grant prvku), se musíme zamýšlet zvlášť nad každým novým prvkem, jehož povolení/zamítnutí může ovlivnit chování prvku, který byl dříve již zamítnut/povolen. Náročnost vytváření i čtení konfiguračního souboru je silně závislá na množství použitých pravidel. V případě používání složitých bezpečnostních politik se zamítavými pravidly stojí za zvážení vyvinutí pomocného programu, jenž by přehledně zobrazoval vzniklé konflikty a také jejich výsledek v závislosti na definici chování bezpečnostní politiky (zda mají vyšší váhu grant nebo deny prvky). 5.1.2 Časová náročnost inicializace a dotazu Vlastnosti časová náročnost inicializace a dotazu jsou použity čistě ve vztahu k provádění aplikace a jejich reálné hodnoty jsou závislé na vlastní implementaci bezpečnostní politiky se zamítavými pravidly. Nejprve opět vysvětlím, co každý pojem reprezentuje: • časová náročnost inicializace - čas potřebný pro vytvoření struktur uchovávajících informace o bezpečnostní politice. • časová náročnost dotazu - čas nutný pro rozhodnutí o povolení nebo zamítnutí přístupu 1. pro více informací o nástroji Policy Tool viz http://download.java.net/jdk8/docs/technotes/guides/security/PolicyGuide.html 31 5. VÝHODY A NEVÝHODY POUŽITÍ ZAMÍTAVÝCH PRAVIDEL Inicializace datových struktur probíhá při první žádosti o přístup k citlivé proměnné nebo při každém volání metody re f resh () třídy P o l i c y . Při vhodné implementaci a použití dvouprůchodové kontroly přístupu by čas pro vytvoření struktur obsahujících informace potřebné k řízení přístupu se zamítavými pravidly měl být nejhůře dvojnásobný (jedná se tedy o lineární nárůst) než pro standardní bezpečnostní politiku. Každé pravidlo je uloženo právě do jedné odpovídající struktury přičemž každá z těchto struktur může být stejná jako ve standardních politikách. Při použití jedné kolekce pro uložení vyhodnocování přístupů je vytvářecí doba delší a čistě závislá na implementaci. Rychlost vyhodnocení dotazu je většinou důležitější než rychlost inicializace, protože je používána mnohokrát častěji. Standardní implementace v Javě má výhodu, že hned při prvním nálezu vhodné permission je povolen přístup, proto nemusí být zbytek struktury ani procházen. Při použití zamítavých pravidel a dvouprůchodové kontroly přístupu musí být kontrolována také druhá ze struktur, na druhou stranu toto rozšíření stále spadá do stejné časové třídy složitosti. V případě použití jedné kolekce může být vyhledávání taktéž ukončeno po nalezení první příslušné permis­ sion. Ve spojení s časovou náročností inicializace a dotazu si musíme také uvědomit jeden ze základních důvodů zavedení zamítavých pravidel - totiž zjednodušení v případě, kdy pro citlivý zdroj chceme povolit vše až na nějakou malou množinu permission. V tomto případě budou obě časové náročnosti daleko složitější pro standardní bezpečnostní politiku v Javě, která bude muset garantovat množství povolení k přístupu, zatímco vhodně zapsaná bezpečnostní politika se zamítavými pravidly bude potřebovat pouze pár zamítavých pravidel. Právě zde je velká síla zamítavých pravidel a jejich použití je v tomto případě velice výhodné. 5.1.3 Vyjadřovací schopnost V dobře vytvořené bezpečnostní politice by pomocí její konfigurace měly jít nastavit všechny možnosti k povolení přístupu k citlivému zdroji. Toto tvrzení splňuje i standardní bezpečnostní politika v Javě - umožňuje říci, k čemu všemu by měl být přístup povolen. Problém nastává, když se na možnosti bezpečnostní politiky podíváme z druhé strany - ke každému citlivému zdroji by měly jít zakázat všechny různé možnosti přístupu. Toto je problém, se kterým si standardní bezpečnostní politika z Javy neumí poradit. Povolení i zákazy v tomto případě pracují nad stejnou množinou a mohlo by se tedy zdát, že pro vyřešení problému, kdy chceme povolit vše 32 5. VÝHODY A NEVÝHODY POUŽITÍ ZAMÍTAVÝCH PRAVIDEL až na jednu konkrétni permission, stačí použít doplněk množiny k zákazu, tedy vyjmenovat přístupy, které jsou povoleny. Toto tvrzení je pravdivé, řešitelné je však pouze pro konečné množiny (navíc v případě velké množiny značně náročné). V případě, kdy je množina možných přístupů k citlivému zdroji nekonečná, nemá standardní bezpečnostní politika v Javě žádný prostředek, jak zamezit pouze jednomu přístupu (nebo množině přístupů) k citlivému zdroji. 5.2 Polemika s odbornou literaturou Standardní Java nepočítá s použitím zamítavých pravidel, proto nejsou v literatuře nijak zvlášť probírány. Zajímavá je však podkapitola 5.1.5 Positive versus Negative Permissions z knihy Inside Java 2 Platform Security, Second Edition - Achitecture, API Design, and implementation, již napsali L i Gong, Gary Ellison a Mary Dageförde. Podkapitola pojednává o důvodech nepoužití záporných permission v bezpečnostních politikách v Javě, což je prakticky tentýž problém jako používání zamítavých pravidel. Podkapitola popisuje výhody jednoduchého zápisu a také rychlosti provádění při použití pouze pozitivních permission. Jak ale popisuji výše, i s použitím zamítavých pravidel (tj. prakticky negativních permission) nemusí být žádná z těchto vlastností nijak výrazně ovlivněna. Dovolím si ale nesouhlasit s pasáží, ve které je popsáno, že použití negativních řešení přístupu není potřeba, protože jejich absence s sebou nese pouze ztrátu pohodlnosti, ne však funkcionality. Je zmíněno, že každou negativní permission lze zapsat pomocí pozitivních permission jejího doplňku. Toto tvrzení je však neuskutečnitelné v nekonečné množině (kdy je doplněk nekonečný). Absence zákazů přístupu sebou tedy nese i ztrátu funkcionality, a proto se nejedná pouze o problém pohodlnosti.[2] 5.3 Celkové zhodnocení výhod a nevýhod Některé výhody a nevýhody bezpečnostních politik se zamítavými pravidly byly zmíněny v podkapitolách výše, některé jsou důsledkem výše zmíněných vlastností. V této podkapitole se budu pomocí nabytých poznatků věnovat nejprve výpisu konkrétních výhod a nevýhod a dále také výhodám a nevýhodám závislých na požadované bezpečnostní politice. 33 5. VÝHODY A NEVÝHODY POUŽITÍ ZAMÍTAVÝCH PRAVIDEL 5.3.1 Výhody Zákaz permission v nekonečné množině2 Díky použití zamítavých pravidel získává bezpečnostní politika oproti standardní Javě novou funkcionalitu - zakázat některé permission i na nekonečné množině možných permission. Standardní Java umí zakazovat pouze pomocí garantování všech permission z doplňku permission, které chceme zakázat. Tento doplněk může být v nekonečné množině také nekonečný a tedy neřešitelný. Dá se však elegantně vyřešit pomocí zamítavých pravidel. Možný způsob zamezení přístupu jednomu uživateli V každé aplikaci se může stát, že se určitý uživatel stane na nějakou dobu nežádaným (například z důvodu častého porušování pravidel atd.). Pomocí zamítavých pravidel můžeme na úrovni konfigurace bezpečnostní politiky řešit zákaz všech (nebo jen některých) přístupů k citlivým zdrojům pro daného uživatele. 5.3.2 Nevýhody Spatné použití starších konfigurací Při použití standardní konfigurace bezpečnostní politiky je potřeba dbát na to, aby byla spouštěna s předností pro zamítavá pravidla. V případě, kdy by byla spuštěna s bezpečnostní politikou dávající vyšší váhu grant prvkům, by byly všechny přístupy povolené, což by bylo pravděpodobně nežádoucí. Nutnost řešit konflikty Při použití zamítavých pravidel se setkáváme s nutností řešit konflikty mezi současným povolením a zamítnutím přístupu. Aplikace konflikty řeší podle předem určené vyšší váhy grant nebo deny pravidel. Nad konflikty však musí přemýšlet také uživatel při zápisu konfigurace bezpečnostní politiky, kdy pro každý grant i deny prvek musí být vzaty v potaz všechny již přidané prvky, které jsou s tímto novým v konfliktu. Vytvoření zamýšlené bezpečnostní politiky může být tím pádem podstatně náročnější než ve standardní Javě. 2. Použitím pojmu nekonečná množina v tomto případě myslím i konečnou množinu s předem neznámou množinou oprávnění (tedy potencionálně až nekonečnou). 34 5. VÝHODY A NEVÝHODY POUŽITÍ ZAMÍTAVÝCH PRAVIDEL Nemožnost použití nástroje Policy Tool Jak již bylo zmíněno výše, Policy Tool je grafická aplikace usnadňující vytváření souboru s konfigurací bezpečnostní politiky. Aplikace samozřejmě nepočítá s možností použití zamítavých pravidel a je tedy pro bezpečnostní politiky se zamítavými pravidly nepoužitelná. Soubor s konfigurací bezpečnostní politiky však může být jednoduše vytvářen i pomocí textového editoru, proto absence Policy Toolu není pravděpodobně nikterak stěžejní. 5.3.3 Výhody a nevýhody závislé na bezpečnostní politice Následující vlastnosti mohou být výhodou i nevýhodou v závislosti na potřebné bezpečnostní politice. Přehlednost V případech, kdy chceme zamítat nějaké menší podmnožiny permission, je přehlednost při použití zamítavých pravidel lepší než ve standardní Javě. Čím více však přibývá konfliktů, tím více se přehlednost zhoršuje. Rychlost Rychlost rozhodnutí o povolení nebo zamítnutí přístupu je závislá na mnoha faktorech. Obecně však platí, že čím větší jsou možné množiny permission, ve kterých chceme nějakou podstatně menší podmnožinu permission zamítnout, tím je výhodnější použít přístup se zamítavými pravidly. 5.4 Vyhodnocení výhod a nevýhod Zavedení zamítavých pravidel do bezpečnostních politik s sebou nese především vyšší náročnost použití pro uživatele - je třeba pečlivě dbát na to, zda se výsledná bezpečnostní politika opravdu chová tak, jak bylo původně zamýšleno. Jejich správné použití však také může uživateli ušetřit čas a námahu při vytváření konfigurace bezpečnostní politiky. Důležitým faktorem je také nová funkcionalita, kterou zamítavá pravidla oproti standardní Javě umožňují - možnost zakázat přístup k citlivému zdroji i v nekonečné množině permission. Po zhodnocení výhod a nevýhod spojených s použitím zamítavých pravidel myslím, že jejich zavedení má smysl a může být uživateli velice pro­ spěšné. 35 6 Návrh řešení Částečný návrh možných rozšíření bezpečnostních politik o zamítavá pravidla je již rozebrán v kapitole 4 Možnosti rozšíření bezpečnostních politik o zamítavá pravidla. V této a následující kapitole se budu věnovat již návrhu a implementaci jednoho konkrétního způsobu rozšíření (jehož jednotlivé části jsou popsány ve výše zmíněné kapitole). Návrh, a stejně tak i následná implementace, se bude týkat rozšíření současného způsobu vykonávání bezpečnostní politiky v Javě o zamítavá pravidla, nikoliv návrhu a implementace celé bezpečnostní politiky. N a základě návrhu a implementace bude snadno ukazatelná výhoda použití zamítavých pravidel v bezpečnostních politikách v Javě. 6.1 Návrh tříd SecurityManager, AccessController Jedním z cílů této diplomové práce je implementovat Security Manager a Access Controller pro vybraný návrh. Význam těchto tříd byl zmíněn v kapitole 3 Řízení přístupu v Javě, nicméně je důležité si krátce shrnout některé jejich vlastnosti: • třída SecurityManager používá pro rozhodování o přístupu třídu A c c e s s C o n t r o l l e r • třída A c c e s s C o n t r o l l e r je finální a není tedy možné ji rozšířit • třída A c c e s s C o n t r o l l e r se pro zjištění, zda bezpečnostní politika povoluje daný přístup k citlivému zdroji, ptá přímo bezpečnostní poli­ tiky Jedním z možných způsobů implementace těchto dvou tříd je možnost rozšíření třídy SecurityManager tak, aby pro své rozhodování nepoužívala finální třídu A c c e s s C o n t r o l l e r , ale Access Controller, který implementujeme sami. Nastává však otázka, co jiného by umožňovala naše implementace než povolení o přístupu na základě dané bezpečnostní politiky (tak jako to dělá původní Access Controller). A c c e s s C o n t r o l l e r je sice třídou, která rozhoduje o povolení nebo zamítnutí přístupu, není však třídou, která by měla vliv na chování povolujících a zamítavých pravidel - to je získáno na základě vyhodnocení používané bezpečnostní politiky. Pro svou práci navíc používá i nativní metody, které značně zefektivňují jeho rychlost. Z tohoto důvodu je pro naši implementaci možné (a dokonce 36 6. NÁVRH ŘEŠENÍ vhodné) použít standardní Access Controller. Musíme však zajistit, že finální A c c e s s C o n t r o l l e r bude přistupovat ke správné bezpečnostní politice - je tedy nutné tuto bezpečnostní politiku nastavit ještě dříve, než bude A c c e s s C o n t r o l l e r zavolán pro rozhodnutí o povolení přístupu. Toho však můžeme dosáhnout vytvořením vlastní třídy rozšiřující S e c u r i t y Manager, jenž bude při své inicializaci nastavovat v platnost námi určenou třídu rozšiřující abstraktní třídu P o l i c y . Tím zaručíme, že třída A c c e s s C o n t r o l l e r bude pracovat se správnou bezpečnostní politikou. 6.2 Návrh třídy s bezpečnostní politikou Bezpečnostní politika je reprezentována abstraktní třídou P o l i c y . Při jejím návrhu je nutné stanovit koncepty, na základě kterých bude bezpečnostní politika pracovat se zamítavými pravidly - tedy implementace bude pracovat na základě těchto pravidel, popsaných v kapitole 4 Možnosti rozšíření bezpečnostních politik o zamítavá pravidla: • Reprezentace zamítavého pravidla bude tvořena pomocí stejných objektů Permission, jako je reprezentováno povolující pravidlo. • Bude použita dvouprůchodová kontrola přístupu. V rámci optimalizace použijeme striktní rozhodování, kdy při přednosti zamítavých pravidel bude nejprve prozkoumána struktura obsahující povolující pravidla, a stejně tak při přednosti povolujících pravidel budou nejprve kontrolovány zamítavá pravidla. Možnosti a důvody použití těchto dvou pravidel jsou popsány ve výše zmíněné kapitole a nepokládám za důležité je zde více rozebírat. 6.3 Návrh souboru s konfigurací bezpečnostní politiky Prvním a důležitým předpokladem pro návrh souboru s konfigurací bezpečnostní politiky je jeho zpětná kompatibilita se standardními soubory s konfigurací bezpečnostní politiky v Javě. Tudíž musí použití všech prvků (i jejich podprvků) obsažených v tomto standardním souboru zůstat platné i pro náš návrh. Jedná se o prvky grant, keystore, keystorePasswordURL. Nově zavedené prvky jsou spojeny s použitím negativních pravidel. Jednak je nutno nějak reprezentovat samotné zamítavé pravidlo, a také je nutné rozhodnout, zda bude priorita přednosti povolujících/zamítavých pravidel určena v souboru nebo v systémové proměnné (viz 4.1.4 Způsoby řešení konfliktů). 37 6. NÁVRH ŘEŠENÍ • Zamítavá pravidla budou v souboru s bezpečnostní politikou použita naprosto stejně jako povolující pravidla s tím rozdílem, že místo klíčového slova "grant", budou uvedena klíčovým slovem "deny". Vlastnosti všech podprvků v tomto pravidle budou stejné jako vlastnosti u grant prvku, pouze budou značit zamítnutí, a stejně tak jejich logika bude stejná (například v případě použití dvou hodnot v podprvku signedBy bude zamítavé pravidlo platit pouze v případě, kdy je použito obou zmíněných podpisů). • Pro určení priority bude použit nový nepovinný prvek označený klíčovým slovem "priority", za kterým bude následovat vždy jedno slovo z dvojice "grant", "deny". V případě, že hodnota v prvku priority nebude vůbec nastavena, bude z důvodu zpětné kompatibility použita hodnota "deny". V případě, že bude priorita v souboru použita vícekrát, je v potaz brán pouze první výskyt. Přednost při řešení konfliktů bude tedy určena přímo v souboru s konfigurací bezpečnostní politiky pro celou politiku stejně, což mi připadá jako daleko pochopitelnější varianta, a tudíž vhodnější pro mou implementaci. Stejně tak v případě použití více bezpečnostních politik je priorita načtena pouze z prvního souboru s bezpečnostní politikou. Tímto způsobem je zajištěna stejná priorita pro celou aplikaci, tudíž je její používání přehlednější. 38 7 Implementace Implementace, která je součástí této práce, získala název Prograde, což je zkratka tvořená písmeny z anglického sousloví Policy Rules Of GRanting And DEnying1 . Jedná se o knihovnu dostupnou jako Maven artefakt. Zdrojové kódy jsou dostupné pod licencí G N U LGPL. Jelikož se implementace týká rozšíření již existující funkcionality v Javě, je součástí této diplomové práce také aplikace, pomocí níž je možné si funkcionalitu této implementace snadno vyzkoušet. Návod na její spuštění, nastavení a použití je sepsán v příloze (viz A Vyzkoušení funkčnosti knihovny Prograde). 7.1 Použité nástroje 7.1.1 Apache Maven Jedná se o nástroj vyvíjený společností The Apache Software Foundation sloužící pro snadné sestavení Java projektu a také jeho celkové řízení. Maven projekt musí obsahovat soubor porn. xml, ve kterém jsou definovány závislosti na různých artefaktech. Artefakty se rozumí používané externí knihovny. Ty jsou načteny z lokálního Maven repozitáře, což je složka, ve které jsou artefakty uloženy. Do lokálního repozitáře mohou být přidány například pomocí internetové sítě nebo jako výsledek sestavení nějakého Maven projektu (většinou lokálně, je však možné je do repozitáře i zkopírovat). Pro definici úložišť, ve kterých mají být artefakty hledány a následně staženy, v případě, že nejsou dosud dostupné v lokálním repozitáři, je použit soubor s e t t i n g s . xml. Každý artefakt má definováno své g r o u p l d (identifikátor skupiny projektů) a a r t i c a f t l d (identifikátor konkrétního projektuzdané groupld). Kombinace g r o u p l d a a r t i c a f t l d tvoří uniká tni dvojici jednoznačně určující konkrétní projekt. Každý artefakt má také nastavenou verzi, pomocí níž je možné určit konkrétní knihovnu v daném projektu. Nástroj je volán příkazem mvn, za nímž následují jména jednotlivých gólů (což jsou jednotlivé části cyklu sestavování projektu). Nástroji mohou být také předané různé parametry. [25] Prograde je Maven projekt s g r o u p l d n e t . s o u r c e f orge . p r o - g r a d e a a r t i c a f t l d pro-grade a v době dokončení diplomové práce byl ve verzi 1.0. 1. česky přeložitelné jako Politika pravidel povolování a zamítání 39 7. I M P L E M E N T A C E 7.1.2 Git Git je nástroj sloužící pro správu verzí, tedy systém umožňující uchovávat změny v souboru v čase. Git je distribuovaný systém, což na rozdíl od častějších centralizovaných systémů pro správu verzí (například Subversion) znamená, že každý uživatel má na svém disku nahrán celý repozitář. Tato vlastnost umožňuje pracovat se systémem s různými lidmi na různých úrovních (tj. s každým s jinou verzí). Zajímavou vlastností je také způsob, jakým Git pracuje s jednotlivými verzemi. Ve většině verzovacích systémů je verze uložena jako rozdíl oproti verzi předešlé, zatímco v Gitu je každá verze chápána jako snapshot2 všech souborů (v rámci ušetření místa jsou nezměněné soubory nahrazeny pouze odkazy na tento soubor v předešlé verzi). Lokální kopii repozitáře je možné získat pomocí zavolání příkazu[4]: git clone adresa_k_repozitáři Pro uložení projektů v internetu je možné mimo jiné použít GitHub (www.github.com), což je komerční úložiště Git projektů. Hostování veřejných projektů je zdarma, soukromé projekty jsou již placené. Prograde je od své verze 1.0 umístěn na GitHubu a tudíž je dostupný pod adresou https://github.com/olukas/pro-grade. Získání lokální kopie repozitáře je zaregistrovaným uživatelům umožněno pomocí příkazu: git clone https://github.com/olukas/pro-grade.git 7.2 Balíky a třídy Implementace se skládá ze čtyř balíků, z nichž každý bude probrán zvlášť, a taktéž budou zmíněny jejich zajímavé třídy a některé jejich metody. 7.2.1 Balík net.sourceforge.prograde.sm Tento balík obsahuje pouze třídy přímo spojené s prací vlastní implementace Security Manageru. V současné době balík obsahuje pouze třídu P r o gradeSecurityManager, která rozšiřuje standardní SecurityManager, od kterého se liší pouze v konstruktoru, ve kterém nastavuje pomocí statické metody s e t P o l i c y ze třídy P o l i c y v platnost Prograde bezpečnostní politiku se zamítavými pravidly. Toto nastavení probíhá v privilegovaném stavu. Pokud by někdy v budoucnu bylo nutné implementovat vlastní Access Controller, měl by být součástí tohoto balíku. 2. stav souborů v konkrétním čase 40 7. I M P L E M E N T A C E 7.2.2 Balík net.sourceforge.prograde.policyparser Balík sdružuje třídy spojené se získáváním informací ze souboru s konfigurací bezpečnostní politiky. Základem je třída P ar ser, jenž ve své jediné veřejné metodě p a r s e ( F i l e f i l e ) postupně prochází soubor s konfigurací bezpečnostní politiky, jenž je jí předán jako parametr. Pro průchod je použita třída java . i o . StreamTokenizer. Získané informace jsou uloženy ve třídě P a r s e d P o l i c y , která obsahuje objekty tříd, v nichž už jsou obsaženy konkrétní informace získané ze souboru. Informace jsou ve výsledku uloženy v objektech typu St r i n g , případně jako boolean hodnoty. Třídy slouží pouze pro načtení informací a není v nich prováděna kontrola vstupních dat (například zda daný soubor s úložištěm klíčů, keystore, opravdu existuje). Třída pracuje pouze se souborem s konfigurací bezpečnostní politiky, jaký je popsán v návrhu (tj. stejným jako ve standardní Javě rozšířeným o deny prvky a prvek priority), nicméně je možné přidat do balíku další třídy, které mohou číst bezpečnostní politiku i z jiných souborů než ze standardního souboru s bezpečnostní politikou. 7.2.3 Balík net.sourceforge.prograde.policy Nejdůležitější funkcionalitou knihovny Prograde je schopnost rozhodovat o přístupu k citlivým zdrojům aplikace na základě povolujících nebo zamítavých pravidel. Veškerá tato funkcionalita je implementována v balíku n e t . s o u r c e f orge . prograde . p o l i c y , který se tak stává stěžejním balíkem celého rozšíření. Z tohoto důvodu bude tento balík probrán detailněji než zbylé tři balíky. Balík v současné době obsahuje tři třídy - třídy P r o g r a d e P r i n c i p a l a P r o g r a d e P o l i c y E n t r y představím nejdříve, jelikož obě slouží pro podporu hlavní třídy P r o g r a d e P o l i c y F i l e . ProgradePrincipal Třída P r o g r a d e P r i n c i p a l pouze reprezentuje vlastnosti prvku principál, získaného při čtení souboru s konfigurací bezpečnostní politiky včetně zástupného symbolu "*", který reprezentuje výraz "jakýkoliv". Symbol "*" může být použit u jména třídy P r i n c i p a l nebo u jména konkrétní instance třídy P r i n c i p a l . Tato informace je uchována ve třídě ProgradeP r i n c i p a l a slouží pro rozhodování třídy P r o g r a d e P o l i c y E n t r y , zda kontrolovat tyto vlastnosti třídy P r i n c i p a l nebo pouze zkontrolovat, že existují v jakékoliv podobě. 41 7. I M P L E M E N T A C E ProgradePolicyEntry Objekt třídy P r o g r a d e P o l i c y E n t r y reprezentuje jeden konkrétní grant/ deny prvek ze souboru s konfigurací bezpečnostní politiky. Informace obsažené v podprvcích codebase a signedBy uchovává v objektu třídy CodeSource, informace z podprvků principal v seznamu objektů ProgradeP r i n c i p a l . Jednotlivé permission jsou uchovány v objektu třídy P e r missions. Při vytváření instance třídy P r o g r a d e P o l i c y E n t r y je nutné uvést, zda se jedná o grant nebo deny prvek, nicméně tato informace je použita pouze při debugování3 bezpečnosti aplikace. Třída obsahuje metodu s e t N e v e r l m p l i e s (boolean n), pomocí které je možno nastavit, že daná P r o g r a d e P o l i c y E n t r y nikdy neimplikuje žádnou Permission. Tento stav může nastat například v případě, kdy grant/deny prvek definuje podprvek signedBy, ale soubor s definicí bezpečnostní politiky neobsahuje žádný prvek keystore. Nejdůležitější metodou je metoda i m p l i e s (ProtectionDomain p d , P e rmi s s i o n p e r m i s s i o n ) , která určuje, zda daný grant/deny prvek implikuje zadanou Permission. Rozhodování probíhá ve čtyřech krocích, kdy je pro přechod do každého dalšího kroku nutné, aby byl splněn aktuální krok: 1. Je zkontrolováno, zda není nastavena hodnota určující, že daný prvek nikdy neimplikuje žádnou Permission. 2. V případě, kdy je v objektu třídy P r o g r a d e P o l i c y E n t r y definován objekt třídy CodeSource, je zkontrolováno, zda tento CodeSource implikuje CodeSource aktivní ProtectionDomain, tj. chráněné domény, která žádá o přístup k citlivému zdroji. Tato kontrola obnáší jak porovnání URL obou CodeSource, tak i porovnání jejich certifikátů. 3. Pokud seznam s objekty P r o g r a d e P r i n c i p a l není prázdný, je zkontrolováno, zda aktivní chráněná doména obsahuje všechny potřebné instance třídy P r i n c i p a l . Je zde samozřejmě přihlíženo k použití zástupného symbolu "*"v souboru s definicí bezpečnostní politiky. 4. Je zavolána metoda i m p l i e s instance třídy Permissions, pomocí které se definitivně určí, zda objekt P r o g r a d e P o l i c y E n t r y implikuje danou Permission. Kroky 1 až 3 slouží pro určení, zda se tento objekt třídy P r o g r a d e P o l i c y E n t r y vůbec týká rozhodování o dané P e r m i s s i o n (tj. jestli jsou splněny 3. česky - odladění 42 7. I M P L E M E N T A C E požadavky z podprvků codebase, principál a signedBy tohoto grant/deny prvku) a v kladném případě je pak samotná implikace dané P e r m i s s i o n rozhodnuta na základě výsledku 4. kroku. ProgradePolicyFile P r o g r a d e P o l i c y F i l e je třídou, která rozšiřuje třídu P o l i c y . Toto rozšíření obnáší především přepsání dvou základních metod - r e f r e s h () a i m p l i e s ( P r o t e c t i o n D o m a i n p r o t e c t i o n D o m a i n , P e r m i s s i o n p e r m i s s i o n ) . Metoda r e f r e s h je použita pro načtení souborů s konfiguracemi bezpečnostních politik. Jedná se o načtení souboru definovaného hodnotou systémové proměnné j a v a . s e c u r i t y . p o l i c y . V případě, kdy je hodnota přiřazena pouze s jedním "=", jsou načteny také bezpečnostní politiky definované přímo Javou v souboru $ { java . home} / l i b / s e c u r i t y / j a v a . s e c u r i t y . Metoda se nejdříve snaží načíst soubor předaný systémovou proměnnou, a teprve poté soubory definované Javou - to je důležité při určení, ze kterého souboru je načtena hodnota prvku priority. V případě, kdy není třídou Par ser úspěšně načten žádný ze souborů definovaných Javou, ani soubor předaný přes systémovou proměnnou, je stejně jako ve standardní implementaci načtena statická bezpečnostní politika. Ta je shodná se standardním obsahem souboru $ { java . home} / l i b / s e c u r i t y / j a v a . p o l i c y ve standardní Javě. Pokud je přiřazení systémové proměnné provedeno pomocí "==", je načten pouze soubor definovaný v oné systémové proměnné a ani v případě neúspěchu není načtena statická bezpečnostní politika. Práce metody r e f r e s h spočívá v uložení načteného souboru s bezpečnostní politikou do objektů třídy P r o g r a d e P o l i c y E n t r y . Tyto objekty jsou uloženy ve dvou seznamech na základě vlastnosti, zda se jedná o povolující nebo zamítající prvek. Informace o použitém úložišti klíčů nemusí být nikde uchovávána, protože je použita pouze při načtení tohoto souboru. Informace o nastavené prioritě je uložena jako boolean hodnota přímo ve třídě P r o g r a d e P o l i c y F i l e . Metoda i m p l i e s ve třídě P r o g r a d e P o l i c y F i l e pracuje na základě definované priority. V případě, kdy je použita větší priorita zamítavých pravidel, tak je nejprve kontrolováno, zda není daná P e r m i s s i o n zamítnuta (pokud je zamítnuta, metoda i m p l i e s končí s návratovou hodnotou f a l š e ) , pokud P e r m i s s i o n zamítnuta není, je hledáno, zda je povolena. V kladném případě i m p l i e s končí s návratovou hodnotou true, v opačném případě s f a l š e . Obdobně probíhá vyhodnocení metody i m - 43 7. I M P L E M E N T A C E p l i e s pro případ s vyšší vahou povolujících pravidel. Samotná kontrola, zda je povolující pravidlo bezpečnostní politikou povoleno a zamítavé pravidlo zamítáno, probíhá pomocí průchodu povolovacího a zamítavého seznam objektů P r o g r a d e P o l i c y E n t r y . N a každém tomto objektu je volána jeho metoda i m p l i e s až do chvíle, kdy je nalezen objekt P r o g r a d e P o l i c y E n t r y , který danou P e r m i s s i o n implikuje, nebo do chvíle, kdy je zkontrolován celý seznam. Mimo výše zmíněných vlastností pracuje třída P r o g r a d e P o l i c y F i l e se dvěma proměnnými. Jedná se o hodnotu systémové proměnné j ava . p o l i c y . debug, pomocí které je mimo jiné určeno, zda má bezpečnostní politika vypisovat rozšířené informace ohledně vykonávání bezpečnostní politiky. Další je proměnná p o l i c y . expandProperties definovaná v souboru $ { java . horne} / l i b / s e c u r i t y / java . s e c u r i t y a určující, zda má daná bezpečnostní politika povolit expanzi systémových proměnných nebo nikoliv. 7.2.4 Balík net.sourceťorge.prograde.debug Balík slouží pro zapisování informací spojených s prací knihovny Prograde. V současné implementaci obsahuje balík jen třídu P r o g r a d e P o l i c y D e bugger sloužící k vypisování informací spojených s použitím systémové proměnné java . s e c u r i t y . debug s hodnotami p o l i c y nebo a l l . Třída obsahuje jedinou veřejnou statickou metodu l o g ( S t r i n g l o g ) , která umístí předaný řetězec za spojení " P o l i c y : " a výsledek zapíše na standardní výstup. Pokud bude v budoucnu nutné implementovat nějaké další třídy spojené se zapisováním informací produkovaných knihovnou Prograde, měly by být součástí tohoto balíku. 7.3 Nedostatky implementace Moje implementace má několik nedostatků, u kterých považuji za důležité, aby zde byly zmíněny. Jedná se o následující: Cesta v CodeSource Třída CodeSource mimo jiné používá ve své metodě i m p l i e s porovnání URL z obou porovnávaných objektů CodeSource, přičemž aktivní CodeSource předaný třídě P r o g r a d e P o l i c y F i l e třídou A c c e s s C o n t r o l l e r (přesněji řečeno třídou ProtectionDomain, ale na základě původního 44 7. I M P L E M E N T A C E volání metody checkPermission ze třídy A c c e s s C o n t r o l l e r ) kóduje určité symboly ve svém U R L do tvaru %xx případně %xx%xx. Java neposkytuje žádnou třídu nebo metodu umožňující snadno provést toto kódování a ani se mi nepovedlo dohledat přesnou definici, jak ono kódování probíhá. Moje implementace tedy kóduje pouze nejčastěji používané znaky. Následkem toho mohou být v názvu složek použitých v absolutní cestě uložené v CodeSource pouze znaky: a-z, A - Z , 0-9, české symboly á, č, ď, é, ě, í, ň, ó, ř, š, ť, ú, ů, ý, ž a symboly #, %, ", =, §, <, >, !, @, $, &, *, (/ )/ -/ +/ ' a čárka a mezera. Toto kódování probíhá v p r o t e c t e d metodě e n c o d e S p e c i a l C h a r a c t e r s třídy P r o g r a d e P o l i c y F i l e a je tedy možné jej v potomcích změnit. Tvar vlastních Permission V případě použití třídy P e r m i s s i o n , která nepochází přímo z Javy, je nutné, aby tato třída poskytovala aspoň jeden ze 3 konstruktorů: a. bezparametrický konstruktor b. konstruktor s jedním parametrem typu St r i n g , určující jméno dané P e r m i s s i o n c. konstruktor se dvěma parametry typu St r i n g , kdy první určuje jméno dané P e r m i s s i o n a druhý seznam akcí Pokud vlastní Permi s s i o n nesplňuje tuto podmínku, není možné ji úspěšně vytvořit, a tudíž povolit nebo zamítnout přístup k ní nebo s ní jakkoliv dále pracovat. Obecná expanze4 Standardní Java umožňuje použít v souboru s konfigurací bezpečnostní politiky také obecnou expanzi. Obecná expanze je definována ve tvaru $ { { jméno} } a na základě předem definovaných pravidel v bezpečnostní politice v Javě překládá tento řetězec na daný tvar. Tato vlastnost nemá obecně žádný vliv na rozšíření bezpečnostní politiky o zamítavá pravidla a její funkce by byla stejná jako ve standardní Javě. Její implementace by obnášela větší úsilí, které není nikterak spojeno s cílem této implementace a z toho důvodu není tato funkce implementována. 4. anglicky General Expansion 45 7. I M P L E M E N T A C E 7.4 Řízení bezpečnosti pomocí třídy ProgradeSecurityManager Nastavení bezpečnostní politiky používající zamítavá pravidla lze uskutečnit pomocí nastavení třídy ProgradeSecurityManager jako Security Manager celé aplikace. Tohoto lze dosáhnout stejnou cestou jako při nastavení standardního Security Manageru. To může být učiněno skrze systémovou proměnnou java . s e c u r i t y .manager nastavenou při volání aplikace nebo skrze metodu setSecurityManager třídy System. V případě, kdy chceme nastavit ProgradeSecurityManager do aplikace, která již nějaký SecurityManager používá, je nutné povolit některé permission potřebné pro inicializaci třídy ProgradeSecurityManager. Pro bližší informace je možno použít při startu aplikace systémovou proměnnou java . s e c u r i t y . debug (blíže viz [26]). 7.5 Testovaní aplikace Součástí ověření správné funkčnosti implementace je sada testů. Testování knihovny Prograde je provedeno pomocí tří různých typů testů. Jednotkové testy Část implementace je pokryta jednotkovými testy. Jedná se o testy tříd P r o g r a d e P o l i c y E n t r y a především Parser. U zbylých tříd nemá použití jednotkových testů velký význam a jejich funkcionalitu testuji až v test- suite5 (viz níže). Důležitý je především test metody parse ze třídy Parser, který zaručuje, že správně vytvořený soubor s konfigurací bezpečnostní politiky bude správně načten pro její následné použití. Testsuite Jedná se o projekt s automatizovanou sadou testů, jejichž úspěšný průchod je nutným předpokladem pro správné chování knihovny Prograde. Tento projekt nese název progradeTests a je dostupný z githubu pomocí příkazu: git clone https://github.com/olukas/progradeTests.git Samotné spuštění testů je možné příkazem (je samozřejmě nutné, aby byl v repozitáři již také obsažen artefakt pro-grade): mvn clean test -Dmaven.repo.local=cesta_k_maven_repozitari 5. česky sada testů 46 7. I M P L E M E N T A C E Projekt slouží k pokrytí škály možných operací prováděných knihovnou Prograde a s dalším vývojem knihovny je nutné také rozšiřovat tento pro­ jekt. Funkční testování Bohužel ne každou část implementace je možné testovat pomocí automatizovaných testů. Prvek codebase ze souboru s definicí bezpečnostní politiky je ovlivněn chováním metody i m p l i e s třídy CodeSource, kdy tato třída nemá striktně určeno, v jakém přesném formátu je uvedena její URL adresa (zda se jedná o absolutní nebo relativní cestu a sama metoda i m p l i e s této třídy neumí vzájemně porovnávat tyto dva typy adres). V tomto případě je lepší a přesnější se vyhnout automatizovanému testu a funkcionalitu prvku codebase testovat ručně. 7.6 Budoucí vývoj knihovny Před dalším vývojem knihovny by bylo nejprve dobré odstranit současné nedostatky uvedené v podkapitole 7.3 Nedostatky implementace. Za důležité pokládám především přepsání metody e n c o d e S p e c i a l C h a r a c t e r s ze třídy P r o g r a d e P o l i c y F i l e tak, aby upravovala správně libovolnou cestu. Dále by bylo dobré rozšířit bezpečnostní politiku tak, aby obstarávala všechnu funkcionalitu, jejíž konfiguraci může přebírat ze souboru $ { j a v a . h o m e } / l i b / s e c u r i t y / j a v a . s e c u r i t y (byť není spojena s funkcí zamítavých pravidel). Nejzajímavější budoucí vývoj aplikace by mohl být spojen s vývojem heuristik pro rozhodování, zda procházet nejdříve povolující nebo zamítavý seznam s prvky P r o g r a d e P o l i c y E n t r y tak, jak bylo zmíněno na konci podkapitoly 4.2.2 Dvouprůchodová kontrola přístupu. Pro vývoj těchto heuristik by však bylo dobré získat nějaká statistická data o běžném poměru mezi povolujícími a zamítavými pravidly. Tím pádem by bylo užitečné nejprve nasadit do provozu lehce upravenou současnou verzi knihovny a posbírat různá statistická data. 47 8 Porovnání výkonů bezpečnostních politik Jedním z hlavních důvodů pro zavedení bezpečnostní politiky podporující zamítavá pravidla je zrychlení výkonu aplikací. Abychom mohli ukázat, že zavedení této nové bezpečnostní politiky má skutečně význam, je nutné provést měření, ve kterých porovnáme výkon aplikace používající standardní implementaci bezpečnostní politiky s výkonem stejné aplikace při použití knihovny Prograde. Tato měření můžeme provést napříč různými implementacemi platformy Java. N a závěr můžeme také pro zajímavost mezi sebou porovnat dosažené výsledky v těchto použitých implemen­ tacích. 8.1 Porovnávací scénáře Pro měření výkonu aplikace jsem navrhl tři různé scénáře, na jejichž základě jsem vytvořil tři jednoduché aplikace, které přistupují k některým citlivým zdrojům, a tudíž pro svůj běh používají bezpečnostní politiku (v případě, kdy je nastaven Security Manager). Jedná se pouze o ukázkové scénáře demonstrující funkci a možnosti fungování bezpečnostní politiky při použití zajímavých pravidel, nikoliv o příklady reálných aplikací. Scénář A Definice scénáře: Aplikace přečte hodnotu systémových proměnných java.home a user.home. Cílem tohoto scénáře je získat údaje o rychlosti vyhodnocování běžné bezpečnostní politiky, přesněji řečeno o získání poměru rychlosti mezi standardní bezpečnostní politikou a knihovnou Prograde. Pro provedení scénáře A není potřeba použít zamítavá pravidla, a tudíž tento scénář slouží především pro získání výchozí hodnoty určující, jakým poměrem se liší obě implementace ve své téměř základní možné podobě. Pro získání objektivnějších dat je v aplikaci použit cyklus, který zmíněný scénář provede 10 000 000 krát. Souslovím "běh scénáře A " budu označovat právě provedení tohoto cyklu. Scénář B Definice scénáře: Mějme systém, se kterým pracuje 5 rolí, reprezentovaných objekty třídy Principal, se jmény roleA až roleE, a řekněme, že každý Subject může 48 8. P O R O V N Á N Í V Ý K O N Ů B E Z P E Č N O S T N Í C H P O L I T I K mít přiřazenu nejvýše jednu tuto roli. Aplikace se postupně snaží přečíst hodnotu systémových proměnných java.home, user.home a java.version. Pro přístup k citlivým proměnným platí tato pravidla: • Proměnnou user.home smí číst kdokoliv, kdo má přiřazenu libovolnou z daných rolí. • Proměnnou java.version smí číst kdokoliv, kdo má přiřazenu některou z daných rolí, ne však ten, kdo má přiřazenu roli E. • Proměnnou java.home smí číst pouze ten, kdo má přiřazenu roli A. Tento scénář má za úkol ukázat praktičnost použití zamítavých pravidel na jednoduché aplikaci, jejíž požadavky na bezpečnostní politiku mohou být v principu shodné s požadavky na bezpečnostní politiku běžně používanou i bez zamítavých pravidel. Podmínky přístupu lze poměrně snadno zapsat i bez zamítavých pravidel (pokud má definice pravidel bezpečnostní politiky tak malý rozsah jako v tomto scénáři), zajímat nás tak bude především poměr výkonů při použití nebo nepoužití zamítavých pravidel. Pro jeho přesnější porovnání bude aplikace stejně jako v minulém scénáři provedena v cyklu, tentokrát 100 000 krát. Souslovím "běh scénáře B" budu opět označovat právě provedení tohoto cyklu. Scénář C Definice scénáře: Uvažujme, že ve složce ${user.homel/temp mohou být uloženy soubory se jmény filel.txt, file2.txt,..., filel00000.txt. Aplikace může číst všechny soubory s výjimkou souboru filel.txt, který nesmí číst nikdo. Aplikace se postupně u každého možného souboru snaží zjistit, zda tento soubor existuje. Na první pohled je zřejmé, že cílem tohoto scénáře je ukázat efektivitu použití zajímavých pravidel na nějakém extrémním příkladu použití. Zatímco v případě použití bezpečnostní politiky se zamítavými pravidly bude rozhodnutí o povolení nebo zamítnutí přístupu poměrně snadnou operací, tak při použití standardní bezpečnostní politiky se bude jednat o daleko náročnější proces. Stejně tak zápis potřebné konfigurace bezpečnostní politiky bude daleko snazší v případě použití bezpečnostní politiky podporující zamítavá pravidla. Tento scénář nepotřebuje být proveden v žádném cyklu, a proto sousloví "běh scénáře C " odpovídá přímo provedení jednoho běhu scénáře. 49 8. P O R O V N Á N Í V Ý K O N Ů B E Z P E Č N O S T N Í C H P O L I T I K 8.2 Získání výsledků scénářů Každá z aplikací implementující některý ze scénářů má ve svém těle umístěny dvě místa, která při průchodu uloží do proměnné systémový čas. Jedno toto místo je umístěno přímo před začátkem běhu scénáře a druhé hned za jeho koncem. Veškeré nutné nastavení aplikace je provedeno před nebo po běhu scénáře, a tudíž lze dobu běhu scénáře spočítat pomocí rozdílu dvou proměnných obsahujících časy průchodu oběma kontrolními místy. Pro získání přesnějších výsledků byla každá aplikace spuštěna sedmkrát a výsledky každého běhu byly zaznamenány. Pro snadné opětovné spuštění se shodným nastavením pracovního prostředí byl použit nástroj Jenkins. Jedná se o open source nástroj sloužící pro opakovaný běh skriptů (nazývaných joby) používaných pro nastavení systému a spuštění aplikací. Výsledky byly získány při bězích na operačním systému RHEL 6 a slouží především pro vzájemné porovnání. Pro získání objektivnějších výsledků byl vždy použit stejný stroj se stejným iniciálním nastavením. Knihovnu Prograde jsem se rozhodl porovnat s bezpečnostní politikou ve třech různých implementacích Javy, z toho každou z nich ve dvou nejnovějších verzích. Srovnání se tedy týká: • standardní Javy vydávané společností Oracle ve verzi 1.6 a 1.7 • OpenJDK, což je open source implementace platformy Java, taktéž ve verzi 1.6 a 1.7 • IBM Javy, tedy Javy vyvíjené společností IBM, ve verzi 6 a 7 8.3 Výsledky a jejich vyhodnocení Za výsledky běhů scénářů můžeme dosadit aritmetické průměry všech sedmi běhů aplikace pro konkrétní kombinaci Javy a použití nebo nepoužití zamítavých pravidel. Výsledek poté můžeme zaokrouhlit na celé milisekundy. První scénář použijeme pro zjištění, v jakém poměru jsou výkony standardní bezpečnostní politiky (označme jako standard) a knihovny Prograde (označme jako Prograde) při použití bezpečnostní politiky nevyžadující zamítavá pravidla. Tento poměr označme A a jeho hodnotu získáme pomocí podílu výsledků běhů scénáře A v obou variantách, tedy: standardj± — Prograde Druhý a třetí scénář již použijeme pro skutečné porovnání standardních bezpečnostních politik a bezpečnostních politik povolujících zamítavá 50 8. P O R O V N Á N Í V Ý K O N Ů B E Z P E Č N O S T N Í C H P O L I T I K pravidla. Výsledek získáme opět podílem výsledného času běhu scénáře B nebo C při použití standardní bezpečnostní politiky a knihovny Prograde, tento podíl můžeme opět označit jako B, resp. C pro scénář C (obdobně jako ve scénáři A). Pro zjištění opravdového zrychlení (nebo zpomalení v případě celkové výsledné hodnoty nižší než 1) můžeme použít poměr obou scénářů. Zajímá nás, jak se zlepšil výkon ve scénáři B (resp. C) oproti scénáři A , tedy výsledek V můžeme vypočítat pomocí: Vr B Ä C ~A Nyní můžeme na základě výše zmíněných vzorců vyhodnotit výsledky běhů bezpečnostních politik na jednotlivých Java platformách. 8.3.1 Oracle Java 1.6 standardní bezpečnostní politika knihovna Prograde podíl scénář A 23419ms 23713ms 0,988 scénář B 88277ms 14423ms 6,121 scénář C 156143ms 6083ms 25,669 vh B V, C Ä _ 6,121 " 0 , 9 8 8 2 5 , 6 6 9 0 , 9 8 8 6,195 2 5 , 9 8 1 Běh scénáře B je 6,195 krát a běh scénáře C 25,981 krát rychlejší při použití zamítavých pravidel než při použití běžné bezpečnostní politiky. 8.3.2 Oracle Java 1.7 standardní bezpečnostní politika knihovna Prograde podíl scénář A 23371ms 20963ms 1,115 scénář B 88226ms 15152ms 5,823 scénář C 159914ms 6001ms 26,648 Vi, B ~A 5 , 8 2 3 1,115 5 , 2 2 2 51 8. P O R O V N Á N Í V Ý K O N Ů B E Z P E Č N O S T N Í C H P O L I T I K C 26,648 ^ = i= ťny =23 '9 Běh scénáře B je 5,222 krát a běh scénáře C 23,9 krát rychlejší při použití zamítavých pravidel než při použití běžné bezpečnostní politiky. 8.3.3 OpenJDK1.6 standardní bezpečnostní politika knihovna Prograde podíl scénář A 25780ms 23840ms 1,081 scénář B 74352ms 14147ms 5,256 scénář C 152697ms 5969ms 25,582 B 5,256 Vb = — = = 4, 862 A 1,081 C 25,582 V c = - = — = 23, 665 A 1,081 Běh scénáře B je 4,862 krát a běh scénáře C 23,665 krát rychlejší při použití zamítavých pravidel než při použití běžné bezpečnostní politiky. 8.3.4 OpenJDK1.7 standardní bezpečnostní politika knihovna Prograde podíl scénář A 24255ms 22790ms 1,064 scénář B 80823ms 15165ms 5,33 scénář C 162966ms 5865ms 27,786 B 5,33 v >= Ä= Úu=5 -°°9 C 27,786 ,. A 1,064 Běh scénáře B je 5,009 krát a běh scénáře C 26,115 krát rychlejší při použití zamítavých pravidel než při použití běžné bezpečnostní politiky. 52 8. P O R O V N Á N Í V Ý K O N Ů B E Z P E Č N O S T N Í C H P O L I T I K 8.3.5 IBM Java 6 standardní bezpečnostní politika knihovna Prograde podíl scénář A 95088ms 49135ms 1,935 scénář B 44187ms 21492ms 2,056 scénář C 1800225ms 6146ms 292,91 B 2 , 0 5 6 V b = A = 1 ^ 3 5= 1 ' 0 6 3 V c = C ^ = 1 B 1 3 7 B A 1 , 9 3 5 Běh scénáře B je 1,063 krát a běh scénáře C 151,375 krát rychlejší při použití zamítavých pravidel než při použití běžné bezpečnostní politiky. Výsledky běhu aplikace s IBM Javou 6 jsou poměrně zajímavé, jelikož se podstatně liší od jinak podobných výsledků všech ostatních zkoumaných implementací platformy Java. V IBM Javě 7 se výsledky však už vrací zpátky do normálu, je tedy možné, že v IBM Javě 6 je použitý rozdílný typ bezpečnostní politiky než v jiných platformách. Toto téma však již nesouvisí s tématem této diplomové práce, kdy nás zajímá porovnání bezpečnostních politik s a bez zamítavých pravidel, nikoliv bezpečnostních politik v různých implementacích Javy mezi sebou. 8.3.6 IBM Java 7 standardní bezpečnostní politika knihovna Prograde podíl scénář A 45511ms 47289ms 0,962 scénář B 85024ms 22379ms 3,799 scénář C 319407ms 9513ms 33,576 B 3,799 F ' = I = Ô ^ 2 = 3 ' 9 4 9 C 33,576 A 0,962 Běh scénáře B je 3,949 krát a běh scénáře C 34,902 krát rychlejší při použití zamítavých pravidel než při použití běžné bezpečnostní politiky. 53 8. P O R O V N Á N Í V Ý K O N Ů B E Z P E Č N O S T N Í C H P O L I T I K 8.3.7 Znázornění výsledků Nejzajímavější porovnání přináší scénář B, který nabízí nikterak extrémní definici bezpečnostní politiky, která přesto ukazuje rozdíl při použití standardní bezpečnostní politiky a politiky obsahující zamítavá pravidla. Dosažené výsledky výkonů v tomto scénáři jsou graficky zobrazeny na následujícím grafu: Čas provedení běhu scénáře B v milisekundách 1 0 0 0 0 0 E 0 0 0 0 O r a c l e J a v a 1.6 O r a c l e J a v a 1.7 O p e n J D K 1.6 O p e n J D K 1.7 I B M J a v a 6 I B M J a v a 7 • s t a n d a r d n í i m p l e m e n t a c e • k n i h o v n a P r o g r a d e Další graf znázorňuje porovnání hodnot Vb, tedy opravdových zrychlení ve všech testovaných implementacích Javy: Procentuální zvýšení výkonu ve scénáři B při použití zamítavých pravidel zzz ^zz •;zz 2ZZ LZ-Z O r a c l e J a v a 1.6 O r a c l e J a v a 1.7 O p e n J D K 1.6 O p e n J D K 1.7 I B M J a v a 6 I B M J a v a 7 54 8. P O R O V N Á N Í V Ý K O N Ů B E Z P E Č N O S T N Í C H P O L I T I K Ve výsledcích scénáře C je na první pohled zřejmé, že využití bezpečnostních politik se zamítavými pravidly výrazně zvýší výkon aplikace. Pro lepší demonstraci výsledků můžeme tato data taktéž zobrazit v grafech1 : Čas provedení běhu scénáře C v milisekundách 3 5 0 0 0 0 3 0 0 0 0 0 2 5 0 0 0 0 2 0 0 0 0 0 15C COC IDO 000 5 0 0 0 0 O r a c l e J a v a 1.5 O r a c l e J a v a 1.7 O p e n J D K 1.5 O p e n J D K 1.7 I B M J a v a 7 i s t a n d a r d n i i m p l e m e n t a c e • k n i h o v n a P r o g r a d e Procentuální zvýšení výkonu v e scénáři C při použití zamítavých pravidel 4 0 0 0 3 5 0 0 3 0 0 0 2 5 0 0 2 0 0 0 1 5 0 0 1 0 0 0 5 0 0 0 3 3 9 0 . 2 2 4 9 8 , 1 2 5 1 1 . 5 2 2 9 0 22ČČ.5 O r a c l e J a v a 1 . 6 O r a c l e J a v a 1 . 7 O p e n J D K 1 . 6 O p e n J D K 1 . 7 I B M J a v a 7 1. V obou grafech nejsou zahrnuty výsledky běhu scénáře C s IBM Javou 6 - její rozdíly ve výsledcích jsou daleko větší než u zbylých měření a vedly by k výraznému znepřehlednění obou grafů. 55 8. P O R O V N Á N Í V Ý K O N Ů B E Z P E Č N O S T N Í C H P O L I T I K 8.3.8 Vyhodnocení Na základě získaných hodnot můžeme názorně vidět, že zavedení bezpečnostních politik podporujících zamítavá pravidla skutečně význam má. Ve scénáři B je tento rozdíl viditelný, i když by se na první pohled mohlo zdát, že zavedením zamítavých pravidel v tomto případě nic výrazného nezískáme. Daleko markantnější rozdíl je již vidět ve výsledcích scénáře C, kdy je čas potřebný pro provedení bezpečnostní politiky bez zamítavých pravidel zhruba 25 krát delší. 56 9 Závěr Ve své diplomové práci jsem nejdříve zanalyzoval současnou implementaci bezpečnostní politiky v Javě. Navrhl jsem možná rozšíření bezpečnostní politiky o zamítavá pravidla a jednu z těchto možností jsem následně implementoval. Součástí návrhu a implementace byl též návrh souboru s konfigurací bezpečnostní politiky který je zpětně kompatibilní s tímto souborem v Javě. Zabýval jsem se taktéž výhodami a nevýhodami jejího použití a na závěr jsem připravil výkonnostní scénáře, na jejichž základě jsem provedl porovnání mé implementace bezpečnostní politiky se zamítavými pravidly s implementací standardní bezpečnostní politiky v Javě. Zajímavý mi přišel názor z knihy Inside Java 2 Platform SecuritySecond Edition - Achitecture, API Design, and implementation (viz [2]), kde autoři píší, že zamítavá pravidla nejsou potřeba, protože nepřináší novou vyjadřovací schopnost. Tato úvaha je však mylná. Během zkoumání možností zápisu konfigurace bezpečnostní politiky jsem narazil na možné konfigurace, které lze pomocí zamítavých pravidel snadno vyjádřit, zatímco bez jejich použití je to možné velmi složitě nebo dokonce vůbec. Pomocí porovnání výkonů bezpečnostních politik při práci s definovanými scénáři jsem názorně ukázal, že použití zamítavých pravidel může zrychlit provádění celé bezpečnostní kontroly. Stejně tak zápis konfigurace bezpečnostní politiky může být daleko snadnější. Jedinou nevýhodu při použití bezpečnostních politik se zamítavými pravidly vidím v možném ztížení čitelnosti souboru s konfigurací bezpečnostní politiky v případě, kdy daná definice bezpečnostní politiky obsahuje větší množství pravidel. Nicméně tuto nevýhodu lze eliminovat vývojem jednoduché aplikace, která by pomáhala danou konfiguraci bezpečnostní politiky vytvořit a také umožňovala kontrolovat, zda je daná konfigurace správně zapsaná. V rámci celkového shrnutí práce si myslím, že zavedení bezpečnostní politiky se zamítavými pravidly má smysl. Aplikace díky ní může mít rychlejší výsledky vyhodnocování rozhodnutí o přístupu k citlivým zdrojům, je však potřeba dbát na správný zápis konfigurace bezpečnostní politiky. 57 A Vyzkoušení funkčnosti knihovny Prograde Pro názorné vyzkoušení funkčnosti knihovny Prograde jsem pro účely této diplomové práce vyvinul aplikaci s názvem progradeSimpleTestingProject. Základní funkčnost aplikace, kterou potřebuje uživatel znát, je jednoduchá - aplikace se snaží postupně přečíst a vypsat na standardní výstup hodnoty systémových proměnných java.home a user.home. Dále se snaží zapsat na standardní výstup návratovou hodnotu metody getSecret třídy S p e c i á l Cla s s (tato třída a její metoda je implementovaná s jediným účelem - během své metody g e t S e c r e t vyžaduje, aby měla aplikace povolenu permission třídy n e t . s o u r c e f orge . prograde . p r o g r a d e s i m p l e t e s t i n g p r o j e c t . S p e c i a l P e r m i s s i o n se jménem "5" nebo libovolným číslem vyšším než 5). Aplikace přiřazuje subjektu, který spouští ony akce vyžadující povolenou nějakou z daných permission, dva různé objekty typu P r i n c i p a l - jedná se o dvě instance objektů n e t . sourcef orge. p r o g r a d e . p r o g r a d e s i m p l e t e s t i n g p r o j e c t . T e s t i n g P r i n c i p a l se jmény "userA" a "userB". Výslednou sestavenou aplikaci je možné podepsat pomocí nástroje j a r s i g n e r . Na základě výše zmíněných informací může být vyzkoušena funkčnost knihovny Prograde, kdy pro definici souboru s konfigurací bezpečnostní politiky může být využito všech kombinací prvků codebase, principál a signedBy. Taktéž mohou být nastaveny různé kombinace grant a deny prvků a obě možnosti prvku priority. Záleží jen a jen na uživateli, jak danou konfiguraci bezpečnostní politiky nastaví. V případě hlubšího zájmu o přístup k různým P e r m i s s i o n mohou být do kódu těla třídy T e s t i n g A c t i o n s v projektu progradeSimpleTestingProject přidány další metody vyžadující povolení nějaké Permission. V tomto případě je po změně kódu nutné aplikaci znovu sestavit. A . l Sestavení a spuštění aplikace progradeSimpleTestingProject Návod je určený pro distribuce operačního systému Linux. Tento návod také předpokládá, že má uživatel již nainstalován Apache Maven a v případě použití kroku la. také Git. Všechny příkazy v tomto návodu je nutné psát vždy na jeden řádek (i když jsou v textu rozděleny do více řádků). 1. Získání knihovny Prograde Získání knihovny Prograde je možné pomocí jedné z následujících možností: 58 A . V Y Z K O U Š E N Í F U N K Č N O S T I K N I H O V N Y P R O G R A D E a. stáhnutí z githubu V tomto případě stačí ze složky, ve které chceme mít uložený projekt s knihovnou pro-grade, zavolat příkaz: g i t c l o n ě h t t p s : / / g i t h u b . c o m / o l u k a s / p r o - g r a d e . g i t b. zkopírování z přiloženého CD Projekt s knihovnou pro-grade je také uložen na přiloženém C D ve složce codesources. Stačí tedy do složky, ve které chceme mít uložený projekt s knihovnou Prograde, zkopírovat složku codesources/pro-grade z přiloženého CD. 2. Sestavení knihovny Prograde (a přidání do Maven repozitáře) Před samotným sestavením knihovny Pro-grade přejděme v terminálu do její složky: cd p r o - g r a d e Knihovnu Pro-grade sestavíme pomocí následujícího příkazu: mvn c l e a n i n s t a l l -Dmaven.repo.local=$MAVEN_REPO Proměnná prostředí $ MAVEN_REP0 by měla obsahovat absolutní cestu k lokálnímu maven repozitáři. Nicméně proměnná maven . repo . 1 o c a 1 je nepovinná, v případě jejího nepoužití bude knihovna nahrána do repozitáře předdefinovaného samotným Mavenem. 3. Nepovinně: Spuštění testsuite pomocí projektu progradeTests Projekt progradeTests získáme buď z přiloženého C D zkopírováním složky codesources/progradeTests, a nebo pomocí příkazu: g i t c l o n ě h t t p s : / / g i t h u b . c o m / o l u k a s / p r o g r a d e T e s t s . g i t Poté přejdeme do složky progradeTests a všechny testy spustíme pomocí příkazu: mvn c l e a n t e s t -Dmaven.repo.local=$MAVEN_REPO O správném průběhu testů nás informuje řádek: T e s t s r u n : 29, F a i l u r e s : 0, E r r o r s : 0, S k i p p e d : 0 59 A . V Y Z K O U Š E N Í F U N K Č N O S T I K N I H O V N Y P R O G R A D E 4. Sestavení testovacího projektu Nejdříve přejděme do složky s projektem progradeSimpleTestingProject (který si zkopírujeme ze složky codesources/progradeSimpleTestingProject z přiloženého CD). Sestavení poté provedeme pomocí příkazu: mvn c l e a n compile a s s e m b l y : s i n g l e -Dmaven.repo.local=$MAVEN_REPO Výsledek sestavení bude umístěn ve složce target. 5. Zkopírování do složky playground Výsledný sestavený projekt je nutné zkopírovat do složky playground (tu i s jejím obsahem získáme z přiloženého CD, je umístěna v kořenovém adresáři CD), to můžeme mimo jiné provést pomocí příkazu: cp t a r g e t / p r o g r a d e S i m p l e T e s t i n g P r o j e c t - 1 . 0 - j a r w i t h - d e p e n d e n c i e s . j a r $PLAYGROUND Proměnná $PLAYGROUND označuje cestu ke složce playground (zkopírované z CD). Poté přejděme do složky playground pomocí příkazu: cd $PLAYGROUND 6. Nepovinně: podepsání aplikace Pro podepsání aplikace je použit nástroj j a r signer, který provede podepsání na základě úložiště klíčů prograde . keystore umístěného ve složce playground. Pomocí tohoto úložiště může být aplikace podepsána dvěma klíči - duke a a dam. Heslo k oběma klíčům je "password". Podepsání provedeme pomocí příkazu: j a r s i g n e r - k e y s t o r e p r o g r a d e . k e y s t o r e - s t o r e p a s s keypass - k e y p a s s password p r o g r a d e S i m p l e T e s t i n g P r o j e c t - 1 . 0 - j a r - w i t h - d e p e n d e n c i e s . j a r duke resp. j a r s i g n e r - k e y s t o r e p r o g r a d e . k e y s t o r e - s t o r e p a s s keypass - k e y p a s s password p r o g r a d e S i m p l e T e s t i n g P r o j e c t - 1 . 0 - j a r - w i t h - d e p e n d e n c i e s . j a r adam 60 A . V Y Z K O U Š E N Í F U N K Č N O S T I K N I H O V N Y P R O G R A D E Aplikace může být podepsána jedním z těchto klíčů nebo oběma, případně nemusí být podepsána žádným z nich. Podpis slouží pro testování prvku signedBy z konfigurace bezpečnostní politiky. 7. Spuštění aplikace progradeSimpleTestingProject Před spuštěním aplikace je nutné nastavit konfiguraci bezpečnostní politiky. Mnou předdefinovaná konfigurace, která jednoduše povolí všechny tří permission nutné pro úspěšný běh aplikace, je umístěna v souboru t e s t i n g . p o l i c y ve složce playground. Tento soubor však slouží k následnému editování do libovolné podoby vyhovující danému uživateli. Pro snadnou práci obsahuje řadu komentářů, které pomohou při zápisu oné konfigurace. Spuštění aplikace progradeSimpleTestingProject provedeme příkazem: Java - j a r -D j a v a . s e c u r i t y . m a n a g e r = n e t . s o u r c e f o r g e . p r o g r a d e . sm.ProgradeSecurityManager - D j a v a . s e c u r i t y . p o l i c y = = t e s t i n g . p o l i c y - D J a v a . s e c u r i t y . a u t h . l o g i n . c o n f i g = = l o g i n m o d u l e . c o n f i g p r o g r a d e S i m p l e T e s t i n g P r o j e c t - 1 . 0 - j a r - w i t h d e p e n d e n c i e s . j a r V případě, kdy chceme, aby aplikace vypisovala také ladící informace, můžeme dle našeho uvážení zvolit hodnotu proměnné java . s e c u r i t y . debug (například p o l i c y ) a použít příkaz: java - j a r - D j a v a . s e c u r i t y . d e b u g = p o l i c y -D j a v a . s e c u r i t y . m a n a g e r = n e t . s o u r c e f o r g e . p r o g r a d e . sm.ProgradeSecurityManager - D j a v a . s e c u r i t y . p o l i c y = = t e s t i n g . p o l i c y - D j a v a . s e c u r i t y . a u t h . l o g i n . c o n f i g = = l o g i n m o d u l e . c o n f i g p r o g r a d e S i m p l e T e s t i n g P r o j e c t - 1 . 0 - j a r - w i t h d e p e n d e n c i e s . j a r Na základě použité konfigurace bezpečnostní politiky aplikace vypíše hodnoty proměnných java . home a u s e r . home a řetězec "SECRET". V případě, kdy je některá potřebná permission zamítnuta, bude vyvolána bezpečnostní výjimka. 61 B Slovník pojmů Překlady některých anglických výrazů a slov používaných v českém jazyce (a naopak) nejsou příliš frekventované, a tudíž tak známé jako v jazyce opačném. Z tohoto důvodu přidávám stručný slovník několika pojmů, které by mohly způsobit nějaké nesrovnalosti. Nejedná se o doslovné překlady, ale spíše o významová spojení: balík kolekce oprávnění podtřída politika řízení přístupu sestavení (projektu) systémová proměnná úložiště klíčů vracet vyvolat výjimku zděděný kontext package collection permission subclass policy access control build (project) system property keystore return throw exception inherited context 62 C Obsah přiloženého CD Na přiloženém C D se nachází následující soubory a složky: • codesources/ - složka obsahující zdrojové kódy všech projektů a aplikací vytvořených v rámci diplomové práce; obsahuje podsložky: - pro-grade/ - implementace knihovny Prograde - progradeTests/ - testsuite knihovny Prograde - progradeSimpleTestingProject/ - projekt sloužící k vyzkoušení funkčnosti knihovny Prograde - testovací_scénáře/ - složka obsahující projekty se scénáři použitými pro porovnání výkonů bezpečnostních politik a také soubory potřebné pro toto porovnání • playground/ - složka obsahující soubory potřebné pro vyzkoušení funkčnosti knihovny Prograde, viz A Vyzkoušení funkčnosti knihovny Prograde • dp.pdf - dokument s textem této diplomové práce • porovnání_výkonů_bezpečnostních_politik.ods - soubor obsahující naměřené výsledky při porovnávání výkonů bezpečnostních politik v různých implementacích Javy 63 Literatura [1] Oaks, S. Java Security. Sebastopol, C A : O'REILLY & Associates, Inc., 1998, ISBN 1-56592-403-7. [2] Gong, L., Ellison, G., Dadgeforde, M . Inside Java 2 Platform Security: Architecture, API Design, and Implementation. 2. vyd., Addison-Wesley Professional, 2003, ISBN 0201787911. [3] Jaworski, J., Perrone, P. Java Security Handbook. Indianapolis, Sams Professional, 2000, ISBN 0-672-31602-1. [4] Chacon, S. Pro Git. Praha, CZ.NIC, 2009, ISBN 978-80-904248-1-4. [5] Matyáš, Václav: studijní materiály ke kurzu PV080 Ochrana dat a informačního soukromí [6] Říha, Zdeněk: studijní materiály ke kurzu PV157 Autentizace a řízení přístupu [7] keytool - Key and Certificate Management Tool [online]. Oracle, [cit. 30.10.2013] Dostupné z World Wide Web: . [8] SecurityManager [online]. Oracle, [cit. 12.10.2013] Dostupné z World Wide Web: < h t t p : / / d o c s . o r a c l e . e o m / j a v a s e / 7 / d o c s / a p i / j a v a / l a n g / S e c u r i t y M a n a g e r . h t m l > . [9] Permission [online]. Oracle, [cit. 12.10.2013] Dostupné z World Wide Web: < h t t p : / / d o c s . o r a c l e . c o m / j a v a s e / 7 / d o c s / a p i / J a v a / s e c u r i t y / P e r m i s s i o n . h t m l > . [10] AllPermission [online]. Oracle, [cit. 12.10.2013] Dostupné z World Wide Web: < h t t p : / / d o c s . o r a c l e . c o m / j a v a s e / 7 / d o c s / a p i / J a v a / s e c u r i t y / A l l P e r m i s s i o n . h t m l > . [11] UnresolvedPermission [online]. Oracle, [cit. 12.10.2013] Dostupné z World Wide Web: < h t t p : / / d o c s . o r a c l e . e o m / j a v a s e / 7 / d o c s / a p i / J a v a / s e c u r i t y / U n r e s o l v e d P e r m i s s i o n . h t m l > . [12] Policy [online]. Oracle, [cit. 12.10.2013] Dostupné z World Wide Web: < h t t p : / / d o c s . o r a c l e . c o m / j a v a s e / 7 / d o c s / a p i / J a v a / s e c u r i t y / P o l i c y . h t m l > . 64 C. O B S A H P Ř I L O Ž E N É H O C D [13] PolicyFile [online]. GrepCode. [cit. 12.10.2013] Dostupné z World Wide Web: < h t t p : / / g r e p c o d e . c o m / f i l e / r e p o s i t o r y . g r e p c o d e . c o m / J a v a / r o o t / j d k / o p e n j d k / 6 - b l 4 / s u n / s e c u r i t y / p r o v i d e r / P o l i c y F i l e . j a v a > . [14] Default Policy Implementation and Policy File Syntax [online]. Oracle, [cit. 12.10.2013] Dostupné z World Wide Web: < h t t p : / / d o c s . o r a c l e . c o m / j a v a s e / 7 / d o c s / t e c h n o t e s / g u i d e s / s e c u r i t y / P o l i c y F i l e s . h t m l > . [15] AccessController [online]. Oracle, [cit. 12.10.2013] Dostupné z World Wide Web: < h t t p : / / d o c s . o r a c l e . e o m / j a v a s e / 7 / d o c s / a p i / J a v a / s e c u r i t y / A c c e s s C o n t r o l l e r . h t m l > . [16] AccessControlContext [online]. Oracle, [cit. 12.10.2013] Dostupné z World Wide Web: < h t t p : / / d o c s . o r a c l e . e o m / j a v a s e / 7 / d o c s / a p i / J a v a / s e c u r i t y / A c c e s s C o n t r o l C o n t e x t . h t m l > . [17] PermissionCollection [online]. Oracle, [cit. 12.10.2013] Dostupné z World Wide Web: < h t t p : / / d o c s . o r a c l e . e o m / j a v a s e / 7 / d o c s / a p i / J a v a / s e c u r i t y / P e r m i s s i o n C o l l e c t i o n . h t m l > . [18] Permissions [online]. Oracle, [cit. 12.10.2013] Dostupné z World Wide Web: < h t t p : / / d o c s . o r a c l e . c o m / j a v a s e / 7 / d o c s / a p i / J a v a / s e c u r i t y / P e r m i s s i o n s . h t m l > . [19] CodeSource [online]. Oracle, [cit. 12.10.2013] Dostupné z World Wide Web: < h t t p : / / d o c s . o r a c l e . c o m / j a v a s e / 7 / d o c s / a p i / J a v a / s e c u r i t y / C o d e S o u r c e . h t m l > . [20] ProtectionDomain [online]. Oracle, [cit. 12.10.2013] Dostupné z World Wide Web: < h t t p : / / d o c s . o r a c l e . e o m / j a v a s e / 7 / d o c s / a p i / J a v a / s e c u r i t y / P r o t e c t i o n D o m a i n . h t m l > . [21] Guard [online]. Oracle, [cit. 12.10.2013] Dostupné z World Wide Web: < h t t p : / / d o c s . o r a c l e . c o m / j a v a s e / 7 / d o c s / a p i / J a v a / s e c u r i t y / G u a r d . h t m l > . [22] GuardedObject [online]. Oracle, [cit. 12.10.2013] Dostupné z World Wide Web: < h t t p : / / d o c s . o r a c l e . e o m / j a v a s e / 7 / d o c s / a p i / J a v a / s e c u r i t y / G u a r d e d O b j e c t . h t m l > . [23] Java Authentication and Authorization Service (JAAS) Reference Guide [online]. Oracle, [cit. 12.10.2013] Dostupné z World Wide Web: 65 C. O B S A H P Ř I L O Ž E N É H O C D < h t t p : / / d o c s . o r a c l e . c o m / j a v a s e / 7 / d o c s / t e c h n o t e s / g u i d e s / s e c u r i t y / j a a s / J A A S R e f G u i d e . h t m l > . [24] BasicPermission [online]. Oracle, [cit. 12.10.2013] Dostupne z World Wide Web: < h t t p : / / d o c s . o r a c l e . e o m / j a v a s e / 7 / d o c s / a p i / J a v a / s e c u r i t y / B a s i c P e r m i s s i o n . h t m l > . [25] Apache Maven [online]. The Apache Software Foundation, [cit. 9.12.2013] Dostupne z World Wide Web: < h t t p : / / h t t p : / /maven . apache.org/>. [26] Troubleshooting Security [online]. Oracle. [cit. 10.12.2013] Dostupne z World Wide Web: < h t t p : / / d o c s . o r a c l e . c o m / j a v a s e / 7 / d o c s / t e c h n o t e s / g u i d e s / s e c u r i t y / t r o u b l e s h o o t i n g - s e c u r i t y . h t m l > . 66