// // PAPI --> S.DS (LDAP or WinNT) conversion routines // static internal void MultiStringToDirectoryEntryConverter(Principal p, string propertyName, DirectoryEntry de, string suggestedProperty) { PrincipalValueCollection <string> trackingList = (PrincipalValueCollection <string>)p.GetValueForProperty(propertyName); if (p.unpersisted && trackingList == null) { return; } List <string> insertedValues = trackingList.Inserted; List <string> removedValues = trackingList.Removed; List <Pair <string, string> > changedValues = trackingList.ChangedValues; PropertyValueCollection properties = de.Properties[suggestedProperty]; // We test to make sure the change hasn't already been applied to the PropertyValueCollection, // because PushChangesToNative can be called multiple times prior to committing the changes and // we want to maintain idempotency foreach (string value in removedValues) { if (value != null && properties.Contains(value)) { properties.Remove(value); } } foreach (Pair <string, string> changedValue in changedValues) { // Remove the original value and add in the new value Debug.Assert(changedValue.Left != null); // since it came from the system properties.Remove(changedValue.Left); if (changedValue.Right != null && !properties.Contains(changedValue.Right)) { properties.Add(changedValue.Right); } } foreach (string value in insertedValues) { if (value != null && !properties.Contains(value)) { properties.Add(value); } } }
internal const int SAM_DefaultUAC = (int)(0x200 | 0x1); // UF_NORMAL_ACCOUNT | UF_SCRIPT static internal void AccountControlToDirectoryEntry( Principal p, string propertyName, DirectoryEntry de, string suggestedProperty, bool isSAM, bool isUnpersisted) { Debug.Assert( (!isSAM && (String.Equals(suggestedProperty, "userAccountControl", StringComparison.OrdinalIgnoreCase))) || (isSAM && (String.Equals(suggestedProperty, "UserFlags", StringComparison.OrdinalIgnoreCase))) ); bool flag = (bool)p.GetValueForProperty(propertyName); int uacValue = 0; // We want to get the current value, so we can flip the appropriate bit while leaving the other bits as-is. // If this is a to-be-inserted Principal, we should have already initialized the userAccountControl property if (de.Properties[suggestedProperty].Count > 0) { Debug.Assert(de.Properties[suggestedProperty].Count == 1); uacValue = (int)de.Properties[suggestedProperty][0]; // When we write to userAccountControl, we must OR the new value with the value of msDS-User-Account-Control-Computed. // Otherwise we might mistakenly clear computed bits like UF_LOCKOUT. if (!isSAM && de.Properties["msDS-User-Account-Control-Computed"].Count > 0) { Debug.Assert(de.Properties["msDS-User-Account-Control-Computed"].Count == 1); uacValue = uacValue | (int)de.Properties["msDS-User-Account-Control-Computed"][0]; } } else { // We don't have the userAccountControl property, this must be a persisted principal. Perhaps we don't have access // to it. In that case, we don't want to blindly overwrite whatever other bits might be there. Debug.Assert(p.unpersisted == false); throw new PrincipalOperationException( SR.ADStoreCtxUnableToReadExistingAccountControlFlagsForUpdate); } uint bitmask; // Get the right bitmask for the property switch (propertyName) { case PropertyNames.AuthenticablePrincipalEnabled: if (!isUnpersisted || isSAM) { // UF_ACCOUNTDISABLE // Note that the logic is inverted on this one. We expose "Enabled", // but AD/SAM store it as "Disabled". bitmask = 0x2; flag = !flag; } else { // We're writing to an unpersisted AD principal Debug.Assert(!isSAM && isUnpersisted); // Nothing to do here. The ADStoreCtx will take care of enabling the // principal after it's persisted. bitmask = 0; } break; case PropertyNames.AcctInfoSmartcardRequired: // UF_SMARTCARD_REQUIRED bitmask = 0x40000; break; case PropertyNames.AcctInfoDelegationPermitted: // 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" bitmask = 0x100000; flag = !flag; break; case PropertyNames.PwdInfoPasswordNotRequired: // UF_PASSWD_NOTREQD bitmask = 0x0020; break; case PropertyNames.PwdInfoPasswordNeverExpires: // UF_DONT_EXPIRE_PASSWD bitmask = 0x10000; break; case PropertyNames.PwdInfoAllowReversiblePasswordEncryption: // UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED bitmask = 0x0080; break; // This bit doesn't work in userAccountControl case PropertyNames.PwdInfoCannotChangePassword: if (isSAM) { // UF_PASSWD_CANT_CHANGE bitmask = 0x0040; break; } else { Debug.Fail( "SDSUtils.AccountControlToDirectoryEntry: At PwdInfoCannotChangePassword but isSAM==false, path=" + de.Path ); goto default; } default: Debug.Fail("SDSUtils.AccountControlToDirectoryEntry: Fell off end looking for " + propertyName); bitmask = 0; break; } // Set/clear the "bitmask" bit in "uacValue", based on the value of "flag" if (flag) { Utils.SetBit(ref uacValue, bitmask); } else { Utils.ClearBit(ref uacValue, bitmask); } de.Properties[suggestedProperty].Value = uacValue; }
static internal void InsertPrincipal( Principal p, StoreCtx storeCtx, GroupMembershipUpdater updateGroupMembership, NetCred credentials, AuthenticationTypes authTypes, bool needToSetPassword) { GlobalDebug.WriteLineIf(GlobalDebug.Info, "SDSUtils", "Entering InsertPrincipal"); Debug.Assert(storeCtx != null); Debug.Assert(storeCtx is ADStoreCtx || storeCtx is SAMStoreCtx); Debug.Assert(p != null); if ((!(p is UserPrincipal)) && (!(p is GroupPrincipal)) && (!(p is AuthenticablePrincipal)) && (!(p is ComputerPrincipal))) { // It's not a type of Principal that we support GlobalDebug.WriteLineIf(GlobalDebug.Warn, "SDSUtils", "InsertPrincipal: Bad principal type:" + p.GetType().ToString()); throw new InvalidOperationException( String.Format(CultureInfo.CurrentCulture, SR.StoreCtxUnsupportedPrincipalTypeForSave, p.GetType().ToString())); } // Commit the properties SDSUtils.ApplyChangesToDirectory( p, storeCtx, updateGroupMembership, credentials, authTypes ); // Handle any saved-off operations // For SAM, we set password elsewhere prior to creating the principal, so needToSetPassword == false // For AD, we have to set the password after creating the principal, so needToSetPassword == true if (needToSetPassword && p.GetChangeStatusForProperty(PropertyNames.PwdInfoPassword)) { GlobalDebug.WriteLineIf(GlobalDebug.Info, "SDSUtils", "InsertPrincipal: Setting password"); // Only AuthenticablePrincipals can have PasswordInfo Debug.Assert(p is AuthenticablePrincipal); string password = (string)p.GetValueForProperty(PropertyNames.PwdInfoPassword); Debug.Assert(password != null); // if null, PasswordInfo should not have indicated it was changed storeCtx.SetPassword((AuthenticablePrincipal)p, password); } if (p.GetChangeStatusForProperty(PropertyNames.PwdInfoExpireImmediately)) { // Only AuthenticablePrincipals can have PasswordInfo Debug.Assert(p is AuthenticablePrincipal); bool expireImmediately = (bool)p.GetValueForProperty(PropertyNames.PwdInfoExpireImmediately); if (expireImmediately) { GlobalDebug.WriteLineIf(GlobalDebug.Info, "SDSUtils", "InsertPrincipal: Setting pwd expired"); storeCtx.ExpirePassword((AuthenticablePrincipal)p); } } }
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 static void MultiStringToDirectoryEntryConverter(Principal p, string propertyName, DirectoryEntry de, string suggestedProperty) { PrincipalValueCollection <string> valueForProperty = (PrincipalValueCollection <string>)p.GetValueForProperty(propertyName); if (!p.unpersisted || valueForProperty != null) { List <string> inserted = valueForProperty.Inserted; List <string> removed = valueForProperty.Removed; List <Pair <string, string> > changedValues = valueForProperty.ChangedValues; PropertyValueCollection item = de.Properties[suggestedProperty]; foreach (string str in removed) { if (str == null || !item.Contains(str)) { continue; } item.Remove(str); } foreach (Pair <string, string> changedValue in changedValues) { item.Remove(changedValue.Left); if (changedValue.Right == null || item.Contains(changedValue.Right)) { continue; } item.Add(changedValue.Right); } foreach (string str1 in inserted) { if (str1 == null || item.Contains(str1)) { continue; } item.Add(str1); } return; } else { return; } }
internal static void AccountControlToDirectoryEntry(Principal p, string propertyName, DirectoryEntry de, string suggestedProperty, bool isSAM, bool isUnpersisted) { uint num; bool valueForProperty = (bool)p.GetValueForProperty(propertyName); if (de.Properties[suggestedProperty].Count <= 0) { throw new PrincipalOperationException(StringResources.ADStoreCtxUnableToReadExistingAccountControlFlagsForUpdate); } else { int item = (int)de.Properties[suggestedProperty][0]; if (!isSAM && de.Properties["msDS-User-Account-Control-Computed"].Count > 0) { item = item | (int)de.Properties["msDS-User-Account-Control-Computed"][0]; } string str = propertyName; string str1 = str; if (str != null) { if (str1 == "AuthenticablePrincipal.Enabled") { if (!isUnpersisted || isSAM) { num = 2; valueForProperty = !valueForProperty; if (!valueForProperty) { Utils.ClearBit(ref item, num); } else { Utils.SetBit(ref item, num); } de.Properties[suggestedProperty].Value = (object)item; return; } else { num = 0; if (!valueForProperty) { Utils.ClearBit(ref item, num); } else { Utils.SetBit(ref item, num); } de.Properties[suggestedProperty].Value = (object)item; return; } } else if (str1 == "AuthenticablePrincipal.AccountInfo.SmartcardLogonRequired") { num = 0x40000; if (!valueForProperty) { Utils.ClearBit(ref item, num); } else { Utils.SetBit(ref item, num); } de.Properties[suggestedProperty].Value = (object)item; return; } else if (str1 == "AuthenticablePrincipal.AccountInfo.DelegationPermitted") { num = 0x100000; valueForProperty = !valueForProperty; if (!valueForProperty) { Utils.ClearBit(ref item, num); } else { Utils.SetBit(ref item, num); } de.Properties[suggestedProperty].Value = (object)item; return; } else if (str1 == "AuthenticablePrincipal.PasswordInfo.PasswordNotRequired") { num = 32; if (!valueForProperty) { Utils.ClearBit(ref item, num); } else { Utils.SetBit(ref item, num); } de.Properties[suggestedProperty].Value = (object)item; return; } else if (str1 == "AuthenticablePrincipal.PasswordInfo.PasswordNeverExpires") { num = 0x10000; if (!valueForProperty) { Utils.ClearBit(ref item, num); } else { Utils.SetBit(ref item, num); } de.Properties[suggestedProperty].Value = (object)item; return; } else if (str1 == "AuthenticablePrincipal.PasswordInfo.AllowReversiblePasswordEncryption") { num = 128; if (!valueForProperty) { Utils.ClearBit(ref item, num); } else { Utils.SetBit(ref item, num); } de.Properties[suggestedProperty].Value = (object)item; return; } else if (str1 == "AuthenticablePrincipal.PasswordInfo.UserCannotChangePassword") { if (!isSAM) { num = 0; if (!valueForProperty) { Utils.ClearBit(ref item, num); } else { Utils.SetBit(ref item, num); } de.Properties[suggestedProperty].Value = (object)item; return; } num = 64; if (!valueForProperty) { Utils.ClearBit(ref item, num); } else { Utils.SetBit(ref item, num); } de.Properties[suggestedProperty].Value = (object)item; return; } num = 0; if (!valueForProperty) { Utils.ClearBit(ref item, num); } else { Utils.SetBit(ref item, num); } de.Properties[suggestedProperty].Value = (object)item; return; } else { num = 0; if (!valueForProperty) { Utils.ClearBit(ref item, num); } else { Utils.SetBit(ref item, num); } de.Properties[suggestedProperty].Value = (object)item; return; } if (!valueForProperty) { Utils.ClearBit(ref item, num); } else { Utils.SetBit(ref item, num); } de.Properties[suggestedProperty].Value = item; return; } }
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); } } } } }