protected QbeFilterDescription BuildQbeFilterDescription(Principal p) { QbeFilterDescription qbeFilterDescription = new QbeFilterDescription(); if (p != null) { this.BuildFilterSet(p, StoreCtx.principalProperties, qbeFilterDescription); } if (p as AuthenticablePrincipal != null) { this.BuildFilterSet(p, StoreCtx.authenticablePrincipalProperties, qbeFilterDescription); } if (p as UserPrincipal != null) { if (!p.GetChangeStatusForProperty("AuthenticablePrincipal.AccountInfo.AccountExpirationDate") || !p.GetChangeStatusForProperty("AuthenticablePrincipal.AccountInfoExpired")) { this.BuildFilterSet(p, StoreCtx.userProperties, qbeFilterDescription); } else { object[] externalForm = new object[1]; externalForm[0] = PropertyNamesExternal.GetExternalForm("AuthenticablePrincipal.AccountInfo.AccountExpirationDate"); throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, StringResources.StoreCtxMultipleFiltersForPropertyUnsupported, externalForm)); } } if (p as GroupPrincipal != null) { this.BuildFilterSet(p, StoreCtx.groupProperties, qbeFilterDescription); } if (p as ComputerPrincipal != null) { this.BuildFilterSet(p, StoreCtx.computerProperties, qbeFilterDescription); } return(qbeFilterDescription); }
protected QbeFilterDescription BuildQbeFilterDescription(Principal p) { QbeFilterDescription qbeFilterDescription = new QbeFilterDescription(); // We don't have to check to make sure the application didn't try to set any // disallowed properties (i..e, referential properties, such as Group.Members), // because that check was enforced by the PrincipalSearcher in its // FindAll() and GetUnderlyingSearcher() methods, by calling // PrincipalSearcher.HasReferentialPropertiesSet(). if (p is Principal) { BuildFilterSet(p, principalProperties, qbeFilterDescription); } if (p is AuthenticablePrincipal) { BuildFilterSet(p, authenticablePrincipalProperties, qbeFilterDescription); } if (p is UserPrincipal) // includes AccountInfo and PasswordInfo { // AcctInfoExpirationDate and AcctInfoExpiredAccount represent filters on the same property // check that only one is specified if (p.GetChangeStatusForProperty(PropertyNames.AcctInfoExpirationDate) && p.GetChangeStatusForProperty(PropertyNames.AcctInfoExpiredAccount)) { throw new InvalidOperationException( String.Format( CultureInfo.CurrentCulture, StringResources.StoreCtxMultipleFiltersForPropertyUnsupported, PropertyNamesExternal.GetExternalForm(ExpirationDateFilter.PropertyNameStatic))); } BuildFilterSet(p, userProperties, qbeFilterDescription); } if (p is GroupPrincipal) { BuildFilterSet(p, groupProperties, qbeFilterDescription); } if (p is ComputerPrincipal) { BuildFilterSet(p, computerProperties, qbeFilterDescription); } return(qbeFilterDescription); }
// The core query operation. // Given a PrincipalSearcher containg a query filter, transforms it into the store schema // and performs the query to get a collection of matching native objects (up to a maximum of sizeLimit, // or uses the sizelimit already set on the DirectorySearcher if sizeLimit == -1). // If the PrincipalSearcher does not have a query filter (PrincipalSearcher.QueryFilter == null), // matches all principals in the store. // // The collection may not be complete, i.e., paging - the returned ResultSet will automatically // page in additional results as needed. internal override ResultSet Query(PrincipalSearcher ps, int sizeLimit) { GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMStoreCtx", "Query"); Debug.Assert(sizeLimit >= -1); // Build the description of the properties we'll filter by. In SAMStoreCtx, the "native" searcher // is simply the QbeFilterDescription, which will be passed to the SAMQuerySet to use to // manually filter out non-matching results. QbeFilterDescription propertiesToMatch = (QbeFilterDescription)PushFilterToNativeSearcher(ps); // Get the entries we'll iterate over. Write access to Children is controlled through the // ctxBaseLock, but we don't want to have to hold that lock while we're iterating over all // the child entries. So we have to clone the ctxBase --- not ideal, but it prevents // multithreading issues. DirectoryEntries entries = SDSUtils.BuildDirectoryEntry(_ctxBase.Path, _credentials, _authTypes).Children; Debug.Assert(entries != null); // Determine the principal types of interest. The SAMQuerySet will use this to restrict // the types of DirectoryEntry objects returned. Type qbeFilterType = typeof(Principal); if (ps.QueryFilter != null) { qbeFilterType = ps.QueryFilter.GetType(); } List <string> schemaTypes = GetSchemaFilter(qbeFilterType); // Create the ResultSet that will perform the client-side filtering SAMQuerySet resultSet = new SAMQuerySet( schemaTypes, entries, _ctxBase, sizeLimit, this, new QbeMatcher(propertiesToMatch)); return(resultSet); }
// Pushes the query represented by the QBE filter into the PrincipalSearcher's underlying native // searcher object (creating a fresh native searcher and assigning it to the PrincipalSearcher if one // doesn't already exist) and returns the native searcher. // If the PrincipalSearcher does not have a query filter set (PrincipalSearcher.QueryFilter == null), // produces a query that will match all principals in the store. // // For stores which don't have a native searcher (SAM), the StoreCtx // is free to create any type of object it chooses to use as its internal representation of the query. // // Also adds in any clauses to the searcher to ensure that only principals, not mere // contacts, are retrieved from the store. internal override object PushFilterToNativeSearcher(PrincipalSearcher ps) { // There's no underlying searcher for SAM Debug.Assert(ps.UnderlyingSearcher == null); Principal qbeFilter = ps.QueryFilter; QbeFilterDescription filters; // If they specified a filter object, extract the set properties from it. // Otherwise, use an empty set. Note that we don't worry about filtering by // the type of the qbeFilter object (e.g., restricting the returned principals // to only Users, or only Groups) --- that's handled in Query(). if (qbeFilter != null) { filters = BuildQbeFilterDescription(qbeFilter); } else { filters = new QbeFilterDescription(); } return(filters); }
protected QbeFilterDescription BuildQbeFilterDescription(Principal p) { QbeFilterDescription qbeFilterDescription = new QbeFilterDescription(); if (p != null) { this.BuildFilterSet(p, StoreCtx.principalProperties, qbeFilterDescription); } if (p as AuthenticablePrincipal != null) { this.BuildFilterSet(p, StoreCtx.authenticablePrincipalProperties, qbeFilterDescription); } if (p as UserPrincipal != null) { if (!p.GetChangeStatusForProperty("AuthenticablePrincipal.AccountInfo.AccountExpirationDate") || !p.GetChangeStatusForProperty("AuthenticablePrincipal.AccountInfoExpired")) { this.BuildFilterSet(p, StoreCtx.userProperties, qbeFilterDescription); } else { object[] externalForm = new object[1]; externalForm[0] = PropertyNamesExternal.GetExternalForm("AuthenticablePrincipal.AccountInfo.AccountExpirationDate"); throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, StringResources.StoreCtxMultipleFiltersForPropertyUnsupported, externalForm)); } } if (p as GroupPrincipal != null) { this.BuildFilterSet(p, StoreCtx.groupProperties, qbeFilterDescription); } if (p as ComputerPrincipal != null) { this.BuildFilterSet(p, StoreCtx.computerProperties, qbeFilterDescription); } return qbeFilterDescription; }
private void BuildFilterSet(Principal p, string[] propertySet, QbeFilterDescription qbeFilterDescription) { string[] strArrays = propertySet; for (int i = 0; i < (int)strArrays.Length; i++) { string str = strArrays[i]; if (p.GetChangeStatusForProperty(str)) { object valueForProperty = p.GetValueForProperty(str); if (valueForProperty as PrincipalValueCollection<string> == null) { if (valueForProperty as X509Certificate2Collection == null) { object obj = FilterFactory.CreateFilter(str); if (valueForProperty != null) { if (!valueForProperty as bool) { if (valueForProperty as string == null) { if (valueForProperty as GroupScope == GroupScope.Local) { if (valueForProperty as byte[] == null) { if (valueForProperty as DateTime? == null) { if (valueForProperty as ExtensionCache == null) { if (valueForProperty as QbeMatchType != null) { ((FilterBase)obj).Value = (QbeMatchType)valueForProperty; } } else { ((FilterBase)obj).Value = (ExtensionCache)valueForProperty; } } else { ((FilterBase)obj).Value = (DateTime?)valueForProperty; } } else { ((FilterBase)obj).Value = (byte[])valueForProperty; } } else { ((FilterBase)obj).Value = (GroupScope)valueForProperty; } } else { ((FilterBase)obj).Value = (string)valueForProperty; } } else { ((FilterBase)obj).Value = (bool)valueForProperty; } } else { ((FilterBase)obj).Value = null; } qbeFilterDescription.FiltersToApply.Add(obj); } else { X509Certificate2Collection x509Certificate2Collection = (X509Certificate2Collection)valueForProperty; X509Certificate2Enumerator enumerator = x509Certificate2Collection.GetEnumerator(); while (enumerator.MoveNext()) { X509Certificate2 current = enumerator.Current; object obj1 = FilterFactory.CreateFilter(str); ((FilterBase)obj1).Value = current; qbeFilterDescription.FiltersToApply.Add(obj1); } } } else { PrincipalValueCollection<string> strs = (PrincipalValueCollection<string>)valueForProperty; foreach (string inserted in strs.Inserted) { object obj2 = FilterFactory.CreateFilter(str); ((FilterBase)obj2).Value = inserted; qbeFilterDescription.FiltersToApply.Add(obj2); } } } } }
private void BuildFilterSet(Principal p, string[] propertySet, QbeFilterDescription qbeFilterDescription) { foreach (string propertyName in propertySet) { if (p.GetChangeStatusForProperty(propertyName)) { // Property has changed. Add it to the filter set. object value = p.GetValueForProperty(propertyName); GlobalDebug.WriteLineIf( GlobalDebug.Info, "StoreCtx", "BuildFilterSet: type={0}, property name={1}, property value={2} of type {3}", p.GetType().ToString(), propertyName, value.ToString(), value.GetType().ToString()); // Build the right filter based on type of the property value if (value is PrincipalValueCollection <string> ) { PrincipalValueCollection <string> trackingList = (PrincipalValueCollection <string>)value; foreach (string s in trackingList.Inserted) { object filter = FilterFactory.CreateFilter(propertyName); ((FilterBase)filter).Value = (string)s; qbeFilterDescription.FiltersToApply.Add(filter); } } else if (value is X509Certificate2Collection) { // Since QBE filter objects are always unpersisted, any certs in the collection // must have been inserted by the application. X509Certificate2Collection certCollection = (X509Certificate2Collection)value; foreach (X509Certificate2 cert in certCollection) { object filter = FilterFactory.CreateFilter(propertyName); ((FilterBase)filter).Value = (X509Certificate2)cert; qbeFilterDescription.FiltersToApply.Add(filter); } } else { // It's not one of the multivalued cases. Try the scalar cases. object filter = FilterFactory.CreateFilter(propertyName); if (value == null) { ((FilterBase)filter).Value = null; } else if (value is bool) { ((FilterBase)filter).Value = (bool)value; } else if (value is string) { ((FilterBase)filter).Value = (string)value; } else if (value is GroupScope) { ((FilterBase)filter).Value = (GroupScope)value; } else if (value is byte[]) { ((FilterBase)filter).Value = (byte[])value; } else if (value is Nullable <DateTime> ) { ((FilterBase)filter).Value = (Nullable <DateTime>)value; } else if (value is ExtensionCache) { ((FilterBase)filter).Value = (ExtensionCache)value; } else if (value is QbeMatchType) { ((FilterBase)filter).Value = (QbeMatchType)value; } else { // Internal error. Didn't match either the known multivalued or scalar cases. Debug.Fail(String.Format( CultureInfo.CurrentCulture, "StoreCtx.BuildFilterSet: fell off end looking for {0} of type {1}", propertyName, value.GetType().ToString() )); } qbeFilterDescription.FiltersToApply.Add(filter); } } } }
internal QbeMatcher(QbeFilterDescription propertiesToMatch) { _propertiesToMatch = propertiesToMatch; }
// Pushes the query represented by the QBE filter into the PrincipalSearcher's underlying native // searcher object (creating a fresh native searcher and assigning it to the PrincipalSearcher if one // doesn't already exist) and returns the native searcher. // If the PrincipalSearcher does not have a query filter set (PrincipalSearcher.QueryFilter == null), // produces a query that will match all principals in the store. // // For stores which don't have a native searcher (SAM), the StoreCtx // is free to create any type of object it chooses to use as its internal representation of the query. // // Also adds in any clauses to the searcher to ensure that only principals, not mere // contacts, are retrieved from the store. internal override object PushFilterToNativeSearcher(PrincipalSearcher ps) { // This is the first time we're being called on this principal. Create a fresh searcher. if (ps.UnderlyingSearcher == null) { GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "PushFilterToNativeSearcher: creating fresh DirectorySearcher"); ps.UnderlyingSearcher = new DirectorySearcher(this.ctxBase); ((DirectorySearcher)ps.UnderlyingSearcher).PageSize = ps.PageSize; ((DirectorySearcher)ps.UnderlyingSearcher).ServerTimeLimit = new TimeSpan(0, 0, 30); // 30 seconds } DirectorySearcher ds = (DirectorySearcher)ps.UnderlyingSearcher; Principal qbeFilter = ps.QueryFilter; StringBuilder ldapFilter = new StringBuilder(); if (qbeFilter == null) { GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "PushFilterToNativeSearcher: no qbeFilter specified"); // No filter specified. Search for all principals (all users, computers, groups). ldapFilter.Append("(|(objectClass=user)(objectClass=computer)(objectClass=group))"); } else { // // Start by appending the appropriate objectClass given the Principal type // ldapFilter.Append(GetObjectClassPortion(qbeFilter.GetType())); // // Next, fill in the properties (if any) // QbeFilterDescription filters = BuildQbeFilterDescription(qbeFilter); GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "PushFilterToNativeSearcher: using {0} filters", filters.FiltersToApply.Count); Hashtable filterTable = (Hashtable)s_filterPropertiesTable[this.MappingTableIndex]; foreach (FilterBase filter in filters.FiltersToApply) { FilterPropertyTableEntry entry = (FilterPropertyTableEntry)filterTable[filter.GetType()]; if (entry == null) { // Must be a property we don't support throw new InvalidOperationException( SR.Format( SR.StoreCtxUnsupportedPropertyForQuery, PropertyNamesExternal.GetExternalForm(filter.PropertyName))); } ldapFilter.Append(entry.converter(filter, entry.suggestedADPropertyName)); } // // Wrap off the filter // ldapFilter.Append(')'); } // We don't need any attributes returned, since we're just going to get a DirectoryEntry // for the result. Per RFC 2251, OID 1.1 == no attributes. //ds.PropertiesToLoad.Add("1.1"); BuildPropertySet(qbeFilter.GetType(), ds.PropertiesToLoad); ds.Filter = ldapFilter.ToString(); GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "PushFilterToNativeSearcher: using LDAP filter {0}", ds.Filter); return(ds); }
internal QbeMatcher(QbeFilterDescription propertiesToMatch) { this.propertiesToMatch = propertiesToMatch; }
internal override object PushFilterToNativeSearcher(PrincipalSearcher ps) { QbeFilterDescription qbeFilterDescription; Principal queryFilter = ps.QueryFilter; if (queryFilter == null) { qbeFilterDescription = new QbeFilterDescription(); } else { qbeFilterDescription = base.BuildQbeFilterDescription(queryFilter); } return qbeFilterDescription; }
private void BuildFilterSet(Principal p, string[] propertySet, QbeFilterDescription qbeFilterDescription) { string[] strArrays = propertySet; for (int i = 0; i < (int)strArrays.Length; i++) { string str = strArrays[i]; if (p.GetChangeStatusForProperty(str)) { object valueForProperty = p.GetValueForProperty(str); if (valueForProperty as PrincipalValueCollection <string> == null) { if (valueForProperty as X509Certificate2Collection == null) { object obj = FilterFactory.CreateFilter(str); if (valueForProperty != null) { if (!valueForProperty as bool) { if (valueForProperty as string == null) { if (valueForProperty as GroupScope == GroupScope.Local) { if (valueForProperty as byte[] == null) { if (valueForProperty as DateTime? == null) { if (valueForProperty as ExtensionCache == null) { if (valueForProperty as QbeMatchType != null) { ((FilterBase)obj).Value = (QbeMatchType)valueForProperty; } } else { ((FilterBase)obj).Value = (ExtensionCache)valueForProperty; } } else { ((FilterBase)obj).Value = (DateTime?)valueForProperty; } } else { ((FilterBase)obj).Value = (byte[])valueForProperty; } } else { ((FilterBase)obj).Value = (GroupScope)valueForProperty; } } else { ((FilterBase)obj).Value = (string)valueForProperty; } } else { ((FilterBase)obj).Value = (bool)valueForProperty; } } else { ((FilterBase)obj).Value = null; } qbeFilterDescription.FiltersToApply.Add(obj); } else { X509Certificate2Collection x509Certificate2Collection = (X509Certificate2Collection)valueForProperty; X509Certificate2Enumerator enumerator = x509Certificate2Collection.GetEnumerator(); while (enumerator.MoveNext()) { X509Certificate2 current = enumerator.Current; object obj1 = FilterFactory.CreateFilter(str); ((FilterBase)obj1).Value = current; qbeFilterDescription.FiltersToApply.Add(obj1); } } } else { PrincipalValueCollection <string> strs = (PrincipalValueCollection <string>)valueForProperty; foreach (string inserted in strs.Inserted) { object obj2 = FilterFactory.CreateFilter(str); ((FilterBase)obj2).Value = inserted; qbeFilterDescription.FiltersToApply.Add(obj2); } } } } }