xsrftoken: panic for unsafe zero length keys

Passing a zero length key (or secret) gives no safety against XSRF
attacks. This is a relatively easy mistake to make, e.g. by passing
`make([]byte, 0, 1024)` to `rand.Read` instead of `make([]byte, 1024)`,
and currently fails open, silently.

This uses panic, as the API does not allow returning a structured error,
and catching this programming error is not worth breaking API
compatibility. Passing a zero length secret is also not an error
condition that API callers would handle, so there is little value in
returning a proper error.

Change-Id: Ib6457347675872188d51d2a220eee4b67900f79e
Reviewed-on: https://go-review.googlesource.com/42411
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
Martin Probst
2017-05-02 12:17:47 +02:00
committed by Brad Fitzpatrick
parent da118f7b8e
commit 0819898fb4

View File

@@ -27,15 +27,18 @@ func clean(s string) string {
// Generate returns a URL-safe secure XSRF token that expires in 24 hours.
//
// key is a secret key for your application.
// userID is a unique identifier for the user.
// actionID is the action the user is taking (e.g. POSTing to a particular path).
// key is a secret key for your application; it must be non-empty.
// userID is an optional unique identifier for the user.
// actionID is an optional action the user is taking (e.g. POSTing to a particular path).
func Generate(key, userID, actionID string) string {
return generateTokenAtTime(key, userID, actionID, time.Now())
}
// generateTokenAtTime is like Generate, but returns a token that expires 24 hours from now.
func generateTokenAtTime(key, userID, actionID string, now time.Time) string {
if len(key) == 0 {
panic("zero length xsrf secret key")
}
// Round time up and convert to milliseconds.
milliTime := (now.UnixNano() + 1e6 - 1) / 1e6
@@ -57,6 +60,9 @@ func Valid(token, key, userID, actionID string) bool {
// validTokenAtTime reports whether a token is valid at the given time.
func validTokenAtTime(token, key, userID, actionID string, now time.Time) bool {
if len(key) == 0 {
panic("zero length xsrf secret key")
}
// Extract the issue time of the token.
sep := strings.LastIndex(token, ":")
if sep < 0 {