Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UserPrincipal.GetGroups fails with unknown error

Tags:

I am trying to get all Active Directory groups for a user, with the following code:

    private static IEnumerable<string> GetGroupNames(string userName)     {         using (var context = new PrincipalContext(ContextType.Domain))         {             using (var userPrincipal = UserPrincipal.FindByIdentity(context, userName))             {                 var groupSearch = userPrincipal.GetGroups(context);                 var result = new List<string>();                 foreach (var principal in groupSearch)                 {                     Log.LogDebug("User {0} is member of group {0}", userPrincipal.DisplayName, principal.DisplayName);                     result.Add(principal.SamAccountName);                 }                 return result;             }         }     } 

This code correctly finds the user principal, but fails when GetGroups is called with a PrincipalOperationException: Unknown error (0x80005000).

Root exception:

   at System.DirectoryServices.AccountManagement.ADStoreCtx.GetGroupsMemberOf(Principal foreignPrincipal, StoreCtx foreignContext)    at System.DirectoryServices.AccountManagement.Principal.GetGroupsHelper(PrincipalContext contextToQuery)    at System.DirectoryServices.AccountManagement.Principal.GetGroups(PrincipalContext contextToQuery)    at [line of the GetGroup call] 

Inner exception (COMException):

   at System.DirectoryServices.DirectoryEntry.Bind(Boolean throwIfFail)    at System.DirectoryServices.DirectoryEntry.Bind()    at System.DirectoryServices.DirectoryEntry.get_AdsObject()    at System.DirectoryServices.PropertyValueCollection.PopulateList()    at System.DirectoryServices.PropertyValueCollection..ctor(DirectoryEntry entry, String propertyName)    at System.DirectoryServices.PropertyCollection.get_Item(String propertyName)    at System.DirectoryServices.AccountManagement.ADUtils.RetriveWkDn(DirectoryEntry deBase, String defaultNamingContext, String serverN 

Another report with this problem.

Any clues?

like image 237
Holstebroe Avatar asked Dec 23 '10 11:12

Holstebroe


2 Answers

Adding Environment.UserDomainName as the name argument to the PrincipalContext helped:

using (var context = new PrincipalContext(ContextType.Domain, Environment.UserDomainName)) 

I still don't know why PrincipalContext(ContextType.Domain) only works for finding the UserPrincipal and not the groups of the user. The COM error message "unknown error" is not very helpful and the PrincipalContext constructor overload with only the ContextType is virtually undocumented at MSDN. It smells like an issue with the .NET framework as pointed out by Harvey Kwok.

like image 72
Holstebroe Avatar answered Oct 25 '22 01:10

Holstebroe


As mentioned in the question comments, another reason this particular error can happen when calling GetGroups is due to a documented bug in .NET and .NET Core. It happens when attempting to get groups for user principals that have a slash ('/') in their AD Distinguished Name.

The workaround, at least until the bug is fixed, is to write your own GetGroups method. Here is a working example that returns just the group names (also includes distribution lists):

public static List<string> GetGroups(UserPrincipal user) {     List<string> groupNames = new List<string>();      using (DirectoryEntry directoryEntryUser = (DirectoryEntry)user.GetUnderlyingObject())     {         object[] groups = GetAdPropertyValueObjectArray(directoryEntryUser, "memberOf");         const int prefixLength = 3;         const string prefix = "CN=";  // CN = Common Name          if (groups != null)         {             foreach (string group in groups)             {                 if (group.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))                 {                     int commaIndex = group.IndexOf(",", prefixLength);                     string groupName;                      if (commaIndex >= 0)                         groupName = group.Substring(prefixLength, commaIndex - prefixLength);                     else                         groupName = group.Substring(prefixLength);                      if (groupName.Length > 0)                         groupNames.Add(groupName);                 }             }         }     }      return groupNames; }  private static object[] GetAdPropertyValueObjectArray(DirectoryEntry userAccount, string adPropertyKey) {     object[] result = null;     PropertyValueCollection property = userAccount.Properties[adPropertyKey];      if (property != null)     {         object propertyValue = property.Value;          if (propertyValue != null)         {             if (propertyValue is string)             {                 result = new object[1];                 result[0] = propertyValue;             }             else             {                 result = (object[])propertyValue;             }         }     }      return result; } 
like image 44
Tawab Wakil Avatar answered Oct 25 '22 01:10

Tawab Wakil