internal static DirectoryEntryHolder GetDirectoryEntry(DirectoryInformation directoryInfo, string objectDN, bool revertImpersonation) { Debug.Assert ((objectDN != null) && (objectDN.Length != 0)); // // Get the adspath and create a directory entry holder // DirectoryEntryHolder holder = new DirectoryEntryHolder(new DirectoryEntry ( directoryInfo.GetADsPath(objectDN), directoryInfo.GetUsername(), directoryInfo.GetPassword(), directoryInfo.AuthenticationTypes)); // // If revertImpersonation is true, we need to revert // holder.Open(null, revertImpersonation); return holder; }
internal static DirectoryEntryHolder GetDirectoryEntry(DirectoryInformation directoryInfo, string objectDN, bool revertImpersonation) { DirectoryEntryHolder holder = new DirectoryEntryHolder(new DirectoryEntry(directoryInfo.GetADsPath(objectDN), directoryInfo.GetUsername(), directoryInfo.GetPassword(), directoryInfo.AuthenticationTypes)); holder.Open(null, revertImpersonation); return holder; }
public override void Initialize(string name, NameValueCollection config) { if (System.Web.Hosting.HostingEnvironment.IsHosted) HttpRuntime.CheckAspNetHostingPermission (AspNetHostingPermissionLevel.Low, SR.Feature_not_supported_at_this_level); if (initialized) return; if (config == null) throw new ArgumentNullException("config"); if (String.IsNullOrEmpty(name)) name = "AspNetActiveDirectoryMembershipProvider"; if (string.IsNullOrEmpty(config["description"])) { config.Remove("description"); config.Add("description", SR.GetString(SR.ADMembership_Description)); } base.Initialize(name, config); appName = config["applicationName"]; if (string.IsNullOrEmpty(appName)) appName = SecUtility.GetDefaultAppName(); if( appName.Length > 256 ) throw new ProviderException(SR.GetString(SR.Provider_application_name_too_long)); string temp = config["connectionStringName"]; if (String.IsNullOrEmpty(temp)) throw new ProviderException(SR.GetString(SR.Connection_name_not_specified)); adConnectionString = GetConnectionString(temp, true); if (String.IsNullOrEmpty(adConnectionString)) throw new ProviderException(SR.GetString(SR.Connection_string_not_found, temp)); // // Get the provider specific configuration settings // // connectionProtection string connProtection = config["connectionProtection"]; if (connProtection == null) connProtection = "Secure"; else { if ((String.Compare(connProtection, "Secure", StringComparison.Ordinal) != 0) && (String.Compare(connProtection, "None", StringComparison.Ordinal) != 0)) throw new ProviderException(SR.GetString(SR.ADMembership_InvalidConnectionProtection, connProtection)); } // // credentials // username and password if specified must not be empty, moreover if one is specified the other must // be specified as well // string username = config["connectionUsername"]; if (username != null && username.Length == 0) throw new ProviderException(SR.GetString(SR.ADMembership_Connection_username_must_not_be_empty)); string password = config["connectionPassword"]; if (password != null && password.Length == 0) throw new ProviderException(SR.GetString(SR.ADMembership_Connection_password_must_not_be_empty)); if ((username != null && password == null) || (password != null && username == null)) throw new ProviderException(SR.GetString(SR.ADMembership_Username_and_password_reqd)); NetworkCredential credential = new NetworkCredential(username, password); int clientSearchTimeout = SecUtility.GetIntValue(config, "clientSearchTimeout", -1, false, 0); int serverSearchTimeout = SecUtility.GetIntValue(config, "serverSearchTimeout", -1, false, 0); enableSearchMethods = SecUtility.GetBooleanValue(config, "enableSearchMethods", false); requiresUniqueEmail = SecUtility.GetBooleanValue(config, "requiresUniqueEmail", false); enablePasswordReset = SecUtility.GetBooleanValue(config, "enablePasswordReset", false); requiresQuestionAndAnswer = SecUtility.GetBooleanValue(config, "requiresQuestionAndAnswer", false); minRequiredPasswordLength = SecUtility.GetIntValue( config, "minRequiredPasswordLength", 7, false, 128 ); minRequiredNonalphanumericCharacters = SecUtility.GetIntValue( config, "minRequiredNonalphanumericCharacters", 1, true, 128 ); passwordStrengthRegularExpression = config["passwordStrengthRegularExpression"]; if( passwordStrengthRegularExpression != null ) { passwordStrengthRegularExpression = passwordStrengthRegularExpression.Trim(); if( passwordStrengthRegularExpression.Length != 0 ) { try { Regex regex = new Regex( passwordStrengthRegularExpression ); } catch( ArgumentException e ) { throw new ProviderException( e.Message, e ); } } } else { passwordStrengthRegularExpression = string.Empty; } if (minRequiredNonalphanumericCharacters > minRequiredPasswordLength) throw new HttpException(SR.GetString(SR.MinRequiredNonalphanumericCharacters_can_not_be_more_than_MinRequiredPasswordLength)); using (new ApplicationImpersonationContext()) { // // This will make some checks regarding whether the connectionProtection is valid (choose the right // connectionprotection if necessary, make sure credentials are valid, container exists and the directory is // either AD or ADAM) // directoryInfo = new DirectoryInformation(adConnectionString, credential, connProtection, clientSearchTimeout, serverSearchTimeout, enablePasswordReset); // // initialize the syntaxes table // syntaxes.Add("attributeMapUsername", "DirectoryString"); syntaxes.Add("attributeMapEmail", "DirectoryString"); syntaxes.Add("attributeMapPasswordQuestion", "DirectoryString"); syntaxes.Add("attributeMapPasswordAnswer", "DirectoryString"); syntaxes.Add("attributeMapFailedPasswordAnswerCount", "Integer"); syntaxes.Add("attributeMapFailedPasswordAnswerTime", "Integer8"); syntaxes.Add("attributeMapFailedPasswordAnswerLockoutTime", "Integer8"); // // initialize the in use attributes list // attributesInUse.Add("objectclass", null); attributesInUse.Add("objectsid", null); attributesInUse.Add("comment", null); attributesInUse.Add("whencreated", null); attributesInUse.Add("pwdlastset", null); attributesInUse.Add("msds-user-account-control-computed", null); attributesInUse.Add("lockouttime", null); if (directoryInfo.DirectoryType == DirectoryType.AD) attributesInUse.Add("useraccountcontrol", null); else attributesInUse.Add("msds-useraccountdisabled", null); // // initialize the user attributes list // userObjectAttributes = GetUserObjectAttributes(); // // get the username/email schema mappings // int maxLength; string attrMapping = GetAttributeMapping(config, "attributeMapUsername", out maxLength); if (attrMapping != null) { attributeMapUsername = attrMapping; if (maxLength != -1) { if (maxLength < maxUsernameLength) maxUsernameLength = maxLength; if (maxLength < maxUsernameLengthForCreation) maxUsernameLengthForCreation = maxLength; } } attributesInUse.Add(attributeMapUsername, null); if (StringUtil.EqualsIgnoreCase(attributeMapUsername, "sAMAccountName")) { usernameIsSAMAccountName = true; usernameIsUPN = false; } attrMapping = GetAttributeMapping(config, "attributeMapEmail", out maxLength); if (attrMapping != null) { attributeMapEmail = attrMapping; if (maxLength != -1 && maxLength < maxEmailLength) maxEmailLength = maxLength; } attributesInUse.Add(attributeMapEmail, null); // // get max length of "comment" attribute // maxLength = GetRangeUpperForSchemaAttribute("comment"); if (maxLength != -1 && maxLength < maxCommentLength) maxCommentLength = maxLength; // // enablePasswordReset and requiresQuestionAndAnswer should match // if (enablePasswordReset) { // // AD membership provider does not support password reset without question and answer // if (!requiresQuestionAndAnswer) throw new ProviderException(SR.GetString(SR.ADMembership_PasswordReset_without_question_not_supported)); // // Other password reset related attributes // maxInvalidPasswordAttempts = SecUtility.GetIntValue(config, "maxInvalidPasswordAttempts", 5, false, 0); passwordAttemptWindow = SecUtility.GetIntValue(config, "passwordAttemptWindow", 10, false, 0); passwordAnswerAttemptLockoutDuration = SecUtility.GetIntValue(config, "passwordAnswerAttemptLockoutDuration", 30, false, 0); // // some more schema mappings that must be specified for Password Reset // attributeMapFailedPasswordAnswerCount = GetAttributeMapping(config, "attributeMapFailedPasswordAnswerCount", out maxLength /* ignored */); if (attributeMapFailedPasswordAnswerCount != null) attributesInUse.Add(attributeMapFailedPasswordAnswerCount, null); attributeMapFailedPasswordAnswerTime = GetAttributeMapping(config, "attributeMapFailedPasswordAnswerTime", out maxLength /* ignored */); if (attributeMapFailedPasswordAnswerTime != null) attributesInUse.Add(attributeMapFailedPasswordAnswerTime, null); attributeMapFailedPasswordAnswerLockoutTime = GetAttributeMapping(config, "attributeMapFailedPasswordAnswerLockoutTime", out maxLength /* ignored */); if (attributeMapFailedPasswordAnswerLockoutTime != null) attributesInUse.Add(attributeMapFailedPasswordAnswerLockoutTime, null); if (attributeMapFailedPasswordAnswerCount == null || attributeMapFailedPasswordAnswerTime == null || attributeMapFailedPasswordAnswerLockoutTime == null) throw new ProviderException(SR.GetString(SR.ADMembership_BadPasswordAnswerMappings_not_specified)); } // // Password Q&A mappings // attributeMapPasswordQuestion = GetAttributeMapping(config, "attributeMapPasswordQuestion", out maxLength); if (attributeMapPasswordQuestion != null) { if (maxLength != -1 && maxLength < maxPasswordQuestionLength) maxPasswordQuestionLength = maxLength; attributesInUse.Add(attributeMapPasswordQuestion, null); } attributeMapPasswordAnswer = GetAttributeMapping(config, "attributeMapPasswordAnswer", out maxLength); if (attributeMapPasswordAnswer != null) { if (maxLength != -1 && maxLength < maxPasswordAnswerLength) maxPasswordAnswerLength = maxLength; attributesInUse.Add(attributeMapPasswordAnswer, null); } if (requiresQuestionAndAnswer) { // // We also need to check that the password question and answer attributes are mapped // if (attributeMapPasswordQuestion == null || attributeMapPasswordAnswer == null) throw new ProviderException(SR.GetString(SR.ADMembership_PasswordQuestionAnswerMapping_not_specified)); } // // the auth type to be used for validation is determined as follows: // if directory is ADAM: authType = AuthType.Basic // if directory is AD: authType is based on connectionProtection (None, SSL: AuthType.Basic; SignAndSeal: AuthType.Negotiate) // if (directoryInfo.DirectoryType == DirectoryType.ADAM) authTypeForValidation = AuthType.Basic; else authTypeForValidation = directoryInfo.GetLdapAuthenticationTypes(directoryInfo.ConnectionProtection, CredentialsType.NonWindows); if (directoryInfo.DirectoryType == DirectoryType.AD) { // // if password reset is enabled we should perform all operations on a single server // if (enablePasswordReset) directoryInfo.SelectServer(); // // if the username is mapped to upn we need to do forest wide search to check the uniqueness of the upn. // and if the username is mapped to samAccountName then we need to append the domain name in the username for reliable validation // directoryInfo.InitializeDomainAndForestName(); } } // // Create a new common ldap connection for validation // connection = directoryInfo.CreateNewLdapConnection(authTypeForValidation); temp = config["passwordCompatMode"]; if (!string.IsNullOrEmpty(temp)) _LegacyPasswordCompatibilityMode = (MembershipPasswordCompatibilityMode) Enum.Parse(typeof(MembershipPasswordCompatibilityMode), temp); config.Remove("name"); config.Remove("applicationName"); config.Remove("connectionStringName"); config.Remove("requiresUniqueEmail"); config.Remove("enablePasswordReset"); config.Remove("requiresQuestionAndAnswer"); config.Remove("attributeMapPasswordQuestion"); config.Remove("attributeMapPasswordAnswer"); config.Remove("attributeMapUsername"); config.Remove("attributeMapEmail"); config.Remove("connectionProtection"); config.Remove("connectionUsername"); config.Remove("connectionPassword"); config.Remove("clientSearchTimeout"); config.Remove("serverSearchTimeout"); config.Remove("enableSearchMethods"); config.Remove("maxInvalidPasswordAttempts"); config.Remove("passwordAttemptWindow"); config.Remove("passwordAnswerAttemptLockoutDuration"); config.Remove("attributeMapFailedPasswordAnswerCount"); config.Remove("attributeMapFailedPasswordAnswerTime"); config.Remove("attributeMapFailedPasswordAnswerLockoutTime"); config.Remove("minRequiredPasswordLength"); config.Remove("minRequiredNonalphanumericCharacters"); config.Remove("passwordStrengthRegularExpression"); config.Remove("passwordCompatMode"); if (config.Count > 0) { string attribUnrecognized = config.GetKey(0); if (!String.IsNullOrEmpty(attribUnrecognized)) throw new ProviderException(SR.GetString(SR.Provider_unrecognized_attribute, attribUnrecognized)); } initialized = true; }
public override void Initialize(string name, NameValueCollection config) { if (HostingEnvironment.IsHosted) { HttpRuntime.CheckAspNetHostingPermission(AspNetHostingPermissionLevel.Low, "Feature_not_supported_at_this_level"); } if (this.initialized) { return; } if (config == null) { throw new ArgumentNullException("config"); } if (string.IsNullOrEmpty(name)) { name = "AspNetActiveDirectoryMembershipProvider"; } if (string.IsNullOrEmpty(config["description"])) { config.Remove("description"); config.Add("description", System.Web.SR.GetString("ADMembership_Description")); } base.Initialize(name, config); this.appName = config["applicationName"]; if (string.IsNullOrEmpty(this.appName)) { this.appName = SecUtility.GetDefaultAppName(); } if (this.appName.Length > 0x100) { throw new ProviderException(System.Web.SR.GetString("Provider_application_name_too_long")); } string str = config["connectionStringName"]; if (string.IsNullOrEmpty(str)) { throw new ProviderException(System.Web.SR.GetString("Connection_name_not_specified")); } this.adConnectionString = this.GetConnectionString(str, true); if (string.IsNullOrEmpty(this.adConnectionString)) { throw new ProviderException(System.Web.SR.GetString("Connection_string_not_found", new object[] { str })); } string strA = config["connectionProtection"]; if (strA == null) { strA = "Secure"; } else if ((string.Compare(strA, "Secure", StringComparison.Ordinal) != 0) && (string.Compare(strA, "None", StringComparison.Ordinal) != 0)) { throw new ProviderException(System.Web.SR.GetString("ADMembership_InvalidConnectionProtection", new object[] { strA })); } string userName = config["connectionUsername"]; if ((userName != null) && (userName.Length == 0)) { throw new ProviderException(System.Web.SR.GetString("ADMembership_Connection_username_must_not_be_empty")); } string password = config["connectionPassword"]; if ((password != null) && (password.Length == 0)) { throw new ProviderException(System.Web.SR.GetString("ADMembership_Connection_password_must_not_be_empty")); } if (((userName != null) && (password == null)) || ((password != null) && (userName == null))) { throw new ProviderException(System.Web.SR.GetString("ADMembership_Username_and_password_reqd")); } NetworkCredential credentials = new NetworkCredential(userName, password); int clientSearchTimeout = SecUtility.GetIntValue(config, "clientSearchTimeout", -1, false, 0); int serverSearchTimeout = SecUtility.GetIntValue(config, "serverSearchTimeout", -1, false, 0); this.enableSearchMethods = SecUtility.GetBooleanValue(config, "enableSearchMethods", false); this.requiresUniqueEmail = SecUtility.GetBooleanValue(config, "requiresUniqueEmail", false); this.enablePasswordReset = SecUtility.GetBooleanValue(config, "enablePasswordReset", false); this.requiresQuestionAndAnswer = SecUtility.GetBooleanValue(config, "requiresQuestionAndAnswer", false); this.minRequiredPasswordLength = SecUtility.GetIntValue(config, "minRequiredPasswordLength", 7, false, 0x80); this.minRequiredNonalphanumericCharacters = SecUtility.GetIntValue(config, "minRequiredNonalphanumericCharacters", 1, true, 0x80); this.passwordStrengthRegularExpression = config["passwordStrengthRegularExpression"]; if (this.passwordStrengthRegularExpression != null) { this.passwordStrengthRegularExpression = this.passwordStrengthRegularExpression.Trim(); if (this.passwordStrengthRegularExpression.Length == 0) { goto Label_02DD; } try { new Regex(this.passwordStrengthRegularExpression); goto Label_02DD; } catch (ArgumentException exception) { throw new ProviderException(exception.Message, exception); } } this.passwordStrengthRegularExpression = string.Empty; Label_02DD: if (this.minRequiredNonalphanumericCharacters > this.minRequiredPasswordLength) { throw new HttpException(System.Web.SR.GetString("MinRequiredNonalphanumericCharacters_can_not_be_more_than_MinRequiredPasswordLength")); } using (new ApplicationImpersonationContext()) { int rangeUpperForSchemaAttribute; this.directoryInfo = new DirectoryInformation(this.adConnectionString, credentials, strA, clientSearchTimeout, serverSearchTimeout, this.enablePasswordReset); this.syntaxes.Add("attributeMapUsername", "DirectoryString"); this.syntaxes.Add("attributeMapEmail", "DirectoryString"); this.syntaxes.Add("attributeMapPasswordQuestion", "DirectoryString"); this.syntaxes.Add("attributeMapPasswordAnswer", "DirectoryString"); this.syntaxes.Add("attributeMapFailedPasswordAnswerCount", "Integer"); this.syntaxes.Add("attributeMapFailedPasswordAnswerTime", "Integer8"); this.syntaxes.Add("attributeMapFailedPasswordAnswerLockoutTime", "Integer8"); this.attributesInUse.Add("objectclass", null); this.attributesInUse.Add("objectsid", null); this.attributesInUse.Add("comment", null); this.attributesInUse.Add("whencreated", null); this.attributesInUse.Add("pwdlastset", null); this.attributesInUse.Add("msds-user-account-control-computed", null); this.attributesInUse.Add("lockouttime", null); if (this.directoryInfo.DirectoryType == DirectoryType.AD) { this.attributesInUse.Add("useraccountcontrol", null); } else { this.attributesInUse.Add("msds-useraccountdisabled", null); } this.userObjectAttributes = this.GetUserObjectAttributes(); string str5 = this.GetAttributeMapping(config, "attributeMapUsername", out rangeUpperForSchemaAttribute); if (str5 != null) { this.attributeMapUsername = str5; if (rangeUpperForSchemaAttribute != -1) { if (rangeUpperForSchemaAttribute < this.maxUsernameLength) { this.maxUsernameLength = rangeUpperForSchemaAttribute; } if (rangeUpperForSchemaAttribute < this.maxUsernameLengthForCreation) { this.maxUsernameLengthForCreation = rangeUpperForSchemaAttribute; } } } this.attributesInUse.Add(this.attributeMapUsername, null); if (System.Web.Util.StringUtil.EqualsIgnoreCase(this.attributeMapUsername, "sAMAccountName")) { this.usernameIsSAMAccountName = true; this.usernameIsUPN = false; } str5 = this.GetAttributeMapping(config, "attributeMapEmail", out rangeUpperForSchemaAttribute); if (str5 != null) { this.attributeMapEmail = str5; if ((rangeUpperForSchemaAttribute != -1) && (rangeUpperForSchemaAttribute < this.maxEmailLength)) { this.maxEmailLength = rangeUpperForSchemaAttribute; } } this.attributesInUse.Add(this.attributeMapEmail, null); rangeUpperForSchemaAttribute = this.GetRangeUpperForSchemaAttribute("comment"); if ((rangeUpperForSchemaAttribute != -1) && (rangeUpperForSchemaAttribute < this.maxCommentLength)) { this.maxCommentLength = rangeUpperForSchemaAttribute; } if (this.enablePasswordReset) { if (!this.requiresQuestionAndAnswer) { throw new ProviderException(System.Web.SR.GetString("ADMembership_PasswordReset_without_question_not_supported")); } this.maxInvalidPasswordAttempts = SecUtility.GetIntValue(config, "maxInvalidPasswordAttempts", 5, false, 0); this.passwordAttemptWindow = SecUtility.GetIntValue(config, "passwordAttemptWindow", 10, false, 0); this.passwordAnswerAttemptLockoutDuration = SecUtility.GetIntValue(config, "passwordAnswerAttemptLockoutDuration", 30, false, 0); this.attributeMapFailedPasswordAnswerCount = this.GetAttributeMapping(config, "attributeMapFailedPasswordAnswerCount", out rangeUpperForSchemaAttribute); if (this.attributeMapFailedPasswordAnswerCount != null) { this.attributesInUse.Add(this.attributeMapFailedPasswordAnswerCount, null); } this.attributeMapFailedPasswordAnswerTime = this.GetAttributeMapping(config, "attributeMapFailedPasswordAnswerTime", out rangeUpperForSchemaAttribute); if (this.attributeMapFailedPasswordAnswerTime != null) { this.attributesInUse.Add(this.attributeMapFailedPasswordAnswerTime, null); } this.attributeMapFailedPasswordAnswerLockoutTime = this.GetAttributeMapping(config, "attributeMapFailedPasswordAnswerLockoutTime", out rangeUpperForSchemaAttribute); if (this.attributeMapFailedPasswordAnswerLockoutTime != null) { this.attributesInUse.Add(this.attributeMapFailedPasswordAnswerLockoutTime, null); } if (((this.attributeMapFailedPasswordAnswerCount == null) || (this.attributeMapFailedPasswordAnswerTime == null)) || (this.attributeMapFailedPasswordAnswerLockoutTime == null)) { throw new ProviderException(System.Web.SR.GetString("ADMembership_BadPasswordAnswerMappings_not_specified")); } } this.attributeMapPasswordQuestion = this.GetAttributeMapping(config, "attributeMapPasswordQuestion", out rangeUpperForSchemaAttribute); if (this.attributeMapPasswordQuestion != null) { if ((rangeUpperForSchemaAttribute != -1) && (rangeUpperForSchemaAttribute < this.maxPasswordQuestionLength)) { this.maxPasswordQuestionLength = rangeUpperForSchemaAttribute; } this.attributesInUse.Add(this.attributeMapPasswordQuestion, null); } this.attributeMapPasswordAnswer = this.GetAttributeMapping(config, "attributeMapPasswordAnswer", out rangeUpperForSchemaAttribute); if (this.attributeMapPasswordAnswer != null) { if ((rangeUpperForSchemaAttribute != -1) && (rangeUpperForSchemaAttribute < this.maxPasswordAnswerLength)) { this.maxPasswordAnswerLength = rangeUpperForSchemaAttribute; } this.attributesInUse.Add(this.attributeMapPasswordAnswer, null); } if (this.requiresQuestionAndAnswer && ((this.attributeMapPasswordQuestion == null) || (this.attributeMapPasswordAnswer == null))) { throw new ProviderException(System.Web.SR.GetString("ADMembership_PasswordQuestionAnswerMapping_not_specified")); } if (this.directoryInfo.DirectoryType == DirectoryType.ADAM) { this.authTypeForValidation = AuthType.Basic; } else { this.authTypeForValidation = this.directoryInfo.GetLdapAuthenticationTypes(this.directoryInfo.ConnectionProtection, CredentialsType.NonWindows); } if (this.directoryInfo.DirectoryType == DirectoryType.AD) { if (this.enablePasswordReset) { this.directoryInfo.SelectServer(); } this.directoryInfo.InitializeDomainAndForestName(); } } this.connection = this.directoryInfo.CreateNewLdapConnection(this.authTypeForValidation); str = config["passwordCompatMode"]; if (!string.IsNullOrEmpty(str)) { this._LegacyPasswordCompatibilityMode = (MembershipPasswordCompatibilityMode) System.Enum.Parse(typeof(MembershipPasswordCompatibilityMode), str); } config.Remove("name"); config.Remove("applicationName"); config.Remove("connectionStringName"); config.Remove("requiresUniqueEmail"); config.Remove("enablePasswordReset"); config.Remove("requiresQuestionAndAnswer"); config.Remove("attributeMapPasswordQuestion"); config.Remove("attributeMapPasswordAnswer"); config.Remove("attributeMapUsername"); config.Remove("attributeMapEmail"); config.Remove("connectionProtection"); config.Remove("connectionUsername"); config.Remove("connectionPassword"); config.Remove("clientSearchTimeout"); config.Remove("serverSearchTimeout"); config.Remove("enableSearchMethods"); config.Remove("maxInvalidPasswordAttempts"); config.Remove("passwordAttemptWindow"); config.Remove("passwordAnswerAttemptLockoutDuration"); config.Remove("attributeMapFailedPasswordAnswerCount"); config.Remove("attributeMapFailedPasswordAnswerTime"); config.Remove("attributeMapFailedPasswordAnswerLockoutTime"); config.Remove("minRequiredPasswordLength"); config.Remove("minRequiredNonalphanumericCharacters"); config.Remove("passwordStrengthRegularExpression"); config.Remove("passwordCompatMode"); if (config.Count > 0) { string key = config.GetKey(0); if (!string.IsNullOrEmpty(key)) { throw new ProviderException(System.Web.SR.GetString("Provider_unrecognized_attribute", new object[] { key })); } } this.initialized = true; }