Page MenuHomePhabricator

Add parsing for ssh options (-o) which are passed when using GIT v2 wire protocol by git command (SSH transport)
ClosedPublic

Authored by artms on Jul 27 2018, 7:50 AM.
Tags
None
Referenced Files
Unknown Object (File)
Fri, Dec 20, 10:45 PM
Unknown Object (File)
Thu, Dec 19, 12:49 AM
Unknown Object (File)
Sun, Dec 8, 12:52 PM
Unknown Object (File)
Fri, Dec 6, 4:51 PM
Unknown Object (File)
Thu, Dec 5, 11:02 PM
Unknown Object (File)
Mon, Dec 2, 8:59 PM
Unknown Object (File)
Wed, Nov 27, 9:20 AM
Unknown Object (File)
Sun, Nov 24, 6:09 PM
Subscribers

Details

Summary

Makes ssh-connect compatible with Git v2 wire protocol over SSH

More details about git V2 wire: https://opensource.googleblog.com/2018/05/introducing-git-protocol-version-2.html

git command (2.18+) passes extra options (-o "SendEnv GIT_PROTOCOL") to underlying ssh command to enable v2 wire protocol (environment variable enabling new protocol).

Phabricator ssh-connect command doesn't understand -o options and interprets it as host parts hence when you enable git v2 all clones/ls-remotes crash with:

#0 ExecFuture::resolvex() called at [<phabricator>/src/applications/repository/storage/PhabricatorRepository.php:525]
#1 PhabricatorRepository::execxRemoteCommand(string, PhutilOpaqueEnvelope) called at [<phabricator>/src/applications/repository/engine/PhabricatorRepositoryPullEngine.php:400]
#2 PhabricatorRepositoryPullEngine::loadGitRemoteRefs(PhabricatorRepository) called at [<phabricator>/src/applications/repository/engine/PhabricatorRepositoryPullEngine.php:343]
#3 PhabricatorRepositoryPullEngine::executeGitUpdate() called at [<phabricator>/src/applications/repository/engine/PhabricatorRepositoryPullEngine.php:126]
#4 PhabricatorRepositoryPullEngine::pullRepositoryWithLock() called at [<phabricator>/src/applications/repository/engine/PhabricatorRepositoryPullEngine.php:40]
#5 PhabricatorRepositoryPullEngine::pullRepository() called at [<phabricator>/src/applications/repository/management/PhabricatorRepositoryManagementUpdateWorkflow.php:59]
#6 PhabricatorRepositoryManagementUpdateWorkflow::execute(PhutilArgumentParser) called at [<phutil>/src/parser/argument/PhutilArgumentParser.php:441]
#7 PhutilArgumentParser::parseWorkflowsFull(array) called at [<phutil>/src/parser/argument/PhutilArgumentParser.php:333]
#8 PhutilArgumentParser::parseWorkflows(array) called at [<phabricator>/scripts/repository/manage_repositories.php:22]
COMMAND
git ls-remote '********'
STDOUT
(empty)
STDERR
ssh: Could not resolve hostname -o: Name or service not known
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
at [<phutil>/src/future/exec/ExecFuture.php:369]
Test Plan

How to reproduce:

  1. add repository to Phabricator which is accessed via ssh
  2. Use git 2.18+
  3. Enable wire protocol in /etc/gitconfig:
[protocol]
    version = 2
  1. Try refreshing repository: phabricator/bin/repository update somecallsing
  2. Repository update fails with ssh: Could not resolve hostname -o: Name or service not known

after this changes - updates will succeed

Diff Detail

Repository
rP Phabricator
Lint
Lint Not Applicable
Unit
Tests Not Applicable

Event Timeline

artms requested review of this revision.Jul 27 2018, 7:50 AM

I think we should whitelist the permitted options and allow only SendEnv GIT_PROTOCOL exactly. Some options (including ProxyCommand) are dangerous. See T12961 for context.

Although we control invocations of ssh-connect and it "should" be safe to allow dangerous options, T12961 "should" also never have happened in the first place, but no VCS interacted with the SSH subprocess safely.

The downside is that we need to bring a similar patch upstream every few years, but our turnaround time on this stuff is generally pretty good and I'd like to balance things in favor of security paranoia over future-version-compatibility here.

This revision now requires changes to proceed.Jul 27 2018, 4:03 PM
  • Allow only SendEnv=GIT_PROTOCOL ssh option
scripts/ssh/ssh-connect.php
129

This will essentially dump "unrecognized" options, please advise if such behavior is acceptable? We can also "crash" if unrecognized options is passed to have less surprises in future when some unrecognized option is passed to ssh command

Yeah, just throw an exception -- something like this, probably:

throw new Exeception(
  pht(
    'Disallowed option "%s" given with "-o". Allowed options are: %s.',
    $option,
    implode(', ', $allowed_ssh_options)));

Looks good otherwise. Thanks!

This revision now requires changes to proceed.Jul 30 2018, 3:01 PM
  • Throw error if unknown ssh option is passed

Thanks!

I added you to Blessed Committers, so you should be able to land this yourself. See that project description for more instructions, or let me know if you run into trouble.

(I also added you to Community, granting you sweeping janitorial powers on this install.)

This revision is now accepted and ready to land.Aug 1 2018, 1:08 PM
This revision was automatically updated to reflect the committed changes.