Зміна власника папки або файлу PowerShell (частина 2) - PKI Extensions

Якось давно Олександр Станкевич просив у мене варіант скрипту, який змінював би власника файлу або папки з PowerShell. Свого часу я займався цим питанням і результатом моїх досліджень:

Я для вирішення цієї задачі вирішив використовувати класWin32_LogicalFileSecuritySetting (хоча, можна і Win32_Directory використовувати але після дрібного доопрацювання. Але про це я висловлюся наприкінці статті).

Отже, класWin32_LogicalFileSecuritySetting має самі методи, як і інші класи, які працюють зі списками ACL - GetSecurityDescriptor і SetSecurityDescriptor. Я вже неодноразово порушував питання роботи з SecurityDescriptor в PowerShell, тому приступимо відразу до вирішення завдання.

Як видно з картинки, нас буде цікавити об'єктOwner таControlFlags. Об'єктDACL нас не цікавитиме зовсім, тому працювати з Win32_Ace нам не доведеться, а тільки з Trustee:

Далі слідує стандартна процедура перетворення імені користувача в SID та отримання байтового масиву з SID'а:

Тепер $SIDArray та ім'я користувача запишемо в Trustee і помістимо цей об'єкт у властивість Owner дескриптора безпеки:

Для того, щоб замінити власника папки, потрібно заповнити об'єкт Control Flags, які описані тут: http://msdn.microsoft.com/en-us/library/aa394402(VS.85).aspx. Не впевнений, що варто заглиблюватися в цей момент (на практиці дуже рідко доводиться користуватися ним), тому скажу, що нас зацікавить прапорSE_SELF_RELATIVE. Заповнюється він одним рядком:

Його можна записувати як десяткове число (32768 ), так і в HEX нотації. Я використовую HEX. Ось і все, дескриптор безпеки у нас готовий. Тепер саме час отримати ACL у форматі SecurityDescriptor з наявної папки:

В Options крімвключення привілеїв можна вказувати імперсоналізацію користувача (Impersonate) та інші параметри. Щоб переглянути доступні властивості, достатньо набрати в консолі:

Коли привілеї увімкнені, можна вже записувати дескриптор у папку за допомогою методу SetSecurityDescriptor:

Якщо ім'я папки вказано правильно, то у виведенніReturnValue має повернути значення0, що означає, що власник змінено! :rock: і ми невеликим (але для PowerShell'а це вже багато, враховуючи що багато речей у ньому робляться в один рядок ;-) ) збільшенням обсягу коду можемо повноцінно змінювати власника файлу або папки без встановлення додаткових розширень, як PSCX або окремих консольних утиліт, як SubInAcl чи SetAcl.

Тепер це все окультурити в готовий скрипт:

Примітка:При вказівці шляху, який містить прогалини, шлях потрібно укладати в лапки!

і трохи про стандартність використання методів SetSecurityDescriptor для різних об'єктів. Мені не зрозуміло, чому в різних класах WMI використовуються різні імена властивостей дескриптора безпеки, коли в цьому явних причин немає? Наприклад:

  • Win32_Share для дескриптора використовує властивістьAccess методу SetShareInfo
  • Win32_Printer використовує властивістьDescriptor методу SetSecurityDescriptor
  • Win32_Directory використовуєSecurityDescriptor метод SetSecurityDescriptor (і для SetSecurityDescrptorEx)
  • Win32_LogicalFileSecuritySetting використовуєDescriptor метод SetSecurityDescriptor

Ось 4 WMI класу управління ACL списками різних об'єктів, з якими я нещодавно працював і маємо 3 різних іменування властивості дескриптора безпеки та Win32_Share використовує навіть іншу назву методу (SetShareInfo), хоча цей методвикористовує той самий Win32_SecurityDescriptor. Але це вже офтопік та особисті роздуми. Ось :)