github.com/edermi/gophish_mods@v0.7.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(UnindexedFileSystem{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  }