Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/scripts/ssh/ssh-connect.php
12241 views
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.
10
if (function_exists('pcntl_async_signals')) {
11
pcntl_async_signals(true);
12
} else {
13
declare(ticks = 1);
14
}
15
16
$root = dirname(dirname(dirname(__FILE__)));
17
require_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
41
if (function_exists('pcntl_signal')) {
42
pcntl_signal(SIGTERM, 'ssh_connect_signal');
43
}
44
45
function 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
67
if ($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
86
if ($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
96
if ($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
113
if (!$port) {
114
if (count($parts) == 2) {
115
$port = $parts[1];
116
}
117
}
118
119
if ($port) {
120
$pattern[] = '-p %d';
121
$arguments[] = $port;
122
}
123
124
$options = $args->getArg('options');
125
$allowed_ssh_options = array('SendEnv=GIT_PROTOCOL');
126
127
if (!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
148
foreach ($passthru_args as $passthru_arg) {
149
$pattern[] = '%s';
150
$arguments[] = $passthru_arg;
151
}
152
153
$pattern = implode(' ', $pattern);
154
array_unshift($arguments, $pattern);
155
156
$err = newv('PhutilExecPassthru', $arguments)
157
->resolve();
158
159
exit($err);
160
161