msys2-runtime icon indicating copy to clipboard operation
msys2-runtime copied to clipboard

Please consider POSIXifying the `GNUPGHOME` variable

Open chawyehsu opened this issue 6 months ago • 14 comments

Context

GNUPGHOME is an environment variable used by gnupg, which allows users to change the home directory of gpg. gnupg for Windows is an official build that supports changing the home directory using GNUPGHOME in the form of C:\Users\user\.gnupg. In the community however, some tools such as git-for-windows, package a gnupg build based on MSYS2 and rely on the msys2-runtime and only supports parsing and using GNUPGHOME in the form of /c/Users/user/.gnupg to change the home directory.

Why

Under certain conditions, users may actively or passively install multiple editions of gnupg, including the two different gnupg mentioned above. When they want to share the same gnupg home directory across different gnupg builds, they may use the GNUPGHOME variable. However, due to different interpretations of the GNUPGHOME variable, this goal cannot be achieved. This has been discussed in the gnupg mailing list [1][2], and similar issues have also been reported in the git-for-windows issue tracker [3][4]. Specifically, when users set GNUPGHOME=C:\Users\user\.gnupg or GNUPGHOME=C:/Users/user/.gnupg, the gnupg based on msys2-runtime will be unable to use this variable and will report an error.

$ gpgconf.exe -L
sysconfdir:/etc/gnupg
bindir:/usr/bin
libexecdir:/usr/lib/gnupg
libdir:/usr/lib/gnupg
datadir:/usr/share/gnupg
localedir:/usr/share/locale
socketdir:C%3a\Users\user\.gnupg
dirmngr-socket:C%3a\Users\user\.gnupg/S.dirmngr
keyboxd-socket:C%3a\Users\user\.gnupg/S.keyboxd
agent-ssh-socket:C%3a\Users\user\.gnupg/S.gpg-agent.ssh
agent-extra-socket:C%3a\Users\user\.gnupg/S.gpg-agent.extra
agent-browser-socket:C%3a\Users\user\.gnupg/S.gpg-agent.browser
agent-socket:C%3a\Users\user\.gnupg/S.gpg-agent
homedir:C%3a\Users\user\.gnupg

Proposal

Propose to POSIXify the GNUPGHOME variable, similar to the way of handling SHELL implemented by @dscho in [5]. Such a proposal was also mentioned in the comments [6]. I can draft a pull-request or patch if this is reasonable.

chawyehsu avatar Jul 04 '25 14:07 chawyehsu

I can draft a pull-request or patch if this is reasonable.

I think it is reasonable ;-)

dscho avatar Jul 04 '25 19:07 dscho

Given the insight that Win32 and Cygwin/MSYS2 gpg/gpg-agent cannot work with each other, I would be in favor of both closing this here ticket as well as https://github.com/msys2/msys2-runtime/pull/300 as "CANNOTFIX". What do you think @chawyehsu?

dscho avatar Jul 17 '25 16:07 dscho

Hi @dscho sorry for not following up after the pull-request was raised, as I didn't have time. Regarding @jeremyd2019's question in #300, I think your statement My thinking involved the keyring only, which should be able to be shared. is in line with my expectations, but I haven't had time to verify it yet. After raising #300 I have repalced with the patched msys-2.0.dll locally and found that msys2-gnupg can work fine with gnupg-win32 and share the same keyring (and sharing keyring is the main goal), they spawned different sockets in different locations to run two different gpg-agents though. However, this is just my superficial "testing", and I can't give a complete answer to jeremyd2019's question for the time being. If you think it'd be more appropriate to close the ticket, please do so. I believe I will come back to discuss with you when I have time. Thank you.

chawyehsu avatar Jul 17 '25 17:07 chawyehsu

they spawned different sockets in different locations

@chawyehsu that's interesting, could you fill in the details?

dscho avatar Jul 17 '25 17:07 dscho

found that msys2-gnupg can work fine with gnupg-win32 and share the same keyring (and sharing keyring is the main goal), they spawned different sockets in different locations to run two different gpg-agents though.

Right, my concern is that these agents would each assume they had exclusive use of the keyring and might corrupt things

jeremyd2019 avatar Jul 17 '25 17:07 jeremyd2019

that's interesting, could you fill in the details?

More specifically, msys2-gnupg spawned sockets in the GNUPGHOME but gnupg-win32 did not follow GNUPGHOME env var and spawned sockets in %LOCAL_APPDATA%. (I just found https://dev.gnupg.org/T5537)

Image

msys2-gnupg can work fine with gnupg-win32 and share the same keyring

From gpg --list-keys output, they do share the keyring.

And we can see two agents running.. (the one having the icon is gnupg-win32)

Image

But there was one issue I encoutered and did not have enough time to investigate is that the keyring may be locked by one of the two gnupg installs and the other will not be able to lock the keyring. I think this is @jeremyd2019 's concern?

I was going to review gnupg's codebase but I just did not have more time and put that on hold.

The above is all I know so far.

chawyehsu avatar Jul 17 '25 17:07 chawyehsu

@chawyehsu hmm. So https://dev.gnupg.org/T5537 says that the socket should not be created in the Roaming profile, which makes sense. What does not sense is that gpg misses when an overridden GNUPGHOME does not even point into the Roaming profile, and that might be "fixed" in the future, causing the S.gpg-agent sockets/files to clash. I believe that that is the actual concern, and it is a very valid one.

Likewise, I imagine that locking is done differently between the MSYS and the Win32 version of gpg.

So the more I think about it, the more I believe that POSIX-ifying that variable would be a mistake: It would essentially state officially that MSYS2 expects the MSYS and the Win32 versions to play nicely together, when we know for a fact that they don't and we also know that we cannot fix that.

dscho avatar Jul 17 '25 17:07 dscho

I think that what people who ask for this really want is to use win32 gpg instead of MSYS2 version (that's what I would want to do, if I did gpg-signed commits). I think removing the MSYS2 one (/usr/bin/gpg and maybe some other things if they also cause problems) would probably work in falling back to the gpg on the path from gpg4win. Much like is done with ssh

jeremyd2019 avatar Jul 17 '25 17:07 jeremyd2019

I in fact love @jeremyd2019 's proposal of having the option to remove the msys2-gnupg from GfW and be able to fall back to gnupg-win32/gpg4win which is the offical^1 supported distrubiton by the gnupg team. From my personal experience, I did often struggle with the built-in msys-gnupg when using GfW doing gpg-signed commits and had to specify an external gpg in gitconfig.

However, I have to point out that only providing the option in GfW would not eliminate the gap as this would still be exposed to downstream users through other software built upon MSYS2.^1 It's better than nothing though.

chawyehsu avatar Jul 17 '25 18:07 chawyehsu

I in fact love @jeremyd2019 's proposal of having the option to remove the msys2-gnupg from GfW and be able to fall back to gnupg-win32/gpg4win

It's not actually easy: https://github.com/git-for-windows/build-extra/pull/480. I'd welcome your work on that, if you can pull it off.

dscho avatar Jul 17 '25 18:07 dscho

I wasn't envisioning being quite as thorough as removing gnupg package and all its no-longer-needed dependencies. That's a pain without having the package manager around (and pacman has a dependency on gnupg).

D:\>git-sdk-64\usr\bin\pacman.exe -Rddns gnupg

Packages (6) libassuan-3.0.2-1  libksba-1.6.7-1  libnpth-1.8-1  nettle-3.10.2-1
             pinentry-1.3.1-2  gnupg-2.4.7-1

Total Removed Size:  11.64 MiB

jeremyd2019 avatar Jul 17 '25 19:07 jeremyd2019

The problem is that you kind of have to remove the dependencies because any other gpg.exe/gpg-agent.exe/etc might depend on (potentially different versions of) DLL files with the same filename.

dscho avatar Jul 20 '25 01:07 dscho

msys2 gpg would depend on msys- prefixed dlls while gpg4win/gnupg binaries are mingw and have lib prefixed dlls. More concerning to me would be a conflict with the files in /mingw64/bin (or /clangarm64/bin), the only one of those present in my git for windows install (x86_64) is zlib1.dll. gnupg seems to be 32-bit still, so it can't load the 64-bit zlib1.dll anyway.

jeremyd2019 avatar Jul 21 '25 19:07 jeremyd2019

msys2 gpg would depend on msys- prefixed dlls while gpg4win/gnupg binaries are mingw and have lib prefixed dlls. More concerning to me would be a conflict with the files in /mingw64/bin (or /clangarm64/bin), the only one of those present in my git for windows install (x86_64) is zlib1.dll. gnupg seems to be 32-bit still, so it can't load the 64-bit zlib1.dll anyway.

You're right, my recollection was incorrect. The problem was more the .exe files like gpg-agent.exe, dirmngr.exe and keyboxd.exe, and a vague suspicion that even .exe files outside of the gnupg package might interfere with the desired functionality; Keep in mind that Git for Windows' git.exe forcefully prepends its own /usr/bin/ to the PATH so that e.g. the Bash is found when Git wants to execute, say, aliases or hooks. This means that if gpg wants to auto-start any daemon and looks it up on the PATH, it might very well end up with a non-working or incompatible one if all we do is delete "just a few" gnupg-related files like gpg.exe.

dscho avatar Jul 22 '25 08:07 dscho