/** * Gets the SQL query part to add to a query. * * @param ClassMetaData $targetEntity Metadata object for the target entity to be filtered * @param string $targetTableAlias The target table alias used in the current query * @return string The constraint SQL if there is available, empty string otherwise */ public function addFilterConstraint(ClassMetadata $targetEntity, $targetTableAlias) { $this->initializeDependencies(); /* * TODO: Instead of checking for class account we could introduce some interface for white listing entities from entity security checks * Problem with checking the Account is, that this filter calls getRoles() on the security context while accounts are not * yet fully initialized. By this we get a half built account object that will end up in access denied exception, * as it has no roles (and other properties) set */ if ($this->securityContext->areAuthorizationChecksDisabled() || $targetEntity->getName() === \TYPO3\Flow\Security\Account::class) { return ''; } if (!$this->securityContext->isInitialized()) { if (!$this->securityContext->canBeInitialized()) { return ''; } $this->securityContext->initialize(); } // This is needed to include the current context of roles into query cache identifier $this->setParameter('__contextHash', $this->securityContext->getContextHash(), 'string'); $sqlConstraints = array(); $grantedConstraints = array(); $deniedConstraints = array(); foreach ($this->securityContext->getRoles() as $role) { $entityPrivileges = $role->getPrivilegesByType(\TYPO3\Flow\Security\Authorization\Privilege\Entity\EntityPrivilegeInterface::class); /** @var EntityPrivilegeInterface $privilege */ foreach ($entityPrivileges as $privilege) { if (!$privilege->matchesEntityType($targetEntity->getName())) { continue; } $sqlConstraint = $privilege->getSqlConstraint($targetEntity, $targetTableAlias); if ($sqlConstraint === null) { continue; } $sqlConstraints[] = ' NOT (' . $sqlConstraint . ')'; if ($privilege->isGranted()) { $grantedConstraints[] = ' NOT (' . $sqlConstraint . ')'; } elseif ($privilege->isDenied()) { $deniedConstraints[] = ' NOT (' . $sqlConstraint . ')'; } } } $grantedConstraints = array_diff($grantedConstraints, $deniedConstraints); $effectiveConstraints = array_diff($sqlConstraints, $grantedConstraints); if (count($effectiveConstraints) > 0) { return ' (' . implode(') AND (', $effectiveConstraints) . ') '; } return ''; }
/** * Checks whether the current request has the same security context hash as the one of the token * * @param array $tokenData * @param HttpRequest $httpRequest * @return void * @throws AccessDeniedException */ protected function verifySecurityContextHash(array $tokenData, HttpRequest $httpRequest) { if (!isset($tokenData['securityContextHash'])) { return; } /** @var $actionRequest ActionRequest */ $actionRequest = $this->objectManager->get(ActionRequest::class, $httpRequest); $this->securityContext->setRequest($actionRequest); if ($tokenData['securityContextHash'] !== $this->securityContext->getContextHash()) { throw new AccessDeniedException(sprintf('Invalid security hash!%sThis request is signed for a security context hash of "%s", but the current hash is "%s"', chr(10), $tokenData['securityContextHash'], $this->securityContext->getContextHash()), 1429705633); } }
/** * Returns the web accessible URI pointing to the specified persistent resource * * @param Resource $resource Resource object * @return string The URI * @throws Exception */ public function getPublicPersistentResourceUri(Resource $resource) { $resourceData = array('resourceIdentifier' => $resource->getSha1()); if ($this->shouldIncludeSecurityContext()) { $resourceData['securityContextHash'] = $this->securityContext->getContextHash(); } elseif (!empty($this->options['tokenLifetime'])) { $expirationDateTime = clone $this->now; $expirationDateTime = $expirationDateTime->modify(sprintf('+%d seconds', $this->options['tokenLifetime'])); $resourceData['expirationDateTime'] = $expirationDateTime->format(\DateTime::ISO8601); } $encodedResourceData = base64_encode(json_encode($resourceData)); $signedResourceData = $this->hashService->appendHmac($encodedResourceData); return $this->detectResourcesBaseUri() . '?__protectedResource=' . $signedResourceData; }
/** * Renders an identifier for a content cache entry * * @param string $typoScriptPath * @param array $cacheIdentifierValues * @return string An MD5 hash built from the typoScriptPath and certain elements of the given identifier values * @throws \TYPO3\TypoScript\Exception\CacheException If an invalid entry identifier value is given */ protected function renderContentCacheEntryIdentifier($typoScriptPath, array $cacheIdentifierValues) { ksort($cacheIdentifierValues); $identifierSource = ''; foreach ($cacheIdentifierValues as $key => $value) { if ($value instanceof CacheAwareInterface) { $identifierSource .= $key . '=' . $value->getCacheEntryIdentifier() . '&'; } elseif (is_string($value) || is_bool($value) || is_integer($value)) { $identifierSource .= $key . '=' . $value . '&'; } elseif ($value !== null) { throw new Exception\CacheException(sprintf('Invalid cache entry identifier @cache.entryIdentifier.%s for path "%s". A entry identifier value must be a string or implement CacheAwareInterface.', $key, $typoScriptPath), 1395846615); } } $identifierSource .= 'securityContextHash=' . $this->securityContext->getContextHash(); return md5($typoScriptPath . '@' . $identifierSource); }
/** * Provides a way to identify a context to prevent duplicate context objects. * * @param array $contextProperties * @return string */ protected function getIdentifier(array $contextProperties) { return md5($this->securityContext->getContextHash() . $this->getIdentifierSource($contextProperties)); }
/** * @param string $id * @return string */ protected function convertCacheIdentifier($id) { return md5($id . '|' . $this->securityContext->getContextHash()); }