1
Fork 0
mirror of https://github.com/jech/galene.git synced 2024-11-22 08:35:57 +01:00

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.
This commit is contained in:
Juliusz Chroboczek 2023-05-14 21:14:59 +02:00
parent dc8a78be32
commit 3c0dbf5e9b
4 changed files with 55 additions and 6 deletions

View file

@ -120,7 +120,7 @@ func toStringArray(a []interface{}) ([]string, bool) {
return b, true 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) { t, err := jwt.Parse(token, func(t *jwt.Token) (interface{}, error) {
return getKey(t.Header, keys) return getKey(t.Header, keys)
}) })

View file

@ -55,11 +55,14 @@ func SetStatefulFilename(filename string) {
tokens.modTime = time.Time{} tokens.modTime = time.Time{}
} }
func getStateful(token string) (Token, error) { func getStateful(token string) (*Stateful, error) {
tokens.mu.Lock() tokens.mu.Lock()
defer tokens.mu.Unlock() defer tokens.mu.Unlock()
err := tokens.load() err := tokens.load()
if err != nil { if err != nil {
if os.IsNotExist(err) {
return nil, nil
}
return nil, err return nil, err
} }
if tokens.tokens == nil { if tokens.tokens == nil {

View file

@ -2,6 +2,7 @@ package token
import ( import (
"errors" "errors"
"os"
) )
var ErrUsernameRequired = errors.New("username required") var ErrUsernameRequired = errors.New("username required")
@ -11,9 +12,23 @@ type Token interface {
} }
func Parse(token string, keys []map[string]interface{}) (Token, error) { func Parse(token string, keys []map[string]interface{}) (Token, error) {
t, err := getStateful(token) // both getStateful and parseJWT may return nil, which we
if err == nil && t != nil { // shouldn't cast into an interface. Be very careful.
return t, nil 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)
} }

31
token/token_test.go Normal file
View file

@ -0,0 +1,31 @@
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)
}
}