Page MenuHomePhabricator

D10401.id25535.diff
No OneTemporary

D10401.id25535.diff

diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -14,6 +14,7 @@
'AlmanacDevice' => 'applications/almanac/storage/AlmanacDevice.php',
'AlmanacDevicePHIDType' => 'applications/almanac/phid/AlmanacDevicePHIDType.php',
'AlmanacDeviceProperty' => 'applications/almanac/storage/AlmanacDeviceProperty.php',
+ 'AlmanacDevicePropertyQuery' => 'applications/almanac/query/AlmanacDevicePropertyQuery.php',
'AlmanacDeviceQuery' => 'applications/almanac/query/AlmanacDeviceQuery.php',
'AlmanacManagementRegisterWorkflow' => 'applications/almanac/management/AlmanacManagementRegisterWorkflow.php',
'AlmanacManagementWorkflow' => 'applications/almanac/management/AlmanacManagementWorkflow.php',
@@ -2864,6 +2865,7 @@
),
'AlmanacDevicePHIDType' => 'PhabricatorPHIDType',
'AlmanacDeviceProperty' => 'AlmanacDAO',
+ 'AlmanacDevicePropertyQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'AlmanacDeviceQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'AlmanacManagementRegisterWorkflow' => 'AlmanacManagementWorkflow',
'AlmanacManagementWorkflow' => 'PhabricatorManagementWorkflow',
diff --git a/src/applications/almanac/query/AlmanacDevicePropertyQuery.php b/src/applications/almanac/query/AlmanacDevicePropertyQuery.php
new file mode 100644
--- /dev/null
+++ b/src/applications/almanac/query/AlmanacDevicePropertyQuery.php
@@ -0,0 +1,73 @@
+<?php
+
+final class AlmanacDevicePropertyQuery
+ extends PhabricatorCursorPagedPolicyAwareQuery {
+
+ private $devicePHIDs;
+ private $keys;
+ private $values;
+
+ public function withKeys(array $keys) {
+ $this->keys = $keys;
+ return $this;
+ }
+
+ public function withValues(array $values) {
+ $this->values = $values;
+ return $this;
+ }
+
+ public function withDevicePHIDs(array $device_phids) {
+ $this->devicePHIDs = $device_phids;
+ return $this;
+ }
+
+ protected function loadPage() {
+ $table = new AlmanacDeviceProperty();
+ $conn_r = $table->establishConnection('r');
+
+ $data = queryfx_all(
+ $conn_r,
+ 'SELECT * FROM %T %Q %Q %Q',
+ $table->getTableName(),
+ $this->buildWhereClause($conn_r),
+ $this->buildOrderClause($conn_r),
+ $this->buildLimitClause($conn_r));
+
+ return $table->loadAllFromArray($data);
+ }
+
+ protected function buildWhereClause($conn_r) {
+ $where = array();
+
+ if ($this->devicePHIDs !== null) {
+ $where[] = qsprintf(
+ $conn_r,
+ 'devicePHIDs IN (%Ls)',
+ $this->devicePHIDs);
+ }
+
+ if ($this->keys !== null) {
+ $where[] = qsprintf(
+ $conn_r,
+ '`key` IN (%Ls)',
+ $this->keys);
+ }
+
+ if ($this->values !== null) {
+ $where[] = qsprintf(
+ $conn_r,
+ 'value IN (%Ls)',
+ $this->values);
+ }
+
+ $where[] = $this->buildPagingClause($conn_r);
+
+ return $this->formatWhereClause($where);
+ }
+
+ public function getQueryApplicationClass() {
+ return 'PhabricatorAlmanacApplication';
+ }
+
+}
diff --git a/src/applications/almanac/util/AlmanacConduitUtil.php b/src/applications/almanac/util/AlmanacConduitUtil.php
--- a/src/applications/almanac/util/AlmanacConduitUtil.php
+++ b/src/applications/almanac/util/AlmanacConduitUtil.php
@@ -2,6 +2,42 @@
final class AlmanacConduitUtil extends Phobject {
+ public static function loadSigningKeys() {
+ static $private_key = null;
+ static $public_key = null;
+
+ if ($private_key === null) {
+ $private_key = new PhutilOpaqueEnvelope(
+ Filesystem::readFile(self::getHostPrivateKeyPath()));
+ }
+
+ if ($public_key === null) {
+ $host_id = Filesystem::readFile(self::getHostIDPath());
+
+ $device = id(new AlmanacDevice())->load($host_id);
+
+ if ($device === null) {
+ throw new Exception('Current device is not registered in Almanac.');
+ }
+
+ $property = id(new AlmanacDevicePropertyQuery())
+ ->setViewer(PhabricatorUser::getOmnipotentUser())
+ ->withDevicePHIDs(array($device->getPHID()))
+ ->withKeys(array('conduitPublicOpenSSLKey'))
+ ->executeOne();
+
+ if ($property === null) {
+ throw new Exception(
+ 'Current device does not have an OpenSSL key available '.
+ 'for Conduit access.');
+ }
+
+ $public_key = $property->getValue();
+ }
+
+ return array($public_key, $private_key);
+ }
+
public static function getHostPrivateKeyPath() {
$root = dirname(phutil_get_library_root('phabricator'));
$path = $root.'/conf/local/HOSTKEY';
diff --git a/src/applications/conduit/call/ConduitCall.php b/src/applications/conduit/call/ConduitCall.php
--- a/src/applications/conduit/call/ConduitCall.php
+++ b/src/applications/conduit/call/ConduitCall.php
@@ -145,15 +145,22 @@
$params['__conduit__']['isProxied'] = true;
if ($this->handler->shouldRequireAuthentication()) {
- $client->callMethodSynchronous(
- 'conduit.connect',
- array(
- 'client' => 'PhabricatorConduit',
- 'clientVersion' => '1.0',
- 'user' => $this->getUser()->getUserName(),
- 'certificate' => $this->getUser()->getConduitCertificate(),
- '__conduit__' => $params['__conduit__'],
- ));
+ if ($user->isOmnipotent()) {
+ list($public_key, $private_key) =
+ AlmanacConduitUtil::loadSigningKeys();
+
+ $client->setSigningKeys($public_key, $private_key);
+ } else {
+ $client->callMethodSynchronous(
+ 'conduit.connect',
+ array(
+ 'client' => 'PhabricatorConduit',
+ 'clientVersion' => '1.0',
+ 'user' => $this->getUser()->getUserName(),
+ 'certificate' => $this->getUser()->getConduitCertificate(),
+ '__conduit__' => $params['__conduit__'],
+ ));
+ }
}
return $client->callMethodSynchronous(
diff --git a/src/applications/conduit/controller/PhabricatorConduitAPIController.php b/src/applications/conduit/controller/PhabricatorConduitAPIController.php
--- a/src/applications/conduit/controller/PhabricatorConduitAPIController.php
+++ b/src/applications/conduit/controller/PhabricatorConduitAPIController.php
@@ -209,6 +209,48 @@
$request->getUser());
}
+ // handle cross-host auth
+ if (isset($metadata['signature']) && isset($metadata['publicKey'])) {
+ $signature = $metadata['signature'];
+ $public_key = $metadata['publicKey'];
+
+ $property = id(new AlmanacDevicePropertyQuery())
+ ->setViewer(PhabricatorUser::getOmnipotentUser())
+ ->withKeys(array('conduitPublicOpenSSLKey'))
+ ->withValues(array($public_key))
+ ->executeOne();
+ if ($property === null) {
+ return array(
+ 'ERR-INVALID-AUTH',
+ 'No registered device with matching OpenSSL public key.',
+ );
+ }
+
+ // These are not included in the signature, so remove them from
+ // metadata before verifying.
+ unset($metadata['signature']);
+ unset($metadata['publicKey']);
+
+ $verified = ConduitClient::verifySignature(
+ $signature,
+ $public_key,
+ $this->method,
+ $api_request->getAllParameters(),
+ $metadata);
+
+ if ($verified) {
+ // Authenticated using server signature; therefore the user is
+ // the omnipotent user.
+ $api_request->setUser(PhabricatorUser::getOmnipotentUser());
+ return null;
+ } else {
+ return array(
+ 'ERR-INVALID-AUTH',
+ 'Server signature is invalid.',
+ );
+ }
+ }
+
// handle oauth
$access_token = $request->getStr('access_token');
$method_scope = $metadata['scope'];

File Metadata

Mime Type
text/plain
Expires
Wed, Jan 22, 7:31 PM (4 h, 26 m)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7035241
Default Alt Text
D10401.id25535.diff (7 KB)

Event Timeline