diff options
Diffstat (limited to 'service')
| -rw-r--r-- | service/service.go | 16 | ||||
| -rw-r--r-- | service/transport.go | 25 | 
2 files changed, 35 insertions, 6 deletions
| diff --git a/service/service.go b/service/service.go index 2f87fa3..c925b83 100644 --- a/service/service.go +++ b/service/service.go @@ -1,6 +1,8 @@  package service  import ( +	"crypto/sha256" +	"encoding/base64"  	"errors"  	"fmt"  	"mime/multipart" @@ -1014,8 +1016,18 @@ func (s *service) SaveSettings(c *client, settings *model.Settings) (err error)  	default:  		return errInvalidArgument  	} -	if len(settings.CSS) > 1<<20 { -		return errInvalidArgument +	if len(settings.CSS) > 0 { +		if len(settings.CSS) > 1<<20 { +			return errInvalidArgument +		} +		// For some reason, browsers convert CRLF to LF before calculating +		// the hash of the inline resources. +		settings.CSS = strings.ReplaceAll(settings.CSS, "\x0d\x0a", "\x0a") + +		h := sha256.Sum256([]byte(settings.CSS)) +		settings.CSSHash = base64.StdEncoding.EncodeToString(h[:]) +	} else { +		settings.CSSHash = ""  	}  	c.s.Settings = *settings  	return c.setSession(c.s) diff --git a/service/transport.go b/service/transport.go index 1182d6c..d032cce 100644 --- a/service/transport.go +++ b/service/transport.go @@ -26,6 +26,16 @@ const (  	CSRF  ) +const csp = "default-src 'none';" + +	" img-src *;" + +	" media-src *;" + +	" font-src *;" + +	" child-src *;" + +	" connect-src 'self';" + +	" form-action 'self';" + +	" script-src 'self';" + +	" style-src 'self'" +  func NewHandler(s *service, verbose bool, staticDir string) http.Handler {  	r := mux.NewRouter() @@ -58,14 +68,14 @@ func NewHandler(s *service, verbose bool, staticDir string) http.Handler {  				}(time.Now())  			} -			var ct string +			h := c.w.Header()  			switch rt {  			case HTML: -				ct = "text/html; charset=utf-8" +				h.Set("Content-Type", "text/html; charset=utf-8") +				h.Set("Content-Security-Policy", csp)  			case JSON: -				ct = "application/json" +				h.Set("Content-Type", "application/json")  			} -			c.w.Header().Add("Content-Type", ct)  			err = c.authenticate(at, s.instance)  			if err != nil { @@ -73,6 +83,13 @@ func NewHandler(s *service, verbose bool, staticDir string) http.Handler {  				return  			} +			// Override the CSP header to allow custom CSS +			if rt == HTML && len(c.s.Settings.CSS) > 0 && +				len(c.s.Settings.CSSHash) > 0 { +				v := fmt.Sprintf("%s 'sha256-%s'", csp, c.s.Settings.CSSHash) +				h.Set("Content-Security-Policy", v) +			} +  			err = f(c)  			if err != nil {  				writeError(c, err, rt, req.Method == http.MethodGet) | 
