ILIAS  release_7 Revision v7.30-3-g800a261c036
All Data Structures Namespaces Files Functions Variables Modules Pages
class.ilWACSignedPath.php
Go to the documentation of this file.
1 <?php
18 // declare(strict_types=1);
24 
25 require_once('./Services/WebAccessChecker/class.ilWACException.php');
26 require_once('class.ilWACToken.php');
27 require_once('./Services/WebAccessChecker/classes/class.ilWebAccessChecker.php');
28 require_once './Services/WebAccessChecker/interfaces/PathType.php';
29 require_once './Services/WebAccessChecker/classes/HttpServiceAware.php';
30 
38 {
39  use HttpServiceAware;
40  const WAC_TOKEN_ID = 'il_wac_token';
41  const WAC_TIMESTAMP_ID = 'il_wac_ts';
42  const WAC_TTL_ID = 'il_wac_ttl';
43  const TS_SUFFIX = 'ts';
44  const TTL_SUFFIX = 'ttl';
45  const MAX_LIFETIME = 600;
49  protected $path_object = null;
53  protected $token_instance = null;
57  protected $type = PathType::FILE;
61  protected static $token_max_lifetime_in_seconds = 3;
65  protected static $cookie_max_lifetime_in_seconds = 300;
69  protected $checked = false;
73  private $httpService;
77  private $cookieFactory;
78 
79 
87  public function __construct(ilWACPath $ilWACPath, GlobalHttpState $httpState, CookieFactory $cookieFactory)
88  {
89  $this->setPathObject($ilWACPath);
90  $this->httpService = $httpState;
91  $this->cookieFactory = $cookieFactory;
92  }
93 
94 
99  public function getSignedPath()
100  {
101  if ($this->getType() !== PathType::FILE) {
103  }
104  if (!$this->getPathObject()->getOriginalRequest()) {
105  return '';
106  }
107  if (!$this->getPathObject()->fileExists()) {
108  // return $this->getPathObject()->getOriginalRequest();
109  }
110 
111  if (strpos($this->getPathObject()->getPath(), '?')) {
112  $path = $this->getPathObject()->getPath() . '&' . self::WAC_TOKEN_ID . '='
113  . $this->getTokenInstance()->getToken();
114  } else {
115  $path = $this->getPathObject()->getPath() . '?' . self::WAC_TOKEN_ID . '='
116  . $this->getTokenInstance()->getToken();
117  }
118 
119  $path = $path . '&' . self::WAC_TTL_ID . '=' . $this->getTokenInstance()->getTTL();
120  $path = $path . '&' . self::WAC_TIMESTAMP_ID . '='
121  . $this->getTokenInstance()->getTimestamp();
122 
123  return $path;
124  }
125 
126 
130  public function isFolderSigned()
131  {
132  $jar = $this->httpService->cookieJar();
133  $cookies = $jar->getAll();
134 
135  $this->setType(PathType::FOLDER);
136  $plain_token = $this->buildTokenInstance();
137  $name = $plain_token->getHashedId();
138 
139  // Token
140  $default_token = '';
141  $token_cookie_value = $this->httpService->request()->getCookieParams()[$name] ?? $default_token;
142  // Timestamp
143  $default_timestamp = 0;
144  $timestamp_cookie_value = $this->httpService->request()->getCookieParams()[$name . self::TS_SUFFIX] ?? $default_timestamp;
145  $timestamp_cookie_value = intval($timestamp_cookie_value);
146  // TTL
147  $default_ttl = 0;
148  $ttl_cookie_value = $this->httpService->request()->getCookieParams()[$name . self::TTL_SUFFIX] ?? $default_ttl;
149  $ttl_cookie_value = intval($ttl_cookie_value);
150 
151  $this->getPathObject()->setToken($token_cookie_value);
152  $this->getPathObject()->setTimestamp($timestamp_cookie_value);
153  $this->getPathObject()->setTTL($ttl_cookie_value);
154  $this->buildAndSetTokenInstance();
155 
156  return $this->getPathObject()->hasToken();
157  }
158 
159 
164  public function isFolderTokenValid()
165  {
166  if (!$this->isFolderSigned()) {
167  return false;
168  }
169 
170  return $this->checkToken();
171  }
172 
173 
177  protected function saveFolderToken()
178  {
179  $ttl = $this->getPathObject()->getTTL();
180  $cookie_lifetime = $ttl !== 0 ? $ttl : self::getCookieMaxLifetimeInSeconds();
181  $id = $this->getTokenInstance()->getHashedId();
182  $expire = time() + $cookie_lifetime + 3600;
183  $secure = true;
184  $domain = null;
185  $http_only = true;
186  $path = '/';
187 
188  $tokenCookie = $this->cookieFactory->create($id, $this->getTokenInstance()->getToken())
189  ->withExpires($expire)
190  ->withPath($path)
191  ->withSecure($secure)
192  ->withDomain($domain)
193  ->withHttpOnly($http_only);
194 
195  $timestampCookie = $this->cookieFactory->create($id . self::TS_SUFFIX, time())
196  ->withExpires($expire)
197  ->withPath($path)
198  ->withDomain($domain)
199  ->withSecure($secure)
200  ->withHttpOnly($http_only);
201 
202  $ttlCookie = $this->cookieFactory->create($id . self::TTL_SUFFIX, $cookie_lifetime)
203  ->withExpires($expire)
204  ->withPath($path)
205  ->withDomain($domain)
206  ->withSecure($secure)
207  ->withHttpOnly($http_only);
208 
209  $jar = $this->httpService->cookieJar()->with($tokenCookie)
210  ->with($timestampCookie)
211  ->with($ttlCookie);
212 
213  // FIX: currently the cookies are never stored, we must use setcookie
214  foreach ($jar->getAll() as $cookie) {
215  setcookie(
216  $cookie->getName(),
217  $cookie->getValue(),
218  $cookie->getExpires(),
219  $cookie->getPath(),
220  $cookie->getDomain(),
221  $cookie->getSecure(),
222  $cookie->getHttpOnly()
223  );
224  }
225  }
226 
227 
231  public function revalidatingFolderToken()
232  {
233  if ($this->getType() !== PathType::FOLDER) {
234  return false;
235  }
236  $this->buildAndSetTokenInstance(time(), $this->getPathObject()->getTTL());
237  $this->getPathObject()->setTTL($this->getTokenInstance()->getTTL());
238  $this->getPathObject()->setTimestamp($this->getTokenInstance()->getTimestamp());
239  $this->getPathObject()->setToken($this->getTokenInstance()->getToken());
240 
241  $this->saveFolderToken();
242 
243  return true;
244  }
245 
246 
250  public function isSignedPath()
251  {
252  return ($this->getPathObject()->hasToken() && $this->getPathObject()->hasTimestamp()
253  && $this->getPathObject()->hasTTL());
254  }
255 
256 
261  public function isSignedPathValid()
262  {
263  $this->buildAndSetTokenInstance($this->getPathObject()->getTimestamp(), $this->getPathObject()->getTTL());
264 
265  return $this->checkToken();
266  }
267 
268 
276  public static function signFile($path_to_file)
277  {
278  if (!$path_to_file) {
279  return '';
280  }
281  $ilWACPath = new ilWACPath($path_to_file, false);
282  if (!$ilWACPath->getClient()) {
283  return $path_to_file;
284  }
285  $obj = new self($ilWACPath, self::http(), new CookieFactoryImpl());
286  $obj->setType(PathType::FILE);
287  $obj->buildAndSetTokenInstance(time(), self::getTokenMaxLifetimeInSeconds());
288 
289  return $obj->getSignedPath();
290  }
291 
292 
297  public static function signFolderOfStartFile($start_file_path)
298  {
299  $obj = new self(new ilWACPath($start_file_path, false), self::http(), new CookieFactoryImpl());
300  $obj->setType(PathType::FOLDER);
301  $obj->buildAndSetTokenInstance(time(), self::getCookieMaxLifetimeInSeconds());
302  $obj->saveFolderToken();
303  }
304 
305 
309  public function getTokenInstance()
310  {
311  return $this->token_instance;
312  }
313 
314 
320  {
321  $this->token_instance = $token_instance;
322  }
323 
324 
328  public function getType()
329  {
330  return (int) $this->type;
331  }
332 
333 
338  public function setType($type)
339  {
340  assert(is_int($type));
341  $this->type = $type;
342  }
343 
344 
348  public function getPathObject()
349  {
350  return $this->path_object;
351  }
352 
353 
359  {
360  $this->path_object = $path_object;
361  }
362 
363 
368  protected function checkToken()
369  {
370  $request_token_string = $this->getPathObject()->getToken();
371  $request_ttl = $this->getPathObject()->getTTL();
372  $request_timestamp = $this->getPathObject()->getTimestamp();
373  $current_timestamp = time();
374 
375  $timestamp_valid = ($current_timestamp < ($request_timestamp + $request_ttl));
376 
377  if (!$timestamp_valid) {
378  $this->setChecked(true);
379 
380  return false;
381  }
382 
383  $simulated_token = $this->buildTokenInstance($request_timestamp, $request_ttl);
384  $simulated_token_string = $simulated_token->getToken();
385  $token_valid = ($simulated_token_string == $request_token_string);
386 
387  if (!$token_valid) {
388  $this->setChecked(true);
389 
390  return false;
391  }
392 
393  return true;
394  }
395 
396 
404  protected function buildTokenInstance($timestamp = 0, $ttl = 0)
405  {
406  assert(is_int($timestamp));
407  assert(is_int($ttl));
408  if (!$this->getType()) {
410  }
411 
412  switch ($this->getType()) {
413  case PathType::FOLDER:
414  $path = $this->getPathObject()->getSecurePath();
415  break;
416  default:
417  $path = $this->getPathObject()->getPathWithoutQuery();
418  break;
419  }
420 
421  $client = $this->getPathObject()->getClient();
422  $timestamp = $timestamp !== 0 ? $timestamp : $this->getPathObject()->getTimestamp();
423  $ttl = $ttl !== 0 ? $ttl : $this->getPathObject()->getTTL();
424 
425  return new ilWACToken($path, $client, $timestamp, $ttl);
426  }
427 
428 
436  public function buildAndSetTokenInstance($timestamp = 0, $ttl = 0)
437  {
438  assert(is_int($timestamp));
439  assert(is_int($ttl));
440 
441  $this->setTokenInstance($this->buildTokenInstance($timestamp, $ttl));
442  }
443 
444 
448  public static function getTokenMaxLifetimeInSeconds()
449  {
450  return self::$token_max_lifetime_in_seconds;
451  }
452 
453 
461  {
462  assert(is_int($token_max_lifetime_in_seconds));
463  if ($token_max_lifetime_in_seconds > self::MAX_LIFETIME) {
465  }
466  self::$token_max_lifetime_in_seconds = $token_max_lifetime_in_seconds;
467  }
468 
469 
473  public static function getCookieMaxLifetimeInSeconds()
474  {
475  return self::$cookie_max_lifetime_in_seconds;
476  }
477 
478 
487  {
488  assert(is_int($cookie_max_lifetime_in_seconds));
489  if ($cookie_max_lifetime_in_seconds > self::MAX_LIFETIME) {
491  }
492  self::$cookie_max_lifetime_in_seconds = $cookie_max_lifetime_in_seconds;
493  }
494 
495 
499  protected function getRelevantLifeTime()
500  {
501  $request_ttl = $this->getPathObject()->getTTL();
502  if ($request_ttl > 0) {
503  return $request_ttl;
504  }
505  switch ($this->getType()) {
506  case PathType::FOLDER:
507  $life_time = self::getCookieMaxLifetimeInSeconds();
508  break;
509  case PathType::FILE:
510  $life_time = self::getTokenMaxLifetimeInSeconds();
511  break;
512  default:
513  $life_time = 0;
514  break;
515  }
516 
517  return $life_time;
518  }
519 
520 
524  public function isChecked()
525  {
526  return (bool) $this->checked;
527  }
528 
529 
534  public function setChecked($checked)
535  {
536  assert(is_bool($checked));
537  $this->checked = $checked;
538  }
539 }
Interface GlobalHttpState.
buildTokenInstance($timestamp=0, $ttl=0)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static getCookieMaxLifetimeInSeconds()
setTokenInstance(ilWACToken $token_instance)
if($_SERVER['argc']< 4) $client
Definition: cron.php:12
__construct(ilWACPath $ilWACPath, GlobalHttpState $httpState, CookieFactory $cookieFactory)
ilWACSignedPath constructor.
Class ilWACPath.
trait HttpServiceAware
Trait HttpServiceAware.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static signFolderOfStartFile($start_file_path)
if($format !==null) $name
Definition: metadata.php:230
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.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
foreach($mandatory_scripts as $file) $timestamp
Definition: buildRTE.php:81
trait HttpServiceAware
Trait HttpServiceAware.
static setTokenMaxLifetimeInSeconds($token_max_lifetime_in_seconds)
static getTokenMaxLifetimeInSeconds()
static $cookie_max_lifetime_in_seconds