diff --git a/Yvand.LDAPCPSE/Yvand.LDAPCPSE.csproj b/Yvand.LDAPCPSE/Yvand.LDAPCPSE.csproj
index c1a3aaa..ff01a1e 100644
--- a/Yvand.LDAPCPSE/Yvand.LDAPCPSE.csproj
+++ b/Yvand.LDAPCPSE/Yvand.LDAPCPSE.csproj
@@ -65,6 +65,7 @@
False
references\SPSE\Microsoft.SharePoint.dll
+ False
diff --git a/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/Configuration/ClaimsProviderConstants.cs b/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/Configuration/ClaimsProviderConstants.cs
index 98cf5a6..d585dce 100644
--- a/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/Configuration/ClaimsProviderConstants.cs
+++ b/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/Configuration/ClaimsProviderConstants.cs
@@ -312,7 +312,7 @@ public class OperationContext
///
public List CurrentClaimTypeConfigList { get; private set; }
- public List LdapConnections { get; private set; }
+ public List LdapConnections { get; set; }
public OperationContext(ClaimsProviderSettings settings, OperationType currentRequestType, string input, SPClaim incomingEntity, Uri context, string[] entityTypes, string hierarchyNodeID, int maxCount)
{
diff --git a/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/Configuration/DirectoryConnection.cs b/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/Configuration/DirectoryConnection.cs
index 695c9ec..367397f 100644
--- a/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/Configuration/DirectoryConnection.cs
+++ b/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/Configuration/DirectoryConnection.cs
@@ -105,6 +105,17 @@ public string[] GroupMembershipLdapAttributes
[Persisted]
private string[] _GroupMembershipLdapAttributes = new string[] { "memberOf", "uniquememberof" };
+ ///
+ /// Get or set a LDAP filter specific to this LDAP connection
+ ///
+ public string CustomFilter
+ {
+ get { return _CustomFilter; }
+ set { _CustomFilter = value; }
+ }
+ [Persisted]
+ private string _CustomFilter;
+
///
/// DirectoryEntry used to make LDAP queries
///
diff --git a/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/LDAPCPSE.cs b/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/LDAPCPSE.cs
index 47650c7..45caa31 100644
--- a/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/LDAPCPSE.cs
+++ b/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/LDAPCPSE.cs
@@ -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 groups = this.EntityProvider.GetEntityGroups(currentContext);
@@ -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 entities = SearchOrValidate(currentContext);
if (entities == null || entities.Count == 0) { return; }
foreach (PickerEntity entity in entities)
@@ -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 entities = this.SearchOrValidate(currentContext);
if (entities == null || entities.Count == 0) { return; }
SPProviderHierarchyNode matchNode = null;
@@ -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 entities = this.SearchOrValidate(currentContext);
if (entities?.Count == 1)
{
@@ -947,6 +951,10 @@ protected virtual string FormatPermissionDisplayText(LdapEntityProviderResult di
}
return entityDisplayText;
}
+
+ public virtual void ValidateRuntimeSettings(OperationContext operationContext)
+ {
+ }
#endregion
///
diff --git a/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/LdapEntityProvider.cs b/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/LdapEntityProvider.cs
index 2cda0bf..2038c5d 100644
--- a/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/LdapEntityProvider.cs
+++ b/Yvand.LDAPCPSE/Yvand.LdapClaimsProvider/LdapEntityProvider.cs
@@ -411,30 +411,42 @@ public override List SearchOrValidateEntities(Operatio
return new List(0);
}
- string ldapFilter = this.BuildFilter(currentContext);
+ //string ldapFilter = this.BuildFilter(currentContext);
List 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 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)
@@ -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))
@@ -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;
}
@@ -484,7 +496,7 @@ protected string AddLdapAttributeToFilter(OperationContext currentContext, strin
return filter;
}
- protected List QueryLDAPServers(OperationContext currentContext, string ldapFilter)
+ protected List QueryLDAPServers(OperationContext currentContext)
{
if (this.Settings.LdapConnections == null || this.Settings.LdapConnections.Count == 0) { return null; }
object lockResults = new object();
@@ -492,9 +504,15 @@ protected List QueryLDAPServers(OperationContext curre
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)
diff --git a/custom-claims-provider-samples/LDAPCPSE_basic/LDAPCPSE_Custom.cs b/custom-claims-provider-samples/LDAPCPSE_basic/LDAPCPSE_Custom.cs
index 86eb028..bfa59f2 100644
--- a/custom-claims-provider-samples/LDAPCPSE_basic/LDAPCPSE_Custom.cs
+++ b/custom-claims-provider-samples/LDAPCPSE_basic/LDAPCPSE_Custom.cs
@@ -1,4 +1,5 @@
-using Yvand.LdapClaimsProvider;
+using System;
+using Yvand.LdapClaimsProvider;
using Yvand.LdapClaimsProvider.Configuration;
namespace LDAPCPSE_basic
@@ -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)";
+ }
+ }
}
}