Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F14754527
D10401.id25534.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
7 KB
Referenced Files
None
Subscribers
None
D10401.id25534.diff
View Options
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,60 @@
+<?php
+
+final class AlmanacDevicePropertyQuery
+ extends PhabricatorCursorPagedPolicyAwareQuery {
+
+ private $keys;
+ private $devicePHIDs;
+
+ public function withKeys(array $keys) {
+ $this->keys = $keys;
+ 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->keys !== null) {
+ $where[] = qsprintf(
+ $conn_r,
+ '`key` IN (%Ls)',
+ $this->keys);
+ }
+
+ if ($this->devicePHIDs !== null) {
+ $where[] = qsprintf(
+ $conn_r,
+ 'devicePHIDs IN (%Ls)',
+ $this->devicePHIDs);
+ }
+
+ $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
Details
Attached
Mime Type
text/plain
Expires
Wed, Jan 22, 3:33 PM (42 m, 27 s)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7034464
Default Alt Text
D10401.id25534.diff (7 KB)
Attached To
Mode
D10401: Allow Phabricator to accept Conduit requests signed with an SSH key
Attached
Detach File
Event Timeline
Log In to Comment