Member 11866893 Ответов: 2

Удаление осиротевших sids VB.NET


Я пытаюсь создать программу для удаления осиротевших Sid из пользовательских папок. То, что у меня есть, может перечислить осиротевшие Sid и перечислить их в списке, но не очищает их от ACL. Вот что у меня есть до сих пор:

Imports System.ComponentModel
Imports System.IO
Imports System.Security.AccessControl
Imports System.Security.Principal
Imports System.Threading

Public Class Form1
    Dim bw As BackgroundWorker = New BackgroundWorker
    Public Delegate Sub PictureVisibilityDelegate(ByVal visibility As Boolean)
    Dim ChangePictureVisibility As PictureVisibilityDelegate

    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        AddHandler bw.DoWork, AddressOf bw_DoWork
        AddHandler bw.RunWorkerCompleted, AddressOf bw_RunWorkerCompleted
        ChangePictureVisibility = AddressOf ChangeVisibility
        TextBox1.Focus()
    End Sub
    '-----------------------------------------------Go Button Click--------------------------------------------------
    Private Sub BtnGo_Click(sender As Object, e As EventArgs) Handles BtnGo.Click
        Me.Invoke(ChangePictureVisibility, True)
        Me.BtnGo.Enabled = False
        Me.BtnClear.Enabled = False
        Me.BtnExit.Enabled = True
        If Not bw.IsBusy = True Then
            bw.RunWorkerAsync()
        End If
    End Sub
    '-----------------------------------------------Folder Browser Selection-----------------------------------------
    Private Sub FoldBrowse_Click(sender As Object, e As EventArgs) Handles FoldBrowse.Click
        If FolderBrowserDialog1.ShowDialog() = DialogResult.OK Then
            Me.TextBox1.Text = FolderBrowserDialog1.SelectedPath
        End If
    End Sub

    Private Sub BtnClear_Click(sender As Object, e As EventArgs) Handles BtnClear.Click
        TextBox1.Text = ""
    End Sub
    '-----------------------------------------------Exit Button Click--------------------------------------------------
    Private Sub BtnExit_Click(sender As Object, e As EventArgs) Handles BtnExit.Click
        If bw.IsBusy Then
            'If it supports cancellation, Cancel It  
            If bw.WorkerSupportsCancellation Then
                ' Tell the Background Worker to stop working.  
                bw.CancelAsync()
            End If
        End If

        ' Disable Buttons  
        Me.BtnExit.Enabled = False
        Me.Close()
    End Sub
    '-----------------------------------------------Background Worker--------------------------------------------------
    Private Sub bw_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs)
        CheckForIllegalCrossThreadCalls = False
        Dim setFolder As String = TextBox1.Text
        HandleDir(setFolder)
    End Sub


    '-----------------------------------------------Background Work Completed------------------------------------------
    Private Sub bw_RunWorkerCompleted(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs)
        ' Enable Buttons 
        WaitStatus.Close()
        Me.BtnGo.Enabled = True
        Me.BtnClear.Enabled = True
        Me.Refresh()
        MessageBox.Show("Orphaned SID Cleaner has finished cleaning your selection.", "Orphaned SID Cleaner", MessageBoxButtons.OK, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1, MessageBoxOptions.ServiceNotification, False)
    End Sub
    '-----------------------------------------------Check if log file is in use----------------------------------------
    Public Function FileInUse(ByVal sFile As String) As Boolean
        If System.IO.File.Exists(sFile) Then
            Try
                Dim F As Short = FreeFile()
                FileOpen(F, sFile, OpenMode.Binary, OpenAccess.ReadWrite, OpenShare.LockReadWrite)
                FileClose(F)
            Catch
                Return True
            End Try
        End If
    End Function
    '-----------------------------------------------Recursion---------------------------------------------------------
    Sub HandleDir(Path As String)
        Dim dinfo As New DirectoryInfo(TextBox1.Text)
        Dim dSecurity As DirectorySecurity = dinfo.GetAccessControl(AccessControlSections.All)
        Try
            If FileInUse("c:\orphansid.txt") = True Then
                Thread.Sleep(2)
                My.Computer.FileSystem.WriteAllText("c:\orphansid.txt", "Scanning:" & Path & vbCrLf, True)
            Else
                My.Computer.FileSystem.WriteAllText("c:\orphansid.txt", "Scanning:" & Path & vbCrLf, True)
                Thread.Sleep(2)
            End If

            Dim security As DirectorySecurity = Directory.GetAccessControl(Path)
            Dim rules = security.GetAccessRules(True, False, GetType(SecurityIdentifier))

            'Tracks the SIDs to remove
            Dim removeList = New List(Of IdentityReference)()
            For Each rule In rules.OfType(Of FileSystemAccessRule)()
                Try
                    Dim account = rule.IdentityReference.Translate(GetType(NTAccount))
                Catch generatedExceptionName As IdentityNotMappedException
                    'Assume invalid so remove it
                    If Not removeList.Any(Function(sid) sid.Value = rule.IdentityReference.Value) Then
                        removeList.Add(rule.IdentityReference)

                    End If
                End Try
            Next
            'Remove all rules associated with the given SID
            For Each id In removeList
                'Remove all permissions
                If FileInUse("c:\orphansid.txt") = True Then
                    Thread.Sleep(2)
                    ListBox1.Items.Add("Removed the following SID:" & id.ToString & " From " & Path & vbCrLf)
                    My.Computer.FileSystem.WriteAllText("c:\orphansid.txt", "Removed the following SID:" & id.ToString & " From " & Path & vbCrLf, True)
                Else
                    ListBox1.Items.Add("Removed the following SID:" & id.ToString & " From " & Path & vbCrLf)
                    My.Computer.FileSystem.WriteAllText("c:\orphansid.txt", "Removed the following SID:" & id.ToString & " From " & Path & vbCrLf, True)
                    Thread.Sleep(2)
                End If
                Dim DirACLs As New Security.AccessControl.DirectorySecurity(Path, AccessControlSections.All)

                DirACLs.PurgeAccessRules(id)
                'dSecurity.PurgeAccessRules(id)
                dinfo.SetAccessControl(dSecurity)
            Next

            For Each subdir As String In System.IO.Directory.GetDirectories(Path)
                HandleDir(subdir)
            Next subdir
        Catch ex As System.Exception

        End Try
    End Sub

    Public Sub ChangeVisibility(ByVal visibility As Boolean)
        WaitStatus.Show()
    End Sub
End Class 


Часть, которая не очищает SID, - это:

'Remove all rules associated with the given SID
            For Each id In removeList
                'Remove all permissions
                If FileInUse("c:\orphansid.txt") = True Then
                    Thread.Sleep(2)
                    ListBox1.Items.Add("Removed the following SID:" & id.ToString & " From " & Path & vbCrLf)
                    My.Computer.FileSystem.WriteAllText("c:\orphansid.txt", "Removed the following SID:" & id.ToString & " From " & Path & vbCrLf, True)
                Else
                    ListBox1.Items.Add("Removed the following SID:" & id.ToString & " From " & Path & vbCrLf)
                    My.Computer.FileSystem.WriteAllText("c:\orphansid.txt", "Removed the following SID:" & id.ToString & " From " & Path & vbCrLf, True)
                    Thread.Sleep(2)
                End If
                Dim DirACLs As New Security.AccessControl.DirectorySecurity(Path, AccessControlSections.All)

                DirACLs.PurgeAccessRules(id)
                'dSecurity.PurgeAccessRules(id)
                dinfo.SetAccessControl(dSecurity)
            Next


Я хочу, чтобы программа очистила осиротевший SID, а затем внесла его в список и имела возможность скопировать список осиротевших Sid в буфер обмена.

Может ли кто-нибудь помочь мне выяснить, почему это работает не так, как я хочу, и/или найти альтернативное решение?

Что я уже пробовал:

Я попробовал код, приведенный выше, и он успешно перечисляет осиротевшие Sid и добавляет их в список в нужном мне формате, но он не очищает осиротевшие Sid.

2 Ответов

Рейтинг:
4

Member 11866893

Этот инструмент находит потерянные SID в верхних каталогах данного пути, становится владельцем и очищает ACL, а затем добавляет в ACL 2 группы администраторов. Он удаляет наследование перед добавлением групп администраторов. После добавления групп администраторов он исправляет файл desktop.ini (проблема в нашей среде), а затем сбрасывает право собственности на администратора. Мне пришлось делать длинные перерывы между изменением ACL, потому что по какой-то причине наследование не распространялось на подкаталоги, поэтому я просто делал длинные перерывы между ними, чтобы дать каждому время закончить работу над ACL, и, похоже, это помогло. Это не добавляет так много времени выполнения, потому что не так много потерянных пользовательских каталогов, и работа выполняется только на потерянных SID.

Try
            Dim security As DirectorySecurity = Directory.GetAccessControl(Path)
            Dim rules = security.GetAccessRules(True, False, GetType(SecurityIdentifier))
            'Add SIDs to be removed to a list
            Dim removeList = New List(Of IdentityReference)()
            For Each rule In rules.OfType(Of FileSystemAccessRule)()
                Try
                    'Attempt to resolve SID
                    Dim account = rule.IdentityReference.Translate(GetType(NTAccount))
                Catch generatedExceptionName As IdentityNotMappedException
                    'If the exception is thrown then add SID to the list
                    If Not removeList.Any(Function(sid) sid.Value = rule.IdentityReference.Value) Then
                        ChangeOwner(Path)
                        removeList.Add(rule.IdentityReference)
                        Dim dinfo1 As New DirectoryInfo(Path)
                        Dim DirACLs As New Security.AccessControl.DirectorySecurity(Path, AccessControlSections.All)
                        For Each oAccessRule As System.Security.AccessControl.FileSystemAccessRule In DirACLs.GetAccessRules(True, False, GetType(SecurityIdentifier))
                            DirACLs.PurgeAccessRules(oAccessRule.IdentityReference)
                            dinfo1.SetAccessControl(DirACLs)
                        Next
                        Threading.Thread.Sleep(1000)
                        removeinherit(Path)
                        Threading.Thread.Sleep(10000)
                        SetNetWorkerPerms(Path)
                        Threading.Thread.Sleep(10000)
                        SetAdmin1Perms(Path)
                        Threading.Thread.Sleep(10000)
                        removeINI(Path)
                        Threading.Thread.Sleep(1000)
                        resetadmin(Path)
                    End If
                End Try
            Next
            'Display and log entries on the list then remove them from the ACL
            Using logWriter As New StreamWriter("c:\orphansid.txt", True)
                For Each id In removeList
                    ListBox1.Items.Add("Removed the following SID:  " & id.ToString & " From " & Path & vbCrLf)
                    logWriter.WriteLine("Removed the following SID: {0} From {1}", id, Path)
                Next
            End Using


Рейтинг:
20

Richard Deeming

У вас есть два разных DirectorySecurity объекты, смотрящие на один и тот же путь - dSecurity и DirACLs.

Вам очистить списки от DirACLs пример. Затем вы применяете правила из dSecurity в директорию. Но, поскольку вы не изменили dSecurity например, никаких изменений не будет.

Либо очистить правила от dSecurity например, или установите ACL в DirACLs пример.

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

Вы также можете избежать открытия и закрытия файла журнала каждый раз, когда вы пишете в него.

If removeList.Count <> 0 Then
    Dim DirACLs As New Security.AccessControl.DirectorySecurity(Path, AccessControlSections.All)
    
    Using logWriter As New StreamWriter("c:\orphansid.txt", true)
        For Each id In removeList
            logWriter.WriteLine("Removed the following SID: {0} From {1}", id, Path)
            DirACLs.PurgeAccessRules(id)
        Next
    End Using
    
    dinfo.SetAccessControl(DirACLs)
End If


Member 11866893

Я попробовал код, который вы выложили с dsecurity и diracls. Я также попробовал использовать dinfo. setaccesscontrol(desecurity) так, как вы его разместили, а также внутри цикла. Он все еще просто находит осиротевший sid и правильно отображает его в списке, а также регистрирует его, но не удаляет.

Если удалить список.Тогда считайте < & gt; 0
- Тусклые Дираклы Как Новая Охрана.Фильтр accesscontrol.DirectorySecurity(Path, AccessControlSections. All)
Использование logWriter в качестве нового StreamWriter("c:\orphansid.txt", правда)
Для каждого идентификатора в removeList
Список listbox1.Предметы.Добавить("удалить следующие Сида:" &амп; ИД.Метод toString &ампер; " от " &амп; путь &ампер; vbCrLf)
планируются.WriteLine ("удален следующий SID: {0} из {1}", id, Path)
dSecurity.PurgeAccessRules(id)
dinfo. SetAccessControl(dSecurity)
Следующий
Конец Использования
Конец, Если

Я администратор домена и запускаю программу с повышенными привилегиями. Есть идеи, что еще я могу сделать не так?

Richard Deeming

Этот поток StackOverflow[^] имеет почти такой же код в C#, и OP утверждает, что он работает.

Вы уверены, что правила не наследуются из родительской папки?

Member 11866893

Я снова запущу его в одной папке пользователя,а затем вручную проверю, не является ли проблема проблемой наследования. Я не думаю, что это потому, что я выбираю родительскую папку, которая f:\user1 с FolderBrowserDialog и каждый пользователь имеет папку под user1. Он правильно находит и отображает пользовательские папки. У меня есть все подпапки и файлы, наследуемые в папке пользователя, наследующие разрешения от папки пользователя, которая отображается правильно, а не от user1. Я дам вам знать. Я только программировал, так что вполне возможно, что я мог бы упустить что-то подобное.

Member 11866893

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

Member 11866893

Возможно, вы что-то напутали с наследством. Я посмотрел GetAccessRules это объяснение Microsoft сказал:
GetAccessRules государственной функции (includeExplicit как логическое, includeInherited как логический, формат как тип)


Поэтому я изменил эту строку кода: Dim rules = security.GetAccessRules (True, False, GetType(SecurityIdentifier))
to: Dim rules = безопасность.GetAccessRules(True, True, GetType(SecurityIdentifier))

До сих пор я вижу, что is не отображал результаты правильно. Это был только поиск осиротевшего Сида в каждом верхнем каталоге. Он все еще работает, но теперь он отображает все подкаталоги под каждым верхним каталогом. Так что, надеюсь, причина, по которой он не удалял его, заключалась в том, что наследование было установлено для каждой папки пользователя, и флаг, который был установлен в false, заставлял его работать не так, как я хотел. Когда он закончит, я дам вам знать, если это было проблемой.

Member 11866893

никакая радость. что слишком откроется подкаталоги с сиротами малых островных развивающихся государств. У меня есть инструмент, который очищает все записи в ACL, я могу попытаться использовать его и просто очистить все и вернуть только группы администраторов домена. Я не думаю, что простое удаление осиротевшего Сида когда-либо сработает. ничто из того, что я пробовал до сих пор, не приблизилось к работе. если другой код работает, я опубликую обновление и закрою вопрос.

Member 11866893

Хорошо, я придумал обходной путь, который отвечает моим потребностям в пользовательских каталогах. Мне все еще нужно будет выяснить, как удалить один осиротевший SID из ACL, чтобы я мог использовать его в групповых каталогах, но пока это работает хорошо. Код размещен ниже. Спасибо за помощь в том, что вы написали, помогло мне устранить неполадки и придумать часть решения ниже.