ProtonMail / proton-bridge

Proton Mail Bridge application
GNU General Public License v3.0
1.15k stars 156 forks source link

Renaming the home directory causes `permission denied` error #439

Open tingerrr opened 10 months ago

tingerrr commented 10 months ago

So, somewhat expectedly, renaming the user's home directory causes protonmail bridge to attempt to access/create the old cache and data dirs. The confusing part is that the log message indicates that it correctly tries to set backend/db into my current (new) home dir, while trying to create backend/store in the old home dir.

Expected Behavior

The application uses the current user's home directory for both the gluonCacheDir and the gluonDataDir for a default installation.

Current Behavior

The application seems to pull the old home directory out of thin air and crashes when it cannot create $OLD_HOME/.local.

Log message from (shortened for brevity):

$HOME/.local/share/protonmail/bridge-v3/logs/20231115_173933558_bri_000_v3.6.1_br-178.log:time="Nov 15 17:39:33.677" level=info msg="Creating IMAP server" gluonDB=$HOME/.local/share/protonmail/bridge-v3/gluon/backend/db gluonStore=$OLD_HOME/.local/share/protonmail/bridge-v3/gluon/backend/store logClient=false logServer=false version=3.6.1

I have replaced the current and old home with $HOME and $OLD_HOME respectively in this message for privacy reasons.

Possible Solution

I figured clearing all configuration and removing the files owned by the package (pacman -Ql protonmail-bridge-bin) would suffice, but even after clearing all sorts of cache directories containing a mere mention of protonmail-bridge it still does not seem to work.

Steps to Reproduce

  1. prepare a barebones linux installation with a user X
  2. install protonmail bridge and set it up with an account
  3. rename the user sudo usermod -l X Y
  4. rename the users home directory sudo usermod -d /home/Y -m Y
  5. (re)start protonmail bridge

Some of these steps like setting up the account may not be necessary, I don't really have the time to actually test this.

Version Information

Anywhere between 3.1.3-1 to 3.6.1-3, installed from the aur, which it seems is just a mirror of the deb. Currently isntalled is 3.6.1-3

Context (Environment)

Host: Linux hsh 6.5.9-arch2-1 #1 SMP PREEMPT_DYNAMIC Thu, 26 Oct 2023 00:52:20 +0000 x86_64 GNU/Linux

Neither XDG_DATA_DIR nor XDG_CACHE_DIR were set when running protonmail bridge, but setting cache and data dir explicitly doesn't have any effect, it seems.

As mentioned above, I have uninstalled the program completely and searched my whole system (a la fd -H protonmail /) for traces of its files that could contain the old dir. But none of these even contain those paths.

LBeernaertProton commented 10 months ago

Hey @tingerrr thanks for bringing this to our attention, we have internally tracked this as GODT-3126.

tingerrr commented 8 months ago

So it turns out after I cleaned my system up and uninstalled gnome-keyring as I was not using it anywhere, the problem disappeared. And it persists when reinstalling gnome-keyring, so this doesn't seem to be a protonmail-bridge issue directly.

I'll switch keyring for now, as I can't seem to track down where the old path is stored. My package manager removes all known traces of gnome-keyring so it must be storing the old path somewhere without letting my package manager know about it.

willcoxe commented 8 months ago

I have this problem. I don't use gnome-keyring but keepassxc.

EDIT: I have worked around the problem by (re)moving ~/.config/protonmail ~/.cache/protonmail ~/.local/share/protonmail

After this running the bridge and creating a new bridge connection worked. I did grep all the files in those directories recursively for the original homedir first and there were no results so I don't think it's stored as human readable.

ssmendon commented 3 months ago

Wanted to comment that this occurs on macOS. I tried uninstalling the application and re-installing it fresh, but that hasn't helped.

EDIT: I ran Proton Mail Bridge through a debugger on macOS and traced out the program's execution, to get some more insight as to why this error was happening (see the not entirely accurate https://github.com/ProtonMail/proton-bridge/issues/439#issuecomment-2212921810).

The crux of the issue on macOS is that the vault.enc file stored in the config folder (see the README.md) had a stale path in it (reference to the old home directory).

I resolved the issue by:

ssmendon commented 2 months ago

I stepped through this in a debugger to get a better sense of why this error was happening. The high-level issue is that a stale directory is cached in the vault (namely, the gluon data directory/the cache directory).

Because trying to create the cache directory occurs very early on in the Proton Mail Bridge application, it crashes very quickly with limited logs.

The remainder of this is more detailed, so you can understand the flow... It's a little confusing, because the data dir, cache dir, and config dir are used interchangeably in the source.

For example, a function takes in a parameter "gluonConfigDir" (internal/services/imapsmtpserver/imap.go newIMAPServer). But we pass in a variable called "gluonDataDir" in internal/services/imapsmtpserver/service.go createIMAPServer L441.

Similarly, on internal/services/imapsmtpserver/imap.go newIMAPServer L116 we call gluon.New with its "DataDir" set to the variable gluonCacheDir.

Then, inside of github.com/protonmail/gluon/builder.go's build() method on L58, we are calling it the a "DataDir" but the error message says "failed to access or create local cache".


For context, my original homedir was sohum.mendon and has since changed to smendon.

It looks like it boils down to the following stack trace:

(dlv) bt
 0  0x00000001031493b0 in github.com/ProtonMail/proton-bridge/v3/internal/vault.(*Vault).getUnsafe
    at ./internal/vault/vault.go:397
 1  0x00000001031491f0 in github.com/ProtonMail/proton-bridge/v3/internal/vault.(*Vault).getSafe
    at ./internal/vault/vault.go:387
 2  0x00000001031403b0 in github.com/ProtonMail/proton-bridge/v3/internal/vault.(*Vault).GetGluonCacheDir
    at ./internal/vault/settings.go:87
 3  0x00000001035d7b94 in github.com/ProtonMail/proton-bridge/v3/internal/bridge.(*Bridge).GetGluonCacheDir
    at ./internal/bridge/settings.go:125
 4  0x00000001035d6d04 in github.com/ProtonMail/proton-bridge/v3/internal/bridge.(*bridgeIMAPSettings).CacheDirectory
    at ./internal/bridge/imap.go:109
 5  0x000000010357d138 in github.com/ProtonMail/proton-bridge/v3/internal/services/imapsmtpserver.(*Service).createIMAPServer
    at ./internal/services/imapsmtpserver/service.go:441
 6  0x0000000103578ea4 in github.com/ProtonMail/proton-bridge/v3/internal/services/imapsmtpserver.(*Service).Init
    at ./internal/services/imapsmtpserver/service.go:92
 7  0x00000001035ca980 in github.com/ProtonMail/proton-bridge/v3/internal/bridge.newBridge

The encrypted data structure has the problem. It looks like this (fields omitted for privacy & brevity):

> github.com/ProtonMail/proton-bridge/v3/internal/vault.(*Vault).GetGluonCacheDir() ./internal/vault/settings.go:87 (PC: 0x1031403b0)
Values returned:
        ~r0: github.com/ProtonMail/proton-bridge/v3/internal/vault.Data {
                Settings: github.com/ProtonMail/proton-bridge/v3/internal/vault.Settings {
                        GluonDir: "/Users/sohum.mendon/Library/Application Support/protonmail/bridge-v3/gluon",
                        IMAPPort: 1143,
                        SMTPPort: 1025,
                        IMAPSSL: false,
                        SMTPSSL: true,

...

Later on, during the flow for newIMAPServer in internal/services/imapsmtpserver/imap.go:114, gluon.New is called, which ultimately calls serverBuilder.build in gluon/builder.go:60, which calls os.MkDirTemp(), which ends up failing (as the directory doesn't exist, and you need root-level permissions to create).

The problematic part here is that the GluonDir property was created with my previous home directory, but that of course no longer exists.

Other locations, like the gluonDataDir don't pull the path from the encrypted vault. Their stack trace looks like:

0  0x0000000102ad35ac in path/filepath.Join
   at /opt/homebrew/Cellar/go/1.22.5/libexec/src/path/filepath/path.go:263
1  0x0000000102b31b08 in github.com/ProtonMail/proton-bridge/v3/internal/locations.(*Locations).getGluonDataPath
   at ./internal/locations/locations.go:214
2  0x0000000102b314cc in github.com/ProtonMail/proton-bridge/v3/internal/locations.(*Locations).ProvideGluonDataPath
   at ./internal/locations/locations.go:154
3  0x00000001035d7c18 in github.com/ProtonMail/proton-bridge/v3/internal/bridge.(*Bridge).GetGluonDataDir
   at ./internal/bridge/settings.go:129
4  0x00000001035d6d80 in github.com/ProtonMail/proton-bridge/v3/internal/bridge.(*bridgeIMAPSettings).DataDirectory
   at ./internal/bridge/imap.go:113

The Locations struct looks like:

*github.com/ProtonMail/proton-bridge/v3/internal/locations.Locations {
        userConfig: "/Users/smendon/Library/Application Support/protonmail/bridge-v3",
        userData: "/Users/smendon/Library/Application Support/protonmail/bridge-v3",
        userCache: "/Users/smendon/Library/Caches/protonmail/bridge-v3",
        configName: "bridge-v3",
        configGuiName: "bridge-v3-gui",}