Commit Graph

15 Commits

Author SHA1 Message Date
brian m. carlson
8b4017dcbb
ssh: make strings translatable 2022-01-18 17:38:25 +00:00
brian m. carlson
a106dcb1e0
ssh: avoid using -- where possible
In Git LFS version 3.0, we added support for understanding the
GIT_SSH_VARIANT environment variable and its corresponding configuration
option.  When we did so, we dropped the special-casing for program names
and instead always used the -- setting for the default variant, "ssh".
This variant represents OpenSSH, which as a program with normal POSIX
option handling, supports -- just fine.

Unfortunately, not all clients do.  TeamCity's SSH client doesn't set
the variant and also doesn't understand --.  We need to handle this case
to prevent option injection in case someone tries to use a URL like
"ssh://-oProxyCommand=exploit/", which could otherwise lead to arbitrary
code execution.

However, we don't have to add this all the time, but only when the
user-and-host portion starts with a dash.  The reason is that the only
other place an attacker could inject an option is in the path, and the
path is not a separate option by itself.  The path is always preceded by
a command (either "git-lfs-authenticate" or "git-lfs-transfer" in a
single option that contains the name of the command, the path, and the
operation, separated by spaces.  As a result, option injection is not
possible in the path since those commands don't take options.

Note that Git just dies in this case with a message like so:

  fatal: strange hostname '-oProxyCommand=exploit' blocked

Let's adopt this approach of using -- less often so that we can more
gracefully deal with this case and fix some SSH clients, even if they
really should learn to understand this option.  Update the test binary
to expect the new results as well.

Since we're adjusting the end-of-options delimiter such that it's only
used for the default SSH variant and, in particular, only when the
user/host parameter starts with a "-" character, we still need to accept
that command argument format in our lfs-ssh-echo test helper program, so
we keep that logic, but also simplify our logic for parsing the
program's arguments so it will be, with luck, easier to maintain in the
future.

Note that we also remove the "$4" from one error message
because it's no longer the case that that error condition
always arises due to the fourth argument.

Co-authored-by: Chris Darroch <chrisd8088@github.com>
2021-11-30 20:20:58 +00:00
brian m. carlson
087db1de70
Set package version to v3
Since we're about to do a v3.0.0 release, let's bump the version to v3.

Make this change automatically with the following command to avoid any
missed items:

  git grep -l github.com/git-lfs/git-lfs/v2 | \
  xargs sed -i -e 's!github.com/git-lfs/git-lfs/v2!github.com/git-lfs/git-lfs/v3!g'
2021-09-02 20:41:08 +00:00
Chris Darroch
dd8e306e31 all: update go.mod module path with explicit v2
When our go.mod file was introduced in commit
114e85c2002091eb415040923d872f8e4a4bc636 in PR #3208, the module
path chosen did not include a trailing /v2 component.  However,
the Go modules specification now advises that module paths must
have a "major version suffix" which matches the release version.

We therefore add a /v2 suffix to our module path and all its
instances in import paths.

See also https://golang.org/ref/mod#major-version-suffixes for
details regarding the Go module system's major version suffix rule.
2021-08-09 23:18:38 -07:00
brian m. carlson
691de51161
t: test batch transfers with git-lfs-transfer
Add a test case to test batch transfers with git-lfs-transfer as well as
git-lfs-authenticate.  Label the test appropriately, so folks can
distinguish between them.
2021-07-20 19:16:00 +00:00
brian m. carlson
a0190a6020
lfshttp: don't strip off initial slash on SSH commands
When we process an SSH URL, we intentionally strip off the slash at the
beginning of the URL.  While that was convenient for
git-lfs-authenticate, it also prevents us from handling an absolute path
in git-lfs-transfer, since the path will have its leading slash stripped
off and will therefore be relative.

Instead, let's adopt Git's behavior, which is to not remove the leading
slash.  This is an incompatible change, but we're about to do a major
release, so it's a good time to make it.  This will affect both
git-lfs-transfer and git-lfs-authenticate commands, but at least GitHub
already supports the proper syntax.

Note that since we process the non-URL form of SSH remotes by converting
them to a URL and then parsing, let's strip off the leading slash when
we process that form, since there we do have the ability to distinguish
between absolute and relative paths.

Update the lfs-ssh-echo binary to handle this new format.
2021-07-20 19:16:00 +00:00
brian m. carlson
9c46a38281
ssh: support concurrent transfers using the pure SSH protocol
When using the pure SSH-based protocol, we can get much higher speeds by
multiplexing multiple connections on the same SSH connection.  If we're
using OpenSSH, let's enable the ControlMaster option unless
lfs.ssh.automultiplex is set to false, and multiplex these shell
operations over one connection.

We prefer XDG_RUNTIME_DIR because it's guaranteed to be private and we
can share many connections over one socket, but if that's not set, let's
default to creating a new temporary directory for the socket.  On
Windows, where the native SSH client doesn't support ControlMaster,
we should fall back to using multiple connections since we use
ControlMaster=auto.

Note that the option exists because users may already be using SSH
multiplexing and we would want to provide a way for them to disable
this, in addition to the case where users have an old or broken OpenSSH
which cannot support this option.

We pass the connection object into each worker and adjust our transfer
code to pass it into each function we invoke.  We also make sure to
properly terminate each connection at the end by reducing our connection
count to 0, which closes the extra (i.e., all) connections.

Co-authored-by: Chris Darroch <chrisd8088@github.com>
2021-07-20 19:15:59 +00:00
brian m. carlson
9ff6739b6b
ssh: implement Git SSH variant selection
We'd implemented Git's autodetection of SSH variants in the past, but we
hadn't implemented the newer explicit SSH selection.  Since we're about
to pass some additional options to our ssh binaries, let's implement the
proper variant using GIT_SSH_VARIANT and ssh.variant.

Roughly, the algorithm is this: GIT_SSH_VARIANT overrides ssh.variant,
and if neither is set, autodetection occurs.  A user can specify either
"ssh" (OpenSSH), "putty" (or its synonym "plink"), "tortoiseplink", or
"simple", or, if they'd like the autodetection behavior, "auto".  If the
value is not any of these, then it is interpreted as "ssh".

Remove the special-casing of certain command names in favor of the
variant type.

Co-authored-by: Chris Darroch <chrisd8088@github.com>
2021-07-20 19:15:59 +00:00
brian m. carlson
c033051a40
ssh: introduce an ID for multiple traced pkt-line connections
Since we're multithreaded, unlike Git, let's provide a useful
per-connection ID when we track pkt-line values so that we can
distinguish multiple connections in the trace output.
2021-07-20 19:15:59 +00:00
brian m. carlson
898dc43d1d
ssh: support multiple connections for one transfer
Since we currently support multiple connections for HTTPS, let's also
add multiple connections for pure SSH connections.  For now, we spawn a
whole new connection, but in the future we'll support using OpenSSH's
ControlMaster flag.

Introduce several new functions to create SSH connections and adjust the
number of connection being used.
2021-07-20 19:15:59 +00:00
brian m. carlson
594f8e386c
tq: implement a pure SSH-based protocol for transfers
A pure SSH-based protocol has been a long time request from many users,
so let's implement one.  Implement basic upload and download support,
plus batch requests, and support pkt-line tracing for text packets to
make debugging easier.

Note that locking is not yet supported; that will come in a future
patch.

We prefer the Endpoint function to the RemoteEndpoint function because
the former handles lfs.url and the latter does not.

Update a comment about the shared temporary directory; it is no longer
cleared automatically by the adapter, and instead the cleanup happens
later in other code.  Therefore, it is safe to share the directory among
the transport adapters.

Co-authored-by: Chris Darroch <chrisd8088@github.com>
2021-07-20 19:15:40 +00:00
brian m. carlson
b4544ca5bb
ssh: implement protocol handling for pure SSH-based protocol
With the pure SSH-based protocol, we have a couple different types of
messages that can be sent and received.  Let's implement generic helpers
for these types so we can use them later on when we implement the actual
protocol.
2021-07-20 18:39:12 +00:00
brian m. carlson
0981842d21
lfsapi: permit accessing context later on
We'll want to access the context that was originally passed to us later
on in a future commit, so let's preserve it so we can extract it from
our API client.
2021-07-20 18:39:10 +00:00
brian m. carlson
ab94bbfa24
ssh: create a traceable pkt-line interface
One thing that Git provides is a traceable pkt-line interface when
GIT_TRACE_PACKET=1 is provided.  Let's add a wrapper around the text
parts of the pkt-line interface so we can trace what's happening and
provide helpful debug output.
2021-07-20 18:39:10 +00:00
brian m. carlson
42e08e18b1
Move much of SSH code into a separate package
In the future, we'll want to call into the SSH code from multiple
packages, so let's move it out of the lfshttp package into its own
package to avoid package import loops.  While we're at it, rename the
function names to remove the "ssh" prefix, since it's implied by the
fact that they're in a package called "ssh".

Move the tests to their own package to prevent an import loop and expose
the private functions so we can test them there.
2021-07-20 18:37:31 +00:00