summaryrefslogtreecommitdiffstats
path: root/apps/federation/lib
diff options
context:
space:
mode:
authorJoas Schilling <nickvergessen@owncloud.com>2016-05-09 15:09:50 +0200
committerJoas Schilling <nickvergessen@owncloud.com>2016-05-19 09:48:00 +0200
commit0c727f175509ccfdec87dc69fd52af60cf2d6b94 (patch)
treef3e43242a9d5713ff34bf17b5b4f196ddb4bb651 /apps/federation/lib
parent7ca5b35379144d868a36f10c237c78de56f4ed5a (diff)
downloadnextcloud-server-0c727f175509ccfdec87dc69fd52af60cf2d6b94.tar.gz
nextcloud-server-0c727f175509ccfdec87dc69fd52af60cf2d6b94.zip
Move federation code to PSR-4
Diffstat (limited to 'apps/federation/lib')
-rw-r--r--apps/federation/lib/API/OCSAuthAPI.php176
-rw-r--r--apps/federation/lib/AppInfo/Application.php181
-rw-r--r--apps/federation/lib/BackgroundJob/GetSharedSecret.php200
-rw-r--r--apps/federation/lib/BackgroundJob/RequestSharedSecret.php184
-rw-r--r--apps/federation/lib/Command/SyncFederationAddressBooks.php74
-rw-r--r--apps/federation/lib/Controller/SettingsController.php122
-rw-r--r--apps/federation/lib/DAV/FedAuth.php54
-rw-r--r--apps/federation/lib/DbHandler.php (renamed from apps/federation/lib/dbhandler.php)0
-rw-r--r--apps/federation/lib/Hooks.php (renamed from apps/federation/lib/hooks.php)0
-rw-r--r--apps/federation/lib/Middleware/AddServerMiddleware.php72
-rw-r--r--apps/federation/lib/SyncFederationAddressBooks.php (renamed from apps/federation/lib/syncfederationaddressbooks.php)0
-rw-r--r--apps/federation/lib/SyncJob.php (renamed from apps/federation/lib/syncjob.php)0
-rw-r--r--apps/federation/lib/TrustedServers.php (renamed from apps/federation/lib/trustedservers.php)0
13 files changed, 1063 insertions, 0 deletions
diff --git a/apps/federation/lib/API/OCSAuthAPI.php b/apps/federation/lib/API/OCSAuthAPI.php
new file mode 100644
index 00000000000..1c4e73cc8de
--- /dev/null
+++ b/apps/federation/lib/API/OCSAuthAPI.php
@@ -0,0 +1,176 @@
+<?php
+/**
+ * @author Björn Schießle <schiessle@owncloud.com>
+ * @author Lukas Reschke <lukas@owncloud.com>
+ * @author Robin Appelman <icewind@owncloud.com>
+ * @author Roeland Jago Douma <rullzer@owncloud.com>
+ * @author Thomas Müller <thomas.mueller@tmit.eu>
+ *
+ * @copyright Copyright (c) 2016, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+
+namespace OCA\Federation\API;
+
+use OCA\Federation\DbHandler;
+use OCA\Federation\TrustedServers;
+use OCP\AppFramework\Http;
+use OCP\BackgroundJob\IJobList;
+use OCP\ILogger;
+use OCP\IRequest;
+use OCP\Security\ISecureRandom;
+
+/**
+ * Class OCSAuthAPI
+ *
+ * OCS API end-points to exchange shared secret between two connected ownClouds
+ *
+ * @package OCA\Federation\API
+ */
+class OCSAuthAPI {
+
+ /** @var IRequest */
+ private $request;
+
+ /** @var ISecureRandom */
+ private $secureRandom;
+
+ /** @var IJobList */
+ private $jobList;
+
+ /** @var TrustedServers */
+ private $trustedServers;
+
+ /** @var DbHandler */
+ private $dbHandler;
+
+ /** @var ILogger */
+ private $logger;
+
+ /**
+ * OCSAuthAPI constructor.
+ *
+ * @param IRequest $request
+ * @param ISecureRandom $secureRandom
+ * @param IJobList $jobList
+ * @param TrustedServers $trustedServers
+ * @param DbHandler $dbHandler
+ * @param ILogger $logger
+ */
+ public function __construct(
+ IRequest $request,
+ ISecureRandom $secureRandom,
+ IJobList $jobList,
+ TrustedServers $trustedServers,
+ DbHandler $dbHandler,
+ ILogger $logger
+ ) {
+ $this->request = $request;
+ $this->secureRandom = $secureRandom;
+ $this->jobList = $jobList;
+ $this->trustedServers = $trustedServers;
+ $this->dbHandler = $dbHandler;
+ $this->logger = $logger;
+ }
+
+ /**
+ * request received to ask remote server for a shared secret
+ *
+ * @return \OC_OCS_Result
+ */
+ public function requestSharedSecret() {
+
+ $url = $this->request->getParam('url');
+ $token = $this->request->getParam('token');
+
+ if ($this->trustedServers->isTrustedServer($url) === false) {
+ $this->logger->error('remote server not trusted (' . $url . ') while requesting shared secret', ['app' => 'federation']);
+ return new \OC_OCS_Result(null, HTTP::STATUS_FORBIDDEN);
+ }
+
+ // if both server initiated the exchange of the shared secret the greater
+ // token wins
+ $localToken = $this->dbHandler->getToken($url);
+ if (strcmp($localToken, $token) > 0) {
+ $this->logger->info(
+ 'remote server (' . $url . ') presented lower token. We will initiate the exchange of the shared secret.',
+ ['app' => 'federation']
+ );
+ return new \OC_OCS_Result(null, HTTP::STATUS_FORBIDDEN);
+ }
+
+ // we ask for the shared secret so we no longer have to ask the other server
+ // to request the shared secret
+ $this->jobList->remove('OCA\Federation\BackgroundJob\RequestSharedSecret',
+ [
+ 'url' => $url,
+ 'token' => $localToken
+ ]
+ );
+
+ $this->jobList->add(
+ 'OCA\Federation\BackgroundJob\GetSharedSecret',
+ [
+ 'url' => $url,
+ 'token' => $token,
+ ]
+ );
+
+ return new \OC_OCS_Result(null, Http::STATUS_OK);
+
+ }
+
+ /**
+ * create shared secret and return it
+ *
+ * @return \OC_OCS_Result
+ */
+ public function getSharedSecret() {
+
+ $url = $this->request->getParam('url');
+ $token = $this->request->getParam('token');
+
+ if ($this->trustedServers->isTrustedServer($url) === false) {
+ $this->logger->error('remote server not trusted (' . $url . ') while getting shared secret', ['app' => 'federation']);
+ return new \OC_OCS_Result(null, HTTP::STATUS_FORBIDDEN);
+ }
+
+ if ($this->isValidToken($url, $token) === false) {
+ $expectedToken = $this->dbHandler->getToken($url);
+ $this->logger->error(
+ 'remote server (' . $url . ') didn\'t send a valid token (got "' . $token . '" but expected "'. $expectedToken . '") while getting shared secret',
+ ['app' => 'federation']
+ );
+ return new \OC_OCS_Result(null, HTTP::STATUS_FORBIDDEN);
+ }
+
+ $sharedSecret = $this->secureRandom->generate(32);
+
+ $this->trustedServers->addSharedSecret($url, $sharedSecret);
+ // reset token after the exchange of the shared secret was successful
+ $this->dbHandler->addToken($url, '');
+
+ return new \OC_OCS_Result(['sharedSecret' => $sharedSecret], Http::STATUS_OK);
+
+ }
+
+ protected function isValidToken($url, $token) {
+ $storedToken = $this->dbHandler->getToken($url);
+ return hash_equals($storedToken, $token);
+ }
+
+}
diff --git a/apps/federation/lib/AppInfo/Application.php b/apps/federation/lib/AppInfo/Application.php
new file mode 100644
index 00000000000..74185345329
--- /dev/null
+++ b/apps/federation/lib/AppInfo/Application.php
@@ -0,0 +1,181 @@
+<?php
+/**
+ * @author Björn Schießle <schiessle@owncloud.com>
+ * @author Robin Appelman <icewind@owncloud.com>
+ * @author Thomas Müller <thomas.mueller@tmit.eu>
+ *
+ * @copyright Copyright (c) 2016, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OCA\Federation\AppInfo;
+
+use OCA\Federation\API\OCSAuthAPI;
+use OCA\Federation\Controller\SettingsController;
+use OCA\Federation\DAV\FedAuth;
+use OCA\Federation\DbHandler;
+use OCA\Federation\Hooks;
+use OCA\Federation\Middleware\AddServerMiddleware;
+use OCA\Federation\SyncFederationAddressBooks;
+use OCA\Federation\SyncJob;
+use OCA\Federation\TrustedServers;
+use OCP\API;
+use OCP\App;
+use OCP\AppFramework\IAppContainer;
+use OCP\SabrePluginEvent;
+use OCP\Util;
+use Sabre\DAV\Auth\Plugin;
+
+class Application extends \OCP\AppFramework\App {
+
+ /**
+ * @param array $urlParams
+ */
+ public function __construct($urlParams = array()) {
+ parent::__construct('federation', $urlParams);
+ $this->registerService();
+ $this->registerMiddleware();
+ }
+
+ /**
+ * register setting scripts
+ */
+ public function registerSettings() {
+ App::registerAdmin('federation', 'settings/settings-admin');
+ }
+
+ private function registerService() {
+ $container = $this->getContainer();
+
+ $container->registerService('addServerMiddleware', function(IAppContainer $c) {
+ return new AddServerMiddleware(
+ $c->getAppName(),
+ \OC::$server->getL10N($c->getAppName()),
+ \OC::$server->getLogger()
+ );
+ });
+
+ $container->registerService('DbHandler', function(IAppContainer $c) {
+ return new DbHandler(
+ \OC::$server->getDatabaseConnection(),
+ \OC::$server->getL10N($c->getAppName())
+ );
+ });
+
+ $container->registerService('TrustedServers', function(IAppContainer $c) {
+ $server = $c->getServer();
+ return new TrustedServers(
+ $c->query('DbHandler'),
+ $server->getHTTPClientService(),
+ $server->getLogger(),
+ $server->getJobList(),
+ $server->getSecureRandom(),
+ $server->getConfig(),
+ $server->getEventDispatcher()
+ );
+ });
+
+ $container->registerService('SettingsController', function (IAppContainer $c) {
+ $server = $c->getServer();
+ return new SettingsController(
+ $c->getAppName(),
+ $server->getRequest(),
+ $server->getL10N($c->getAppName()),
+ $c->query('TrustedServers')
+ );
+ });
+
+ }
+
+ private function registerMiddleware() {
+ $container = $this->getContainer();
+ $container->registerMiddleware('addServerMiddleware');
+ }
+
+ /**
+ * register OCS API Calls
+ */
+ public function registerOCSApi() {
+
+ $container = $this->getContainer();
+ $server = $container->getServer();
+
+ $auth = new OCSAuthAPI(
+ $server->getRequest(),
+ $server->getSecureRandom(),
+ $server->getJobList(),
+ $container->query('TrustedServers'),
+ $container->query('DbHandler'),
+ $server->getLogger()
+
+ );
+
+ API::register('get',
+ '/apps/federation/api/v1/shared-secret',
+ array($auth, 'getSharedSecret'),
+ 'federation',
+ API::GUEST_AUTH
+ );
+
+ API::register('post',
+ '/apps/federation/api/v1/request-shared-secret',
+ array($auth, 'requestSharedSecret'),
+ 'federation',
+ API::GUEST_AUTH
+ );
+
+ }
+
+ /**
+ * listen to federated_share_added hooks to auto-add new servers to the
+ * list of trusted servers.
+ */
+ public function registerHooks() {
+
+ $container = $this->getContainer();
+ $hooksManager = new Hooks($container->query('TrustedServers'));
+
+ Util::connectHook(
+ 'OCP\Share',
+ 'federated_share_added',
+ $hooksManager,
+ 'addServerHook'
+ );
+
+ $dispatcher = $this->getContainer()->getServer()->getEventDispatcher();
+ $dispatcher->addListener('OCA\DAV\Connector\Sabre::authInit', function($event) use($container) {
+ if ($event instanceof SabrePluginEvent) {
+ $authPlugin = $event->getServer()->getPlugin('auth');
+ if ($authPlugin instanceof Plugin) {
+ $h = new DbHandler($container->getServer()->getDatabaseConnection(),
+ $container->getServer()->getL10N('federation')
+ );
+ $authPlugin->addBackend(new FedAuth($h));
+ }
+ }
+ });
+ }
+
+ /**
+ * @return SyncFederationAddressBooks
+ */
+ public function getSyncService() {
+ $syncService = \OC::$server->query('CardDAVSyncService');
+ $dbHandler = $this->getContainer()->query('DbHandler');
+ return new SyncFederationAddressBooks($dbHandler, $syncService);
+ }
+
+}
diff --git a/apps/federation/lib/BackgroundJob/GetSharedSecret.php b/apps/federation/lib/BackgroundJob/GetSharedSecret.php
new file mode 100644
index 00000000000..66ab082c1a2
--- /dev/null
+++ b/apps/federation/lib/BackgroundJob/GetSharedSecret.php
@@ -0,0 +1,200 @@
+<?php
+/**
+ * @author Björn Schießle <schiessle@owncloud.com>
+ * @author Thomas Müller <thomas.mueller@tmit.eu>
+ *
+ * @copyright Copyright (c) 2016, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+
+namespace OCA\Federation\BackgroundJob;
+
+use GuzzleHttp\Exception\ClientException;
+use OC\BackgroundJob\JobList;
+use OC\BackgroundJob\Job;
+use OCA\Federation\DbHandler;
+use OCA\Federation\TrustedServers;
+use OCP\AppFramework\Http;
+use OCP\BackgroundJob\IJobList;
+use OCP\Http\Client\IClient;
+use OCP\Http\Client\IResponse;
+use OCP\ILogger;
+use OCP\IURLGenerator;
+
+/**
+ * Class GetSharedSecret
+ *
+ * request shared secret from remote ownCloud
+ *
+ * @package OCA\Federation\Backgroundjob
+ */
+class GetSharedSecret extends Job{
+
+ /** @var IClient */
+ private $httpClient;
+
+ /** @var IJobList */
+ private $jobList;
+
+ /** @var IURLGenerator */
+ private $urlGenerator;
+
+ /** @var TrustedServers */
+ private $trustedServers;
+
+ /** @var DbHandler */
+ private $dbHandler;
+
+ /** @var ILogger */
+ private $logger;
+
+ /** @var bool */
+ protected $retainJob = false;
+
+ private $endPoint = '/ocs/v2.php/apps/federation/api/v1/shared-secret?format=json';
+
+ /**
+ * RequestSharedSecret constructor.
+ *
+ * @param IClient $httpClient
+ * @param IURLGenerator $urlGenerator
+ * @param IJobList $jobList
+ * @param TrustedServers $trustedServers
+ * @param ILogger $logger
+ * @param DbHandler $dbHandler
+ */
+ public function __construct(
+ IClient $httpClient = null,
+ IURLGenerator $urlGenerator = null,
+ IJobList $jobList = null,
+ TrustedServers $trustedServers = null,
+ ILogger $logger = null,
+ DbHandler $dbHandler = null
+ ) {
+ $this->logger = $logger ? $logger : \OC::$server->getLogger();
+ $this->httpClient = $httpClient ? $httpClient : \OC::$server->getHTTPClientService()->newClient();
+ $this->jobList = $jobList ? $jobList : \OC::$server->getJobList();
+ $this->urlGenerator = $urlGenerator ? $urlGenerator : \OC::$server->getURLGenerator();
+ $this->dbHandler = $dbHandler ? $dbHandler : new DbHandler(\OC::$server->getDatabaseConnection(), \OC::$server->getL10N('federation'));
+ if ($trustedServers) {
+ $this->trustedServers = $trustedServers;
+ } else {
+ $this->trustedServers = new TrustedServers(
+ $this->dbHandler,
+ \OC::$server->getHTTPClientService(),
+ $this->logger,
+ $this->jobList,
+ \OC::$server->getSecureRandom(),
+ \OC::$server->getConfig(),
+ \OC::$server->getEventDispatcher()
+ );
+ }
+ }
+
+ /**
+ * run the job, then remove it from the joblist
+ *
+ * @param JobList $jobList
+ * @param ILogger $logger
+ */
+ public function execute($jobList, ILogger $logger = null) {
+ $target = $this->argument['url'];
+ // only execute if target is still in the list of trusted domains
+ if ($this->trustedServers->isTrustedServer($target)) {
+ $this->parentExecute($jobList, $logger);
+ }
+
+ if (!$this->retainJob) {
+ $jobList->remove($this, $this->argument);
+ }
+ }
+
+ /**
+ * call execute() method of parent
+ *
+ * @param JobList $jobList
+ * @param ILogger $logger
+ */
+ protected function parentExecute($jobList, $logger) {
+ parent::execute($jobList, $logger);
+ }
+
+ protected function run($argument) {
+ $target = $argument['url'];
+ $source = $this->urlGenerator->getAbsoluteURL('/');
+ $source = rtrim($source, '/');
+ $token = $argument['token'];
+
+ $result = null;
+ try {
+ $result = $this->httpClient->get(
+ $target . $this->endPoint,
+ [
+ 'query' =>
+ [
+ 'url' => $source,
+ 'token' => $token
+ ],
+ 'timeout' => 3,
+ 'connect_timeout' => 3,
+ ]
+ );
+
+ $status = $result->getStatusCode();
+
+ } catch (ClientException $e) {
+ $status = $e->getCode();
+ if ($status === Http::STATUS_FORBIDDEN) {
+ $this->logger->info($target . ' refused to exchange a shared secret with you.', ['app' => 'federation']);
+ } else {
+ $this->logger->logException($e, ['app' => 'federation']);
+ }
+ } catch (\Exception $e) {
+ $status = Http::STATUS_INTERNAL_SERVER_ERROR;
+ $this->logger->logException($e, ['app' => 'federation']);
+ }
+
+ // if we received a unexpected response we try again later
+ if (
+ $status !== Http::STATUS_OK
+ && $status !== Http::STATUS_FORBIDDEN
+ ) {
+ $this->retainJob = true;
+ } else {
+ // reset token if we received a valid response
+ $this->dbHandler->addToken($target, '');
+ }
+
+ if ($status === Http::STATUS_OK && $result instanceof IResponse) {
+ $body = $result->getBody();
+ $result = json_decode($body, true);
+ if (isset($result['ocs']['data']['sharedSecret'])) {
+ $this->trustedServers->addSharedSecret(
+ $target,
+ $result['ocs']['data']['sharedSecret']
+ );
+ } else {
+ $this->logger->error(
+ 'remote server "' . $target . '"" does not return a valid shared secret',
+ ['app' => 'federation']
+ );
+ $this->trustedServers->setServerStatus($target, TrustedServers::STATUS_FAILURE);
+ }
+ }
+
+ }
+}
diff --git a/apps/federation/lib/BackgroundJob/RequestSharedSecret.php b/apps/federation/lib/BackgroundJob/RequestSharedSecret.php
new file mode 100644
index 00000000000..040e8e1d8e2
--- /dev/null
+++ b/apps/federation/lib/BackgroundJob/RequestSharedSecret.php
@@ -0,0 +1,184 @@
+<?php
+/**
+ * @author Björn Schießle <schiessle@owncloud.com>
+ * @author Robin Appelman <icewind@owncloud.com>
+ * @author Thomas Müller <thomas.mueller@tmit.eu>
+ *
+ * @copyright Copyright (c) 2016, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+
+namespace OCA\Federation\BackgroundJob;
+
+
+use GuzzleHttp\Exception\ClientException;
+use OC\BackgroundJob\JobList;
+use OC\BackgroundJob\Job;
+use OCA\Federation\DbHandler;
+use OCA\Federation\TrustedServers;
+use OCP\AppFramework\Http;
+use OCP\BackgroundJob\IJobList;
+use OCP\Http\Client\IClient;
+use OCP\ILogger;
+use OCP\IURLGenerator;
+
+/**
+ * Class RequestSharedSecret
+ *
+ * Ask remote ownCloud to request a sharedSecret from this server
+ *
+ * @package OCA\Federation\Backgroundjob
+ */
+class RequestSharedSecret extends Job {
+
+ /** @var IClient */
+ private $httpClient;
+
+ /** @var IJobList */
+ private $jobList;
+
+ /** @var IURLGenerator */
+ private $urlGenerator;
+
+ /** @var DbHandler */
+ private $dbHandler;
+
+ /** @var TrustedServers */
+ private $trustedServers;
+
+ private $endPoint = '/ocs/v2.php/apps/federation/api/v1/request-shared-secret?format=json';
+
+ /** @var ILogger */
+ private $logger;
+
+ /** @var bool */
+ protected $retainJob = false;
+
+ /**
+ * RequestSharedSecret constructor.
+ *
+ * @param IClient $httpClient
+ * @param IURLGenerator $urlGenerator
+ * @param IJobList $jobList
+ * @param TrustedServers $trustedServers
+ * @param DbHandler $dbHandler
+ */
+ public function __construct(
+ IClient $httpClient = null,
+ IURLGenerator $urlGenerator = null,
+ IJobList $jobList = null,
+ TrustedServers $trustedServers = null,
+ DbHandler $dbHandler = null
+ ) {
+ $this->httpClient = $httpClient ? $httpClient : \OC::$server->getHTTPClientService()->newClient();
+ $this->jobList = $jobList ? $jobList : \OC::$server->getJobList();
+ $this->urlGenerator = $urlGenerator ? $urlGenerator : \OC::$server->getURLGenerator();
+ $this->dbHandler = $dbHandler ? $dbHandler : new DbHandler(\OC::$server->getDatabaseConnection(), \OC::$server->getL10N('federation'));
+ $this->logger = \OC::$server->getLogger();
+ if ($trustedServers) {
+ $this->trustedServers = $trustedServers;
+ } else {
+ $this->trustedServers = new TrustedServers(
+ $this->dbHandler,
+ \OC::$server->getHTTPClientService(),
+ $this->logger,
+ $this->jobList,
+ \OC::$server->getSecureRandom(),
+ \OC::$server->getConfig(),
+ \OC::$server->getEventDispatcher()
+ );
+ }
+ }
+
+
+ /**
+ * run the job, then remove it from the joblist
+ *
+ * @param JobList $jobList
+ * @param ILogger $logger
+ */
+ public function execute($jobList, ILogger $logger = null) {
+ $target = $this->argument['url'];
+ // only execute if target is still in the list of trusted domains
+ if ($this->trustedServers->isTrustedServer($target)) {
+ $this->parentExecute($jobList, $logger);
+ }
+
+ if (!$this->retainJob) {
+ $jobList->remove($this, $this->argument);
+ }
+ }
+
+ /**
+ * call execute() method of parent
+ *
+ * @param JobList $jobList
+ * @param ILogger $logger
+ */
+ protected function parentExecute($jobList, $logger) {
+ parent::execute($jobList, $logger);
+ }
+
+ protected function run($argument) {
+
+ $target = $argument['url'];
+ $source = $this->urlGenerator->getAbsoluteURL('/');
+ $source = rtrim($source, '/');
+ $token = $argument['token'];
+
+ try {
+ $result = $this->httpClient->post(
+ $target . $this->endPoint,
+ [
+ 'body' => [
+ 'url' => $source,
+ 'token' => $token,
+ ],
+ 'timeout' => 3,
+ 'connect_timeout' => 3,
+ ]
+ );
+
+ $status = $result->getStatusCode();
+
+ } catch (ClientException $e) {
+ $status = $e->getCode();
+ if ($status === Http::STATUS_FORBIDDEN) {
+ $this->logger->info($target . ' refused to ask for a shared secret.', ['app' => 'federation']);
+ } else {
+ $this->logger->logException($e, ['app' => 'federation']);
+ }
+ } catch (\Exception $e) {
+ $status = Http::STATUS_INTERNAL_SERVER_ERROR;
+ $this->logger->logException($e, ['app' => 'federation']);
+ }
+
+ // if we received a unexpected response we try again later
+ if (
+ $status !== Http::STATUS_OK
+ && $status !== Http::STATUS_FORBIDDEN
+ ) {
+ $this->retainJob = true;
+ }
+
+ if ($status === Http::STATUS_FORBIDDEN) {
+ // clear token if remote server refuses to ask for shared secret
+ $this->dbHandler->addToken($target, '');
+ }
+
+ }
+}
diff --git a/apps/federation/lib/Command/SyncFederationAddressBooks.php b/apps/federation/lib/Command/SyncFederationAddressBooks.php
new file mode 100644
index 00000000000..879d38f8c22
--- /dev/null
+++ b/apps/federation/lib/Command/SyncFederationAddressBooks.php
@@ -0,0 +1,74 @@
+<?php
+/**
+ * @author Björn Schießle <schiessle@owncloud.com>
+ * @author Lukas Reschke <lukas@owncloud.com>
+ * @author Thomas Müller <thomas.mueller@tmit.eu>
+ *
+ * @copyright Copyright (c) 2016, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+namespace OCA\Federation\Command;
+
+use OCA\Federation\DbHandler;
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Helper\ProgressBar;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+
+class SyncFederationAddressBooks extends Command {
+
+ /** @var \OCA\Federation\SyncFederationAddressBooks */
+ private $syncService;
+
+ /**
+ * @param \OCA\Federation\SyncFederationAddressBooks $syncService
+ */
+ function __construct(\OCA\Federation\SyncFederationAddressBooks $syncService) {
+ parent::__construct();
+
+ $this->syncService = $syncService;
+ }
+
+ protected function configure() {
+ $this
+ ->setName('federation:sync-addressbooks')
+ ->setDescription('Synchronizes addressbooks of all federated clouds');
+ }
+
+ /**
+ * @param InputInterface $input
+ * @param OutputInterface $output
+ * @return int
+ */
+ protected function execute(InputInterface $input, OutputInterface $output) {
+
+ $progress = new ProgressBar($output);
+ $progress->start();
+ $this->syncService->syncThemAll(function($url, $ex) use ($progress, $output) {
+ if ($ex instanceof \Exception) {
+ $output->writeln("Error while syncing $url : " . $ex->getMessage());
+
+ } else {
+ $progress->advance();
+ }
+ });
+
+ $progress->finish();
+ $output->writeln('');
+
+ return 0;
+ }
+}
diff --git a/apps/federation/lib/Controller/SettingsController.php b/apps/federation/lib/Controller/SettingsController.php
new file mode 100644
index 00000000000..3adb6fced66
--- /dev/null
+++ b/apps/federation/lib/Controller/SettingsController.php
@@ -0,0 +1,122 @@
+<?php
+/**
+ * @author Björn Schießle <schiessle@owncloud.com>
+ *
+ * @copyright Copyright (c) 2016, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OCA\Federation\Controller;
+
+use OC\HintException;
+use OCA\Federation\TrustedServers;
+use OCP\AppFramework\Controller;
+use OCP\AppFramework\Http;
+use OCP\AppFramework\Http\DataResponse;
+use OCP\IL10N;
+use OCP\IRequest;
+
+
+class SettingsController extends Controller {
+
+ /** @var IL10N */
+ private $l;
+
+ /** @var TrustedServers */
+ private $trustedServers;
+
+ /**
+ * @param string $AppName
+ * @param IRequest $request
+ * @param IL10N $l10n
+ * @param TrustedServers $trustedServers
+ */
+ public function __construct($AppName,
+ IRequest $request,
+ IL10N $l10n,
+ TrustedServers $trustedServers
+ ) {
+ parent::__construct($AppName, $request);
+ $this->l = $l10n;
+ $this->trustedServers = $trustedServers;
+ }
+
+
+ /**
+ * add server to the list of trusted ownClouds
+ *
+ * @param string $url
+ * @return DataResponse
+ * @throws HintException
+ */
+ public function addServer($url) {
+ $this->checkServer($url);
+ $id = $this->trustedServers->addServer($url);
+
+ return new DataResponse(
+ [
+ 'url' => $url,
+ 'id' => $id,
+ 'message' => (string) $this->l->t('Server added to the list of trusted ownClouds')
+ ]
+ );
+ }
+
+ /**
+ * add server to the list of trusted ownClouds
+ *
+ * @param int $id
+ * @return DataResponse
+ */
+ public function removeServer($id) {
+ $this->trustedServers->removeServer($id);
+ return new DataResponse();
+ }
+
+ /**
+ * enable/disable to automatically add servers to the list of trusted servers
+ * once a federated share was created and accepted successfully
+ *
+ * @param bool $autoAddServers
+ */
+ public function autoAddServers($autoAddServers) {
+ $this->trustedServers->setAutoAddServers($autoAddServers);
+ }
+
+ /**
+ * check if the server should be added to the list of trusted servers or not
+ *
+ * @param string $url
+ * @return bool
+ * @throws HintException
+ */
+ protected function checkServer($url) {
+ if ($this->trustedServers->isTrustedServer($url) === true) {
+ $message = 'Server is already in the list of trusted servers.';
+ $hint = $this->l->t('Server is already in the list of trusted servers.');
+ throw new HintException($message, $hint);
+ }
+
+ if ($this->trustedServers->isOwnCloudServer($url) === false) {
+ $message = 'No ownCloud server found';
+ $hint = $this->l->t('No ownCloud server found');
+ throw new HintException($message, $hint);
+ }
+
+ return true;
+ }
+
+}
diff --git a/apps/federation/lib/DAV/FedAuth.php b/apps/federation/lib/DAV/FedAuth.php
new file mode 100644
index 00000000000..bb1041adcdf
--- /dev/null
+++ b/apps/federation/lib/DAV/FedAuth.php
@@ -0,0 +1,54 @@
+<?php
+/**
+ * @author Thomas Müller <thomas.mueller@tmit.eu>
+ *
+ * @copyright Copyright (c) 2016, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+namespace OCA\Federation\DAV;
+
+use OCA\Federation\DbHandler;
+use Sabre\DAV\Auth\Backend\AbstractBasic;
+
+class FedAuth extends AbstractBasic {
+
+ /** @var DbHandler */
+ private $db;
+
+ /**
+ * FedAuth constructor.
+ *
+ * @param DbHandler $db
+ */
+ public function __construct(DbHandler $db) {
+ $this->db = $db;
+ $this->principalPrefix = 'principals/system/';
+ }
+
+ /**
+ * Validates a username and password
+ *
+ * This method should return true or false depending on if login
+ * succeeded.
+ *
+ * @param string $username
+ * @param string $password
+ * @return bool
+ */
+ protected function validateUserPass($username, $password) {
+ return $this->db->auth($username, $password);
+ }
+}
diff --git a/apps/federation/lib/dbhandler.php b/apps/federation/lib/DbHandler.php
index 8720560efc6..8720560efc6 100644
--- a/apps/federation/lib/dbhandler.php
+++ b/apps/federation/lib/DbHandler.php
diff --git a/apps/federation/lib/hooks.php b/apps/federation/lib/Hooks.php
index b7f63d27f55..b7f63d27f55 100644
--- a/apps/federation/lib/hooks.php
+++ b/apps/federation/lib/Hooks.php
diff --git a/apps/federation/lib/Middleware/AddServerMiddleware.php b/apps/federation/lib/Middleware/AddServerMiddleware.php
new file mode 100644
index 00000000000..4b752f51ee4
--- /dev/null
+++ b/apps/federation/lib/Middleware/AddServerMiddleware.php
@@ -0,0 +1,72 @@
+<?php
+/**
+ * @author Björn Schießle <schiessle@owncloud.com>
+ * @author Thomas Müller <thomas.mueller@tmit.eu>
+ *
+ * @copyright Copyright (c) 2016, ownCloud, Inc.
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OCA\Federation\Middleware;
+
+use OC\HintException;
+use OCP\AppFramework\Http;
+use OCP\AppFramework\Http\JSONResponse;
+use OCP\AppFramework\Middleware;
+use OCP\IL10N;
+use OCP\ILogger;
+
+class AddServerMiddleware extends Middleware {
+
+ /** @var string */
+ protected $appName;
+
+ /** @var IL10N */
+ protected $l;
+
+ /** @var ILogger */
+ protected $logger;
+
+ public function __construct($appName, IL10N $l, ILogger $logger) {
+ $this->appName = $appName;
+ $this->l = $l;
+ $this->logger = $logger;
+ }
+
+ /**
+ * Log error message and return a response which can be displayed to the user
+ *
+ * @param \OCP\AppFramework\Controller $controller
+ * @param string $methodName
+ * @param \Exception $exception
+ * @return JSONResponse
+ */
+ public function afterException($controller, $methodName, \Exception $exception) {
+ $this->logger->error($exception->getMessage(), ['app' => $this->appName]);
+ if ($exception instanceof HintException) {
+ $message = $exception->getHint();
+ } else {
+ $message = $exception->getMessage();
+ }
+
+ return new JSONResponse(
+ ['message' => $message],
+ Http::STATUS_BAD_REQUEST
+ );
+
+ }
+
+}
diff --git a/apps/federation/lib/syncfederationaddressbooks.php b/apps/federation/lib/SyncFederationAddressBooks.php
index 209094266ca..209094266ca 100644
--- a/apps/federation/lib/syncfederationaddressbooks.php
+++ b/apps/federation/lib/SyncFederationAddressBooks.php
diff --git a/apps/federation/lib/syncjob.php b/apps/federation/lib/SyncJob.php
index 2b904813b92..2b904813b92 100644
--- a/apps/federation/lib/syncjob.php
+++ b/apps/federation/lib/SyncJob.php
diff --git a/apps/federation/lib/trustedservers.php b/apps/federation/lib/TrustedServers.php
index 3b356ea2a49..3b356ea2a49 100644
--- a/apps/federation/lib/trustedservers.php
+++ b/apps/federation/lib/TrustedServers.php