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)
|
certFPKey := fmt.Sprintf(keyCertToAccount, certfp)
|
||||||
|
|
||||||
var creds AccountCredentials
|
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
|
// it's fine if this is empty, that just means no certificate is authorized
|
||||||
creds.Certificate = certfp
|
creds.Certificate = certfp
|
||||||
if passphrase != "" {
|
if passphrase != "" {
|
||||||
creds.PassphraseHash, err = am.server.passwords.GenerateFromPassword(creds.PassphraseSalt, passphrase)
|
creds.PassphraseHash, err = passwd.GenerateEncodedPasswordBytes(passphrase)
|
||||||
|
creds.PassphraseIsV2 = true
|
||||||
if err != nil {
|
if err != nil {
|
||||||
am.server.logger.Error("internal", fmt.Sprintf("could not hash password: %v", err))
|
am.server.logger.Error("internal", fmt.Sprintf("could not hash password: %v", err))
|
||||||
return errAccountCreation
|
return errAccountCreation
|
||||||
|
|
@ -459,8 +455,50 @@ func (am *AccountManager) AuthenticateByPassphrase(client *Client, accountName s
|
||||||
return errAccountUnverified
|
return errAccountUnverified
|
||||||
}
|
}
|
||||||
|
|
||||||
err = am.server.passwords.CompareHashAndPassword(
|
if account.Credentials.PassphraseIsV2 {
|
||||||
account.Credentials.PassphraseHash, account.Credentials.PassphraseSalt, passphrase)
|
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 {
|
if err != nil {
|
||||||
return errAccountInvalidCredentials
|
return errAccountInvalidCredentials
|
||||||
}
|
}
|
||||||
|
|
@ -680,6 +718,7 @@ var (
|
||||||
type AccountCredentials struct {
|
type AccountCredentials struct {
|
||||||
PassphraseSalt []byte
|
PassphraseSalt []byte
|
||||||
PassphraseHash []byte
|
PassphraseHash []byte
|
||||||
|
PassphraseIsV2 bool `json:"passphrase-is-v2"`
|
||||||
Certificate string // fingerprint
|
Certificate string // fingerprint
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,17 +10,18 @@ import "errors"
|
||||||
// Runtime Errors
|
// Runtime Errors
|
||||||
var (
|
var (
|
||||||
errAccountAlreadyRegistered = errors.New("Account already exists")
|
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")
|
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")
|
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")
|
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")
|
errAccountVerificationFailed = errors.New("Account verification failed")
|
||||||
errAccountVerificationInvalidCode = errors.New("Invalid account verification code")
|
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")
|
errCallbackFailed = errors.New("Account verification could not be sent")
|
||||||
errCertfpAlreadyExists = errors.New("An account already exists with your certificate")
|
errCertfpAlreadyExists = errors.New("An account already exists with your certificate")
|
||||||
errChannelAlreadyRegistered = errors.New("Channel is already registered")
|
errChannelAlreadyRegistered = errors.New("Channel is already registered")
|
||||||
|
|
|
||||||
|
|
@ -15,16 +15,19 @@ var (
|
||||||
ErrEmptyPassword = errors.New("empty password")
|
ErrEmptyPassword = errors.New("empty password")
|
||||||
)
|
)
|
||||||
|
|
||||||
// GenerateEncodedPassword returns an encrypted password, encoded into a string with base64.
|
// GenerateEncodedPasswordBytes returns an encrypted password, returning the bytes directly.
|
||||||
func GenerateEncodedPassword(passwd string) (encoded string, err error) {
|
func GenerateEncodedPasswordBytes(passwd string) (encoded []byte, err error) {
|
||||||
if passwd == "" {
|
if passwd == "" {
|
||||||
err = ErrEmptyPassword
|
err = ErrEmptyPassword
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
bcrypted, err := bcrypt.GenerateFromPassword([]byte(passwd), bcrypt.MinCost)
|
encoded, err = bcrypt.GenerateFromPassword([]byte(passwd), bcrypt.MinCost)
|
||||||
if err != nil {
|
return
|
||||||
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)
|
encoded = base64.StdEncoding.EncodeToString(bcrypted)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue