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