Тема: VBS & WMI: замена объекта класса Win32_Truste в DACL каталога
Продолжение темы VBS & WMI: безопасность NTFS для каталога, DACL (чтение, изменение).
Сценарий 6.
Замена объекта класса "Win32_Trustee" в списке управления доступом NTFS (DACL) заданного каталога текущего компьютера с сохранением настроек, унаследованных от "родителя".
Смысловое назначение сценария состоит в том, чтобы удалить текущую привязку записи DACL к некоторой пользовательской учётной записи, а затем привязать эту же запись DACL к другой пользовательской учётной записи. При этом тип, область действия и маска доступа записи DACL не изменяются.
Результат работы сценария аналогичен результату процедуры удаления некоторой записи DACL, а затем создания такой же по типу, области действия и маске доступа записи DACL, но соответствующей иной учётной записи пользователя.
Предполагается, что участвующие в процедуре пользовательские учётные записи, во-первых, являются доменными, во-вторых, принадлежат одному и тому же домену.
Сценарий способен работать и в графическом, и в консольном режимах.
Dim objWsNet, objFS, objWMI
Dim strDomain, strBaseFolder, blnContinue, xResult
Dim strAccountOld, strSIDOld, strAccountNew, strSIDNew
strAccountOld = "user1": strAccountNew = "user2"
strBaseFolder = "C:\Temp"
Set objWsNet = CreateObject("WScript.Network")
strDomain = objWsNet.UserDomain
Set objWsNet = Nothing
Set objFS = CreateObject("Scripting.FileSystemObject")
On Error Resume Next
Set objWMI = GetObject("winmgmts:\\.\root\cimv2")
If Err.Number = 0 Then
If objFS.FolderExists(strBaseFolder) Then
If StrComp(strDomain & "\" & strAccountOld, strDomain & "\" & strAccountNew, vbTextCompare) <> 0 Then
Set objAccount = objWMI.Get("Win32_UserAccount.Domain='" & strDomain & "',Name='" & strAccountOld & "'")
If Err.Number = 0 Then
strSIDOld = UCase(objAccount.SID)
Set objAccount = objWMI.Get("Win32_UserAccount.Domain='" & strDomain & "',Name='" & strAccountNew & "'")
If Err.Number = 0 Then
strSIDNew = UCase(objAccount.SID)
xResult = Change_Trustee(objWMI, strDomain, strAccountOld, strSIDOld, strAccountNew, strSIDNew, strBaseFolder)
WScript.Echo strAccountOld & " <-> " & strAccountNew & ": " & xResult
Else
WScript.Echo strAccountNew & " -> не найдена учётная запись объекта"
End If
Else
WScript.Echo strAccountOld & " -> не найдена учётная запись объекта"
Err.Clear
End If
Set objAccount = Nothing
Else
WScript.Echo strAccountOld & " <-> " & strAccountNew & ": бессмысленная операция"
End If
Else
WScript.Echo "Не найден путь " & UCase(strBaseFolder)
End If
Else
WScript.Echo "Ошибка " & Err.Number & " при подключении к WMI-пространству" & vbNewLine & Err.Description
Err.Clear
End If
Set objWMI = Nothing
Set objFS = Nothing
WScript.Quit 0
'======
Function Change_Trustee(objWMIServ, strDom, strSAN1, strSID1, strSAN2, strSID2, strDir)
Dim objSecSettings, objSD, objItem, blnHasInherited
Dim objSID, objTrustee, arrACE, arrLines, xRes, i, j
Const SE_DACL_PROTECTED = 4096 'Флаг-признак отключенного режима наследования управляемым каталогом безопасности NTFS от "родителя"
Const INHERITED_ACE = 16 'Флаг-признак того, что текущая запись DACL унаследована от "родителя"
On Error Resume Next
xRes = 0
Set objSecSettings = objWMIServ.Get("Win32_LogicalFileSecuritySetting.Path='" & strDir & "'")
If Err.Number = 0 Then
If objSecSettings.GetSecurityDescriptor(objSD) = 0 Then
If Not IsNull(objSD.DACL) Then
If Not CBool(objSD.ControlFlags And SE_DACL_PROTECTED) Then blnHasInherited = True
arrACE = Array(): i = -1: arrLines = Array(): j = -1
'--- Выборка из исходного DACL записей, не унаследованных от "родителя",
'и поиск среди них (по SID) тех, которые привязаны к заменяемой пользовательской "учётке"
For Each objItem In objSD.DACL
If Not CBool(objItem.AceFlags And INHERITED_ACE) Then
If UCase(objItem.Trustee.SIDString) = strSID1 Then
j = j + 1
ReDim Preserve arrLines(j)
arrLines(j) = i + 1
End If
i = i + 1
ReDim Preserve arrACE(i)
Set arrACE(i) = objItem
End If
Next
Set objItem = Nothing
'------
If j >= 0 Then
If blnHasInherited Then
'--- Отключение наследования настроек безопасности от "родителя"
objSD.ControlFlags = objSD.ControlFlags + SE_DACL_PROTECTED
xRes = objSecSettings.SetSecurityDescriptor(objSD)
'------
End If
If xRes = 0 Then
'--- Создание экземпляра класса "Win32_Trustee",
'привязанного к заменяющей пользовательской "учётке"
Set objSID = objWMI.Get("Win32_SID.SID='" & strSID2 & "'")
Set objTrustee = objWMIServ.Get("Win32_Trustee").Spawninstance_
objTrustee.Domain = strDom
objTrustee.Name = strSAN2
objTrustee.SID = objSID.BinaryRepresentation
objTrustee.SidLength = objSID.SidLength
objTrustee.SIDString = strSID2
Set objSID = Nothing
'------
'--- Замена объекта класса "Win32_Trustee" у обрабатываемых записей DACL
For j = 0 To UBound(arrLines)
arrACE(arrLines(j)).Trustee = objTrustee
Next
'------
objSD.DACL = arrACE 'собственно изменение DACL
Erase arrACE: Erase arrLines
'--- Включение наследования настроек безопасности от "родителя", если первоначально оно было включено
If blnHasInherited Then objSD.ControlFlags = objSD.ControlFlags - SE_DACL_PROTECTED
'------
'--- Итоговое сохраненение изменений, внесённых в дескриптор безопасности
xRes = objSecSettings.SetSecurityDescriptor(objSD)
Select Case xRes
Case 0: xRes = "успешное завершение"
Case 2: xRes = "не удалось сохранить изменения DACL (доступ запрещён)"
Case 5, 9: xRes = "не удалось сохранить изменения DACL (для выполнения операции недостаточно полномочий)"
Case 21: xRes = "не удалось сохранить изменения DACL (заданы недопустимые значения параметров)"
Case Else: xRes = "не удалось сохранить изменения DACL (неизвестная ошибка)"
End Select
'------
Else
xRes = "не удалось отключить наследование безопасности"
End If
Else
xRes = "не обнаружено не унаследованных записей исходного объекта"
End If
Set objTrustee = Nothing
Else
xRes = "список управления доступом пуст"
End If
Else
xRes = "не удалось прочитать дескриптор безопасности объекта"
End If
Set objSD = Nothing
Set objSecSettings = Nothing
Else
xRes = "ошибка " & CStr(Err.Number) & vbNewLine & Err.Description
Err.Clear
End If
On Error GoTo 0
Change_Trustee = xRes
End Function
Примечания.
1. Работа сценария проверена в 32-битных версиях: 2000 Pro. + SP4/XP Pro. + SP3/2008 Std. + SP2/7 Pro. + SP1
2. Сценарий ориентирован на использование в русифицированных ОС.