forked from External/ergo
Compare commits
1 commit
master
...
devel+pass
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bf04dc24f9 |
3 changed files with 63 additions and 20 deletions
|
|
@ -130,15 +130,11 @@ func (am *AccountManager) Register(client *Client, account string, callbackNames
|
|||
certFPKey := fmt.Sprintf(keyCertToAccount, certfp)
|
||||
|
||||
var creds AccountCredentials
|
||||
// always set passphrase salt
|
||||
creds.PassphraseSalt, err = passwd.NewSalt()
|
||||
if err != nil {
|
||||
return errAccountCreation
|
||||
}
|
||||
// it's fine if this is empty, that just means no certificate is authorized
|
||||
creds.Certificate = certfp
|
||||
if passphrase != "" {
|
||||
creds.PassphraseHash, err = am.server.passwords.GenerateFromPassword(creds.PassphraseSalt, passphrase)
|
||||
creds.PassphraseHash, err = passwd.GenerateEncodedPasswordBytes(passphrase)
|
||||
creds.PassphraseIsV2 = true
|
||||
if err != nil {
|
||||
am.server.logger.Error("internal", fmt.Sprintf("could not hash password: %v", err))
|
||||
return errAccountCreation
|
||||
|
|
@ -459,8 +455,50 @@ func (am *AccountManager) AuthenticateByPassphrase(client *Client, accountName s
|
|||
return errAccountUnverified
|
||||
}
|
||||
|
||||
err = am.server.passwords.CompareHashAndPassword(
|
||||
account.Credentials.PassphraseHash, account.Credentials.PassphraseSalt, passphrase)
|
||||
if account.Credentials.PassphraseIsV2 {
|
||||
err = passwd.ComparePassword(account.Credentials.PassphraseHash, []byte(passphrase))
|
||||
} else {
|
||||
// compare using legacy method
|
||||
err = am.server.passwords.CompareHashAndPassword(account.Credentials.PassphraseHash, account.Credentials.PassphraseSalt, passphrase)
|
||||
if err == nil {
|
||||
// passphrase worked! silently upgrade them to use v2 hashing going forward.
|
||||
//TODO(dan): in future, replace this with an am.updatePassphrase(blah) function, which we can reuse in /ns update pass?
|
||||
err = am.server.store.Update(func(tx *buntdb.Tx) error {
|
||||
var creds AccountCredentials
|
||||
creds.Certificate = account.Credentials.Certificate
|
||||
creds.PassphraseHash, err = passwd.GenerateEncodedPasswordBytes(passphrase)
|
||||
creds.PassphraseIsV2 = true
|
||||
if err != nil {
|
||||
am.server.logger.Error("internal", fmt.Sprintf("could not hash password (updating existing hash version): %v", err))
|
||||
return errAccountCredUpdate
|
||||
}
|
||||
|
||||
credText, err := json.Marshal(creds)
|
||||
if err != nil {
|
||||
am.server.logger.Error("internal", fmt.Sprintf("could not marshal credentials (updating existing hash version): %v", err))
|
||||
return errAccountCredUpdate
|
||||
}
|
||||
credStr := string(credText)
|
||||
|
||||
// we know the account name is valid if this line is reached, otherwise the
|
||||
// above would have failed. as such, chuck out and ignore err on casefolding
|
||||
casefoldedAccountName, _ := CasefoldName(accountName)
|
||||
credentialsKey := fmt.Sprintf(keyAccountCredentials, casefoldedAccountName)
|
||||
|
||||
//TODO(dan): sling, can you please checkout this mutex usage, see if it
|
||||
// makes sense or not? bleh
|
||||
am.serialCacheUpdateMutex.Lock()
|
||||
defer am.serialCacheUpdateMutex.Unlock()
|
||||
|
||||
tx.Set(credentialsKey, credStr, nil)
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return errAccountInvalidCredentials
|
||||
}
|
||||
|
|
@ -680,6 +718,7 @@ var (
|
|||
type AccountCredentials struct {
|
||||
PassphraseSalt []byte
|
||||
PassphraseHash []byte
|
||||
PassphraseIsV2 bool `json:"passphrase-is-v2"`
|
||||
Certificate string // fingerprint
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,17 +10,18 @@ import "errors"
|
|||
// Runtime Errors
|
||||
var (
|
||||
errAccountAlreadyRegistered = errors.New("Account already exists")
|
||||
errAccountAlreadyVerified = errors.New("Account is already verified")
|
||||
errAccountCantDropPrimaryNick = errors.New("Can't unreserve primary nickname")
|
||||
errAccountCreation = errors.New("Account could not be created")
|
||||
errAccountCredUpdate = errors.New("Could not update password hash to new method")
|
||||
errAccountDoesNotExist = errors.New("Account does not exist")
|
||||
errAccountInvalidCredentials = errors.New("Invalid account credentials")
|
||||
errAccountNickReservationFailed = errors.New("Could not (un)reserve nick")
|
||||
errAccountNotLoggedIn = errors.New("You're not logged into an account")
|
||||
errAccountTooManyNicks = errors.New("Account has too many reserved nicks")
|
||||
errAccountUnverified = errors.New("Account is not yet verified")
|
||||
errAccountVerificationFailed = errors.New("Account verification failed")
|
||||
errAccountVerificationInvalidCode = errors.New("Invalid account verification code")
|
||||
errAccountUnverified = errors.New("Account is not yet verified")
|
||||
errAccountAlreadyVerified = errors.New("Account is already verified")
|
||||
errAccountInvalidCredentials = errors.New("Invalid account credentials")
|
||||
errAccountTooManyNicks = errors.New("Account has too many reserved nicks")
|
||||
errAccountNickReservationFailed = errors.New("Could not (un)reserve nick")
|
||||
errAccountCantDropPrimaryNick = errors.New("Can't unreserve primary nickname")
|
||||
errCallbackFailed = errors.New("Account verification could not be sent")
|
||||
errCertfpAlreadyExists = errors.New("An account already exists with your certificate")
|
||||
errChannelAlreadyRegistered = errors.New("Channel is already registered")
|
||||
|
|
|
|||
|
|
@ -15,16 +15,19 @@ var (
|
|||
ErrEmptyPassword = errors.New("empty password")
|
||||
)
|
||||
|
||||
// GenerateEncodedPassword returns an encrypted password, encoded into a string with base64.
|
||||
func GenerateEncodedPassword(passwd string) (encoded string, err error) {
|
||||
// GenerateEncodedPasswordBytes returns an encrypted password, returning the bytes directly.
|
||||
func GenerateEncodedPasswordBytes(passwd string) (encoded []byte, err error) {
|
||||
if passwd == "" {
|
||||
err = ErrEmptyPassword
|
||||
return
|
||||
}
|
||||
bcrypted, err := bcrypt.GenerateFromPassword([]byte(passwd), bcrypt.MinCost)
|
||||
if err != nil {
|
||||
encoded, err = bcrypt.GenerateFromPassword([]byte(passwd), bcrypt.MinCost)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// GenerateEncodedPassword returns an encrypted password, encoded into a string with base64.
|
||||
func GenerateEncodedPassword(passwd string) (encoded string, err error) {
|
||||
bcrypted, err := GenerateEncodedPasswordBytes(passwd)
|
||||
encoded = base64.StdEncoding.EncodeToString(bcrypted)
|
||||
return
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue