2
2
mirror of https://github.com/octoleo/restic.git synced 2024-11-02 11:46:36 +00:00

Limit the number of key files checked on SearchKey

This commit is contained in:
Alexander Neumann 2016-08-21 13:09:31 +02:00
parent 79e950b710
commit d8107f77aa
5 changed files with 30 additions and 11 deletions

View File

@ -197,6 +197,8 @@ func (o GlobalOptions) ReadPasswordTwice(prompt1, prompt2 string) string {
return pw1
}
const maxKeys = 20
// OpenRepository reads the password and opens the repository.
func (o GlobalOptions) OpenRepository() (*repository.Repository, error) {
if o.Repo == "" {
@ -214,7 +216,7 @@ func (o GlobalOptions) OpenRepository() (*repository.Repository, error) {
o.password = o.ReadPassword("enter password for repository: ")
}
err = s.SearchKey(o.password)
err = s.SearchKey(o.password, maxKeys)
if err != nil {
return nil, fmt.Errorf("unable to open repo: %v", err)
}

View File

@ -249,7 +249,7 @@ func TestCheckerModifiedData(t *testing.T) {
beError := &errorBackend{Backend: be}
checkRepo := repository.New(beError)
OK(t, checkRepo.SearchKey(TestPassword))
OK(t, checkRepo.SearchKey(TestPassword, 5))
chkr := checker.New(checkRepo)

View File

@ -16,6 +16,9 @@ import (
var (
// ErrNoKeyFound is returned when no key for the repository could be decrypted.
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.
@ -98,18 +101,32 @@ func OpenKey(s *Repository, name string, password string) (*Key, error) {
return k, nil
}
// SearchKey tries to decrypt all keys in the backend with the given password.
// If none could be found, ErrNoKeyFound is returned.
func SearchKey(s *Repository, password string) (*Key, error) {
// try all keys in repo
// SearchKey tries to decrypt at most maxKeys keys in the backend with the
// given password. If none could be found, ErrNoKeyFound is returned. When
// maxKeys is reached, ErrMaxKeysReached is returned. When setting maxKeys to
// 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{})
defer close(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])
key, err := OpenKey(s, name, password)
if err != nil {
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])

View File

@ -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
// read and parsed.
func (r *Repository) SearchKey(password string) error {
key, err := SearchKey(r, password)
// read and parsed. It tries at most maxKeys key files in the repo.
func (r *Repository) SearchKey(password string, maxKeys int) error {
key, err := SearchKey(r, password, maxKeys)
if err != nil {
return err
}

View File

@ -214,7 +214,7 @@ func OpenLocalRepo(t testing.TB, dir string) *repository.Repository {
OK(t, err)
repo := repository.New(be)
err = repo.SearchKey(TestPassword)
err = repo.SearchKey(TestPassword, 10)
OK(t, err)
return repo