The built-in SSH transport currently only supports socket connections directly to a remote host. I'm attempting to write support for Krypton (https://krypt.co) to work with libgit2, but the lack of ProxyCommand (which Krypton uses to perform its operations), means this is a bit of a non-starter unless:
- I write my own custom transport, reimplementing all features of it on top of libssh2 again
- The built-in transport is amended to support delegating to the host app for ProxyCommand-like behaviors
I'd prefer not to do the former, as that means not using the already great built-in SSH transport. With that in mind, here are some thoughts for how hooks to support ProxyCommand could be implemented in the library.
From my (limited) knowledge, OpenSSH-style ProxyCommand works, on Unix at least, by starting a subprocess by shell command (either via fork-exec or another method), setting up a socket between the host and subprocess via stdio, and passing all traffic into and out of that subprocess's socket as if it were the remote socket created for normal SSH operations. Krypton also works this way, using its krssh executable, which is a wrapper around ssh.
This is obviously all very specific to Posix, and implemented differently on Windows, and not supported at all on iOS due to the lack of multiprocess support. Also, most of ProxyCommand's details are stored in a user's SSH config file, and as such, it's unlikely that the libgit2 library wants to handle anything that specific: SSH config files, exec'ing processes, etc.
With that in mind, the SSH transport currently creates its socket using git_socket_stream_new, passing it the expected host and port. A very simple option is to create a callback that asks the host application to create the socket for libgit2 before this, taking the host and port as arguments, and returning the file descriptor to be used by the libssh2 implementation. This would allow the host app to perform the actual socket creation, or pass through to fall back on the default behavior. The library would not need to handle ProxyCommand-related cross-platform issues. Since the socket is just a file descriptor either way, libssh2 likely doesn't care?
This does, however, introduce a remote callback that is very specific to the SSH transport. I've been thinking about better ways to abstract this operation out (similar to how credential callbacks work, as those have SSH-specific functionality), but have not come up with anything concrete, as this is a very specific case related mostly to just SSH over the other transport types.
I'd love to hear the project contributors' thoughts on how best something like this should be implemented. I'm happy to work on it, but definitely wanted to propose everything and get some feedback before I got started making API-related changes to a fork of the project.
Thanks!
Version of libgit2 (release number or SHA1)
Currently I am at tag 0.27.0.
Operating system(s) tested
macOS 10.14
The built-in SSH transport currently only supports socket connections directly to a remote host. I'm attempting to write support for Krypton (https://krypt.co) to work with libgit2, but the lack of ProxyCommand (which Krypton uses to perform its operations), means this is a bit of a non-starter unless:
I'd prefer not to do the former, as that means not using the already great built-in SSH transport. With that in mind, here are some thoughts for how hooks to support ProxyCommand could be implemented in the library.
From my (limited) knowledge, OpenSSH-style ProxyCommand works, on Unix at least, by starting a subprocess by shell command (either via fork-exec or another method), setting up a socket between the host and subprocess via stdio, and passing all traffic into and out of that subprocess's socket as if it were the remote socket created for normal SSH operations. Krypton also works this way, using its
krsshexecutable, which is a wrapper aroundssh.This is obviously all very specific to Posix, and implemented differently on Windows, and not supported at all on iOS due to the lack of multiprocess support. Also, most of ProxyCommand's details are stored in a user's SSH config file, and as such, it's unlikely that the
libgit2library wants to handle anything that specific: SSH config files, exec'ing processes, etc.With that in mind, the SSH transport currently creates its socket using
git_socket_stream_new, passing it the expected host and port. A very simple option is to create a callback that asks the host application to create the socket forlibgit2before this, taking the host and port as arguments, and returning the file descriptor to be used by the libssh2 implementation. This would allow the host app to perform the actual socket creation, or pass through to fall back on the default behavior. The library would not need to handle ProxyCommand-related cross-platform issues. Since the socket is just a file descriptor either way, libssh2 likely doesn't care?This does, however, introduce a remote callback that is very specific to the SSH transport. I've been thinking about better ways to abstract this operation out (similar to how credential callbacks work, as those have SSH-specific functionality), but have not come up with anything concrete, as this is a very specific case related mostly to just SSH over the other transport types.
I'd love to hear the project contributors' thoughts on how best something like this should be implemented. I'm happy to work on it, but definitely wanted to propose everything and get some feedback before I got started making API-related changes to a fork of the project.
Thanks!
Version of libgit2 (release number or SHA1)
Currently I am at tag 0.27.0.
Operating system(s) tested
macOS 10.14