quexten / goldwarden

A feature-packed Bitwarden compatible desktop client
MIT License
749 stars 25 forks source link

Browser Biometrics don't work #15

Closed c4tz closed 10 months ago

c4tz commented 10 months ago

Hey, its me again!

I think the browser biometrics do not work in goldwarden (in contrast to bw-bio-handler, where they work flawlessly).

One part of the problem could be (just a guess, though) that you set the AppID to com.8bit.bitwarden here, but to com.quexten.bw-bio-handler here.

But sadly, this doesn't seem to fix it for me, the BW chromium addon always tells me that "the browser integration in the Bitwarden Desktop app has not been activated", which is why I didn't open a PR for this yet.

Do you maybe have an idea what else the underlying problem could be?

quexten commented 10 months ago

Thanks once again for the report. For me - in Firefox - it seems to work on the latest version, but I will try to figure out what's going on. It's been a while since I reverse-engineered the communication so I don't recall the edge cases too well.

But sadly, this doesn't seem to fix it for me, the BW chromium addon always tells me that "the browser integration in the Bitwarden Desktop app has not been activated", which is why I didn't open a PR for this yet.

Does bw-bio-handler work in this case? (Just want to rule out that chromium is snap or flatpak, which do not work with either tool or the official desktop app due to sandboxing)

quexten commented 10 months ago

Also: Is goldwarden runnning as a daemon (f.e using systemd since you are on arch - this is not auto activated on setup), and if so are there any logs? (If setup using goldwarden setup, then you can get the logs with: journalctl --user -u goldwarden, but of course feel free to censor out any personal data - should there be any (usually this should not be logged).

c4tz commented 10 months ago

Is goldwarden runnning as a daemon (f.e using systemd since you are on arch - this is not auto activated on setup), and if so are there any logs?

I'm running chromium on arch. The systemd service is running as the same user chromium runs with. Hmm, the logs seem to be confusing to me. Have a look at the end, especially. I restarted the daemon and tried to activate biometrics in the chromium addon (again) with the same result as before, but there is no crash and no Warning, like before: https://pastebin.com/wxkFhmHc

Does bw-bio-handler work in this case? (Just want to rule out that chromium is snap or flatpak, which do not work with either tool or the official desktop app due to sandboxing)

Yes, that's what made wonder in the first place. I tried it out yesterday and it worked flawlessly. I even wanted to contribute an AUR pkg for it until I found out about goldwarden :grin:

quexten commented 10 months ago

Thanks, that log is very helpful. So the websocket warnings at the end are annoying, but unrelated. I only test against vaultwarden, since that's what I use. I'm guessing you are on the official server or self hosted official server and it has some slightly different messages?

Either way, that's untrelated. For the actual problem of the first time starting the service:

Dez 21 16:00:47 pc goldwarden[3400]: unexpected fault address 0x7f2300006fe0 Dez 21 16:00:47 pc goldwarden[3400]: fatal error: fault Dez 21 16:00:47 pc goldwarden[3400]: [signal SIGSEGV: segmentation violation code=0x2 addr=0x7f2300006fe0 pc=0x55b027958ea4] Dez 21 16:00:47 pc goldwarden[3400]: goroutine 171 [running]: Dez 21 16:00:47 pc goldwarden[3400]: runtime.throw({0x55b027f38621?, 0x50?}) Dez 21 16:00:47 pc goldwarden[3400]: runtime/panic.go:1077 +0x5e fp=0xc0006c2ce0 sp=0xc0006c2cb0 pc=0x55b0279254be Dez 21 16:00:47 pc goldwarden[3400]: runtime.sigpanic() Dez 21 16:00:47 pc goldwarden[3400]: runtime/signal_unix.go:875 +0x285 fp=0xc0006c2d40 sp=0xc0006c2ce0 pc=0x55b02793ba05 Dez 21 16:00:47 pc goldwarden[3400]: runtime.memclrNoHeapPointers() Dez 21 16:00:47 pc goldwarden[3400]: runtime/memclr_amd64.s:182 +0x224 fp=0xc0006c2d48 sp=0xc0006c2d40 pc=0x55b027958ea4 Dez 21 16:00:47 pc goldwarden[3400]: github.com/awnumar/memguard/core.Wipe(...) Dez 21 16:00:47 pc goldwarden[3400]: github.com/awnumar/memguard@v0.22.3/core/crypto.go:101 Dez 21 16:00:47 pc goldwarden[3400]: github.com/awnumar/memguard.(LockedBuffer).Wipe(0xc000226000) Dez 21 16:00:47 pc goldwarden[3400]: github.com/awnumar/memguard@v0.22.3/buffer.go:331 +0x9f fp=0xc0006c2db8 sp=0xc0006c2d48 pc=0x55b027a48f9f Dez 21 16:00:47 pc goldwarden[3400]: github.com/quexten/goldwarden/agent/config.(Config).Lock(0xc000656160) Dez 21 16:00:47 pc goldwarden[3400]: github.com/quexten/goldwarden/agent/config/config.go:142 +0xd7 fp=0xc0006c2e30 sp=0xc0006c2db8 pc=0x55b027b6d637

For memory protection, goldwarden uses the memguard library. This seems to be causing problems here. I've seen 2 circumstances under which this happens; running in the go debugger debugger (due to an unresolved bug in a dependency) or running on different architectures (since you are on regular arch, I'm guessing you are on x86_64 should be fine). If you are running under the debugger, the temporary solution is to run the debugger as root or setting the suid bit and chowning it to root.

If neither of the above is the case, then there is a different issue that's causing a conflict with the memory lockdown here. In that case I will go digging deeper, but might just add a no memory lockdown mode as a solution for cases like this.

On the second time the service was started in your logs - 16:23:08 - it seems to not have encountered any memguard related issues, did you attempt to setup biometrics then? (If so, the memguard issue might be entirely unrelated for this specific issue. Since I'm not seeing anything biometrics related in the logs of the second run, this might be the case)

Could you also post your ~/.config/chromium/NativeMessagingHosts/com.8bit.bitwarden.json

c4tz commented 10 months ago

I'm guessing you are on the official server or self hosted official server and it has some slightly different messages?

Yes, I'm using the official BW (EU) servers.

running in the go debugger debugger (due to an unresolved bug in a dependency) or running on different architectures (since you are on regular arch, I'm guessing you are on x86_64 should be fine). If you are running under the debugger, the temporary solution is to run the debugger as root or setting the suid bit and chowning it to root.

Ah yes, I ran a go build . in the git root of goldwarden and cped the resulting bin to /usr/bin/ when I wanted to test my first guess (what I wrote in the first post). This should have embedded the debug info in the binary, right? So this might be why we see this. But: I now re-installed from the AUR, restarted the goldwarden systemd service, unlocked the vault and can see the same segfault (with the same address, even) in the logs.

Also, I'm running on x86_64 with the latest kernel:

$ uname -a
Linux pc 6.6.7-arch1-1 #1 SMP PREEMPT_DYNAMIC Thu, 14 Dec 2023 03:45:42 +0000 x86_64 GNU/Linux

Could you also post your ~/.config/chromium/NativeMessagingHosts/com.8bit.bitwarden.json

$ cat ~/.config/chromium/NativeMessagingHosts/com.8bit.bitwarden.json                                                                       01:33
{
        "name": "com.8bit.bitwarden",
        "description": "Bitwarden desktop <-> browser bridge",
        "path": "/usr/bin/goldwarden",
        "type": "stdio",
        "allowed_origins": [
          "chrome-extension://nngceckbapebfimnlniiiahkandclblb/",
          "chrome-extension://jbkfoedolllekgbhcbcoahefnbanhhlh/",
          "chrome-extension://ccnckbpmaceehanjmeomladnmlffdjgn/"
        ]
  }
quexten commented 10 months ago

Ah yes, I ran a go build . in the git root of goldwarden and cped the resulting bin to /usr/bin/ when I wanted to test my first guess (what I wrote in the first post). This should have embedded the debug info in the binary, right? So this might be why we see this. But: I now re-installed from the AUR, restarted the goldwarden systemd service, unlocked the vault and can see the same segfault (with the same address, even) in the logs.

No, that's entirely fine, the bug (https://github.com/awnumar/memguard/issues/144) seems to be related to using delve to debug (f.e if you run it in an IDE with breakpoints), but also occurs under some other conditions. Running go build and using that binary should not result in this issue. Adding a mode that does not use memguard might already resolve your issue. I will investigate this.

This also reminds me to add a status command to inspect vault status (there is no good way to see if your vault actually unlocks and syncs correctly right now I think), and some more debug logs.

One more request: Could you run cat ~/.config/goldwarden.json | jq and check that it has the structure:

{
  "IdentityUrl": "URL_HERE",
  "ApiUrl": "URL_HERE",
  "NotificationsUrl": "URL_HERE",
  "DeviceUUID": "UUID_HERE",
  "ConfigKeyHash": "HEX_STRING_HERE",
  "EncryptedToken": "BASE64_TEXT_HERE",
  "EncryptedUserSymmetricKey": "BASE64_TEXT_HERE",
  "EncryptedMasterPasswordHash": "BASE64_TEXT_HERE",
  "EncryptedMasterKey": "BASE64_TEXT_HERE"
}

(Needless to say, do not post the config, even though it is encrypted).

c4tz commented 10 months ago

No, that's entirely fine, the bug is related to using delve to debug (f.e if you run it in an IDE with breakpoints). Running go build and using that binary should not result in this issue.

Ah, okay! Good to know.

One more request: Could you run cat ~/.config/goldwarden.json | jq and check that it has the structure:

Yes, the structure seems to be right.

Thank you for investigating this! :smile:

quexten commented 10 months ago

@c4tz Could you check with https://github.com/quexten/goldwarden/pull/16 ?

Specifically, after installing it, you should also update your ~/.config/systemd/user/goldwarden.service and add: Environment="GOLDWARDEN_NO_MEMGUARD=true"

The updated version should also have more logs relevant here to see if the biometrics request is reaching the daemon, or if there is some IPC issue to the browser extension.

quexten commented 10 months ago

Additionally, when the daemon is active try running: goldwarden vault unlock and then goldwarden vault status

This will show whether the daemon was able to sync and decrypt the ciphers correctly.

c4tz commented 10 months ago

Okay, I did what you wrote plus: I locked and unlocked the vault once again and afterwards tried to connect the BW Browser extension again.

Results:

Thank you again for your work on this! :)

quexten commented 10 months ago

Ok, so your vault unlocked correctly, what's not working is the Browser<->Goldwarden[Client-browserbiometrics] part, or the Goldwarden[Client-browserbiometrics]<->Goldwarden[Agent] part since this is missing:

[INF] [12:45] [Goldwarden > Actions] >>> Browser Biometrics: Key requested, verifying biometrics...
[INF] [12:45] [Goldwarden > Biometrics] >>> Checking biometrics for com.quexten.goldwarden.browserbiometrics
[INF] [12:45] [Goldwarden > Biometrics] >>> Biometrics result: true
[INF] [12:45] [Goldwarden > Actions] >>> Browser Biometrics: Biometrics verified, asking for approval...
[INF] [12:45] [Goldwarden > Pinentry] >>> Asking for approval |Approve Credential Access|quexten on gnome-shell>firefox-bin>goldwarden is trying to access your vault encryption key for browser biometric unlock.|
[INF] [12:45] [Goldwarden > Pinentry] >>> Got approval from user
[INF] [12:45] [Goldwarden > Actions] >>> Browser Biometrics: Approved, getting key...
[INF] [12:45] [Goldwarden > Actions] >>> Browser Biometrics: Sending key...

(from my agent's logs when unlocking).

Just to make sure, did you copy the updated build to "/usr/bin/goldwarden (or alternatively update ~/.config/chromium/NativeMessagingHosts/com.8bit.bitwarden.json to point to the current build)?

Otherwise, I'll add logging to the browserbiometrics component to debug this further.

c4tz commented 10 months ago

Yes, I copied the newly built binary to /usr/bin/ before I did all that. (Else I would also have to point the systemd service to it, right?)

The error in the browser extension also is displayed almost instantly, so I guess it doesn't even call the binary? Even though the path is correct in the native messaging host config :thinking:

quexten commented 10 months ago

Added logging to the [Client-browserbiometrics] part too now. This has to be stored separately, specifically in /tmp/DELETE_ME.log but it should clear up what's going on. Beware there are some sensitive parts in the log, I've made it so the ones to specifically pay attention to are marked as SENSITIVE in the log, but there might be other parts. Just make sure not to post any encryption keys accidentally :)

Also, when testing, please fully kill chrome after rebuilding. On Firefox, the process seems to keep the goldwarden instance used for IPC around for a while.

c4tz commented 10 months ago

Hmm, I re-built the binary with your new commits, unlocked the vault, killed chomium, re-started it and re-tried activating biometrics in the BW extension.

The systemd unit has these logs (again):

$ journalctl --user-unit goldwarden
Dez 22 16:01:49 pc systemd[1223]: Started "Goldwarden daemon".
Dez 22 16:01:49 pc goldwarden[23688]: [INF] [16:01] [Goldwarden > Keyring] >>> Creating new memory keyring
Dez 22 16:01:49 pc goldwarden[23688]: [INF] [16:01] [Goldwarden > Agent] >>> Agent listening on /home/c4tz/.goldwarden.sock...
Dez 22 16:01:49 pc goldwarden[23688]: [INF] [16:01] [Goldwarden > SSH] >>> SSH Agent listening on /home/c4tz/.goldwarden-ssh-agent.sock
Dez 22 16:02:16 pc goldwarden[23688]: [INF] [16:02] [Goldwarden > Pinentry] >>> Asking for pin |Unlock Goldwarden|Enter the vault PIN|
Dez 22 16:02:18 pc goldwarden[23688]: [INF] [16:02] [Goldwarden > Pinentry] >>> Got pin from user
Dez 22 16:02:19 pc goldwarden[23688]: [INF] [16:02] [Goldwarden > Keyring] >>> Unlocking keyring with account key
Dez 22 16:02:19 pc goldwarden[23688]: [INF] [16:02] [Goldwarden > Auth] >>> Refreshing token
Dez 22 16:02:19 pc goldwarden[23688]: [INF] [16:02] [Goldwarden > Auth] >>> Token refreshed
Dez 22 16:02:19 pc goldwarden[23688]: [INF] [16:02] [Goldwarden > Bitwarden API] >>> Performing full sync...
Dez 22 16:02:19 pc goldwarden[23688]: [INF] [16:02] [Goldwarden > Bitwarden API] >>> Sync successful, initializing keyring and vault...
Dez 22 16:02:19 pc goldwarden[23688]: [INF] [16:02] [Goldwarden > Bitwarden API] >>> Reading  1 org keys...
Dez 22 16:02:19 pc goldwarden[23688]: [INF] [16:02] [Goldwarden > Bitwarden API] >>> Initializing keyring from user symmetric key...
Dez 22 16:02:19 pc goldwarden[23688]: [INF] [16:02] [Goldwarden > Keyring] >>> Unlocking keyring with account key
Dez 22 16:02:19 pc goldwarden[23688]: [INF] [16:02] [Goldwarden > Bitwarden API] >>> Clearing vault...
Dez 22 16:02:19 pc goldwarden[23688]: [INF] [16:02] [Goldwarden > Bitwarden API] >>> Adding 196 ciphers to vault...
Dez 22 16:02:20 pc goldwarden[23688]: [INF] [16:02] [Goldwarden > Websocket] >>> Connected to websocket server...
Dez 22 16:02:35 pc goldwarden[23688]: [WRN] [16:02] [Goldwarden > Websocket] >>> Invalid message received, length too short
Dez 22 16:02:51 pc goldwarden[23688]: [WRN] [16:02] [Goldwarden > Websocket] >>> Invalid message received, length too short
Dez 22 16:03:06 pc goldwarden[23688]: [WRN] [16:03] [Goldwarden > Websocket] >>> Invalid message received, length too short
[... about 50 more of the same message]

but /tmp/DELETE_ME.log is still empty. That endorses my theory of chromium not even calling goldwarden in the first place. But how can this be, if bw-bio-handler works and I didn't upgrade chromium inbetween (just verified this in my pacman logs)?

c4tz commented 10 months ago

Just did a strace for chromium while trying again:

$ sudo strace -f -p 30002 2>&1 | grep warden                                                                 x  04:34
[pid 30018] access("/home/c4tz/.config/chromium/NativeMessagingHosts/com.8bit.bitwarden.json", F_OK <unfinished ...>
[pid 30018] openat(AT_FDCWD, "/home/c4tz/.config/chromium/NativeMessagingHosts/com.8bit.bitwarden.json", O_RDONLY|O_CLOEXEC <unfinished ...>
[pid 30018] <... read resumed>"{\n\t\"name\": \"com.8bit.bitwarden\","..., 4096) = 343
[pid 30018] access("/usr/bin/goldwarden", F_OK <unfinished ...>
[pid 33371] execve("/usr/bin/goldwarden", ["/usr/bin/goldwarden", "chrome-extension://nngceckbapebf"...], 0x1834023e85a0 /* 56 vars */) = 0
[pid 33371] write(2, "Run 'goldwarden --help' for usag"..., 35) = 35
[pid 30022] <... read resumed>"33371 (goldwarden) Z 30002 30002"..., 4096) = 179

it seems that chromium sends some wrong arguments/commands to goldwarden, as far as I can interpret this log.

quexten commented 10 months ago

Oh, this is very helpful! Goldwarden expects a different argument order, maybe something about chromium changed since I implemented this. The code for detecting goldwarden being called by chromium/firefox as an IPC proxy is:

if len(os.Args) > 1 && strings.Contains(os.Args[1], "com.8bit.bitwarden.json") {
    browserbiometrics.Main()
    return
}

So this would not detect what you posted above. Will test and fix in a bit.

quexten commented 10 months ago

Pushed a fix to the pr now and tested on a chromium installation, can you test if it works for you on the latest version of the PR?

c4tz commented 10 months ago

Yes! It works! :tada: Thank you for the ultra-fast solving!

So just for me to understang: something changed with the way chromium calls the native app? Why did bw-bio-handler still work, then?

quexten commented 10 months ago

To be honest, I'm not sure if chromium changed, or if I just didn't test on chromium on goldwarden. When writing bw-bio-hander, I tested both chromium and Firefox.

So the difference between Firefox and chromium seems to be the arguments it calls the IPC binary with. Where Firefox supplies the appid, chromium supplies "chrome-extension://...". On bw-bio-handler this was not an issue, since it did not care about any arguments it got (since these don't matter). For goldwarden, there is no separate binary dedicated to ipc, instead the regular CLI client just detects being called by the browser by checking the arguments, and then runs a modified version of bw-bio-handler under the hood, that communicates with the goldwarden agent instead of using a secret stored via libsecret. This detection of being called by the browser seems to have only detected Firefox and not chromium.

Also, thanks for the help tracking this bug down :)

c4tz commented 10 months ago

Ahh, ok! That makes perfect sense, now that you explained it. :bulb:

So this would be something you would also have to keep in mind if you someday want to support other browsers, too. Btw, during my research yesterday I came across this useful list of NativeMessagingHost-paths and just now thought you might need it in the aforementioned case. This is also where I got the strace command from :wink:

Thank you again for your work and have wonderful holidays! :christmas_tree:

quexten commented 10 months ago

Thanks for the list. At the moment, bw-bio-hander and Goldwarden just recursively search from ~/.config/ and ~/.mozilla/ for any native messaging hosts folders. For most chomium-like browsers this works fine, but something like librewolf, waterfox, or something on mac/windows would not be detected yet. Though either way it's more than the official desktop client detects (it just has a preset list of a few browsers).

Wonderful holidays to you too!