Active Directory

Remove DNS NS Records after demoting domain controller with PowerShell

 

Get-DnsServerZone | ForEach-Object { Get-DnsServerResourceRecord -ZoneName $_.ZoneName -RRType Ns | Where-Object {$_.RecordData.NameServer -like ‘DCName.fqdn.com.‘} | Remove-DnsServerResourceRecord -ZoneName $_.ZoneName -Confirm:$false }

 

Replace the bold test with the fully qualified domain name of the name server. Don’t forget to keep the period at the end of it as well.

Remove DNS NS Records after demoting domain controller with PowerShell Read More »

Directory Services–Cannot Change Password – Constraint Violation nTSecurityDescriptor

 

Recently I ran into an issue where trying to enable or disable the option ‘Cannot Change Password’ in Active Directory in my C# code. Using a Domain Administrator account the code worked perfectly fine, but when it was run under a non-administrator I would get “Constrain Violation Occurred” and the following exception

"0000051B: AtrErr: DSID-030F22B2, #1:\n\t0: 0000051B: DSID-030F22B2, problem 1005 (CONSTRAINT_ATT_TYPE), data 0, Att 20119 (nTSecurityDescriptor)\n"

Now the user in question was delegated full control over the user object which made it more frustrating as it could be done manually within Active Directory Users and Computers. What I did find out is that if the non-administrator user was assigned the owner of the user in the security option the code would work and is what lead me to the answer.

 

You must have the DirectoryEntry.Options.SecurityMasks defined to SecurityMasks.Dacl for it to work for a non-administrator user.

 

Allow Change Password

   1: public static void AllowChangePassword(DirectoryEntry user)

   2:        {

   3:            user.Options.SecurityMasks = SecurityMasks.Dacl;

   4:  

   5:            // Create a Guid that identifies the Change Password right.

   6:            Guid changePasswordGuid =

   7:                new Guid("{AB721A53-1E2F-11D0-9819-00AA0040529B}");

   8:  

   9:            // Get the ActiveDirectorySecurity for the user.

  10:            ActiveDirectorySecurity userSecurity = user.ObjectSecurity;

  11:  

  12:            // Create a SecurityIdentifier object for "everyone".

  13:            SecurityIdentifier everyoneSid =

  14:                new SecurityIdentifier(WellKnownSidType.WorldSid, null);

  15:  

  16:            // Create a SecurityIdentifier object for "self".

  17:            SecurityIdentifier selfSid =

  18:                new SecurityIdentifier(WellKnownSidType.SelfSid, null);

  19:  

  20:            // Create an access rule to allow everyone the change password 

  21:            // right. 

  22:            // This is used to remove any existing access rules.

  23:            ActiveDirectoryAccessRule allowEveryone =

  24:                new ActiveDirectoryAccessRule(

  25:                    everyoneSid,

  26:                    ActiveDirectoryRights.ExtendedRight,

  27:                    AccessControlType.Allow,

  28:                    changePasswordGuid);

  29:  

  30:            // Create an access rule to deny everyone the change password right.

  31:            ActiveDirectoryAccessRule denyEveryone =

  32:                new ActiveDirectoryAccessRule(

  33:                    everyoneSid,

  34:                    ActiveDirectoryRights.ExtendedRight,

  35:                    AccessControlType.Deny,

  36:                    changePasswordGuid);

  37:  

  38:            // Create an access rule to allow self the change password right.

  39:            // This is used to remove any existing access rules.

  40:            ActiveDirectoryAccessRule allowSelf =

  41:                new ActiveDirectoryAccessRule(

  42:                    selfSid,

  43:                    ActiveDirectoryRights.ExtendedRight,

  44:                    AccessControlType.Allow,

  45:                    changePasswordGuid);

  46:  

  47:            // Create an access rule to deny self the change password right.

  48:            ActiveDirectoryAccessRule denySelf =

  49:                new ActiveDirectoryAccessRule(

  50:                    selfSid,

  51:                    ActiveDirectoryRights.ExtendedRight,

  52:                    AccessControlType.Deny,

  53:                    changePasswordGuid);

  54:  

  55:            // Remove any existing rule that gives "everyone" the change 

  56:            // password right.

  57:            userSecurity.RemoveAccessRuleSpecific(denyEveryone);

  58:  

  59:            // Add a new access rule to deny "everyone" the change password 

  60:            // right.

  61:            userSecurity.AddAccessRule(allowEveryone);

  62:  

  63:            // Remove any existing rule that gives "self" the change password 

  64:            // right.

  65:            userSecurity.RemoveAccessRuleSpecific(denySelf);

  66:  

  67:            // Add a new access rule to deny "self" the change password right.

  68:            userSecurity.AddAccessRule(allowSelf);

  69:  

  70:            // Commit the changes.

  71:            user.CommitChanges();

  72:  

  73:            user.Options.SecurityMasks = SecurityMasks.None;

  74:        }

 

Deny Change Password

   1: public static void DenyChangePassword(DirectoryEntry user)

   2:       {

   3:           user.Options.SecurityMasks = SecurityMasks.Dacl;

   4:           

   5:           // Create a Guid that identifies the Change Password right.

   6:           Guid changePasswordGuid =

   7:               new Guid("{AB721A53-1E2F-11D0-9819-00AA0040529B}");

   8:  

   9:           // Get the ActiveDirectorySecurity for the user.

  10:           ActiveDirectorySecurity userSecurity = user.ObjectSecurity;

  11:  

  12:           // Create a SecurityIdentifier object for "everyone".

  13:           SecurityIdentifier everyoneSid =

  14:               new SecurityIdentifier(WellKnownSidType.WorldSid, null);

  15:  

  16:           // Create a SecurityIdentifier object for "self".

  17:           SecurityIdentifier selfSid =

  18:               new SecurityIdentifier(WellKnownSidType.SelfSid, null);

  19:  

  20:           // Create an access rule to allow everyone the change password 

  21:           // right. 

  22:           // This is used to remove any existing access rules.

  23:           ActiveDirectoryAccessRule allowEveryone =

  24:               new ActiveDirectoryAccessRule(

  25:                   everyoneSid,

  26:                   ActiveDirectoryRights.ExtendedRight,

  27:                   AccessControlType.Allow,

  28:                   changePasswordGuid);

  29:  

  30:           // Create an access rule to deny everyone the change password right.

  31:           ActiveDirectoryAccessRule denyEveryone =

  32:               new ActiveDirectoryAccessRule(

  33:                   everyoneSid,

  34:                   ActiveDirectoryRights.ExtendedRight,

  35:                   AccessControlType.Deny,

  36:                   changePasswordGuid);

  37:  

  38:           // Create an access rule to allow self the change password right.

  39:           // This is used to remove any existing access rules.

  40:           ActiveDirectoryAccessRule allowSelf =

  41:               new ActiveDirectoryAccessRule(

  42:                   selfSid,

  43:                   ActiveDirectoryRights.ExtendedRight,

  44:                   AccessControlType.Allow,

  45:                   changePasswordGuid);

  46:  

  47:           // Create an access rule to deny self the change password right.

  48:           ActiveDirectoryAccessRule denySelf =

  49:               new ActiveDirectoryAccessRule(

  50:                   selfSid,

  51:                   ActiveDirectoryRights.ExtendedRight,

  52:                   AccessControlType.Deny,

  53:                   changePasswordGuid);

  54:  

  55:           // Remove any existing rule that gives "everyone" the change 

  56:           // password right.

  57:           userSecurity.RemoveAccessRuleSpecific(allowEveryone);

  58:  

  59:           // Add a new access rule to deny "everyone" the change password 

  60:           // right.

  61:           userSecurity.AddAccessRule(denyEveryone);

  62:  

  63:           // Remove any existing rule that gives "self" the change password 

  64:           // right.

  65:           userSecurity.RemoveAccessRuleSpecific(allowSelf);

  66:  

  67:           // Add a new access rule to deny "self" the change password right.

  68:           userSecurity.AddAccessRule(denySelf);

  69:  

  70:           // Commit the changes.

  71:           user.CommitChanges();

  72:  

  73:           user.Options.SecurityMasks = SecurityMasks.None;

  74:       }

Directory Services–Cannot Change Password – Constraint Violation nTSecurityDescriptor Read More »

Check group membership from AD with Foreign Security Principals

The following code will check if a user is a member of a specific group. This will work with a domain trust and Foreign Security Principals.

See the update below!

groupName = The sAMAccountName of the group you want to check the members of.
SearchDomain = This is the FQDN that you will be searching for the group. Ex: contoso.com
userName = This is the sAMAccountName of the user that you are checking if they are part of the group.
userDomain = This is the NetBIOS name of the domain of the user that you are checking. This really only comes into play when you are checking a user from a domain trust. Ex. CONTOSO
UserIsNativeDomain = This is true if the user you are checking is in the SearchDomain. If this is false, the user is in a domain trust and the code should be looking for the Foreign Security Principal and matching it to the userDomain and userName.

static bool CheckIfGroupMember(string groupName, string SearchDomain, string userName, string userDomain, bool UserIsNativeDomain)

        {

            bool GroupMember = false;                         

            string UserDN = string.Empty;           

            string FullLogonName = userDomain + "\\" + userName;

 

           if (UserIsNativeDomain == true)               

            {

                try //Get User's distinguishedName

                {                    

                    System.DirectoryServices.DirectoryEntry entry2 = new System.DirectoryServices.DirectoryEntry("LDAP://" + SearchDomain);

                    System.DirectoryServices.DirectorySearcher mySearcher2 = new System.DirectoryServices.DirectorySearcher(entry2);

                    mySearcher2.Filter = "(&(objectCategory=person)(ObjectClass=user)(sAMAccountName=" + userName + "))";

                    mySearcher2.PageSize = 1000;

                    System.DirectoryServices.SearchResult sr2 = mySearcher2.FindOne();

                    if (sr2 != null)

                    {

                        System.DirectoryServices.DirectoryEntry de2 = sr2.GetDirectoryEntry();

                        UserDN = de2.Properties["distinguishedName"].Value.ToString();

                        de2.Close();

                    }

                }

                catch (DirectoryServicesCOMException e2) { Console.Write(e2.Message); }

            }

 

            try //Check Group Membership

            {

                System.DirectoryServices.DirectoryEntry entry = new System.DirectoryServices.DirectoryEntry("LDAP://" + SearchDomain);

                System.DirectoryServices.DirectorySearcher mySearcher = new System.DirectoryServices.DirectorySearcher(entry);

                mySearcher.Filter = "(&(objectCategory=group)(sAMAccountName=" + groupName + "))";

                mySearcher.PageSize = 1000;

                System.DirectoryServices.SearchResult sr = mySearcher.FindOne();

                System.DirectoryServices.DirectoryEntry de = sr.GetDirectoryEntry();

 

                object[] members = (object[])de.Properties["member"].Value;

                foreach (object member in members)

                {

                    if (UserIsNativeDomain == false &&

                        member.ToString().Contains("CN=S-1-5"))   //If group member is a Foreign Security Principal

                    {

                        if (GetUserNameOfFSP(member.ToString()).ToLower() == FullLogonName.ToLower())

                        {

                            GroupMember = true;

                            break;

                        }

 

                    }

                    else

                    {

                        if (member.ToString().ToLower() == UserDN)

                        {

                            GroupMember = true;

                            break;

                        }

                    }

                }

                de.Close();

                return GroupMember;

            }

            catch (DirectoryServicesCOMException e) { Console.Write(e.Message); }

            return GroupMember;

        }

UPDATE 5/19/14: While working on an Active Directory Migration project using ADMT I found an issue with the code above. If you’re migrating a user from the source domain who is a member in a group in the target domain already it uses a Foreign Security Principal. Well after the ADMT migrates the user to the target domain, the user still shows as a Foreign Security Principal in the target domains group but with an updated domain name in the ForeignSecurityPrincipal OU. This new code will resolve that issue and handle it as necessary.

groupName = The sAMAccountName of the group you want to check the members of.

groupDomain = This is the FQDN that you will be searching for the group. Ex: contoso.com

userName = This is the sAMAccountName of the user that you are checking if they are part of the group.

userDomain = This is the NetBIOS name of the domain of the user that you are checking. Ex. CONTOSO

static bool CheckIfGroupMember(string groupName, string groupDomain, string userName, string userDomain)

{          

    bool GroupMember = false;

    string UserDN = string.Empty;

    string FullLogonName = userDomain + "\\" + userName;

 

    try //Get User's distinguishedName

    {

        DirectoryEntry entry2 = new DirectoryEntry("LDAP://" + userDomain);

        DirectorySearcher mySearcher2 = new DirectorySearcher(entry2);

        mySearcher2.Filter = "(&(objectCategory=person)(ObjectClass=user)(sAMAccountName=" + userName + "))";

        mySearcher2.PageSize = 1000;

        SearchResult sr2 = mySearcher2.FindOne();

        if (sr2 != null)

        {

            DirectoryEntry de2 = sr2.GetDirectoryEntry();

            UserDN = de2.Properties["distinguishedName"].Value.ToString();

            de2.Close();

        }

        entry2.Close();

    }

    catch (DirectoryServicesCOMException e2) { Console.Write(e2.Message); }

  

 

    try //Check Group Membership

    {

        DirectoryEntry entry = new DirectoryEntry("LDAP://" + groupDomain);

        DirectorySearcher mySearcher = new DirectorySearcher(entry);

        mySearcher.Filter = "(&(objectCategory=group)(sAMAccountName=" + groupName + "))";

        mySearcher.PageSize = 1000;

        SearchResult sr = mySearcher.FindOne();

        DirectoryEntry de = sr.GetDirectoryEntry();

 

        object[] members = (object[])de.Properties["member"].Value;

        foreach (object member in members)

        {

            if (member.ToString().Contains("CN=S-1-5"))

            {

                string FSPName = GetUserNameOfFSP(member.ToString().ToLower());

                if (FSPName.ToLower() == FullLogonName.ToLower())

                {

                    GroupMember = true;

                    break;

                }

            }

            else

            {

                if (member.ToString().ToLower() == UserDN.ToLower())

                {

                    GroupMember = true;

                    break;

                }

            }                

        }             

    }

    catch (DirectoryServicesCOMException e) { Console.Write(e.Message); }

 

    return GroupMember;

}

Check group membership from AD with Foreign Security Principals Read More »

Get username and domain of Foreign Security Principal from domain trust

You can use this code to determine the DOMAIN\username from the Foreign Security Principal which is really the SID of the account. Pass the full distinguishedName of the ForeignSecurityPrincipal.

static string GetUserNameOfFSP(string ForeignSecurityPrincipal)

       {

           //Returns with syntax of "DOMAIN\logonname"

           try

           {

               DirectoryEntry user = new DirectoryEntry("LDAP://" + ForeignSecurityPrincipal);

               SecurityIdentifier sid = new SecurityIdentifier((byte[])user.InvokeGet("objectSid"), 0);

               NTAccount account = (NTAccount)sid.Translate(typeof(NTAccount));

               return account.ToString();

           }

           catch (DirectoryServicesCOMException e) { Console.Write(e.Message); return "Error"; }

       }

Get username and domain of Foreign Security Principal from domain trust Read More »

Authenticate a user against Active Directory including domain trust

Authenticate a user’s credentials with this code against a domain. This also works with a domain trust.

static bool AuthenticateUser(string userName, string password, string domain)

        {

            bool authentic = false;

            try

            {

                DirectoryEntry entry = new DirectoryEntry("LDAP://" + domain,

                    userName, password);

                object nativeObject = entry.NativeObject;

                authentic = true;

            }

            catch (DirectoryServicesCOMException e) { Console.Write(e.Message); }

            return authentic;

        }

Authenticate a user against Active Directory including domain trust Read More »