PSNetShare – ACL

Jak ostatnio pisałem dziś skupię się na omówieniu klasy Win32_SecurityDescriptor w celu tworzenia Access List do naszych udostępnianych zasobów. Obiekty tej klasy same w sobie nie zawierają wiele na pierwszy rzut oka jasnych danych:

class Win32_SecurityDescriptor : __SecurityDescriptor
{
  uint32        ControlFlags;
  Win32_ACE     DACL[];
  Win32_Trustee Group;
  Win32_Trustee Owner;
  Win32_ACE     SACL[];
};

Dlatego by móc zrobić cokolwiek interesującego będziemy musieli posłużyć się kolejnymi dwoma klasami Win32_Ace – odpowiadającej za nadawanie uprawnień oraz Win32_Trustee – odpowiadającej za identyfikowanie użytkownika.

Na początek jednak stwórzmy sobie listę użytkowników i ich praw.

$Users = "G1\Administrator", "G1\mg"
$Rights = "F", "R"

Następnie przygotowujemy obiekty typu ACE oraz Trustee dla każdego z użytkowników. Do tego celu posłużymy się pętlą foreach

Foreach($user in $Users) {  ...  }

Na wstępie jednak sprawdzamy czy aby na pewno tacy użytkownicy istnieją.

$Account = New-Object system.security.principal.ntaccount($user)
$SID = $Account.Translate([system.security.principal.securityidentifier])

Niestety klasa Win32_Trustee wymaga aby SID był przedstawiony w postaci binarnej tablicy. Dlatego preparujemy odpowiednio SID.

[byte[]]$BinarySID = ,0 * $SID.BinaryLength
$SID.GetBinaryForm($BinarySID,0)

Rozdzielamy nazwę domeny od użytkownika

$Domain = $user.Split("\")[0]
$UserName = $user.Split("\")[1]

Posiadając tak przygotowane dane możemy przystąpić do stworzenia obiektu Trustee, któremu nadajemy odpowiednie wartości.

$objTrustee = [WMIClass] "Win32_Trustee"
$trustee = $objTrustee.CreateInstance()
$trustee.Domain = $Domain
$trustee.Name = $UserName
$trustee.SID = $BinarySID

Zanim jednak stworzymy obiekt ACE musimy dowiedzieć się nieco o AceFlags i AceType. Do tego celu najlepiej zapraszam do dokumentacji na stronie MSDN. W skrócie określają one typ dostępu oraz flagę ustalającą rodzaj dziedziczenia uprawnień.

#ACE Flags
$ACETYPE_ACCESS_ALLOWED = 0
$ACETYPE_ACCESS_DENIED = 1
$ACETYPE_SYSTEM_AUDIT = 2
$ACEFLAG_OBJECT_INHERIT_ACE = 1
$ACEFLAG_CONTAINER_INHERIT_ACE = 2
$ACEFLAG_NO_PROPAGATE_INHERIT_ACE = 4
$ACEFLAG_INHERIT_ONLY_ACE = 8
$ACEFLAG_INHERITED_ACE = 16
$ACEFLAG_SUCCESSFUL_ACCESS = 64
$ACEFLAG_FAILED_ACCESS = 128

Następnie dekodujemy nasze uprawnienia.

switch -exect ($Rights[$i])
{
  "R" {$Access = 1179817} # Read
  "C" {$Access = 1245631} # Change
  "F" {$Access = 2032127} # Full
}

Teraz możemy stworzyć kolejny obiekt – ACE i przypisać do niego odpowiednie wartości.

$objACE = [WMIClass] "Win32_Ace"
$ace = $objACE.CreateInstance()
$ace.AccessMask = $Access
$ace.AceFlags = $ACEFLAG_CONTAINER_INHERIT_ACE
$ace.AceType = $ACETYPE_ACCESS_ALLOWED
$ace.Trustee = $trustee

Po udanym przetworzeniu danych przypisujemy je do tablicy w celu zajęcia się następnym uzytkownikiem.

[Array]$ACL += $ace

Całość wygląda następująco.

#ACE Flags
$ACETYPE_ACCESS_ALLOWED = 0
$ACETYPE_ACCESS_DENIED = 1
$ACETYPE_SYSTEM_AUDIT = 2</p>
$ACEFLAG_OBJECT_INHERIT_ACE = 1
$ACEFLAG_CONTAINER_INHERIT_ACE = 2
$ACEFLAG_NO_PROPAGATE_INHERIT_ACE = 4
$ACEFLAG_INHERIT_ONLY_ACE = 8
$ACEFLAG_INHERITED_ACE = 16
$ACEFLAG_SUCCESSFUL_ACCESS = 64
$ACEFLAG_FAILED_ACCESS = 128

$i=0
Foreach($user in $Users)
{
  if($user)
  {
    #Get user SID
    $Account = New-Object system.security.principal.ntaccount($user)
    $SID = $Account.Translate([system.security.principal.securityidentifier])
    [byte[]]$BinarySID = ,0 * $SID.BinaryLength
    $SID.GetBinaryForm($BinarySID,0)

    $Domain = $user.Split("\")[0]
    $UserName = $user.Split("\")[1]

    #Create User Trustee
    $objTrustee = [WMIClass] "Win32_Trustee"
    $trustee = $objTrustee.CreateInstance()
    $trustee.Domain = $Domain
    $trustee.Name = $UserName
    $trustee.SID = $BinarySID

    $Access = 1179817           # Default set to Read
    switch -exect ($Rights[$i])
    {
      "R" {$Access = 1179817} # Read
      "C" {$Access = 1245631} # Change
      "F" {$Access = 2032127} # Full
    }

    #Create User ACE
    $objACE = [WMIClass] "Win32_Ace"
    $ace = $objACE.CreateInstance()
    $ace.AccessMask = $Access
    $ace.AceFlags = $ACEFLAG_CONTAINER_INHERIT_ACE
    $ace.AceType = $ACETYPE_ACCESS_ALLOWED
    $ace.Trustee = $trustee

    [Array]$ACL += $ace
  }
  $i++
}

Mając tak spreparowaną access listę możemy przystąpić do wtórzenia obiekty SecurityDescriptor.

$objSD = [WMIClass] "Win32_SecurityDescriptor"
$SD = $objSD.CreateInstance()

Zmieniamy typ naszej ACL na discretionary access control list (DACL) i przypisujemy ją obiektowi SecurityDescriptor’a.

[System.Management.ManagementObject[]] $DACL = $ACL
$SD.DACL = $DACL

Następnie pozostaje nam tylko użyć tak spreparowanej listy dostępu podczas udostępniania kolejnego zasobu.

$objNetShare = [WMIClass] "Win32_Share"
$objNetShare.Create('C:\Users\mg\Desktop\Nowy folder', 'Test', 0, 10, 'Testowy zasob', '', $SD)

Natomiast aby zmodyfikować uprawnienia istniejącego zasobu odnajdujemy go i wykorzystujemy metodę SetShareInfo.

$objNetShare = Get-WmiObject -class Win32_Share  -Filter "name='Test'"
$objNetShare.SetShareInfo(10,'Zmodyfikowany testowy zasób', $SD)

Źródło:
http://msdn.microsoft.com/en-us/library/aa394402(v=vs.85).aspx
http://msdn.microsoft.com/en-us/library/aa394063(VS.85).aspx
http://msdn.microsoft.com/en-us/library/aa394501(VS.85).aspx

Reklamy

Skomentuj

Wprowadź swoje dane lub kliknij jedną z tych ikon, aby się zalogować:

Logo WordPress.com

Komentujesz korzystając z konta WordPress.com. Wyloguj / Zmień )

Zdjęcie z Twittera

Komentujesz korzystając z konta Twitter. Wyloguj / Zmień )

Zdjęcie na Facebooku

Komentujesz korzystając z konta Facebook. Wyloguj / Zmień )

Zdjęcie na Google+

Komentujesz korzystając z konta Google+. Wyloguj / Zmień )

Connecting to %s