Skip to content

Commit

Permalink
Add property CustomFilter to class DirectoryConnection
Browse files Browse the repository at this point in the history
  • Loading branch information
Yvand committed Sep 18, 2024
1 parent 327e2f2 commit 80fa4bc
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 11 deletions.
1 change: 1 addition & 0 deletions Yvand.LDAPCPSE/Yvand.LDAPCPSE.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
<Reference Include="Microsoft.SharePoint, Version=16.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>references\SPSE\Microsoft.SharePoint.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ public class OperationContext
/// </summary>
public List<ClaimTypeConfig> CurrentClaimTypeConfigList { get; private set; }

public List<DirectoryConnection> LdapConnections { get; private set; }
public List<DirectoryConnection> LdapConnections { get; set; }

public OperationContext(ClaimsProviderSettings settings, OperationType currentRequestType, string input, SPClaim incomingEntity, Uri context, string[] entityTypes, string hierarchyNodeID, int maxCount)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,17 @@ public string[] GroupMembershipLdapAttributes
[Persisted]
private string[] _GroupMembershipLdapAttributes = new string[] { "memberOf", "uniquememberof" };

/// <summary>
/// Get or set a LDAP filter specific to this LDAP connection
/// </summary>
public string CustomFilter
{
get { return _CustomFilter; }
set { _CustomFilter = value; }
}
[Persisted]
private string _CustomFilter;

/// <summary>
/// DirectoryEntry used to make LDAP queries
/// </summary>
Expand Down
8 changes: 8 additions & 0 deletions Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/LDAPCPSE.cs
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,7 @@ protected void AugmentEntity(Uri context, SPClaim entity, SPClaimProviderContext

Logger.Log($"[{Name}] Starting augmentation for user '{decodedEntity.Value}'.", TraceSeverity.Verbose, EventSeverity.Information, TraceCategory.Augmentation);
currentContext = new OperationContext(this.Settings as ClaimsProviderSettings, OperationType.Augmentation, String.Empty, decodedEntity, context, null, null, Int32.MaxValue);
ValidateRuntimeSettings(currentContext);
Stopwatch timer = new Stopwatch();
timer.Start();
List<string> groups = this.EntityProvider.GetEntityGroups(currentContext);
Expand Down Expand Up @@ -439,6 +440,7 @@ protected override void FillResolve(Uri context, string[] entityTypes, string re
try
{
OperationContext currentContext = new OperationContext(this.Settings as ClaimsProviderSettings, OperationType.Search, resolveInput, null, context, entityTypes, null, 30);
ValidateRuntimeSettings(currentContext);
List<PickerEntity> entities = SearchOrValidate(currentContext);
if (entities == null || entities.Count == 0) { return; }
foreach (PickerEntity entity in entities)
Expand Down Expand Up @@ -470,6 +472,7 @@ protected override void FillSearch(Uri context, string[] entityTypes, string sea
try
{
OperationContext currentContext = new OperationContext(this.Settings as ClaimsProviderSettings, OperationType.Search, searchPattern, null, context, entityTypes, hierarchyNodeID, maxCount);
ValidateRuntimeSettings(currentContext);
List<PickerEntity> entities = this.SearchOrValidate(currentContext);
if (entities == null || entities.Count == 0) { return; }
SPProviderHierarchyNode matchNode = null;
Expand Down Expand Up @@ -523,6 +526,7 @@ protected override void FillResolve(Uri context, string[] entityTypes, SPClaim r
if (!String.Equals(resolveInput.OriginalIssuer, this.OriginalIssuerName, StringComparison.InvariantCultureIgnoreCase)) { return; }

OperationContext currentContext = new OperationContext(this.Settings as ClaimsProviderSettings, OperationType.Validation, resolveInput.Value, resolveInput, context, entityTypes, null, 1);
ValidateRuntimeSettings(currentContext);
List<PickerEntity> entities = this.SearchOrValidate(currentContext);
if (entities?.Count == 1)
{
Expand Down Expand Up @@ -947,6 +951,10 @@ protected virtual string FormatPermissionDisplayText(LdapEntityProviderResult di
}
return entityDisplayText;
}

public virtual void ValidateRuntimeSettings(OperationContext operationContext)
{
}
#endregion

/// <summary>
Expand Down
36 changes: 27 additions & 9 deletions Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/LdapEntityProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -411,30 +411,42 @@ public override List<LdapEntityProviderResult> SearchOrValidateEntities(Operatio
return new List<LdapEntityProviderResult>(0);
}

string ldapFilter = this.BuildFilter(currentContext);
//string ldapFilter = this.BuildFilter(currentContext);
List<LdapEntityProviderResult> LdapSearchResult = null;
SPSecurity.RunWithElevatedPrivileges(delegate ()
{
LdapSearchResult = this.QueryLDAPServers(currentContext, ldapFilter);
LdapSearchResult = this.QueryLDAPServers(currentContext);
});
return LdapSearchResult;
}

protected string BuildFilter(OperationContext currentContext)
protected string BuildFilter(List<ClaimTypeConfig> claimTypeConfigList, string inputText, bool exactSearch, DirectoryConnection ldapConnection)
{
if (ldapConnection != null && String.IsNullOrWhiteSpace(ldapConnection.CustomFilter))
{ // In this case, the generic LDAP filter can be used
return String.Empty;
}

StringBuilder filter = new StringBuilder();
if (this.Settings.FilterEnabledUsersOnly)
{
filter.Append(ClaimsProviderConstants.LDAPFilterEnabledUsersOnly);
}

// A LDAP connection may have a custom filter
if (!String.IsNullOrWhiteSpace(ldapConnection?.CustomFilter))
{
filter.Append(ldapConnection.CustomFilter);
}

filter.Append("(| "); // START OR

// Fix bug https://github.com/Yvand/LDAPCP/issues/53 by escaping special characters with their hex representation as documented in https://ldap.com/ldap-filters/
string input = Utils.EscapeSpecialCharacters(currentContext.Input);
string input = Utils.EscapeSpecialCharacters(inputText);

foreach (var ctConfig in currentContext.CurrentClaimTypeConfigList)
foreach (var ctConfig in claimTypeConfigList)
{
filter.Append(AddLdapAttributeToFilter(currentContext, input, ctConfig));
filter.Append(AddLdapAttributeToFilter(exactSearch, input, ctConfig));
}

if (this.Settings.FilterEnabledUsersOnly)
Expand All @@ -446,7 +458,7 @@ protected string BuildFilter(OperationContext currentContext)
return filter.ToString();
}

protected string AddLdapAttributeToFilter(OperationContext currentContext, string input, ClaimTypeConfig attributeConfig)
protected string AddLdapAttributeToFilter(bool exactSearch, string input, ClaimTypeConfig attributeConfig)
{
// Prevent use of wildcard for LDAP attributes which do not support it
if (String.Equals(attributeConfig.DirectoryObjectAttribute, "objectSid", StringComparison.InvariantCultureIgnoreCase))
Expand All @@ -460,7 +472,7 @@ protected string AddLdapAttributeToFilter(OperationContext currentContext, strin

// Test if wildcard(s) should be added to the input
string inputFormatted;
if (currentContext.ExactSearch || !attributeConfig.DirectoryObjectAttributeSupportsWildcard)
if (exactSearch || !attributeConfig.DirectoryObjectAttributeSupportsWildcard)
{
inputFormatted = input;
}
Expand All @@ -484,17 +496,23 @@ protected string AddLdapAttributeToFilter(OperationContext currentContext, strin
return filter;
}

protected List<LdapEntityProviderResult> QueryLDAPServers(OperationContext currentContext, string ldapFilter)
protected List<LdapEntityProviderResult> QueryLDAPServers(OperationContext currentContext)
{
if (this.Settings.LdapConnections == null || this.Settings.LdapConnections.Count == 0) { return null; }
object lockResults = new object();
List<LdapEntityProviderResult> results = new List<LdapEntityProviderResult>();
Stopwatch globalStopWatch = new Stopwatch();
globalStopWatch.Start();

string ldapFilter = this.BuildFilter(currentContext.CurrentClaimTypeConfigList, currentContext.Input, currentContext.ExactSearch, null);
//foreach (var ldapConnection in this.Settings.LdapConnections.Where(x => x.LdapEntry != null))
Parallel.ForEach(this.Settings.LdapConnections.Where(x => x.LdapEntry != null), ldapConnection =>
{
if (!String.IsNullOrWhiteSpace(ldapConnection.CustomFilter))
{
// The LDAP filter needs to be entirely rewritten to include the filter specified in current connection
ldapFilter = this.BuildFilter(currentContext.CurrentClaimTypeConfigList, currentContext.Input, currentContext.ExactSearch, ldapConnection);
}
Debug.WriteLine($"ldapConnection: Path: {ldapConnection.LdapEntry.Path}, UseDefaultADConnection: {ldapConnection.UseDefaultADConnection}");
Logger.LogDebug($"ldapConnection: Path: {ldapConnection.LdapEntry.Path}, UseDefaultADConnection: {ldapConnection.UseDefaultADConnection}");
using (DirectoryEntry directory = ldapConnection.LdapEntry)
Expand Down
13 changes: 12 additions & 1 deletion custom-claims-provider-samples/LDAPCPSE_basic/LDAPCPSE_Custom.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Yvand.LdapClaimsProvider;
using System;
using Yvand.LdapClaimsProvider;
using Yvand.LdapClaimsProvider.Configuration;

namespace LDAPCPSE_basic
Expand All @@ -25,5 +26,15 @@ public override ILdapProviderSettings GetSettings()
settings.EntityDisplayTextPrefix = "(custom) ";
return settings;
}

public override void ValidateRuntimeSettings(OperationContext operationContext)
{
Uri currentSite = operationContext.UriContext;
string currentUser = operationContext.UserInHttpContext?.Value;
if (currentSite.Port == 6000)
{
operationContext.LdapConnections[0].CustomFilter = "(telephoneNumber=00110011)";
}
}
}
}

0 comments on commit 80fa4bc

Please sign in to comment.