124 lines
3.7 KiB
C#

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<LdapUser> SearchInAD(
string targetOU,
string query,
SearchScope scope
)
{
// search as admin
return this.SearchInADAsUser(targetOU, query, scope, this.AdminBind, this.AdminPass);
}
public List<LdapUser> 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<LdapUser>();
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;
}
}