2018-04-30 10:29:56 -04:00
< ? php
/**
2024-05-27 11:39:07 -04:00
* SPDX - FileCopyrightText : 2018 Nextcloud GmbH and Nextcloud contributors
* SPDX - License - Identifier : AGPL - 3.0 - or - later
2018-04-30 10:29:56 -04:00
*/
namespace OCA\CloudFederationAPI\Controller ;
2024-11-17 19:43:47 -05:00
use NCU\Security\Signature\Exceptions\IdentityNotFoundException ;
2024-11-12 17:07:16 -05:00
use NCU\Security\Signature\Exceptions\IncomingRequestException ;
use NCU\Security\Signature\Exceptions\SignatoryNotFoundException ;
use NCU\Security\Signature\Exceptions\SignatureException ;
use NCU\Security\Signature\Exceptions\SignatureNotFoundException ;
use NCU\Security\Signature\ISignatureManager ;
use NCU\Security\Signature\Model\IIncomingSignedRequest ;
use OC\OCM\OCMSignatoryManager ;
2018-04-30 10:29:56 -04:00
use OCA\CloudFederationAPI\Config ;
2023-07-13 01:20:55 -04:00
use OCA\CloudFederationAPI\ResponseDefinitions ;
2024-11-17 19:43:47 -05:00
use OCA\FederatedFileSharing\AddressHandler ;
2018-04-30 10:29:56 -04:00
use OCP\AppFramework\Controller ;
use OCP\AppFramework\Http ;
2024-07-25 07:14:44 -04:00
use OCP\AppFramework\Http\Attribute\BruteForceProtection ;
use OCP\AppFramework\Http\Attribute\NoCSRFRequired ;
2024-01-18 10:23:36 -05:00
use OCP\AppFramework\Http\Attribute\OpenAPI ;
2024-07-25 07:14:44 -04:00
use OCP\AppFramework\Http\Attribute\PublicPage ;
2018-04-30 10:29:56 -04:00
use OCP\AppFramework\Http\JSONResponse ;
2018-05-09 11:06:35 -04:00
use OCP\Federation\Exceptions\ActionNotSupportedException ;
2018-05-29 10:21:13 -04:00
use OCP\Federation\Exceptions\AuthenticationFailedException ;
use OCP\Federation\Exceptions\BadRequestException ;
2018-04-30 10:29:56 -04:00
use OCP\Federation\Exceptions\ProviderCouldNotAddShareException ;
2019-11-22 14:52:10 -05:00
use OCP\Federation\Exceptions\ProviderDoesNotExistsException ;
2018-04-30 10:29:56 -04:00
use OCP\Federation\ICloudFederationFactory ;
use OCP\Federation\ICloudFederationProviderManager ;
2018-05-04 09:25:02 -04:00
use OCP\Federation\ICloudIdManager ;
2024-11-12 17:07:16 -05:00
use OCP\IAppConfig ;
2018-06-13 08:19:59 -04:00
use OCP\IGroupManager ;
2018-04-30 10:29:56 -04:00
use OCP\IRequest ;
use OCP\IURLGenerator ;
use OCP\IUserManager ;
2018-06-07 08:40:12 -04:00
use OCP\Share\Exceptions\ShareNotFound ;
2024-11-12 17:07:16 -05:00
use OCP\Share\IProviderFactory ;
use OCP\Share\IShare ;
2024-10-10 06:40:31 -04:00
use OCP\Util ;
2021-03-09 14:42:47 -05:00
use Psr\Log\LoggerInterface ;
2018-04-30 10:29:56 -04:00
/**
2023-07-13 01:20:55 -04:00
* Open - Cloud - Mesh - API
2018-04-30 10:29:56 -04:00
*
* @ package OCA\CloudFederationAPI\Controller
2023-07-13 01:20:55 -04:00
*
2023-10-23 10:47:38 -04:00
* @ psalm - import - type CloudFederationAPIAddShare from ResponseDefinitions
* @ psalm - import - type CloudFederationAPIValidationError from ResponseDefinitions
* @ psalm - import - type CloudFederationAPIError from ResponseDefinitions
2018-04-30 10:29:56 -04:00
*/
2024-01-18 10:23:36 -05:00
#[OpenAPI(scope: OpenAPI::SCOPE_FEDERATION)]
2018-04-30 10:29:56 -04:00
class RequestHandlerController extends Controller {
2023-09-05 08:42:48 -04:00
public function __construct (
string $appName ,
IRequest $request ,
private LoggerInterface $logger ,
private IUserManager $userManager ,
private IGroupManager $groupManager ,
private IURLGenerator $urlGenerator ,
private ICloudFederationProviderManager $cloudFederationProviderManager ,
private Config $config ,
2024-11-17 19:43:47 -05:00
private readonly AddressHandler $addressHandler ,
2024-11-12 17:07:16 -05:00
private readonly IAppConfig $appConfig ,
2023-09-05 08:42:48 -04:00
private ICloudFederationFactory $factory ,
2024-09-19 05:10:31 -04:00
private ICloudIdManager $cloudIdManager ,
2024-11-12 17:07:16 -05:00
private readonly ISignatureManager $signatureManager ,
private readonly OCMSignatoryManager $signatoryManager ,
private readonly IProviderFactory $shareProviderFactory ,
2018-04-30 10:29:56 -04:00
) {
parent :: __construct ( $appName , $request );
}
/**
2023-07-13 01:20:55 -04:00
* Add share
2018-04-30 10:29:56 -04:00
*
2023-07-13 01:20:55 -04:00
* @ param string $shareWith The user who the share will be shared with
* @ param string $name The resource name ( e . g . document . odt )
* @ param string | null $description Share description
* @ param string $providerId Resource UID on the provider side
* @ param string $owner Provider specific UID of the user who owns the resource
* @ param string | null $ownerDisplayName Display name of the user who shared the item
* @ param string | null $sharedBy Provider specific UID of the user who shared the resource
* @ param string | null $sharedByDisplayName Display name of the user who shared the resource
2024-09-24 09:53:13 -04:00
* @ param array { name : list < string > , options : array < string , mixed > } $protocol e , . g . [ 'name' => 'webdav' , 'options' => [ 'username' => 'john' , 'permissions' => 31 ]]
2023-07-13 01:20:55 -04:00
* @ param string $shareType 'group' or 'user' share
* @ param string $resourceType 'file' , 'calendar' , ...
2018-04-30 10:29:56 -04:00
*
2023-10-23 10:47:38 -04:00
* @ return JSONResponse < Http :: STATUS_CREATED , CloudFederationAPIAddShare , array {} >| JSONResponse < Http :: STATUS_BAD_REQUEST , CloudFederationAPIValidationError , array {} >| JSONResponse < Http :: STATUS_NOT_IMPLEMENTED , CloudFederationAPIError , array {} >
2024-08-23 09:10:27 -04:00
*
2023-07-13 01:20:55 -04:00
* 201 : The notification was successfully received . The display name of the recipient might be returned in the body
* 400 : Bad request due to invalid parameters , e . g . when `shareWith` is not found or required properties are missing
* 501 : Share type or the resource type is not supported
2018-04-30 10:29:56 -04:00
*/
2024-07-25 07:14:44 -04:00
#[PublicPage]
#[NoCSRFRequired]
#[BruteForceProtection(action: 'receiveFederatedShare')]
2018-04-30 10:29:56 -04:00
public function addShare ( $shareWith , $name , $description , $providerId , $owner , $ownerDisplayName , $sharedBy , $sharedByDisplayName , $protocol , $shareType , $resourceType ) {
2024-11-12 17:07:16 -05:00
try {
// if request is signed and well signed, no exception are thrown
// if request is not signed and host is known for not supporting signed request, no exception are thrown
$signedRequest = $this -> getSignedRequest ();
$this -> confirmSignedOrigin ( $signedRequest , 'owner' , $owner );
} catch ( IncomingRequestException $e ) {
$this -> logger -> warning ( 'incoming request exception' , [ 'exception' => $e ]);
return new JSONResponse ([ 'message' => $e -> getMessage (), 'validationErrors' => []], Http :: STATUS_BAD_REQUEST );
}
2018-04-30 10:29:56 -04:00
// check if all required parameters are set
if ( $shareWith === null ||
$name === null ||
$providerId === null ||
$resourceType === null ||
$shareType === null ||
! is_array ( $protocol ) ||
! isset ( $protocol [ 'name' ]) ||
2020-04-09 10:05:56 -04:00
! isset ( $protocol [ 'options' ]) ||
2018-05-28 11:13:19 -04:00
! is_array ( $protocol [ 'options' ]) ||
! isset ( $protocol [ 'options' ][ 'sharedSecret' ])
2018-04-30 10:29:56 -04:00
) {
return new JSONResponse (
2023-07-13 01:20:40 -04:00
[
'message' => 'Missing arguments' ,
'validationErrors' => [],
],
2018-04-30 10:29:56 -04:00
Http :: STATUS_BAD_REQUEST
);
}
2018-06-13 08:19:59 -04:00
$supportedShareTypes = $this -> config -> getSupportedShareTypes ( $resourceType );
if ( ! in_array ( $shareType , $supportedShareTypes )) {
2018-04-30 10:29:56 -04:00
return new JSONResponse (
2018-06-13 08:19:59 -04:00
[ 'message' => 'Share type "' . $shareType . '" not implemented' ],
Http :: STATUS_NOT_IMPLEMENTED
2018-04-30 10:29:56 -04:00
);
}
2018-06-13 08:19:59 -04:00
$cloudId = $this -> cloudIdManager -> resolveCloudId ( $shareWith );
$shareWith = $cloudId -> getUser ();
if ( $shareType === 'user' ) {
$shareWith = $this -> mapUid ( $shareWith );
if ( ! $this -> userManager -> userExists ( $shareWith )) {
2022-06-13 03:30:51 -04:00
$response = new JSONResponse (
2023-07-13 01:20:40 -04:00
[
'message' => 'User "' . $shareWith . '" does not exists at ' . $this -> urlGenerator -> getBaseUrl (),
'validationErrors' => [],
],
2018-06-13 08:19:59 -04:00
Http :: STATUS_BAD_REQUEST
);
2022-06-13 03:30:51 -04:00
$response -> throttle ();
return $response ;
2018-06-13 08:19:59 -04:00
}
}
if ( $shareType === 'group' ) {
2020-04-10 08:19:56 -04:00
if ( ! $this -> groupManager -> groupExists ( $shareWith )) {
2022-06-13 03:30:51 -04:00
$response = new JSONResponse (
2023-07-13 01:20:40 -04:00
[
'message' => 'Group "' . $shareWith . '" does not exists at ' . $this -> urlGenerator -> getBaseUrl (),
'validationErrors' => [],
],
2018-06-13 08:19:59 -04:00
Http :: STATUS_BAD_REQUEST
);
2022-06-13 03:30:51 -04:00
$response -> throttle ();
return $response ;
2018-06-13 08:19:59 -04:00
}
}
2018-04-30 10:29:56 -04:00
// if no explicit display name is given, we use the uid as display name
$ownerDisplayName = $ownerDisplayName === null ? $owner : $ownerDisplayName ;
$sharedByDisplayName = $sharedByDisplayName === null ? $sharedBy : $sharedByDisplayName ;
// sharedBy* parameter is optional, if nothing is set we assume that it is the same user as the owner
if ( $sharedBy === null ) {
$sharedBy = $owner ;
$sharedByDisplayName = $ownerDisplayName ;
}
try {
$provider = $this -> cloudFederationProviderManager -> getCloudFederationProvider ( $resourceType );
2018-05-28 11:13:19 -04:00
$share = $this -> factory -> getCloudFederationShare ( $shareWith , $name , $description , $providerId , $owner , $ownerDisplayName , $sharedBy , $sharedByDisplayName , '' , $shareType , $resourceType );
$share -> setProtocol ( $protocol );
2018-06-13 08:19:59 -04:00
$provider -> shareReceived ( $share );
2023-07-13 01:20:40 -04:00
} catch ( ProviderDoesNotExistsException | ProviderCouldNotAddShareException $e ) {
2018-04-30 10:29:56 -04:00
return new JSONResponse (
[ 'message' => $e -> getMessage ()],
Http :: STATUS_NOT_IMPLEMENTED
);
} catch ( \Exception $e ) {
2022-06-07 16:00:26 -04:00
$this -> logger -> error ( $e -> getMessage (), [ 'exception' => $e ]);
2018-04-30 10:29:56 -04:00
return new JSONResponse (
2023-07-13 01:20:40 -04:00
[
'message' => 'Internal error at ' . $this -> urlGenerator -> getBaseUrl (),
'validationErrors' => [],
],
2018-04-30 10:29:56 -04:00
Http :: STATUS_BAD_REQUEST
);
}
2024-08-13 07:19:52 -04:00
$responseData = [ 'recipientDisplayName' => '' ];
if ( $shareType === 'user' ) {
$user = $this -> userManager -> get ( $shareWith );
if ( $user ) {
$responseData = [
'recipientDisplayName' => $user -> getDisplayName (),
'recipientUserId' => $user -> getUID (),
];
}
2018-06-13 05:57:00 -04:00
}
2024-08-13 07:19:52 -04:00
return new JSONResponse ( $responseData , Http :: STATUS_CREATED );
2018-04-30 10:29:56 -04:00
}
/**
2023-07-13 01:20:55 -04:00
* Send a notification about an existing share
2018-04-30 10:29:56 -04:00
*
2023-07-13 01:20:55 -04:00
* @ param string $notificationType Notification type , e . g . SHARE_ACCEPTED
* @ param string $resourceType calendar , file , contact , ...
* @ param string | null $providerId ID of the share
* @ param array < string , mixed >| null $notification The actual payload of the notification
*
2023-10-23 10:47:38 -04:00
* @ return JSONResponse < Http :: STATUS_CREATED , array < string , mixed > , array {} >| JSONResponse < Http :: STATUS_BAD_REQUEST , CloudFederationAPIValidationError , array {} >| JSONResponse < Http :: STATUS_FORBIDDEN | Http :: STATUS_NOT_IMPLEMENTED , CloudFederationAPIError , array {} >
2024-08-23 09:10:27 -04:00
*
2023-07-13 01:20:55 -04:00
* 201 : The notification was successfully received
* 400 : Bad request due to invalid parameters , e . g . when `type` is invalid or missing
* 403 : Getting resource is not allowed
* 501 : The resource type is not supported
2018-04-30 10:29:56 -04:00
*/
2024-07-25 07:14:44 -04:00
#[NoCSRFRequired]
#[PublicPage]
#[BruteForceProtection(action: 'receiveFederatedShareNotification')]
2023-07-13 01:20:55 -04:00
public function receiveNotification ( $notificationType , $resourceType , $providerId , ? array $notification ) {
2024-11-12 17:07:16 -05:00
try {
// if request is signed and well signed, no exception are thrown
// if request is not signed and host is known for not supporting signed request, no exception are thrown
$signedRequest = $this -> getSignedRequest ();
$this -> confirmShareOrigin ( $signedRequest , $notification [ 'sharedSecret' ] ? ? '' );
} catch ( IncomingRequestException $e ) {
$this -> logger -> warning ( 'incoming request exception' , [ 'exception' => $e ]);
return new JSONResponse ([ 'message' => $e -> getMessage (), 'validationErrors' => []], Http :: STATUS_BAD_REQUEST );
}
2018-04-30 10:29:56 -04:00
// check if all required parameters are set
2018-05-09 11:06:35 -04:00
if ( $notificationType === null ||
$resourceType === null ||
2018-05-28 11:13:19 -04:00
$providerId === null ||
! is_array ( $notification )
2018-04-30 10:29:56 -04:00
) {
return new JSONResponse (
2023-07-13 01:20:40 -04:00
[
'message' => 'Missing arguments' ,
'validationErrors' => [],
],
2018-04-30 10:29:56 -04:00
Http :: STATUS_BAD_REQUEST
);
}
try {
$provider = $this -> cloudFederationProviderManager -> getCloudFederationProvider ( $resourceType );
2018-06-04 06:16:03 -04:00
$result = $provider -> notificationReceived ( $notificationType , $providerId , $notification );
2018-04-30 10:29:56 -04:00
} catch ( ProviderDoesNotExistsException $e ) {
return new JSONResponse (
2023-07-13 01:20:40 -04:00
[
'message' => $e -> getMessage (),
'validationErrors' => [],
],
2018-04-30 10:29:56 -04:00
Http :: STATUS_BAD_REQUEST
);
2018-06-07 08:40:12 -04:00
} catch ( ShareNotFound $e ) {
2022-06-13 03:30:51 -04:00
$response = new JSONResponse (
2023-07-13 01:20:40 -04:00
[
'message' => $e -> getMessage (),
'validationErrors' => [],
],
2018-04-30 10:29:56 -04:00
Http :: STATUS_BAD_REQUEST
);
2022-06-13 03:30:51 -04:00
$response -> throttle ();
return $response ;
2018-05-09 11:06:35 -04:00
} catch ( ActionNotSupportedException $e ) {
return new JSONResponse (
[ 'message' => $e -> getMessage ()],
Http :: STATUS_NOT_IMPLEMENTED
);
2018-05-29 10:21:13 -04:00
} catch ( BadRequestException $e ) {
return new JSONResponse ( $e -> getReturnMessage (), Http :: STATUS_BAD_REQUEST );
} catch ( AuthenticationFailedException $e ) {
2022-06-13 03:30:51 -04:00
$response = new JSONResponse ([ 'message' => 'RESOURCE_NOT_FOUND' ], Http :: STATUS_FORBIDDEN );
$response -> throttle ();
return $response ;
2020-04-10 08:19:56 -04:00
} catch ( \Exception $e ) {
2024-11-17 19:43:47 -05:00
$this -> logger -> warning ( 'incoming notification exception' , [ 'exception' => $e ]);
2018-04-30 10:29:56 -04:00
return new JSONResponse (
2023-07-13 01:20:40 -04:00
[
'message' => 'Internal error at ' . $this -> urlGenerator -> getBaseUrl (),
'validationErrors' => [],
],
2018-04-30 10:29:56 -04:00
Http :: STATUS_BAD_REQUEST
);
}
2023-09-05 08:42:48 -04:00
return new JSONResponse ( $result , Http :: STATUS_CREATED );
2018-04-30 10:29:56 -04:00
}
/**
* map login name to internal LDAP UID if a LDAP backend is in use
*
* @ param string $uid
* @ return string mixed
*/
private function mapUid ( $uid ) {
// FIXME this should be a method in the user management instead
$this -> logger -> debug ( 'shareWith before, ' . $uid , [ 'app' => $this -> appName ]);
2024-10-10 06:40:31 -04:00
Util :: emitHook (
2018-04-30 10:29:56 -04:00
'\OCA\Files_Sharing\API\Server2Server' ,
'preLoginNameUsedAsUserName' ,
2020-03-26 04:30:18 -04:00
[ 'uid' => & $uid ]
2018-04-30 10:29:56 -04:00
);
$this -> logger -> debug ( 'shareWith after, ' . $uid , [ 'app' => $this -> appName ]);
return $uid ;
}
2024-11-12 17:07:16 -05:00
/**
* returns signed request if available .
* throw an exception :
* - if request is signed , but wrongly signed
* - if request is not signed but instance is configured to only accept signed ocm request
*
* @ return IIncomingSignedRequest | null null if remote does not ( and never did ) support signed request
* @ throws IncomingRequestException
*/
private function getSignedRequest () : ? IIncomingSignedRequest {
try {
2024-11-21 05:25:00 -05:00
$signedRequest = $this -> signatureManager -> getIncomingSignedRequest ( $this -> signatoryManager );
$this -> logger -> debug ( 'signed request available' , [ 'signedRequest' => $signedRequest ]);
return $signedRequest ;
2024-11-12 17:07:16 -05:00
} catch ( SignatureNotFoundException | SignatoryNotFoundException $e ) {
2024-11-21 05:25:00 -05:00
$this -> logger -> debug ( 'remote does not support signed request' , [ 'exception' => $e ]);
2024-11-12 17:07:16 -05:00
// remote does not support signed request.
// currently we still accept unsigned request until lazy appconfig
// core.enforce_signed_ocm_request is set to true (default: false)
if ( $this -> appConfig -> getValueBool ( 'core' , OCMSignatoryManager :: APPCONFIG_SIGN_ENFORCED , lazy : true )) {
$this -> logger -> notice ( 'ignored unsigned request' , [ 'exception' => $e ]);
throw new IncomingRequestException ( 'Unsigned request' );
}
} catch ( SignatureException $e ) {
2024-11-21 05:25:00 -05:00
$this -> logger -> warning ( 'wrongly signed request' , [ 'exception' => $e ]);
2024-11-12 17:07:16 -05:00
throw new IncomingRequestException ( 'Invalid signature' );
}
return null ;
}
/**
* confirm that the value related to $key entry from the payload is in format userid @ hostname
* and compare hostname with the origin of the signed request .
*
* If request is not signed , we still verify that the hostname from the extracted value does ,
* actually , not support signed request
*
* @ param IIncomingSignedRequest | null $signedRequest
* @ param string $key entry from data available in data
* @ param string $value value itself used in case request is not signed
*
* @ throws IncomingRequestException
*/
private function confirmSignedOrigin ( ? IIncomingSignedRequest $signedRequest , string $key , string $value ) : void {
if ( $signedRequest === null ) {
$instance = $this -> getHostFromFederationId ( $value );
try {
$this -> signatureManager -> searchSignatory ( $instance );
throw new IncomingRequestException ( 'instance is supposed to sign its request' );
} catch ( SignatoryNotFoundException ) {
return ;
}
}
$body = json_decode ( $signedRequest -> getBody (), true ) ? ? [];
$entry = trim ( $body [ $key ] ? ? '' , '@' );
if ( $this -> getHostFromFederationId ( $entry ) !== $signedRequest -> getOrigin ()) {
2024-11-17 19:43:47 -05:00
throw new IncomingRequestException ( 'share initiation (' . $signedRequest -> getOrigin () . ') from different instance (' . $entry . ') [key=' . $key . ']' );
2024-11-12 17:07:16 -05:00
}
}
/**
* confirm that the value related to share token is in format userid @ hostname
* and compare hostname with the origin of the signed request .
*
* If request is not signed , we still verify that the hostname from the extracted value does ,
* actually , not support signed request
*
* @ param IIncomingSignedRequest | null $signedRequest
* @ param string $token
*
* @ throws IncomingRequestException
*/
private function confirmShareOrigin ( ? IIncomingSignedRequest $signedRequest , string $token ) : void {
if ( $token === '' ) {
throw new BadRequestException ([ 'sharedSecret' ]);
}
$provider = $this -> shareProviderFactory -> getProviderForType ( IShare :: TYPE_REMOTE );
$share = $provider -> getShareByToken ( $token );
2024-11-17 19:43:47 -05:00
try {
$this -> confirmShareEntry ( $signedRequest , $share -> getSharedWith ());
2024-11-21 05:25:00 -05:00
} catch ( IncomingRequestException $e ) {
2024-11-17 19:43:47 -05:00
// notification might come from the instance that owns the share
2024-11-21 05:25:00 -05:00
$this -> logger -> debug ( 'could not confirm origin on sharedWith (' . $share -> getSharedWIth () . '); going with shareOwner (' . $share -> getShareOwner () . ')' , [ 'exception' => $e ]);
try {
$this -> confirmShareEntry ( $signedRequest , $share -> getShareOwner ());
} catch ( IncomingRequestException $f ) {
// if both entry are failing, we log first exception as warning and second exception
// will be logged as warning by the controller
$this -> logger -> warning ( 'could not confirm origin on sharedWith (' . $share -> getSharedWIth () . '); going with shareOwner (' . $share -> getShareOwner () . ')' , [ 'exception' => $e ]);
throw $f ;
}
2024-11-17 19:43:47 -05:00
}
}
2024-11-12 17:07:16 -05:00
2024-11-17 19:43:47 -05:00
/**
* @ param IIncomingSignedRequest | null $signedRequest
* @ param string $entry
*
* @ return void
* @ throws IncomingRequestException
*/
private function confirmShareEntry ( ? IIncomingSignedRequest $signedRequest , string $entry ) : void {
2024-11-12 17:07:16 -05:00
$instance = $this -> getHostFromFederationId ( $entry );
if ( $signedRequest === null ) {
try {
$this -> signatureManager -> searchSignatory ( $instance );
throw new IncomingRequestException ( 'instance is supposed to sign its request' );
} catch ( SignatoryNotFoundException ) {
return ;
}
} elseif ( $instance !== $signedRequest -> getOrigin ()) {
2024-11-17 19:43:47 -05:00
throw new IncomingRequestException ( 'token sharedWith (' . $instance . ') not linked to origin (' . $signedRequest -> getOrigin () . ')' );
2024-11-12 17:07:16 -05:00
}
}
/**
* @ param string $entry
* @ return string
* @ throws IncomingRequestException
*/
private function getHostFromFederationId ( string $entry ) : string {
if ( ! str_contains ( $entry , '@' )) {
2024-11-17 19:43:47 -05:00
throw new IncomingRequestException ( 'entry ' . $entry . ' does not contains @' );
2024-11-12 17:07:16 -05:00
}
2024-11-17 19:43:47 -05:00
$rightPart = substr ( $entry , strrpos ( $entry , '@' ) + 1 );
2024-11-12 17:07:16 -05:00
2024-11-17 19:43:47 -05:00
// in case the full scheme is sent; getting rid of it
$rightPart = $this -> addressHandler -> removeProtocolFromUrl ( $rightPart );
try {
return $this -> signatureManager -> extractIdentityFromUri ( 'https://' . $rightPart );
} catch ( IdentityNotFoundException ) {
throw new IncomingRequestException ( 'invalid host within federation id: ' . $entry );
2024-11-12 17:07:16 -05:00
}
}
2018-04-30 10:29:56 -04:00
}