ILIAS  release_9 Revision v9.13-25-g2c18ec4c24f
class.ilWebAccessChecker.php
Go to the documentation of this file.
1 <?php
2 
23 
31 {
32  public const DISPOSITION = 'disposition';
33  public const STATUS_CODE = 'status_code';
34  public const REVALIDATE = 'revalidate';
35  public const CM_FILE_TOKEN = 1;
36  public const CM_FOLDER_TOKEN = 2;
37  public const CM_CHECKINGINSTANCE = 3;
38  public const CM_SECFOLDER = 4;
39 
40  protected ?ilWACPath $path_object = null;
41  protected bool $checked = false;
43  protected string $override_mimetype = '';
44  protected bool $send_status_code = false;
45  protected bool $initialized = false;
46  protected bool $revalidate_folder_tokens = true;
47  protected static bool $use_seperate_logfile = false;
51  protected array $applied_checking_methods = [];
52  private Services $http;
54 
58  public function __construct(Services $httpState, private CookieFactory $cookieFactory)
59  {
60  try {
61  $this->setPathObject(new ilWACPath($httpState->request()->getRequestTarget()));
62  } catch (ilWACException $e) {
63  if ($e->getCode() !== ilWACException::NOT_FOUND) {
64  throw $e;
65  }
66  $this->ressource_not_found = $e;
67  }
68 
69  $this->http = $httpState;
70  }
71 
75  public function check(): bool
76  {
77  if (!$this->getPathObject() instanceof \ilWACPath) {
78  if ($this->ressource_not_found instanceof \ilWACException) {
79  throw new ilWACException(ilWACException::NOT_FOUND, '', $this->ressource_not_found);
80  }
81 
82  throw new ilWACException(ilWACException::CODE_NO_PATH);
83  }
84 
85  // Check if Path has been signed with a token
86  $ilWACSignedPath = new ilWACSignedPath($this->getPathObject(), $this->http, $this->cookieFactory);
87  if ($ilWACSignedPath->isSignedPath()) {
88  $this->addAppliedCheckingMethod(self::CM_FILE_TOKEN);
89  if ($ilWACSignedPath->isSignedPathValid()) {
90  $this->setChecked(true);
91  $this->sendHeader('checked using token');
92 
93  return true;
94  }
95  }
96 
97  // Check if the whole secured folder has been signed
98  if ($ilWACSignedPath->isFolderSigned()) {
99  $this->addAppliedCheckingMethod(self::CM_FOLDER_TOKEN);
100  if ($ilWACSignedPath->isFolderTokenValid()) {
101  if ($this->isRevalidateFolderTokens()) {
102  $ilWACSignedPath->revalidatingFolderToken();
103  }
104  $this->setChecked(true);
105  $this->sendHeader('checked using secure folder');
106 
107  return true;
108  }
109  }
110 
111  // Fallback, have to initiate ILIAS
112  $this->initILIAS();
113 
114  // Check if Path is within accepted paths
115  if ($this->getPathObject()->getModuleType() !== 'rs') {
116  $clean_path = $this->getPathObject()->getCleanURLdecodedPath();
117  $path = realpath($clean_path);
118  $data_dir = realpath(CLIENT_WEB_DIR);
119  if (!str_starts_with($path, $data_dir)) {
120  return false;
121  }
122  if (dirname($path) === $data_dir && is_file($path)) {
123  return false;
124  }
125  }
126 
128  // Maybe the path has been registered, lets check
129  $checkingInstance = ilWACSecurePath::getCheckingInstance($this->getPathObject());
130  $this->addAppliedCheckingMethod(self::CM_CHECKINGINSTANCE);
131  $canBeDelivered = $checkingInstance->canBeDelivered($this->getPathObject());
132  if ($canBeDelivered) {
133  $this->sendHeader('checked using fallback');
134  if ($ilWACSignedPath->isFolderSigned() && $this->isRevalidateFolderTokens()) {
135  $ilWACSignedPath->revalidatingFolderToken();
136  }
137  }
138  $this->setChecked(true);
139  return $canBeDelivered;
140  }
141 
142  // none of the checking mechanisms could have been applied. no access
143  $this->setChecked(true);
144  $this->addAppliedCheckingMethod(self::CM_SECFOLDER);
145  return !$this->getPathObject()->isInSecFolder();
146  }
147 
148  protected function sendHeader(string $message): void
149  {
150  $response = $this->http->response()->withHeader('X-ILIAS-WebAccessChecker', $message);
151  $this->http->saveResponse($response);
152  }
153 
154  public function initILIAS(): void
155  {
156  global $DIC;
157 
158  if ($this->isInitialized()) {
159  return;
160  }
161 
162  $GLOBALS['COOKIE_PATH'] = '/';
163 
164  $cookie = $this->cookieFactory->create('ilClientId', $this->getPathObject()->getClient())
165  ->withPath('/')
166  ->withExpires(0);
167 
168  $response = $this->http->cookieJar()
169  ->with($cookie)
170  ->renderIntoResponseHeader($this->http->response());
171 
172  $this->http->saveResponse($response);
173 
175  try {
177  $this->checkUser();
178  $this->checkPublicSection();
179  } catch (Exception $e) {
180  if ($e instanceof ilWACException
181  && $e->getCode() !== ilWACException::ACCESS_DENIED_NO_LOGIN) {
182  throw $e;
183  }
184  if (($e instanceof Exception && $e->getMessage() === 'Authentication failed.')
185  || $e->getCode() === ilWACException::ACCESS_DENIED_NO_LOGIN) {
186  $this->initAnonymousSession();
187  $this->checkUser();
188  $this->checkPublicSection();
189  }
190  }
191  $this->setInitialized(true);
192 
193  // This workaround is needed because these issues:
194  // https://mantis.ilias.de/view.php?id=32284 and
195  // https://mantis.ilias.de/view.php?id=32063
196  if ($DIC->user()->getId() === 0) {
197  $DIC->user()->setId(ANONYMOUS_USER_ID);
198  }
199  }
200 
204  protected function checkPublicSection(): void
205  {
206  global $DIC;
207  $is_anonymous = ((int) $DIC->user()->getId() === (int) ANONYMOUS_USER_ID);
208  $is_null_user = ($DIC->user()->getId() === 0);
209  $pub_section_activated = (bool) $DIC['ilSetting']->get('pub_section');
210  $isset = isset($DIC['ilSetting']);
211  $instanceof = $DIC['ilSetting'] instanceof ilSetting;
212 
213  if (!$isset || !$instanceof) {
215  }
216 
217  if ($pub_section_activated && ($is_null_user || $is_anonymous)) {
218  // Request is initiated from an enabled public area
219  return;
220  }
221 
222  if ($is_anonymous || $is_null_user) {
224  }
225  }
226 
227  protected function checkUser(): void
228  {
229  global $DIC;
230 
231  $is_user = $DIC->user() instanceof ilObjUser;
232  $user_id_is_zero = ((int) $DIC->user()->getId() === 0);
233  if (!$is_user || $user_id_is_zero) {
235  }
236  }
237 
238  public function isChecked(): bool
239  {
240  return $this->checked;
241  }
242 
243  public function setChecked(bool $checked): void
244  {
245  $this->checked = $checked;
246  }
247 
248  public function getPathObject(): ?\ilWACPath
249  {
250  return $this->path_object;
251  }
252 
253  public function setPathObject(ilWACPath $path_object): void
254  {
255  $this->path_object = $path_object;
256  }
257 
258  public function getDisposition(): string
259  {
260  return $this->disposition;
261  }
262 
263  public function setDisposition(string $disposition): void
264  {
265  $this->disposition = $disposition;
266  }
267 
268  public function getOverrideMimetype(): string
269  {
271  }
272 
273  public function setOverrideMimetype(string $override_mimetype): void
274  {
275  $this->override_mimetype = $override_mimetype;
276  }
277 
278  public function isInitialized(): bool
279  {
280  return $this->initialized;
281  }
282 
283  public function setInitialized(bool $initialized): void
284  {
285  $this->initialized = $initialized;
286  }
287 
288  public function isSendStatusCode(): bool
289  {
291  }
292 
293  public function setSendStatusCode(bool $send_status_code): void
294  {
295  $this->send_status_code = $send_status_code;
296  }
297 
298  public function isRevalidateFolderTokens(): bool
299  {
301  }
302 
303  public function setRevalidateFolderTokens(bool $revalidate_folder_tokens): void
304  {
305  $this->revalidate_folder_tokens = $revalidate_folder_tokens;
306  }
307 
308  public static function isUseSeperateLogfile(): bool
309  {
310  return self::$use_seperate_logfile;
311  }
312 
313  public static function setUseSeperateLogfile(bool $use_seperate_logfile): void
314  {
315  self::$use_seperate_logfile = $use_seperate_logfile;
316  }
317 
321  public function getAppliedCheckingMethods(): array
322  {
324  }
325 
329  public function setAppliedCheckingMethods(array $applied_checking_methods): void
330  {
331  $this->applied_checking_methods = $applied_checking_methods;
332  }
333 
334  protected function addAppliedCheckingMethod(int $method): void
335  {
336  $this->applied_checking_methods[] = $method;
337  }
338 
339  protected function initAnonymousSession(): void
340  {
341  global $DIC;
342  session_destroy();
348  $ilAuthSession = $DIC['ilAuthSession'];
349  $ilAuthSession->regenerateId();
350  $ilAuthSession->setUserId(ANONYMOUS_USER_ID);
351  $ilAuthSession->setAuthenticated(false, ANONYMOUS_USER_ID);
352  $DIC->user()->setId(ANONYMOUS_USER_ID);
353  }
354 }
setPathObject(ilWACPath $path_object)
__construct(Services $httpState, private CookieFactory $cookieFactory)
ilWebAccessChecker constructor.
const CONTEXT_WAC
const ANONYMOUS_USER_ID
Definition: constants.php:27
$response
Definition: xapitoken.php:93
setAppliedCheckingMethods(array $applied_checking_methods)
setInitialized(bool $initialized)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
setOverrideMimetype(string $override_mimetype)
$path
Definition: ltiservices.php:32
global $DIC
Definition: feed.php:28
static initILIAS()
ilias initialisation
setSendStatusCode(bool $send_status_code)
static http()
Fetches the global http state from ILIAS.
$GLOBALS["DIC"]
Definition: wac.php:31
Class ilWebAccessChecker.
const CLIENT_WEB_DIR
Definition: constants.php:47
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
setRevalidateFolderTokens(bool $revalidate_folder_tokens)
static hasCheckingInstanceRegistered(ilWACPath $ilWACPath)
Searches a checking instance for the given wac path.
static init(string $a_type)
Init context by type.
static setUseSeperateLogfile(bool $use_seperate_logfile)
setDisposition(string $disposition)
$message
Definition: xapiexit.php:32
ilWACException $ressource_not_found