From daa6e35bf20090cddeda5044d1f6a1d4c6b75d34 Mon Sep 17 00:00:00 2001 From: mpl Date: Tue, 11 Jun 2013 17:16:21 +0200 Subject: [PATCH] wizard: added xsrf protection Change-Id: I1d80faecd43953c22162a85eec92590cdfcef4ed --- pkg/server/wizard.go | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/pkg/server/wizard.go b/pkg/server/wizard.go index 24cf3babc..a50f6bbe1 100644 --- a/pkg/server/wizard.go +++ b/pkg/server/wizard.go @@ -17,6 +17,7 @@ limitations under the License. package server import ( + "crypto/rand" "encoding/json" "fmt" "html/template" @@ -32,6 +33,8 @@ import ( "camlistore.org/pkg/httputil" "camlistore.org/pkg/jsonconfig" "camlistore.org/pkg/osutil" + + "camlistore.org/third_party/code.google.com/p/xsrftoken" ) var ignoredFields = map[string]bool{ @@ -123,6 +126,12 @@ func flattenPublish(config jsonconfig.Obj) error { return nil } +var serverKey = func() string { + var b [20]byte + rand.Read(b[:]) + return string(b[:]) +}() + func sendWizard(rw http.ResponseWriter, req *http.Request, hasChanged bool) { config, err := jsonconfig.ReadFile(osutil.UserServerConfigPath()) if err != nil { @@ -144,13 +153,17 @@ func sendWizard(rw http.ResponseWriter, req *http.Request, hasChanged bool) { } return true }, + "genXSRF": func() string { + return xsrftoken.Generate(serverKey, "user", "wizardSave") + }, } body := ` -
+ {{range $k,$v := .}}{{if showField $k}}{{end}}{{end}}
{{printf "%v" $k}}
+ (Will restart server.)
` if hasChanged { @@ -184,13 +197,17 @@ func rewriteConfig(config *jsonconfig.Obj, configfile string) error { return err } -// TODO(mpl): use XRRF func handleSetupChange(rw http.ResponseWriter, req *http.Request) { hilevelConf, err := jsonconfig.ReadFile(osutil.UserServerConfigPath()) if err != nil { httputil.ServeError(rw, req, err) return } + if !xsrftoken.Valid(req.FormValue("token"), serverKey, "user", "wizardSave") { + http.Error(rw, "Form expired. Press back and reload form.", http.StatusBadRequest) + log.Printf("invalid xsrf token=%q", req.FormValue("token")) + return + } hasChanged := false var el interface{} @@ -230,9 +247,14 @@ func handleSetupChange(rw http.ResponseWriter, req *http.Request) { httputil.ServeError(rw, req, err) return } + err = osutil.RestartProcess() + if err != nil { + log.Fatal("Failed to restart: " + err.Error()) + http.Error(rw, "Failed to restart process", 500) + return + } } sendWizard(rw, req, hasChanged) - return } func (sh *SetupHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request) { @@ -251,11 +273,8 @@ func (sh *SetupHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request) { } if len(req.Form) > 0 { handleSetupChange(rw, req) - err = osutil.RestartProcess() - if err != nil { - log.Fatal("Failed to restart: " + err.Error()) - } } + return } sendWizard(rw, req, false)