How to get a valid DirectoryEntry? - c#

I am trying to read an LDAP directory entry in a C# console application and I somehow don't succeed. Setting up the connection works fine:
private static LdapConnection ldapConnection;
public static void Main()
{
NetworkCredential credentials = new NetworkCredential("uid=admin,ou=system", "secret");
ldapConnection = new LdapConnection("127.0.0.1:10389");
ldapConnection.SessionOptions.ProtocolVersion = 3;
ldapConnection.AuthType = AuthType.Basic;
try
{
ldapConnection.Bind(credentials);
Console.WriteLine("Ldap connection is created.");
}
catch (Exception e)
{
Console.WriteLine("\r\nUnexpected exception occurred:\r\n\t" + e.GetType() + ":" + e.Message);
return;
}
//searchUsers();
//getSchemaClassName();
}
I can even find me some users:
private static void searchUsers()
{
string[] attrs = new string[] { "cn", "sn" };
string[] followedBy = new string[] { " ", "\n" };
var request = new SearchRequest("ou=users,ou=system", "(objectClass=*)", System.DirectoryServices.Protocols.SearchScope.Subtree, attrs);
var response = (SearchResponse)ldapConnection.SendRequest(request);
foreach (SearchResultEntry entry in response.Entries)
{
for (int i = 0; i < attrs.Length; i++)
{
if (entry.Attributes.Contains(attrs[i]))
{
Console.Write(entry.Attributes[attrs[i]].GetValues(Type.GetType("System.String"))[0] + followedBy[i]);
}
}
}
}
But when I for example try to read a directory entry's schema classname, I find that the directory entry contains a bunch of errors. This is the code:
private static void getSchemaClassName()
{
string path = "ldap://localhost:10389/cn=David,ou=users,ou=system"; //path is ok, points to an existing user
DirectoryEntry de = new DirectoryEntry(path, "uid=admin,ou=system", "secret");
Console.WriteLine("Schema classname:" + de.SchemaClassName); //breakpoint here
}
When I place a breakpoint on the "breakpoint here"-line and subsequently examine de properties, I find that Guid, Name, Options, Parent, SchemaClassName and some others display the "The directory service is unavailable" error. Which even makes sense to me, since ldapConnection isn't in any way involved in this code, whereas it is in searchUsers(). But I don't know how to connect this code to ldapConnection; every DirectoryEntry example I come across on the internet apparently works without the connection. How can I get this fixed?
Thx, Cooz
Edit:
Changing getSchemaClassName() to the following helped somewhat...
private static void getSchemaClassName()
{
string path = "LDAP://localhost:10389/cn=David,ou=users,ou=system";
DirectoryEntry de = new DirectoryEntry(path, "uid=admin,ou=system", "secret", AuthenticationTypes.None);
Console.WriteLine("Schema classname:" + de.SchemaClassName); //breakpoint here
}
...but not enough. Now at first sight only the Guid and NativeGuid properties of de give a System.Runtime.InteropServices.COMException and the rest seems fine. de.SchemaClassName is "organizationalPerson". Perfect.
However, upon setting the breakpoint once again and expanding for example de.SchemaEntry.SchemaEntry, almost everything that becomes visible there throws said exception: Guid, Name, ObjectSecurity, Options, SchemaClassName, SchemaEntry... you name it. The code still is not much use to me. What might be the possible cause of all those errors and how can I get it fixed?

Related

Facing Unknown error (0x80005000) while adding the user t LDAP in C#

I am facing Unknown error (0x80005000) while adding user to LDAP server(Apache), the following is my code. Could anyone please let me know where I am doing mistake.
namespace TestMethods
{
public class Program
{
static void Main(string[] args)
{
var ldi = new LdapDirectoryIdentifier("localhost", 10389);
AddUser("username", "o=Company");
}
public static void AddUser(string username, string group)
{
try
{
DirectoryEntry dirEntry = new
DirectoryEntry("LDAP://localhost:10389,o=Company" + group);
Console.WriteLine("Added to the path");// Working
dirEntry.Invoke("Add", new object[] { username });//Received Exception here
dirEntry.CommitChanges();
Console.WriteLine("Added to the path");
dirEntry.Close();
}
catch(Exception e)
{
Console.WriteLine(e.Message);
}
}
}
}
I believe you should use a / to separate the server name from the DN in your path:
LDAP://localhost:10389/o=Company
The constructor of DirectoryEntry doesn't make any network requests, so your path isn't validated until you actually use it.
However, if you are not using Active Directory, then I don't think Invoke will work for you. The description of DirectoryEntry.Invoke says:
Calls a method on the native Active Directory Domain Services object.
Even then, I'm not sure which Add method you're trying to use.
The way to create a new object using DirectoryEntry is like this (assuming dirEntry is pointing to a path where it can be created):
var newUser = dirEntry.Children.Add($"uid={username}", "inetOrgPerson");
// Set other attributes like this:
// newUser.Properties["someAttribute"].Value = "something";
//Save - this is where the object is actually created
newUser.CommitChanges();
I've never used Apache's LDAP server (I know AD better), so you may have to edit the schema ("inetOrgPerson") if you need to.

C# script to connect to Oracle Directory Server Enterprise Edition

I have a C# script I am trying to use to connect to an Oracle Directory Server Enterprise Edition
So far i have had very little success.
I am receiving a Unknown error (0x80005000) error message
Can somebody tell me what I am doing wrong. I have been researching the web and most online boards say that this error message is because the LDAP in the path needs to be in uppercase letters.
As you can see I have done that but still no luck.
Below is my code
private static readonly string PATH = "LDAP://LDAPDEV.example.com:389/o=example.com";
private static readonly string USERNAME = uid=SERVICE_USR,ou=ApplicationIDs,o=example.com";
private static readonly string PASSWORD = "test1234";
string DN = "";
// connect to determine proper distinguishedname
DirectoryEntry Entry = new DirectoryEntry(Path, USERNAME, PASSWORD, AuthenticationTypes.None);
try
{
// Bind to the native AdsObject to force authentication.
Object obj = Entry.NativeObject;
DirectorySearcher Search = new DirectorySearcher(Entry);
Search.ReferralChasing = ReferralChasingOption.All
}
catch (Exception ex)
{
throw new Exception("Error looking up distinguishedname. ", ex);
}
finally
{
anonymousEntry.Close();
}
return DN;
}
string sDomain="LDAPDEV.example.com:389";
string sDefaultOU = #"o=example.com";
string sServiceUser = #"uid=user,ou=ApplicationIDs,o=example.com";
string sServicePassword = "password";
try
{
PrincipalContext oPrincipalContext = new PrincipalContext(ContextType.Domain, sDomain, sDefaultOU, ontextOptions.SimpleBind, sServiceUser,sServicePassword);
}
catch (Exception ex)
{
ex.Message;
}
Here is something that you can use to get some information by using PrincipalContext look at this working example and replace the values with your domain name values.
// if you are doing this via web application if not you can replace
// the Request/ServerVariables["LOGON_USER"]
// with Environment.UserName; this will return your user name like msmith for example so var userName = Environvironment.UserName;
var userName = Request.ServerVariables["LOGON_USER"].Split(new string[] {"\\"}, StringSplitOptions.RemoveEmptyEntries);
var pc = new PrincipalContext(ContextType.Domain,"yourdomain.com",null, null);
var userFind = UserPrincipal.FindByIdentity(pc, IdentityType.SamAccountName, userName);
this is basically all you need to see the information like email address SamAccountName ect.. use the debugger to inspect all the property values available in the pc variable and userFind variable

Updating AD User information

I am having a problem updating user information in an Active Directory DB...
When I run the following code I get this error:
The specified directory service attribute or value does not exist
The problem is the path it is using to save the information is this:
CN=AD Test,OU=Container Name,DC=us,DC=flg,DC=int
Ad Test is the username in AD that I am trying to update.
and I believe it should be:
CN=Ad Test,OU=Container Name, OU=Server Name,DC=us,DC=flg,DC=int
I am new to Directory services so I would greatly appreciate any help in finding out why I cannot update... Thank you in advance
public bool UpdateActiveDirectory(string LdapServerName, string CustId, Employee SQLresult)
{
try
{
DirectoryEntry rootEntry = new DirectoryEntry("LDAP://" + LdapServerName, "usrename", "password", AuthenticationTypes.Secure);
DirectorySearcher searcher = new DirectorySearcher(rootEntry);
searcher.Filter = "(sAMAccountName=" + SQLresult.LogonNT + ")";
searcher.PropertiesToLoad.Add("title");
searcher.PropertiesToLoad.Add("street");
searcher.PropertiesToLoad.Add("1");
searcher.PropertiesToLoad.Add("st");
searcher.PropertiesToLoad.Add("postalCode");
searcher.PropertiesToLoad.Add("department");
searcher.PropertiesToLoad.Add("mail");
searcher.PropertiesToLoad.Add("manager");
searcher.PropertiesToLoad.Add("telephoneNumber");
SearchResult result = searcher.FindOne();
if (result != null)
{
// create new object from search result
DirectoryEntry entryToUpdate = result.GetDirectoryEntry();
entryToUpdate.Properties["title"].Value = SQLresult.Title;
entryToUpdate.Properties["street"].Value = SQLresult.Address;
entryToUpdate.Properties["1"].Value = SQLresult.City;
entryToUpdate.Properties["st"].Value = SQLresult.State;
entryToUpdate.Properties["postalCode"].Value = SQLresult.ZipCode;
entryToUpdate.Properties["department"].Value = SQLresult.Department;
entryToUpdate.Properties["mail"].Value = SQLresult.EMailID;
entryToUpdate.Properties["manager"].Value = SQLresult.ManagerName;
entryToUpdate.Properties["telephoneNumber"].Value = SQLresult.Phone;
entryToUpdate.CommitChanges();
Console.WriteLine("User Updated");
}
else
{
Console.WriteLine("User not found!");
}
}
catch (Exception e)
{
Console.WriteLine("Exception caught:\n\n" + e.ToString());
}
return true;
}
Maybe just a typo?
The third property you're trying to update:
entryToUpdate.Properties["1"].Value = SQLresult.City;
is that a one (1) in there? It should be a small L (l) instead.
Also: the manager's name must be the Distinguished Name of the manager - the whole
CN=Manager,CN=Ad Test,OU=Container Name, OU=Server Name,DC=us,DC=flg,DC=int
thing - not just the name itself.
If that doesn't help anything - just go back to old-school debugging technique:
update just a single property; if it fails --> that's your problem case - figure out why it's a problem.
If it works: uncomment a second property and run again
-> repeat over and over again, until you find your culprit

Create Windows User programmatically c# .net (using PricinpalUser / CreateProfile)

In a nutshell, what I'm trying to do is create a new user, which has the ability to log in.
I have plucked code from various sources, and tried to simplify it. However, I'm hitting a few stumbling blocks.
When I call UserPrincipal.Save() - it gives me an error
'The directory property cannot be found in the cache' with an
exception type of.. 'COMExceptioncrossed a native/managed boundary'.
For some reason, when I run my program directly (not through vs2010) it works fine. So I can get around that !
My main problem though, is that even though everything seems ok, when I try to log in, it comes up with the message 'loading desktop' or whatever it is, and then just says 'logging out'. So it's almost as if the profile hasn't been set up correctly.
The return value from the API 'CreateProfile' isn't 0, so maybe that's causing a problem.
Is there anything else I need to do ?
My Code is...
private void Run(string un, string pw)
{
UserPrincipal NewUP = CreateUser(un, pw);
AddGroup(NewUP, "Users");
AddGroup(NewUP, "HomeUsers");
CreateProfile(NewUP);
}
private UserPrincipal CreateUser(string Username, string Password)
{
PrincipalContext pc = new PrincipalContext(ContextType.Machine, Environment.MachineName);
UserPrincipal up = UserPrincipal.FindByIdentity(pc, IdentityType.SamAccountName, Username);
if (up == null)
{
up = new UserPrincipal(pc, Username, Password, true);
up.UserCannotChangePassword = false;
up.PasswordNeverExpires = false;
up.Save(); // this is where it crashes when I run through the debugger
}
return up;
}
private void AddGroup(UserPrincipal Up, string GroupName)
{
PrincipalContext pc = new PrincipalContext(ContextType.Machine, Environment.MachineName);
GroupPrincipal gp = GroupPrincipal.FindByIdentity(pc, GroupName);
if (!gp.Members.Contains(Up))
{
gp.Members.Add(Up);
gp.Save();
}
gp.Dispose();
}
private void CreateProfile(UserPrincipal Up)
{
int MaxPath = 240;
StringBuilder pathBuf = new StringBuilder(MaxPath);
uint pathLen = (uint)pathBuf.Capacity;
int Res = CreateProfile(Up.Sid.ToString(), Up.SamAccountName, pathBuf, pathLen);
}
Strangely, when this is run on a server machine (i.e. not my development machine) it works fine. I've got a feeling this is something to do with Windows 7, or my particular installation of it.
Thanks for your suggestions anyway.

System.DirectoryServices.DirectoryServicesCOMException (0x8007203B): A local error has occurred

When we try to search for a user in ActiveDirectory, we get that exception - 0x8007203B.
Basically we deployed a web service, which uses DirectoryEntry & DirectorySearcher class to find a user in AD, and sometimes this exception happens. But when we do IISReset, it again works fine.
Code is very simple like this:
DirectoryEntry domainUser = new DirectoryEntry("LDAP://xxx.yyy/dc=xxx,dc=yyy", "domain\user", "pwd", AuthenticationTypes.Secure);
DirectoryEntry result = new DirectorySearcher(domainUser, filter);
Only some times this happens. I don't have much information to provide, any guess much appreciated
This is how my filter looks like
public static string BuildFilter(DirectoryEntry dirEntry, string userName, string userMail)
{
try
{
string filter = string.Empty;
if (!string.IsNullOrEmpty(userName) && string.IsNullOrEmpty(userMail))
filter = string.Format(#"(&(objectClass=user)(samaccounttype=805306368)(|(CN={0})(samaccountname={0})))", userName);
else if (string.IsNullOrEmpty(userName) && !string.IsNullOrEmpty(userMail))
filter = string.Format(#"(&(objectClass=user)(samaccounttype=805306368)(mail={0}))", userMail);
else
filter = string.Format(#"(&(objectClass=user)(samaccounttype=805306368)(|(CN={0})(samaccountname={0})(mail={1})))", userName, userMail);
return filter;
}
catch (Exception ex)
{
_logger.Error("BuildUserSearch - Failed to build LDAP search", ex);
}
return null;
}
You say that this it's just append after some time. As DirectoryEntry and DirectorySearcher are built on COM object into disposable class I would first just add some using sections to be sure that underlying objects are corectly freed.
using(DirectoryEntry root = new DirectoryEntry(ldapPath))
{
using(DirectorySearcher searcher=new DirectorySearcher(root))
{
...
}
...
}
Any guess are appreciated?
Then here's mine:
ASP.NET: DirectoryServicesCOMException [...];
Windows Error Codes: Repair 0x8007203B. How To Repair 0x8007203B.
What makes me confuse is that you say it works most of the time...
Did this help?
P.S. I'll update if I think of anything else.

Categories