Nella precedente versione del Framework se si voleva lavorare con l'
ACL(Access Control List),lista controllo accessi) di file e directory bisognava per forza ricorrere all'utilizzo delle API di Windows, quindi con maggior difficoltà di implementazione per chi conosce poco, il vasto mondo dell'API di Windows.
Con la versione
2.0 del .NET Framework adesso possiamo lavorare con le
ACL di file e directory direttamente con codice managed tramite il namespace
System.Security.AccessControl.
Questo Namespace ha moltissime classi per lavorare con il controllo degli accessi ma in questo articolo prenderemo in esame le classi
FileSecurity e
DirectorySecurity che sono le classi predisposte proprio alla sicurezza rispettivamente di File e Directory.
Premessa
Per poter recuperare e impostare la sicurezza di file e directory bisogna avere l'hard disk impostato con una partizione
NTFS (NT File System) altrimenti non si potrà accedere a tali funzioni con una partizione per esempio
FAT32. Se avete ancora una partizione di questo tipo
FAT o
FAT32 potete convertirla con il comando
convert.exe.
Per capire meglio come funzionano queste classi prendiamo come esempio un file di testo presente sul mio pc che hai i seguenti utenti con i vari permessi:
Abbiamo i tre utenti:
Administrator,
Marco e
System che hanno il controllo completo, mentre il gruppo
Users ha solamente consentito i permessi
Lettura ed
Esecuzione.
Quindi proviamo da codice a recuperare questa lista di utenti e permessi.
Il codice seguente sarà in
C# ma in allegato all'articolo troverete anche il codice in
VB.NET.
Come detto prima dobbiamo riferirci al namespace
System.Security.AccessControl e quindi faremo un using per utilizzare le sue classi e faremo anche uno using del namespace
System.IO per lavorare con file e directory.
Recuperare le ACL
Come prima cosa dobbiamo avere un'istanza del file ed aprirlo in lettura e per fare questo useremo la classe
FileStream come di seguito riportato:
using System.Security.AccessControl;
using System.IO;
string pathFile = (@"C:\Demo\testAcl.txt");
using(FileStream fs = new FileStream(pathFile,FileMode.Open,FileAccess.Read))
{
}
Tramite la keyword
using (questa keyword è presente solo in
C#) apro il
FileStream. Il vantaggio dell'uso di
using è che quando la risorsa non sarà necessaria e quindi andrà in out of scope sarà automaticamente distrutta (
disposed).
All'interno dello using scrivo il seguente codice che serve a recuperare l'
ACL del file
testAcl.txt:
FileSecurity _fileSecurity = fs.GetAccessControl();
foreach (FileSystemAccessRule fsRule in
_fileSecurity.GetAccessRules(true,true,typeof(System.Security.Principal.NTAccount)))
{
Console.WriteLine("Utente:{0},Accesso:{1},Permessi:{2}",
fsRule.IdentityReference,
fsRule.AccessControlType,
fsRule.FileSystemRights);
}
Analizziamo il codice appena scritto.
Come prima cosa dobbiamo creare un'istanza della classe
FileSecurity o lo facciamo attraverso il metodo
GetAccessControl() del
FileStream.
FileSecurity _fileSecurity = fs.GetAccessControl();
Una volta ottenuta un'istanza della classe
FileSecurity eseguo un ciclo
ForEach per recuperare tutti i permessi utilizzando il metodo
GetAccessRules().
Il metodo
GetAccessRules espone tre parametri:
1. includeExplicit se true include tutte le regole di accesso impostate esplicitamente
2. includeInherit se true eredita tutte le regole di accesso dal padre
3. TargetType il tipo di indentità di sicurezza per il quale bisogna recuperare le regole.
Nel nostro caso il terzo parametro è un
NTAccount che rappresenta un'utente o un Gruppo di dominio.
Una voltra ottenuta un'istanza del classe
FileSystemAccessRule possiamo recuperare:
1. Identità(utente o gruppo) fsRule.IdentityReference
2. Tipo di accesso fsRule.AccessControlType
3. Permessi fsRule.FileSystemRights
Tramite il codice appena scritto avremo in output le seguenti regole di accesso:
Allo stesso modo dei file possiamo accedere alle regole di accesso delle directory utilizzando la classe
DirectorySecurity:
DirectoryInfo _dirInfo = new DirectoryInfo(path);
DirectorySecurity _dirSecurity = _dirInfo.GetAccessControl();
foreach (FileSystemAccessRule fsRule in
_dirSecurity.GetAccessRules(true,true,typeof(System.Security.Principal.NTAccount)))
{
Console.WriteLine("Utente:{0},Accesso:{1},Permessi:{2}",
fsRule.IdentityReference,
fsRule.AccessControlType,
fsRule.FileSystemRights);
}
Modificare le ACL
Se invece vogliamo modificare le impostazioni esistenti per esempio vogliamo negare la scrittura al gruppo
Users dobbiamo scrivere il seguente codice:
using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite))
{
FileSecurity _fileSecurity = fs.GetAccessControl();
FileSystemAccessRule _fsRule = new FileSystemAccessRule("BUILTIN\\Users",
FileSystemRights.Write,
AccessControlType.Deny);
_fileSecurity.AddAccessRule(_fsRule);
File.SetAccessControl(filePath, _fileSecurity);
}
Come nell'esempio di prima utilizzeremo la classe
FileStream per aprire il file ma questa volta utilizzeremo l'opzione
ReadWrite dell'enumeration
FileAccess, perchè bisogna modificare il file.
Come prima istanziamo la classe
FileSecurity e poi andiamo a creare la nostra regola di accesso tramite la classe
FileSystemAccessRule e gli definiamo:
• Account
"BUILTIN\USERS" (in
C# il carattere
\ è un carattere di escape quindi và raddoppiato
\\)
• La regola da impostare
FileSystemRigths.Write• Il tipo di controllo da impostare che può essere
Allow o
Deny.
Una volta creata la regola bisogna aggiungerla all'istanza della classe
FileSecurity:
fileSecurity.AddAccessRule(_fsRule);
Poi per salvare le impostazioni bisogna richiamare il metodo
SetAccessControl della classe
File. Se invece vogliamo rimuovere una regola basta richiamare il metodo:
_fileSecurity.RemoveAccessRule(_fsRule);
Oppure se vogliamo rimuovere tutte le ACL per un determinato account basta richiamare il metodo
RemoveAccessRuleAll().
Lavorando sulle
ACL in modo più approfondito è possibile raggiungere un livello di controllo e di sicurezza ben più elevato rispetto allo standard normale. Se vogliamo dare accessi a file e/o cartelle ad account già esistenti come il famigerato
ASPNET si può fare così:
FileSystemAccessRule _fsRule = new FileSystemAccessRule(new System.Security.Principal.NTAccount(“Caruso\\ASPNET”),
FileSystemRights.Read | FileSystemRights.Write,
AccessControlType.Allow);
Questo è un esempio comune e utile per chi programma Web Application in
ASP.NET. Infatti spesso è necessario dare diritti di Modifica alla cartella contentente i database di
Access. Ricordo che per
IIS 5.0/5.1 l'utente a cui dare i diritti è
ASPNET mentre su
IIS 6.0 e quindi
Windows 2003 l'utente è
NETWORK SERVICE.
Conclusioni
L'utilizzo di queste classi per la gestione delle
ACL credo sia molto importante per chi lavora normalmente con file e directory, ma in particolare riveste una particolare rilevanza l'esplorazione e la conoscenza del namespace
Security.AccessControl che ha molteplici classi per varie soluzioni.