Submit
Path:
~
/
/
opt
/
psa
/
phpMyAdmin
/
vendor
/
web-auth
/
metadata-service
/
src
/
File Content:
MetadataService.php
<?php declare(strict_types=1); /* * The MIT License (MIT) * * Copyright (c) 2014-2021 Spomky-Labs * * This software may be modified and distributed under the terms * of the MIT license. See the LICENSE file for details. */ namespace Webauthn\MetadataService; use Assert\Assertion; use Base64Url\Base64Url; use function count; use InvalidArgumentException; use function is_array; use Jose\Component\KeyManagement\JWKFactory; use Jose\Component\Signature\Algorithm\ES256; use Jose\Component\Signature\Serializer\CompactSerializer; use League\Uri\UriString; use LogicException; use Psr\Http\Client\ClientInterface; use Psr\Http\Message\RequestFactoryInterface; use Psr\Log\LoggerInterface; use Psr\Log\NullLogger; use function Safe\json_decode; use function Safe\sprintf; use Throwable; use Webauthn\CertificateToolbox; class MetadataService { /** * @var ClientInterface */ private $httpClient; /** * @var RequestFactoryInterface */ private $requestFactory; /** * @var array */ private $additionalQueryStringValues; /** * @var array */ private $additionalHeaders; /** * @var string */ private $serviceUri; /** * @var LoggerInterface */ private $logger; public function __construct(string $serviceUri, ClientInterface $httpClient, RequestFactoryInterface $requestFactory, array $additionalQueryStringValues = [], array $additionalHeaders = [], ?LoggerInterface $logger = null) { if (0 !== count($additionalQueryStringValues)) { @trigger_error('The argument "additionalQueryStringValues" is deprecated since version 3.3 and will be removed in 4.0. Please set an empty array instead and us the method `addQueryStringValues`.', E_USER_DEPRECATED); } if (0 !== count($additionalQueryStringValues)) { @trigger_error('The argument "additionalHeaders" is deprecated since version 3.3 and will be removed in 4.0. Please set an empty array instead and us the method `addHeaders`.', E_USER_DEPRECATED); } if (null !== $logger) { @trigger_error('The argument "logger" is deprecated since version 3.3 and will be removed in 4.0. Please use the method "setLogger" instead.', E_USER_DEPRECATED); } $this->serviceUri = $serviceUri; $this->httpClient = $httpClient; $this->requestFactory = $requestFactory; $this->additionalQueryStringValues = $additionalQueryStringValues; $this->additionalHeaders = $additionalHeaders; $this->logger = $logger ?? new NullLogger(); } public function addQueryStringValues(array $additionalQueryStringValues): self { $this->additionalQueryStringValues = $additionalQueryStringValues; return $this; } public function addHeaders(array $additionalHeaders): self { $this->additionalHeaders = $additionalHeaders; return $this; } public function setLogger(LoggerInterface $logger): self { $this->logger = $logger; return $this; } public function has(string $aaguid): bool { try { $toc = $this->fetchMetadataTOCPayload(); } catch (Throwable $e) { return false; } foreach ($toc->getEntries() as $entry) { if ($entry->getAaguid() === $aaguid && null !== $entry->getUrl()) { return true; } } return false; } public function get(string $aaguid): MetadataStatement { $toc = $this->fetchMetadataTOCPayload(); foreach ($toc->getEntries() as $entry) { if ($entry->getAaguid() === $aaguid && null !== $entry->getUrl()) { $mds = $this->fetchMetadataStatementFor($entry); $mds ->setStatusReports($entry->getStatusReports()) ->setRootCertificates($toc->getRootCertificates()) ; return $mds; } } throw new InvalidArgumentException(sprintf('The Metadata Statement with AAGUID "%s" is missing', $aaguid)); } /** * @deprecated This method is deprecated since v3.3 and will be removed in v4.0 */ public function getMetadataStatementFor(MetadataTOCPayloadEntry $entry, string $hashingFunction = 'sha256'): MetadataStatement { return $this->fetchMetadataStatementFor($entry, $hashingFunction); } public function fetchMetadataStatementFor(MetadataTOCPayloadEntry $entry, string $hashingFunction = 'sha256'): MetadataStatement { $this->logger->info('Trying to get the metadata statement for a given entry', ['entry' => $entry]); try { $hash = $entry->getHash(); $url = $entry->getUrl(); if (null === $hash || null === $url) { throw new LogicException('The Metadata Statement has not been published'); } $uri = $this->buildUri($url); $result = $this->fetchMetadataStatement($uri, true, $hash, $hashingFunction); $this->logger->info('The metadata statement exists'); $this->logger->debug('Metadata Statement', ['mds' => $result]); return $result; } catch (Throwable $throwable) { $this->logger->error('An error occurred', [ 'exception' => $throwable, ]); throw $throwable; } } /** * @deprecated This method is deprecated since v3.3 and will be removed in v4.0 */ public function getMetadataTOCPayload(): MetadataTOCPayload { return $this->fetchMetadataTOCPayload(); } private function fetchMetadataTOCPayload(): MetadataTOCPayload { $this->logger->info('Trying to get the metadata service TOC payload'); try { $uri = $this->buildUri($this->serviceUri); $toc = $this->fetchTableOfContent($uri); $this->logger->info('The TOC payload has been received'); $this->logger->debug('TOC payload', ['toc' => $toc]); return $toc; } catch (Throwable $throwable) { $this->logger->error('An error occurred', [ 'exception' => $throwable, ]); throw $throwable; } } private function buildUri(string $uri): string { $parsedUri = UriString::parse($uri); $queryString = $parsedUri['query']; $query = []; if (null !== $queryString) { parse_str($queryString, $query); } foreach ($this->additionalQueryStringValues as $k => $v) { if (!isset($query[$k])) { $query[$k] = $v; continue; } if (!is_array($query[$k])) { $query[$k] = [$query[$k], $v]; continue; } $query[$k][] = $v; } $parsedUri['query'] = 0 === count($query) ? null : http_build_query($query, '', '&', PHP_QUERY_RFC3986); return UriString::build($parsedUri); } private function fetchTableOfContent(string $uri): MetadataTOCPayload { $content = $this->fetch($uri); $rootCertificates = []; $payload = $this->getJwsPayload($content, $rootCertificates); $data = json_decode($payload, true); $toc = MetadataTOCPayload::createFromArray($data); $toc->setRootCertificates($rootCertificates); return $toc; } private function fetchMetadataStatement(string $uri, bool $isBase64UrlEncoded, string $hash = '', string $hashingFunction = 'sha256'): MetadataStatement { $payload = $this->fetch($uri); if ('' !== $hash) { Assertion::true(hash_equals($hash, hash($hashingFunction, $payload, true)), 'The hash cannot be verified. The metadata statement shall be rejected'); } $json = $isBase64UrlEncoded ? Base64Url::decode($payload) : $payload; $data = json_decode($json, true); return MetadataStatement::createFromArray($data); } private function fetch(string $uri): string { $request = $this->requestFactory->createRequest('GET', $uri); foreach ($this->additionalHeaders as $k => $v) { $request = $request->withHeader($k, $v); } $response = $this->httpClient->sendRequest($request); Assertion::eq(200, $response->getStatusCode(), sprintf('Unable to contact the server. Response code is %d', $response->getStatusCode())); $content = $response->getBody()->getContents(); Assertion::notEmpty($content, 'Unable to contact the server. The response has no content'); return $content; } private function getJwsPayload(string $token, array &$rootCertificates): string { $jws = (new CompactSerializer())->unserialize($token); Assertion::eq(1, $jws->countSignatures(), 'Invalid response from the metadata service. Only one signature shall be present.'); $signature = $jws->getSignature(0); $payload = $jws->getPayload(); Assertion::notEmpty($payload, 'Invalid response from the metadata service. The token payload is empty.'); $header = $signature->getProtectedHeader(); Assertion::keyExists($header, 'alg', 'The "alg" parameter is missing.'); Assertion::eq($header['alg'], 'ES256', 'The expected "alg" parameter value should be "ES256".'); Assertion::keyExists($header, 'x5c', 'The "x5c" parameter is missing.'); Assertion::isArray($header['x5c'], 'The "x5c" parameter should be an array.'); $key = JWKFactory::createFromX5C($header['x5c']); $rootCertificates = array_map(static function (string $x509): string { return CertificateToolbox::fixPEMStructure($x509); }, $header['x5c']); $algorithm = new ES256(); $isValid = $algorithm->verify($key, $signature->getEncodedProtectedHeader().'.'.$jws->getEncodedPayload(), $signature->getSignature()); Assertion::true($isValid, 'Invalid response from the metadata service. The token signature is invalid.'); return $jws->getPayload(); } }
Edit
Rename
Chmod
Delete
FILE
FOLDER
INFO
Name
Size
Permission
Action
AbstractDescriptor.php
1183 bytes
0644
AuthenticatorStatus.php
2133 bytes
0644
BiometricAccuracyDescriptor.php
2486 bytes
0644
BiometricStatusReport.php
2890 bytes
0644
CodeAccuracyDescriptor.php
1951 bytes
0644
DisplayPNGCharacteristicsDescriptor.php
4178 bytes
0644
DistantSingleMetadata.php
2247 bytes
0644
EcdaaTrustAnchor.php
2473 bytes
0644
ExtensionDescriptor.php
2850 bytes
0644
MetadataService.php
10209 bytes
0644
MetadataStatement.php
17561 bytes
0644
MetadataStatementFetcher.php
3884 bytes
0644
MetadataStatementRepository.php
679 bytes
0644
MetadataTOCPayload.php
3657 bytes
0644
MetadataTOCPayloadEntry.php
5624 bytes
0644
PatternAccuracyDescriptor.php
1928 bytes
0644
RgbPaletteEntry.php
1736 bytes
0644
RogueListEntry.php
1351 bytes
0644
SingleMetadata.php
1147 bytes
0644
StatusReport.php
4676 bytes
0644
Utils.php
810 bytes
0644
VerificationMethodANDCombinations.php
1475 bytes
0644
VerificationMethodDescriptor.php
5021 bytes
0644
Version.php
1847 bytes
0644
N4ST4R_ID | Naxtarrr