reklama

Poznáváme C# a Microsoft .NET 77. díl – Programové použití CAS

Po teoretickém úvodu do světa bezpečnosti v .NET frameworku a představení CAS se v dnešním díle konečně podíváme na možnost využití této technologie z našeho programového kódu a to jak imperativním způsobem, tak způsobem deklarativním.

Možnosti programového použití CAS

Po minulém díle již víme, že technologie zabezpečení CAS slouží k ochraně zdrojů před nebezpečným kódem a také víme, že je tento způsob zabezpečení postaven na konfigurovatelném principu kódových skupin a sad oprávnění. Systém zabezpečení CAS jsme schopni využívat i z našeho programového kódu.

Díky této možnosti jsme například schopni zjistit zda-li běžící kód disponuje oprávněními pro přístup k určitému chráněnému zdroji a na základě toho zareagovat. A to třeba tak, že vyhodíme chybovou hlášku nebo změníme chování aplikace. Také jsme schopni například zajistit, že kód volající naši assembly bude dočasně moci přistupovat k prostředku na který nemá potřebná oprávnění a nebo je naopak možné zamítnout volajícímu kódu přistup k chráněnému prostředku i když oprávněním na přístup disponuje.

Způsoby programového použití CAS

Pracovat programově se systémem zabezpečení CAS je možné dvěma odlišnými způsoby. Prvním z nich je takzvaný imperativní, při kterém jsou standardně v kódu používány třídy systému zabezpečení CAS. Druhým způsobem je deklarativní, při jehož použití jsou používány atributy k označení typů a jejich členů, k zajištění požadované bezpečnostní funkčnosti. Nelze říci, že imperativním způsobem lze udělat to samé jako způsobem deklarativním a naopak. Řada věcí sice lze realizovat oběma způsoby, ale existuje i několik specifických věcí, které lze provést pouze jedním způsobem.

Při použití imperativního způsobu je, díky tomu, že jde o standardní volání metod na objektech, možné inicializovat objekty představující požadovaná oprávnění na základě informací, které jsou k dispozici pouze za běhu aplikace, a také je možné reagovat vlastními operacemi na případy, kdy kód nemá dostatečná oprávnění. Naproti tomu u použití deklarativního způsobu je možné provádět požadavky na potřebná minimální přidělená oprávnění a díky tomu, že je u toho způsobu použito atributů, lze informace o požadovaných oprávněních získat pomocí mechanismu reflexe. Také je použití tohoto způsobu pohodlnější, protože při něm napíšete méně kódu.

Vyžádání oprávnění

Všechna oprávnění v CAS jsou představována třídami, které implementují rozhraní IPermission ze jmenného prostoru System.Security. Dalším často implementovaným rozhraním je rozhraní IStackWalk ze stejného jmenného prostoru. Obě tato rozhraní obsahují metodu Demand, pro vyžádání daného oprávnění, ovšem pokud třída oprávnění implementuje rozhraní IStackWalk, znamená to, že při žádosti o oprávnění je procházen celý zásobník volání k ověření toho, že všichni volající mají požadované oprávnění. Většina tříd oprávnění rozhraní IStackWalk implementuje, ale jsou i výjimky typu PrincipalPermission (spojené ale spíše s role-based security), které implementují pouze rozhraní IPermission, tudíž v implementaci metody Demand zásobník volání neprocházejí. Společným předkem tříd pro práci se zdroji pomocí CAS je třída CodeAccessPermission, která implementuje obě dvě výše zmíněná rozhraní.

Při využití imperativního přístupu tedy pro vyžádání oprávnění zavoláme metodu Demand na konkrétním objektu oprávnění. Pokud mají všichni volající dostatečná oprávnění volání metody proběhne bez problému, avšak pokud některý volající nemá potřebná oprávnění je vyhozena výjimka typu SecurityException.

public class DemandExample
{
        public static void TestDemand()
        {
            IPermission perm = new EnvironmentPermission(EnvironmentPermissionAccess.Read, "PATH");
            try
            {
                //vyzadame opravneni - pokud kod opravneni nema je vyhozena vyjimka SecurityException
                perm.Demand();
                Console.WriteLine("Kod MA opravneni pro pristup k promenne prostredi PATH");
            }
            catch (SecurityException)
            {
                Console.WriteLine("Kod NEMA opravneni pro pristup k promenne prostredi PATH");
            }
        }
}

Při použití deklarativního způsobu použijeme atribut pro konkrétní typ oprávnění a specifikujeme, jakou akci chceme provést. K tomu nám slouží výčet SecurityAction. Takže pokud chceme oprávnění vyžádat, použijeme hodnotu výčtu Demand. Další upřesňující informace pro vyžádání oprávnění specifikujeme pomocí pojmenovaných parametrů.

[FileIOPermission(SecurityAction.Demand, PathDiscovery = "C:/")]
private static void DoFilePermDemand()
{
       Console.WriteLine("Pristup k disku z byl overen");
       //dalsi implementace metody..
}

Dočasné odepření přístupu ke zdroji

Vyžadování oprávnění není jediná operace, kterou jsme schopni v našem kódu provádět. Můžeme také zařídit, že dočasně odepřeme přístup k danému zdroji, takže i když bude volající kód podle konfigurace disponovat oprávněním pro přístup k tomuto zdroji, jeho požadavek o použití zdroje stejně skončí vyhozením výjimky. Za tímto účelem využijeme metody Deny, která se nachází na všech typech oprávnění, které implementují rozhraní IStackWalk. Po zavolání této metody, bude tedy jakýkoli pokus o přístup k danému zdroji v rámci aplikace odepřen.

public class DenyExample
{
        public static void TestDeny()
        {
            string path = @"C:\file.dll";
            //vytvoreni instance tridy zabezpeceni
            FileIOPermission perm = new FileIOPermission(FileIOPermissionAccess.Write, path);
            //docasne odepreni pristupu k souboru
            perm.Deny();
            StreamWriter writer = null;
            try
            {
                //tento pokus skonci vyhozenim vyjimky
                writer = new StreamWriter(path);
            }
            catch (SecurityException ex)
            {
                Console.WriteLine(ex);
            }
            finally
            {
                if (writer != null)
                {
                    writer.Close();
                }
            }

            //vratime docasne odepreni pristupu k souboru
            CodeAccessPermission.RevertDeny();

            try
            {
                //tento pokus bude jiz uspesny
                writer = new StreamWriter(path);
            }
            catch (SecurityException ex)
            {
                Console.WriteLine(ex);
            }
            finally
            {
                if (writer != null)
                {
                    writer.Close();
                }
            }
        }
}

K tomu, abychom opět umožnili přístup k chráněnému zdroji musíme použít statickou metodu třídy CodeAccessPermission, kterou je metoda RevertDeny. Tato metoda vrátí zpět všechna odepření v rámci volání. Jak můžete vidět po spuštění příkladu, druhý pokus o použití souboru, který se děje po zavolání této metody je již úspěšný.

Pokud budeme chtít na úrovni určitého elementu programového kódu odepřít přístup k nějakému zdroji pomocí deklarativní bezpečnosti použijeme v atributu oprávnění SecurityAction.Deny.

[FileIOPermission(SecurityAction.Deny, AllLocalFiles = FileIOPermissionAccess.AllAccess)]
public static void TestDeclarativeDeny()
        {
            string path = @"C:\file.dll";
            StreamWriter writer = null;
            try
            {
                writer = new StreamWriter(path);
            }
            catch (SecurityException)
            {
                Console.WriteLine("Kod nema opravneni pro pristup k soubouru");
            }
            finally
            {
                if (writer != null)
                {
                    writer.Close();
                }
            }
}

Dočasné povolení oprávnění

Podobně jako je možné dočasně odepřít přístup ke zdroji, je možné i přístup dočasně povolit. To znamená, že pokud volající kód disponuje určitým oprávněním, může toto oprávnění dočasně povolit, čímž zapříčiní, že i když kód, který jej volá, daným oprávněním nedisponuje, použití zdroje bude možné. Pro dočasné použití použijeme metodu Assert na instanci představující konkrétní oprávnění.

public class AssertExample
{

        public static void TestAssert()
        {
            FileIOPermission perm = new FileIOPermission(FileIOPermissionAccess.AllAccess, "C:/file.txt");
            //docasne odepreme pristup k souboru
            perm.Deny();
            FileWriter writer = new FileWriter();
            writer.WriteMessage();
        }
       
    }

    public class FileWriter
    {
        public void WriteMessage()
        {
            StreamWriter writer = null;
            FileIOPermission perm = new FileIOPermission(FileIOPermissionAccess.AllAccess, "C:/file.txt");
            //docasne povolime pristup k souboru
            perm.Assert();
            try
            {
                writer = new StreamWriter("C:/file.txt");
                writer.WriteLine("Nejaka zprava..");
            }
            finally
            {
                if (writer != null)
                {
                    writer.Close();
                }
            }
            //zrusime docasne povoleni pro pristup k souboru
            CodeAccessPermission.RevertAssert();
        }
}

V příkladu je pomocí metody Deny nasimulováno, že volající kód nemá oprávnění pro přístup k danému souboru. Avšak v metodě WriteMessage třídy FileWriter, která je tímto kódem volána, je použita metoda Assert pro dočasné udělení oprávnění a přístup k souboru neskoční vyhozením bezpečnostní výjimky.

Po provedení operací nad daným zdrojem je potřeba uvést vše do původního stavu pomocí statické metody RevertAssert třídy CodeAccessPermission, jinak by po opuštění důvěryhodného kódu mohlo dojít k narušení bezpečnosti méně důvěryhodným kódem (to znamená, že by mohl používat zdroj na který nemá oprávnění). Obecně doporučuji být při využívání metody Assert velmi opatrný. V případě použití deklarativní bezpečnosti se pro dočasné udělení oprávnění použije SecurityAction.Assert v atributu oprávnění.

Příklady ke článku lze stáhnout zde.

Příště dále rozebereme programové použití CAS.

Témata článku: Software, Microsoft, Programování, Public, Catch, Nema

1 komentář

Nejnovější komentáře

  • gully, gully 7. 8. 2006 12:41:02
    Off-line verzi seriálu si můžete stáhnout z
reklama
Určitě si přečtěte

UPC překopli páteřní kabel. V Brně i druhý den nejede internet ani kabelovka

UPC překopli páteřní kabel. V Brně i druhý den nejede internet ani kabelovka

** V Brně byl velký výpadek služeb UPC ** Důvodem je překopnutý páteřní kabel ** V některých lokalitách služby stále nefungují

5.  12.  2016 | Jakub Čížek | 103

17 expertek Microsoftu předpovědělo rok 2027. Splní se alespoň něco?

17 expertek Microsoftu předpovědělo rok 2027. Splní se alespoň něco?

** Zmizí klasické vyhledávače ** Budeme programovat buňky ** Kvantové počítače překonají šifry

6.  12.  2016 | Jakub Čížek | 36

11 tipů na dobrý stolní počítač: od základu po herní mašiny

11 tipů na dobrý stolní počítač: od základu po herní mašiny

** Postavte si stolní počítač! Máme pro vás 11 vzorových sestav s rozpisem komponent ** Většina tipů cílí na hráče, věnujeme se ale i základnímu PC a počítačům na střih videa ** Nadělte si nový počítač třeba pod stromeček

5.  12.  2016 | Adam Kahánek | 74

Nejlepší notebooky nad 20 tisíc: poradíme, které teď chcete

Nejlepší notebooky nad 20 tisíc: poradíme, které teď chcete

** V notebooku s cenou nad 20 tisíc nesmí chybět kvalitní displej a rychlé úložiště ** Za dalších deset tisíc můžete dostat navíc styl nebo výkonnější komponenty ** Vybírat můžete z různých velikostí i konstrukcí

8.  12.  2016 | Stanislav Janů | 84


reklama