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); }
internal override bool Matches(DirectoryEntry de) { bool flag; if (de.Properties["objectSid"] == null || de.Properties["objectSid"].Count == 0) { return(false); } else { IEnumerator enumerator = this.propertiesToMatch.FiltersToApply.GetEnumerator(); try { while (enumerator.MoveNext()) { FilterBase current = (FilterBase)enumerator.Current; QbeMatcher.FilterPropertyTableEntry item = (QbeMatcher.FilterPropertyTableEntry)QbeMatcher.filterPropertiesTable[current.GetType()]; if (item != null) { if (item.matcher(current, item.winNTPropertyName, de)) { continue; } flag = false; return(flag); } else { object[] externalForm = new object[1]; externalForm[0] = PropertyNamesExternal.GetExternalForm(current.PropertyName); throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, StringResources.StoreCtxUnsupportedPropertyForQuery, externalForm)); } } return(true); } finally { IDisposable disposable = enumerator as IDisposable; if (disposable != null) { disposable.Dispose(); } } return(flag); } }
internal override bool Matches(DirectoryEntry de) { // If it has no SID, it's not a security principal, and we're not interested in it. // (In reg-SAM, computers don't have accounts and therefore don't have SIDs, but ADSI // creates fake Computer objects for them. In LSAM, computers CAN have accounts, and thus // SIDs). if (de.Properties["objectSid"] == null || de.Properties["objectSid"].Count == 0) { GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMQuerySet", "SamMatcher: Matches: skipping no-SID {0}", de.Path); return(false); } // Try to match each specified property in turn foreach (FilterBase filter in _propertiesToMatch.FiltersToApply) { FilterPropertyTableEntry entry = (FilterPropertyTableEntry)s_filterPropertiesTable[filter.GetType()]; if (entry == null) { // Must be a property we don't support throw new NotSupportedException( String.Format( CultureInfo.CurrentCulture, SR.StoreCtxUnsupportedPropertyForQuery, PropertyNamesExternal.GetExternalForm(filter.PropertyName))); } if (!entry.matcher(filter, entry.winNTPropertyName, de)) { GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMQuerySet", "SamMatcher: Matches: no match {0}", de.Path); return(false); } } // All tests pass --- it's a match GlobalDebug.WriteLineIf(GlobalDebug.Info, "SAMQuerySet", "SamMatcher: Matches: match {0}", de.Path); return(true); }
protected static string UserAccountControlConverter(FilterBase filter, string suggestedAdProperty) { Debug.Assert(string.Equals(suggestedAdProperty, "userAccountControl", StringComparison.OrdinalIgnoreCase)); string result = ""; // bitwise-AND bool value = (bool)filter.Value; switch (filter.PropertyName) { case AuthPrincEnabledFilter.PropertyNameStatic: // UF_ACCOUNTDISABLE // Note that the logic is inverted on this one. We expose "Enabled", // but AD stores it as "Disabled". result = value ? "(!(userAccountControl:1.2.840.113556.1.4.803:=2))" : "(userAccountControl:1.2.840.113556.1.4.803:=2)"; break; case SmartcardLogonRequiredFilter.PropertyNameStatic: // UF_SMARTCARD_REQUIRED result = value ? "(userAccountControl:1.2.840.113556.1.4.803:=262144)" : "(!(userAccountControl:1.2.840.113556.1.4.803:=262144))"; break; case DelegationPermittedFilter.PropertyNameStatic: // UF_NOT_DELEGATED // Note that the logic is inverted on this one. That's because we expose // "delegation allowed", but AD represents it as the inverse, "delegation NOT allowed" result = value ? "(!(userAccountControl:1.2.840.113556.1.4.803:=1048576))" : "(userAccountControl:1.2.840.113556.1.4.803:=1048576)"; break; case PasswordNotRequiredFilter.PropertyNameStatic: // UF_PASSWD_NOTREQD result = value ? "(userAccountControl:1.2.840.113556.1.4.803:=32)" : "(!(userAccountControl:1.2.840.113556.1.4.803:=32))"; break; case PasswordNeverExpiresFilter.PropertyNameStatic: // UF_DONT_EXPIRE_PASSWD result = value ? "(userAccountControl:1.2.840.113556.1.4.803:=65536)" : "(!(userAccountControl:1.2.840.113556.1.4.803:=65536))"; break; case CannotChangePasswordFilter.PropertyNameStatic: // UF_PASSWD_CANT_CHANGE // This bit doesn't work correctly in AD (AD models the "user can't change password" // setting as special ACEs in the ntSecurityDescriptor). throw new InvalidOperationException( SR.Format( SR.StoreCtxUnsupportedPropertyForQuery, PropertyNamesExternal.GetExternalForm(filter.PropertyName))); case AllowReversiblePasswordEncryptionFilter.PropertyNameStatic: // UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED result = value ? "(userAccountControl:1.2.840.113556.1.4.803:=128)" : "(!(userAccountControl:1.2.840.113556.1.4.803:=128))"; break; default: Debug.Fail("ADStoreCtx.UserAccountControlConverter: fell off end looking for " + filter.PropertyName); break; } return(result); }
// 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); }