github.com/jonathaningram/gophish@v0.3.1-0.20170829042651-ac3fe6aeae6c/controllers/route.go (about) 1 package controllers 2 3 import ( 4 "fmt" 5 "html/template" 6 "log" 7 "net/http" 8 "os" 9 10 "github.com/gophish/gophish/auth" 11 "github.com/gophish/gophish/config" 12 ctx "github.com/gophish/gophish/context" 13 mid "github.com/gophish/gophish/middleware" 14 "github.com/gophish/gophish/models" 15 "github.com/gorilla/csrf" 16 "github.com/gorilla/mux" 17 "github.com/gorilla/sessions" 18 ) 19 20 // Logger is used to send logging messages to stdout. 21 var Logger = log.New(os.Stdout, " ", log.Ldate|log.Ltime|log.Lshortfile) 22 23 // CreateAdminRouter creates the routes for handling requests to the web interface. 24 // This function returns an http.Handler to be used in http.ListenAndServe(). 25 func CreateAdminRouter() http.Handler { 26 router := mux.NewRouter() 27 // Base Front-end routes 28 router.HandleFunc("/", Use(Base, mid.RequireLogin)) 29 router.HandleFunc("/login", Login) 30 router.HandleFunc("/logout", Use(Logout, mid.RequireLogin)) 31 router.HandleFunc("/campaigns", Use(Campaigns, mid.RequireLogin)) 32 router.HandleFunc("/campaigns/{id:[0-9]+}", Use(CampaignID, mid.RequireLogin)) 33 router.HandleFunc("/templates", Use(Templates, mid.RequireLogin)) 34 router.HandleFunc("/users", Use(Users, mid.RequireLogin)) 35 router.HandleFunc("/landing_pages", Use(LandingPages, mid.RequireLogin)) 36 router.HandleFunc("/sending_profiles", Use(SendingProfiles, mid.RequireLogin)) 37 router.HandleFunc("/register", Use(Register, mid.RequireLogin)) 38 router.HandleFunc("/settings", Use(Settings, mid.RequireLogin)) 39 // Create the API routes 40 api := router.PathPrefix("/api").Subrouter() 41 api = api.StrictSlash(true) 42 api.HandleFunc("/", Use(API, mid.RequireLogin)) 43 api.HandleFunc("/reset", Use(API_Reset, mid.RequireLogin)) 44 api.HandleFunc("/campaigns/", Use(API_Campaigns, mid.RequireAPIKey)) 45 api.HandleFunc("/campaigns/summary", Use(API_Campaigns_Summary, mid.RequireAPIKey)) 46 api.HandleFunc("/campaigns/{id:[0-9]+}", Use(API_Campaigns_Id, mid.RequireAPIKey)) 47 api.HandleFunc("/campaigns/{id:[0-9]+}/results", Use(API_Campaigns_Id_Results, mid.RequireAPIKey)) 48 api.HandleFunc("/campaigns/{id:[0-9]+}/summary", Use(API_Campaign_Id_Summary, mid.RequireAPIKey)) 49 api.HandleFunc("/campaigns/{id:[0-9]+}/complete", Use(API_Campaigns_Id_Complete, mid.RequireAPIKey)) 50 api.HandleFunc("/groups/", Use(API_Groups, mid.RequireAPIKey)) 51 api.HandleFunc("/groups/summary", Use(API_Groups_Summary, mid.RequireAPIKey)) 52 api.HandleFunc("/groups/{id:[0-9]+}", Use(API_Groups_Id, mid.RequireAPIKey)) 53 api.HandleFunc("/groups/{id:[0-9]+}/summary", Use(API_Groups_Id_Summary, mid.RequireAPIKey)) 54 api.HandleFunc("/templates/", Use(API_Templates, mid.RequireAPIKey)) 55 api.HandleFunc("/templates/{id:[0-9]+}", Use(API_Templates_Id, mid.RequireAPIKey)) 56 api.HandleFunc("/pages/", Use(API_Pages, mid.RequireAPIKey)) 57 api.HandleFunc("/pages/{id:[0-9]+}", Use(API_Pages_Id, mid.RequireAPIKey)) 58 api.HandleFunc("/smtp/", Use(API_SMTP, mid.RequireAPIKey)) 59 api.HandleFunc("/smtp/{id:[0-9]+}", Use(API_SMTP_Id, mid.RequireAPIKey)) 60 api.HandleFunc("/util/send_test_email", Use(API_Send_Test_Email, mid.RequireAPIKey)) 61 api.HandleFunc("/import/group", API_Import_Group) 62 api.HandleFunc("/import/email", API_Import_Email) 63 api.HandleFunc("/import/site", API_Import_Site) 64 65 // Setup static file serving 66 router.PathPrefix("/").Handler(http.FileServer(http.Dir("./static/"))) 67 68 // Setup CSRF Protection 69 csrfHandler := csrf.Protect([]byte(auth.GenerateSecureKey()), 70 csrf.FieldName("csrf_token"), 71 csrf.Secure(config.Conf.AdminConf.UseTLS)) 72 csrfRouter := csrfHandler(router) 73 return Use(csrfRouter.ServeHTTP, mid.CSRFExceptions, mid.GetContext) 74 } 75 76 // Use allows us to stack middleware to process the request 77 // Example taken from https://github.com/gorilla/mux/pull/36#issuecomment-25849172 78 func Use(handler http.HandlerFunc, mid ...func(http.Handler) http.HandlerFunc) http.HandlerFunc { 79 for _, m := range mid { 80 handler = m(handler) 81 } 82 return handler 83 } 84 85 // Register creates a new user 86 func Register(w http.ResponseWriter, r *http.Request) { 87 // If it is a post request, attempt to register the account 88 // Now that we are all registered, we can log the user in 89 params := struct { 90 Title string 91 Flashes []interface{} 92 User models.User 93 Token string 94 }{Title: "Register", Token: csrf.Token(r)} 95 session := ctx.Get(r, "session").(*sessions.Session) 96 switch { 97 case r.Method == "GET": 98 params.Flashes = session.Flashes() 99 session.Save(r, w) 100 templates := template.New("template") 101 _, err := templates.ParseFiles("templates/register.html", "templates/flashes.html") 102 if err != nil { 103 Logger.Println(err) 104 } 105 template.Must(templates, err).ExecuteTemplate(w, "base", params) 106 case r.Method == "POST": 107 //Attempt to register 108 succ, err := auth.Register(r) 109 //If we've registered, redirect to the login page 110 if succ { 111 session.AddFlash(models.Flash{ 112 Type: "success", 113 Message: "Registration successful!.", 114 }) 115 session.Save(r, w) 116 http.Redirect(w, r, "/login", 302) 117 return 118 } 119 // Check the error 120 m := err.Error() 121 Logger.Println(err) 122 session.AddFlash(models.Flash{ 123 Type: "danger", 124 Message: m, 125 }) 126 session.Save(r, w) 127 http.Redirect(w, r, "/register", 302) 128 return 129 } 130 } 131 132 // Base handles the default path and template execution 133 func Base(w http.ResponseWriter, r *http.Request) { 134 params := struct { 135 User models.User 136 Title string 137 Flashes []interface{} 138 Token string 139 }{Title: "Dashboard", User: ctx.Get(r, "user").(models.User), Token: csrf.Token(r)} 140 getTemplate(w, "dashboard").ExecuteTemplate(w, "base", params) 141 } 142 143 // Campaigns handles the default path and template execution 144 func Campaigns(w http.ResponseWriter, r *http.Request) { 145 // Example of using session - will be removed. 146 params := struct { 147 User models.User 148 Title string 149 Flashes []interface{} 150 Token string 151 }{Title: "Campaigns", User: ctx.Get(r, "user").(models.User), Token: csrf.Token(r)} 152 getTemplate(w, "campaigns").ExecuteTemplate(w, "base", params) 153 } 154 155 // CampaignID handles the default path and template execution 156 func CampaignID(w http.ResponseWriter, r *http.Request) { 157 // Example of using session - will be removed. 158 params := struct { 159 User models.User 160 Title string 161 Flashes []interface{} 162 Token string 163 }{Title: "Campaign Results", User: ctx.Get(r, "user").(models.User), Token: csrf.Token(r)} 164 getTemplate(w, "campaign_results").ExecuteTemplate(w, "base", params) 165 } 166 167 // Templates handles the default path and template execution 168 func Templates(w http.ResponseWriter, r *http.Request) { 169 // Example of using session - will be removed. 170 params := struct { 171 User models.User 172 Title string 173 Flashes []interface{} 174 Token string 175 }{Title: "Email Templates", User: ctx.Get(r, "user").(models.User), Token: csrf.Token(r)} 176 getTemplate(w, "templates").ExecuteTemplate(w, "base", params) 177 } 178 179 // Users handles the default path and template execution 180 func Users(w http.ResponseWriter, r *http.Request) { 181 // Example of using session - will be removed. 182 params := struct { 183 User models.User 184 Title string 185 Flashes []interface{} 186 Token string 187 }{Title: "Users & Groups", User: ctx.Get(r, "user").(models.User), Token: csrf.Token(r)} 188 getTemplate(w, "users").ExecuteTemplate(w, "base", params) 189 } 190 191 // LandingPages handles the default path and template execution 192 func LandingPages(w http.ResponseWriter, r *http.Request) { 193 // Example of using session - will be removed. 194 params := struct { 195 User models.User 196 Title string 197 Flashes []interface{} 198 Token string 199 }{Title: "Landing Pages", User: ctx.Get(r, "user").(models.User), Token: csrf.Token(r)} 200 getTemplate(w, "landing_pages").ExecuteTemplate(w, "base", params) 201 } 202 203 // SendingProfiles handles the default path and template execution 204 func SendingProfiles(w http.ResponseWriter, r *http.Request) { 205 // Example of using session - will be removed. 206 params := struct { 207 User models.User 208 Title string 209 Flashes []interface{} 210 Token string 211 }{Title: "Sending Profiles", User: ctx.Get(r, "user").(models.User), Token: csrf.Token(r)} 212 getTemplate(w, "sending_profiles").ExecuteTemplate(w, "base", params) 213 } 214 215 // Settings handles the changing of settings 216 func Settings(w http.ResponseWriter, r *http.Request) { 217 switch { 218 case r.Method == "GET": 219 params := struct { 220 User models.User 221 Title string 222 Flashes []interface{} 223 Token string 224 Version string 225 }{Title: "Settings", Version: config.Version, User: ctx.Get(r, "user").(models.User), Token: csrf.Token(r)} 226 getTemplate(w, "settings").ExecuteTemplate(w, "base", params) 227 case r.Method == "POST": 228 err := auth.ChangePassword(r) 229 msg := models.Response{Success: true, Message: "Settings Updated Successfully"} 230 if err == auth.ErrInvalidPassword { 231 msg.Message = "Invalid Password" 232 msg.Success = false 233 JSONResponse(w, msg, http.StatusBadRequest) 234 return 235 } 236 if err != nil { 237 msg.Message = err.Error() 238 msg.Success = false 239 JSONResponse(w, msg, http.StatusBadRequest) 240 return 241 } 242 JSONResponse(w, msg, http.StatusOK) 243 } 244 } 245 246 // Login handles the authentication flow for a user. If credentials are valid, 247 // a session is created 248 func Login(w http.ResponseWriter, r *http.Request) { 249 params := struct { 250 User models.User 251 Title string 252 Flashes []interface{} 253 Token string 254 }{Title: "Login", Token: csrf.Token(r)} 255 session := ctx.Get(r, "session").(*sessions.Session) 256 switch { 257 case r.Method == "GET": 258 params.Flashes = session.Flashes() 259 session.Save(r, w) 260 templates := template.New("template") 261 _, err := templates.ParseFiles("templates/login.html", "templates/flashes.html") 262 if err != nil { 263 Logger.Println(err) 264 } 265 template.Must(templates, err).ExecuteTemplate(w, "base", params) 266 case r.Method == "POST": 267 //Attempt to login 268 succ, u, err := auth.Login(r) 269 if err != nil { 270 Logger.Println(err) 271 } 272 //If we've logged in, save the session and redirect to the dashboard 273 if succ { 274 session.Values["id"] = u.Id 275 session.Save(r, w) 276 http.Redirect(w, r, "/", 302) 277 } else { 278 Flash(w, r, "danger", "Invalid Username/Password") 279 http.Redirect(w, r, "/login", 302) 280 } 281 } 282 } 283 284 // Logout destroys the current user session 285 func Logout(w http.ResponseWriter, r *http.Request) { 286 // If it is a post request, attempt to register the account 287 // Now that we are all registered, we can log the user in 288 session := ctx.Get(r, "session").(*sessions.Session) 289 delete(session.Values, "id") 290 Flash(w, r, "success", "You have successfully logged out") 291 http.Redirect(w, r, "/login", 302) 292 } 293 294 // Preview allows for the viewing of page html in a separate browser window 295 func Preview(w http.ResponseWriter, r *http.Request) { 296 if r.Method != "POST" { 297 http.Error(w, "Method not allowed", http.StatusBadRequest) 298 return 299 } 300 fmt.Fprintf(w, "%s", r.FormValue("html")) 301 } 302 303 // Clone takes a URL as a POST parameter and returns the site HTML 304 func Clone(w http.ResponseWriter, r *http.Request) { 305 vars := mux.Vars(r) 306 if r.Method != "POST" { 307 http.Error(w, "Method not allowed", http.StatusBadRequest) 308 return 309 } 310 if url, ok := vars["url"]; ok { 311 Logger.Println(url) 312 } 313 http.Error(w, "No URL given.", http.StatusBadRequest) 314 } 315 316 func getTemplate(w http.ResponseWriter, tmpl string) *template.Template { 317 templates := template.New("template") 318 _, err := templates.ParseFiles("templates/base.html", "templates/"+tmpl+".html", "templates/flashes.html") 319 if err != nil { 320 Logger.Println(err) 321 } 322 return template.Must(templates, err) 323 } 324 325 // Flash handles the rendering flash messages 326 func Flash(w http.ResponseWriter, r *http.Request, t string, m string) { 327 session := ctx.Get(r, "session").(*sessions.Session) 328 session.AddFlash(models.Flash{ 329 Type: t, 330 Message: m, 331 }) 332 session.Save(r, w) 333 }