ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
class.ilWACSignedPath.php
Go to the documentation of this file.
1<?php
2
19// declare(strict_types=1);
24
32{
33 public const WAC_TOKEN_ID = 'il_wac_token';
34 public const WAC_TIMESTAMP_ID = 'il_wac_ts';
35 public const WAC_TTL_ID = 'il_wac_ttl';
36 public const TS_SUFFIX = 'ts';
37 public const TTL_SUFFIX = 'ttl';
38 public const MAX_LIFETIME = 600;
39
40 protected ?ilWACPath $path_object = null;
41 protected ?ilWACToken $token_instance = null;
42 protected int $type = PathType::FILE;
43 protected static int $token_max_lifetime_in_seconds = 5;
44 protected static int $cookie_max_lifetime_in_seconds = 300;
45 protected bool $checked = false;
46
50 public function __construct(ilWACPath $ilWACPath, private GlobalHttpState $httpService, private CookieFactory $cookieFactory)
51 {
52 $this->setPathObject($ilWACPath);
53 }
54
58 public function getSignedPath(): string
59 {
60 if ($this->getType() !== PathType::FILE) {
62 }
63 if ($this->getPathObject()->getOriginalRequest() === '' || $this->getPathObject()->getOriginalRequest() === '0') {
64 return '';
65 }
66 if (!$this->getPathObject()->fileExists()) {
67 // return $this->getPathObject()->getOriginalRequest();
68 }
69
70 if (strpos($this->getPathObject()->getPath(), '?')) {
71 $path = $this->getPathObject()->getPath() . '&' . self::WAC_TOKEN_ID . '='
72 . $this->getTokenInstance()->getToken();
73 } else {
74 $path = $this->getPathObject()->getPath() . '?' . self::WAC_TOKEN_ID . '='
75 . $this->getTokenInstance()->getToken();
76 }
77
78 $path .= '&' . self::WAC_TTL_ID . '=' . $this->getTokenInstance()->getTTL();
79
80 return $path . '&' . self::WAC_TIMESTAMP_ID . '='
81 . $this->getTokenInstance()->getTimestamp();
82 }
83
84 public function isFolderSigned(): bool
85 {
86 $this->httpService->cookieJar();
87
88 $this->setType(PathType::FOLDER);
89 $plain_token = $this->buildTokenInstance();
90 $name = $plain_token->getHashedId();
91
92 // Token
93 $default_token = '';
94 $token_cookie_value = $this->httpService->request()->getCookieParams()[$name] ?? $default_token;
95 // Timestamp
96 $default_timestamp = 0;
97 $timestamp_cookie_value = $this->httpService->request()->getCookieParams()[$name . self::TS_SUFFIX] ?? $default_timestamp;
98 $timestamp_cookie_value = (int) $timestamp_cookie_value;
99 // TTL
100 $default_ttl = 0;
101 $ttl_cookie_value = $this->httpService->request()->getCookieParams()[$name . self::TTL_SUFFIX] ?? $default_ttl;
102 $ttl_cookie_value = (int) $ttl_cookie_value;
103
104 $this->getPathObject()->setToken($token_cookie_value);
105 $this->getPathObject()->setTimestamp($timestamp_cookie_value);
106 $this->getPathObject()->setTTL($ttl_cookie_value);
108
109 return $this->getPathObject()->hasToken();
110 }
111
115 public function isFolderTokenValid(): bool
116 {
117 if (!$this->isFolderSigned()) {
118 return false;
119 }
120
121 return $this->checkToken();
122 }
123
124 protected function saveFolderToken(): void
125 {
126 $ttl = $this->getPathObject()->getTTL();
127 $cookie_lifetime = $ttl !== 0 ? $ttl : self::getCookieMaxLifetimeInSeconds();
128 $id = $this->getTokenInstance()->getHashedId();
129 $expire = time() + $cookie_lifetime + 3600;
130 $secure = true;
131 $domain = null;
132 $http_only = true;
133 $path = '/';
134
135 $tokenCookie = $this->cookieFactory->create($id, $this->getTokenInstance()->getToken())
136 ->withExpires($expire)
137 ->withPath($path)
138 ->withSecure($secure)
139 ->withDomain($domain)
140 ->withHttpOnly($http_only);
141
142 $timestampCookie = $this->cookieFactory->create($id . self::TS_SUFFIX, time())
143 ->withExpires($expire)
144 ->withPath($path)
145 ->withDomain($domain)
146 ->withSecure($secure)
147 ->withHttpOnly($http_only);
148
149 $ttlCookie = $this->cookieFactory->create($id . self::TTL_SUFFIX, $cookie_lifetime)
150 ->withExpires($expire)
151 ->withPath($path)
152 ->withDomain($domain)
153 ->withSecure($secure)
154 ->withHttpOnly($http_only);
155
156 $jar = $this->httpService->cookieJar()->with($tokenCookie)
157 ->with($timestampCookie)
158 ->with($ttlCookie);
159
160 // FIX: currently the cookies are never stored, we must use setcookie
161 foreach ($jar->getAll() as $cookie) {
162 setcookie(
163 $cookie->getName(),
164 (string) $cookie->getValue(),
165 [
166 'expires' => $cookie->getExpires(),
167 'path' => $cookie->getPath() ?? '/',
168 'domain' => $cookie->getDomain() ?? '',
169 'secure' => $cookie->getSecure(),
170 'httponly' => $cookie->getHttpOnly()
171 ]
172 );
173 }
174 }
175
176 public function revalidatingFolderToken(): bool
177 {
178 if ($this->getType() !== PathType::FOLDER) {
179 return false;
180 }
181 $this->buildAndSetTokenInstance(time(), $this->getPathObject()->getTTL());
182 $this->getPathObject()->setTTL($this->getTokenInstance()->getTTL());
183 $this->getPathObject()->setTimestamp($this->getTokenInstance()->getTimestamp());
184 $this->getPathObject()->setToken($this->getTokenInstance()->getToken());
185
186 $this->saveFolderToken();
187
188 return true;
189 }
190
191 public function isSignedPath(): bool
192 {
193 return ($this->getPathObject()->hasToken() && $this->getPathObject()->hasTimestamp()
194 && $this->getPathObject()->hasTTL());
195 }
196
200 public function isSignedPathValid(): bool
201 {
202 $this->buildAndSetTokenInstance($this->getPathObject()->getTimestamp(), $this->getPathObject()->getTTL());
203
204 return $this->checkToken();
205 }
206
212 public static function signFile(string $path_to_file): string
213 {
214 global $DIC;
215 if ($path_to_file === '' || $path_to_file === '0') {
216 return '';
217 }
218 $ilWACPath = new ilWACPath($path_to_file);
219 if ($ilWACPath->getClient() === '' || $ilWACPath->getClient() === '0') {
220 return $path_to_file;
221 }
222 $obj = new self($ilWACPath, $DIC->http(), new CookieFactoryImpl());
223 $obj->setType(PathType::FILE);
224 $obj->buildAndSetTokenInstance(time(), self::getTokenMaxLifetimeInSeconds());
225
226 return $obj->getSignedPath();
227 }
228
229 public static function signFolderOfStartFile(string $start_file_path): void
230 {
231 global $DIC;
232 $obj = new self(new ilWACPath($start_file_path), $DIC->http(), new CookieFactoryImpl());
233 $obj->setType(PathType::FOLDER);
234 $obj->buildAndSetTokenInstance(time(), self::getCookieMaxLifetimeInSeconds());
235 $obj->saveFolderToken();
236 }
237
238 public function getTokenInstance(): ?\ilWACToken
239 {
241 }
242
244 {
245 $this->token_instance = $token_instance;
246 }
247
248 public function getType(): int
249 {
250 return $this->type;
251 }
252
253 public function setType(int $type): void
254 {
255 $this->type = $type;
256 }
257
258 public function getPathObject(): ?\ilWACPath
259 {
260 return $this->path_object;
261 }
262
263 public function setPathObject(ilWACPath $path_object): void
264 {
265 $this->path_object = $path_object;
266 }
267
271 protected function checkToken(): bool
272 {
273 $request_token_string = $this->getPathObject()->getToken();
274 $request_ttl = $this->getPathObject()->getTTL();
275 $request_timestamp = $this->getPathObject()->getTimestamp();
276 $current_timestamp = time();
277
278 $timestamp_valid = ($current_timestamp < ($request_timestamp + $request_ttl));
279
280 if (!$timestamp_valid) {
281 $this->setChecked(true);
282
283 return false;
284 }
285
286 $simulated_token = $this->buildTokenInstance($request_timestamp, $request_ttl);
287 $simulated_token_string = $simulated_token->getToken();
288 $token_valid = ($simulated_token_string === $request_token_string);
289
290 if (!$token_valid) {
291 $this->setChecked(true);
292
293 return false;
294 }
295
296 return true;
297 }
298
303 protected function buildTokenInstance(int $timestamp = 0, int $ttl = 0): \ilWACToken
304 {
305 if ($this->getType() === 0) {
307 }
308
309 $path = match ($this->getType()) {
310 PathType::FOLDER => $this->getPathObject()->getSecurePath(),
311 default => $this->getPathObject()->getPathWithoutQuery(),
312 };
313
314 $client = $this->getPathObject()->getClient();
315 $timestamp = $timestamp !== 0 ? $timestamp : $this->getPathObject()->getTimestamp();
316 $ttl = $ttl !== 0 ? $ttl : $this->getPathObject()->getTTL();
317
318 return new ilWACToken($path, $client, $timestamp, $ttl);
319 }
320
325 public function buildAndSetTokenInstance(int $timestamp = 0, int $ttl = 0): void
326 {
327 $this->setTokenInstance($this->buildTokenInstance($timestamp, $ttl));
328 }
329
330 public static function getTokenMaxLifetimeInSeconds(): int
331 {
333 }
334
340 {
341 if ($token_max_lifetime_in_seconds > self::MAX_LIFETIME) {
343 }
344 self::$token_max_lifetime_in_seconds = $token_max_lifetime_in_seconds;
345 }
346
347 public static function getCookieMaxLifetimeInSeconds(): int
348 {
350 }
351
358 {
359 if ($cookie_max_lifetime_in_seconds > self::MAX_LIFETIME) {
361 }
362 self::$cookie_max_lifetime_in_seconds = $cookie_max_lifetime_in_seconds;
363 }
364
365 protected function getRelevantLifeTime(): int
366 {
367 $request_ttl = $this->getPathObject()->getTTL();
368 if ($request_ttl > 0) {
369 return $request_ttl;
370 }
371
372 return match ($this->getType()) {
373 PathType::FOLDER => self::getCookieMaxLifetimeInSeconds(),
374 PathType::FILE => self::getTokenMaxLifetimeInSeconds(),
375 default => 0,
376 };
377 }
378
379 public function isChecked(): bool
380 {
381 return $this->checked;
382 }
383
384 public function setChecked(bool $checked): void
385 {
386 $this->checked = $checked;
387 }
388}
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
foreach($mandatory_scripts as $file) $timestamp
Definition: buildRTE.php:70
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Class ilWACSignedPath.
static setCookieMaxLifetimeInSeconds(int $cookie_max_lifetime_in_seconds)
static setTokenMaxLifetimeInSeconds(int $token_max_lifetime_in_seconds)
static int $cookie_max_lifetime_in_seconds
__construct(ilWACPath $ilWACPath, private GlobalHttpState $httpService, private CookieFactory $cookieFactory)
ilWACSignedPath constructor.
setChecked(bool $checked)
setTokenInstance(ilWACToken $token_instance)
static signFolderOfStartFile(string $start_file_path)
static signFile(string $path_to_file)
static getCookieMaxLifetimeInSeconds()
setPathObject(ilWACPath $path_object)
buildTokenInstance(int $timestamp=0, int $ttl=0)
static int $token_max_lifetime_in_seconds
static getTokenMaxLifetimeInSeconds()
buildAndSetTokenInstance(int $timestamp=0, int $ttl=0)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
$client
Interface GlobalHttpState.
Interface PathType.
Definition: PathType.php:31
$path
Definition: ltiservices.php:30
global $DIC
Definition: shib_login.php:26