github.com/topsteplocal/gophish@v0.6.0/auth/auth.go (about)

     1  package auth
     2  
     3  import (
     4  	"encoding/gob"
     5  	"errors"
     6  	"fmt"
     7  	"io"
     8  	"net/http"
     9  
    10  	"crypto/rand"
    11  
    12  	ctx "github.com/gophish/gophish/context"
    13  	log "github.com/gophish/gophish/logger"
    14  	"github.com/gophish/gophish/models"
    15  	"github.com/gorilla/securecookie"
    16  	"github.com/gorilla/sessions"
    17  	"github.com/jinzhu/gorm"
    18  	"golang.org/x/crypto/bcrypt"
    19  )
    20  
    21  //init registers the necessary models to be saved in the session later
    22  func init() {
    23  	gob.Register(&models.User{})
    24  	gob.Register(&models.Flash{})
    25  	Store.Options.HttpOnly = true
    26  	// This sets the maxAge to 5 days for all cookies
    27  	Store.MaxAge(86400 * 5)
    28  }
    29  
    30  // Store contains the session information for the request
    31  var Store = sessions.NewCookieStore(
    32  	[]byte(securecookie.GenerateRandomKey(64)), //Signing key
    33  	[]byte(securecookie.GenerateRandomKey(32)))
    34  
    35  // ErrInvalidPassword is thrown when a user provides an incorrect password.
    36  var ErrInvalidPassword = errors.New("Invalid Password")
    37  
    38  // ErrEmptyPassword is thrown when a user provides a blank password to the register
    39  // or change password functions
    40  var ErrEmptyPassword = errors.New("Password cannot be blank")
    41  
    42  // ErrPasswordMismatch is thrown when a user provides passwords that do not match
    43  var ErrPasswordMismatch = errors.New("Passwords must match")
    44  
    45  // ErrUsernameTaken is thrown when a user attempts to register a username that is taken.
    46  var ErrUsernameTaken = errors.New("Username already taken")
    47  
    48  // Login attempts to login the user given a request.
    49  func Login(r *http.Request) (bool, models.User, error) {
    50  	username, password := r.FormValue("username"), r.FormValue("password")
    51  	u, err := models.GetUserByUsername(username)
    52  	if err != nil {
    53  		return false, models.User{}, err
    54  	}
    55  	//If we've made it here, we should have a valid user stored in u
    56  	//Let's check the password
    57  	err = bcrypt.CompareHashAndPassword([]byte(u.Hash), []byte(password))
    58  	if err != nil {
    59  		return false, models.User{}, ErrInvalidPassword
    60  	}
    61  	return true, u, nil
    62  }
    63  
    64  // Register attempts to register the user given a request.
    65  func Register(r *http.Request) (bool, error) {
    66  	username := r.FormValue("username")
    67  	newPassword := r.FormValue("password")
    68  	confirmPassword := r.FormValue("confirm_password")
    69  	u, err := models.GetUserByUsername(username)
    70  	// If the given username already exists, throw an error and return false
    71  	if err == nil {
    72  		return false, ErrUsernameTaken
    73  	}
    74  
    75  	// If we have an error which is not simply indicating that no user was found, report it
    76  	if err != nil && err != gorm.ErrRecordNotFound {
    77  		log.Warn(err)
    78  		return false, err
    79  	}
    80  
    81  	u = models.User{}
    82  	// If we've made it here, we should have a valid username given
    83  	// Check that the passsword isn't blank
    84  	if newPassword == "" {
    85  		return false, ErrEmptyPassword
    86  	}
    87  	// Make sure passwords match
    88  	if newPassword != confirmPassword {
    89  		return false, ErrPasswordMismatch
    90  	}
    91  	// Let's create the password hash
    92  	h, err := bcrypt.GenerateFromPassword([]byte(newPassword), bcrypt.DefaultCost)
    93  	if err != nil {
    94  		return false, err
    95  	}
    96  	u.Username = username
    97  	u.Hash = string(h)
    98  	u.ApiKey = GenerateSecureKey()
    99  	err = models.PutUser(&u)
   100  	return true, nil
   101  }
   102  
   103  // GenerateSecureKey creates a secure key to use
   104  // as an API key
   105  func GenerateSecureKey() string {
   106  	// Inspired from gorilla/securecookie
   107  	k := make([]byte, 32)
   108  	io.ReadFull(rand.Reader, k)
   109  	return fmt.Sprintf("%x", k)
   110  }
   111  
   112  func ChangePassword(r *http.Request) error {
   113  	u := ctx.Get(r, "user").(models.User)
   114  	currentPw := r.FormValue("current_password")
   115  	newPassword := r.FormValue("new_password")
   116  	confirmPassword := r.FormValue("confirm_new_password")
   117  	// Check the current password
   118  	err := bcrypt.CompareHashAndPassword([]byte(u.Hash), []byte(currentPw))
   119  	if err != nil {
   120  		return ErrInvalidPassword
   121  	}
   122  	// Check that the new password isn't blank
   123  	if newPassword == "" {
   124  		return ErrEmptyPassword
   125  	}
   126  	// Check that new passwords match
   127  	if newPassword != confirmPassword {
   128  		return ErrPasswordMismatch
   129  	}
   130  	// Generate the new hash
   131  	h, err := bcrypt.GenerateFromPassword([]byte(newPassword), bcrypt.DefaultCost)
   132  	if err != nil {
   133  		return err
   134  	}
   135  	u.Hash = string(h)
   136  	if err = models.PutUser(&u); err != nil {
   137  		return err
   138  	}
   139  	return nil
   140  }