Compare to check what messed up the refresh check.
This commit is contained in:
parent
a7134c1c90
commit
0fcf12663d
11
Makefile
11
Makefile
|
@ -42,4 +42,13 @@ service:
|
|||
clean:
|
||||
rm -f go-auth.h
|
||||
rm -f go-auth.so
|
||||
rm -f pw
|
||||
rm -f pw
|
||||
|
||||
docker-build:
|
||||
docker build -t mosquitto-go-auth.test -f Dockerfile.runtest .
|
||||
|
||||
docker-test:
|
||||
docker run --rm mosquitto-go-auth.test ./run-test-in-docker.sh
|
||||
|
||||
docker-test-local:
|
||||
docker run -v $(pwd):/app --rm -ti mosquitto-go-auth.test ./run-test-in-docker.sh
|
|
@ -18,23 +18,25 @@ import (
|
|||
|
||||
// redisCache stores necessary values for Redis cache
|
||||
type redisStore struct {
|
||||
authExpiration time.Duration
|
||||
aclExpiration time.Duration
|
||||
authJitter time.Duration
|
||||
aclJitter time.Duration
|
||||
refreshExpiration bool
|
||||
client bes.RedisClient
|
||||
h hash.Hash
|
||||
client bes.RedisClient
|
||||
h hash.Hash
|
||||
options Options
|
||||
}
|
||||
|
||||
type goStore struct {
|
||||
authExpiration time.Duration
|
||||
aclExpiration time.Duration
|
||||
authJitter time.Duration
|
||||
aclJitter time.Duration
|
||||
refreshExpiration bool
|
||||
client *goCache.Cache
|
||||
h hash.Hash
|
||||
client *goCache.Cache
|
||||
h hash.Hash
|
||||
options Options
|
||||
}
|
||||
|
||||
type Options struct {
|
||||
AuthExpiration time.Duration
|
||||
AclExpiration time.Duration
|
||||
SuperuserExpiration time.Duration
|
||||
AuthJitter time.Duration
|
||||
AclJitter time.Duration
|
||||
SuperuserJitter time.Duration
|
||||
RefreshExpiration bool
|
||||
}
|
||||
|
||||
const (
|
||||
|
@ -46,47 +48,41 @@ type Store interface {
|
|||
CheckAuthRecord(ctx context.Context, username, password string) (bool, bool)
|
||||
SetACLRecord(ctx context.Context, username, topic, clientid string, acc int, granted string) error
|
||||
CheckACLRecord(ctx context.Context, username, topic, clientid string, acc int) (bool, bool)
|
||||
SetSuperuserRecord(ctx context.Context, username, password, granted string) error
|
||||
CheckSuperuserRecord(ctx context.Context, username, password string) (bool, bool)
|
||||
Connect(ctx context.Context, reset bool) bool
|
||||
Close()
|
||||
}
|
||||
|
||||
// NewGoStore initializes a cache using go-cache as the store.
|
||||
func NewGoStore(authExpiration, aclExpiration, authJitter, aclJitter time.Duration, refreshExpiration bool) *goStore {
|
||||
func NewGoStore(options Options) *goStore {
|
||||
// TODO: support hydrating the cache to retain previous values.
|
||||
|
||||
return &goStore{
|
||||
authExpiration: authExpiration,
|
||||
aclExpiration: aclExpiration,
|
||||
authJitter: authJitter,
|
||||
aclJitter: aclJitter,
|
||||
refreshExpiration: refreshExpiration,
|
||||
client: goCache.New(time.Second*defaultExpiration, time.Second*(defaultExpiration*2)),
|
||||
h: sha1.New(),
|
||||
client: goCache.New(time.Second*defaultExpiration, time.Second*(defaultExpiration*2)),
|
||||
h: sha1.New(),
|
||||
options: options,
|
||||
}
|
||||
}
|
||||
|
||||
// NewSingleRedisStore initializes a cache using a single Redis instance as the store.
|
||||
func NewSingleRedisStore(host, port, password string, db int, authExpiration, aclExpiration, authJitter, aclJitter time.Duration, refreshExpiration bool) *redisStore {
|
||||
func NewSingleRedisStore(host, port, password string, db int, options Options) *redisStore {
|
||||
addr := fmt.Sprintf("%s:%s", host, port)
|
||||
redisClient := goredis.NewClient(&goredis.Options{
|
||||
Addr: addr,
|
||||
Password: password, // no password set
|
||||
DB: db, // use default db
|
||||
Password: password,
|
||||
DB: db,
|
||||
})
|
||||
//If cache is on, try to start redis.
|
||||
|
||||
return &redisStore{
|
||||
authExpiration: authExpiration,
|
||||
aclExpiration: aclExpiration,
|
||||
authJitter: authJitter,
|
||||
aclJitter: aclJitter,
|
||||
refreshExpiration: refreshExpiration,
|
||||
client: bes.SingleRedisClient{redisClient},
|
||||
h: sha1.New(),
|
||||
client: bes.SingleRedisClient{redisClient},
|
||||
h: sha1.New(),
|
||||
options: options,
|
||||
}
|
||||
}
|
||||
|
||||
// NewSingleRedisStore initializes a cache using a Redis Cluster as the store.
|
||||
func NewRedisClusterStore(password string, addresses []string, authExpiration, aclExpiration, authJitter, aclJitter time.Duration, refreshExpiration bool) *redisStore {
|
||||
func NewRedisClusterStore(password string, addresses []string, options Options) *redisStore {
|
||||
clusterClient := goredis.NewClusterClient(
|
||||
&goredis.ClusterOptions{
|
||||
Addrs: addresses,
|
||||
|
@ -94,13 +90,9 @@ func NewRedisClusterStore(password string, addresses []string, authExpiration, a
|
|||
})
|
||||
|
||||
return &redisStore{
|
||||
authExpiration: authExpiration,
|
||||
aclExpiration: aclExpiration,
|
||||
authJitter: authJitter,
|
||||
aclJitter: aclJitter,
|
||||
refreshExpiration: refreshExpiration,
|
||||
client: clusterClient,
|
||||
h: sha1.New(),
|
||||
client: clusterClient,
|
||||
h: sha1.New(),
|
||||
options: options,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -110,9 +102,15 @@ func toAuthRecord(username, password string, h hash.Hash) string {
|
|||
return b64.StdEncoding.EncodeToString(sum)
|
||||
}
|
||||
|
||||
func toSuperuserRecord(username, password string, h hash.Hash) string {
|
||||
sum := h.Sum([]byte(fmt.Sprintf("superuser-%s-%s", username, password)))
|
||||
log.Debugf("to superuser record: %v\n", sum)
|
||||
return b64.StdEncoding.EncodeToString(sum)
|
||||
}
|
||||
|
||||
func toACLRecord(username, topic, clientid string, acc int, h hash.Hash) string {
|
||||
sum := h.Sum([]byte(fmt.Sprintf("acl-%s-%s-%s-%d", username, topic, clientid, acc)))
|
||||
log.Debugf("to auth record: %v\n", sum)
|
||||
log.Debugf("to acl record: %v\n", sum)
|
||||
return b64.StdEncoding.EncodeToString(sum)
|
||||
}
|
||||
|
||||
|
@ -179,13 +177,19 @@ func (s *redisStore) Close() {
|
|||
// CheckAuthRecord checks if the username/password pair is present in the cache. Return if it's present and, if so, if it was granted privileges
|
||||
func (s *goStore) CheckAuthRecord(ctx context.Context, username, password string) (bool, bool) {
|
||||
record := toAuthRecord(username, password, s.h)
|
||||
return s.checkRecord(ctx, record, expirationWithJitter(s.authExpiration, s.authJitter))
|
||||
return s.checkRecord(ctx, record, expirationWithJitter(s.options.AuthExpiration, s.options.AuthJitter))
|
||||
}
|
||||
|
||||
//CheckAclCache checks if the username/topic/clientid/acc mix is present in the cache. Return if it's present and, if so, if it was granted privileges.
|
||||
// CheckAclRecord checks if the username/topic/clientid/acc mix is present in the cache. Return if it's present and, if so, if it was granted privileges.
|
||||
func (s *goStore) CheckACLRecord(ctx context.Context, username, topic, clientid string, acc int) (bool, bool) {
|
||||
record := toACLRecord(username, topic, clientid, acc, s.h)
|
||||
return s.checkRecord(ctx, record, expirationWithJitter(s.aclExpiration, s.aclJitter))
|
||||
return s.checkRecord(ctx, record, expirationWithJitter(s.options.AclExpiration, s.options.AclJitter))
|
||||
}
|
||||
|
||||
// CheckSuperuserRecord checks if the username is in the superuser cache. Return if it's present and, if so, if it was granted privileges.
|
||||
func (s *goStore) CheckSuperuserRecord(ctx context.Context, username, password string) (bool, bool) {
|
||||
record := toSuperuserRecord(username, password, s.h)
|
||||
return s.checkRecord(ctx, record, expirationWithJitter(s.options.SuperuserExpiration, s.options.SuperuserJitter))
|
||||
}
|
||||
|
||||
func (s *goStore) checkRecord(ctx context.Context, record string, expirationTime time.Duration) (bool, bool) {
|
||||
|
@ -198,7 +202,7 @@ func (s *goStore) checkRecord(ctx context.Context, record string, expirationTime
|
|||
granted = true
|
||||
}
|
||||
|
||||
if s.refreshExpiration {
|
||||
if s.options.RefreshExpiration {
|
||||
s.client.Set(record, value, expirationTime)
|
||||
}
|
||||
}
|
||||
|
@ -208,13 +212,19 @@ func (s *goStore) checkRecord(ctx context.Context, record string, expirationTime
|
|||
// CheckAuthRecord checks if the username/password pair is present in the cache. Return if it's present and, if so, if it was granted privileges
|
||||
func (s *redisStore) CheckAuthRecord(ctx context.Context, username, password string) (bool, bool) {
|
||||
record := toAuthRecord(username, password, s.h)
|
||||
return s.checkRecord(ctx, record, s.authExpiration)
|
||||
return s.checkRecord(ctx, record, expirationWithJitter(s.options.AuthExpiration, s.options.AuthJitter))
|
||||
}
|
||||
|
||||
//CheckAclCache checks if the username/topic/clientid/acc mix is present in the cache. Return if it's present and, if so, if it was granted privileges.
|
||||
// CheckAclRecord checks if the username/topic/clientid/acc mix is present in the cache. Return if it's present and, if so, if it was granted privileges.
|
||||
func (s *redisStore) CheckACLRecord(ctx context.Context, username, topic, clientid string, acc int) (bool, bool) {
|
||||
record := toACLRecord(username, topic, clientid, acc, s.h)
|
||||
return s.checkRecord(ctx, record, s.aclExpiration)
|
||||
return s.checkRecord(ctx, record, expirationWithJitter(s.options.AclExpiration, s.options.AclJitter))
|
||||
}
|
||||
|
||||
// CheckSuperuserRecord checks if the username is in the superuser cache. Return if it's present and, if so, if it was granted privileges.
|
||||
func (s *redisStore) CheckSuperuserRecord(ctx context.Context, username, password string) (bool, bool) {
|
||||
record := toSuperuserRecord(username, password, s.h)
|
||||
return s.checkRecord(ctx, record, expirationWithJitter(s.options.SuperuserExpiration, s.options.SuperuserJitter))
|
||||
}
|
||||
|
||||
func (s *redisStore) checkRecord(ctx context.Context, record string, expirationTime time.Duration) (bool, bool) {
|
||||
|
@ -244,7 +254,7 @@ func (s *redisStore) getAndRefresh(ctx context.Context, record string, expiratio
|
|||
return false, false, err
|
||||
}
|
||||
|
||||
if s.refreshExpiration {
|
||||
if s.options.RefreshExpiration {
|
||||
_, err = s.client.Expire(ctx, record, expirationTime).Result()
|
||||
if err != nil {
|
||||
return false, false, err
|
||||
|
@ -261,15 +271,23 @@ func (s *redisStore) getAndRefresh(ctx context.Context, record string, expiratio
|
|||
// SetAuthRecord sets a pair, granted option and expiration time.
|
||||
func (s *goStore) SetAuthRecord(ctx context.Context, username, password string, granted string) error {
|
||||
record := toAuthRecord(username, password, s.h)
|
||||
s.client.Set(record, granted, expirationWithJitter(s.authExpiration, s.authJitter))
|
||||
s.client.Set(record, granted, expirationWithJitter(s.options.AuthExpiration, s.options.AuthJitter))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
//SetAclCache sets a mix, granted option and expiration time.
|
||||
// SetAclRecord sets a mix, granted option and expiration time.
|
||||
func (s *goStore) SetACLRecord(ctx context.Context, username, topic, clientid string, acc int, granted string) error {
|
||||
record := toACLRecord(username, topic, clientid, acc, s.h)
|
||||
s.client.Set(record, granted, expirationWithJitter(s.aclExpiration, s.aclJitter))
|
||||
s.client.Set(record, granted, expirationWithJitter(s.options.AclExpiration, s.options.AclJitter))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetSuperuserRecord sets a pair, granted option and expiration time.
|
||||
func (s *goStore) SetSuperuserRecord(ctx context.Context, username, password string, granted string) error {
|
||||
record := toSuperuserRecord(username, password, s.h)
|
||||
s.client.Set(record, granted, expirationWithJitter(s.options.AuthExpiration, s.options.AuthJitter))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -277,13 +295,19 @@ func (s *goStore) SetACLRecord(ctx context.Context, username, topic, clientid st
|
|||
// SetAuthRecord sets a pair, granted option and expiration time.
|
||||
func (s *redisStore) SetAuthRecord(ctx context.Context, username, password string, granted string) error {
|
||||
record := toAuthRecord(username, password, s.h)
|
||||
return s.setRecord(ctx, record, granted, expirationWithJitter(s.authExpiration, s.authJitter))
|
||||
return s.setRecord(ctx, record, granted, expirationWithJitter(s.options.AuthExpiration, s.options.AuthJitter))
|
||||
}
|
||||
|
||||
//SetAclCache sets a mix, granted option and expiration time.
|
||||
// SetAclRecord sets a mix, granted option and expiration time.
|
||||
func (s *redisStore) SetACLRecord(ctx context.Context, username, topic, clientid string, acc int, granted string) error {
|
||||
record := toACLRecord(username, topic, clientid, acc, s.h)
|
||||
return s.setRecord(ctx, record, granted, expirationWithJitter(s.aclExpiration, s.aclJitter))
|
||||
return s.setRecord(ctx, record, granted, expirationWithJitter(s.options.AclExpiration, s.options.AclJitter))
|
||||
}
|
||||
|
||||
// SetSuperuserRecord sets a pair, granted option and expiration time.
|
||||
func (s *redisStore) SetSuperuserRecord(ctx context.Context, username, password string, granted string) error {
|
||||
record := toSuperuserRecord(username, password, s.h)
|
||||
return s.setRecord(ctx, record, granted, expirationWithJitter(s.options.AuthExpiration, s.options.AuthJitter))
|
||||
}
|
||||
|
||||
func (s *redisStore) setRecord(ctx context.Context, record, granted string, expirationTime time.Duration) error {
|
||||
|
|
|
@ -41,18 +41,30 @@ func TestExpirationWithoutJitter(t *testing.T) {
|
|||
func TestGoStore(t *testing.T) {
|
||||
authExpiration := 100 * time.Millisecond
|
||||
aclExpiration := 100 * time.Millisecond
|
||||
superuserExpiration := 100 * time.Millisecond
|
||||
authJitter := 10 * time.Millisecond
|
||||
aclJitter := 10 * time.Millisecond
|
||||
superuserJitter := 10 * time.Millisecond
|
||||
refreshExpiration := false
|
||||
|
||||
store := NewGoStore(authExpiration, aclExpiration, authJitter, aclJitter, refreshExpiration)
|
||||
options := Options{
|
||||
AuthExpiration: authExpiration,
|
||||
AclExpiration: aclExpiration,
|
||||
AuthJitter: authJitter,
|
||||
AclJitter: aclJitter,
|
||||
SuperuserExpiration: superuserExpiration,
|
||||
SuperuserJitter: superuserJitter,
|
||||
RefreshExpiration: refreshExpiration,
|
||||
}
|
||||
|
||||
store := NewGoStore(options)
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
assert.Equal(t, authExpiration, store.authExpiration)
|
||||
assert.Equal(t, aclExpiration, store.aclExpiration)
|
||||
assert.Equal(t, authJitter, store.authJitter)
|
||||
assert.Equal(t, aclJitter, store.aclJitter)
|
||||
assert.Equal(t, authExpiration, store.options.AuthExpiration)
|
||||
assert.Equal(t, aclExpiration, store.options.AclExpiration)
|
||||
assert.Equal(t, authJitter, store.options.AuthJitter)
|
||||
assert.Equal(t, aclJitter, store.options.AclJitter)
|
||||
|
||||
assert.True(t, store.Connect(ctx, false))
|
||||
|
||||
|
@ -128,7 +140,7 @@ func TestGoStore(t *testing.T) {
|
|||
assert.False(t, granted)
|
||||
|
||||
// Check expiration is refreshed.
|
||||
store = NewGoStore(authExpiration, aclExpiration, authExpiration, aclJitter, true)
|
||||
store = NewGoStore(options)
|
||||
|
||||
// Test granted access.
|
||||
err = store.SetAuthRecord(ctx, username, password, "true")
|
||||
|
@ -159,18 +171,30 @@ func TestGoStore(t *testing.T) {
|
|||
func TestRedisSingleStore(t *testing.T) {
|
||||
authExpiration := 1000 * time.Millisecond
|
||||
aclExpiration := 1000 * time.Millisecond
|
||||
superuserExpiration := 1000 * time.Millisecond
|
||||
authJitter := 100 * time.Millisecond
|
||||
aclJitter := 100 * time.Millisecond
|
||||
superuserJitter := 100 * time.Millisecond
|
||||
refreshExpiration := false
|
||||
|
||||
store := NewSingleRedisStore("localhost", "6379", "", 3, authExpiration, aclExpiration, authJitter, aclJitter, refreshExpiration)
|
||||
options := Options{
|
||||
AuthExpiration: authExpiration,
|
||||
AclExpiration: aclExpiration,
|
||||
SuperuserExpiration: superuserExpiration,
|
||||
AuthJitter: authJitter,
|
||||
AclJitter: aclJitter,
|
||||
SuperuserJitter: superuserJitter,
|
||||
RefreshExpiration: refreshExpiration,
|
||||
}
|
||||
|
||||
store := NewSingleRedisStore("localhost", "6379", "", 3, options)
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
assert.Equal(t, authExpiration, store.authExpiration)
|
||||
assert.Equal(t, aclExpiration, store.aclExpiration)
|
||||
assert.Equal(t, authJitter, store.authJitter)
|
||||
assert.Equal(t, aclJitter, store.aclJitter)
|
||||
assert.Equal(t, authExpiration, store.options.AuthExpiration)
|
||||
assert.Equal(t, aclExpiration, store.options.AclExpiration)
|
||||
assert.Equal(t, authJitter, store.options.AuthJitter)
|
||||
assert.Equal(t, aclJitter, store.options.AclJitter)
|
||||
|
||||
assert.True(t, store.Connect(ctx, false))
|
||||
|
||||
|
@ -223,7 +247,7 @@ func TestRedisSingleStore(t *testing.T) {
|
|||
assert.False(t, granted)
|
||||
|
||||
// Check expiration is refreshed.
|
||||
store = NewSingleRedisStore("localhost", "6379", "", 3, authExpiration, aclExpiration, authJitter, aclJitter, true)
|
||||
store = NewSingleRedisStore("localhost", "6379", "", 3, options)
|
||||
|
||||
// Test granted access.
|
||||
err = store.SetAuthRecord(ctx, username, password, "true")
|
||||
|
@ -254,19 +278,31 @@ func TestRedisSingleStore(t *testing.T) {
|
|||
func TestRedisClusterStore(t *testing.T) {
|
||||
authExpiration := 1000 * time.Millisecond
|
||||
aclExpiration := 1000 * time.Millisecond
|
||||
superuserExpiration := 1000 * time.Millisecond
|
||||
authJitter := 100 * time.Millisecond
|
||||
aclJitter := 100 * time.Millisecond
|
||||
superuserJitter := 100 * time.Millisecond
|
||||
refreshExpiration := false
|
||||
|
||||
options := Options{
|
||||
AuthExpiration: authExpiration,
|
||||
AclExpiration: aclExpiration,
|
||||
SuperuserExpiration: superuserExpiration,
|
||||
AuthJitter: authJitter,
|
||||
AclJitter: aclJitter,
|
||||
SuperuserJitter: superuserJitter,
|
||||
RefreshExpiration: refreshExpiration,
|
||||
}
|
||||
|
||||
addresses := []string{"localhost:7000", "localhost:7001", "localhost:7002"}
|
||||
store := NewRedisClusterStore("", addresses, authExpiration, aclExpiration, authJitter, aclJitter, refreshExpiration)
|
||||
store := NewRedisClusterStore("", addresses, options)
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
assert.Equal(t, authExpiration, store.authExpiration)
|
||||
assert.Equal(t, aclExpiration, store.aclExpiration)
|
||||
assert.Equal(t, authJitter, store.authJitter)
|
||||
assert.Equal(t, aclJitter, store.aclJitter)
|
||||
assert.Equal(t, authExpiration, store.options.AuthExpiration)
|
||||
assert.Equal(t, aclExpiration, store.options.AclExpiration)
|
||||
assert.Equal(t, authJitter, store.options.AuthJitter)
|
||||
assert.Equal(t, aclJitter, store.options.AclJitter)
|
||||
|
||||
assert.True(t, store.Connect(ctx, false))
|
||||
|
||||
|
@ -318,7 +354,7 @@ func TestRedisClusterStore(t *testing.T) {
|
|||
assert.True(t, present)
|
||||
assert.False(t, granted)
|
||||
|
||||
store = NewRedisClusterStore("", addresses, authExpiration, aclExpiration, authJitter, aclJitter, true)
|
||||
store = NewRedisClusterStore("", addresses, options)
|
||||
|
||||
// Test granted access.
|
||||
err = store.SetAuthRecord(ctx, username, password, "true")
|
||||
|
|
26
go-auth.go
26
go-auth.go
|
@ -185,6 +185,14 @@ func setCache(authOpts map[string]string) {
|
|||
refreshExpiration = true
|
||||
}
|
||||
|
||||
options := cache.Options{
|
||||
AclExpiration: time.Duration(aclCacheSeconds) * time.Second,
|
||||
AuthExpiration: time.Duration(authCacheSeconds) * time.Second,
|
||||
AuthJitter: time.Duration(authJitterSeconds) * time.Second,
|
||||
AclJitter: time.Duration(aclJitterSeconds) * time.Second,
|
||||
RefreshExpiration: refreshExpiration,
|
||||
}
|
||||
|
||||
switch authOpts["cache_type"] {
|
||||
case "redis":
|
||||
host := "localhost"
|
||||
|
@ -219,11 +227,7 @@ func setCache(authOpts map[string]string) {
|
|||
authPlugin.cache = cache.NewRedisClusterStore(
|
||||
password,
|
||||
addresses,
|
||||
time.Duration(authCacheSeconds)*time.Second,
|
||||
time.Duration(aclCacheSeconds)*time.Second,
|
||||
time.Duration(authJitterSeconds)*time.Second,
|
||||
time.Duration(aclJitterSeconds)*time.Second,
|
||||
refreshExpiration,
|
||||
options,
|
||||
)
|
||||
|
||||
} else {
|
||||
|
@ -249,21 +253,13 @@ func setCache(authOpts map[string]string) {
|
|||
port,
|
||||
password,
|
||||
db,
|
||||
time.Duration(authCacheSeconds)*time.Second,
|
||||
time.Duration(aclCacheSeconds)*time.Second,
|
||||
time.Duration(authJitterSeconds)*time.Second,
|
||||
time.Duration(aclJitterSeconds)*time.Second,
|
||||
refreshExpiration,
|
||||
options,
|
||||
)
|
||||
}
|
||||
|
||||
default:
|
||||
authPlugin.cache = cache.NewGoStore(
|
||||
time.Duration(authCacheSeconds)*time.Second,
|
||||
time.Duration(aclCacheSeconds)*time.Second,
|
||||
time.Duration(authJitterSeconds)*time.Second,
|
||||
time.Duration(aclJitterSeconds)*time.Second,
|
||||
refreshExpiration,
|
||||
options,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -89,11 +89,7 @@ func (h argon2IDHasher) Compare(password string, passwordHash string) bool {
|
|||
keylen := uint32(len(extractedHash))
|
||||
newHash := argon2.IDKey([]byte(password), salt, iterations, memory, parallelism, keylen)
|
||||
|
||||
if subtle.ConstantTimeCompare(newHash, extractedHash) == 1 {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
return subtle.ConstantTimeCompare(newHash, extractedHash) == 1
|
||||
}
|
||||
|
||||
func (h argon2IDHasher) hashWithSalt(password string, salt []byte, memory uint32, iterations int, parallelism uint8, keylen int) string {
|
||||
|
|
|
@ -23,8 +23,6 @@ func (h bcryptHasher) Hash(password string) (string, error) {
|
|||
// Compare checks that a bcrypt generated password matches the password hash.
|
||||
func (h bcryptHasher) Compare(password, passwordHash string) bool {
|
||||
err := bcrypt.CompareHashAndPassword([]byte(passwordHash), []byte(password))
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
|
||||
return err != nil
|
||||
}
|
||||
|
|
|
@ -61,9 +61,9 @@ func preferredEncoding(saltEncoding string) string {
|
|||
|
||||
// Empty backend: use whatever plugin wise hashing options are present by returning whole opts.
|
||||
// Backend present: check if there's a backend_hasher option:
|
||||
// - Yes: return a new map with whatever hashing options are present for the given backend and hasher
|
||||
// (defaults will be used for missing options).
|
||||
// - No: use whatever plugin wise hashing options are present by returning whole opts.
|
||||
// - Yes: return a new map with whatever hashing options are present for the given backend and hasher
|
||||
// (defaults will be used for missing options).
|
||||
// - No: use whatever plugin wise hashing options are present by returning whole opts.
|
||||
func processHashOpts(authOpts map[string]string, backend string) map[string]string {
|
||||
|
||||
// Return authOpts if no backend given.
|
||||
|
@ -145,6 +145,4 @@ func NewHasher(authOpts map[string]string, backend string) HashComparer {
|
|||
|
||||
saltEncoding := opts["hasher_salt_encoding"]
|
||||
return NewPBKDF2Hasher(saltSize, iterations, algorithm, saltEncoding, keyLen)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -28,7 +28,6 @@ func TestNewHasher(t *testing.T) {
|
|||
assert.Equal(t, Base64, pHasher.saltEncoding)
|
||||
|
||||
// Check that options are set correctly.
|
||||
authOpts = make(map[string]string)
|
||||
authOpts = map[string]string{
|
||||
"hasher": Pbkdf2Opt,
|
||||
"hasher_algorithm": SHA256,
|
||||
|
@ -60,7 +59,6 @@ func TestNewHasher(t *testing.T) {
|
|||
assert.Equal(t, defaultArgon2IDParallelism, aHasher.parallelism)
|
||||
assert.Equal(t, defaultArgon2IDSaltSize, aHasher.saltSize)
|
||||
|
||||
authOpts = make(map[string]string)
|
||||
authOpts = map[string]string{
|
||||
"hasher": Argon2IDOpt,
|
||||
"hasher_iterations": "100",
|
||||
|
@ -89,7 +87,6 @@ func TestNewHasher(t *testing.T) {
|
|||
assert.Equal(t, bHasher.cost, defaultBcryptCost)
|
||||
|
||||
// Check that options are set correctly.
|
||||
authOpts = make(map[string]string)
|
||||
authOpts = map[string]string{
|
||||
"hasher": BcryptOpt,
|
||||
"hasher_cost": "15",
|
||||
|
|
Loading…
Reference in New Issue