Page MenuHome GnuPG

Add Win32-OpenSSH support to gpg-agent's ssh-agent
Open, NormalPublic

Assigned To
Authored By
Apr 7 2018, 12:59 AM
"Mountain of Wealth" token, awarded by gpguser123."Love" token, awarded by avemilia."Love" token, awarded by nicolaslegland."Love" token, awarded by emmedve1.


The OpenSSH port shipping with new versions of Windows uses Windows named pipes for interprocess communication. The enable-ssh-support option for gpg-agent should be extended on Windows to support named pipes in addition to Cygwin/MSYS emulation of Unix sockets, or a new option should be added to Windows for this, so that "native" ssh client can be used instead of requiring Cygwin ssh client or PuTTY.

Event Timeline

werner triaged this task as Normal priority.Apr 9 2018, 10:25 AM
werner added a subscriber: werner.

Thanks for the pointer. But as long as the Windows ssh server is that instable I see no urgent need to add this to GnuPG.

BTW, can you confirm that gpg-agent works with the Cygwin SSH? IIRC, I once added a hack to allow for this but never thoroughly tested it.

I would argue that the Windows port of OpenSSH is not unstable at this point, especially given that Microsoft is even providing it as an installable feature in the next regular Windows 10 release. The fact that the port is now using actual OpenSSH version numbers instead of their own 0.x versions lends credence to this as well.

As for Cygwin, it's been so long since I needed to use the Cygwin or MSYS builds of the OpenSSH client that I didn't even realize I still had it installed. However, after checking with both latest version of Cygwin and latest 64-bit MSYS2, gpg-agent doesn't work with their ssh client packages. Trying to use the S.gpg-agent.ssh "socket" results in this error message when attempting to access the agent via ssh, ssh-add, etc.:

Error connecting to agent: Bad file descriptor

Rhat's for the client, right. I never used it. We used to run a Windows 8 instance in a VM to run tests via ssh on it. That worked most not really stable. For obvious reasons I am more interested in the server part ;-)

The Cygwin thing was a quick and untested hack. I don't think it makes much sense to follow up on this. Better to support the native ssh thing.

I've been working with one of Microsoft's developers on a temporary tool that should bridge the connection between named pipes and the Unix sockets emulation used by gpg-agent but things appear to trip up with sending the nonce. From the position of the tool, the nonce value is successfully sent (send returns 16), but never seems to be picked up by gpg-agent. Instead both gpg-agent and the bridge sit there until whatever tool is using them (I test using ssh-add -l) is terminated, at which point gpg-agent immediately spits up the message

gpg-agent[16064]: error reading nonce on fd 660: Input/output error

(PID and FD variable, of course.)

@werner After sending the nonce value from the socket file, does anything need to be read back before ssh-agent commands can be sent? Are there any byte ordering requirements for sending the nonce or can they be sent in the same order as they are in the file?

The nonce is a string of octets thus it needs to be passed verbatim. I would need to study the code in libassun/src/assuan-socket.c to tell more.

I just took a look through assuan-socket.c and it appears that we just need to send the nonce and don't need to read anything back. We also found a bug on our side that was preventing the nonce from being sent, which has been fixed. The error message logged above no longer happens.

Now however, as soon as the nonce is sent across, we get log messages like

gpg-agent[32944]: ssh handler 0x3 for fd 844 started
gpg-agent[32944]: ssh handler 0x3 for fd 844 terminated

It appears that the actual ssh-agent message coming across the bridge is never read or acted upon, but the socket connection isn't closed despite the log message stating that the handler is terminated.

@werner I was hoping to make a modified gpg-agent build that would let me walk through what's going on after the nonce is sent but it looks like the gpg4win process only takes in a package of pre-built gpg binaries which rules that out. As far as I can figure out, after the nonce is read and accepted, libassuan creates a stream object out of the socket and then finding nothing in the stream terminates the ssh handler. We send the actual client request immediately after the nonce but in a separate call to send() so I now wonder if by not having anything read in at the same time as the nonce gpg-agent or libassuan thinks that it's a 0-length stream.

Although I don't use the ssh client on Windows I had to integrate the Windows ssh server into our release process (GlobalSign sent us a Windows-only token, for the new cert and so we can't anymore use osslsigncode). The ssh server is really stable and so it makes a lot of sense to better integrate our ssh-agent into Windows.

I need to look into their named pipes IPC - I once ruled that out for Windows because it is not possible to limit connections to the local machine.

In the meantime you can use [0]. I have tested with ssh key on yubikey and AuthenticationMethods publickey, win32-ssh (or ssh-portable, which is the new repository name) correctly works with gpg and pinentry is called. Despite it being called wsl, wsl environment is not required.


I'm actually trying to do the following:

I have 2 Windows PCs at home: Laptop and Desktop.

I'm using Windows' native OpenSSH client and server so I can connect to my desktop using my laptop.

I want to edit a file while on SSH that's placed on my desktop, and then run git commit so I can save my work.

The problem is my Git is configured to ask for a GPG key, that has a password. Since I'm over SSH, the GnuPG window asking for such password can't be rendered and my Desktop gets stuck at this step.

What I'm looking for is a way to forward this password prompt to my laptop, where I can then sign my commit through SSH.

Is such a thing possible? And does WSL SSH Pageant work for the process I mentioned?

P.S.: local commit signing (without SSH connections) is working on both machines, they both have the same GPG keys and config for Git and GnuPG.

P.S.²: I never used any graphical GPG client (Pageant, gpg4win, etc), I just use GPG to sign Git Commits through the CLI.

@bvieira You need to set pinentry-mode=loopback for gpg program used in git.

On unix systems GPG_TTY=$(tty) makes it work. But not sure on windows how this logic is handled.

So you might have to use git --config global gpg.Program and try passing pinentry-mode. Not sure if you can pass arguments to it directly, otherwise might have to create a wrapper batch file.

Unfortunately you can't pass extra arguments.

loopback mode won't help; it is simply that we don't support the integrated OpenSSH yet. The Putty support uses a different IPC mechanism than our inter-GnuPG-IPC which is again different from OpenSSH for Windows.

So, if there's no support for native OpenSSH yet, I'll wait for it. After it's supported, I should be able to get the scenery I described working, right?

@werner can you confirm if the environment I provided will work with OpenSSH support fully implemented?

I wrote to simplify usage on Windows until this issue is resolved - it handles various edge cases on Windows.