Guest User

Untitled

a guest
Mar 11th, 2016
61
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 8.61 KB | None | 0 0
  1. <?php
  2. /**
  3.  * ownCloud - gallery
  4.  *
  5.  * This file is licensed under the Affero General Public License version 3 or
  6.  * later. See the COPYING file.
  7.  *
  8.  * @author Olivier Paroz <owncloud@interfasys.ch>
  9.  * @author Bernhard Posselt <dev@bernhard-posselt.com>
  10.  * @author Authors of \OCA\Files_Sharing\Helper
  11.  *
  12.  * @copyright Olivier Paroz 2014-2015
  13.  * @copyright Bernhard Posselt 2012-2015
  14.  * @copyright Authors of \OCA\Files_Sharing\Helper 2014-2015
  15.  */
  16.  
  17. namespace OCA\Gallery\Middleware;
  18.  
  19. use OCP\IRequest;
  20. use OCP\IURLGenerator;
  21. use OCP\ISession;
  22. use OCP\ILogger;
  23. use OCP\Share;
  24. use OCP\Security\IHasher;
  25.  
  26. use OCP\AppFramework\Http;
  27. use OCP\AppFramework\Utility\IControllerMethodReflector;
  28.  
  29. use OCA\Gallery\Environment\Environment;
  30. use OCP\Share\IManager;
  31.  
  32. /**
  33.  * Checks that we have a valid token linked to a valid resource and that the
  34.  * user is authorised to access it
  35.  *
  36.  * Once all checks have been passed, the environment is ready to use
  37.  *
  38.  * @package OCA\Gallery\Middleware
  39.  */
  40. class EnvCheckMiddleware extends CheckMiddleware {
  41.  
  42.     /** @var IHasher */
  43.     private $hasher;
  44.     /** @var ISession */
  45.     private $session;
  46.     /** @var Environment */
  47.     private $environment;
  48.     /** @var IControllerMethodReflector */
  49.     protected $reflector;
  50.  
  51.     protected $shareManager;
  52.  
  53.     /***
  54.      * Constructor
  55.      *
  56.      * @param string $appName
  57.      * @param IRequest $request
  58.      * @param IHasher $hasher
  59.      * @param ISession $session
  60.      * @param Environment $environment
  61.      * @param IControllerMethodReflector $reflector
  62.      * @param IURLGenerator $urlGenerator
  63.      * @param ILogger $logger
  64.      */
  65.     public function __construct(
  66.         $appName,
  67.         IRequest $request,
  68.         IHasher $hasher,
  69.         ISession $session,
  70.         Environment $environment,
  71.         IControllerMethodReflector $reflector,
  72.         IURLGenerator $urlGenerator,
  73.         ILogger $logger,
  74.         IManager $shareManager
  75.     ) {
  76.         parent::__construct(
  77.             $appName,
  78.             $request,
  79.             $urlGenerator,
  80.             $logger
  81.         );
  82.  
  83.         $this->hasher = $hasher;
  84.         $this->session = $session;
  85.         $this->environment = $environment;
  86.         $this->reflector = $reflector;
  87.         $this->shareManager = $shareManager;
  88.     }
  89.  
  90.     /**
  91.      * Checks that we have a valid token linked to a valid resource and that the
  92.      * user is authorised to access it
  93.      *
  94.      * Inspects the controller method annotations and if PublicPage is found
  95.      * it checks that we have a token and an optional password giving access to a valid resource.
  96.      * Once that's done, the environment is setup so that our services can find the resources they
  97.      * need.
  98.      *
  99.      * The checks are not performed on "guest" pages and the environment is not setup. Typical
  100.      * guest pages are anonymous error ages
  101.      *
  102.      * @inheritDoc
  103.      */
  104.     public function beforeController($controller, $methodName) {
  105.         if ($this->reflector->hasAnnotation('Guest')) {
  106.             return;
  107.         }
  108.         $isPublicPage = $this->reflector->hasAnnotation('PublicPage');
  109.         if ($isPublicPage) {
  110.             $this->validateAndSetTokenBasedEnv();
  111.         } else {
  112.             $this->environment->setStandardEnv();
  113.         }
  114.     }
  115.  
  116.     /**
  117.      * Checks that we have a token and an optional password giving access to a
  118.      * valid resource. Sets the token based environment after that
  119.      *
  120.      * @throws CheckException
  121.      */
  122.     private function validateAndSetTokenBasedEnv() {
  123.         $token = $this->request->getParam('token');
  124.         if (!$token) {
  125.             throw new CheckException(
  126.                 "Can't access a public resource without a token", Http::STATUS_NOT_FOUND
  127.             );
  128.         } else {
  129.             $linkItem = $this->getLinkItem($token);
  130.             $password = $this->request->getParam('password');
  131.             // Let's see if the user needs to provide a password
  132.             $this->checkAuthorisation($linkItem, $password);
  133.  
  134.             $this->environment->setTokenBasedEnv($linkItem);
  135.         }
  136.     }
  137.  
  138.     /**
  139.      * Validates a token to make sure its linked to a valid resource
  140.      *
  141.      * Logic mostly duplicated from @see \OCA\Files_Sharing\Helper
  142.      *
  143.      * @fixme setIncognitoMode in 8.1 https://github.com/owncloud/core/pull/12912
  144.      *
  145.      * @param string $token
  146.      *
  147.      * @return array
  148.      *
  149.      * @throws CheckException
  150.      */
  151.     private function getLinkItem($token) {
  152.         // Allows a logged in user to access public links
  153.         \OC_User::setIncognitoMode(true);
  154.        
  155.         // creating an object results in failure....HELP!!
  156.         $linkItem = $this->shareManager->getShareByToken($token);
  157.  
  158.         // Checks passed, let's store the linkItem
  159.         $linkItem = Share::getShareByToken($token, false);
  160.         $this->checkLinkItemExists($linkItem);
  161.         $this->checkLinkItemIsValid($linkItem, $token);
  162.         $this->checkItemType($linkItem);
  163.         return $linkItem;
  164.     }
  165.  
  166.     /**
  167.      * Makes sure that the token exists
  168.      *
  169.      * @param array|bool $linkItem
  170.      *
  171.      * @throws CheckException
  172.      */
  173.     private function checkLinkItemExists($linkItem) {
  174.         if ($linkItem === false
  175.             || ($linkItem['item_type'] !== 'file'
  176.                 && $linkItem['item_type'] !== 'folder')
  177.         ) {
  178.             $message = 'Passed token parameter is not valid';
  179.             throw new CheckException($message, Http::STATUS_BAD_REQUEST);
  180.         }
  181.     }
  182.  
  183.     /**
  184.      * Makes sure that the token contains all the information that we need
  185.      *
  186.      * @param array|bool $linkItem
  187.      * @param string $token
  188.      *
  189.      * @throws CheckException
  190.      */
  191.     private function checkLinkItemIsValid($linkItem, $token) {
  192.         if (!isset($linkItem['uid_owner'])
  193.             || !isset($linkItem['file_source'])
  194.         ) {
  195.             $message =
  196.                 'Passed token seems to be valid, but it does not contain all necessary information . ("'
  197.                 . $token . '")';
  198.             throw new CheckException($message, Http::STATUS_NOT_FOUND);
  199.         }
  200.     }
  201.  
  202.     /**
  203.      * Makes sure an item type was set for that token
  204.      *
  205.      * @param array|bool $linkItem
  206.      *
  207.      * @throws CheckException
  208.      */
  209.     private function checkItemType($linkItem) {
  210.         if (!isset($linkItem['item_type'])) {
  211.             $message = 'No item type set for share id: ' . $linkItem['id'];
  212.             throw new CheckException($message, Http::STATUS_NOT_FOUND);
  213.         }
  214.     }
  215.  
  216.     /**
  217.      * Checks if a password is required or if the one supplied is working
  218.      *
  219.      * @param array|bool $linkItem
  220.      * @param string|null $password optional password
  221.      *
  222.      * @throws CheckException
  223.      */
  224.     private function checkAuthorisation($linkItem, $password) {
  225.         $passwordRequired = isset($linkItem['share_with']);
  226.  
  227.         if ($passwordRequired) {
  228.             if ($password !== null) {
  229.                 $this->authenticate($linkItem, $password);
  230.             } else {
  231.                 $this->checkSession($linkItem);
  232.             }
  233.         }
  234.     }
  235.  
  236.     /**
  237.      * Authenticate link item with the given password
  238.      * or with the session if no password was given.
  239.      *
  240.      * @fixme @LukasReschke says: Migrate old hashes to new hash format
  241.      * Due to the fact that there is no reasonable functionality to update the password
  242.      * of an existing share no migration is yet performed there.
  243.      * The only possibility is to update the existing share which will result in a new
  244.      * share ID and is a major hack.
  245.      *
  246.      * In the future the migration should be performed once there is a proper method
  247.      * to update the share's password. (for example `$share->updatePassword($password)`
  248.      *
  249.      * @link https://github.com/owncloud/core/issues/10671
  250.      *
  251.      * @param array|bool $linkItem
  252.      * @param string $password
  253.      *
  254.      * @return bool true if authorized, an exception is raised otherwise
  255.      *
  256.      * @throws CheckException
  257.      */
  258.     private function authenticate($linkItem, $password) {
  259.         if ((int)$linkItem['share_type'] === Share::SHARE_TYPE_LINK) {
  260.             $this->checkPassword($linkItem, $password);
  261.         } else {
  262.             throw new CheckException(
  263.                 'Unknown share type ' . $linkItem['share_type'] . ' for share id '
  264.                 . $linkItem['id'], Http::STATUS_NOT_FOUND
  265.             );
  266.         }
  267.  
  268.         return true;
  269.     }
  270.  
  271.     /**
  272.      * Validates the given password
  273.      *
  274.      * @param array|bool $linkItem
  275.      * @param string $password
  276.      *
  277.      * @throws CheckException
  278.      */
  279.     private function checkPassword($linkItem, $password) {
  280.         $newHash = '';
  281.         if ($this->hasher->verify($password, $linkItem['share_with'], $newHash)) {
  282.             // Save item id in session for future requests
  283.             $this->session->set('public_link_authenticated', $linkItem['id']);
  284.             // @codeCoverageIgnoreStart
  285.             if (!empty($newHash)) {
  286.                 // For future use
  287.             }
  288.             // @codeCoverageIgnoreEnd
  289.         } else {
  290.             throw new CheckException("Wrong password", Http::STATUS_UNAUTHORIZED);
  291.         }
  292.     }
  293.  
  294.     /**
  295.      * Makes sure the user is already properly authenticated when a password is required and none
  296.      * was provided
  297.      *
  298.      * @param array|bool $linkItem
  299.      *
  300.      * @throws CheckException
  301.      */
  302.     private function checkSession($linkItem) {
  303.         // Not authenticated ?
  304.         if (!$this->session->exists('public_link_authenticated')
  305.             || $this->session->get('public_link_authenticated') !== $linkItem['id']
  306.         ) {
  307.             throw new CheckException("Missing password", Http::STATUS_UNAUTHORIZED);
  308.         }
  309.     }
  310.  
  311. }
Add Comment
Please, Sign In to add comment