using System.Collections; using System.ComponentModel; using song_of_the_day; using System.DirectoryServices.Protocols; using System.Linq; public class LdapIntegration { public static LdapIntegration? Instance; private readonly string[] attributesToQuery = new string[] { "uid", "givenName", "sn", "mail" }; public LdapIntegration(string uri, int port, string adminBind, string adminPass) { this.Uri = uri; this.Port = port; this.AdminBind = adminBind; this.AdminPass = adminPass; } private string Uri { get; set; } private int Port { get; set; } private string AdminBind { get; set; } private string AdminPass { get; set; } public bool TestLogin(string username, string password) { try { var userList = this.SearchInADAsUser( AppConfiguration.Instance.LDAPConfig.LDAPQueryBase, $"(uid={username})", SearchScope.Subtree, username, password); } catch (LdapException ex) { if (ex.Message.Contains("credential is invalid")) { return false; } throw; } return true; } public List SearchInAD( string targetOU, string query, SearchScope scope ) { // search as admin return this.SearchInADAsUser(targetOU, query, scope, this.AdminBind, this.AdminPass); } public List SearchInADAsUser( string targetOU, string query, SearchScope scope, string userName, string userPass ) { // on Windows the authentication type is Negotiate, so there is no need to prepend // AD user login with domain. On other platforms at the moment only // Basic authentication is supported var authType = AuthType.Basic; var user = userName.StartsWith("cn=") || userName.StartsWith("uid=") ? userName : "uid=" + userName + "," + AppConfiguration.Instance.LDAPConfig.LDAPUserQueryBase; //var connection = new LdapConnection(ldapServer) var connection = new LdapConnection( new LdapDirectoryIdentifier(this.Uri, this.Port) ) { AuthType = authType, Credential = new(user, userPass) }; // the default one is v2 (at least in that version), and it is unknown if v3 // is actually needed, but at least Synology LDAP works only with v3, // and since our Exchange doesn't complain, let it be v3 connection.SessionOptions.ProtocolVersion = 3; // this is for connecting via LDAPS (636 port). It should be working, // according to https://github.com/dotnet/runtime/issues/43890, // but it doesn't (at least with Synology DSM LDAP), although perhaps // for a different reason //connection.SessionOptions.SecureSocketLayer = true; connection.Bind(); var request = new SearchRequest(targetOU, query, scope, attributesToQuery); var response = (System.DirectoryServices.Protocols.SearchResponse)connection.SendRequest(request); var userList = new List(); foreach (SearchResultEntry result in response.Entries) { userList.Add(new LdapUser() { UserId = result.Attributes["uid"][0].ToString(), FirstName = result.Attributes["givenName"][0].ToString(), LastName = result.Attributes["sn"][0].ToString(), Email = result.Attributes["mail"][0].ToString(), }); } connection.Dispose(); return userList; } }