gilbertchen / duplicacy

A new generation cloud backup tool
https://duplicacy.com
Other
5.22k stars 338 forks source link

Changing password via one of the repositories with shared storage requires manual intervention for the other #297

Open ghost opened 6 years ago

ghost commented 6 years ago

Assume I have single storage and two repositories backing up to it as below. The repo password is now saved twice to MacOS Keychain for "default" and for "sftpds01" storages.

Repo 1

[
    {
        "name": "default",
        "id": "users-imac",
        "storage": "sftp://alex@DS01//Backups/duplicacy/",
        "encrypted": true,
        "no_backup": false,
        "no_restore": false,
        "no_save_password": false,
        "keys": {
                "ssh_key_file":"path_to_RSA_private_key"
        }
    }
]

Repo 2

[
   {
        "name": "sftpds01",
        "id": "alex-imac",
        "storage": "sftp://alex@DS01//Backups/duplicacy/",
        "encrypted": true,
        "no_backup": false,
        "no_restore": false,
        "no_save_password": false,
        "keys": {
            "ssh_key_file":"path_to_RSA_private_key"
    }
    }
]

Repro steps:

  1. Go to Repo1 and change password. This succeeds.
  2. Now go to Repo2 and attempt backup.

Observed result: Duplicacy will fail due to password mismatch. There is no indication on how to recover for the end user.

Workaround: Delete the second repository's password from Keychain to force duplicacy to ask for the storage password again.

Proposed solution: Verify the storage encryption key and if it mismatches ignore it and proceed with asking for it in the console.

gilbertchen commented 6 years ago

I tried to reproduce it with the following steps, but it worked as expected:

cd /path/to/repository1
duplicacy init -e test /path/to/storage1
duplicacy list

cd /path/to/repository2
duplicacy init -e test /path/to/storage2
#modify /path/to/repository2/.duplicacy/preferences to change the storage name
duplicacy list

cd /path/to/repository1
duplicacy password
duplicacy list

If the storage's name is default, the password will be saved in the Keychain entry with the account password. Otherwise, the account will be storagename_password. In your case, the storage password for Repo 2 will be saved under account sftpds01. You probably ran list or backup before you changed the storage name from default to sftpds01 and that would overwrite the storage password for Repo 1 in Keychain.

ghost commented 6 years ago

Sorry, I should have made it clearer - the storage URL should be the same in both cases.

Attaching reproduction script and output. repro01.log repro01.sh.txt

Rename the latter one to .sh and run it. To use:

  1. Remove duplicacy entries from Keychain.
  2. Run the script.
  3. the script will init two repos and single storage under /tmp with password "Password"
  4. Then it will attempt to backup in Repo1 and will ask for the password. Enter "Password". It will be also saved to Keychain at this point.
  5. Next it will try to backup second repro, and also ask for the password. Enter "Password" again because it's the same storage.
  6. Now back in the Repo1 it will call duplicacy password. Enter old password "Password" again followed by new password twice -e.g. "aaaaaaaa"
  7. Password change will succeed
  8. Next it will go to Repo2 and attempt to backup.

->> At this point it will fail without asking for a password (Apparently because the password stored in the keychain entry for the storage2 is now outdated.

Edit. Now that I think about it this is because there are two different storage "given" names referring to the same actual storage path; and since the keychain entries are derived from the given storage name this makes it possible for multiple different keychain entries with different passwords to exist for the same actual storage.

I guess one could say that I should not have named/referred to the same storage differently in two repositories - but that somehow happened (twice!) when I was messing around adding and removing destinations from/to repositories - once it got named "default" and the next time I had to name it explicitly.

The solution could be to disallow users to refer to the same repository by different names. This could be accomplished by also storing the given name as created in the destination (config file perhaps). If then another repository tries to name that storage differently - do something about it right there.