Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimize RootDse search and add cancellation tokens to async search extensions. #173

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 32 additions & 31 deletions LdapForNet/LdapSearchExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using LdapForNet.Utils;
using static LdapForNet.Native.Native;
Expand All @@ -8,50 +9,49 @@ namespace LdapForNet
{
public static class LdapSearchExtensions
{
public static IList<LdapEntry> SearchByCn(this ILdapConnection connection, string @base, string cn,
LdapSearchScope scope = LdapSearchScope.LDAP_SCOPE_SUBTREE)
public static LdapEntry GetRootDse(this ILdapConnection connection)
{
return connection.Search(@base, $"(cn={cn})", scope: scope);
return connection.Search(
null,
"(objectclass=*)",
new[] { "*", "+", "supportedExtension" },
LdapSearchScope.LDAP_SCOPE_BASE)
.First();
}

public static LdapEntry GetRootDse(this ILdapConnection connection)
public static async Task<LdapEntry> GetRootDseAsync(this ILdapConnection connection,
CancellationToken token = default)
{
var result = connection.Search(null, "(objectclass=*)",
new[]
{
"namingContexts", "subschemaSubentry", "supportedLDAPVersion", "supportedSASLMechanisms",
"supportedExtension", "supportedControl", "supportedFeatures", "vendorName", "vendorVersion"
}, LdapSearchScope.LDAP_SCOPE_BASE)
.FirstOrDefault();
if (result == null)
{
return null;
}

var rootDse = connection.Search(null, "(objectclass=*)", scope: LdapSearchScope.LDAP_SCOPE_BASE).First();
foreach (var attribute in rootDse.DirectoryAttributes)
{
result.DirectoryAttributes.Remove(attribute.Name);
result.DirectoryAttributes.Add(attribute);
}
return (await connection.SearchAsync(
null,
"(objectclass=*)",
new[] { "*", "+", "supportedExtension" },
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it doesn't work on unix subsystems. Need to specify all properties

new[]
                     {
                         "namingContexts", "subschemaSubentry", "supportedLDAPVersion", "supportedSASLMechanisms",
                         "supportedExtension", "supportedControl", "supportedFeatures", "vendorName", "vendorVersion"
                     }
                     ```

LdapSearchScope.LDAP_SCOPE_BASE,
token))
.First();
}

return result;
public static IList<LdapEntry> SearchByCn(this ILdapConnection connection, string @base, string cn,
LdapSearchScope scope = LdapSearchScope.LDAP_SCOPE_SUBTREE)
{
return connection.Search(@base, $"(cn={cn})", scope: scope);
}

public static async Task<IList<LdapEntry>> SearchByCnAsync(this ILdapConnection connection, string @base,
string cn, LdapSearchScope scope = LdapSearchScope.LDAP_SCOPE_SUBTREE)
string cn, LdapSearchScope scope = LdapSearchScope.LDAP_SCOPE_SUBTREE, CancellationToken token = default)
{
return await connection.SearchAsync(@base, $"(cn={cn})", scope: scope);
return await connection.SearchAsync(@base, $"(cn={cn})", scope: scope, token: token);
}

public static IList<LdapEntry> SearchByCn(this ILdapConnection connection, string cn)
{
return connection.SearchByCn(LdapUtils.GetDnFromHostname(), cn);
}

public static async Task<IList<LdapEntry>> SearchByCnAsync(this ILdapConnection connection, string cn)
public static async Task<IList<LdapEntry>> SearchByCnAsync(this ILdapConnection connection, string cn,
CancellationToken token = default)
{
return await connection.SearchByCnAsync(LdapUtils.GetDnFromHostname(), cn);
return await connection.SearchByCnAsync(LdapUtils.GetDnFromHostname(), cn, token: token);
}

public static IList<LdapEntry> SearchBySid(this ILdapConnection connection, string @base, string sid,
Expand All @@ -62,20 +62,21 @@ public static IList<LdapEntry> SearchBySid(this ILdapConnection connection, stri
}

public static async Task<IList<LdapEntry>> SearchBySidAsync(this ILdapConnection connection, string @base,
string sid, LdapSearchScope scope = LdapSearchScope.LDAP_SCOPE_SUBTREE)
string sid, LdapSearchScope scope = LdapSearchScope.LDAP_SCOPE_SUBTREE, CancellationToken token = default)
{
var hex = HexEscaper.Escape(LdapSidConverter.ConvertToHex(sid));
return await connection.SearchAsync(@base, $"(objectSID={hex})", scope: scope);
return await connection.SearchAsync(@base, $"(objectSID={hex})", scope: scope, token: token);
}

public static IList<LdapEntry> SearchBySid(this ILdapConnection connection, string sid)
{
return connection.SearchBySid(LdapUtils.GetDnFromHostname(), sid);
}

public static async Task<IList<LdapEntry>> SearchBySidAsync(this ILdapConnection connection, string sid)
public static async Task<IList<LdapEntry>> SearchBySidAsync(this ILdapConnection connection, string sid,
CancellationToken token = default)
{
return await connection.SearchBySidAsync(LdapUtils.GetDnFromHostname(), sid);
return await connection.SearchBySidAsync(LdapUtils.GetDnFromHostname(), sid, token: token);
}
}
}