Showing posts with label Active Directory. Show all posts
Showing posts with label Active Directory. Show all posts

Thursday, June 28, 2018

AD Query still returns old user name after user name was changed at domain controller

Symptoms:

Consider the following scenario:

  1. On the domain member computer, an application calls the LsaLookupSids function to translate a security identifier (SID) to a user name.
  2. The user name has been changed on a domain controller.
  3. In this scenario, the LsaLookupSids function may return the old user name instead of the new user name. This behavior may prevent the application from working correctly.


Cause:

The local security authority (LSA) caches the mapping between the SID and the user name in a local cache on the domain member computer. The cached user name is not synchronized with domain controllers. The LSA on the domain member computer first queries the local SID cache. If an existing mapping is already in the local SID cache, the LSA returns the cached user name information instead of querying the domain controllers. This behavior is intended to improve performance.

The cache entries do time out, however chances are that recurring queries by applications keep the existing cache entry alive for the maximum lifetime of the cache entry.


Workaround:

To work around this issue, disable the local SID cache on the domain member computer as follows.

  1. In RegEdit, locate HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa
  2. Create a new DWORD directly under "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa", name it LsaLookupCacheMaxSize and assign value 0.
  3. Reboot may not be required.

Note The LsaLookupCacheMaxSize registry entry sets the maximum number of cached mappings that can be saved in the local SID cache. The default maximum number is 128. When the LsaLookupCacheMaxSize registry entry is set to 0, the local SID cache is disabled.


Resources:
https://support.microsoft.com/en-us/help/946358/the-lsalookupsids-function-may-return-the-old-user-name-instead-of-the
https://marclsitinfrablog.wordpress.com/2011/06/25/lsa-lookup-cache/

Sunday, May 15, 2016

ADQuery.ReadOnly (Active Directory Query Utility)

using System;
using System.Collections;
using System.Data;
using System.DirectoryServices;
using System.DirectoryServices.ActiveDirectory;
namespace ADQuery
{
 public class ReadOnly
 {

  public enum DNObjectClass
  {
   user,
   group,
   computer
  }

  public enum DNReturnType
  {
   distinguishedName,
   ObjectGuid
  }

  public static string FriendlyDomainToLdapDomain(string friendlyDomainName)
  {
   string result = null;
   try
   {
    DirectoryContext context = new DirectoryContext(
      DirectoryContextType.Domain, friendlyDomainName);
    Domain domain = Domain.GetDomain(context);
    result = domain.Name;
   }
   catch (DirectoryServicesCOMException ex)
   {
    result = ex.Message.ToString();
   }
   return result;
  }

  public static ArrayList EnumerateDomains()
  {
   ArrayList arrayList = new ArrayList();
   Forest currentForest = Forest.GetCurrentForest();
   DomainCollection domains = currentForest.Domains;
   foreach (Domain domain in domains)
   {
    arrayList.Add(domain.Name);
   }
   return arrayList;
  }

  public static ArrayList EnumerateCatalogs()
  {
   ArrayList arrayList = new ArrayList();
   Forest currentForest = Forest.GetCurrentForest();
   foreach (GlobalCatalog globalCatalog in currentForest.GlobalCatalogs)
   {
    arrayList.Add(globalCatalog.Name);
   }
   return arrayList;
  }

  public static ArrayList EnumerateDomainControllers()
  {
   ArrayList arrayList = new ArrayList();
   Domain currentDomain = Domain.GetCurrentDomain();
   foreach (DomainController domainController in currentDomain.DomainControllers)
   {
    arrayList.Add(domainController.Name);
   }
   return arrayList;
  }

  public ArrayList EnumerateOU(string OuDn)
  {
   ArrayList arrayList = new ArrayList();
   try
   {
    DirectoryEntry directoryEntry = new DirectoryEntry("LDAP://" + OuDn);
    foreach (DirectoryEntry directoryEntry2 in directoryEntry.Children)
    {
     string text = directoryEntry2.Path.ToString();
     arrayList.Add(text.Remove(0, 7));
     directoryEntry2.Close();
     directoryEntry2.Dispose();
    }
    directoryEntry.Close();
    directoryEntry.Dispose();
   }
   catch (DirectoryServicesCOMException ex)
   {
    arrayList.Add("An Error Occurred: " + ex.Message.ToString());
   }
   return arrayList;
  }

  public static bool Exists(string objectPath)
  {
   bool result = false;
   if (DirectoryEntry.Exists("LDAP://" + objectPath))
   {
    result = true;
   }
   return result;
  }

  public ArrayList AttributeValuesMultiString(
    string attributeName, string objectDn, ArrayList valuesCollection, bool recursive)
  {
   DirectoryEntry directoryEntry = new DirectoryEntry(objectDn);
   PropertyValueCollection propertyValueCollection = directoryEntry.Properties[attributeName];
   IEnumerator enumerator = propertyValueCollection.GetEnumerator();
   while (enumerator.MoveNext())
   {
    if (enumerator.Current != null)
    {
     if (!valuesCollection.Contains(enumerator.Current.ToString()))
     {
      valuesCollection.Add(enumerator.Current.ToString());
      if (recursive)
      {
       this.AttributeValuesMultiString(attributeName, 
         "LDAP://" + enumerator.Current.ToString(), valuesCollection, true);
      }
     }
    }
   }
   directoryEntry.Close();
   directoryEntry.Dispose();
   return valuesCollection;
  }

  public string AttributeValuesSingleString(string attributeName, string objectDn)
  {
   DirectoryEntry directoryEntry = new DirectoryEntry(objectDn);
   string result = directoryEntry.Properties[attributeName].Value.ToString();
   directoryEntry.Close();
   directoryEntry.Dispose();
   return result;
  }

  public static ArrayList GetUsedAttributes(string objectDn)
  {
   DirectoryEntry directoryEntry = new DirectoryEntry("LDAP://" + objectDn);
   ArrayList arrayList = new ArrayList();
   foreach (string text in directoryEntry.Properties.PropertyNames)
   {
    string text2 = directoryEntry.Properties[text].Value.GetType().ToString();
    string text3 = string.Empty;
    if (!directoryEntry.Properties[text].Value.GetType().IsArray)
    {
     text3 = directoryEntry.Properties[text].Value.ToString();
    }
    if (text == "objectGUID")
    {
     Guid guid = new Guid((byte[])directoryEntry.Properties[text].Value);
     text3 = guid.ToString();
     text3 = text3 + "(" + directoryEntry.Guid.ToString() + ")";
    }
    if (text == "objectSID")
    {
     Guid guid = new Guid((byte[])directoryEntry.Properties[text].Value);
     text3 = guid.ToString();
     text3 = text3 + "(" + directoryEntry.Guid.ToString() + ")";
    }
    if (text == "memberOf")
    {
     ArrayList arrayList2 = new ArrayList((object[])directoryEntry.Properties[text].Value);
     ReadOnly readOnly = new ReadOnly();
     foreach (object current in arrayList2)
     {
      string text4 = (string)current;
      text3 = text3 + "" + text4 + "";
      text3 = text3 + " (objectGuid = " + readOnly.ConvertDnToGuid(text4) + ")";
     }
    }
    if (text == "member")
    {
     ArrayList arrayList2 = new ArrayList((object[])directoryEntry.Properties[text].Value);
     ReadOnly readOnly = new ReadOnly();
     foreach (object current in arrayList2)
     {
      string text4 = (string)current;
      text3 = text3 + "" + text4 + "";
      text3 = text3 + " (objectGuid = " + readOnly.ConvertDnToGuid(text4) + ")";
     }
    }
    arrayList.Add(string.Concat(new string[]
    {
     text,
     ", type = ",
     text2,
     ", value = ",
     text3,
     ""    
     }));
   }
   return arrayList;
  }

  public DataTable GetADUserAttributes(string objectDN)
  {
   DataTable result;
   if (!DirectoryEntry.Exists("LDAP://" + objectDN))
   {
    result = null;
   }
   else
   {
    try
    {
     DirectoryEntry directoryEntry = new DirectoryEntry("LDAP://" + objectDN);
     SearchResult searchResult = new DirectorySearcher(directoryEntry)
     {
      Filter = "(&(objectCategory=Person)(objectClass=user)))",
      SearchScope = SearchScope.Subtree
     }.FindOne();
     DataTable dataTable = new DataTable();
     dataTable.Columns.Add("CN");
     dataTable.Columns.Add("displayName");
     dataTable.Columns.Add("employeeID");
     dataTable.Columns.Add("givenName");
     dataTable.Columns.Add("sn");
     dataTable.Columns.Add("sAMAccountName");
     dataTable.Columns.Add("sAMAccountType");
     dataTable.Columns.Add("telephoneNumber");
     dataTable.Columns.Add("UserAccountControl");
     dataTable.Columns.Add("UserPrincipalName");
     dataTable.Columns.Add("extensionAttribute1");
     dataTable.Columns.Add("primaryGroupID");
     dataTable.Columns.Add("mail");
     dataTable.Columns.Add("whenChanged");
     dataTable.Columns.Add("whenCreated");
     dataTable.Columns.Add("ObjectGUID");
     DataRow dataRow = dataTable.NewRow();
     directoryEntry.Close();
     result = dataTable;
    }
    catch
    {
     throw new DirectoryServicesCOMException("There was an error searching for user in AD");
    }
   }
   return result;
  }

  public string GetDistinguishedName(string sAMAccountName, string LdapDomain)
  {
   string result = string.Empty;
   string text = "LDAP://" + LdapDomain;
   DirectoryEntry directoryEntry = new DirectoryEntry(text);
   DirectorySearcher directorySearcher = new DirectorySearcher(directoryEntry);
   directorySearcher.Filter = "(&(objectClass=user)(sAMAccountName=" + sAMAccountName + "))";
   SearchResult searchResult = directorySearcher.FindOne();
   if (searchResult == null)
   {
    throw new DirectoryServicesCOMException(string.Concat(new string[]
    {
     "Cannot locate distinguishedName for ",
     sAMAccountName,
     " in ",
     text,
     "."
    }));
   }
   DirectoryEntry directoryEntry2 = searchResult.GetDirectoryEntry();
   result = "LDAP://" + directoryEntry2.Properties["distinguishedName"].Value;
   directoryEntry.Close();
   directoryEntry.Dispose();
   directorySearcher.Dispose();
   return result;
  }

  public string GetObjectDistinguishedName(
    ReadOnly.DNObjectClass dnObjectClass, ReadOnly.DNReturnType dnReturnType, 
    string objectName, string LdapDomain)
  {
   string result = string.Empty;
   string path = "LDAP://" + LdapDomain;
   DirectoryEntry directoryEntry = new DirectoryEntry(path);
   DirectorySearcher directorySearcher = new DirectorySearcher(directoryEntry);
   switch (dnObjectClass)
   {
   case ReadOnly.DNObjectClass.user:
    directorySearcher.Filter = string.Concat(new string[]
    {
     "(&(objectClass=user)(|(cn=",
     objectName,
     ")(sAMAccountName=",
     objectName,
     ")))"
    });
    break;
   case ReadOnly.DNObjectClass.group:
    directorySearcher.Filter = string.Concat(new string[]
    {
     "(&(objectClass=group)(|(cn=",
     objectName,
     ")(dn=",
     objectName,
     ")))"
    });
    break;
   case ReadOnly.DNObjectClass.computer:
    directorySearcher.Filter = string.Concat(new string[]
    {
     "(&(objectClass=computer)(|(cn=",
     objectName,
     ")(dn=",
     objectName,
     ")))"
    });
    break;
   }
   SearchResult searchResult = directorySearcher.FindOne();
   if (searchResult == null)
   {
    throw new NullReferenceException(string.Concat(new string[]
    {
     "unable to locate the distinguishedName for the object ",
     objectName,
     " in the ",
     LdapDomain,
     " domain"
    }));
   }
   DirectoryEntry directoryEntry2 = searchResult.GetDirectoryEntry();
   switch (dnReturnType)
   {
   case ReadOnly.DNReturnType.distinguishedName:
    result = "LDAP://" + directoryEntry2.Properties["distinguishedName"].Value;
    break;
   case ReadOnly.DNReturnType.ObjectGuid:
    result = directoryEntry2.Guid.ToString();
    break;
   }
   directoryEntry.Close();
   directoryEntry.Dispose();
   directorySearcher.Dispose();
   return result;
  }

  public string ConvertDnToGuid(string objectDN)
  {
   string result = string.Empty;
   if (DirectoryEntry.Exists("LDAP://" + objectDN))
   {
    DirectoryEntry directoryEntry = new DirectoryEntry("LDAP://" + objectDN);
    result = directoryEntry.Guid.ToString();
    directoryEntry.Close();
    directoryEntry.Dispose();
   }
   return result;
  }

  public static string ConvertGuidToOctetString(string objectGuid)
  {
   Guid guid = new Guid(objectGuid);
   byte[] array = guid.ToByteArray();
   string text = "";
   byte[] array2 = array;
   for (int i = 0; i < array2.Length; i++)
   {
    byte b = array2[i];
    text = text + "\\" + b.ToString("x2");
   }
   return text;
  }

  public ArrayList LogonUserGroups()
  {
   return null;
  }

  public static string ConvertGuidToDn(string guid)
  {
   DirectoryEntry directoryEntry = new DirectoryEntry();
   string nativeGuid = directoryEntry.NativeGuid;
   directoryEntry.Close();
   directoryEntry.Dispose();
   return null;
  }
 }
}