diff options
author | Steve Manuel <nilslice@gmail.com> | 2017-01-02 21:57:53 -0800 |
---|---|---|
committer | Steve Manuel <nilslice@gmail.com> | 2017-01-02 21:57:53 -0800 |
commit | c1d9ac15acdc9ea2f389cfcd8eee2ac7db291f87 (patch) | |
tree | 316c4a0c854dca1a089573daf44cc0098a643ed2 | |
parent | 2ed96b15af39aaeb43ed56c7c9ef6535f31a6d96 (diff) |
update codebase where previous deps were used
-rw-r--r-- | system/admin/handlers.go | 39 | ||||
-rw-r--r-- | system/admin/user/auth.go | 101 | ||||
-rw-r--r-- | system/db/user.go | 6 |
3 files changed, 108 insertions, 38 deletions
diff --git a/system/admin/handlers.go b/system/admin/handlers.go index 3d0cf16..0fb025c 100644 --- a/system/admin/handlers.go +++ b/system/admin/handlers.go @@ -74,7 +74,12 @@ func initHandler(res http.ResponseWriter, req *http.Request) { // create and save admin user email := strings.ToLower(req.FormValue("email")) password := req.FormValue("password") - usr := user.NewUser(email, password) + usr, err := user.New(email, password) + if err != nil { + log.Println(err) + res.WriteHeader(http.StatusInternalServerError) + return + } _, err = db.SetUser(usr) if err != nil { @@ -227,7 +232,12 @@ func configUsersHandler(res http.ResponseWriter, req *http.Request) { return } - usr := user.NewUser(email, password) + usr, err := user.New(email, password) + if err != nil { + log.Println(err) + res.WriteHeader(http.StatusInternalServerError) + return + } _, err = db.SetUser(usr) if err != nil { @@ -301,9 +311,19 @@ func configUsersEditHandler(res http.ResponseWriter, req *http.Request) { newPassword := req.PostFormValue("new_password") var updatedUser *user.User if newPassword != "" { - updatedUser = user.NewUser(email, newPassword) + updatedUser, err = user.New(email, newPassword) + if err != nil { + log.Println(err) + res.WriteHeader(http.StatusInternalServerError) + return + } } else { - updatedUser = user.NewUser(email, password) + updatedUser, err = user.New(email, password) + if err != nil { + log.Println(err) + res.WriteHeader(http.StatusInternalServerError) + return + } } // set the ID to the same ID as current user @@ -676,7 +696,6 @@ func recoveryKeyHandler(res http.ResponseWriter, req *http.Request) { if key != actual { log.Println("Bad recovery key submitted:", key) - log.Println("Actual:", actual) res.WriteHeader(http.StatusBadRequest) res.Write([]byte("Error, please go back and try again.")) @@ -712,7 +731,15 @@ func recoveryKeyHandler(res http.ResponseWriter, req *http.Request) { return } - update := user.NewUser(email, password) + update, err := user.New(email, password) + if err != nil { + log.Println(err) + + res.WriteHeader(http.StatusInternalServerError) + res.Write([]byte("Error, please go back and try again.")) + return + } + update.ID = usr.ID err = db.UpdateUser(usr, update) diff --git a/system/admin/user/auth.go b/system/admin/user/auth.go index 3ff2b2b..76c4804 100644 --- a/system/admin/user/auth.go +++ b/system/admin/user/auth.go @@ -1,11 +1,15 @@ package user import ( + "bytes" + crand "crypto/rand" "encoding/base64" + "log" + mrand "math/rand" "net/http" + "time" "github.com/nilslice/jwt" - "github.com/nilslice/rand" "golang.org/x/crypto/bcrypt" ) @@ -17,10 +21,21 @@ type User struct { Salt string `json:"salt"` } -// NewUser creates a user -func NewUser(email, password string) *User { - salt := salt128() - hash := encryptPassword([]byte(password), salt) +var ( + r = mrand.New(mrand.NewSource(time.Now().Unix())) +) + +// New creates a user +func New(email, password string) (*User, error) { + salt, err := randSalt() + if err != nil { + return nil, err + } + + hash, err := hashPassword([]byte(password), salt) + if err != nil { + return nil, err + } user := &User{ Email: email, @@ -28,7 +43,7 @@ func NewUser(email, password string) *User { Salt: base64.StdEncoding.EncodeToString(salt), } - return user + return user, nil } // Auth is HTTP middleware to ensure the request has proper token credentials @@ -63,42 +78,68 @@ func IsUser(usr *User, password string) bool { return false } - err = comparePassword([]byte(usr.Hash), []byte(password), salt) + err = checkPassword([]byte(usr.Hash), []byte(password), salt) if err != nil { + log.Println("Error checking password:", err) return false } return true } -// The following functions are from github.com/sluu99/um ----------------------- +// randSalt generates 16 * 8 bits of data for a random salt +func randSalt() ([]byte, error) { + buf := make([]byte, 16) + count := len(buf) + n, err := crand.Read(buf) + if err != nil { + return nil, err + } -// salt128 generates 128 bits of random data. -func salt128() []byte { - x := make([]byte, 16) - rand.Read(x) - return x -} + if n != count || err != nil { + for count > 0 { + count-- + buf[count] = byte(r.Int31n(256)) + } + } -// makePassword makes the actual password from the plain password and salt -func makePassword(plainPw, salt []byte) []byte { - password := make([]byte, 0, len(plainPw)+len(salt)) - password = append(password, salt...) - password = append(password, plainPw...) - return password + return buf, nil } -// encryptPassword uses bcrypt to encrypt a password and salt combination. -// It returns the encrypted password in hex form. -func encryptPassword(plainPw, salt []byte) []byte { - hash, _ := bcrypt.GenerateFromPassword(makePassword(plainPw, salt), 10) - return hash +// saltPassword combines the salt and password provided +func saltPassword(password, salt []byte) ([]byte, error) { + salted := &bytes.Buffer{} + _, err := salted.Write(append(salt, password...)) + if err != nil { + return nil, err + } + + return salted.Bytes(), nil } -// comparePassword compares a hash with the plain password and the salt. -// The function returns nil on success or an error on failure. -func comparePassword(hash, plainPw, salt []byte) error { - return bcrypt.CompareHashAndPassword(hash, makePassword(plainPw, salt)) +// hashPassword encrypts the salted password using bcrypt +func hashPassword(password, salt []byte) ([]byte, error) { + salted, err := saltPassword(password, salt) + if err != nil { + return nil, err + } + + hash, err := bcrypt.GenerateFromPassword(salted, 10) + if err != nil { + return nil, err + } + + return hash, nil } -// End code from github.com/sluu99/um ------------------------------------------ +// checkPassword compares the hash with the salted password. A nil return means +// the password is correct, but an error could mean either the password is not +// correct, or the salt process failed - indicated in logs +func checkPassword(hash, password, salt []byte) error { + salted, err := saltPassword(password, salt) + if err != nil { + return err + } + + return bcrypt.CompareHashAndPassword(hash, salted) +} diff --git a/system/db/user.go b/system/db/user.go index 1b15a82..02fda95 100644 --- a/system/db/user.go +++ b/system/db/user.go @@ -5,13 +5,14 @@ import ( "encoding/json" "errors" "fmt" + "math/rand" "net/http" + "time" "github.com/ponzu-cms/ponzu/system/admin/user" "github.com/boltdb/bolt" "github.com/nilslice/jwt" - "github.com/nilslice/rand" ) // ErrUserExists is used for the db to report to admin user of existing user @@ -198,7 +199,8 @@ func CurrentUser(req *http.Request) ([]byte, error) { // SetRecoveryKey generates and saves a random secret key to verify an email // address submitted in order to recover/reset an account password func SetRecoveryKey(email string) (string, error) { - key := fmt.Sprintf("%d", rand.Int63()) + r := rand.New(rand.NewSource(time.Now().Unix())) + key := fmt.Sprintf("%d", r.Int63()) err := store.Update(func(tx *bolt.Tx) error { b, err := tx.CreateBucketIfNotExists([]byte("__recoveryKeys")) |