2015-11-10 12:50:59 +03:00
< ? php
/**
* @ author Björn Schießle < schiessle @ owncloud . com >
2016-01-12 17:02:16 +03:00
* @ 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 >
2015-11-10 12:50:59 +03:00
*
2016-01-12 17:02:16 +03:00
* @ copyright Copyright ( c ) 2016 , ownCloud , Inc .
2015-11-10 12:50:59 +03:00
* @ 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 ;
2015-11-19 19:10:42 +03:00
use OCP\BackgroundJob\IJobList ;
2015-12-21 17:48:02 +03:00
use OCP\ILogger ;
2015-11-10 12:50:59 +03:00
use OCP\IRequest ;
use OCP\Security\ISecureRandom ;
use OCP\Security\StringUtils ;
/**
* 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 ;
2015-11-19 19:10:42 +03:00
/** @var IJobList */
2015-11-10 12:50:59 +03:00
private $jobList ;
/** @var TrustedServers */
private $trustedServers ;
/** @var DbHandler */
private $dbHandler ;
2015-12-21 17:48:02 +03:00
/** @var ILogger */
private $logger ;
2015-11-10 12:50:59 +03:00
/**
2015-11-19 19:10:42 +03:00
* OCSAuthAPI constructor .
2015-11-10 12:50:59 +03:00
*
* @ param IRequest $request
* @ param ISecureRandom $secureRandom
2015-11-19 19:10:42 +03:00
* @ param IJobList $jobList
2015-11-10 12:50:59 +03:00
* @ param TrustedServers $trustedServers
* @ param DbHandler $dbHandler
2015-12-21 17:48:02 +03:00
* @ param ILogger $logger
2015-11-10 12:50:59 +03:00
*/
public function __construct (
IRequest $request ,
ISecureRandom $secureRandom ,
2015-11-19 19:10:42 +03:00
IJobList $jobList ,
2015-11-10 12:50:59 +03:00
TrustedServers $trustedServers ,
2015-12-21 17:48:02 +03:00
DbHandler $dbHandler ,
ILogger $logger
2015-11-10 12:50:59 +03:00
) {
$this -> request = $request ;
$this -> secureRandom = $secureRandom ;
$this -> jobList = $jobList ;
$this -> trustedServers = $trustedServers ;
$this -> dbHandler = $dbHandler ;
2015-12-21 17:48:02 +03:00
$this -> logger = $logger ;
2015-11-10 12:50:59 +03:00
}
/**
* 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 ) {
2016-02-01 15:38:46 +03:00
$this -> logger -> log ( \OCP\Util :: ERROR , 'remote server not trusted (' . $url . ') while requesting shared secret' , [ 'app' => 'federation' ]);
2015-11-10 12:50:59 +03:00
return new \OC_OCS_Result ( null , HTTP :: STATUS_FORBIDDEN );
}
2015-11-19 13:48:21 +03:00
// if both server initiated the exchange of the shared secret the greater
// token wins
$localToken = $this -> dbHandler -> getToken ( $url );
if ( strcmp ( $localToken , $token ) > 0 ) {
2016-02-01 15:38:46 +03:00
$this -> logger -> log ( \OCP\Util :: ERROR , 'remote server (' . $url . ') presented lower token' , [ 'app' => 'federation' ]);
2015-11-19 13:48:21 +03:00
return new \OC_OCS_Result ( null , HTTP :: STATUS_FORBIDDEN );
}
2015-11-10 12:50:59 +03:00
$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' );
2015-12-21 17:48:02 +03:00
if ( $this -> trustedServers -> isTrustedServer ( $url ) === false ) {
2016-02-01 15:38:46 +03:00
$this -> logger -> log ( \OCP\Util :: ERROR , 'remote server not trusted (' . $url . ') while getting shared secret' , [ 'app' => 'federation' ]);
2015-12-21 17:48:02 +03:00
return new \OC_OCS_Result ( null , HTTP :: STATUS_FORBIDDEN );
}
if ( $this -> isValidToken ( $url , $token ) === false ) {
2016-02-01 15:38:46 +03:00
$this -> logger -> log ( \OCP\Util :: ERROR , 'remote server (' . $url . ') didn\'t send a valid token (got ' . $token . ') while getting shared secret' , [ 'app' => 'federation' ]);
2015-11-10 12:50:59 +03:00
return new \OC_OCS_Result ( null , HTTP :: STATUS_FORBIDDEN );
}
2016-01-11 22:05:30 +03:00
$sharedSecret = $this -> secureRandom -> generate ( 32 );
2015-11-10 12:50:59 +03:00
$this -> trustedServers -> addSharedSecret ( $url , $sharedSecret );
2015-11-19 13:48:21 +03:00
// reset token after the exchange of the shared secret was successful
$this -> dbHandler -> addToken ( $url , '' );
2015-11-10 12:50:59 +03:00
return new \OC_OCS_Result ([ 'sharedSecret' => $sharedSecret ], Http :: STATUS_OK );
}
protected function isValidToken ( $url , $token ) {
$storedToken = $this -> dbHandler -> getToken ( $url );
2015-12-11 08:17:47 +03:00
return hash_equals ( $storedToken , $token );
2015-11-10 12:50:59 +03:00
}
}