Here is my repaired version of Jit Ghosh's AD/AM Membership Provider:
using System;using System.Configuration;using System.Web.Configuration;using System.Configuration.Provider;using System.Web.Security;using System.DirectoryServices;using System.Security.Cryptography;using System.Text;using System.IO;
namespace CustomProviders{ /// <summary> /// Implements a custom provier for the ASP.NET 2.0 Membership Service. /// This provider uses Microsoft Active Directory Application Mode as the storage system for user information /// </summary> public class ADAMMembershipProvider: MembershipProvider {
private string _Name = null;
private string _ADAMServerUri = "localhost"; private string _ADAMUserName = null; private string _ADAMPassword = null; private string _ADAMTopContainer = "CN=ASP.NET Security Provider"; private string _ADAMUserContainer = "CN=Users"; private bool _EnablePasswordRetrieval = false; private bool _EnablePasswordReset = true; private string _ApplicationName = null; private bool _RequiresQuestionAndAnswer = false; private bool _RequiresUniqueEMail = false; private byte[] _DecryptionKey = null; private byte[] _ValidationKey = null;
private MembershipPasswordFormat _PasswordFormat = MembershipPasswordFormat.Hashed;
private const int PAGEINDEX_NOPAGING = 1; private const int PAGESIZE_NOPAGING = int.MaxValue;
//Filter formats for various LDAP queries
private const string _ADAMCommonName = "CN={0}"; private const string _ADAMGetAllUsersFilterAppSpecific = "(&(objectClass=aspnetmembershipuser)(aspnetmembershipuserApplicationName={0}))"; private const string _ADAMUserSearchByUserNameFilterAppSpecific = "(&(&(objectClass=aspnetmembershipuser)(aspnetmembershipuserApplicationName={0}))(aspnetmembershipuserUserName={1}))"; private const string _ADAMUserSearchByEmailFilterAppSpecific = "(&(&(objectClass=aspnetmembershipuser)(aspnetmembershipuserApplicationName={0}))(aspnetmembershipuserEMail={1}))"; private const string _ADAMUserSearchByNameAndEmailFilterAppSpecific = "(&(&(objectClass=aspnetmembershipuser)(aspnetmembershipuserApplicationName={0}))(&(aspnetmembershipuserUserName={1})(aspnetmembershipuserEMail={2})))"; private const string _ADAMCountUsersOnlineAppSpecific = "(&(&(objectClass=aspnetmembershipuser)(aspnetmembershipuserApplicationName={0}))(aspnetmembershipuserLastActivityTimeStamp>={1:yyMMddHHmmss}Z))"; private const string _ADAMGetAllUsersFilter = "(objectClass=aspnetmembershipuser)"; private const string _ADAMUserSearchByUserNameFilter = "(&(objectClass=aspnetmembershipuser)(aspnetmembershipuserUserName={0}))"; private const string _ADAMUserSearchByEmailFilter = "(&(objectClass=aspnetmembershipuser)(aspnetmembershipuserEMail={0}))"; private const string _ADAMUserSearchByNameAndEmailFilter = "(&(objectClass=aspnetmembershipuser)(&(aspnetmembershipuserUserName={0})(aspnetmembershipuserEMail={1})))"; private const string _ADAMCountUsersOnline = "(&(objectClass=aspnetmembershipuser)(aspnetmembershipuserLastActivityTimeStamp>={0:yyMMddHHmmss}Z))"; private string _ADAMLDAPPathToUserContainer = null;
//Various ADAM Schema class and attribute name literals private const string _ADAMUserObjectClass = "aspnetmembershipuser"; private const string _ADAMPropApplicationName = "aspnetmembershipuserApplicationName"; private const string _ADAMPropUserName = "aspnetmembershipuserUserName"; private const string _ADAMPropUserId = "aspnetmembershipuserUserId"; private const string _ADAMPropEMail = "aspnetmembershipuserEmail"; private const string _ADAMPropComment = "aspnetmembershipuserComment"; private const string _ADAMPropIsAnonymous = "aspnetmembershipuserIsAnonymous"; private const string _ADAMPropIsApproved = "aspnetmembershipuserIsApproved"; private const string _ADAMPropUserCreationTimestamp = "aspnetmembershipuserUserCreationTimeStamp"; private const string _ADAMPropLastActivityTimestamp = "aspnetmembershipuserLastActivityTimeStamp"; private const string _ADAMPropLastLoginTimestamp = "aspnetmembershipuserLastLoginTimeStamp"; private const string _ADAMPropLastPasswordChangeTimestamp = "aspnetmembershipuserLastPasswordChangeTimestamp"; private const string _ADAMPropPassword = "aspnetmembershipuserPassword"; private const string _ADAMPropPasswordQuestion = "aspnetmembershipuserPasswordQuestion"; private const string _ADAMPropPasswordAnswer = "aspnetmembershipuserPasswordAnswer"; private const string _ADAMPropPasswordFormat = "aspnetmembershipuserPasswordFormat"; private const string _ADAMPropPasswordSaltOrIV = "aspnetmembershipuserPasswordSaltOrIV";
public ADAMMembershipProvider() {
}
public override string ResetPassword(string name, string answer) { DirectoryEntry deUserContainer = null; DirectoryEntry deMembershipUser = null;
string RetVal = null;
try { //Cannot reset password if not enabled via configuration settings if (_EnablePasswordReset == false) throw new NotSupportedException("Current configuration settings do not allow resetting passwords"); //check if the user exists deUserContainer = (_ADAMUserName != null && _ADAMPassword != null) ? new DirectoryEntry(_ADAMLDAPPathToUserContainer, _ADAMUserName, _ADAMPassword) : new DirectoryEntry(_ADAMLDAPPathToUserContainer); if (ADAMFindUser((_ApplicationName != null) ? string.Format(_ADAMUserSearchByUserNameFilterAppSpecific, _ApplicationName, name) : string.Format(_ADAMUserSearchByUserNameFilter, name), deUserContainer, out deMembershipUser) == false) throw new ApplicationException(string.Format("User {0} does not exist", name));
if (deMembershipUser != null)//user record found!! { deMembershipUser.RefreshCache(); //if configuration settings require a security question/answer protocol for passwords //then the supplied answer parameter needs to match the stored password answer for the user if (_RequiresQuestionAndAnswer && (deMembershipUser.Properties[_ADAMPropPasswordAnswer].Value == null || (string)deMembershipUser.Properties[_ADAMPropPasswordAnswer].Value != answer)) throw new ApplicationException("Password answer does not match");
//generate a new random password. I have chosen to use a 6 character password. //It is advisable to make this a configuration setting as well RetVal = Membership.GeneratePassword(6); //convert password for storage per password format, and set the user record with the new password deMembershipUser.Properties[_ADAMPropPassword].Value = this.ConvertPasswordForStorage(RetVal); //record timestamp deMembershipUser.Properties[_ADAMPropLastPasswordChangeTimestamp].Value = DateTime.UtcNow; //save changes deMembershipUser.CommitChanges(); } } catch (Exception Ex) { throw new ApplicationException("Error resetting password", Ex); } finally { try { deMembershipUser.Close(); deUserContainer.Close(); } catch (Exception Ex) { } } //return new password return RetVal; ; }
public override bool ChangePassword(string name, string oldPwd, string newPwd) { DirectoryEntry deUserContainer = null; DirectoryEntry deMembershipUser = null;
try {
//check for existence of user record deUserContainer = (_ADAMUserName != null && _ADAMPassword != null) ? new DirectoryEntry(_ADAMLDAPPathToUserContainer, _ADAMUserName, _ADAMPassword) : new DirectoryEntry(_ADAMLDAPPathToUserContainer); if (ADAMFindUser((_ApplicationName != null) ? string.Format(_ADAMUserSearchByUserNameFilterAppSpecific, _ApplicationName, name) : string.Format(_ADAMUserSearchByUserNameFilter, name), deUserContainer, out deMembershipUser) == false) throw new ApplicationException(string.Format("User {0} does not exist", name));
if (deMembershipUser != null)//user record found!! { deMembershipUser.RefreshCache(); //check if the old password matches if (!ComparePassword(oldPwd, (byte[])deMembershipUser.Properties[_ADAMPropPassword].Value)) throw new ApplicationException("Existing password does not match"); ////convert password for storage per password format, and set the user record with the new password deMembershipUser.Properties[_ADAMPropPassword].Value = ConvertPasswordForStorage(newPwd); //record timestamp deMembershipUser.Properties[_ADAMPropLastPasswordChangeTimestamp].Value = DateTime.UtcNow; //save changes deMembershipUser.CommitChanges(); } } catch (Exception Ex) { throw new ApplicationException("Error changing password", Ex); } finally { try { deMembershipUser.Close(); deUserContainer.Close(); } catch (Exception Ex) { } } return true; }
public override void UpdateUser(MembershipUser user) { DirectoryEntry deUserContainer = null; DirectoryEntry deMembershipUser = null;
try { //check if the user exists deUserContainer = (_ADAMUserName != null && _ADAMPassword != null) ? new DirectoryEntry(_ADAMLDAPPathToUserContainer, _ADAMUserName, _ADAMPassword) : new DirectoryEntry(_ADAMLDAPPathToUserContainer); if (ADAMFindUser((_ApplicationName != null) ? string.Format(_ADAMUserSearchByUserNameFilterAppSpecific, _ApplicationName, user.UserName) : string.Format(_ADAMUserSearchByUserNameFilter, user.UserName), deUserContainer, out deMembershipUser) == false) throw new ApplicationException(string.Format("User {0} does not exist", user.UserName));
int Count = 0;
if (deMembershipUser != null)//user record found!! { deMembershipUser.RefreshCache(); //if requiresUniqueEmail is true, the update cannot specify an email that violates uniqueness //if the email in the update is different than the original email in the user record, check to see if there //is another user in the system with the same email if (_RequiresUniqueEMail && deMembershipUser.Properties[_ADAMPropEMail].Value != user.Email && ADAMFindUser((_ApplicationName != null) ? string.Format(_ADAMUserSearchByEmailFilterAppSpecific, _ApplicationName, user.Email) : string.Format(_ADAMUserSearchByEmailFilter, user.Email), deUserContainer, out deMembershipUser) == true) throw new ApplicationException(string.Format("A user with email {0} already exists", user.Email));
//set the user record with the updates deMembershipUser.Properties[_ADAMPropUserName].Value = user.UserName; deMembershipUser.Properties[_ADAMPropEMail].Value = user.Email; //deMembershipUser.Properties[_ADAMPropComment].Value = user.Comment; //deMembershipUser.Properties[_ADAMPropIsApproved].Value = user.IsApproved.ToString(); deMembershipUser.Properties[_ADAMPropPasswordQuestion].Value = user.PasswordQuestion;
//save changes deMembershipUser.CommitChanges(); } } catch (Exception Ex) { throw new ApplicationException("Error updating User", Ex); } finally { try { deMembershipUser.Close(); deUserContainer.Close(); } catch (Exception Ex) { } }
public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, out MembershipCreateStatus status) { MembershipUser NewUser = null; DirectoryEntry deUserContainer = null;
DirectoryEntry deMembershipUser = null;
status = MembershipCreateStatus.UserRejected;
try { //check if the user exists deUserContainer = (_ADAMUserName != null && _ADAMPassword != null) ? new DirectoryEntry(_ADAMLDAPPathToUserContainer, _ADAMUserName, _ADAMPassword) : new DirectoryEntry(_ADAMLDAPPathToUserContainer); if (ADAMFindUser((_ApplicationName != null) ? string.Format(_ADAMUserSearchByUserNameFilterAppSpecific, _ApplicationName, username) : string.Format(_ADAMUserSearchByUserNameFilter, username), deUserContainer, out deMembershipUser) == true) { //if found, return error status = MembershipCreateStatus.DuplicateUserName; return null; } //check for duplicate email constraint if (_RequiresUniqueEMail && ADAMFindUser((_ApplicationName != null) ? string.Format(_ADAMUserSearchByEmailFilterAppSpecific, _ApplicationName, email) : string.Format(_ADAMUserSearchByEmailFilter, email), deUserContainer, out deMembershipUser) == true) { //if violated return error status = MembershipCreateStatus.DuplicateEmail; return null; }
//create new user id Guid UserId = Guid.NewGuid(); DateTime TimeNow = DateTime.UtcNow; //add the object. Set CN to the user id GUID. CN needs to be unique. This avoids conflicts around having same user names //for multiple applications. Other alternative could be to use a concat to username and appname as CN deMembershipUser = deUserContainer.Children.Add(string.Format(_ADAMCommonName, UserId.ToString()), _ADAMUserObjectClass); //set other attributes deMembershipUser.Properties[_ADAMPropUserId].Value = UserId.ToByteArray(); deMembershipUser.Properties[_ADAMPropUserName].Value = username; deMembershipUser.Properties[_ADAMPropApplicationName].Value = _ApplicationName; deMembershipUser.Properties[_ADAMPropPassword].Value = ConvertPasswordForStorage(password); deMembershipUser.Properties[_ADAMPropEMail].Value = email; deMembershipUser.Properties[_ADAMPropUserCreationTimestamp].Value = TimeNow; deMembershipUser.Properties[_ADAMPropPasswordQuestion].Value = passwordQuestion; deMembershipUser.Properties[_ADAMPropPasswordAnswer].Value = passwordAnswer; deMembershipUser.Properties[_ADAMPropIsApproved].Value = true; //save changes deMembershipUser.CommitChanges(); //create new instance of MembershipUser and return it NewUser = new MembershipUser(this, username, UserId, email, null, null, true, (DateTime)deMembershipUser.Properties[_ADAMPropUserCreationTimestamp].Value, DateTime.Now, DateTime.Now, DateTime.Now); status = MembershipCreateStatus.Success;
} catch (Exception Ex) { status = MembershipCreateStatus.ProviderError; NewUser = null; } finally { try { deMembershipUser.Close(); deUserContainer.Close(); } catch (Exception Ex) { } }
return NewUser;
public override bool EnablePasswordReset { get {
return _EnablePasswordReset; } }
public override int GetNumberOfUsersOnline() { DirectoryEntry deUserContainer = null;
int Count = 0; try {
deUserContainer = (_ADAMUserName != null && _ADAMPassword != null) ? new DirectoryEntry(_ADAMLDAPPathToUserContainer, _ADAMUserName, _ADAMPassword) : new DirectoryEntry(_ADAMLDAPPathToUserContainer); //search for all users where LastActivityTimeStamp >= TimeNow - UserIsOnlineTimeWindow string Filter = (_ApplicationName != null) ? string.Format(_ADAMCountUsersOnlineAppSpecific, _ApplicationName, DateTime.UtcNow.AddMinutes(Convert.ToDouble(-1 * Membership.UserIsOnlineTimeWindow))) : string.Format(_ADAMCountUsersOnline, DateTime.UtcNow.AddMinutes(Convert.ToDouble(-1 * Membership.UserIsOnlineTimeWindow))); ADAMFindUsers(Filter, deUserContainer, PAGEINDEX_NOPAGING, PAGESIZE_NOPAGING, out Count); } catch (Exception Ex) { throw; } finally { try { deUserContainer.Close(); } catch (Exception Ex) { } } //return count return Count; }
public override bool ChangePasswordQuestionAndAnswer(string name, string password, string newPwdQuestion, string newPwdAnswer) { DirectoryEntry deUserContainer = null; DirectoryEntry deMembershipUser = null;
try { //check if the user exists deUserContainer = (_ADAMUserName != null && _ADAMPassword != null) ? new DirectoryEntry(_ADAMLDAPPathToUserContainer, _ADAMUserName, _ADAMPassword) : new DirectoryEntry(_ADAMLDAPPathToUserContainer); if (ADAMFindUser((_ApplicationName != null) ? string.Format(_ADAMUserSearchByUserNameFilterAppSpecific, _ApplicationName, name) : string.Format(_ADAMUserSearchByUserNameFilter, name), deUserContainer, out deMembershipUser) == false) throw new ApplicationException(string.Format("User {0} does not exist", name));
if (deMembershipUser != null)//user record found !! { deMembershipUser.RefreshCache(); //check if the old password matches if (!ComparePassword(password, (byte[])deMembershipUser.Properties[_ADAMPropPassword].Value)) throw new ApplicationException("Existing password does not match"); //set properties and save changes deMembershipUser.Properties[_ADAMPropPasswordQuestion].Value = newPwdQuestion; deMembershipUser.Properties[_ADAMPropPasswordAnswer].Value = newPwdAnswer; deMembershipUser.CommitChanges(); } } catch (Exception Ex) { throw new ApplicationException("Error changing password", Ex); } finally { try { deMembershipUser.Close(); deUserContainer.Close(); } catch (Exception Ex) { } } return true; }
public override MembershipUser GetUser(string name, bool userIsOnline) { DirectoryEntry deUserContainer = null; DirectoryEntry deMembershipUser = null;
if (deMembershipUser != null)//user record found!! {
//refresh the AD cache to load all attributes deMembershipUser.RefreshCache(); //if the user is indicated to be online if (userIsOnline) { //update the appropriate timestamp and save changes deMembershipUser.Properties[_ADAMPropLastActivityTimestamp].Value = DateTime.UtcNow; deMembershipUser.CommitChanges(); } //return a new instance created from the retrieved user record return this.ConstructMembershipUserFromDirectoryEntry(deMembershipUser); /* return new MembershipUser(this, (string)deMembershipUser.Properties[_ADAMPropUserName].Value, deMembershipUser.Properties[_ADAMPropUserId].Value == null ? string.Empty : (string)deMembershipUser.Properties[_ADAMPropUserId].Value, deMembershipUser.Properties[_ADAMPropEMail].Value == null ? String.Empty : (string)deMembershipUser.Properties[_ADAMPropEMail].Value, deMembershipUser.Properties[_ADAMPropPasswordQuestion].Value == null ? String.Empty : (string)deMembershipUser.Properties[_ADAMPropPasswordQuestion].Value, deMembershipUser.Properties[_ADAMPropComment].Value == null ? String.Empty : (string)deMembershipUser.Properties[_ADAMPropComment].Value, deMembershipUser.Properties[_ADAMPropIsApproved].Value == null ? false : (bool)deMembershipUser.Properties[_ADAMPropIsApproved].Value, deMembershipUser.Properties[_ADAMPropUserCreationTimestamp].Value == null ? DateTime.Now : (DateTime)deMembershipUser.Properties[_ADAMPropUserCreationTimestamp].Value, deMembershipUser.Properties[_ADAMPropLastLoginTimestamp].Value == null ? DateTime.Now : (DateTime)deMembershipUser.Properties[_ADAMPropLastLoginTimestamp].Value, deMembershipUser.Properties[_ADAMPropLastActivityTimestamp].Value == null ? DateTime.Now : (DateTime)deMembershipUser.Properties[_ADAMPropLastActivityTimestamp].Value, deMembershipUser.Properties[_ADAMPropLastPasswordChangeTimestamp].Value == null ? DateTime.Now : (DateTime)deMembershipUser.Properties[_ADAMPropLastPasswordChangeTimestamp].Value); */ } } catch (Exception Ex) { throw new ApplicationException("Error getting user", Ex); } finally { try { deMembershipUser.Close(); deUserContainer.Close(); } catch (Exception Ex) { } } return null; }
public override bool EnablePasswordRetrieval { get { return _EnablePasswordRetrieval; } }
public override string ApplicationName { get {
return _ApplicationName; } set { _ApplicationName = value; } }
public override string GetUserNameByEmail(string email) { DirectoryEntry deUserContainer = null; DirectoryEntry deMembershipUser = null; string RetVal = null;
try { //find the user for this application with the specified email address deUserContainer = (_ADAMUserName != null && _ADAMPassword != null) ? new DirectoryEntry(_ADAMLDAPPathToUserContainer, _ADAMUserName, _ADAMPassword) : new DirectoryEntry(_ADAMLDAPPathToUserContainer); if (ADAMFindUser((_ApplicationName != null) ? string.Format(_ADAMUserSearchByEmailFilterAppSpecific, _ApplicationName, email) : string.Format(_ADAMUserSearchByEmailFilter, email), deUserContainer, out deMembershipUser)) return null;
if (deMembershipUser != null)//user record found!! { //refresh the cache with the attribute values deMembershipUser.RefreshCache(); //return user name RetVal = (string)deMembershipUser.Properties[_ADAMPropUserName].Value; } } catch (Exception Ex) { throw new ApplicationException("Error retrieving user name", Ex); } finally { try { deMembershipUser.Close(); deUserContainer.Close(); } catch (Exception Ex) { } } return RetVal; }
public override bool ValidateUser(string name, string password) { DirectoryEntry deUserContainer = null; DirectoryEntry deMembershipUser = null; bool RetVal = false;
//check if the user exists deUserContainer = (_ADAMUserName != null && _ADAMPassword != null) ? new DirectoryEntry(_ADAMLDAPPathToUserContainer, _ADAMUserName, _ADAMPassword) : new DirectoryEntry(_ADAMLDAPPathToUserContainer); if (ADAMFindUser((_ApplicationName != null) ? string.Format(_ADAMUserSearchByUserNameFilterAppSpecific, _ApplicationName, name) : string.Format(_ADAMUserSearchByUserNameFilter, name), deUserContainer, out deMembershipUser) == false) RetVal = false;
if (deMembershipUser != null)//user record found!! { //refresh cache with attribute values deMembershipUser.RefreshCache(); //compare supplied password with stored password(or hash of supplied password with the stored hash in case the password format is set to hashed) RetVal = ComparePassword(password, (byte[])deMembershipUser.Properties[_ADAMPropPassword].Value); DateTime TimeNow = DateTime.UtcNow; //set appropriate timestamps deMembershipUser.Properties[_ADAMPropLastLoginTimestamp].Value = TimeNow; deMembershipUser.Properties[_ADAMPropLastActivityTimestamp].Value = TimeNow; deMembershipUser.CommitChanges(); } } catch (Exception Ex) { throw new ApplicationException("Error validating user", Ex); } finally { try { deMembershipUser.Close(); deUserContainer.Close(); } catch (Exception Ex) { } } //return comparison result return RetVal; }
public override string GetPassword(string name, string answer) {
DirectoryEntry deUserContainer = null; DirectoryEntry deMembershipUser = null;
string RetVal = null; try { //if password retrieval is disabled via configuration settings or the password format is set to hashed //we cannot retriev the password if (!_EnablePasswordRetrieval || _PasswordFormat == MembershipPasswordFormat.Hashed) throw new ApplicationException("Current configuration settings do not allow password retrieval"); //check if the user exists deUserContainer = (_ADAMUserName != null && _ADAMPassword != null) ? new DirectoryEntry(_ADAMLDAPPathToUserContainer, _ADAMUserName, _ADAMPassword) : new DirectoryEntry(_ADAMLDAPPathToUserContainer); if (ADAMFindUser((_ApplicationName != null) ? string.Format(_ADAMUserSearchByUserNameFilterAppSpecific, _ApplicationName, name) : string.Format(_ADAMUserSearchByUserNameFilter, name), deUserContainer, out deMembershipUser) == false) throw new ApplicationException(string.Format("User {0} does not exist", name));
if (deMembershipUser != null)//user record found!! { //refresh cache with stored attributes deMembershipUser.RefreshCache(); //if configuration settings demand a security question/answer protocol, the supplied password answer //needs to match the stored password answer if (_RequiresQuestionAndAnswer && (deMembershipUser.Properties[_ADAMPropPasswordAnswer].Value == null || (string)deMembershipUser.Properties[_ADAMPropPasswordAnswer].Value != answer)) throw new ApplicationException("Password answer does not match"); //decode password and return it RetVal = GetReadablePassword((byte[])deMembershipUser.Properties[_ADAMPropPassword].Value); } } catch (Exception Ex) { throw new ApplicationException("Error retrieving password", Ex); } finally { try { deMembershipUser.Close(); deUserContainer.Close(); } catch (Exception Ex) { } } return RetVal;
public override bool DeleteUser(string name, bool deleteAllRelatedData) { DirectoryEntry deUserContainer = null; DirectoryEntry deMembershipUser = null;
//check if user exists deUserContainer = (_ADAMUserName != null && _ADAMPassword != null) ? new DirectoryEntry(_ADAMLDAPPathToUserContainer, _ADAMUserName, _ADAMPassword) : new DirectoryEntry(_ADAMLDAPPathToUserContainer); if (ADAMFindUser((_ApplicationName != null) ? string.Format(_ADAMUserSearchByUserNameFilterAppSpecific, _ApplicationName, name) : string.Format(_ADAMUserSearchByUserNameFilter, name), deUserContainer, out deMembershipUser) == false) return false;
//remove the record deUserContainer.Children.Remove(deMembershipUser); //save changes deUserContainer.CommitChanges(); } } catch (Exception Ex) { throw new ApplicationException("Error deleting user", Ex); } finally { try { deUserContainer.Close(); } catch (Exception Ex) { } } return true; }
public override bool RequiresQuestionAndAnswer { get { return _RequiresQuestionAndAnswer; } }
public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords) { totalRecords = 0;
DirectoryEntry deUserContainer = null;
MembershipUserCollection RetVal = null; try {
deUserContainer = (_ADAMUserName != null && _ADAMPassword != null) ? new DirectoryEntry(_ADAMLDAPPathToUserContainer, _ADAMUserName, _ADAMPassword) : new DirectoryEntry(_ADAMLDAPPathToUserContainer); //get all the users or the nth page of users, and return the collection RetVal = ADAMFindUsers((_ApplicationName != null) ? string.Format(_ADAMUserSearchByEmailFilterAppSpecific, _ApplicationName, emailToMatch) : string.Format(_ADAMUserSearchByEmailFilter, emailToMatch), deUserContainer, pageIndex, pageSize, out totalRecords);
} catch (Exception Ex) { throw; } finally { try { deUserContainer.Close(); } catch (Exception Ex) { } }
return RetVal; }
public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords) { totalRecords = 0;
deUserContainer = (_ADAMUserName != null && _ADAMPassword != null) ? new DirectoryEntry(_ADAMLDAPPathToUserContainer, _ADAMUserName, _ADAMPassword) : new DirectoryEntry(_ADAMLDAPPathToUserContainer); //find the users matching RetVal = ADAMFindUsers((_ApplicationName != null) ? string.Format(_ADAMUserSearchByUserNameFilterAppSpecific, _ApplicationName, usernameToMatch) : string.Format(_ADAMUserSearchByUserNameFilter, usernameToMatch), deUserContainer, pageIndex, pageSize, out totalRecords);
public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords) {
totalRecords = 0;
//let's first see if the user exists deUserContainer = (_ADAMUserName != null && _ADAMPassword != null) ? new DirectoryEntry(_ADAMLDAPPathToUserContainer, _ADAMUserName, _ADAMPassword) : new DirectoryEntry(_ADAMLDAPPathToUserContainer); RetVal = ADAMFindUsers((_ApplicationName != null) ? string.Format(_ADAMGetAllUsersFilterAppSpecific, _ApplicationName) : _ADAMGetAllUsersFilter, deUserContainer, pageIndex, pageSize, out totalRecords);
public override string Name { get { return _Name; } }
public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config) { _Name = name;
try { if (config["server"] != null) _ADAMServerUri = config["server"];
if (config["userName"] != null) _ADAMUserName = config["userName"];
if (config["password"] != null) _ADAMPassword = config["password"];
if (config["topContainer"] != null) _ADAMTopContainer = config["topContainer"];
if (config["userContainer"] != null) _ADAMUserContainer = config["userContainer"];
if (config["applicationName"] != null) _ApplicationName = config["applicationName"];
if (config["enablePasswordRetrieval"] != null) _EnablePasswordRetrieval = Convert.ToBoolean(config["enablePasswordRetrieval"].ToLower());
if (config["enablePasswordReset"] != null) _EnablePasswordReset = Convert.ToBoolean(config["enablePasswordReset"].ToLower());
if (config["requiresQuestionAndAnswer"] != null) _RequiresQuestionAndAnswer = Convert.ToBoolean(config["requiresQuestionAndAnswer"].ToLower());
if (config["requiresUniqueEMail"] != null) _RequiresUniqueEMail = Convert.ToBoolean(config["requiresUniqueEMail"].ToLower());
if (config["passwordFormat"] != null) { switch (config["passwordFormat"].ToLower()) { case "clear": _PasswordFormat = MembershipPasswordFormat.Clear; break; case "hashed": _PasswordFormat = MembershipPasswordFormat.Hashed; break; case "encrypted": _PasswordFormat = MembershipPasswordFormat.Encrypted; break; default: throw new ConfigurationException(string.Format("Unknown password format {0}. Supported password formats are Clear,Hashed or Encrypted", config["passwordFormat"])); } } LoadKey(config);
} catch (Exception Ex) { throw new System.Configuration.ConfigurationException("There was an error reading the membership configuration settings", Ex); }
_ADAMLDAPPathToUserContainer = string.Format("LDAP://{0}/{1},{2}", _ADAMServerUri, _ADAMUserContainer, _ADAMTopContainer);
private void LoadKey(System.Collections.Specialized.NameValueCollection config) { if (_PasswordFormat != MembershipPasswordFormat.Clear) { //object section = ConfigurationSettings.GetConfig("system.web/machineKey"); //MachineKeySection machineKeySection = (MachineKeySection)section; //MachineKeySection machineKeySection = (MachineKeySection)ConfigurationSettings.GetConfig("system.web/machineKey"); Configuration cfg = Configuration.GetWebConfiguration(System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath); MachineKeySection machineKeySection = (MachineKeySection)cfg.GetSection("system.web/machineKey");
switch (_PasswordFormat) { case MembershipPasswordFormat.Encrypted: //we need a symmetric key
if (!machineKeySection.DecryptionKey.ToLower().Contains("autogenerate")) _DecryptionKey = HexStringToByteArray(machineKeySection.DecryptionKey); else if (config["decryptionKey"] != null) _DecryptionKey = HexStringToByteArray(config["decryptionKey"]); else throw new ConfigurationException("Symmetric key required to encrypt passwords. Are you missing a <decryptionKey> in your provider entry ?"); break; case MembershipPasswordFormat.Hashed: if (!machineKeySection.ValidationKey.ToLower().Contains("autogenerate")) _ValidationKey = HexStringToByteArray(machineKeySection.ValidationKey); else if (config["validationKey"] != null) _ValidationKey = HexStringToByteArray(config["validationKey"]); else throw new ConfigurationException("Symmetric key required to hash passwords. Are you missing a <validationKey> in your provider entry ?"); break; } } }
private MembershipUser ConstructMembershipUserFromDirectoryEntry(DirectoryEntry deMembershipUser) { object userName; object userId; object eMail; object passwordQuestion; string comment; object isApproved; object creationDate; object lastLoginDate; object lastActivityDate; object lastPasswordChangedDate;
userName = deMembershipUser.Properties[_ADAMPropUserName].Value; userId = deMembershipUser.Properties[_ADAMPropUserId].Value; eMail = deMembershipUser.Properties[_ADAMPropEMail].Value; passwordQuestion = deMembershipUser.Properties[_ADAMPropPasswordQuestion].Value; comment = string.Empty; isApproved = deMembershipUser.Properties[_ADAMPropIsApproved].Value; creationDate = deMembershipUser.Properties[_ADAMPropUserCreationTimestamp].Value; lastLoginDate = deMembershipUser.Properties[_ADAMPropLastLoginTimestamp].Value; lastActivityDate = deMembershipUser.Properties[_ADAMPropLastActivityTimestamp].Value; lastPasswordChangedDate = deMembershipUser.Properties[_ADAMPropLastPasswordChangeTimestamp].Value;
userName = userName == null ? null : (string)userName; userId = userId == null ? string.Empty : new Guid((byte[])userId).ToString(); ; eMail = eMail == null ? null : (string)eMail; passwordQuestion = passwordQuestion == null ? null : (string)passwordQuestion; isApproved = isApproved == null ? false : (bool)isApproved; creationDate = creationDate == null ? DateTime.Now : (DateTime)creationDate; lastLoginDate = lastLoginDate == null ? DateTime.Now : (DateTime)lastLoginDate; lastActivityDate = lastActivityDate == null ? DateTime.Now : (DateTime)lastActivityDate; lastPasswordChangedDate = lastPasswordChangedDate == null ? DateTime.Now : (DateTime)lastPasswordChangedDate;
MembershipUser user = new MembershipUser(this, (string)userName, (string)userId, (string)eMail, (string)passwordQuestion, comment, (bool)isApproved, (DateTime)creationDate, (DateTime)lastLoginDate, (DateTime)lastActivityDate, (DateTime)lastPasswordChangedDate); return user; }
private MembershipUserCollection ADAMFindUsers(string Filter, DirectoryEntry SearchRoot, int PageIndex, int PageSize, out int Count) {
Count = 0;
SearchResultCollection dsUserSearchResult = null; MembershipUserCollection RetVal = new MembershipUserCollection();
DirectorySearcher dsUser = new DirectorySearcher(SearchRoot, Filter); dsUser.SearchScope = SearchScope.OneLevel;
try { if ((dsUserSearchResult = dsUser.FindAll()) != null) { Count = dsUserSearchResult.Count; if (PageSize == PAGESIZE_NOPAGING) PageSize = Count; //int StartIndex = (PageIndex - 1) * PageSize; int StartIndex = PageIndex * PageSize; int EndIndex = ((PageIndex + 1) * PageSize) - 1; if (EndIndex > (Count - 1)) { EndIndex = Count - 1; }
MembershipUser user; DirectoryEntry deMembershipUser; for (int Idx = StartIndex; Idx <= EndIndex; Idx++) { deMembershipUser = dsUserSearchResult[Idx].GetDirectoryEntry(); deMembershipUser.RefreshCache();
/* userName = deMembershipUser.Properties[_ADAMPropUserName].Value; userId = deMembershipUser.Properties[_ADAMPropUserId].Value; eMail = deMembershipUser.Properties[_ADAMPropEMail].Value; passwordQuestion = deMembershipUser.Properties[_ADAMPropPasswordQuestion].Value; comment = string.Empty; isApproved = deMembershipUser.Properties[_ADAMPropIsApproved].Value; creationDate = deMembershipUser.Properties[_ADAMPropUserCreationTimestamp].Value; lastLoginDate = deMembershipUser.Properties[_ADAMPropLastLoginTimestamp].Value; lastActivityDate = deMembershipUser.Properties[_ADAMPropLastActivityTimestamp].Value; lastPasswordChangedDate = deMembershipUser.Properties[_ADAMPropLastPasswordChangeTimestamp].Value;
userName = userName == null?null:(string)userName; userId = userId == null?string.Empty:new Guid((byte[])userId).ToString();; eMail = eMail == null?null:(string)eMail; passwordQuestion = passwordQuestion == null?null:(string)passwordQuestion; isApproved = isApproved == null?false:(bool)isApproved; creationDate = creationDate == null?DateTime.Now:(DateTime)creationDate; lastLoginDate = lastLoginDate == null?DateTime.Now:(DateTime)lastLoginDate; lastActivityDate = lastActivityDate == null?DateTime.Now:(DateTime)lastActivityDate; lastPasswordChangedDate = lastPasswordChangedDate == null?DateTime.Now:(DateTime)lastPasswordChangedDate; user = new MembershipUser(this,(string)userName,(string)userId,(string)eMail,(string)passwordQuestion,comment,(bool)isApproved,(DateTime)creationDate,(DateTime)lastLoginDate,(DateTime)lastActivityDate,(DateTime)lastPasswordChangedDate); */ user = this.ConstructMembershipUserFromDirectoryEntry(deMembershipUser); RetVal.Add(user); deMembershipUser.Close(); }
return RetVal; } catch (Exception Ex) { throw new ApplicationException("Error retrieving users", Ex); }
private bool ADAMFindUser(string Filter, DirectoryEntry SearchRoot, out DirectoryEntry deUser) {
SearchResult dsUserSearchResult = null; deUser = null;
if ((dsUserSearchResult = dsUser.FindOne()) != null) { deUser = dsUserSearchResult.GetDirectoryEntry(); return true; } else return false;
private string GetReadablePassword(byte[] StoredPassword) { System.Text.UnicodeEncoding ue = new System.Text.UnicodeEncoding(); string RetVal = null;
switch (_PasswordFormat) { case MembershipPasswordFormat.Clear: RetVal = ue.GetString(StoredPassword); break;
case MembershipPasswordFormat.Hashed: throw new ApplicationException("Password cannot be recovered from a hashed format");
case MembershipPasswordFormat.Encrypted: TripleDESCryptoServiceProvider tripleDes = new TripleDESCryptoServiceProvider(); tripleDes.Key = _DecryptionKey; tripleDes.IV = new byte[8];
CryptoStream cryptoStream = new CryptoStream(new MemoryStream(StoredPassword), tripleDes.CreateDecryptor(), CryptoStreamMode.Read); MemoryStream msPasswordDec = new MemoryStream(); int BytesRead = 0; byte[] Buffer = new byte[32]; while ((BytesRead = cryptoStream.Read(Buffer, 0, 32)) > 0) { msPasswordDec.Write(Buffer, 0, BytesRead); } cryptoStream.Close();
RetVal = ue.GetString(msPasswordDec.ToArray()); msPasswordDec.Close(); break; } return RetVal; } private byte[] ConvertPasswordForStorage(string Password) { System.Text.UnicodeEncoding ue = new System.Text.UnicodeEncoding(); byte[] uePassword = ue.GetBytes(Password); byte[] RetVal = null;
switch (_PasswordFormat) { case MembershipPasswordFormat.Clear: RetVal = uePassword; break; case MembershipPasswordFormat.Hashed:
HMACSHA1 SHA1KeyedHasher = new HMACSHA1(); SHA1KeyedHasher.Key = _ValidationKey; RetVal = SHA1KeyedHasher.ComputeHash(uePassword); break; case MembershipPasswordFormat.Encrypted: TripleDESCryptoServiceProvider tripleDes = new TripleDESCryptoServiceProvider(); tripleDes.Key = _DecryptionKey; tripleDes.IV = new byte[8]; MemoryStream mStreamEnc = new MemoryStream(); CryptoStream cryptoStream = new CryptoStream(mStreamEnc, tripleDes.CreateEncryptor(), CryptoStreamMode.Write);
cryptoStream.Write(uePassword, 0, uePassword.Length); cryptoStream.FlushFinalBlock(); RetVal = mStreamEnc.ToArray(); cryptoStream.Close(); break;
} return RetVal; }
private bool ComparePassword(string Password, byte[] StoredPassword) { UnicodeEncoding ue = new UnicodeEncoding(); bool RetVal = false; switch (_PasswordFormat) { case MembershipPasswordFormat.Clear: RetVal = (ue.GetString(StoredPassword) == Password); break; case MembershipPasswordFormat.Hashed: byte[] uePassword = ue.GetBytes(Password); HMACSHA1 SHA1KeyedHasher = new HMACSHA1(); SHA1KeyedHasher.Key = _ValidationKey; byte[] PasswordHash = SHA1KeyedHasher.ComputeHash(uePassword);
if (PasswordHash.Length != StoredPassword.Length) RetVal = false; else { int idx = 0; for (idx = 0; (idx < StoredPassword.Length) && (PasswordHash[idx] == StoredPassword[idx]); idx++) ; RetVal = (idx == StoredPassword.Length) ? true : false; } break; case MembershipPasswordFormat.Encrypted: TripleDESCryptoServiceProvider tripleDes = new TripleDESCryptoServiceProvider(); tripleDes.Key = _DecryptionKey; tripleDes.IV = new byte[8];
RetVal = (ue.GetString(msPasswordDec.ToArray()) == Password); msPasswordDec.Close(); break; }
private byte[] HexStringToByteArray(string HexString) { byte[] Result = new byte[HexString.Length / 2]; for (int idx = 0; idx < Result.Length; idx++) Result[idx] = Convert.ToByte(HexString.Substring(idx * 2, 2), 16); return Result; }
}}