コード例 #1
0
ファイル: csrf.go プロジェクト: rainycape/gondola
func (c *csrf) generate(ctx *app.Context) (*csrf, error) {
	salt1 := stringutil.Random(randomSaltLength)
	salt2 := stringutil.Random(randomSaltLength)
	esA, err := csrfEncryptSigner(ctx, csrfSalt)
	if err != nil {
		return nil, err
	}
	c.GondolaCSRFA, err = esA.EncryptSign([]byte(salt1 + ":" + salt2))
	if err != nil {
		return nil, err
	}
	value := stringutil.Random(randomValueLength)
	esB, err := csrfEncryptSigner(ctx, salt1)
	if err != nil {
		return nil, err
	}
	c.GondolaCSRFB, err = esB.EncryptSign([]byte(value))
	if err != nil {
		return nil, err
	}
	esC, err := csrfEncryptSigner(ctx, salt2)
	if err != nil {
		return nil, err
	}
	c.GondolaCSRFC, err = esC.EncryptSign([]byte(stringutil.Reverse(value)))
	if err != nil {
		return nil, err
	}
	return c, nil
}
コード例 #2
0
ファイル: compiler.go プロジェクト: rainycape/gondola
func (p *program) executeScratch(s *scratch) (*State, error) {
	name := stringutil.Random(16)
	p.code[name] = s.buf
	// We don't really need a buffer here, but let's
	// pass one just in case. If a bug were found when
	// executing a scratch, wasting a few bytes is better
	// than crashing
	var buf bytes.Buffer
	st := newState(p, &buf)
	err := st.execute(name, "", reflect.Value{})
	putState(st)
	delete(p.code, name)
	if err != nil {
		return nil, err
	}
	return st, nil
}
コード例 #3
0
ファイル: password.go プロジェクト: rainycape/gondola
// NewOptions returns a password hashed with the given hash
// and rounds. If the hash is not available or not valid,
// it will panic. If Hash or Rounds are not provided,
// DefaultHash and DefaultRounds, respectivelly, are used.
func NewOptions(plain string, opts *Options) Password {
	if len(plain) > MaxPasswordLength {
		return Password("")
	}
	hash := DefaultHash
	rounds := DefaultRounds
	if opts != nil {
		if opts.Hash != Hash(0) {
			hash = opts.Hash
		}
		if opts.Rounds > 0 {
			rounds = opts.Rounds
		}
	}
	// Use the same number of bits for the salt and the hash, since
	// it provides the maximum possible security.
	salt := stringutil.Random(hash.Size())
	return Password(fmt.Sprintf("%s:%d:%s:%s", hash.Name(), rounds, salt, hash.Hash(salt, plain, rounds)))
}
コード例 #4
0
ファイル: tester_test.go プロジェクト: rainycape/gondola
func init() {
	testApp = app.New()
	testApp.Config().Secret = stringutil.Random(32)
	testApp.Handle("^/hello$", func(ctx *app.Context) {
		ctx.Header().Add("X-Hello", "World")
		ctx.Header().Add("X-Number", "42")
		ctx.WriteString("hello world")
	})
	testApp.Handle("^/empty$", func(ctx *app.Context) {})
	testApp.Handle("^/echo$", func(ctx *app.Context) {
		if ctx.R.Method == "POST" {
			data, err := ioutil.ReadAll(ctx.R.Body)
			if err != nil {
				panic(err)
			}
			ctx.Write(data)
		}
	})
	testApp.Handle("^/echo-form$", func(ctx *app.Context) {
		if err := ctx.R.ParseForm(); err != nil {
			panic(err)
		}
		var values url.Values
		if ctx.R.Method == "POST" || ctx.R.Method == "PUT" {
			values = ctx.R.PostForm
		} else {
			values = ctx.R.Form
		}
		keys := generic.Keys(values).([]string)
		sort.Strings(keys)
		for _, k := range keys {
			fmt.Fprintf(ctx, "%s=%s\n", k, values.Get(k))
		}
	})
	testApp.Handle("^/invalid-write-header$", func(ctx *app.Context) {
		ctx.WriteHeader(0)
	})
	testApp.Handle("^/multiple-write-header$", func(ctx *app.Context) {
		ctx.WriteHeader(200)
		ctx.WriteHeader(300)
	})
}
コード例 #5
0
ファイル: backend.go プロジェクト: rainycape/gondola
func (b *Backend) AddFields(db *sql.DB, m driver.Model, prevTable *sql.Table, newTable *sql.Table, fields []*sql.Field) error {
	rewrite := false
	for _, v := range fields {
		if !b.canAddField(v) {
			rewrite = true
			break
		}
	}
	if rewrite {
		name := db.QuoteIdentifier(m.Table())
		tmpName := fmt.Sprintf("%s_%s", m.Table(), stringutil.Random(8))
		quotedTmpName := db.QuoteIdentifier(tmpName)
		createSql, err := newTable.SQL(db, b, m, tmpName)
		if err != nil {
			return err
		}
		if _, err := db.Exec(createSql); err != nil {
			return err
		}
		fieldNames := generic.Map(prevTable.Fields, func(f *sql.Field) string { return f.Name }).([]string)
		// The previous table might have fields that we're not part
		// of the new table.
		fieldSet := make(map[string]bool)
		for _, v := range newTable.Fields {
			fieldSet[v.Name] = true
		}
		fieldNames = generic.Filter(fieldNames, func(n string) bool { return fieldSet[n] }).([]string)
		sqlFields := strings.Join(generic.Map(fieldNames, db.QuoteIdentifier).([]string), ", ")
		copySql := fmt.Sprintf("INSERT INTO %s (%s) SELECT %s FROM %s", quotedTmpName, sqlFields, sqlFields, name)
		if _, err := db.Exec(copySql); err != nil {
			return err
		}
		if _, err := db.Exec(fmt.Sprintf("DROP TABLE %s", name)); err != nil {
			return err
		}
		if _, err := db.Exec(fmt.Sprintf("ALTER TABLE %s RENAME TO %s", quotedTmpName, name)); err != nil {
			return err
		}
		return nil
	}
	return b.SqlBackend.AddFields(db, m, prevTable, newTable, fields)
}
コード例 #6
0
ファイル: handler.go プロジェクト: rainycape/gondola
// Handler returns an app.Handler from the given OAuth2TokenHandler, client and scopes.
func Handler(handler OAuth2TokenHandler, client *Client, scopes []string) app.Handler {
	return func(ctx *app.Context) {
		code := ctx.FormValue(Code)
		if code == "" {
			// First request, redirect to authorization
			state := stringutil.Random(32)
			redir := ctx.URL().String()
			auth := client.Clone(ctx).Authorization(redir, scopes, state)
			// Save parameters
			cookies := ctx.Cookies()
			cookies.Set(cookieName(client, stateCookieName), state)
			cookies.Set(cookieName(client, redirCookieName), redir)
			ctx.Redirect(auth, false)
			return
		}
		// Got a code, exchange for the token
		state := ctx.FormValue("state")
		var savedState, redir string
		stateCookie := cookieName(client, stateCookieName)
		cookies := ctx.Cookies()
		cookies.Get(stateCookie, &savedState)
		cookies.Delete(stateCookie)
		redirCookie := cookieName(client, redirCookieName)
		cookies.Get(redirCookie, &redir)
		cookies.Delete(redirCookie)
		if state != savedState {
			ctx.Forbidden("invalid state")
			return
		}
		token, err := client.Clone(ctx).Exchange(redir, code)
		if err != nil {
			panic(err)
		}
		handler(ctx, client, token)
	}
}
コード例 #7
0
ファイル: mail_std.go プロジェクト: rainycape/gondola
func makeBoundary() string {
	return "Gondola-Boundary-" + stringutil.Random(32)
}
コード例 #8
0
ファイル: handlers.go プロジェクト: rainycape/gondola
func forgotHandler(ctx *app.Context) {
	d := data(ctx)
	if !d.allowDirectSignIn() {
		ctx.NotFound("")
		return
	}
	var user User
	var isEmail bool
	var sent bool
	var fields struct {
		Username         string `form:",singleline,label=Username or Email"`
		ValidateUsername func(*app.Context) error
	}
	fields.ValidateUsername = func(c *app.Context) error {
		username := Normalize(fields.Username)
		isEmail = strings.Contains(username, "@")
		var field string
		if isEmail {
			field = "User.NormalizedEmail"
		} else {
			field = "User.NormalizedUsername"
		}
		userVal, userIface := newEmptyUser(ctx)
		ok := c.Orm().MustOne(orm.Eq(field, username), userIface)
		if !ok {
			if isEmail {
				return i18n.Errorf("address %q does not belong to any registered user", username)
			}
			return i18n.Errorf("username %q does not belong to any registered user", username)
		}
		user = getUserValue(userVal, "User").(User)
		if user.Email == "" {
			return i18n.Errorf("username %q does not have any registered emails", username)
		}
		return nil
	}
	f := form.New(ctx, &fields)
	if f.Submitted() && f.IsValid() {
		se, err := ctx.App().EncryptSigner(Salt)
		if err != nil {
			panic(err)
		}
		values := make(url.Values)
		values.Add("u", strconv.FormatInt(user.Id(), 36))
		values.Add("t", strconv.FormatInt(time.Now().Unix(), 36))
		values.Add("n", stringutil.Random(64))
		payload := values.Encode()
		p, err := se.EncryptSign([]byte(payload))
		if err != nil {
			panic(err)
		}
		abs := ctx.URL()
		reset := fmt.Sprintf("%s://%s%s?p=%s", abs.Scheme, abs.Host, ctx.MustReverse(ResetHandlerName), p)
		data := map[string]interface{}{
			"URL": reset,
		}
		from := mail.DefaultFrom()
		if from == "" {
			from = fmt.Sprintf("no-reply@%s", abs.Host)
		}
		msg := &mail.Message{
			To:      user.Email,
			From:    from,
			Subject: fmt.Sprintf(ctx.T("Reset your %s password"), d.opts.SiteName),
		}
		ctx.MustSendMail("reset_password.txt", data, msg)
		sent = true
	}
	data := map[string]interface{}{
		"ForgotForm": f,
		"IsEmail":    isEmail,
		"Sent":       sent,
		"User":       user,
	}
	ctx.MustExecute(ForgotTemplateName, data)
}
コード例 #9
0
ファイル: profile.go プロジェクト: rainycape/gondola
func requestProfile(u string, method string, values url.Values, secret string) (*profileInfo, error) {
	var req *http.Request
	var err error
	if method == "POST" {
		if len(values) > 0 {
			req, err = http.NewRequest(method, u, strings.NewReader(values.Encode()))
			if req != nil {
				req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
			}
		} else {
			req, err = http.NewRequest(method, u, nil)
		}
	} else {
		reqURL := u
		if len(values) > 0 {
			reqURL += "?" + values.Encode()
		}
		req, err = http.NewRequest(method, reqURL, nil)
	}
	if err != nil {
		return nil, err
	}
	if secret != "" {
		ts := time.Now().Unix()
		nonce := stringutil.Random(32)
		signer := cryptoutil.Signer{Salt: []byte(profile.Salt), Key: []byte(secret)}
		signed, err := signer.Sign([]byte(fmt.Sprintf("%d:%s", ts, nonce)))
		if err != nil {
			return nil, err
		}
		req.Header.Add(profile.HeaderName, signed)
	} else {
		req.Header.Add(profile.HeaderName, "true")
	}
	dump, err := httputil.DumpRequestOut(req, true)
	if err != nil {
		return nil, err
	}
	log.Debugf("Request: \n%s", string(dump))
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	value := resp.Header.Get(profile.HeaderName)
	switch value {
	case "":
		return nil, fmt.Errorf("no profiling info on %s - is profiling enabled?", u)
	case "auth":
		return nil, errAuthRequired
	case "denied":
		return nil, errAuthFailed
	}
	decoded, err := base64.Decode(value)
	if err != nil {
		return nil, err
	}
	r := flate.NewReader(bytes.NewReader(decoded))
	defer r.Close()
	dec := json.NewDecoder(r)
	var info *profileInfo
	if err := dec.Decode(&info); err != nil {
		return nil, err
	}
	return info, nil
}