check if OU is protected from accidental deletion

3.6k Views Asked by At

I was working with OU's and just trying to find out

Is there any way I can check whether OU is protected from accidental deletion or not?

I googled it but couldn't found any solution.

I am looking for solution in C# not scripting.

Thanks in advance

5

There are 5 best solutions below

0
On

You could do a simple line in powershell with active directory cmdlet Get-ADObject -Filter * -Properties ProtectedFromAccidentalDeletion | where {$_.ProtectedFromAccidentalDeletion -eq $true}

And later if you want to change it - pipe it to | Set-ADObject -ProtectedFromAccidentalDeletion:$false

0
On

You need to open the ACL on the object (the ntSecurityDescriptor attribute) and look for a Deny Everyone Delete. The ActiveDirectorySecurity class gives you a managed wrapper around this - http://msdn.microsoft.com/en-us/library/system.directoryservices.activedirectorysecurity.aspx.

4
On

Check the systemFlags attribute. The MS page on ADS_SYSTEMFLAG_ENUM there is C++ example, it should be easy to adapt it for C#.

0
On

To protect an AD object there are two ACEs neccessary. One is "deny Delete + DeleteTree" which must be set on the object to protect, the second one "deny DeleteChild" must be set on the parent object. If the protection should removed, only the ACE on the object must deleted. The ACE on the parent object must remain, because otherwise other objects in the same OU will not protected anymore!

Here ist my Code which is working perfectly:

    //using System.Security.Principal
    //using System.DirectoryServices;


    public static void SetProtectADObject(DirectoryEntry ent, bool Protect = true)
    {
        //get parent object
        var parentEnt = new DirectoryEntry(ent.Parent.Path);

        //refresh objects
        ent.RefreshCache();
        parentEnt.RefreshCache();

        if (Protect)
        {
            #region Protect
            try
            {
                IdentityReference everyOneAccount = new NTAccount("Everyone").Translate(typeof(SecurityIdentifier)); //S-1-1-0
                var objAce = new ActiveDirectoryAccessRule(everyOneAccount, ActiveDirectoryRights.Delete | ActiveDirectoryRights.DeleteTree, AccessControlType.Deny);
                var parentAce = new ActiveDirectoryAccessRule(everyOneAccount, ActiveDirectoryRights.DeleteChild, AccessControlType.Deny);

                //check if ace present on object
                var objACL = ent.ObjectSecurity;
                bool acePresent = false;
                foreach (ActiveDirectoryAccessRule ace in objACL.GetAccessRules(true, false, typeof(NTAccount)))
                {
                    if (ace.IdentityReference.Value == "Everyone")
                    {
                        if (ace.ActiveDirectoryRights == (ActiveDirectoryRights.DeleteTree | ActiveDirectoryRights.Delete)) { acePresent = true; break; }
                        else if (ace.ActiveDirectoryRights == (ActiveDirectoryRights.DeleteChild | ActiveDirectoryRights.DeleteTree | ActiveDirectoryRights.Delete)) { acePresent = true; break; }
                    }
                }

                if (!acePresent)
                {
                    //set ace to object
                    objACL.AddAccessRule(objAce);

                    //commit changes
                    ent.CommitChanges();
                }

                //check if ace present on parent object
                var parentACL = parentEnt.ObjectSecurity;
                bool parentAcePresent = false;
                foreach (ActiveDirectoryAccessRule ace in parentACL.GetAccessRules(true, false, typeof(NTAccount)))
                {
                    if (ace.IdentityReference.Value == "Everyone")
                    {
                        if (ace.ActiveDirectoryRights == (ActiveDirectoryRights.DeleteChild)) { parentAcePresent = true; break; }
                        else if (ace.ActiveDirectoryRights == (ActiveDirectoryRights.DeleteChild | ActiveDirectoryRights.DeleteTree | ActiveDirectoryRights.Delete)) { parentAcePresent = true; break; }
                    }
                }

                if (!parentAcePresent)
                {
                    //set ace to parent object
                    parentACL.AddAccessRule(parentAce);

                    //commit changes
                    parentEnt.CommitChanges();
                }
            }
            catch (Exception ex)
            {
                throw new Exception(string.Format("Error protecting object {0}", ent.Path), ex);
            }
            #endregion
        }
        else
        {
            #region Unprotect
            //to remove the protection we remove only the ACE from the object, not from the parent. 
            //The ACE on the parent must be in place because otherwise other objects on the same level will not protected anymore!

            try
            {
                IdentityReference everyOneAccount = new NTAccount("Everyone").Translate(typeof(SecurityIdentifier)); //S - 1 - 1 - 0
                var objAce = new ActiveDirectoryAccessRule(everyOneAccount, ActiveDirectoryRights.Delete | ActiveDirectoryRights.DeleteTree, AccessControlType.Deny);

                //check if ace present on object
                var objACL = ent.ObjectSecurity;
                bool acePresent = false;
                foreach (ActiveDirectoryAccessRule ace in objACL.GetAccessRules(true, false, typeof(NTAccount)))
                {
                    if (ace.IdentityReference.Value == "Everyone")
                    {
                        if (ace.ActiveDirectoryRights == (ActiveDirectoryRights.DeleteTree | ActiveDirectoryRights.Delete)) { acePresent = true; break; }
                        else if (ace.ActiveDirectoryRights == (ActiveDirectoryRights.DeleteChild | ActiveDirectoryRights.DeleteTree | ActiveDirectoryRights.Delete)) { acePresent = true; break; }
                    }
                }

                //set ace to object
                if (acePresent)
                {
                    ent.ObjectSecurity.RemoveAccessRule(objAce);
                    ent.CommitChanges();
                }
            }
            catch (Exception ex)
            {
                throw new Exception(string.Format("Error unprotecting object {0}", ent.Path), ex);
            }
            #endregion 
        }
    }

    public static bool IsADObjectProtected(DirectoryEntry ent)
    {
        //get parent object
        var parentEnt = new DirectoryEntry(ent.Parent.Path);

        //refresh objects
        ent.RefreshCache();
        parentEnt.RefreshCache();

        //get current ACLs
        ActiveDirectorySecurity acl = ent.ObjectSecurity;
        ActiveDirectorySecurity parentAcl = ent.Parent.ObjectSecurity;
        AuthorizationRuleCollection rules = acl.GetAccessRules(true, true, typeof(NTAccount));
        AuthorizationRuleCollection parentRules = parentAcl.GetAccessRules(true, false, typeof(NTAccount));

        //check object acl
        bool acePresent = false;
        foreach (ActiveDirectoryAccessRule ace in rules)
        {
            Console.WriteLine(ace.AccessControlType.ToString());
            if (ace.AccessControlType == AccessControlType.Deny)
            {
                if (ace.ActiveDirectoryRights == (ActiveDirectoryRights.DeleteTree | ActiveDirectoryRights.Delete)) { acePresent = true; break; }
                else if (ace.ActiveDirectoryRights == (ActiveDirectoryRights.DeleteChild | ActiveDirectoryRights.DeleteTree | ActiveDirectoryRights.Delete)) { acePresent = true; break; }
            }
        }

        //check parent acl
        bool parentAcePresent = false;
        foreach (ActiveDirectoryAccessRule ace in parentRules)
        {
            if (ace.AccessControlType == AccessControlType.Deny)
            {
                if (ace.ActiveDirectoryRights == (ActiveDirectoryRights.DeleteChild)) { parentAcePresent = true; break; }
                else if (ace.ActiveDirectoryRights == (ActiveDirectoryRights.DeleteChild | ActiveDirectoryRights.DeleteTree | ActiveDirectoryRights.Delete)) { parentAcePresent = true; break; }
            }
        }

        return parentAcePresent && acePresent;
    }
0
On

Here is a code snippet for getting the OU and finding the ACL that determines if it is protected from accidental deletion.
This is using the [System.DirectoryServices], [System.Security.AccessControl] and [System.Security.Principal] namespaces

bool? protected = null;
DirectoryEntry de = new DirectoryEntry("LDAP://OU=TestOu,DC=Test,DC=Local", "Username", "Password");
ActiveDirectorySecurity ads = de.ObjectSecurity;
AuthorizationRuleCollection rules = ads.GetAccessRules(true, true, typeof(NTAccount);
foreach (ActiveDirectoryAccessRule rule in rules)
    if (rule.AccessControlType == AccessControlType.Deny)
        if (rule.ActiveDirectoryRights == (ActiveDirectoryRights.DeleteChild | ActiveDirectoryRights.DeleteTree | ActiveDirectoryRights.Delete))
            protected = true;
        else
            protected = false;

I ran this against one of my root OUs with over 150 ACLs applied and it returned the answer in a second or two.