package controllers import ( "fmt" "html/template" "net/http" ctx "github.com/gorilla/context" "github.com/gorilla/mux" "github.com/gorilla/sessions" "github.com/jordan-wright/gophish/auth" mid "github.com/jordan-wright/gophish/middleware" "github.com/jordan-wright/gophish/models" "github.com/justinas/nosurf" ) var templateDelims = []string{"{{%", "%}}"} func CreateRouter() *nosurf.CSRFHandler { router := mux.NewRouter() // Base Front-end routes router.HandleFunc("/login", Login) router.HandleFunc("/logout", Use(Logout, mid.RequireLogin)) router.HandleFunc("/register", Register) router.HandleFunc("/", Use(Base, mid.RequireLogin)) router.HandleFunc("/campaigns/{id:[0-9]+}", Use(Campaigns_Id, mid.RequireLogin)) router.HandleFunc("/users", Use(Users, mid.RequireLogin)) router.HandleFunc("/settings", Use(Settings, mid.RequireLogin)) // Create the API routes api := router.PathPrefix("/api").Subrouter() api.HandleFunc("/", Use(API, mid.RequireLogin)) api.HandleFunc("/reset", Use(API_Reset, mid.RequireLogin)) api.HandleFunc("/campaigns", Use(API_Campaigns, mid.RequireAPIKey)) api.HandleFunc("/campaigns/{id:[0-9]+}", Use(API_Campaigns_Id, mid.RequireAPIKey)) api.HandleFunc("/groups", Use(API_Groups, mid.RequireAPIKey)) api.HandleFunc("/groups/{id:[0-9]+}", Use(API_Groups_Id, mid.RequireAPIKey)) //Setup static file serving router.PathPrefix("/").Handler(http.FileServer(http.Dir("./static/"))) //Setup CSRF Protection csrfHandler := nosurf.New(router) csrfHandler.ExemptGlob("/api/*") csrfHandler.ExemptGlob("/static/*") return csrfHandler } // 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.HandlerFunc, mid ...func(http.Handler) http.HandlerFunc) http.HandlerFunc { for _, m := range mid { handler = m(handler) } return handler } func Register(w http.ResponseWriter, r *http.Request) { // If it is a post request, attempt to register the account // Now that we are all registered, we can log the user in Login(w, r) } func Logout(w http.ResponseWriter, r *http.Request) { // If it is a post request, attempt to register the account // Now that we are all registered, we can log the user in session := ctx.Get(r, "session").(*sessions.Session) delete(session.Values, "id") session.AddFlash(models.Flash{ Type: "success", Message: "You have successfully logged out.", }) session.Save(r, w) http.Redirect(w, r, "login", 302) } func Base(w http.ResponseWriter, r *http.Request) { // Example of using session - will be removed. params := struct { User models.User Title string Flashes []interface{} }{Title: "Dashboard", User: ctx.Get(r, "user").(models.User)} getTemplate(w, "dashboard").ExecuteTemplate(w, "base", params) } func Users(w http.ResponseWriter, r *http.Request) { params := struct { User models.User Title string Flashes []interface{} }{Title: "Users & Groups", User: ctx.Get(r, "user").(models.User)} getTemplate(w, "users").ExecuteTemplate(w, "base", params) } func Settings(w http.ResponseWriter, r *http.Request) { params := struct { User models.User Title string Flashes []interface{} }{Title: "Settings", User: ctx.Get(r, "user").(models.User)} session := ctx.Get(r, "session").(*sessions.Session) params.Flashes = session.Flashes() session.Save(r, w) getTemplate(w, "settings").ExecuteTemplate(w, "base", params) } func Campaigns_Id(w http.ResponseWriter, r *http.Request) { params := struct { User models.User Title string Flashes []interface{} }{Title: "Results", User: ctx.Get(r, "user").(models.User)} getTemplate(w, "dashboard").ExecuteTemplate(w, "base", params) } func Login(w http.ResponseWriter, r *http.Request) { params := struct { User models.User Title string Flashes []interface{} Token string }{Title: "Login", Token: nosurf.Token(r)} session := ctx.Get(r, "session").(*sessions.Session) switch { case r.Method == "GET": params.Flashes = session.Flashes() session.Save(r, w) getTemplate(w, "login").ExecuteTemplate(w, "base", params) case r.Method == "POST": //Attempt to login err := r.ParseForm() if checkError(err, w, "Error parsing request") { return } succ, err := auth.Login(r) if checkError(err, w, "Error logging in") { return } //If we've logged in, save the session and redirect to the dashboard if succ { session.Save(r, w) http.Redirect(w, r, "/", 302) } else { session.AddFlash(models.Flash{ Type: "danger", Message: "Invalid Username/Password", }) session.Save(r, w) http.Redirect(w, r, "/login", 302) } } } func getTemplate(w http.ResponseWriter, tmpl string) *template.Template { templates := template.New("template") templates.Delims(templateDelims[0], templateDelims[1]) _, err := templates.ParseFiles("templates/base.html", "templates/nav.html", "templates/"+tmpl+".html", "templates/flashes.html") if err != nil { fmt.Println(err) } return template.Must(templates, err) } func checkError(e error, w http.ResponseWriter, m string) bool { if e != nil { fmt.Println(e) http.Error(w, "Error: "+m, http.StatusInternalServerError) return true } return false }