func (h *DeployHandler) serveSetup(w http.ResponseWriter, r *http.Request) { if r.FormValue("mode") != "setupproject" { h.serveError(w, r, errors.New("bad form")) return } ck, err := r.Cookie("user") if err != nil { h.serveFormError(w, errors.New("Cookie expired, or CSRF attempt. Please reload and retry.")) h.logger.Printf("Cookie expired, or CSRF attempt on form.") return } instConf, err := h.confFromForm(r) if err != nil { h.serveFormError(w, err) return } br, err := h.storeInstanceConf(instConf) if err != nil { h.serveError(w, r, fmt.Errorf("could not store instance configuration: %v", err)) return } xsrfToken := xsrftoken.Generate(h.xsrfKey, ck.Value, br.String()) state := fmt.Sprintf("%s:%x", br.String(), xsrfToken) redirectURL := h.oAuthConfig().AuthCodeURL(state) http.Redirect(w, r, redirectURL, http.StatusFound) return }
func sendWizard(rw http.ResponseWriter, req *http.Request, hasChanged bool) { config, err := jsonconfig.ReadFile(osutil.UserServerConfigPath()) if err != nil { httputil.ServeError(rw, req, err) return } err = flattenPublish(config) if err != nil { httputil.ServeError(rw, req, err) return } funcMap := template.FuncMap{ "printWizard": printWizard, "showField": func(inputName string) bool { if _, ok := ignoredFields[inputName]; ok { return false } return true }, "genXSRF": func() string { return xsrftoken.Generate(serverKey, "user", "wizardSave") }, } body := ` <form id="WizardForm" method="POST" enctype="multipart/form-data"> <table> {{range $k,$v := .}}{{if showField $k}}<tr><td>{{printf "%v" $k}}</td><td><input type="text" size="30" name ="{{printf "%v" $k}}" value="{{printWizard $v}}" ></td></tr>{{end}}{{end}} </table> <input type="hidden" name="token" value="{{genXSRF}}"> <input type="submit" form="WizardForm" value="Save"> (Will restart server.)</form>` if hasChanged { body += `<p> Configuration succesfully rewritten </p>` } tmpl, err := template.New("wizard").Funcs(funcMap).Parse(topWizard + body + bottomWizard) if err != nil { httputil.ServeError(rw, req, err) return } err = tmpl.Execute(rw, config) if err != nil { httputil.ServeError(rw, req, err) return } }
func xsrfMiddleware(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) { session, _ := store.Get(r, cfg.SessionName) //TODO aabb234 is not a good value for the function Generate session.Values["xsrf"] = xsrftoken.Generate("aabb234", "1", "login") next(rw, r) }
// Generate maps CSRF to each request. If this request is a Get request, it will generate a new token. // Additionally, depending on options set, generated tokens will be sent via Header and/or Cookie. func Generate(opts *Options) martini.Handler { return func(s sessions.Session, c martini.Context, r *http.Request, w http.ResponseWriter) { if opts.Header == "" { opts.Header = "X-CSRFToken" } if opts.Form == "" { opts.Form = "_csrf" } if opts.Cookie == "" { opts.Cookie = "_csrf" } if opts.ErrorFunc == nil { opts.ErrorFunc = func(w http.ResponseWriter) { http.Error(w, "Invalid csrf token.", http.StatusBadRequest) } } x := &csrf{ Secret: opts.Secret, Header: opts.Header, Form: opts.Form, Cookie: opts.Cookie, ErrorFunc: opts.ErrorFunc, } c.MapTo(x, (*CSRF)(nil)) uid := s.Get(opts.SessionKey) if uid == nil { return } switch uid.(type) { case string: x.ID = uid.(string) case int64: x.ID = strconv.FormatInt(uid.(int64), 10) default: return } if r.Method != "GET" || r.Header.Get("Origin") != "" { return } // If cookie present, map existing token, else generate a new one. if ex, err := r.Cookie(opts.Cookie); err == nil && ex.Value != "" { x.Token = ex.Value } else { x.Token = xsrftoken.Generate(x.Secret, x.ID, "POST") if opts.SetCookie { expire := time.Now().AddDate(0, 0, 1) // Verify the domain is valid. If it is not, set as empty. domain := strings.Split(r.Host, ":")[0] if ok, err := regexp.Match(domainReg, []byte(domain)); !ok || err != nil { domain = "" } cookie := &http.Cookie{ Name: opts.Cookie, Value: x.Token, Path: "/", Domain: domain, Expires: expire, RawExpires: expire.Format(time.UnixDate), MaxAge: 0, Secure: opts.Secure, HttpOnly: false, Raw: fmt.Sprintf("%s=%s", opts.Cookie, x.Token), Unparsed: []string{fmt.Sprintf("token=%s", x.Token)}, } http.SetCookie(w, cookie) } } if opts.SetHeader { w.Header().Add(opts.Header, x.Token) } } }
func (sh *SyncHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request) { if req.Method == "POST" { if req.FormValue("mode") == "validate" { token := req.FormValue("token") if xsrftoken.Valid(token, auth.Token(), "user", "runFullValidate") { sh.startFullValidation() http.Redirect(rw, req, "./", http.StatusFound) return } } http.Error(rw, "Bad POST request", http.StatusBadRequest) return } // TODO: remove this lock and instead just call currentStatus, // and transition to using that here. sh.mu.Lock() defer sh.mu.Unlock() f := func(p string, a ...interface{}) { fmt.Fprintf(rw, p, a...) } now := time.Now() f("<h1>Sync Status (for %s to %s)</h1>", sh.fromName, sh.toName) f("<p><b>Current status: </b>%s</p>", html.EscapeString(sh.status)) if sh.idle { return } f("<h2>Stats:</h2><ul>") f("<li>Source: %s</li>", html.EscapeString(storageDesc(sh.from))) f("<li>Target: %s</li>", html.EscapeString(storageDesc(sh.to))) f("<li>Blobs synced: %d</li>", sh.totalCopies) f("<li>Bytes synced: %d</li>", sh.totalCopyBytes) f("<li>Blobs yet to copy: %d</li>", len(sh.needCopy)) f("<li>Bytes yet to copy: %d</li>", sh.bytesRemain) if !sh.recentCopyTime.IsZero() { f("<li>Most recent copy: %s (%v ago)</li>", sh.recentCopyTime.Format(time.RFC3339), now.Sub(sh.recentCopyTime)) } clarification := "" if len(sh.needCopy) == 0 && sh.totalErrors > 0 { clarification = "(all since resolved)" } f("<li>Previous copy errors: %d %s</li>", sh.totalErrors, clarification) f("</ul>") f("<h2>Validation</h2>") if len(sh.vshards) == 0 { f("Validation disabled") token := xsrftoken.Generate(auth.Token(), "user", "runFullValidate") f("<form method='POST'><input type='hidden' name='mode' value='validate'><input type='hidden' name='token' value='%s'><input type='submit' value='Start validation'></form>", token) } else { f("<p>Background scan of source and destination to ensure that the destination has everything the source does, or is at least enqueued to sync.</p>") f("<ul>") f("<li>Shards complete: %d/%d (%.1f%%)</li>", sh.vshardDone, len(sh.vshards), 100*float64(sh.vshardDone)/float64(len(sh.vshards))) f("<li>Source blobs seen: %d</li>", sh.vsrcCount) f("<li>Source bytes seen: %d</li>", sh.vsrcBytes) f("<li>Dest blobs seen: %d</li>", sh.vdestCount) f("<li>Dest bytes seen: %d</li>", sh.vdestBytes) f("<li>Blobs found missing & enqueued: %d</li>", sh.vmissing) if len(sh.vshardErrs) > 0 { f("<li>Validation errors:<ul>\n") for _, e := range sh.vshardErrs { f(" <li>%s</li>\n", html.EscapeString(e)) } f("</li>\n") } f("</ul>") } if len(sh.copying) > 0 { f("<h2>Currently Copying</h2><ul>") copying := make([]blob.Ref, 0, len(sh.copying)) for br := range sh.copying { copying = append(copying, br) } sort.Sort(blob.ByRef(copying)) for _, br := range copying { f("<li>%s</li>\n", sh.copying[br]) } f("</ul>") } recentErrors := make([]blob.Ref, 0, len(sh.recentErrors)) for _, br := range sh.recentErrors { if _, ok := sh.needCopy[br]; ok { // Only show it in the web UI if it's still a problem. Blobs that // have since succeeded just confused people. recentErrors = append(recentErrors, br) } } if len(recentErrors) > 0 { f("<h2>Recent Errors</h2><p>Blobs that haven't successfully copied over yet, and their last errors:</p><ul>") for _, br := range recentErrors { fail := sh.lastFail[br] f("<li>%s: %s: %s</li>\n", br, fail.when.Format(time.RFC3339), html.EscapeString(fail.err.Error())) } f("</ul>") } }
func auth(c web.C, w http.ResponseWriter, r *http.Request) { session, err := store.Get(r, "p2drive") if err != nil { http.Error(w, err.Error(), 500) return } csrfResponse := r.URL.Query().Get("state") code := r.URL.Query().Get("code") error := r.URL.Query().Get("error") if error == "access_denied" { http.Redirect(w, r, "/projects/p2drive/intro", 302) } b, err := ioutil.ReadFile("client_secret.json") if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) } config, err := google.ConfigFromJSON(b, drive.DriveMetadataReadonlyScope, drive.DriveFileScope, plus.UserinfoProfileScope) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) } config.RedirectURL = redirectUrl if csrfResponse == "" || code == "" { csrfId, err := uuid.NewV4() if err != nil { http.Error(w, "couldn't generate uuid", http.StatusInternalServerError) } session.Values["id"] = csrfId.String() csrfToken := xsrftoken.Generate(secretKey, session.Values["id"].(string), "/projects/p2drive/auth") session.Values["csrf"] = csrfToken session.Save(r, w) authURL := config.AuthCodeURL(csrfToken, oauth2.AccessTypeOffline, oauth2.ApprovalForce) http.Redirect(w, r, authURL, 302) return } if session.Values["csrf"] != csrfResponse { http.Redirect(w, r, "/projects", 400) } if !xsrftoken.Valid(session.Values["csrf"].(string), secretKey, session.Values["id"].(string), "/projects/p2drive/auth") { http.Redirect(w, r, "/projects", 400) } tok, err := config.Exchange(oauth2.NoContext, code) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) } session.Values["access-token"] = tok session.Save(r, w) http.Redirect(w, r, "/projects/p2drive/input", 302) }
func csrf(r *http.Request) string { user := r.RemoteAddr action := r.Method + r.URL.Path return xsrftoken.Generate(siteSecret, user, action) }
func (u *User) GenerateNonce(actionID string) string { return xsrftoken.Generate(string(xsrfSalt), u.LoginName, actionID) }