Browse Source

secure HTTP headers

CSP, frame, XSS, etc.
boyska 6 years ago
parent
commit
0ec0a97855
1 changed files with 34 additions and 12 deletions
  1. 34 12
      http.go

+ 34 - 12
http.go

@@ -16,6 +16,7 @@ import (
 
 	rice "github.com/GeertJohan/go.rice"
 	"github.com/c2h5oh/datasize"
+	"github.com/unrolled/secure"
 )
 
 // MegaUploader acts as controller for all the application. Since this is inherently a web-focused
@@ -23,11 +24,21 @@ import (
 type MegaUploader struct {
 	Conf       Config
 	configLock *sync.RWMutex
+	secureMW   *secure.Secure
 }
 
 // NewMegaUploader create a new mega uploader
 func NewMegaUploader(c Config) MegaUploader {
-	return MegaUploader{Conf: c, configLock: new(sync.RWMutex)}
+	return MegaUploader{
+		Conf:       c,
+		configLock: new(sync.RWMutex),
+		secureMW: secure.New(secure.Options{
+			FrameDeny:             true,
+			ContentTypeNosniff:    true,
+			BrowserXssFilter:      true,
+			ContentSecurityPolicy: "default-src 'self'",
+		}),
+	}
 }
 
 func (mu *MegaUploader) ChangeConf(newconf Config) {
@@ -37,27 +48,37 @@ func (mu *MegaUploader) ChangeConf(newconf Config) {
 }
 
 // confAcquire is a middleware to read-lock configuration
-func (mu *MegaUploader) confAcquire(inner func(w http.ResponseWriter, r *http.Request)) func(w http.ResponseWriter, r *http.Request) {
-	return func(w http.ResponseWriter, r *http.Request) {
+func (mu *MegaUploader) confAcquire(inner http.Handler) http.Handler {
+	f := func(w http.ResponseWriter, r *http.Request) {
 		mu.configLock.RLock()
-		inner(w, r)
+		inner.ServeHTTP(w, r)
 		mu.configLock.RUnlock()
 	}
+
+	return http.HandlerFunc(f)
+}
+
+func (mu *MegaUploader) privateMiddleware(inner func(w http.ResponseWriter, r *http.Request)) func(w http.ResponseWriter, r *http.Request) {
+	return mu.secureMW.Handler(mu.confAcquire(requireUserMiddleware(inner))).ServeHTTP
+}
+func (mu *MegaUploader) publicMiddleware(inner func(w http.ResponseWriter, r *http.Request)) func(w http.ResponseWriter, r *http.Request) {
+	return mu.secureMW.Handler(requireUserMiddleware(inner)).ServeHTTP
 }
 
 // SetupRoutes adds API routes
 func (mu *MegaUploader) SetupRoutes() {
+
 	prefix := strings.TrimRight(mu.Conf.Global.RoutePrefix, "/")
 
-	http.HandleFunc(prefix+"/", mu.confAcquire(requireUserMiddleware(mu.home)))
-	http.HandleFunc(prefix+"/upload/", mu.confAcquire(requireUserMiddleware(mu.uploadUI)))
+	http.HandleFunc(prefix+"/", mu.privateMiddleware(mu.home))
+	http.HandleFunc(prefix+"/upload/", mu.privateMiddleware(mu.uploadUI))
 	static := rice.MustFindBox("res/static")
-	http.HandleFunc(prefix+"/static/", requireUserMiddleware(
+	http.HandleFunc(prefix+"/static/", mu.publicMiddleware(
 		http.StripPrefix(prefix+"/static/", http.FileServer(static.HTTPBox())).ServeHTTP,
 	))
-	http.HandleFunc(prefix+"/api/share", mu.confAcquire(requireUserMiddleware(mu.listShares)))
-	http.HandleFunc(prefix+"/api/share/", mu.confAcquire(requireUserMiddleware(mu.getShare)))
-	http.HandleFunc(prefix+"/api/upload/", mu.confAcquire(requireUserMiddleware(mu.upload)))
+	http.HandleFunc(prefix+"/api/share", mu.privateMiddleware(mu.listShares))
+	http.HandleFunc(prefix+"/api/share/", mu.privateMiddleware(mu.getShare))
+	http.HandleFunc(prefix+"/api/upload/", mu.privateMiddleware(mu.upload))
 }
 
 func getUser(r *http.Request) (string, error) {
@@ -68,8 +89,8 @@ func getUser(r *http.Request) (string, error) {
 	return user, nil
 }
 
-func requireUserMiddleware(inner func(w http.ResponseWriter, r *http.Request)) func(w http.ResponseWriter, r *http.Request) {
-	return func(w http.ResponseWriter, r *http.Request) {
+func requireUserMiddleware(inner func(w http.ResponseWriter, r *http.Request)) http.Handler {
+	f := func(w http.ResponseWriter, r *http.Request) {
 		_, err := getUser(r)
 		if err != nil {
 			http.Error(w, "Only logged-in users are authorized", http.StatusUnauthorized)
@@ -77,6 +98,7 @@ func requireUserMiddleware(inner func(w http.ResponseWriter, r *http.Request)) f
 		}
 		inner(w, r)
 	}
+	return http.HandlerFunc(f)
 }
 
 func (mu *MegaUploader) listShares(w http.ResponseWriter, r *http.Request) {