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