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

Description

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.

gpoul added a subscriber: gpoul.Apr 9 2018, 8:29 AM
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.