[ Index ]

PHP Cross Reference of Phabricator

title

Body

[close]

/src/applications/conduit/method/ -> ConduitConnectConduitAPIMethod.php (source)

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


Generated: Sun Nov 30 09:20:46 2014 Cross-referenced by PHPXref 0.7.1