Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/src/applications/conduit/method/ConduitConnectConduitAPIMethod.php
12256 views
1
<?php
2
3
final class ConduitConnectConduitAPIMethod extends ConduitAPIMethod {
4
5
public function getAPIMethodName() {
6
return 'conduit.connect';
7
}
8
9
public function shouldRequireAuthentication() {
10
return false;
11
}
12
13
public function shouldAllowUnguardedWrites() {
14
return true;
15
}
16
17
public function getMethodDescription() {
18
return pht('Connect a session-based client.');
19
}
20
21
protected function defineParamTypes() {
22
return array(
23
'client' => 'required string',
24
'clientVersion' => 'required int',
25
'clientDescription' => 'optional string',
26
'user' => 'optional string',
27
'authToken' => 'optional int',
28
'authSignature' => 'optional string',
29
'host' => 'deprecated',
30
);
31
}
32
33
protected function defineReturnType() {
34
return 'dict<string, any>';
35
}
36
37
protected function defineErrorTypes() {
38
return array(
39
'ERR-BAD-VERSION' => pht(
40
'Client/server version mismatch. Upgrade your server or downgrade '.
41
'your client.'),
42
'NEW-ARC-VERSION' => pht(
43
'Client/server version mismatch. Upgrade your client.'),
44
'ERR-UNKNOWN-CLIENT' => pht('Client is unknown.'),
45
'ERR-INVALID-USER' => pht(
46
'The username you are attempting to authenticate with is not valid.'),
47
'ERR-INVALID-CERTIFICATE' => pht(
48
'Your authentication certificate for this server is invalid.'),
49
'ERR-INVALID-TOKEN' => pht(
50
"The challenge token you are authenticating with is outside of the ".
51
"allowed time range. Either your system clock is out of whack or ".
52
"you're executing a replay attack."),
53
'ERR-NO-CERTIFICATE' => pht('This server requires authentication.'),
54
);
55
}
56
57
protected function execute(ConduitAPIRequest $request) {
58
$client = $request->getValue('client');
59
$client_version = (int)$request->getValue('clientVersion');
60
$client_description = (string)$request->getValue('clientDescription');
61
$client_description = id(new PhutilUTF8StringTruncator())
62
->setMaximumBytes(255)
63
->truncateString($client_description);
64
$username = (string)$request->getValue('user');
65
66
switch ($client) {
67
case 'arc':
68
$server_version = 6;
69
$supported_versions = array(
70
$server_version => true,
71
// Client version 5 introduced "user.query" call
72
4 => true,
73
// Client version 6 introduced "diffusion.getlintmessages" call
74
5 => true,
75
);
76
77
if (empty($supported_versions[$client_version])) {
78
if ($server_version < $client_version) {
79
$ex = new ConduitException('ERR-BAD-VERSION');
80
$ex->setErrorDescription(
81
pht(
82
"Your '%s' client version is '%d', which is newer than the ".
83
"server version, '%d'. Upgrade your server.",
84
'arc',
85
$client_version,
86
$server_version));
87
} else {
88
$ex = new ConduitException('NEW-ARC-VERSION');
89
$ex->setErrorDescription(
90
pht(
91
'A new version of arc is available! You need to upgrade '.
92
'to connect to this server (you are running version '.
93
'%d, the server is running version %d).',
94
$client_version,
95
$server_version));
96
}
97
throw $ex;
98
}
99
break;
100
default:
101
// Allow new clients by default.
102
break;
103
}
104
105
$token = $request->getValue('authToken');
106
$signature = $request->getValue('authSignature');
107
108
$user = id(new PhabricatorUser())->loadOneWhere('username = %s', $username);
109
if (!$user) {
110
throw new ConduitException('ERR-INVALID-USER');
111
}
112
113
$session_key = null;
114
if ($token && $signature) {
115
$threshold = 60 * 15;
116
$now = time();
117
if (abs($token - $now) > $threshold) {
118
throw id(new ConduitException('ERR-INVALID-TOKEN'))
119
->setErrorDescription(
120
pht(
121
'The request you submitted is signed with a timestamp, but that '.
122
'timestamp is not within %s of the current time. The '.
123
'signed timestamp is %s (%s), and the current server time is '.
124
'%s (%s). This is a difference of %s seconds, but the '.
125
'timestamp must differ from the server time by no more than '.
126
'%s seconds. Your client or server clock may not be set '.
127
'correctly.',
128
phutil_format_relative_time($threshold),
129
$token,
130
date('r', $token),
131
$now,
132
date('r', $now),
133
($token - $now),
134
$threshold));
135
}
136
$valid = sha1($token.$user->getConduitCertificate());
137
if (!phutil_hashes_are_identical($valid, $signature)) {
138
throw new ConduitException('ERR-INVALID-CERTIFICATE');
139
}
140
$session_key = id(new PhabricatorAuthSessionEngine())->establishSession(
141
PhabricatorAuthSession::TYPE_CONDUIT,
142
$user->getPHID(),
143
$partial = false);
144
} else {
145
throw new ConduitException('ERR-NO-CERTIFICATE');
146
}
147
148
return array(
149
'connectionID' => mt_rand(),
150
'sessionKey' => $session_key,
151
'userPHID' => $user->getPHID(),
152
);
153
}
154
155
}
156
157