Commit 3c0dbf5e authored by Juliusz Chroboczek's avatar Juliusz Chroboczek

Reliably return an error from token.Parse.

We would sometimes return nil cast to an interface with no error,
which would cause the server to crash with a null dereference.
parent dc8a78be
......@@ -120,7 +120,7 @@ func toStringArray(a []interface{}) ([]string, bool) {
return b, true
}
func parseJWT(token string, keys []map[string]interface{}) (Token, error) {
func parseJWT(token string, keys []map[string]interface{}) (*JWT, error) {
t, err := jwt.Parse(token, func(t *jwt.Token) (interface{}, error) {
return getKey(t.Header, keys)
})
......
......@@ -55,11 +55,14 @@ func SetStatefulFilename(filename string) {
tokens.modTime = time.Time{}
}
func getStateful(token string) (Token, error) {
func getStateful(token string) (*Stateful, error) {
tokens.mu.Lock()
defer tokens.mu.Unlock()
err := tokens.load()
if err != nil {
if os.IsNotExist(err) {
return nil, nil
}
return nil, err
}
if tokens.tokens == nil {
......
......@@ -2,6 +2,7 @@ package token
import (
"errors"
"os"
)
var ErrUsernameRequired = errors.New("username required")
......@@ -11,9 +12,23 @@ type Token interface {
}
func Parse(token string, keys []map[string]interface{}) (Token, error) {
t, err := getStateful(token)
if err == nil && t != nil {
return t, nil
// both getStateful and parseJWT may return nil, which we
// shouldn't cast into an interface. Be very careful.
s, err1 := getStateful(token)
if err1 == nil && s != nil {
return s, nil
}
jwt, err2 := parseJWT(token, keys)
if err2 == nil && jwt != nil {
return jwt, nil
}
if err1 != nil {
return nil, err1
} else if err2 != nil {
return nil, err2
} else {
return nil, os.ErrNotExist
}
return parseJWT(token, keys)
}
package token
import (
"testing"
"path/filepath"
"os"
)
func TestBad(t *testing.T) {
d := t.TempDir()
tokens = state{
filename: filepath.Join(d, "test.jsonl"),
}
f, err := os.OpenFile(tokens.filename,
os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0600,
)
if err != nil {
t.Fatalf("Create: %v", err)
}
defer f.Close()
token, err := Parse("foo", nil)
if err == nil {
t.Errorf("Expected error, got %v", token)
}
token, err = Parse("foo", []map[string]interface{}{})
if err == nil {
t.Errorf("Expected error, got %v", token)
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment