@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
at recaptime-dev/main 159 lines 4.1 kB view raw
1#!/usr/bin/env php 2<?php 3 4// This is a wrapper script for Git, Mercurial, and Subversion. It primarily 5// serves to inject "-o StrictHostKeyChecking=no" into the SSH arguments. 6 7// In some cases, Subversion sends us SIGTERM. If we don't catch the signal and 8// react to it, we won't run object destructors by default and thus won't clean 9// up temporary files. Declare ticks so we can install a signal handler. 10if (function_exists('pcntl_async_signals')) { 11 pcntl_async_signals(true); 12} else { 13 declare(ticks = 1); 14} 15 16$root = dirname(dirname(dirname(__FILE__))); 17require_once $root.'/scripts/__init_script__.php'; 18 19// Contrary to the documentation, Git may pass a "-p" flag. If it does, respect 20// it and move it before the "--" argument. 21$args = new PhutilArgumentParser($argv); 22$args->parsePartial( 23 array( 24 array( 25 'name' => 'port', 26 'short' => 'p', 27 'param' => pht('port'), 28 'help' => pht('Port number to connect to.'), 29 ), 30 array( 31 'name' => 'options', 32 'short' => 'o', 33 'param' => pht('options'), 34 'repeat' => true, 35 'help' => pht('SSH options.'), 36 ), 37 )); 38 39$unconsumed_argv = $args->getUnconsumedArgumentVector(); 40 41if (function_exists('pcntl_signal')) { 42 pcntl_signal(SIGTERM, 'ssh_connect_signal'); 43} 44 45function ssh_connect_signal($signo) { 46 // This is just letting destructors fire. In particular, we want to clean 47 // up any temporary files we wrote. See T10547. 48 exit(128 + $signo); 49} 50 51$pattern = array(); 52$arguments = array(); 53 54$pattern[] = 'ssh'; 55 56$pattern[] = '-o'; 57$pattern[] = 'StrictHostKeyChecking=no'; 58 59// This prevents "known host" failures, and covers for issues where HOME is set 60// to something unusual. 61$pattern[] = '-o'; 62$pattern[] = 'UserKnownHostsFile=/dev/null'; 63 64$as_device = getenv('PHABRICATOR_AS_DEVICE'); 65$credential_phid = getenv('PHABRICATOR_CREDENTIAL'); 66 67if ($as_device) { 68 $device = AlmanacKeys::getLiveDevice(); 69 if (!$device) { 70 throw new Exception( 71 pht( 72 'Attempting to create an SSH connection that authenticates with '. 73 'the current device, but this host is not configured as a cluster '. 74 'device.')); 75 } 76 77 if ($credential_phid) { 78 throw new Exception( 79 pht( 80 'Attempting to proxy an SSH connection that authenticates with '. 81 'both the current device and a specific credential. These options '. 82 'are mutually exclusive.')); 83 } 84} 85 86if ($credential_phid) { 87 $viewer = PhabricatorUser::getOmnipotentUser(); 88 $key = PassphraseSSHKey::loadFromPHID($credential_phid, $viewer); 89 90 $pattern[] = '-l %P'; 91 $arguments[] = $key->getUsernameEnvelope(); 92 $pattern[] = '-i %P'; 93 $arguments[] = $key->getKeyfileEnvelope(); 94} 95 96if ($as_device) { 97 $pattern[] = '-l %R'; 98 $arguments[] = AlmanacKeys::getClusterSSHUser(); 99 $pattern[] = '-i %R'; 100 $arguments[] = AlmanacKeys::getKeyPath('device.key'); 101} 102 103// Subversion passes us a host in the form "domain.com:port", which is not 104// valid for normal SSH but which we can parse into a valid "-p" flag. 105 106$passthru_args = $unconsumed_argv; 107$host = array_shift($passthru_args); 108$parts = explode(':', $host, 2); 109$host = $parts[0]; 110 111$port = $args->getArg('port'); 112 113if (!$port) { 114 if (count($parts) == 2) { 115 $port = $parts[1]; 116 } 117} 118 119if ($port) { 120 $pattern[] = '-p %d'; 121 $arguments[] = $port; 122} 123 124$options = $args->getArg('options'); 125$allowed_ssh_options = array('SendEnv=GIT_PROTOCOL'); 126 127if (!empty($options)) { 128 foreach ($options as $option) { 129 if (array_search($option, $allowed_ssh_options) !== false) { 130 $pattern[] = '-o %s'; 131 $arguments[] = $option; 132 } else { 133 throw new Exception( 134 pht( 135 'Disallowed ssh option "%s" given with "-o". '. 136 'Allowed options are: %s.', 137 $option, 138 implode(', ', $allowed_ssh_options))); 139 } 140 } 141} 142 143$pattern[] = '--'; 144 145$pattern[] = '%s'; 146$arguments[] = $host; 147 148foreach ($passthru_args as $passthru_arg) { 149 $pattern[] = '%s'; 150 $arguments[] = $passthru_arg; 151} 152 153$pattern = implode(' ', $pattern); 154array_unshift($arguments, $pattern); 155 156$err = newv('PhutilExecPassthru', $arguments) 157 ->resolve(); 158 159exit($err);