using System;
using System.DirectoryServices;
using System.Linq;
using DataModel.Models;
using NLog;
using SearchResult = System.DirectoryServices.SearchResult;
namespace WebInterface.Helpers
{
///
/// LDAP server interface helper methods
///
public class LDAPHelper
{
///
/// LDAP user lookup format
///
private const string LDAP_LOOKUP_FORMAT = "(sAMAccountName={0})";
///
/// Shared logger instance
///
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
///
/// Authenticates the user's credentials against the given LDAP server
///
/// LDAP username
/// LDAP password
/// LDAP server URL
/// LDAP group to filter for
/// Whether or not user's credentials are valid
public static bool Authenticate(string username, string password, string serverURL, string ldapGroup = null)
{
bool result = false;
try
{
//Form full LDAP URL
string ldapURL = $"LDAP://{serverURL}";
//Attempt to find entry
DirectoryEntry entry = new DirectoryEntry(ldapURL, username, password);
object val = entry.NativeObject;
result = true;
}
catch (Exception error)
{
//Log but do not forward error
logger.Error("Authenticate: failed to authenticate user '{0}' against LDAP server '{1}': {2}.", username, serverURL, error.Message);
}
return result;
}
///
/// Checks if user is in given group
///
/// LDAP username
/// LDAP password
/// LDAP server URL
/// LDAP group to filter for
/// LDAP search filter
/// Whether or not user belongs to given group
public static bool IsInGroup(string username, string password, string serverURL, string ldapGroup, string ldapFilter = LDAP_LOOKUP_FORMAT)
{
try
{
//Form full LDAP URL
string ldapURL = $"LDAP://{serverURL}";
//Create a LDAP searcher
DirectorySearcher searcher = new DirectorySearcher
{
SearchRoot = new DirectoryEntry(ldapURL, username, password),
Filter = string.Format(ldapFilter, username)
};
foreach (SearchResult searchResult in searcher.FindAll())
{
DirectoryEntry directoryEntry = searchResult.GetDirectoryEntry();
foreach (var groupName in directoryEntry.Properties["memberOf"])
{
if (string.Equals(groupName.ToString(), ldapGroup, StringComparison.CurrentCultureIgnoreCase))
{
return true;
}
}
}
}
catch (Exception error)
{
//Log but do not forward error
logger.Error("Authenticate: failed to authenticate user '{0}' against LDAP server '{1}': {2}.", username, serverURL, error.Message);
}
return false;
}
///
/// Searches LDAP server for matching entry
///
/// URL for LDAP server to search
/// LDAP server binding username
/// LDAP server binding password
/// LDAP search filter
/// Collection of matching LDAP entries
public static LDAPEntry LookupUser(string username, string password, string serverURL, string ldapFilter = LDAP_LOOKUP_FORMAT)
{
LDAPEntry result = null;
//Form full LDAP URL
string ldapURL = $"LDAP://{serverURL}";
//Create a LDAP searcher
DirectorySearcher searcher = new DirectorySearcher
{
SearchRoot = new DirectoryEntry(ldapURL, username, password),
Filter = string.Format(ldapFilter, username)
};
//Loop through search results
foreach (SearchResult searchResult in searcher.FindAll())
{
//Parse the entry's details
result = new LDAPEntry()
{
DN = ExtractProperty(searchResult, "distinguishedName"),
Username = username.ToLower(),
FirstName = ExtractProperty(searchResult, "givenName"),
LastName = ExtractProperty(searchResult, "sn"),
EmailAddress = ExtractProperty(searchResult, "mail"),
Title = ExtractProperty(searchResult, "title")
};
if (string.IsNullOrEmpty(result.FirstName) && !string.IsNullOrEmpty(result.DisplayName))
{
result.FirstName = result.DisplayName;
}
if (string.IsNullOrEmpty(result.LastName) && !string.IsNullOrEmpty(result.DisplayName))
{
result.LastName = result.DisplayName;
}
}
return result;
}
///
/// Extracts the specified property from the LDAP search result
///
/// LDAP search result to parse property from
/// Lookup key for property
/// Property value if it exists, empty string if it does not exist
private static string ExtractProperty(SearchResult result, string key)
{
return result.Properties[key].Count > 0 ? (string)result.Properties[key][0] : string.Empty;
}
}
}