mirror of https://github.com/gophish/gophish
Cleaned up some errors
Implemented using db.* helpers (ie GetUser) Implemented ChangePassword (not reachable from UI currently) Fixed angular issue in settings.html templatepull/24/head
parent
af7a8f4c4e
commit
40cd2ae837
60
auth/auth.go
60
auth/auth.go
|
@ -1,9 +1,7 @@
|
|||
package auth
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"encoding/gob"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
|
@ -27,24 +25,20 @@ var Store = sessions.NewCookieStore(
|
|||
[]byte(securecookie.GenerateRandomKey(64)), //Signing key
|
||||
[]byte(securecookie.GenerateRandomKey(32)))
|
||||
|
||||
var ErrUsernameTaken = errors.New("Username already taken")
|
||||
|
||||
// Login attempts to login the user given a request.
|
||||
func Login(r *http.Request) (bool, error) {
|
||||
username, password := r.FormValue("username"), r.FormValue("password")
|
||||
session, _ := Store.Get(r, "gophish")
|
||||
u := models.User{}
|
||||
err := db.Conn.SelectOne(&u, "SELECT * FROM Users WHERE username=?", username)
|
||||
if err == sql.ErrNoRows {
|
||||
u, err := db.GetUserByUsername(username)
|
||||
if err != db.ErrUsernameTaken {
|
||||
//Return false, but don't return an error
|
||||
return false, nil
|
||||
} else if err != nil {
|
||||
return false, err
|
||||
}
|
||||
//If we've made it here, we should have a valid user stored in u
|
||||
//Let's check the password
|
||||
err = bcrypt.CompareHashAndPassword([]byte(u.Hash), []byte(password))
|
||||
if err != nil {
|
||||
fmt.Println("Error in comparing hash and password")
|
||||
ctx.Set(r, "user", nil)
|
||||
//Return false, but don't return an error
|
||||
return false, nil
|
||||
|
@ -57,10 +51,9 @@ func Login(r *http.Request) (bool, error) {
|
|||
// Register attempts to register the user given a request.
|
||||
func Register(r *http.Request) (bool, error) {
|
||||
username, password := r.FormValue("username"), r.FormValue("password")
|
||||
u := models.User{}
|
||||
err := db.Conn.SelectOne(&u, "SELECT * FROM Users WHERE username=?", username)
|
||||
if err != sql.ErrNoRows {
|
||||
return false, ErrUsernameTaken
|
||||
u, err := db.GetUserByUsername(username)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
//If we've made it here, we should have a valid username given
|
||||
//Let's create the password hash
|
||||
|
@ -78,31 +71,28 @@ func Register(r *http.Request) (bool, error) {
|
|||
return true, nil
|
||||
}
|
||||
|
||||
// GetUserById returns the user that the given id corresponds to. If no user is found, an
|
||||
// error is thrown.
|
||||
func GetUserById(id int64) (models.User, error) {
|
||||
u := models.User{}
|
||||
err := db.Conn.SelectOne(&u, "SELECT id, username, api_key FROM Users WHERE id=?", id)
|
||||
if err != nil {
|
||||
return u, err
|
||||
}
|
||||
return u, nil
|
||||
}
|
||||
|
||||
// GetUserByAPIKey returns the user that the given API Key corresponds to. If no user is found, an
|
||||
// error is thrown.
|
||||
func GetUserByAPIKey(key []byte) (models.User, error) {
|
||||
u := models.User{}
|
||||
err := db.Conn.SelectOne(&u, "SELECT id, username, api_key FROM Users WHERE apikey=?", key)
|
||||
if err != nil {
|
||||
return u, err
|
||||
}
|
||||
return u, nil
|
||||
}
|
||||
|
||||
func GenerateSecureKey() string {
|
||||
// Inspired from gorilla/securecookie
|
||||
k := make([]byte, 32)
|
||||
io.ReadFull(rand.Reader, k)
|
||||
return fmt.Sprintf("%x", k)
|
||||
}
|
||||
|
||||
func ChangePassword(u *models.User, c string, n string) bool {
|
||||
// Check the current password
|
||||
err := bcrypt.CompareHashAndPassword([]byte(u.Hash), []byte(c))
|
||||
if err != nil {
|
||||
return false
|
||||
} else {
|
||||
// Generate the new hash
|
||||
h, err := bcrypt.GenerateFromPassword([]byte(n), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
u.Hash = string(h)
|
||||
if err = db.PutUser(u); err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,6 @@ import (
|
|||
|
||||
ctx "github.com/gorilla/context"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/gorilla/sessions"
|
||||
"github.com/jordan-wright/gophish/auth"
|
||||
"github.com/jordan-wright/gophish/db"
|
||||
"github.com/jordan-wright/gophish/models"
|
||||
|
@ -37,13 +36,12 @@ func API_Reset(w http.ResponseWriter, r *http.Request) {
|
|||
case r.Method == "POST":
|
||||
u := ctx.Get(r, "user").(models.User)
|
||||
u.APIKey = auth.GenerateSecureKey()
|
||||
db.Conn.Exec("UPDATE users SET api_key=? WHERE id=?", u.APIKey, u.Id)
|
||||
session := ctx.Get(r, "session").(*sessions.Session)
|
||||
session.AddFlash(models.Flash{
|
||||
Type: "success",
|
||||
Message: "API Key Successfully Reset",
|
||||
})
|
||||
session.Save(r, w)
|
||||
err := db.PutUser(&u)
|
||||
if err != nil {
|
||||
Flash(w, r, "danger", "Error resetting API Key")
|
||||
} else {
|
||||
Flash(w, r, "success", "API Key Successfully Reset")
|
||||
}
|
||||
http.Redirect(w, r, "/settings", 302)
|
||||
}
|
||||
}
|
||||
|
@ -53,8 +51,7 @@ func API_Reset(w http.ResponseWriter, r *http.Request) {
|
|||
func API_Campaigns(w http.ResponseWriter, r *http.Request) {
|
||||
switch {
|
||||
case r.Method == "GET":
|
||||
cs := []models.Campaign{}
|
||||
_, err := db.Conn.Select(&cs, "SELECT c.id, name, created_date, completed_date, status, template FROM campaigns c, users u WHERE c.uid=u.id AND u.api_key=?", ctx.Get(r, "api_key"))
|
||||
cs, err := db.GetCampaigns(ctx.Get(r, "api_key"))
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
@ -96,14 +93,11 @@ func API_Campaigns(w http.ResponseWriter, r *http.Request) {
|
|||
// valid, API_Campaigns_Id returns null.
|
||||
func API_Campaigns_Id(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
id, err := strconv.ParseInt(vars["id"], 0, 64)
|
||||
if checkError(err, w, "Invalid Int") {
|
||||
return
|
||||
}
|
||||
id, _ := strconv.ParseInt(vars["id"], 0, 64)
|
||||
switch {
|
||||
case r.Method == "GET":
|
||||
c := models.Campaign{}
|
||||
err := db.Conn.SelectOne(&c, "SELECT campaigns.id, name, created_date, completed_date, status, template FROM campaigns, users WHERE campaigns.uid=users.id AND campaigns.id =? AND users.api_key=?", id, ctx.Get(r, "api_key"))
|
||||
c, err := db.GetCampaign(id, ctx.Get(r, "api_key"))
|
||||
if checkError(err, w, "No campaign found") {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -173,8 +173,8 @@ func Login(w http.ResponseWriter, r *http.Request) {
|
|||
case r.Method == "POST":
|
||||
//Attempt to login
|
||||
succ, err := auth.Login(r)
|
||||
if checkError(err, w, "Error logging in") {
|
||||
return
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
//If we've logged in, save the session and redirect to the dashboard
|
||||
if succ {
|
||||
|
|
11
db/db.go
11
db/db.go
|
@ -118,6 +118,13 @@ func GetCampaigns(key interface{}) ([]models.Campaign, error) {
|
|||
return cs, err
|
||||
}
|
||||
|
||||
func GetCampaign(id int64) {
|
||||
|
||||
func GetCampaign(id int64, key interface{}) (models.Campaign, error) {
|
||||
c := models.Campaign{}
|
||||
err := Conn.SelectOne(&c, "SELECT campaigns.id, name, created_date, completed_date, status, template FROM campaigns, users WHERE campaigns.uid=users.id AND campaigns.id =? AND users.api_key=?", id, key)
|
||||
return c, err
|
||||
}
|
||||
|
||||
func PutCampaign(c *models.Campaign) error {
|
||||
_, err := Conn.Update(c)
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -82,3 +82,7 @@
|
|||
p {
|
||||
font-size:1.2em;
|
||||
}
|
||||
|
||||
.form-label {
|
||||
padding-top:7px;
|
||||
}
|
|
@ -23,22 +23,9 @@
|
|||
{{%template "flashes" .Flashes%}}
|
||||
<h1 style="margin:0px 0px 15px 0px;">User Settings</h1>
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<p><b>Username:</b>
|
||||
</p>
|
||||
</div>
|
||||
<label for="api_key" class="col-sm-2 control-label form-label">API Key:</label>
|
||||
<div class="col-md-6">
|
||||
<input type="text" value="{{%.User.Username%}}" class="form-control" />
|
||||
</div>
|
||||
</div>
|
||||
<br/>
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<p><b>API Key:</b>
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<input type="text" onclick="this.select();" value="{{%.User.APIKey%}}" class="form-control" readonly/>
|
||||
<input type="text" id="api_key" onclick="this.select();" value="{{%.User.APIKey%}}" class="form-control" readonly/>
|
||||
</div>
|
||||
<form action="/api/reset" method="POST">
|
||||
<button class="btn btn-primary"><i class="fa fa-refresh" type="submit"></i> Reset</button>
|
||||
|
@ -46,6 +33,29 @@
|
|||
</form>
|
||||
</div>
|
||||
<br />
|
||||
<form action="/settings" method="POST">
|
||||
<div class="row">
|
||||
<label for="username" class="col-sm-2 control-label form-label">Username:</label>
|
||||
<div class="col-md-6">
|
||||
<input type="text" id="username" value="{{%.User.Username%}}" class="form-control" />
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<div class="row">
|
||||
<label for="current_password" class="col-sm-2 control-label form-label">Old Password:</label>
|
||||
<div class="col-md-6">
|
||||
<input type="password" id="current_password" class="form-control" />
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<div class="row">
|
||||
<label for="new_password" class="col-sm-2 control-label form-label">New Password:</label>
|
||||
<div class="col-md-6">
|
||||
<input type="password" id="new_password" class="form-control" />
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<br/>
|
||||
<button class="btn btn-primary">Save</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -36,7 +36,9 @@
|
|||
<tbody>
|
||||
<tr ng-repeat="group in groups">
|
||||
<td>{{group.name}}</td>
|
||||
<td>{{group.targets}}</td>
|
||||
<td><span ng-repeat="target in group.targets">
|
||||
{{target.email}}{{$last ? '' : ', '}}
|
||||
</span></td>
|
||||
<td>{{group.modified_date | date:'medium'}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
|
Loading…
Reference in New Issue