Skip to content

Commit

Permalink
Support signed urls
Browse files Browse the repository at this point in the history
  • Loading branch information
DeepDiver1975 committed Jul 3, 2020
1 parent 8095322 commit 4c6c090
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 5 deletions.
52 changes: 47 additions & 5 deletions apps/dav/lib/Connector/Sabre/Auth.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
*/
namespace OCA\DAV\Connector\Sabre;

use Exception;
use OC\AppFramework\Http\Request;
use OC\Authentication\Exceptions\PasswordLoginForbiddenException;
use OC\Authentication\TwoFactorAuth\Manager;
Expand All @@ -55,8 +54,6 @@ class Auth extends AbstractBasic {
private $userSession;
/** @var IRequest */
private $request;
/** @var string */
private $currentUser;
/** @var Manager */
private $twoFactorManager;
/** @var AccountModuleManager */
Expand Down Expand Up @@ -158,7 +155,7 @@ public function check(RequestInterface $request, ResponseInterface $response) {
throw new NotAuthenticated($e->getMessage(), $e->getCode(), $e);
} catch (NotAuthenticated $e) {
throw $e;
} catch (Exception $e) {
} catch (\Exception $e) {
$class = \get_class($e);
$msg = $e->getMessage();
throw new ServiceUnavailable("$class: $msg");
Expand Down Expand Up @@ -230,7 +227,7 @@ private function auth(RequestInterface $request, ResponseInterface $response) {
$this->checkAccountModule($user);
$uid = $user->getUID();
\OC_Util::setupFS($uid);
$this->currentUser = $uid;
$currentUser = $uid;
$this->session->close();
return [true, $this->principalPrefix . $uid];
}
Expand All @@ -246,6 +243,19 @@ private function auth(RequestInterface $request, ResponseInterface $response) {
$startPos = \strrpos($data[1], '/') + 1;
$data[1] = \substr_replace($data[1], $user->getUID(), $startPos);
}

// signed url handling
$params = $request->getQueryParameters();
$urlSignature = $params['OC-Signature'];
$urlCredential = $params['OC-Credential'];
if ($urlSignature && $urlCredential && $this->signedRequestIsValid($request)) {
// TODO: setup session
$user = \OC::$server->getUserManager()->get($urlCredential);
$this->userSession->setUser($user);
\OC_Util::setupFS($urlCredential);
$this->session->close();
return [true, $this->principalPrefix . $urlCredential];
}
return $data;
}

Expand Down Expand Up @@ -274,4 +284,36 @@ public function challenge(RequestInterface $request, ResponseInterface $response
$response->addHeader('WWW-Authenticate', "$schema realm=\"{$this->realm}\", charset=\"UTF-8\"");
$response->setStatus(401);
}

private function signedRequestIsValid(RequestInterface $request) {
$params = $request->getQueryParameters();
$urlSignature = $params['OC-Signature'];
$urlCredential = $params['OC-Credential'];
$urlDate = $params['OC-Date'];
$urlExpires = $params['OC-Expires'];
$urlVerb = $params['OC-Verb'];

unset($params['OC-Signature']);

$qp = \http_build_query($params);
$url = \Sabre\Uri\parse($request->getAbsoluteUrl());
$url['query'] = $qp;
$url = \Sabre\Uri\build($url);

$signingKey = \OC::$server->getConfig()->getUserValue($urlCredential, 'core', 'signing-key');

$hash = \hash_pbkdf2("sha512", $url, $signingKey, 10000, 64, false);
if ($hash !== $urlSignature) {
return false;
}
if (\strtoupper($request->getMethod()) !== \strtoupper($urlVerb)) {
return false;
}
$date = new \DateTime($urlDate);
$date->add(new \DateInterval("PT${urlExpires}S"));
if ($date < new \DateTime()) {
return false;
}
return true;
}
}
21 changes: 21 additions & 0 deletions core/Controller/CloudController.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,25 @@ public function getCurrentUser() {
];
return ['data' => $data];
}

/**
* @NoAdminRequired
* @NoCSRFRequired
* @CORS
*
* @return array
* @throws \OCP\PreConditionNotMetException
*/
public function getSigningKey(): array {
$userId = \OC_User::getUser();
$signingKey = \OC::$server->getConfig()->getUserValue($userId, 'core', 'signing-key', null);
if ($signingKey === null) {
$signingKey = \OC::$server->getSecureRandom()->generate(64);
\OC::$server->getConfig()->setUserValue($userId, 'core', 'signing-key', $signingKey, null);
}
return ['data' => [
'user' => $userId,
'signing-key' => $signingKey
]];
}
}
1 change: 1 addition & 0 deletions core/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
'ocs' => [
['root' => '/cloud', 'name' => 'Cloud#getCapabilities', 'url' => '/capabilities', 'verb' => 'GET'],
['root' => '/cloud', 'name' => 'Cloud#getCurrentUser', 'url' => '/user', 'verb' => 'GET'],
['root' => '/cloud', 'name' => 'Cloud#getSigningKey', 'url' => '/user/signing-key', 'verb' => 'GET'],
['root' => '/cloud', 'name' => 'Roles#getRoles', 'url' => '/roles', 'verb' => 'GET'],
['root' => '/cloud', 'name' => 'UserSync#syncUser', 'url' => '/user-sync/{userId}', 'verb' => 'POST'],
]
Expand Down
1 change: 1 addition & 0 deletions lib/private/OCS/CoreCapabilities.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ public function getCapabilities() {
'pollinterval' => $this->config->getSystemValue('pollinterval', 60),
'webdav-root' => $this->config->getSystemValue('webdav-root', 'remote.php/webdav'),
'status' => Util::getStatusInfo(true),
'support-url-signing' => true,
]
];
}
Expand Down

0 comments on commit 4c6c090

Please sign in to comment.