mirror of https://github.com/gophish/gophish
Major refactoring - created auth, config, models, controllers, and middleware packages. Should help provide modularity and a clean architecture.
Added doc.go for each packagepull/24/head
parent
326ab52146
commit
7f084760f9
|
@ -0,0 +1,53 @@
|
|||
package auth
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"net/http"
|
||||
|
||||
"code.google.com/p/go.crypto/bcrypt"
|
||||
ctx "github.com/gorilla/context"
|
||||
"github.com/gorilla/securecookie"
|
||||
"github.com/gorilla/sessions"
|
||||
"github.com/jordan-wright/gophish/models"
|
||||
)
|
||||
|
||||
var Store = sessions.NewCookieStore([]byte(securecookie.GenerateRandomKey(64)))
|
||||
|
||||
// CheckLogin attempts to request a SQL record with the given username.
|
||||
// If successful, it then compares the received bcrypt hash.
|
||||
// If all checks pass, this function sets the session id for later use.
|
||||
func CheckLogin(r *http.Request) (bool, error) {
|
||||
username, password := r.FormValue("username"), r.FormValue("password")
|
||||
session, _ := Store.Get(r, "gophish")
|
||||
stmt, err := db.Prepare("SELECT * FROM Users WHERE username=?")
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
hash, err := bcrypt.GenerateFromPassword(password, bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
u := models.User{}
|
||||
err = stmt.QueryRow(username).Scan(&u.Id, &u.Username, &u.Hash, &u.APIKey)
|
||||
if err == sql.ErrNoRows {
|
||||
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(u.Hash, hash)
|
||||
if err != nil {
|
||||
ctx.Set(r, User, nil)
|
||||
//Return false, but don't return an error
|
||||
return false, nil
|
||||
}
|
||||
ctx.Set(r, models.User, u)
|
||||
session.Values["id"] = GetUser(r).Id
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func GetUser(r *http.Request) User {
|
||||
if rv := ctx.Get(r, models.User); rv != nil {
|
||||
return rv.(models.User)
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -1,5 +1,3 @@
|
|||
package main
|
||||
|
||||
/*
|
||||
gophish - Open-Source Phishing Framework
|
||||
|
||||
|
@ -26,15 +24,5 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import "net/http"
|
||||
|
||||
//Use allows us to stack middleware to process the request
|
||||
//Example taken from https://github.com/gorilla/mux/pull/36#issuecomment-25849172
|
||||
func Use(handler http.Handler, middleware ...func(http.Handler) http.Handler) http.Handler {
|
||||
for _, m := range middleware {
|
||||
handler = m(handler)
|
||||
}
|
||||
return handler
|
||||
}
|
||||
|
||||
//TODO: Add RequireLogin() Middleware
|
||||
// Package auth implements the authentication in use for gophish.
|
||||
package auth
|
|
@ -0,0 +1,22 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"github.com/jordan-wright/gophish/models"
|
||||
)
|
||||
|
||||
var Conf models.Config
|
||||
|
||||
func init() {
|
||||
// Get the config file
|
||||
config_file, err := ioutil.ReadFile("./config.json")
|
||||
if err != nil {
|
||||
fmt.Printf("File error: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
json.Unmarshal(config_file, &Conf)
|
||||
}
|
|
@ -1,5 +1,3 @@
|
|||
package main
|
||||
|
||||
/*
|
||||
gophish - Open-Source Phishing Framework
|
||||
|
||||
|
@ -26,45 +24,5 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"net/http"
|
||||
|
||||
"code.google.com/p/go.crypto/bcrypt"
|
||||
ctx "github.com/gorilla/context"
|
||||
)
|
||||
|
||||
func CheckLogin(r *http.Request) (bool, error) {
|
||||
username, password := r.FormValue("username"), r.FormValue("password")
|
||||
session, _ := store.Get(r, "gophish")
|
||||
stmt, err := db.Prepare("SELECT * FROM Users WHERE username=?")
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
hash, err := bcrypt.GenerateFromPassword(password, bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
err = stmt.QueryRow(username).Scan(&u.Id, &u.Username, &u.Hash, &u.APIKey)
|
||||
if err == sql.ErrNoRows {
|
||||
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(u.Hash, hash)
|
||||
if err != nil {
|
||||
ctx.Set(r, User, nil)
|
||||
//Return false, but don't return an error
|
||||
return false, nil
|
||||
}
|
||||
ctx.Set(r, User, u)
|
||||
session.Values["id"] = GetUser(r).Id
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func GetUser(r *http.Request) User {
|
||||
if rv := ctx.Get(r, User); rv != nil {
|
||||
return rv.(User)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
// Package config implements a global configuration to be used with gophish.
|
||||
package config
|
|
@ -0,0 +1,37 @@
|
|||
package controllers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
func API(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprintf(w, "Hello api")
|
||||
}
|
||||
|
||||
//API_Campaigns returns a list of campaigns if requested via GET.
|
||||
//If requested via POST, API_Campaigns creates a new campaign and returns a reference to it.
|
||||
func API_Campaigns(w http.ResponseWriter, r *http.Request) {
|
||||
switch {
|
||||
case r.Method == "GET":
|
||||
|
||||
case r.Method == "POST":
|
||||
fmt.Fprintf(w, "Hello POST!")
|
||||
}
|
||||
fmt.Fprintf(w, "Hello api")
|
||||
}
|
||||
|
||||
//API_Campaigns_Id returns details about the requested campaign. If the campaign is not
|
||||
//valid, API_Campaigns_Id returns null.
|
||||
func API_Campaigns_Id(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
vars := mux.Vars(r)
|
||||
fmt.Fprintf(w, "{\"method\" : \""+r.Method+"\", \"id\" : "+vars["id"]+"}")
|
||||
}
|
||||
|
||||
//API_Doc renders a template describing the API documentation.
|
||||
func API_Doc(w http.ResponseWriter, r *http.Request) {
|
||||
renderTemplate(w, "api_doc")
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
gophish - Open-Source Phishing Framework
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013 Jordan Wright
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
// Package controllers is responsible for setting up the routing and controllers (http.Handlers) for gophish.
|
||||
package controllers
|
|
@ -1,4 +1,4 @@
|
|||
package main
|
||||
package controllers
|
||||
|
||||
/*
|
||||
gophish - Open-Source Phishing Framework
|
||||
|
@ -31,13 +31,10 @@ import (
|
|||
"net/http"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/gorilla/securecookie"
|
||||
"github.com/gorilla/sessions"
|
||||
"github.com/jordan-wright/gophish/auth"
|
||||
)
|
||||
|
||||
var store = sessions.NewCookieStore([]byte(securecookie.GenerateRandomKey(64)))
|
||||
|
||||
func createRouter() http.Handler {
|
||||
func CreateRouter() http.Handler {
|
||||
router := mux.NewRouter()
|
||||
// Base Front-end routes
|
||||
router.HandleFunc("/", Base)
|
||||
|
@ -66,7 +63,7 @@ func Register(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
func Base(w http.ResponseWriter, r *http.Request) {
|
||||
session, _ := store.Get(r, "gophish")
|
||||
session, _ := auth.Store.Get(r, "gophish")
|
||||
// Example of using session - will be removed.
|
||||
session.Save(r, w)
|
||||
renderTemplate(w, "dashboard")
|
||||
|
@ -81,7 +78,7 @@ func Settings(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
func Base_Campaigns(w http.ResponseWriter, r *http.Request) {
|
||||
//session, _ := store.Get(r, "gophish")
|
||||
//session, _ := auth.Store.Get(r, "gophish")
|
||||
renderTemplate(w, "dashboard")
|
||||
}
|
||||
|
||||
|
@ -90,12 +87,12 @@ func Login(w http.ResponseWriter, r *http.Request) {
|
|||
case r.Method == "GET":
|
||||
renderTemplate(w, "login")
|
||||
case r.Method == "POST":
|
||||
session, _ := store.Get(r, "gophish")
|
||||
session, _ := auth.Store.Get(r, "gophish")
|
||||
//Attempt to login
|
||||
if err := r.ParseForm(); err != nil {
|
||||
http.Error(w, "Error parsing request", http.StatusInternalServerError)
|
||||
}
|
||||
succ, err := login(r)
|
||||
succ, err := auth.CheckLogin(r)
|
||||
if err != nil {
|
||||
http.Error(w, "Error logging in", http.StatusInternalServerError)
|
||||
}
|
28
gophish.go
28
gophish.go
|
@ -26,39 +26,23 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|||
THE SOFTWARE.
|
||||
*/
|
||||
import (
|
||||
"database/sql"
|
||||
"encoding/gob"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
"github.com/jordan-wright/gophish/controllers"
|
||||
"github.com/jordan-wright/gophish/middleware"
|
||||
)
|
||||
|
||||
var config Config
|
||||
var db sql.DB
|
||||
var setupFlag = flag.Bool("setup", false, "Starts the initial setup process for Gophish")
|
||||
|
||||
//init registers the necessary models to be saved in the session later
|
||||
func init() {
|
||||
gob.Register(&User{})
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Get the config file
|
||||
config_file, err := ioutil.ReadFile("./config.json")
|
||||
defer db.Close()
|
||||
if err != nil {
|
||||
fmt.Printf("File error: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
json.Unmarshal(config_file, &config)
|
||||
//Setup the global variables and settings
|
||||
_, err = Setup()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fmt.Printf("Gophish server started at http://%s\n", config.URL)
|
||||
http.Handle("/", createRouter())
|
||||
fmt.Printf("Gophish server started at http://%s\n", config.Conf.URL)
|
||||
http.Handle("/", middleware.Use(controllers.CreateRouter(), middleware.GetContext))
|
||||
http.ListenAndServe(config.URL, nil)
|
||||
}
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"net/smtp"
|
||||
)
|
||||
|
||||
//Send sends an Email using a connection to Server.
|
||||
//If a Username and Password are set for the Server, authentication will be attempted
|
||||
//However, to support open-relays, authentication is optional.
|
||||
func Send(email Email, server Server) {
|
||||
auth := nil
|
||||
if server.User != nil && server.Password != nil {
|
||||
auth := smtp.PlainAuth("", server.User, server.Password, server.Host)
|
||||
}
|
||||
smtp.SendMail(server.Host, auth, email.From, email.To, Email.Body)
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
gophish - Open-Source Phishing Framework
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013 Jordan Wright
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
// Package middleware is responsible for the definition/implementation of middleware functionality.
|
||||
// This package will also handle maintaining request Context and Session.
|
||||
package middleware
|
|
@ -0,0 +1,34 @@
|
|||
package middleware
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// Use allows us to stack middleware to process the request
|
||||
// Example taken from https://github.com/gorilla/mux/pull/36#issuecomment-25849172
|
||||
func Use(handler http.Handler, middleware ...func(http.Handler) http.Handler) http.Handler {
|
||||
for _, m := range middleware {
|
||||
handler = m(handler)
|
||||
}
|
||||
return handler
|
||||
}
|
||||
|
||||
// GetContext wraps each request in a function which fills in the context for a given request.
|
||||
// This includes setting the User and Session keys and values as necessary for use in later functions.
|
||||
func GetContext(handler http.Handler) http.Handler {
|
||||
// Set the context here
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Println("Get context called!")
|
||||
handler.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
// RequireLogin is a simple middleware which checks to see if the user is currently logged in.
|
||||
// If not, the function returns a 302 redirect to the login page.
|
||||
func RequireLogin(handler http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Println("RequireLogin called!!")
|
||||
handler.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
gophish - Open-Source Phishing Framework
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013 Jordan Wright
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
// Package models implements the types and structs needed in gophish.
|
||||
package models
|
|
@ -1,4 +1,4 @@
|
|||
package main
|
||||
package models
|
||||
|
||||
type SMTPServer struct {
|
||||
Host string `json:"host"`
|
26
setup.go
26
setup.go
|
@ -2,20 +2,32 @@ package main
|
|||
|
||||
import (
|
||||
"database/sql"
|
||||
"encoding/gob"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/jordan-wright/gophish/config"
|
||||
"github.com/jordan-wright/gophish/models"
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
)
|
||||
|
||||
//Setup creates and returns the database needed by Gophish
|
||||
func Setup() (*sql.DB, error) {
|
||||
//If the file already exists, delete it and recreate it
|
||||
if _, err := os.Stat(config.DBPath); err == nil {
|
||||
os.Remove(config.DBPath)
|
||||
var Db sql.DB
|
||||
|
||||
//init registers the necessary models to be saved in the session later
|
||||
func init() {
|
||||
gob.Register(&models.User{})
|
||||
Setup()
|
||||
}
|
||||
fmt.Println("Creating db at " + config.DBPath)
|
||||
db, err := sql.Open("sqlite3", config.DBPath)
|
||||
|
||||
// Setup creates and returns the database needed by Gophish.
|
||||
// It also populates the Gophish Config object
|
||||
func Setup() {
|
||||
//If the file already exists, delete it and recreate it
|
||||
if _, err := os.Stat(config.Conf.DBPath); err == nil {
|
||||
os.Remove(Conf.DBPath)
|
||||
}
|
||||
fmt.Println("Creating db at " + config.Conf.DBPath)
|
||||
db, err := sql.Open("sqlite3", config.Conf.DBPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue