1 (изменено: Vasek, 2012-03-29 10:45:04)

Тема: VBScript: Сохранить DACL общего ресурса

Предлагаю для тестирования сценарий, с помощью которого можно делать резервные копии общих ресурсов на сервере. Иногда бывает так что зашифрованный диск подключается, а общие ресурсы не восстанавливаются. Для нормальной работы потребуется создать папки для сохранения файлов резервных копий, в моем примере это c:\scripts\shares\" + dir + "\
    dir - это 1.Пн;2.Вт;3.Ср;4.Чт;5.Пт;6.Сб;7.ВС
Создать задание выполнения этого сценария ежедневно - cscript c:\scripts\shares_backup.vbs

Сценари shares_backup.vbs


WeekDayNumber = WeekDay(Now, vbMonday)

If WeekDayNumber = 1 Then
	dir="1.Пн"
ElseIf WeekDayNumber = 2 Then
	dir="2.Вт"
ElseIf WeekDayNumber = 3 Then
	dir="3.Ср"
ElseIf WeekDayNumber = 4 Then
	dir="4.Чт"
ElseIf WeekDayNumber = 5 Then
	dir="5.Пт"
ElseIf WeekDayNumber = 6 Then
	dir="6.Сб"
ElseIf WeekDayNumber = 7 Then
	dir="7.ВС"
End If

Set fso = WScript.CreateObject("Scripting.FileSystemObject")
Set oWMI = GetObject("winmgmts:")
Set oShares = oWMI.ExecQuery("select Name,Path from Win32_Share where Type=0") 
Set OpenLogFile = Fso.OpenTextFile("c:\scripts\shares\" + dir + "\Recover_Shares.vbs",2,True,-2)

n = 0
On Error Resume Next
For Each oShare In oShares

	Set oShareSecSetting = GetObject("winmgmts:Win32_LogicalShareSecuritySetting.Name='" + oShare.Name + "'") 
	iRC = oShareSecSetting.GetSecurityDescriptor(oSecurityDescriptor) 
	aDACL = oSecurityDescriptor.DACL
	myArray = myArray + "," + Chr(34) + oShare.Name + Chr(34)
	myArray1 = myArray1 + "," + cstr(oSecurityDescriptor.ControlFlags)
	myArray10 = myArray10 + "," + Chr(34) + oShare.Path + Chr(34)
	myArray2 = ""
	myArray3 = ""
	myArray4 = ""
	myArray5 = ""
	myArray6 = ""
	myArray7 = ""
	myArray8 = ""

	For Each oAce In aDACL
		myArray2 = myArray2 + "," + cstr(oAce.AccessMask)
		myArray3 = myArray3 + "," + cstr(oAce.AceType)
		myArray4 = myArray4 + "," + cstr(oAce.AceFlags)
		Set oTrustee = oAce.Trustee
		If not isNull(oTrustee.Domain) Then
			myArray5 = myArray5 + "," + Chr(34) + oTrustee.Domain + Chr(34)
		Else
			myArray5 = myArray5 + "," + Chr(34) + "Null" + Chr(34)
		End If
		If not isNull(oTrustee.Name) Then
			myArray6 = myArray6 + "," + Chr(34) + oTrustee.Name + Chr(34)
		Else 
			myArray6 = myArray6 + "," + Chr(34) + "Null" + Chr(34)
		End If
		myArray7 = myArray7 + "," + cstr(oAce.Trustee.SidLength)
		myArray8 = myArray8 + "," + Chr(34) + oAce.Trustee.SIDString + Chr(34)
		myArray9 = myArray9 + "," + Chr(34) + oAce.Trustee.SIDString + Chr(34)
	Next
	
	myArrayA = Mid(myArray,2,len(myArray) - 1)
	myArrayA1 = Mid(myArray1,2,len(myArray1) - 1)
	myArrayA10 = Mid(myArray10,2,len(myArray10) - 1)
	myArrayA2 = Mid(myArray2,2,len(myArray2) - 1)
	myArrayA3 = Mid(myArray3,2,len(myArray3) - 1)
	myArrayA4 = Mid(myArray4,2,len(myArray4) - 1)
	myArrayA5 = Mid(myArray5,2,len(myArray5) - 1)
	myArrayA6 = Mid(myArray6,2,len(myArray6) - 1)
	myArrayA7 = Mid(myArray7,2,len(myArray7) - 1)
	myArrayA8 = Mid(myArray8,2,len(myArray8) - 1)
	myArrayU = myArrayU + ",ArrAMask" + cstr(n)
	myArrayU1 = myArrayU1 + ",ArrAType" + cstr(n)
	myArrayU2 = myArrayU2 + ",ArrAFlags" + cstr(n)
	myArrayU3 = myArrayU3 + ",ArrADom" + cstr(n)
	myArrayU4 = myArrayU4 + ",ArrAName" + cstr(n)
	myArrayU5 = myArrayU5 + ",ArrATrSidL" + cstr(n)
	myArrayU6 = myArrayU6 + ",ArrATrSIDStr" + cstr(n)
	OpenLogFile.WriteLine "ArrAMask" + cstr(n) + " = Array(" + myArrayA2 + ")"
	OpenLogFile.WriteLine "ArrAType" + cstr(n) + " = Array(" + myArrayA3 + ")"
	OpenLogFile.WriteLine "ArrAFlags" + cstr(n) + " = Array(" + myArrayA4 + ")"
	OpenLogFile.WriteLine "ArrADom" + cstr(n) + " = Array(" + myArrayA5 + ")"
	OpenLogFile.WriteLine "ArrAName" + cstr(n) + " = Array(" + myArrayA6 + ")"
	OpenLogFile.WriteLine "ArrATrSidL" + cstr(n) + " = Array(" + myArrayA7 + ")"
	OpenLogFile.WriteLine "ArrATrSIDStr" + cstr(n) + " = Array(" + myArrayA8 + ")" + VbCrLf
	n = n + 1
	
Next

OpenLogFile.WriteLine "myArrayF = Array(" + Mid(myArrayU,2,len(myArrayU) - 1) + ")"
OpenLogFile.WriteLine "myArrayF1 = Array(" + Mid(myArrayU1,2,len(myArrayU1) - 1) + ")"
OpenLogFile.WriteLine "myArrayF2 = Array(" + Mid(myArrayU2,2,len(myArrayU2) - 1) + ")"
OpenLogFile.WriteLine "myArrayF3 = Array(" + Mid(myArrayU3,2,len(myArrayU3) - 1) + ")"
OpenLogFile.WriteLine "myArrayF4 = Array(" + Mid(myArrayU4,2,len(myArrayU4) - 1) + ")"
OpenLogFile.WriteLine "myArrayF5 = Array(" + Mid(myArrayU5,2,len(myArrayU5) - 1) + ")"
OpenLogFile.WriteLine "myArrayF6 = Array(" + Mid(myArrayU6,2,len(myArrayU6) - 1) + ")"
OpenLogFile.WriteLine "ArrName = Array(" + myArrayA + ")"
OpenLogFile.WriteLine "ArrPath = Array(" + myArrayA10 + ")"
OpenLogFile.WriteLine "ArrCtrlF = Array(" + myArrayA1 + ")"
OpenLogFile.WriteLine VbCr
OpenLogFile.WriteLine "Set objWMIService = GetObject(" + Chr(34) + "winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2" + Chr(34) + ")" + VbCrLf
OpenLogFile.WriteLine "On Error Resume Next" + VbCrLf
OpenLogFile.WriteLine "Set Shares = objWMIService.ExecQuery(" + Chr(34) + "SELECT Name FROM Win32_Share Where Type=0" + Chr(34) + ")" + VbCrLf
OpenLogFile.WriteLine "For Each Share in Shares" + VbCrLf
OpenLogFile.WriteLine VbTab + "Share.Delete()" + VbCrLf
OpenLogFile.WriteLine "Next" + VbCrLf
OpenLogFile.WriteLine "for x = 0 to UBound(ArrName)" + VbCrLf
OpenLogFile.WriteLine"Set objSecDescriptor = objWMIService.Get(" + Chr(34) + "Win32_SecurityDescriptor" + Chr(34) + ").Spawninstance_()" + VbCrLf
OpenLogFile.WriteLine "objSecDescriptor.ControlFlags = ArrCtrlF(x)" + VbCrLf
OpenLogFile.WriteLine "Set objNewShare = objWMIService.Get(" + Chr(34) + "Win32_Share" + Chr(34) + ")" + VbCrLf
OpenLogFile.WriteLine "objNewShare.Create ArrPath(x), ArrName(x), 0, max,,,objSecDescriptor" + VbCrLf
OpenLogFile.WriteLine "Set objDictionary = CreateObject(" + Chr(34) + "Scripting.Dictionary" + Chr(34) + ")" + VbCrLf
OpenLogFile.WriteLine VbTab + "for y = 0 to UBound(myArrayF(x))" + VbCrLf
OpenLogFile.WriteLine VbTab + "Set objShareSecSetting = objWMIService.Get(" + Chr(34) + "Win32_LogicalShareSecuritySetting.Name='" + Chr(34) + " " + Chr(43) + " ArrName(x) " + Chr(43) + " " + Chr(34) + "'" + Chr(34) + ")" + VbCrLf
OpenLogFile.WriteLine VbTab + VbTab + "set ACE = SetACE(myArrayF(x)(y), myArrayF2(x)(y),myArrayF1(x)(y), SetTrustee(myArrayF3(x)(y),myArrayF4(x)(y),myArrayF5(x)(y),myArrayF6(x)(y)))" + VbCrLf
OpenLogFile.WriteLine VbTab + VbTab + "If not isNull(objSecDescriptor.DACL) Then" + VbCrLf
OpenLogFile.WriteLine VbTab + VbTab + VbTab + "For i = LBound(objSecDescriptor.DACL) to UBound(objSecDescriptor.DACL)" + VbCrLf
OpenLogFile.WriteLine VbTab + VbTab + VbTab + VbTab + "objDictionary.Add i, objSecDescriptor.DACL(i)" + VbCrLf
OpenLogFile.WriteLine VbTab + VbTab + VbTab + "Next" + VbCrLf
OpenLogFile.WriteLine VbTab + VbTab + VbTab + "objDictionary.Add y, ACE" + VbCrLf
OpenLogFile.WriteLine VbTab + VbTab + "Else" + VbCrLf
OpenLogFile.WriteLine VbTab + VbTab + VbTab + "objDictionary.Add y, ACE" + VbCrLf
OpenLogFile.WriteLine VbTab + VbTab + "End If" + VbCrLf
OpenLogFile.WriteLine VbTab + "Next" + VbCrLf
OpenLogFile.WriteLine VbTab + "objSecDescriptor.DACL = objDictionary.Items" + VbCrLf
OpenLogFile.WriteLine VbTab + "returnval = objShareSecSetting.SetSecurityDescriptor(objSecDescriptor)" + VbCrLf
OpenLogFile.WriteLine VbTab + "Set objDictionary = nothing" + VbCrLf
OpenLogFile.WriteLine "Next"
OpenLogFile.WriteLine VbCr
OpenLogFile.WriteLine "Function SetTrustee(strDomain, strName, SidL, SidS)" + VbCrLf
OpenLogFile.WriteLine VbTab + "set objTrustee = getObject(" + Chr(34) + "Winmgmts:{impersonationlevel=impersonate}!root/cimv2:Win32_Trustee" + Chr(34) + ").Spawninstance_" + VbCrLf
OpenLogFile.WriteLine VbTab + "objTrustee.Domain = strDomain" + VbCrLf
OpenLogFile.WriteLine VbTab + "objTrustee.Name = strName" + VbCrLf
OpenLogFile.WriteLine VbTab + "objTrustee.SidLength = SidL" + VbCrLf
OpenLogFile.WriteLine VbTab + "objTrustee.SIDString = SidS" + VbCrLf
OpenLogFile.WriteLine VbTab + "set SetTrustee = objTrustee" + VbCrLf
OpenLogFile.WriteLine "End Function"
OpenLogFile.WriteLine VbCr
OpenLogFile.WriteLine "Function SetACE(AccessMask, AceFlags, AceType, objTrustee)" + VbCrLf
OpenLogFile.WriteLine VbTab + "set objACE = getObject(" + Chr(34) + "Winmgmts:{impersonationlevel=impersonate}!root/cimv2:Win32_Ace" + Chr(34) + ").Spawninstance_" + VbCrLf
OpenLogFile.WriteLine VbTab + "objACE.AccessMask = AccessMask" + VbCrLf
OpenLogFile.WriteLine VbTab + "objACE.AceFlags = AceFlags" + VbCrLf
OpenLogFile.WriteLine VbTab + "objACE.AceType = AceType" + VbCrLf
OpenLogFile.WriteLine VbTab + "objACE.Trustee = objTrustee" + VbCrLf
OpenLogFile.WriteLine VbTab + "set SetACE = objACE" + VbCrLf
OpenLogFile.WriteLine "End Function" + VbCrLf
OpenLogFile.WriteLine "Wscript.Echo " + Chr(34) + "Завершено восстановление общих ресурсов" + Chr(34) + VbCrLf
OpenLogFile.WriteLine "Wscript.quit"

Примечания.
Если будут реализованы все условия, сценарий будет создавать(перезаписывать) в каждой папке дня недели файл Recover_Shares.vbs, в котором будет храниться вся информация о ресурсах на время после запуска задания по расписанию. Если после подключения диска общие ресурсы не восстановятся то можно будет запустить этот файл для восстановления общих ресурсов.
Работа сценария проверена в:
XP Pro SP3, server 2003 Std/Ent R2 SP2, server 2008 Std/Ent sp2, server 2008 Std R2 sp1
Все ОС русской редакции

2 (изменено: Dmitrii, 2012-03-26 16:22:16)

Re: VBScript: Сохранить DACL общего ресурса

Проверил на XP Pro+SP3 (впрочем, не особенно тщательно). Работает.
Однако предложу несколько советов.

1. Фраза "... резервные копии общих ресурсов на сервере..." вводит в заблуждение. Ожидается, что предложенный сценарий будет выполнять копирование содержимого папок общего доступа, а на деле выполняется сохранение информации о составе и DACL SMB-разрешений этих папок.

2. По-моему, Вы выбрали избыточный способ решения задачи.
Думается, что вполне достаточно иметь один сценарий восстановления набора (и, соответственно, DACL) общих ресурсов, которому в качестве входных данных "скармливать" сохранённые в виде файла данные заведомо известной структуры. Причём все необходимые сведения о каждой папке я бы постарался уместить в одной строке.

3. SID записей в ACL (а, следовательно, и их байтовые длины) сохранять не стоит, т.к. соответствующих объектов может уже не существовать на момент процедуры восстановления. Здесь вполне достаточно иметь пару значений в формате "Domain\Name", для которой уже и получать "на лету" необходимые сведения о SID. Такой подход вполне можно использовать даже по отношению к "хорошо известным идентификаторам безопасности".
Можно, конечно, применить и комбинированный вариант.

4. Вы забыли, что для корректно созданного экземпляра класса "Win32_Trustee" следовало бы заполнить свойство
uint8 SID[].

5. В процессе восстановления я бы не стал предварительно удалять всю информацию о существующей на текущий момент структуре общих папок. Думается, что корректнее будет восстановить лишь то, что отсутствует (ну, может быть, ещё проверить корректность ACL действующих ресурсов).
Впрочем, вариант "всё удалить, а потом заново создать", конечно, проще.

3

Re: VBScript: Сохранить DACL общего ресурса

Dmitrii пишет:

1. Фраза "... резервные копии общих ресурсов на сервере..." вводит в заблуждение. Ожидается, что предложенный сценарий будет выполнять копирование содержимого папок общего доступа…

Точно! Я именно так и понял.

4

Re: VBScript: Сохранить DACL общего ресурса

Спасибо за советы,
1. В селдующий раз буду точнее задавать название теме.
2. По поводу избыточного способа решения задачи это было сделано не только для разрабочика но и для рядового специалиста, чтобы у него не составило не какого труда разобраться со готовым сценарием, несколько сценариев нужно для того чтобы восстановить DACL более раннего своего состояния, бывает спахватишся а он переписался .
3. По поводу uint8 SID, на сколько я помню он генерировался при создании экземпляра автоматически.
4. По поводу "соответствующих объектов может уже не существовать" - пусть остаются не олицетворенные SID это мне кажется проще делать ручками или дополнительным сценарием. Здесь цель восстановить предыдущее состояние и не чего не потерять.
5. Если есть записаная целая структура, прощее ее восстановить с нуля(создается новый DACL), бывает что все общие папки есть а доступа нет, не однократно сталкивался с такой проблемой, перезагружаешь службу сервер ситуация остается таже(конечно зависит от Шифровалки), зачем лечить(найти ошибку которую сделала шифровалка в DACL очень сложо) если можно быстро восстановить.

5 (изменено: Dmitrii, 2012-03-28 20:17:01)

Re: VBScript: Сохранить DACL общего ресурса

Vasek пишет:

... несколько сценариев нужно для того чтобы восстановить DACL более раннего своего состояния, бывает спахватишся а он переписался...

Для этого, как раз, вполне достаточно хранить несколько файлов с данными, а обрабатывать их одним универсальным сценарием. Впрочем, это лишь мои личные предпочтения.

Vasek пишет:

4. По поводу "соответствующих объектов может уже не существовать" - пусть остаются не олицетворенные SID <...>
5. Если есть записаная целая структура <...> зачем лечить <...> если можно быстро восстановить.

Дело, разумеется, хозяйское. Но Вы не учитываете того, что не всегда приемлем подобный подход, а сценарий выкладываете в общее пользование без соответствующих комментариев.
Советую их сделать, чтобы какому-нибудь начинающему "сисадмину" в один злосчастный момент не стало весьма досадно за то, что он не учёл этих деталей при использовании данной технологии.

Vasek пишет:

3. По поводу uint8 SID, на сколько я помню он генерировался при создании экземпляра автоматически...

Это утверждение для ряда ситуаций является ложным. Например, XP и 2003 (включая R2) такую автогенерацию выполняют не всегда. Приведу сценарий, результат работы которого на указанных версиях ОС иллюстрирует моё утверждение.


Dim objWMI, objCollection, objItem, objWSNet, objFS
Dim objSD, objSID, objTrustee, objACE, objShare
Dim strDomain, strComputer, strUser, strUserSID, blnHasACE
Const FULL_ACCESS = 2032127
Const ACCESS_ALLOWED = 0
Const strShareName = "Temp"
Const strSharePath = "C:\Temp"

Set objWSNet = CreateObject("WScript.Network")
strDomain = objWSNet.UserDomain
strComputer = objWSNet.ComputerName
strUser = objWSNet.UserName
Set objWSNet = Nothing
Set objFS = CreateObject("Scripting.FileSystemObject")
If objFS.FolderExists(strSharePath) Then
	Set objWMI = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\CIMV2")
	Set objCollection = objWMI.ExecQuery("SELECT SID FROM Win32_UserAccount WHERE Domain='" & strDomain & "' AND Name='" & strUser & "'")
	If objCollection.Count > 0 Then
		For Each objItem In objCollection
			strUserSID = objItem.SID
		Next
		Set objCollection = Nothing
		Set objSID = objWMI.Get("Win32_SID.SID='" & strUserSID & "'")
		Set objTrustee = objWMI.Get("Win32_Trustee").SpawnInstance_
		objTrustee.Domain = strDomain
		objTrustee.Name = strUser
		'objTrustee.SID = objSID.BinaryRepresentation
		objTrustee.SidLength = objSID.SidLength
		objTrustee.SIDString = strUserSID
		Set objSID = Nothing							
		Set objACE = objWMI.Get("Win32_Ace").SpawnInstance_
		objACE.AccessMask = FULL_ACCESS
		objACE.AceFlags = 3
		objACE.AceType = ACCESS_ALLOWED
		objACE.Trustee = objTrustee
		Set objTrustee = Nothing
		Set objSD = objWMI.Get("Win32_SecurityDescriptor").SpawnInstance_
		objSD.DACL = Array(objACE)
        Set objACE = Nothing
		On Error Resume Next
		Set objShare = objWMI.Get("Win32_Share.Name='" & strShareName & "'")
        If Err.Number = 0 Then
            intResult = objShare.SetShareInfo(Null, Null, objSD)
            Select Case intResult
                Case 0
					Wscript.Echo "DACL для SMB-разрешения изменён."
					Set objSecSettings = objWMI.Get("Win32_LogicalShareSecuritySetting.Name='" & strShareName & "'")
					If Err.Number = 0 Then
						If objSecSettings.GetSecurityDescriptor(objSD) = 0 Then
							If IsNull(objSD.DACL) Then
								WScript.Echo "Список управления доступом пуст."
							Else
								For Each objACE In objSD.DACL
									If StrComp(objACE.Trustee.Domain, strDomain, vbTextCompare) = 0 AND StrComp(objACE.Trustee.Name, strUser, vbTextCompare) = 0 Then
										WScript.Echo UCase(objACE.Trustee.Domain & "\" & objACE.Trustee.Name) & vbNewLine & objACE.Trustee.SIDString
										If IsArray(objACE.Trustee.SID) Then
											WScript.Echo "Размерность массива objACE.Trustee.SID = [ " & LBound(objACE.Trustee.SID) & " - " & UBound(objACE.Trustee.SID) & " ]"
										Else
											WScript.Echo "Значение свойства objACE.Trustee.SID не определено."
										End If
										blnHasACE = True
										Exit For
									End If
								Next
								If Not blnHasACE Then WScript.Echo "Запись объекта " & UCase(strDomain & "\" & strUser) & " не найдена."
							End If
						Else
							WScript.Echo "Не удалось прочитать дескриптор безопасности."
						End If
					Else
						WScript.Echo "Ошибка " & Err.Number & vbNewLine & Err.Description
						Err.Clear
					End If
                Case 2: Wscript.Echo "Доступ к объекту запрещён."
                Case 8: Wscript.Echo "Неизвестная ошибка."
                Case 9: Wscript.Echo "Неверное имя."
                Case 10: Wscript.Echo "Неверный уровень."
                Case 21: Wscript.Echo "Неверный параметр."
                Case 22: Wscript.Echo "Попытка создания дубликата ресурса."
                Case 23: Wscript.Echo "Перенаправленный путь."
                Case 24: Wscript.Echo "Неизвестное устройство или путь."
                Case 25: Wscript.Echo "Сетевое имя не найдено."
            End Select
            Set objShare = Nothing
        Else
			Err.Clear
            Wscript.Echo "Объект типа ОБЩАЯ ПАПКА не найден."
        End If
		On Error GoTo 0
        Set objSD = Nothing
	Else
		Wscript.Echo "Не обнаружена учётная запись пользователя " & UCase(strUser)
	End If
Else
	WScript.Echo "Путь " & UCase(strSharePath) & " не найден."
End If
Set objWMI = Nothing
Set objFS = Nothing
WScript.Quit 0

6

Re: VBScript: Сохранить DACL общего ресурса

Vasek пишет:

1. В селдующий раз буду точнее задавать название теме.

Не стоит ждать следующего раза, можно сделать сие прямо сейчас. Под каждым Вашим сообщением есть ссылка «Редактировать», в том числе и под самым первым сообщением темы. При его редактировании станет возможным изменение заголовка темы в нужную сторону.

7

Re: VBScript: Сохранить DACL общего ресурса

Dmitrii,

1.  В вашем примере вы подразумеваете что общая папка есть или нет. Если общая папка не создана зачем вы патаетесь ее найти. Если есть то я использую другие методы  SetSecurityDescriptor метод "SetShareInfo" не для этого нужен, а именно у вас SetShareInfo(Null, Null, objSD) - расписываю входные показатели wbemtest SetShareInfo(Access,Discription,MaximumAllowed) - даже если они не по алфавиту в этом методе нет входного параметра дескриптора безопасности который вы ему подставляете. А вот у метода SetSecurityDescriptor как раз на вход есть параметр "Descriptor". И еще без контрольного флага дискриптор не запишется objSD.ControlFlags.

Ваш пример в рабочем состоянии:


Dim objWMI, objCollection, objItem, objWSNet, objFS
Dim objSD, objSID, objTrustee, objACE, objShare
Dim strDomain, strComputer, strUser, strUserSID, blnHasACE
Const FULL_ACCESS = 2032127
Const ACCESS_ALLOWED = 0
Const strShareName = "Temp"
Const strSharePath = "C:\Temp"
 
Set objWSNet = CreateObject("WScript.Network")
strDomain = objWSNet.UserDomain
strComputer = objWSNet.ComputerName
strUser = objWSNet.UserName
Set objWSNet = Nothing
Set objFS = CreateObject("Scripting.FileSystemObject")
If objFS.FolderExists(strSharePath) Then
    Set objWMI = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\CIMV2")
    Set objCollection = objWMI.ExecQuery("SELECT SID FROM Win32_UserAccount WHERE Domain='" & strDomain & "' AND Name='" & strUser & "'")
    If objCollection.Count > 0 Then
        For Each objItem In objCollection
            strUserSID = objItem.SID
        Next
        Set objCollection = Nothing
        Set objSID = objWMI.Get("Win32_SID.SID='" & strUserSID & "'")
        Set objTrustee = objWMI.Get("Win32_Trustee").SpawnInstance_
        objTrustee.Domain = strDomain
        objTrustee.Name = strUser
        'objTrustee.SID = objSID.BinaryRepresentation
        objTrustee.SidLength = objSID.SidLength
        objTrustee.SIDString = strUserSID
        Set objSID = Nothing                            
        Set objACE = objWMI.Get("Win32_Ace").SpawnInstance_
        objACE.AccessMask = FULL_ACCESS
        objACE.AceFlags = 3
        objACE.AceType = ACCESS_ALLOWED
        objACE.Trustee = objTrustee
        Set objTrustee = Nothing
        Set objSD = objWMI.Get("Win32_SecurityDescriptor").SpawnInstance_
        objSD.DACL = Array(objACE)
'        Set objACE = Nothing
		

		
'        On Error Resume Next
        Set objShare = objWMI.Get("Win32_Share.Name='" & strShareName & "'")
        If Err.Number = 0 Then

			objSD.ControlFlags = 32772
		
			Set objShareSecSetting = objWMI.Get("Win32_LogicalShareSecuritySetting.Name='" + strShareName + "'")
		
			returnval = objShareSecSetting.SetSecurityDescriptor(objSD)

            'intResult = objShare.SetShareInfo(Null, Null, objSD)
            Select Case intResult
                Case 0
                    Wscript.Echo "DACL для SMB-разрешения изменён."
                    Set objSecSettings = objWMI.Get("Win32_LogicalShareSecuritySetting.Name='" & strShareName & "'")
                    If Err.Number = 0 Then
                        If objSecSettings.GetSecurityDescriptor(objSD) = 0 Then
                            If IsNull(objSD.DACL) Then
                                WScript.Echo "Список управления доступом пуст."
                            Else
                                For Each objACE In objSD.DACL
                                    If StrComp(objACE.Trustee.Domain, strDomain, vbTextCompare) = 0 AND StrComp(objACE.Trustee.Name, strUser, vbTextCompare) = 0 Then
                                        WScript.Echo UCase(objACE.Trustee.Domain & "\" & objACE.Trustee.Name) & vbNewLine & objACE.Trustee.SIDString
                                        If IsArray(objACE.Trustee.SID) Then
                                            WScript.Echo "Размерность массива objACE.Trustee.SID = [ " & LBound(objACE.Trustee.SID) & " - " & UBound(objACE.Trustee.SID) & " ]"
                                        Else
                                            WScript.Echo "Значение свойства objACE.Trustee.SID не определено."
                                        End If
                                        blnHasACE = True
                                        Exit For
                                    End If
                                Next
                                If Not blnHasACE Then WScript.Echo "Запись объекта " & UCase(strDomain & "\" & strUser) & " не найдена."
                            End If
                        Else
                            WScript.Echo "Не удалось прочитать дескриптор безопасности."
                        End If
                    Else
                        WScript.Echo "Ошибка " & Err.Number & vbNewLine & Err.Description
                        Err.Clear
                    End If
                Case 2: Wscript.Echo "Доступ к объекту запрещён."
                Case 8: Wscript.Echo "Неизвестная ошибка."
                Case 9: Wscript.Echo "Неверное имя."
                Case 10: Wscript.Echo "Неверный уровень."
                Case 21: Wscript.Echo "Неверный параметр."
                Case 22: Wscript.Echo "Попытка создания дубликата ресурса."
                Case 23: Wscript.Echo "Перенаправленный путь."
                Case 24: Wscript.Echo "Неизвестное устройство или путь."
                Case 25: Wscript.Echo "Сетевое имя не найдено."
            End Select
            Set objShare = Nothing
        Else
            Err.Clear
            Wscript.Echo "Объект типа ОБЩАЯ ПАПКА не найден."
        End If
        On Error GoTo 0
        Set objSD = Nothing
    Else
        Wscript.Echo "Не обнаружена учётная запись пользователя " & UCase(strUser)
    End If
Else
    WScript.Echo "Путь " & UCase(strSharePath) & " не найден."
End If
Set objWMI = Nothing
Set objFS = Nothing
WScript.Quit 0

Пишите с вами интересно пообщаться.

8

Re: VBScript: Сохранить DACL общего ресурса

alexii, Dmitrii,
Хороший у вас форум. Спасибо что тратите на меня свое время. Спасибо что помогаете.

9 (изменено: Dmitrii, 2012-03-29 15:32:33)

Re: VBScript: Сохранить DACL общего ресурса

Vasek пишет:

В вашем примере вы подразумеваете что общая папка есть или нет...

Есть.

Vasek пишет:

... Если общая папка не создана зачем вы патаетесь ее найти...

Затем, что имею привычку проверять наличие объекта перед попыткой выполнения с ним каких-либо действий.

Vasek пишет:

... я использую другие методы...

В данном случае это неважно. Было лишь продемонстрировано утверждение о том, что есть ситуации, в которых автогенерация значения свойства SID класса Win32_Trustee может и не выполняться.
Я, например, предпочитаю по возможности такие ситуации учитывать.

Vasek пишет:

... метод "SetShareInfo" не для этого нужен...

На основании чего сделан такой вывод?


Vasek пишет:

... в этом методе нет входного параметра дескриптора безопасности который вы ему подставляете...

Ошибаетесь: SetShareInfo method of the Win32_Share Class


Vasek пишет:

И еще без контрольного флага дискриптор не запишется...

Вновь ошибаетесь.
Добавьте оператор objSD.ControlFlags = 32772 перед или после оператора objSD.DACL = Array(objACE), но оставьте закомментированным оператор objTrustee.SID = objSID.BinaryRepresentation.
Результат работы сценария не изменится.

Vasek пишет:

Ваш пример в рабочем состоянии...

Мой пример вполне работоспособен в своём исходном виде, но с действующим оператором
objTrustee.SID = objSID.BinaryRepresentation.
Это многократно проверено на практике для набора ОС 2000 Pro + SP4/XP Pro + SP3/2003R2 + SP1(2)/2008 + SP1(2)/7 Pro + SP1.
Если исключить указанный оператор из кода, то работоспособность сценария сохранится без изменений на "осях", более новых, чем  2003R2.
В 2000 система не сможет добавить в DACL заданную запись (сообщит, что соответствующая "учётка" не найдена), но добавит "умолчальные" записи локальной системы и группы локальных администраторов.
В XP - 2003 - DACL станет пустым (о чём и будет сообщено).

10

Re: VBScript: Сохранить DACL общего ресурса

Да пардон увидел в wbemtest что в SetShareInfo есть Access но внутрь не заглянул, странно там в обоих методах есть object:Win32_SecurityDescriptor, о вроде нашел отличия в методе  SetShareInfo в заполнении параметра Access обязательно нужно указывать свойство "BinaryRepresentation" а вот в методе SetSecurityDescriptor это не обязательно, как раз из-за этого это параметр и генерируется сам. К сожалению такой ОС у меня под рукой нет "ОС 2000 Pro + SP4". На остальных ОС мой пример работает.
    У вас мой последний пример не работает?

11

Re: VBScript: Сохранить DACL общего ресурса

Вообщем я так понял мы просто начали спорить про разные методы для которых на вход нужно подать разные параметры для правильной работы. Вы так не считаете?

12

Re: VBScript: Сохранить DACL общего ресурса

Я если о чём и спорю, так лишь о том, насколько надёжно полагаться на автозаполнение свойства SID класса Win32_Trustee.
С моей точки зрения,- ненадёжно. Поэтому я, как уже указывал, предпочитаю по возможности избегать в сценариях таких решений.
Вот, собственно, и всё.

13

Re: VBScript: Сохранить DACL общего ресурса

Не буду с вами спорить, ваш метод надежнее, если честно мне просто лень было обработку для массива добавить