diff --git a/handler/middlewares.go b/handler/middlewares.go new file mode 100644 index 0000000..231cbf5 --- /dev/null +++ b/handler/middlewares.go @@ -0,0 +1,19 @@ +package handler + +import ( + "github.com/labstack/echo/v4" + "net/http" +) + +// ContentTypeJson checks that the requests have the Content-Type header set to "application/json". +// This helps against CSRF attacks. +func ContentTypeJson(next echo.HandlerFunc) echo.HandlerFunc { + return func(c echo.Context) error { + contentType := c.Request().Header.Get("Content-Type") + if contentType != "application/json" { + return c.JSON(http.StatusBadRequest, jsonHTTPResponse{false, "Only JSON allowed"}) + } + + return next(c) + } +} diff --git a/main.go b/main.go index 7f99741..65e0edf 100644 --- a/main.go +++ b/main.go @@ -96,7 +96,7 @@ func init() { fmt.Println("Email from name\t:", util.EmailFromName) //fmt.Println("Session secret\t:", util.SessionSecret) fmt.Println("Custom wg.conf\t:", util.WgConfTemplate) - fmt.Println("Base path\t:", util.BasePath + "/") + fmt.Println("Base path\t:", util.BasePath+"/") } func main() { @@ -124,8 +124,8 @@ func main() { app.GET(util.BasePath, handler.WireGuardClients(db), handler.ValidSession) if !util.DisableLogin { - app.GET(util.BasePath + "/login", handler.LoginPage()) - app.POST(util.BasePath + "/login", handler.Login(db)) + app.GET(util.BasePath+"/login", handler.LoginPage()) + app.POST(util.BasePath+"/login", handler.Login(db)) } var sendmail emailer.Emailer @@ -135,32 +135,32 @@ func main() { sendmail = emailer.NewSmtpMail(util.SmtpHostname, util.SmtpPort, util.SmtpUsername, util.SmtpPassword, util.SmtpNoTLSCheck, util.SmtpAuthType, util.EmailFromName, util.EmailFrom) } - app.GET(util.BasePath + "/_health", handler.Health()) - app.GET(util.BasePath + "/logout", handler.Logout(), handler.ValidSession) - app.POST(util.BasePath + "/new-client", handler.NewClient(db), handler.ValidSession) - app.POST(util.BasePath + "/update-client", handler.UpdateClient(db), handler.ValidSession) - app.POST(util.BasePath + "/email-client", handler.EmailClient(db, sendmail, defaultEmailSubject, defaultEmailContent), handler.ValidSession) - app.POST(util.BasePath + "/client/set-status", handler.SetClientStatus(db), handler.ValidSession) - app.POST(util.BasePath + "/remove-client", handler.RemoveClient(db), handler.ValidSession) - app.GET(util.BasePath + "/download", handler.DownloadClient(db), handler.ValidSession) - app.GET(util.BasePath + "/wg-server", handler.WireGuardServer(db), handler.ValidSession) - app.POST(util.BasePath + "/wg-server/interfaces", handler.WireGuardServerInterfaces(db), handler.ValidSession) - app.POST(util.BasePath + "/wg-server/keypair", handler.WireGuardServerKeyPair(db), handler.ValidSession) - app.GET(util.BasePath + "/global-settings", handler.GlobalSettings(db), handler.ValidSession) - app.POST(util.BasePath + "/global-settings", handler.GlobalSettingSubmit(db), handler.ValidSession) - app.GET(util.BasePath + "/status", handler.Status(db), handler.ValidSession) - app.GET(util.BasePath + "/api/clients", handler.GetClients(db), handler.ValidSession) - app.GET(util.BasePath + "/api/client/:id", handler.GetClient(db), handler.ValidSession) - app.GET(util.BasePath + "/api/machine-ips", handler.MachineIPAddresses(), handler.ValidSession) - app.GET(util.BasePath + "/api/suggest-client-ips", handler.SuggestIPAllocation(db), handler.ValidSession) - app.GET(util.BasePath + "/api/apply-wg-config", handler.ApplyServerConfig(db, tmplBox), handler.ValidSession) - app.GET(util.BasePath + "/wake_on_lan_hosts", handler.GetWakeOnLanHosts(db), handler.ValidSession) - app.POST(util.BasePath + "/wake_on_lan_host", handler.SaveWakeOnLanHost(db), handler.ValidSession) - app.DELETE(util.BasePath + "/wake_on_lan_host/:mac_address", handler.DeleteWakeOnHost(db), handler.ValidSession) - app.PUT(util.BasePath + "/wake_on_lan_host/:mac_address", handler.WakeOnHost(db), handler.ValidSession) + app.GET(util.BasePath+"/_health", handler.Health()) + app.GET(util.BasePath+"/logout", handler.Logout(), handler.ValidSession) + app.POST(util.BasePath+"/new-client", handler.NewClient(db), handler.ValidSession, handler.ContentTypeJson) + app.POST(util.BasePath+"/update-client", handler.UpdateClient(db), handler.ValidSession, handler.ContentTypeJson) + app.POST(util.BasePath+"/email-client", handler.EmailClient(db, sendmail, defaultEmailSubject, defaultEmailContent), handler.ValidSession, handler.ContentTypeJson) + app.POST(util.BasePath+"/client/set-status", handler.SetClientStatus(db), handler.ValidSession, handler.ContentTypeJson) + app.POST(util.BasePath+"/remove-client", handler.RemoveClient(db), handler.ValidSession, handler.ContentTypeJson) + app.GET(util.BasePath+"/download", handler.DownloadClient(db), handler.ValidSession) + app.GET(util.BasePath+"/wg-server", handler.WireGuardServer(db), handler.ValidSession) + app.POST(util.BasePath+"/wg-server/interfaces", handler.WireGuardServerInterfaces(db), handler.ValidSession, handler.ContentTypeJson) + app.POST(util.BasePath+"/wg-server/keypair", handler.WireGuardServerKeyPair(db), handler.ValidSession, handler.ContentTypeJson) + app.GET(util.BasePath+"/global-settings", handler.GlobalSettings(db), handler.ValidSession) + app.POST(util.BasePath+"/global-settings", handler.GlobalSettingSubmit(db), handler.ValidSession, handler.ContentTypeJson) + app.GET(util.BasePath+"/status", handler.Status(db), handler.ValidSession) + app.GET(util.BasePath+"/api/clients", handler.GetClients(db), handler.ValidSession) + app.GET(util.BasePath+"/api/client/:id", handler.GetClient(db), handler.ValidSession) + app.GET(util.BasePath+"/api/machine-ips", handler.MachineIPAddresses(), handler.ValidSession) + app.GET(util.BasePath+"/api/suggest-client-ips", handler.SuggestIPAllocation(db), handler.ValidSession) + app.POST(util.BasePath+"/api/apply-wg-config", handler.ApplyServerConfig(db, tmplBox), handler.ValidSession, handler.ContentTypeJson) + app.GET(util.BasePath+"/wake_on_lan_hosts", handler.GetWakeOnLanHosts(db), handler.ValidSession) + app.POST(util.BasePath+"/wake_on_lan_host", handler.SaveWakeOnLanHost(db), handler.ValidSession, handler.ContentTypeJson) + app.DELETE(util.BasePath+"/wake_on_lan_host/:mac_address", handler.DeleteWakeOnHost(db), handler.ValidSession, handler.ContentTypeJson) + app.PUT(util.BasePath+"/wake_on_lan_host/:mac_address", handler.WakeOnHost(db), handler.ValidSession, handler.ContentTypeJson) // servers other static files - app.GET(util.BasePath + "/static/*", echo.WrapHandler(http.StripPrefix(util.BasePath + "/static/", assetHandler))) + app.GET(util.BasePath+"/static/*", echo.WrapHandler(http.StripPrefix(util.BasePath+"/static/", assetHandler))) app.Logger.Fatal(app.Start(util.BindAddress)) } diff --git a/router/router.go b/router/router.go index 3369f6b..45ee836 100644 --- a/router/router.go +++ b/router/router.go @@ -103,11 +103,6 @@ func New(tmplBox *rice.Box, extraData map[string]string, secret []byte) *echo.Ec e.Logger.SetLevel(log.DEBUG) e.Pre(middleware.RemoveTrailingSlash()) e.Use(middleware.Logger()) - e.Use(middleware.CORSWithConfig(middleware.CORSConfig{ - AllowOrigins: []string{"*"}, - AllowHeaders: []string{echo.HeaderOrigin, echo.HeaderContentType, echo.HeaderAccept, echo.HeaderAuthorization}, - AllowMethods: []string{echo.GET, echo.HEAD, echo.PUT, echo.PATCH, echo.POST, echo.DELETE}, - })) e.HideBanner = true e.Validator = NewValidator() e.Renderer = &TemplateRegistry{ diff --git a/templates/base.html b/templates/base.html index 0a70cf2..cf31d4d 100644 --- a/templates/base.html +++ b/templates/base.html @@ -494,7 +494,7 @@ $("#apply_config_confirm").click(function () { $.ajax({ cache: false, - method: 'GET', + method: 'POST', url: '{{.basePath}}/api/apply-wg-config', dataType: 'json', contentType: "application/json",