Limit the number of key files checked on SearchKey
This commit is contained in:
parent
79e950b710
commit
d8107f77aa
5 changed files with 30 additions and 11 deletions
|
@ -197,6 +197,8 @@ func (o GlobalOptions) ReadPasswordTwice(prompt1, prompt2 string) string {
|
||||||
return pw1
|
return pw1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const maxKeys = 20
|
||||||
|
|
||||||
// OpenRepository reads the password and opens the repository.
|
// OpenRepository reads the password and opens the repository.
|
||||||
func (o GlobalOptions) OpenRepository() (*repository.Repository, error) {
|
func (o GlobalOptions) OpenRepository() (*repository.Repository, error) {
|
||||||
if o.Repo == "" {
|
if o.Repo == "" {
|
||||||
|
@ -214,7 +216,7 @@ func (o GlobalOptions) OpenRepository() (*repository.Repository, error) {
|
||||||
o.password = o.ReadPassword("enter password for repository: ")
|
o.password = o.ReadPassword("enter password for repository: ")
|
||||||
}
|
}
|
||||||
|
|
||||||
err = s.SearchKey(o.password)
|
err = s.SearchKey(o.password, maxKeys)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unable to open repo: %v", err)
|
return nil, fmt.Errorf("unable to open repo: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -249,7 +249,7 @@ func TestCheckerModifiedData(t *testing.T) {
|
||||||
|
|
||||||
beError := &errorBackend{Backend: be}
|
beError := &errorBackend{Backend: be}
|
||||||
checkRepo := repository.New(beError)
|
checkRepo := repository.New(beError)
|
||||||
OK(t, checkRepo.SearchKey(TestPassword))
|
OK(t, checkRepo.SearchKey(TestPassword, 5))
|
||||||
|
|
||||||
chkr := checker.New(checkRepo)
|
chkr := checker.New(checkRepo)
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,9 @@ import (
|
||||||
var (
|
var (
|
||||||
// ErrNoKeyFound is returned when no key for the repository could be decrypted.
|
// ErrNoKeyFound is returned when no key for the repository could be decrypted.
|
||||||
ErrNoKeyFound = errors.New("wrong password or no key found")
|
ErrNoKeyFound = errors.New("wrong password or no key found")
|
||||||
|
|
||||||
|
// ErrMaxKeysReached is returned when the maximum number of keys was checked and no key could be found.
|
||||||
|
ErrMaxKeysReached = errors.New("maximum number of keys reached")
|
||||||
)
|
)
|
||||||
|
|
||||||
// Key represents an encrypted master key for a repository.
|
// Key represents an encrypted master key for a repository.
|
||||||
|
@ -98,18 +101,32 @@ func OpenKey(s *Repository, name string, password string) (*Key, error) {
|
||||||
return k, nil
|
return k, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SearchKey tries to decrypt all keys in the backend with the given password.
|
// SearchKey tries to decrypt at most maxKeys keys in the backend with the
|
||||||
// If none could be found, ErrNoKeyFound is returned.
|
// given password. If none could be found, ErrNoKeyFound is returned. When
|
||||||
func SearchKey(s *Repository, password string) (*Key, error) {
|
// maxKeys is reached, ErrMaxKeysReached is returned. When setting maxKeys to
|
||||||
// try all keys in repo
|
// zero, all keys in the repo are checked.
|
||||||
|
func SearchKey(s *Repository, password string, maxKeys int) (*Key, error) {
|
||||||
|
checked := 0
|
||||||
|
|
||||||
|
// try at most maxKeysForSearch keys in repo
|
||||||
done := make(chan struct{})
|
done := make(chan struct{})
|
||||||
defer close(done)
|
defer close(done)
|
||||||
for name := range s.Backend().List(backend.Key, done) {
|
for name := range s.Backend().List(backend.Key, done) {
|
||||||
|
if maxKeys > 0 && checked > maxKeys {
|
||||||
|
return nil, ErrMaxKeysReached
|
||||||
|
}
|
||||||
|
|
||||||
debug.Log("SearchKey", "trying key %v", name[:12])
|
debug.Log("SearchKey", "trying key %v", name[:12])
|
||||||
key, err := OpenKey(s, name, password)
|
key, err := OpenKey(s, name, password)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
debug.Log("SearchKey", "key %v returned error %v", name[:12], err)
|
debug.Log("SearchKey", "key %v returned error %v", name[:12], err)
|
||||||
continue
|
|
||||||
|
// ErrUnauthenticated means the password is wrong, try the next key
|
||||||
|
if err == crypto.ErrUnauthenticated {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
debug.Log("SearchKey", "successfully opened key %v", name[:12])
|
debug.Log("SearchKey", "successfully opened key %v", name[:12])
|
||||||
|
|
|
@ -405,9 +405,9 @@ func LoadIndex(repo *Repository, id backend.ID) (*Index, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// SearchKey finds a key with the supplied password, afterwards the config is
|
// SearchKey finds a key with the supplied password, afterwards the config is
|
||||||
// read and parsed.
|
// read and parsed. It tries at most maxKeys key files in the repo.
|
||||||
func (r *Repository) SearchKey(password string) error {
|
func (r *Repository) SearchKey(password string, maxKeys int) error {
|
||||||
key, err := SearchKey(r, password)
|
key, err := SearchKey(r, password, maxKeys)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -214,7 +214,7 @@ func OpenLocalRepo(t testing.TB, dir string) *repository.Repository {
|
||||||
OK(t, err)
|
OK(t, err)
|
||||||
|
|
||||||
repo := repository.New(be)
|
repo := repository.New(be)
|
||||||
err = repo.SearchKey(TestPassword)
|
err = repo.SearchKey(TestPassword, 10)
|
||||||
OK(t, err)
|
OK(t, err)
|
||||||
|
|
||||||
return repo
|
return repo
|
||||||
|
|
Loading…
Reference in a new issue