UserPrincipal SamAccountName throws DirectoryServicesCOMException unhandled "A local error has occured" - c#

I'm writing a piece of code that is supposed to search the active directory for a specific users GivenName (forename) and Surname based upon their SamAccountName as the search parameter, and then return a string containing their given name and surname.
The code I have written so far is as follows:
public static string GetName(string uName)
{
StringBuilder builder = new StringBuilder();
using (PrincipalContext context = new PrincipalContext(ContextType.Domain, "serverName"))
{
UserPrincipal user = new UserPrincipal(context);
user.SamAccountName = uName;
PrincipalSearcher srch = new PrincipalSearcher(user);
srch.QueryFilter = user;
PrincipalSearchResult<Principal> res = srch.FindAll();
foreach (UserPrincipal u in res)
{
builder.Append(u.GivenName);
builder.Append(" ");
builder.Append(u.Surname);
}
return builder.ToString();
}
}
The problem I'm having with the above code is that during run-time the line
user.SamAccountName = uName;
throws the following error: DirectoryServicesCOMException unhandled "A local error has occured"
The principal context object is created just fine, as is the user principal object, it only throws the error when executing the line mentioned above. What's even more bizarre is that this code seemed to work a couple of days ago. If anyone reading this has any ideas as to why I'm getting this error I'd be greatly appreciative!
P.S.
I resorted to asking about this as the bloody error message is a bit too cryptic to actually figure out, or at least for me anyway (a local error occured) really? Whichever developer thought that was a useful error message is an idiot.

Possible causes:
There is an issue with the computer's domain membership or authentication. For example, is the clock on the computer running the code synchronized (within 5 minutes) of the DCs in the target domain?
The user name is invalid. For example, it contains invalid characters.

Related

ldap server is unavailable

I'm totally new to this
I've tried to connect to an ldap server using the following code.
PrincipalContext principalContext = new PrincipalContext(ContextType.Domain, "abcdef", "OU=abcdef,DC=avengers,DC=net");
I'm getting an "LDAP server is unavailable" exception.
I've looked up other posts which recommended adding username and password to it but I wanted to use this specific overloaded method which takes in Context.Domain, Domain and Container parameters only.
Any suggestions would be appreciated.
I think you are not using Active Directory.
PrincipalContext works well with AD only.
If your directory is OpenLDAP/ any other, then try below code
public static void Main(String[] rags)
{
//If you are not sure about username and password, leave below 2 variables as it is
String username=""; //Change to your username, if you have any
String passwd=""; //Change to your Password, if you have any
DirectoryEntry entry = new DirectoryEntry("LDAP://abcedf/OU=abcdef,DC=avengers,DC=net", username, passwd, AuthenticationTypes.None);
DirectorySearcher ds = new DirectorySearcher(entry,"ObjectClass=*");
// Below statement will list all entries immediately below your BaseDN
foreach (DirectoryEntry c in entry.Children)
{
Console.WriteLine("{0}", c.Path);
}
}
Thank you for the responses.
I was passing in wrong value for the "Domain Name" parameter (second parameter). I was sending OU value instead of Domain Name.

UserPrincipals.GetAuthorizationGroups An error (1301) occurred while enumerating the groups. After upgrading to Server 2012 Domain Controller

Research:
Similar Issue with workaround, but not actual solution to existing problem
Similar issue pointing to Microsoft End Point update as culprit
The above links are the most suited to my problem, I have also viewed every similar question listed by Stack Overflow upon creating this post, and only the above referenced questions fit my issue.
Background:
I have been using UserPrincipal.GetAuthorizationGroups for permissions for specific page access running IIS 7.5 on Server 2008 R2 in a C#.NET 4.0 web forms site for 2 and a half years. On May 15 2013 we removed a primary Domain controller running Server 2008 (not r2) and replaced it with a Server 2012 Domain Controller. The next day we started receiving the exception listed below.
I use Principal Context for Forms Authentication. The username/pass handshake succeeds and the auth cookie is properly set, but the subsequent Principal Context call that also calls UserPrincipal.GetAuthorizationGroups fails intermittently. We've resolved a few BPA issues that appeared in the Server 2012 Domain Controller but this has yet to resolve the issue. I also instituted a cron that runs on two separate servers. The two servers will fail at Group SID resolution at different times though they are running the same code base. (A dev environment and production environment).
The issue resolves itself temporarily upon web server reboot, and also on the dev server it will resolve itself after 12 hours of not functioning. The production server will usually stop functioning properly until a reboot without resolving itself.
At this point I am trying to refine the cron targeting specific Domain Controllers in the network as well as the new DC and using the standard LDAP query that is currently failing to yield more targeted exception times. Thus far we've found on one web server that there is no pattern to the days at which it fails, but it will recover within roughly 12 hours. The latest results show Group SID resolution failure between 8AM-8PM then it recovers, several days later it will fail at 8pm and recover at 8am then run fine for another 12 hours and fail again. We are hoping to see if it is just a specific server communication issue or to see if it is the entire set of Domain Controllers.
Exception:
Exception information:
Exception type: PrincipalOperationException
Exception message: An error (1301) occurred while enumerating the groups.
The group's SID could not be resolved.
at System.DirectoryServices.AccountManagement.SidList.TranslateSids(String target, IntPtr[] pSids)
at System.DirectoryServices.AccountManagement.SidList..ctor(SID_AND_ATTR[] sidAndAttr)
at System.DirectoryServices.AccountManagement.AuthZSet..ctor(Byte[] userSid, NetCred credentials, ContextOptions contextOptions, String flatUserAuthority, StoreCtx userStoreCtx, Object userCtxBase)
at System.DirectoryServices.AccountManagement.ADStoreCtx.GetGroupsMemberOfAZ(Principal p)
at System.DirectoryServices.AccountManagement.UserPrincipal.GetAuthorizationGroups()
Question:
Given the above information, does anyone have any idea why decommissioning the Windows Server 2008 (not r2) and implementing a new Server 2012 DC would cause UserPrincipal.GetAuthorizationGroups to fail with the 1301 SID resolution error?
Ideas on eliminating possible causes would also be appreciated.
Disclaimer:
This is my first post to Stack Overflow, I often research here but have not joined in discussions until now. Forgive me if I should have posted elsewhere and feel free to point out better steps before posting.
UPDATE 13-JUN-2013:
On the 12th of June I addressed the possibility of items not disposed causing the issue.
The time frame has been too short to determine if the adjusted code has fixed the issue, but I will continue to update as we work towards a resolution such that maybe with any luck someone here can lend a hand.
Original Code
public bool isGroupMember(string userName, ArrayList groupList)
{
bool valid = false;
PrincipalContext ctx = new PrincipalContext(ContextType.Domain, domain_server + ".domain.org:636", null, ContextOptions.Negotiate | ContextOptions.SecureSocketLayer);
// find the user in the identity store
UserPrincipal user =
UserPrincipal.FindByIdentity(
ctx,
userName);
// get the groups for the user principal and
// store the results in a PrincipalSearchResult object
PrincipalSearchResult<Principal> groups =
user.GetAuthorizationGroups();
// display the names of the groups to which the
// user belongs
foreach (Principal group in groups)
{
foreach (string groupName in groupList)
{
if (group.ToString() == groupName)
{
valid = true;
}
}
}
return valid;
}
Updated Code
public bool isGroupMember(string userName, ArrayList groupList, string domain_server)
{
bool valid = false;
try
{
using (PrincipalContext ctx = new PrincipalContext(ContextType.Domain, domain_server + ".domain.org:636", null, ContextOptions.Negotiate | ContextOptions.SecureSocketLayer))
{
// find the user in the identity store
UserPrincipal user =
UserPrincipal.FindByIdentity(
ctx,
userName);
try
{
// get the groups for the user principal and
// store the results in a PrincipalSearchResult object
using (PrincipalSearchResult<Principal> groups = user.GetAuthorizationGroups())
{
// display the names of the groups to which the
// user belongs
foreach (Principal group in groups)
{
foreach (string groupName in groupList)
{
if (group.ToString() == groupName)
{
valid = true;
}
}
group.Dispose();
}
}//end using-2
}
catch
{
log_gen("arbitrary info");
return false;
}
}//end using-1
}
catch
{
log_gen("arbitrary info");
return false;
}
return valid;
}
I have just run into this same issue and the info I have managed to track down may be helpful; as above we have seen this problem where the domain controller is running Server 2012 - firstly with a customer deployment and then replicated on our own network.
After some experimentation we found that our code would run fine on Server 2012, but hit the 1301 error code when the client system was running Server 2008. The key information about what was happening was found here:
MS blog translated from German
The hotfix referred to in the link below has fixed the problem on our test system
SID S-1-18-1 and SID S-1-18-2 can't be mapped
Hope this is helpful for someone! As many have noted this method call seems rather fragile and we will probably look at implementing some alternative approach before we hit other issues.
Gary
Here's my solution. It seems to work consistently well. Because the problem happens when iterating over the collection, I use a different approach when iterating in order to handle the exception without blocking the actual iterating:
private string[] GetUserRoles(string Username)
{
List<string> roles = new List<string>();
try
{
string domain = Username.Contains("\\") ? Username.Substring(0, Username.IndexOf("\\")) : string.Empty;
string username = Username.Contains("\\") ? Username.Substring(Username.LastIndexOf("\\") + 1) : Username;
if (!string.IsNullOrEmpty(domain) && !string.IsNullOrEmpty(username))
{
PrincipalContext principalContext = new PrincipalContext(ContextType.Domain, domain);
UserPrincipal user = UserPrincipal.FindByIdentity(principalContext, username);
if (user != null)
{
PrincipalSearchResult<Principal> groups = user.GetAuthorizationGroups();
int count = groups.Count();
for (int i = 0; i < count; i++)
{
IEnumerable<Principal> principalCollection = groups.Skip(i).Take(1);
Principal principal = null;
try
{
principal = principalCollection.FirstOrDefault();
}
catch (Exception e)
{
//Error handling...
//Known exception - sometimes AD can't query a particular group, requires server hotfix?
//http://support.microsoft.com/kb/2830145
}
if (principal!=null && principal is GroupPrincipal)
{
GroupPrincipal groupPrincipal = (GroupPrincipal)principal;
if (groupPrincipal != null && !string.IsNullOrEmpty(groupPrincipal.Name))
{
roles.Add(groupPrincipal.Name.Trim());
}
}
}
}
}
}
catch (Exception e)
{
//Error handling...
}
return roles.ToArray();
}
We experienced this issue when our infrastructure team brought a 2012 Domain Controller online. We also had pre-2012 DCs in place and so we experienced the issue intermittently. We came up with a fix which I wanted to share - it has 2 parts.
First of all, install the hotfix mentioned by Gary Hill. This will resolve the following issue:
An error (1301) occurred while enumerating the groups. The group's SID could not be resolved.
We thought we were home free after installing this hotfix. However, after it was installed we got a different intermittent error. Certain groups that we were interrogating had a null sAMAccountName property. The actual property was populated in Active Directory but it was incorrectly being returned with a null value by the API. I presume this is a bug somewhere in the Active Directory API but I don't know any more than that.
Fortunately we were able to work around the issue by switching to use the group Name property instead of the sAMAccountName property. This worked for us. I believe, that sAMAccountName is effectively deprecated and exists only for backwards compatibility reasons. That being the case it seemed a reasonable change to make.
I enclose a cut down version of our GetRolesForUser code to demonstrate the change in place.
using (var context = new PrincipalContext(ContextType.Domain, _domainName))
{
try
{
var p = UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, username);
if (p == null) throw new NullReferenceException(string.Format("UserPrincipal.FindByIdentity returned null for user: {0}, this can indicate a problem with one or more of the AD controllers", username));
var groups = p.GetAuthorizationGroups();
var domain = username.Substring(0, username.IndexOf(#"\", StringComparison.InvariantCultureIgnoreCase)).ToLower();
foreach (GroupPrincipal group in groups)
{
if (!string.IsNullOrEmpty(group.Name))
{
var domainGroup = domain + #"\" + group.Name.ToLower();
if (_groupsToUse.Any(x => x.Equals(domainGroup, StringComparison.InvariantCultureIgnoreCase)))
{
// Go through each application role defined and check if the AD domain group is part of it
foreach (string role in roleKeys)
{
string[] roleMembers = new [] { "role1", "role2" };
foreach (string member in roleMembers)
{
// Check if the domain group is part of the role
if (member.ToLower().Contains(domainGroup))
{
// Cache the Application Role (NOT the AD role)
results.Add(role);
}
}
}
}
}
group.Dispose();
}
}
catch (Exception ex)
{
throw new ProviderException("Unable to query Active Directory.", ex);
}
}
Hope that helps.
I experienced error code 1301 with UserPrincipal.GetAuthorizationGroups while using a brand new virtual development domain which contained 2 workstations and 50 users/groups (many of which are the built in ones). We were running Windows Server 2012 R2 Essentials with two Windows 8.1 Enterprise workstations joined to the domain.
I was able to recursively obtain a list of a user's group membership using the following code:
class ADGroupSearch
{
List<String> groupNames;
public ADGroupSearch()
{
this.groupNames = new List<String>();
}
public List<String> GetGroups()
{
return this.groupNames;
}
public void AddGroupName(String groupName)
{
this.groupNames.Add(groupName);
}
public List<String> GetListOfGroupsRecursively(String samAcctName)
{
PrincipalContext ctx = new PrincipalContext(ContextType.Domain, System.Environment.UserDomainName);
Principal principal = Principal.FindByIdentity(ctx, IdentityType.SamAccountName, samAcctName);
if (principal == null)
{
return GetGroups();
}
else
{
PrincipalSearchResult<Principal> searchResults = principal.GetGroups();
if (searchResults != null)
{
foreach (GroupPrincipal sr in searchResults)
{
if (!this.groupNames.Contains(sr.Name))
{
AddGroupName(sr.Name);
}
Principal p = Principal.FindByIdentity(ctx, IdentityType.SamAccountName, sr.SamAccountName);
try
{
GetMembersForGroup(p);
}
catch (Exception ex)
{
//ignore errors and continue
}
}
}
return GetGroups();
}
}
private void GetMembersForGroup(Principal group)
{
if (group != null && typeof(GroupPrincipal) == group.GetType())
{
GetListOfGroupsRecursively(group.SamAccountName);
}
}
private bool IsGroup(Principal principal)
{
return principal.StructuralObjectClass.ToLower().Equals("group");
}
}
I'm in an environment with multiple domain forests and trusts. I have pretty much this exact same code running on a web site form used to perform user security group lookups across the different domains.
I get this exact error in one of the very large domains where group membership can include 50+ different groups. It works fine in other domains forests.
In my research I found a thread that looks unrelated, but actually has the same stack trace. It is for a remote application running on SBS. The thread mentions that the error is caused by unresolvable SIDS in a group. I believe these would be what are known as "tombstoned" SIDS in active directory. See the thread here.
The thread suggests that finding the tombstoned enteries and removing them from the groups solves the problem. Is it possible the error you are receiving is because SIDS are getting tombstoned every 12 hours by a separate unrelated process? Ultimately, I believe this is a bug in the framework, and that the method should not crash because of tombstoned/unresolvable SIDS.
Good luck!
If anyone is interested this is a VB.NET version of the same code.
Few things you have to do before this code can work
1) You have to reference the assembly System.DirectoryServices
2) Make sure to pass "theusername" variable without the domain, so if your domain is "GIS" and your username is "Hussein" Windows generally authenticate you as GIS\Hussein. So you have to send in just purely the username "Hussein". I worked out the case sensitive stuff.
3) The method GetGroupsNew takes a username and returns a list of groups
4) The method isMemberofnew takes a username and a group and verifies that this user is part of that group or not, this is the one I was interested in.
Private Function getGroupsNew(theusername As String) As List(Of String)
Dim lstGroups As New List(Of String)
Try
Dim allDomains = Forest.GetCurrentForest().Domains.Cast(Of Domain)()
Dim allSearcher = allDomains.[Select](Function(domain)
Dim searcher As New DirectorySearcher(New DirectoryEntry("LDAP://" + domain.Name))
searcher.Filter = [String].Format("(&(&(objectCategory=person)(objectClass=user)(userPrincipalName=*{0}*)))", theusername)
Return searcher
End Function)
Dim directoryEntriesFound = allSearcher.SelectMany(Function(searcher) searcher.FindAll().Cast(Of SearchResult)().[Select](Function(result) result.GetDirectoryEntry()))
Dim memberOf = directoryEntriesFound.[Select](Function(entry)
Using entry
Return New With { _
Key .Name = entry.Name, _
Key .GroupName = DirectCast(entry.Properties("MemberOf").Value, Object()).[Select](Function(obj) obj.ToString()) _
}
End Using
End Function)
For Each user As Object In memberOf
For Each groupName As Object In user.GroupName
lstGroups.Add(groupName)
Next
Next
Return lstGroups
Catch ex As Exception
Throw
End Try
End Function
Private Function isMemberofGroupNew(theusername As String, thegroupname As String) As Boolean
Try
Dim lstGroups As List(Of String) = getGroupsNew(theusername)
For Each sGroup In lstGroups
If sGroup.ToLower.Contains(thegroupname.ToLower) Then Return True
Next
Return False
Catch ex As Exception
Throw
End Try
End Function
we had a similar issue after upgrading the domain controller to 2012. Suddenly my call to user.GetAuthorizationGroups() started failing; I was getting the same exception you were (error 1301). So, I changed it to user.GetGroups(). That worked for a little while, then started failing intermittently on "bad username or password". My latest workaround appears to fix it, for the moment at least. Instead of calling either of those, after constructing the user object, I also construct a group object, one for each group I want to see if the user is a member of. ie, "user.IsMemberOf(group)". That seems to work.
try
{
using (HostingEnvironment.Impersonate())
{
using (var principalContext = new PrincipalContext(ContextType.Domain, "MYDOMAIN"))
{
using (var user = UserPrincipal.FindByIdentity(principalContext, userName))
{
if (user == null)
{
Log.Debug("UserPrincipal.FindByIdentity failed for userName = " + userName + ", thus not authorized!");
isAuthorized = false;
}
if (isAuthorized)
{
firstName = user.GivenName;
lastName = user.Surname;
// so this code started failing:
// var groups = user.GetGroups();
// adGroups.AddRange(from #group in groups where
// #group.Name.ToUpper().Contains("MYSEARCHSTRING") select #group.Name);
// so the following workaround, which calls, instead,
// "user.IsMemberOf(group)",
// appears to work (for now at least). Will monitor for issues.
// test membership in SuperUsers
const string superUsersGroupName = "MyApp-SuperUsers";
using (var superUsers = GroupPrincipal.FindByIdentity(principalContext, superUsersGroupName))
{
if (superUsers != null && user.IsMemberOf(superUsers))
// add to the list of groups this user is a member of
// then do something with it later
adGroups.Add(superUsersGroupName);
}
I had same exception. If someone don't wanna used "LDAP", use this code. Cause I'm had nested groups, I'm used GetMembers(true) and it's little bit longer in time than GetMembers().
https://stackoverflow.com/a/27548271/1857271
or download fix from here: http://support.microsoft.com/kb/2830145
Facing the same problem enumerating authorization groups and the patches noted in the answer did not apply to our web server.
Manually enumerating and ignoring the trouble causing groups is working well, however:
private static bool UserIsMember(string usr, string grp)
{
usr = usr.ToLower();
grp = grp.ToLower();
using (var pc = new PrincipalContext(ContextType.Domain, "DOMAIN_NAME"))
{
using (var user = UserPrincipal.FindByIdentity(pc, usr))
{
var isMember = false;
var authGroups = user?.GetAuthorizationGroups().GetEnumerator();
while (authGroups?.MoveNext() ?? false)
{
try
{
isMember = authGroups.Current.Name.ToLower().Contains(grp);
if (isMember) break;
}
catch
{
// ignored
}
}
authGroups?.Dispose();
return isMember;
}
}
}
I had the problem that if i am connected over VPN and use groups=UserPrincipal.GetGroups() then the Exception occures when iterating over the groups.
If someone want to read all groups of a user there is following possibility (which is faster than using GetGroups())
private IList<string> GetUserGroupsLDAP(string samAccountName)
{
var groupList = new List<string>();
var domainConnection = new DirectoryEntry("LDAP://" + serverName, serverUser, serverUserPassword); // probably you don't need username and password
var samSearcher = new DirectorySearcher();
samSearcher.SearchRoot = domainConnection;
samSearcher.Filter = "(samAccountName=" + samAccountName + ")";
var samResult = samSearcher.FindOne();
if (samResult != null)
{
var theUser = samResult.GetDirectoryEntry();
theUser.RefreshCache(new string[] { "tokenGroups" });
var sidSearcher = new DirectorySearcher();
sidSearcher.SearchRoot = domainConnection;
sidSearcher.PropertiesToLoad.Add("name");
sidSearcher.Filter = CreateFilter(theUser);
foreach (SearchResult result in sidSearcher.FindAll())
{
groupList.Add((string)result.Properties["name"][0]);
}
}
return groupList;
}
private string CreateFilter(DirectoryEntry theUser)
{
string filter = "(|";
foreach (byte[] resultBytes in theUser.Properties["tokenGroups"])
{
var SID = new SecurityIdentifier(resultBytes, 0);
filter += "(objectSid=" + SID.Value + ")";
}
filter += ")";
return filter;
}

DirectoryEntries.Find: "An invalid dn syntax has been specified"

I'm trying to find a user in the current domain. The code is this:
DirectoryEntry domain = new DirectoryEntry("LDAP://CN-Users, DC=" + Environment.UserDomainName);
DirectoryEntries entries = domain.Children;
try
{
// The following line causes the exception
DirectoryEntry user = entries.Find("(&(objectCategory=user)(cn=" + userName + "))", ActiveDirectoryEntryType.User.TypeName);
user.DeleteTree();
user.CommitChanges();
}
catch
{}
I'm getting an error:
An invalid dn syntax has been specified.
I also tried the following code and got the same error:
DirectoryEntry user = entries.Find(userName, ActiveDirectoryEntryType.User.TypeName);
I could not find information about the proper syntax in the help files. Does anyone know how this is done?
You have an error in this statemet:
DirectoryEntry domain = new DirectoryEntry("LDAP://CN-Users, DC=" + Environment.UserDomainName);
I almost sure that it should be: LDAP://CN=Users, instaed of LDAP://CN-Users,
Second thing is DC=" + Environment.UserDomainName which maybe wrong, because ususally it is something like this: LDAP://OU=Finance,dc=fabrikam,dc=com (there is more than one DC)
You can find all DC using powershell. Run following command:
New-Object DirectoryServices.DirectoryEntry

Can't query AD (get a DirectoryServicesCOMException)

I'm attempting to query AD in an ASP.Net (4.0) application that is running on Windows Server 2008 R2 (IIS7 installed). (It also fails when running as a 2.0 application as well)
This is nothing new for me, as I've done this many times before. I wrote a small ASP.Net program that runs fine on my own machine (Windows XP with IIS6), but fails when run on the 2008 box.
(The result is that you see a list of groups the user is a member of in a textbox)
(on button_click)
var userName = txtUserName.Text;
if (userName.Trim().Length == 0)
{
txtResults.Text = "-- MISSING USER NAME --";
return;
}
var entry = new DirectoryEntry("LDAP://blah.blah/DC=blah,DC=blah",
"cn=acct, dc=blah, dc=blah",
"pass");
var search = new DirectorySearcher(entry);
search.Filter = "(SAMAccountName=" + userName + ")";
search.PropertiesToLoad.Add("memberOf");
var groupsList = new StringBuilder();
var result = search.FindOne();
if (result != null)
{
int groupCount = result.Properties["memberOf"].Count;
for (int counter = 0; counter < groupCount; counter++)
{
groupsList.Append((string)result.Properties["memberOf"][counter]);
groupsList.Append("\r\n");
}
}
txtResults.Text = groupsList.ToString();
When I run this code I get the following error on search.FindOne():
System.DirectoryServices.DirectoryServicesCOMException (0x8007203B): A local error has occurred.
at System.DirectoryServices.DirectoryEntry.Bind(Boolean throwIfFail)
at System.DirectoryServices.DirectoryEntry.Bind()
at System.DirectoryServices.DirectoryEntry.get_AdsObject()
at System.DirectoryServices.DirectorySearcher.FindAll(Boolean findMoreThanOne)
at System.DirectoryServices.DirectorySearcher.FindOne()
at WebApplication1._Default.btnSearch_Click(Object sender, EventArgs e)
We've done a lot of research with this and twiddled every IIS7 setting we can think of, but no go so far. Any clues?
Change the username parameter from "cn=xxx, dc=yyy, dc=zzz" to "Domain\Username"
You can also change the IIS Application Pool to run a domain account with the query priveleges you are searching for.
I have a few other comments as well:
Make sure the first entry for the DirectoryEntry constructor includes the container for the users as well. This should help the DirectorySearcher to work more reliably.
I believe the second parameter in the DirectoryEntry constructor should be the user name, not the AD query path.
You should set the AuthenticationType property as well. With Server 2008, by default, this needs to be set to AuthenticationTypes.Secure | AuthenticationTypes.ServerBind | AuthenticationTypes.Sealing. I'd guess that 2008R2 has a simliar requirement.
I see that the question is rather old, but after struggling with this I thought to mention that it is indeed possible to use the LDAP-style of the username (in opposite to the DNS style). This works well for me:
string connString = "LDAP://MyDomain/CN=blah,DC=blah,DC=blah";
string username = "CN=MyAdmin,CN=Users,CN=blah,DC=blah,DC=blah";
string password = "myLittleSecret";
DirectoryEntry root = new DirectoryEntry(
connString,
username,
password,
AuthenticationTypes.None);
Where MyAdmin is a member in the Administrators role.
One little thing that took me a while to find is the AuthenticationTypes.None parameter that is needed if you do not want to communicate over SSL. Surely, you want to do this in production, but for development purposes it may be OK to skip the encryption.
Environment: Windows 7
I was also getting this exception when tried to query the active directory:
SearchResult result = srch.FindOne();
To resolve this, just put the above code inside Security.RunWithElevatedPrivileges().
Final Solution:
SPSecurity.RunWithElevatedPrivileges(delegate()
{
result = srch.FindOne();
});

Error 0x80005000 and DirectoryServices

I'm trying to run a simple LDAP query using directory services in .Net.
DirectoryEntry directoryEntry = new DirectoryEntry("LDAP://someserver.contoso.com/DC=contoso,DC=com");
directoryEntry.AuthenticationType = AuthenticationTypes.Secure;
DirectorySearcher directorySearcher = new DirectorySearcher(directoryEntry);
directorySearcher.Filter = string.Format("(&(objectClass=user)(objectCategory=user) (sAMAccountName={0}))", username);
var result = directorySearcher.FindOne();
var resultDirectoryEntry = result.GetDirectoryEntry();
return resultDirectoryEntry.Properties["msRTCSIP-PrimaryUserAddress"].Value.ToString();
And I'm getting the following exception:
System.Runtime.InteropServices.COMException (0x80005000): Unknown error (0x80005000)
at System.DirectoryServices.DirectoryEntry.Bind(Boolean throwIfFail)
at System.DirectoryServices.DirectoryEntry.Bind()
at System.DirectoryServices.DirectoryEntry.get_AdsObject()
at System.DirectoryServices.DirectorySearcher.FindAll(Boolean findMoreThanOne)
at System.DirectoryServices.DirectorySearcher.FindOne()
As a snippet in a Console app, this works. But when I run it as part of a WCF service (run under the same credentials), it throws the above exception.
Any suggestions?
Thanks
I had the same again and again and nothing seemed to help.
Changing the path from ldap:// to LDAP:// did the trick.
It's a permission problem.
When you run the console app, that app runs with your credentials, e.g. as "you".
The WCF service runs where? In IIS? Most likely, it runs under a separate account, which is not permissioned to query Active Directory.
You can either try to get the WCF impersonation thingie working, so that your own credentials get passed on, or you can specify a username/password on creating your DirectoryEntry:
DirectoryEntry directoryEntry =
new DirectoryEntry("LDAP://someserver.contoso.com/DC=contoso,DC=com",
userName, password);
OK, so it might not be the credentials after all (that's usually the case in over 80% of the cases I see).
What about changing your code a little bit?
DirectorySearcher directorySearcher = new DirectorySearcher(directoryEntry);
directorySearcher.Filter = string.Format("(&(objectClass=user)(objectCategory=user) (sAMAccountName={0}))", username);
directorySearcher.PropertiesToLoad.Add("msRTCSIP-PrimaryUserAddress");
var result = directorySearcher.FindOne();
if(result != null)
{
if(result.Properties["msRTCSIP-PrimaryUserAddress"] != null)
{
var resultValue = result.Properties["msRTCSIP-PrimaryUserAddress"][0];
}
}
My idea is: why not tell the DirectorySearcher right off the bat what attribute you're interested in? Then you don't need to do another extra step to get the full DirectoryEntry from the search result (should be faster), and since you told the directory searcher to find that property, it's certainly going to be loaded in the search result - so unless it's null (no value set), then you should be able to retrieve it easily.
Marc
In the context of Ektron, this issue is resolved by installing the "IIS6 Metabase compatibility" feature in Windows:
Check 'Windows features' or 'Role Services' for IIS6 Metabase
compatibility, add if missing:
Ref: https://portal.ektron.com/KB/1088/
On IIS hosted sites, try recycling the app pool. It fixed my issue.
Thanks
I had the same error - in my case it was extra slash in path argument that made the difference.
BAD:
DirectoryEntry directoryEntry =
new DirectoryEntry("LDAP://someserver.contoso.com/DC=contoso,DC=com/",
userName, password);
GOOD:
DirectoryEntry directoryEntry =
new DirectoryEntry("LDAP://someserver.contoso.com/DC=contoso,DC=com",
userName, password);
I had this error as well and for me it was an OU with a forward slash in the name: "File/Folder Access Groups".
This forum thread pointed me in the right direction. In the end, calling .Replace("/","\\/") on each path value before use solved the problem for me.
Just FYI, I had the same error and was using the correct credentials but my LDAP url was wrong :(
I got the exact same error message and code
Just had that problem in a production system in the company where I live... A webpage that made a LDAP bind stopped working after an IP changed.
The solution...
... I installed Basic Authentication to perform the troubleshooting indicated here: https://support.microsoft.com/en-us/kb/329986
And after that, things just started to work. Even after I re-disabled Basic Authentication in the page I was testing, all other pages started working again with Windows Authentication.
Regards,
Acácio
I encounter this error when I'm querying an entry of another domain of the forrest and this entry have some custom attribut of the other domain.
To solve this error, I only need to specify the server in the url LDAP :
Path with error = LDAP://CN=MyObj,DC=DOMAIN,DC=COM
Path without error : LDAP://domain.com:389/CN=MyObj,DC=Domain,DC=COM
This Error can occur if the physical machine has run out of memory.
In my case i was hosting a site on IIS trying to access the AD, but the server had run out of memory.
I had to change my code from this:
DirectoryEntry entry = new DirectoryEntry(path, ldapUser, ldapPassword);
DirectorySearcher searcher = new DirectorySearcher();
searcher.SearchRoot = entry;
searcher.SearchScope = SearchScope.Subtree;
To this:
DirectoryEntry entry = new DirectoryEntry(path, ldapUser, ldapPassword);
DirectorySearcher searcher = new DirectorySearcher();
searcher.SearchScope = SearchScope.OneLevel;
SearchResult searchResult = searcher.FindOne();
The same error occurs if in DirectoryEntry.Patch is nothing after the symbols "LDAP//:". It is necessary to check the directoryEntry.Path before directorySearcher.FindOne(). Unless explicitly specified domain, and do not need to "LDAP://".
private void GetUser(string userName, string domainName)
{
DirectoryEntry dirEntry = new DirectoryEntry();
if (domainName.Length > 0)
{
dirEntry.Path = "LDAP://" + domainName;
}
DirectorySearcher dirSearcher = new DirectorySearcher(dirEntry);
dirSearcher.SearchScope = SearchScope.Subtree;
dirSearcher.Filter = string.Format("(&(objectClass=user)(|(cn={0})(sn={0}*)(givenName={0})(sAMAccountName={0}*)))", userName);
var searchResults = dirSearcher.FindAll();
//var searchResults = dirSearcher.FindOne();
if (searchResults.Count == 0)
{
MessageBox.Show("User not found");
}
else
{
foreach (SearchResult sr in searchResults)
{
var de = sr.GetDirectoryEntry();
string user = de.Properties["SAMAccountName"][0].ToString();
MessageBox.Show(user);
}
}
}
Spent a day on my similar issue, but all these answers didn't help.
Turned out in my case, I didn't enable Windows Authentication in IIS setting...
In my case, the problem was that I was trying to reference a DirectoryEntry's property value, even though that DirectoryEntry did not have that property at all.
If you for example, have:
var myGroup = new DirectoryEntry("LDAP://CN=mygroup,OU=mydomain....", myUsername, myPassword);
var groupManager = myGroup.Properties["managedBy"].Value.ToString();
If myGroup has no managedBy attribute set in the AD, this will result in Unknown error (0x80005000)

Categories

Resources