ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
class.ilWACSignedPath.php
Go to the documentation of this file.
1 <?php
2 // declare(strict_types=1);
3 
9 
10 require_once('./Services/WebAccessChecker/class.ilWACException.php');
11 require_once('class.ilWACToken.php');
12 require_once('./Services/WebAccessChecker/classes/class.ilWebAccessChecker.php');
13 require_once './Services/WebAccessChecker/interfaces/PathType.php';
14 require_once './Services/WebAccessChecker/classes/HttpServiceAware.php';
15 
23 {
24  use HttpServiceAware;
25  const WAC_TOKEN_ID = 'il_wac_token';
26  const WAC_TIMESTAMP_ID = 'il_wac_ts';
27  const WAC_TTL_ID = 'il_wac_ttl';
28  const TS_SUFFIX = 'ts';
29  const TTL_SUFFIX = 'ttl';
30  const MAX_LIFETIME = 600;
34  protected $path_object = null;
38  protected $token_instance = null;
42  protected $type = PathType::FILE;
46  protected static $token_max_lifetime_in_seconds = 3;
50  protected static $cookie_max_lifetime_in_seconds = 300;
54  protected $checked = false;
58  private $httpService;
62  private $cookieFactory;
63 
64 
72  public function __construct(ilWACPath $ilWACPath, GlobalHttpState $httpState, CookieFactory $cookieFactory)
73  {
74  $this->setPathObject($ilWACPath);
75  $this->httpService = $httpState;
76  $this->cookieFactory = $cookieFactory;
77  }
78 
79 
84  public function getSignedPath()
85  {
86  if ($this->getType() !== PathType::FILE) {
88  }
89  if (!$this->getPathObject()->getOriginalRequest()) {
90  return '';
91  }
92  if (!$this->getPathObject()->fileExists()) {
93  // return $this->getPathObject()->getOriginalRequest();
94  }
95 
96  if (strpos($this->getPathObject()->getPath(), '?')) {
97  $path = $this->getPathObject()->getPath() . '&' . self::WAC_TOKEN_ID . '='
98  . $this->getTokenInstance()->getToken();
99  } else {
100  $path = $this->getPathObject()->getPath() . '?' . self::WAC_TOKEN_ID . '='
101  . $this->getTokenInstance()->getToken();
102  }
103 
104  $path = $path . '&' . self::WAC_TTL_ID . '=' . $this->getTokenInstance()->getTTL();
105  $path = $path . '&' . self::WAC_TIMESTAMP_ID . '='
106  . $this->getTokenInstance()->getTimestamp();
107 
108  return $path;
109  }
110 
111 
115  public function isFolderSigned()
116  {
117  $jar = $this->httpService->cookieJar();
118  $cookies = $jar->getAll();
119 
120  $this->setType(PathType::FOLDER);
121  $timestamp = time();
122  $plain_token = $this->buildTokenInstance($timestamp, self::getCookieMaxLifetimeInSeconds());
123  $name = $plain_token->getHashedId();
124 
125  // Token
126  $default_token = '';
127  $token_cookie_value = $this->httpService->request()->getCookieParams()[$name] ?? $default_token;
128  // Timestamp
129  $default_timestamp = 0;
130  $timestamp_cookie_value = $this->httpService->request()->getCookieParams()[$name . self::TS_SUFFIX] ?? $default_timestamp;
131  $timestamp_cookie_value = intval($timestamp_cookie_value);
132  // TTL
133  $default_ttl = 0;
134  $ttl_cookie_value = $this->httpService->request()->getCookieParams()[$name . self::TTL_SUFFIX] ?? $default_ttl;
135  $ttl_cookie_value = intval($ttl_cookie_value);
136 
137  $this->getPathObject()->setToken($token_cookie_value);
138  $this->getPathObject()->setTimestamp($timestamp_cookie_value);
139  $this->getPathObject()->setTTL($ttl_cookie_value);
140  $this->buildAndSetTokenInstance($timestamp, self::getCookieMaxLifetimeInSeconds());
141 
142  return $this->getPathObject()->hasToken();
143  }
144 
145 
150  public function isFolderTokenValid()
151  {
152  if (!$this->isFolderSigned()) {
153  return false;
154  }
155 
156  return $this->checkToken();
157  }
158 
159 
163  protected function saveFolderToken()
164  {
165  $cookie_lifetime = self::getCookieMaxLifetimeInSeconds();
166  $id = $this->getTokenInstance()->getHashedId();
167  $expire = time() + $cookie_lifetime + 3600;
168  $secure = true;
169  $domain = null;
170  $http_only = true;
171  $path = '/';
172 
173  $tokenCookie = $this->cookieFactory->create($id, $this->getTokenInstance()->getToken())
174  ->withExpires($expire)
175  ->withPath($path)
176  ->withSecure($secure)
177  ->withDomain($domain)
178  ->withHttpOnly($http_only);
179 
180  $timestampCookie = $this->cookieFactory->create($id . self::TS_SUFFIX, time())
181  ->withExpires($expire)
182  ->withPath($path)
183  ->withDomain($domain)
184  ->withSecure($secure)
185  ->withHttpOnly($http_only);
186 
187  $ttlCookie = $this->cookieFactory->create($id . self::TTL_SUFFIX, $cookie_lifetime)
188  ->withExpires($expire)
189  ->withPath($path)
190  ->withDomain($domain)
191  ->withSecure($secure)
192  ->withHttpOnly($http_only);
193 
194  $response = $this->httpService->cookieJar()->with($tokenCookie)
195  ->with($timestampCookie)
196  ->with($ttlCookie)
197  ->renderIntoResponseHeader($this->httpService->response());
198 
199  // FIX: currently the cookies are never stored
200  foreach ($this->httpService->cookieJar()->getAll() as $cookie) {
201  setcookie($cookie->getName(), $cookie->getValue(), $cookie->getExpires(), $cookie->getPath(), $cookie->getDomain(), $cookie->getSecure(), $cookie->getHttpOnly());
202  }
203 
204  $this->httpService->saveResponse($response);
205  }
206 
207 
211  public function revalidatingFolderToken()
212  {
213  if ($this->getType() !== PathType::FOLDER) {
214  return false;
215  }
216  $this->buildAndSetTokenInstance(time(), self::getCookieMaxLifetimeInSeconds());
217  $this->saveFolderToken();
218 
219  return true;
220  }
221 
222 
226  public function isSignedPath()
227  {
228  return ($this->getPathObject()->hasToken() && $this->getPathObject()->hasTimestamp()
229  && $this->getPathObject()->hasTTL());
230  }
231 
232 
237  public function isSignedPathValid()
238  {
239  $this->buildAndSetTokenInstance($this->getPathObject()->getTimestamp(), $this->getPathObject()->getTTL());
240 
241  return $this->checkToken();
242  }
243 
244 
252  public static function signFile($path_to_file)
253  {
254  if (!$path_to_file) {
255  return '';
256  }
257  $ilWACPath = new ilWACPath($path_to_file);
258  if (!$ilWACPath->getClient()) {
259  return $path_to_file;
260  }
261  $obj = new self($ilWACPath, self::http(), new CookieFactoryImpl());
262  $obj->setType(PathType::FILE);
263  $obj->buildAndSetTokenInstance(time(), self::getTokenMaxLifetimeInSeconds());
264 
265  return $obj->getSignedPath();
266  }
267 
268 
273  public static function signFolderOfStartFile($start_file_path)
274  {
275  $obj = new self(new ilWACPath($start_file_path), self::http(), new CookieFactoryImpl());
276  $obj->setType(PathType::FOLDER);
277  $obj->buildAndSetTokenInstance(time(), self::getCookieMaxLifetimeInSeconds());
278  $obj->saveFolderToken();
279  }
280 
281 
285  public function getTokenInstance()
286  {
287  return $this->token_instance;
288  }
289 
290 
296  {
297  $this->token_instance = $token_instance;
298  }
299 
300 
304  public function getType()
305  {
306  return (int) $this->type;
307  }
308 
309 
314  public function setType($type)
315  {
316  assert(is_int($type));
317  $this->type = $type;
318  }
319 
320 
324  public function getPathObject()
325  {
326  return $this->path_object;
327  }
328 
329 
335  {
336  $this->path_object = $path_object;
337  }
338 
339 
344  protected function checkToken()
345  {
346  $request_token = $this->getPathObject()->getToken();
347  $request_ttl = $this->getPathObject()->getTTL();
348  $request_timestamp = $this->getPathObject()->getTimestamp();
349  $current_timestamp = time();
350 
351  $timestamp_valid = ($current_timestamp < ($request_timestamp + $request_ttl));
352 
353  if (!$timestamp_valid) {
354  $this->setChecked(true);
355 
356  return false;
357  }
358 
359  $simulatedTokenInstance = $this->buildTokenInstance($request_timestamp, $request_ttl);
360  $token_valid = ($simulatedTokenInstance->getToken() == $request_token);
361 
362  if (!$token_valid) {
363  $this->setChecked(true);
364 
365  return false;
366  }
367 
368  return true;
369  }
370 
371 
379  protected function buildTokenInstance($timestamp = 0, $ttl = 0)
380  {
381  assert(is_int($timestamp));
382  assert(is_int($ttl));
383  if (!$this->getType()) {
385  }
386 
387  switch ($this->getType()) {
388  case PathType::FOLDER:
389  $path = $this->getPathObject()->getModulePath();
390  break;
391  case PathType::FILE:
392  $path = $this->getPathObject()->getPathWithoutQuery();
393  break;
394  default:
395  $path = $this->getPathObject()->getPathWithoutQuery();
396  break;
397  }
398 
399  $client = $this->getPathObject()->getClient();
400  $timestamp = $timestamp ? $timestamp : $this->getPathObject()->getTimestamp();
401  $ttl = $ttl ? $ttl : $this->getPathObject()->getTTL();
402 
403  return new ilWACToken($path, $client, $timestamp, $ttl);
404  }
405 
406 
414  public function buildAndSetTokenInstance($timestamp = 0, $ttl = 0)
415  {
416  assert(is_int($timestamp));
417  assert(is_int($ttl));
418 
419  $this->setTokenInstance($this->buildTokenInstance($timestamp, $ttl));
420  }
421 
422 
426  public static function getTokenMaxLifetimeInSeconds()
427  {
428  return self::$token_max_lifetime_in_seconds;
429  }
430 
431 
439  {
440  assert(is_int($token_max_lifetime_in_seconds));
441  if ($token_max_lifetime_in_seconds > self::MAX_LIFETIME) {
443  }
444  self::$token_max_lifetime_in_seconds = $token_max_lifetime_in_seconds;
445  }
446 
447 
451  public static function getCookieMaxLifetimeInSeconds()
452  {
453  return self::$cookie_max_lifetime_in_seconds;
454  }
455 
456 
465  {
466  assert(is_int($cookie_max_lifetime_in_seconds));
467  if ($cookie_max_lifetime_in_seconds > self::MAX_LIFETIME) {
469  }
470  self::$cookie_max_lifetime_in_seconds = $cookie_max_lifetime_in_seconds;
471  }
472 
473 
477  protected function getRelevantLifeTime()
478  {
479  $request_ttl = $this->getPathObject()->getTTL();
480  if ($request_ttl > 0) {
481  return $request_ttl;
482  }
483  switch ($this->getType()) {
484  case PathType::FOLDER:
485  $life_time = self::getCookieMaxLifetimeInSeconds();
486  break;
487  case PathType::FILE:
488  $life_time = self::getTokenMaxLifetimeInSeconds();
489  break;
490  default:
491  $life_time = 0;
492  break;
493  }
494 
495  return $life_time;
496  }
497 
498 
502  public function isChecked()
503  {
504  return (bool) $this->checked;
505  }
506 
507 
512  public function setChecked($checked)
513  {
514  assert(is_bool($checked));
515  $this->checked = $checked;
516  }
517 }
$expire
Definition: saml2-acs.php:140
Interface GlobalHttpState.
$path
Definition: aliased.php:25
buildTokenInstance($timestamp=0, $ttl=0)
Class ilWACException.
static getCookieMaxLifetimeInSeconds()
setTokenInstance(ilWACToken $token_instance)
if(!array_key_exists('StateId', $_REQUEST)) $id
__construct(ilWACPath $ilWACPath, GlobalHttpState $httpState, CookieFactory $cookieFactory)
ilWACSignedPath constructor.
Class ilWACPath.
if($_SERVER['argc']< 4) $client
Definition: cron.php:12
trait HttpServiceAware
Trait HttpServiceAware.
static signFolderOfStartFile($start_file_path)
static http()
Fetches the global http state from ILIAS.
setPathObject(ilWACPath $path_object)
static setCookieMaxLifetimeInSeconds($cookie_max_lifetime_in_seconds)
buildAndSetTokenInstance($timestamp=0, $ttl=0)
Class ilWACSignedPath.
static signFile($path_to_file)
Class ilWACToken.
foreach($mandatory_scripts as $file) $timestamp
Definition: buildRTE.php:81
trait HttpServiceAware
Trait HttpServiceAware.
static setTokenMaxLifetimeInSeconds($token_max_lifetime_in_seconds)
static getTokenMaxLifetimeInSeconds()
if(!array_key_exists('domain', $_REQUEST)) $domain
Definition: resume.php:8
static $cookie_max_lifetime_in_seconds
$response