2014-01-09 06:42:05 +00:00
|
|
|
package auth
|
|
|
|
|
|
|
|
import (
|
2014-01-09 23:18:49 +00:00
|
|
|
"encoding/gob"
|
2014-02-10 19:02:44 +00:00
|
|
|
"errors"
|
2014-02-05 00:39:01 +00:00
|
|
|
"fmt"
|
|
|
|
"io"
|
2014-01-09 06:42:05 +00:00
|
|
|
"net/http"
|
|
|
|
|
2014-03-18 19:28:47 +00:00
|
|
|
"crypto/rand"
|
2015-02-07 23:30:22 +00:00
|
|
|
|
2016-01-12 04:46:48 +00:00
|
|
|
"github.com/gophish/gophish/models"
|
2014-01-09 06:42:05 +00:00
|
|
|
ctx "github.com/gorilla/context"
|
|
|
|
"github.com/gorilla/securecookie"
|
|
|
|
"github.com/gorilla/sessions"
|
2016-01-10 20:54:59 +00:00
|
|
|
"golang.org/x/crypto/bcrypt"
|
2014-01-09 06:42:05 +00:00
|
|
|
)
|
|
|
|
|
2014-01-09 23:18:49 +00:00
|
|
|
//init registers the necessary models to be saved in the session later
|
|
|
|
func init() {
|
|
|
|
gob.Register(&models.User{})
|
2014-02-02 20:47:06 +00:00
|
|
|
gob.Register(&models.Flash{})
|
2016-08-06 21:00:36 +00:00
|
|
|
Store.Options.HttpOnly = true
|
2014-01-09 23:18:49 +00:00
|
|
|
}
|
|
|
|
|
2016-01-25 02:47:16 +00:00
|
|
|
// Store contains the session information for the request
|
2014-01-11 04:37:42 +00:00
|
|
|
var Store = sessions.NewCookieStore(
|
|
|
|
[]byte(securecookie.GenerateRandomKey(64)), //Signing key
|
2014-01-11 06:10:52 +00:00
|
|
|
[]byte(securecookie.GenerateRandomKey(32)))
|
2014-01-09 06:42:05 +00:00
|
|
|
|
2016-01-25 02:47:16 +00:00
|
|
|
// ErrInvalidPassword is thrown when a user provides an incorrect password.
|
2014-02-10 19:02:44 +00:00
|
|
|
var ErrInvalidPassword = errors.New("Invalid Password")
|
|
|
|
|
2016-02-13 22:37:12 +00:00
|
|
|
// ErrEmptyPassword is thrown when a user provides a blank password to the register
|
|
|
|
// or change password functions
|
|
|
|
var ErrEmptyPassword = errors.New("Password cannot be blank")
|
|
|
|
|
2016-03-02 13:30:46 +00:00
|
|
|
// ErrPasswordMismatch is thrown when a user provides passwords that do not match
|
|
|
|
var ErrPasswordMismatch = errors.New("Passwords must match")
|
|
|
|
|
2014-02-05 00:39:01 +00:00
|
|
|
// Login attempts to login the user given a request.
|
2014-01-11 06:10:52 +00:00
|
|
|
func Login(r *http.Request) (bool, error) {
|
2014-01-09 06:42:05 +00:00
|
|
|
username, password := r.FormValue("username"), r.FormValue("password")
|
|
|
|
session, _ := Store.Get(r, "gophish")
|
2014-03-25 03:31:33 +00:00
|
|
|
u, err := models.GetUserByUsername(username)
|
2014-03-26 04:53:51 +00:00
|
|
|
if err != nil && err != models.ErrUsernameTaken {
|
2014-01-09 06:42:05 +00:00
|
|
|
return false, err
|
|
|
|
}
|
|
|
|
//If we've made it here, we should have a valid user stored in u
|
|
|
|
//Let's check the password
|
2014-01-09 23:18:49 +00:00
|
|
|
err = bcrypt.CompareHashAndPassword([]byte(u.Hash), []byte(password))
|
2014-01-09 06:42:05 +00:00
|
|
|
if err != nil {
|
2014-01-09 23:18:49 +00:00
|
|
|
ctx.Set(r, "user", nil)
|
2014-03-18 19:35:02 +00:00
|
|
|
return false, ErrInvalidPassword
|
2014-01-09 06:42:05 +00:00
|
|
|
}
|
2014-01-09 23:18:49 +00:00
|
|
|
ctx.Set(r, "user", u)
|
|
|
|
session.Values["id"] = u.Id
|
2014-01-09 06:42:05 +00:00
|
|
|
return true, nil
|
|
|
|
}
|
|
|
|
|
2014-02-05 00:39:01 +00:00
|
|
|
// Register attempts to register the user given a request.
|
|
|
|
func Register(r *http.Request) (bool, error) {
|
2016-03-02 13:30:46 +00:00
|
|
|
username := r.FormValue("username")
|
2016-03-03 00:59:40 +00:00
|
|
|
newPassword := r.FormValue("password")
|
|
|
|
confirmPassword := r.FormValue("confirm_password")
|
2014-03-25 03:31:33 +00:00
|
|
|
u, err := models.GetUserByUsername(username)
|
2014-02-10 19:02:44 +00:00
|
|
|
// If we have an error which is not simply indicating that no user was found, report it
|
2015-02-07 23:30:22 +00:00
|
|
|
if err != nil {
|
|
|
|
fmt.Println(err)
|
2014-02-06 16:49:53 +00:00
|
|
|
return false, err
|
2014-02-05 00:39:01 +00:00
|
|
|
}
|
2015-02-07 23:30:22 +00:00
|
|
|
u = models.User{}
|
2016-03-02 13:30:46 +00:00
|
|
|
// If we've made it here, we should have a valid username given
|
2016-02-13 22:37:12 +00:00
|
|
|
// Check that the passsword isn't blank
|
2016-03-03 00:59:40 +00:00
|
|
|
if newPassword == "" {
|
2016-02-13 22:37:12 +00:00
|
|
|
return false, ErrEmptyPassword
|
|
|
|
}
|
2016-03-02 13:30:46 +00:00
|
|
|
// Make sure passwords match
|
2016-03-03 00:59:40 +00:00
|
|
|
if newPassword != confirmPassword {
|
2016-03-02 13:30:46 +00:00
|
|
|
return false, ErrPasswordMismatch
|
|
|
|
}
|
|
|
|
// Let's create the password hash
|
2016-03-03 00:59:40 +00:00
|
|
|
h, err := bcrypt.GenerateFromPassword([]byte(newPassword), bcrypt.DefaultCost)
|
2014-02-05 00:39:01 +00:00
|
|
|
if err != nil {
|
|
|
|
return false, err
|
|
|
|
}
|
2015-02-07 23:30:22 +00:00
|
|
|
u.Username = username
|
|
|
|
u.Hash = string(h)
|
|
|
|
u.ApiKey = GenerateSecureKey()
|
|
|
|
err = models.PutUser(&u)
|
2014-02-05 00:39:01 +00:00
|
|
|
return true, nil
|
|
|
|
}
|
|
|
|
|
2016-01-25 02:47:16 +00:00
|
|
|
// GenerateSecureKey creates a secure key to use
|
|
|
|
// as an API key
|
2014-02-05 00:39:01 +00:00
|
|
|
func GenerateSecureKey() string {
|
|
|
|
// Inspired from gorilla/securecookie
|
|
|
|
k := make([]byte, 32)
|
|
|
|
io.ReadFull(rand.Reader, k)
|
|
|
|
return fmt.Sprintf("%x", k)
|
|
|
|
}
|
2014-02-06 16:49:53 +00:00
|
|
|
|
2014-02-10 19:02:44 +00:00
|
|
|
func ChangePassword(r *http.Request) error {
|
|
|
|
u := ctx.Get(r, "user").(models.User)
|
2016-03-02 13:30:46 +00:00
|
|
|
currentPw := r.FormValue("current_password")
|
2016-03-03 00:59:40 +00:00
|
|
|
newPassword := r.FormValue("new_password")
|
|
|
|
confirmPassword := r.FormValue("confirm_new_password")
|
2014-02-06 16:49:53 +00:00
|
|
|
// Check the current password
|
2016-03-02 13:30:46 +00:00
|
|
|
err := bcrypt.CompareHashAndPassword([]byte(u.Hash), []byte(currentPw))
|
2014-02-06 16:49:53 +00:00
|
|
|
if err != nil {
|
2014-02-10 19:02:44 +00:00
|
|
|
return ErrInvalidPassword
|
2014-02-06 16:49:53 +00:00
|
|
|
}
|
2016-02-13 22:37:12 +00:00
|
|
|
// Check that the new password isn't blank
|
2016-03-03 00:59:40 +00:00
|
|
|
if newPassword == "" {
|
2016-02-13 22:37:12 +00:00
|
|
|
return ErrEmptyPassword
|
|
|
|
}
|
2016-03-02 13:30:46 +00:00
|
|
|
// Check that new passwords match
|
2016-03-03 00:59:40 +00:00
|
|
|
if newPassword != confirmPassword {
|
2016-03-02 13:30:46 +00:00
|
|
|
return ErrPasswordMismatch
|
|
|
|
}
|
2016-02-13 22:37:12 +00:00
|
|
|
// Generate the new hash
|
2016-03-03 00:59:40 +00:00
|
|
|
h, err := bcrypt.GenerateFromPassword([]byte(newPassword), bcrypt.DefaultCost)
|
2016-02-13 22:37:12 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
u.Hash = string(h)
|
|
|
|
if err = models.PutUser(&u); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
2014-02-06 16:49:53 +00:00
|
|
|
}
|