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