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.
Poznáváme C# a Microsoft .NET 77. díl – Programové použití CAS

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, Kody, Nema, Nemo, Reflex

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
Určitě si přečtěte

To tu ještě nebylo. Specialisté ukázali, že zavirované mohou být i titulky SRT

To tu ještě nebylo. Specialisté ukázali, že zavirované mohou být i titulky SRT

** Stáhnete si film a titulky třeba z OpenSubtitles.org ** A osud vás za ten warez záhy potrestá ** Specialisté totiž ukázali, že i v titulcích může být schovaný virus

24.  5.  2017 | Jakub Čížek | 58

WannaCry se neměl vůbec rozšířit. Stačilo, abychom používali Windows Update

WannaCry se neměl vůbec rozšířit. Stačilo, abychom používali Windows Update

** WannaCry se masivně rozšířil kvůli zranitelnosti ve Windows ** Ta mu umožnila, aby se pokusil sám napadnout další počítače ** Jenže ta chyba už je dva měsíce opravená!

22.  5.  2017 | Jakub Čížek | 97


Aktuální číslo časopisu Computer

Bojujeme proti Fake News

Dva velké testy: fotoaparáty a NASy

Co musíte vědět o změně evropského roamingu

Radíme s výběrem základní desky