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; } } }