private PasswordHistory <UsernamePassword> ToHistory(string payload) { PasswordHistory <UsernamePassword> tmp = new PasswordHistory <UsernamePassword>(); StringBuilder sb = new StringBuilder(); char prev = ' '; string user = null; foreach (char cur in payload) { if (cur != escape && cur != sep) { sb.Append(cur); prev = cur; } else { if (cur == escape) { if (prev == escape) { sb.Append(cur); prev = ' '; } else { prev = cur; } } else //cur == sep { if (prev == escape) //literal { sb.Append(cur); } else //separation of items { if (user == null) //we're hitting the user separator { user = sb.ToString(); } else //ok, we're at the end of a payload { tmp.Add(new UsernamePassword(user, sb.ToString())); user = null; } sb.Clear(); } prev = cur; } } } if (sb.Length > 0) //have to deal with the last element { tmp.Add(new UsernamePassword(user, sb.ToString())); } return(tmp); }
public bool AddCredential(IUserIdentity user, Security.ICredential credential) { if (user != null && credential != null) { UserPasswordCredential up = credential as UserPasswordCredential; //this is the only type of credential we can use if (up != null) { UsernamePassword hist = up.ToHistoryPair(); //this is what we store in history if (UserPasswordProviderFactory.Instance.ComplexityChecker.IsValid(up.password)) //validate it meets complexity rules { //get the existing credential this will replace, or this may be all together new PersistedCredential curCred = GetPersisted(user.Uid, hist.UserName); if (curCred != null) { PasswordHistory <UsernamePassword> history = GetHistory(user.Uid, hist.UserName); if (!history.MatchesHistory(UsernamePassword.Matches, hist)) //can't add this since it's matching a current history in range { history.Add(hist); //delete and set the new password if (ReplaceCredential(user.Uid, hist.UserName, hist.Password)) { this.historyProvider.Update(user.Uid, history); return(true); } } } else //no existing cred, so this is a new one - but already meets complexity rule { PasswordHistory <UsernamePassword> history = GetHistory(user.Uid, hist.UserName); if (!history.MatchesHistory(UsernamePassword.Matches, hist)) //can't add this since it's matching a current history in range { history.Add(hist); //delete and set the new password if (this.storeProvider.AddCredential(user.Uid, this, hist.UserName, hist.Password)) //the hist is already salted { this.historyProvider.Update(user.Uid, history); //update the history return(true); } } } } //inside this level we have a valid password by complexity } } return(false); }
public bool ReplaceCredential(IUserIdentity user, Security.ICredential existing, Security.ICredential proposed) { if (user != null && existing != null && proposed != null) { UserPasswordCredential toRemove = existing as UserPasswordCredential; //this is the only type of credential we can use UserPasswordCredential toAdd = proposed as UserPasswordCredential; //this is the only type of credential we can use if (toRemove != null && toAdd != null) { PersistedCredential cred = GetPersisted(user.Uid, toRemove.UserName.ToLowerInvariant()); if (cred != null && toRemove.Matches(cred)) //has to be currently valid to do a replace { UsernamePassword up = toAdd.ToHistoryPair(); if (toRemove.UserName.ToLowerInvariant().Equals(toAdd.UserName.ToLowerInvariant())) { PasswordHistory <UsernamePassword> hist = GetHistory(user.Uid, up.UserName); if (!hist.MatchesHistory(UsernamePassword.Matches, up)) //check for historic collision { if (ReplaceCredential(user.Uid, up.UserName, up.Password)) { hist.Add(up); this.historyProvider.Update(user.Uid, hist); return(true); } } } else //different usernames being used { if (this.storeProvider.DeleteCredential(user.Uid, this, toRemove.UserName.ToLowerInvariant())) { this.historyProvider.Delete(user.Uid); //TODO -- this we need to fix by userId,type if (this.storeProvider.AddCredential(user.Uid, this, up.UserName, up.Password)) { PasswordHistory <UsernamePassword> hist = GetHistory(user.Uid, up.UserName); this.historyProvider.Update(user.Uid, hist); return(true); } } } } } } return(false); }