//
// Don't forget to remove the HTML tags above and at the end of the file
using System;
using System.Collections;
using System.Xml;
using System.DirectoryServices;
using System.Runtime.InteropServices;
///
/// Example of LDAP Authentication code using ADSI with MCIT custom error messages
/// written by Dmitriy Kashchenko, IDM team
public class LdapAuthetication
{
// const
private const string ERR_NOT_FOUND = "(0x80072030): not found";
// LDAP metrics
private string _ldapserver = "LDAP://ldap.ent.med.umich.edu:636/";
private string _topContainer = "dc=med,dc=umich,dc=edu";
private String _defaultFilter = "(uid={0})";
// errors handling
// messages file name
private string _messages = "ldapautherrors.xml";
// variables
private string _errorMsg;
private string _provider;
private const string nodeKey = "message";
private const string indexAttr = "index";
private Hashtable errors = null;
private void parseFile(string fname)
{
XmlTextReader node = new XmlTextReader(fname);
node.WhitespaceHandling = WhitespaceHandling.None;
while (node.Read())
{
if (node.NodeType == XmlNodeType.Element && node.Name.Equals(nodeKey))
{
if (node.HasAttributes)
{
string index = node.GetAttribute("index");
node.Read();
string message = node.Value;
errors.Add(index, message);
}
}
}
node.Close();
}
[DllImport("activeds.dll", ExactSpelling = true, EntryPoint = "ADsGetLastError", CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
private static extern int ADsGetLastError(ref int error, IntPtr errorbuf, int errorbuflen, IntPtr namebuf, int namebuflen);
private int getExtendedError()
{
IntPtr errorbuf = (IntPtr)0;
IntPtr namebuf = (IntPtr)0;
int error = 0;
try
{
errorbuf = Marshal.AllocHGlobal(256 * 2);
namebuf = Marshal.AllocHGlobal(256 * 2);
ADsGetLastError(ref error, errorbuf, 256, namebuf, 256);
_errorMsg = Marshal.PtrToStringUni(errorbuf);
_provider = Marshal.PtrToStringUni(namebuf);
return error;
}
finally
{
if (errorbuf != (IntPtr)0) Marshal.FreeHGlobal(errorbuf);
if (namebuf != (IntPtr)0) Marshal.FreeHGlobal(namebuf);
}
}
public string getErrorMessage(Exception e)
{
string rc = e.ToString();
if (errors != null)
{
int ee = getExtendedError();
if (ee != 0) rc = _errorMsg;
foreach (DictionaryEntry entry in errors)
{
string index = (string)entry.Key;
if (rc.IndexOf(index) != -1)
{
rc = (string)entry.Value;
break;
}
}
}
return rc;
}
public LdapAuthetication()
{
errors = new Hashtable();
parseFile(_messages);
}
public DirectoryEntry Authenticate(string user, string password)
{
DirectoryEntry de = new DirectoryEntry(_ldapserver+_topContainer);
// required to initate anonymous bind
de.AuthenticationType = System.DirectoryServices.AuthenticationTypes.ServerBind;
DirectorySearcher searcher = new DirectorySearcher(de);
//set the filer. the filter syntax is the standard LDAP filter syntax
searcher.Filter = string.Format(_defaultFilter, user);
SearchResult result = searcher.FindOne();
if (result == null) throw new Exception(ERR_NOT_FOUND);
de = result.GetDirectoryEntry();
// Distingushed Name of the found account
string DN = de.Path.Substring (de.Path.ToUpper().IndexOf("CN="));
// Close search connection
de.Close();
// now bind
de = new DirectoryEntry(_ldapserver+_topContainer);
de.Username = DN;
de.Password = password;
de.AuthenticationType = System.DirectoryServices.AuthenticationTypes.SecureSocketsLayer;
Object obj = de.NativeObject;
return de;
}
public static void Main(string[] args)
{
LdapAuthetication auth = new LdapAuthetication();
if (args.Length == 2)
{
try
{
DirectoryEntry de = auth.Authenticate(args[0], args[1]);
Console.WriteLine("Authentication Succesful: " + de.Username);
}
catch (Exception e)
{
Console.WriteLine(auth.getErrorMessage(e));
}
}
else
{
Console.WriteLine("Usage: LdapAuthentication Username Password");
}
}
}
//