Split passwd into its' own subpackage

This commit is contained in:
Daniel Oaks 2017-10-06 00:03:53 +10:00
parent 207c1074df
commit 68b1dc9e72
7 changed files with 37 additions and 29 deletions

View File

@ -14,6 +14,7 @@ import (
"github.com/goshuirc/irc-go/ircfmt" "github.com/goshuirc/irc-go/ircfmt"
"github.com/goshuirc/irc-go/ircmsg" "github.com/goshuirc/irc-go/ircmsg"
"github.com/oragono/oragono/irc/passwd"
"github.com/oragono/oragono/irc/sno" "github.com/oragono/oragono/irc/sno"
"github.com/tidwall/buntdb" "github.com/tidwall/buntdb"
) )
@ -224,7 +225,7 @@ func accRegisterHandler(server *Server, client *Client, msg ircmsg.IrcMessage) b
var creds AccountCredentials var creds AccountCredentials
// always set passphrase salt // always set passphrase salt
creds.PassphraseSalt, err = NewSalt() creds.PassphraseSalt, err = passwd.NewSalt()
if err != nil { if err != nil {
return fmt.Errorf("Could not create passphrase salt: %s", err.Error()) return fmt.Errorf("Could not create passphrase salt: %s", err.Error())
} }

View File

@ -14,12 +14,11 @@ import (
"strings" "strings"
"time" "time"
"code.cloudfoundry.org/bytefmt"
"github.com/oragono/oragono/irc/custime" "github.com/oragono/oragono/irc/custime"
"github.com/oragono/oragono/irc/logger" "github.com/oragono/oragono/irc/logger"
"github.com/oragono/oragono/irc/passwd"
"github.com/oragono/oragono/irc/utils" "github.com/oragono/oragono/irc/utils"
"code.cloudfoundry.org/bytefmt"
"gopkg.in/yaml.v2" "gopkg.in/yaml.v2"
) )
@ -48,7 +47,7 @@ func (conf *TLSListenConfig) Config() (*tls.Config, error) {
// PasswordBytes returns the bytes represented by the password hash. // PasswordBytes returns the bytes represented by the password hash.
func (conf *PassConfig) PasswordBytes() []byte { func (conf *PassConfig) PasswordBytes() []byte {
bytes, err := DecodePasswordHash(conf.Password) bytes, err := passwd.DecodePasswordHash(conf.Password)
if err != nil { if err != nil {
log.Fatal("decode password error: ", err) log.Fatal("decode password error: ", err)
} }
@ -102,7 +101,7 @@ type OperConfig struct {
// PasswordBytes returns the bytes represented by the password hash. // PasswordBytes returns the bytes represented by the password hash.
func (conf *OperConfig) PasswordBytes() []byte { func (conf *OperConfig) PasswordBytes() []byte {
bytes, err := DecodePasswordHash(conf.Password) bytes, err := passwd.DecodePasswordHash(conf.Password)
if err != nil { if err != nil {
log.Fatal("decode password error: ", err) log.Fatal("decode password error: ", err)
} }

View File

@ -11,6 +11,8 @@ import (
"os" "os"
"strings" "strings"
"github.com/oragono/oragono/irc/passwd"
"github.com/tidwall/buntdb" "github.com/tidwall/buntdb"
) )
@ -36,7 +38,7 @@ func InitDB(path string) {
err = store.Update(func(tx *buntdb.Tx) error { err = store.Update(func(tx *buntdb.Tx) error {
// set base db salt // set base db salt
salt, err := NewSalt() salt, err := passwd.NewSalt()
encodedSalt := base64.StdEncoding.EncodeToString(salt) encodedSalt := base64.StdEncoding.EncodeToString(salt)
if err != nil { if err != nil {
log.Fatal("Could not generate cryptographically-secure salt for the user:", err.Error()) log.Fatal("Could not generate cryptographically-secure salt for the user:", err.Error())

View File

@ -1,7 +1,7 @@
// Copyright (c) 2016 Daniel Oaks <daniel@danieloaks.net> // Copyright (c) 2016 Daniel Oaks <daniel@danieloaks.net>
// released under the MIT license // released under the MIT license
package irc package passwd
import ( import (
"crypto/rand" "crypto/rand"
@ -9,8 +9,12 @@ import (
"golang.org/x/crypto/bcrypt" "golang.org/x/crypto/bcrypt"
) )
const newSaltLen = 30 const (
const defaultPasswordCost = 14 // newSaltLen is how many bytes long newly-generated salts are.
newSaltLen = 30
// defaultPasswordCost is the bcrypt cost we use for passwords.
defaultPasswordCost = 14
)
// NewSalt returns a salt for crypto uses. // NewSalt returns a salt for crypto uses.
func NewSalt() ([]byte, error) { func NewSalt() ([]byte, error) {
@ -25,22 +29,22 @@ func NewSalt() ([]byte, error) {
return salt, nil return salt, nil
} }
// PasswordManager supports the hashing and comparing of passwords with the given salt. // SaltedManager supports the hashing and comparing of passwords with the given salt.
type PasswordManager struct { type SaltedManager struct {
salt []byte salt []byte
} }
// NewPasswordManager returns a new PasswordManager with the given salt. // NewSaltedManager returns a new SaltedManager with the given salt.
func NewPasswordManager(salt []byte) PasswordManager { func NewSaltedManager(salt []byte) SaltedManager {
var pwm PasswordManager var sm SaltedManager
pwm.salt = salt sm.salt = salt
return pwm return sm
} }
// assemblePassword returns an assembled slice of bytes for the given password details. // assemblePassword returns an assembled slice of bytes for the given password details.
func (pwm *PasswordManager) assemblePassword(specialSalt []byte, password string) []byte { func (sm *SaltedManager) assemblePassword(specialSalt []byte, password string) []byte {
var assembledPasswordBytes []byte var assembledPasswordBytes []byte
assembledPasswordBytes = append(assembledPasswordBytes, pwm.salt...) assembledPasswordBytes = append(assembledPasswordBytes, sm.salt...)
assembledPasswordBytes = append(assembledPasswordBytes, '-') assembledPasswordBytes = append(assembledPasswordBytes, '-')
assembledPasswordBytes = append(assembledPasswordBytes, specialSalt...) assembledPasswordBytes = append(assembledPasswordBytes, specialSalt...)
assembledPasswordBytes = append(assembledPasswordBytes, '-') assembledPasswordBytes = append(assembledPasswordBytes, '-')
@ -49,14 +53,14 @@ func (pwm *PasswordManager) assemblePassword(specialSalt []byte, password string
} }
// GenerateFromPassword encrypts the given password. // GenerateFromPassword encrypts the given password.
func (pwm *PasswordManager) GenerateFromPassword(specialSalt []byte, password string) ([]byte, error) { func (sm *SaltedManager) GenerateFromPassword(specialSalt []byte, password string) ([]byte, error) {
assembledPasswordBytes := pwm.assemblePassword(specialSalt, password) assembledPasswordBytes := sm.assemblePassword(specialSalt, password)
return bcrypt.GenerateFromPassword(assembledPasswordBytes, defaultPasswordCost) return bcrypt.GenerateFromPassword(assembledPasswordBytes, defaultPasswordCost)
} }
// CompareHashAndPassword compares a hashed password with its possible plaintext equivalent. // CompareHashAndPassword compares a hashed password with its possible plaintext equivalent.
// Returns nil on success, or an error on failure. // Returns nil on success, or an error on failure.
func (pwm *PasswordManager) CompareHashAndPassword(hashedPassword []byte, specialSalt []byte, password string) error { func (sm *SaltedManager) CompareHashAndPassword(hashedPassword []byte, specialSalt []byte, password string) error {
assembledPasswordBytes := pwm.assemblePassword(specialSalt, password) assembledPasswordBytes := sm.assemblePassword(specialSalt, password)
return bcrypt.CompareHashAndPassword(hashedPassword, assembledPasswordBytes) return bcrypt.CompareHashAndPassword(hashedPassword, assembledPasswordBytes)
} }

View File

@ -1,7 +1,7 @@
// Copyright (c) 2012-2014 Jeremy Latt // Copyright (c) 2012-2014 Jeremy Latt
// released under the MIT license // released under the MIT license
package irc package passwd
import ( import (
"encoding/base64" "encoding/base64"

View File

@ -26,6 +26,7 @@ import (
"github.com/oragono/oragono/irc/caps" "github.com/oragono/oragono/irc/caps"
"github.com/oragono/oragono/irc/isupport" "github.com/oragono/oragono/irc/isupport"
"github.com/oragono/oragono/irc/logger" "github.com/oragono/oragono/irc/logger"
"github.com/oragono/oragono/irc/passwd"
"github.com/oragono/oragono/irc/sno" "github.com/oragono/oragono/irc/sno"
"github.com/oragono/oragono/irc/utils" "github.com/oragono/oragono/irc/utils"
"github.com/tidwall/buntdb" "github.com/tidwall/buntdb"
@ -108,7 +109,7 @@ type Server struct {
operators map[string]Oper operators map[string]Oper
operclasses map[string]OperClass operclasses map[string]OperClass
password []byte password []byte
passwords *PasswordManager passwords *passwd.SaltedManager
registeredChannels map[string]*RegisteredChannel registeredChannels map[string]*RegisteredChannel
registeredChannelsMutex sync.RWMutex registeredChannelsMutex sync.RWMutex
rehashMutex sync.Mutex rehashMutex sync.Mutex
@ -474,7 +475,7 @@ func passHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
// check the provided password // check the provided password
password := []byte(msg.Params[0]) password := []byte(msg.Params[0])
if ComparePassword(server.password, password) != nil { if passwd.ComparePassword(server.password, password) != nil {
client.Send(nil, server.name, ERR_PASSWDMISMATCH, client.nick, "Password incorrect") client.Send(nil, server.name, ERR_PASSWDMISMATCH, client.nick, "Password incorrect")
client.Send(nil, server.name, "ERROR", "Password incorrect") client.Send(nil, server.name, "ERROR", "Password incorrect")
return true return true
@ -1140,7 +1141,7 @@ func operHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
server.configurableStateMutex.RUnlock() server.configurableStateMutex.RUnlock()
password := []byte(msg.Params[1]) password := []byte(msg.Params[1])
err = ComparePassword(oper.Pass, password) err = passwd.ComparePassword(oper.Pass, password)
if (oper.Pass == nil) || (err != nil) { if (oper.Pass == nil) || (err != nil) {
client.Send(nil, server.name, ERR_PASSWDMISMATCH, client.nick, "Password incorrect") client.Send(nil, server.name, ERR_PASSWDMISMATCH, client.nick, "Password incorrect")
return true return true
@ -1523,7 +1524,7 @@ func (server *Server) loadDatastore(datastorePath string) error {
return err return err
} }
pwm := NewPasswordManager(salt) pwm := passwd.NewSaltedManager(salt)
server.passwords = &pwm server.passwords = &pwm
return nil return nil
}) })

View File

@ -16,6 +16,7 @@ import (
"github.com/docopt/docopt-go" "github.com/docopt/docopt-go"
"github.com/oragono/oragono/irc" "github.com/oragono/oragono/irc"
"github.com/oragono/oragono/irc/logger" "github.com/oragono/oragono/irc/logger"
"github.com/oragono/oragono/irc/passwd"
"github.com/oragono/oragono/mkcerts" "github.com/oragono/oragono/mkcerts"
stackimpact "github.com/stackimpact/stackimpact-go" stackimpact "github.com/stackimpact/stackimpact-go"
"golang.org/x/crypto/ssh/terminal" "golang.org/x/crypto/ssh/terminal"
@ -58,7 +59,7 @@ Options:
log.Fatal("Error reading password:", err.Error()) log.Fatal("Error reading password:", err.Error())
} }
password := string(bytePassword) password := string(bytePassword)
encoded, err := irc.GenerateEncodedPassword(password) encoded, err := passwd.GenerateEncodedPassword(password)
if err != nil { if err != nil {
log.Fatal("encoding error:", err.Error()) log.Fatal("encoding error:", err.Error())
} }