kopia lustrzana https://github.com/nextcloud/social
fixing headers
Signed-off-by: Maxence Lange <maxence@artificial-owl.com>pull/619/head
rodzic
502d94316b
commit
c16f477e73
|
@ -183,7 +183,7 @@ class ActivityPubController extends Controller {
|
|||
$this->miscService->log('[<<] shared-inbox: ' . $body, 1);
|
||||
|
||||
$requestTime = 0;
|
||||
$origin = $this->signatureService->checkRequest($this->request, $requestTime);
|
||||
$origin = $this->signatureService->checkRequest($this->request, $body, $requestTime);
|
||||
$this->fediverseService->authorized($origin);
|
||||
|
||||
$activity = $this->importService->importFromJson($body);
|
||||
|
@ -227,7 +227,7 @@ class ActivityPubController extends Controller {
|
|||
$this->miscService->log('[<<] inbox: ' . $body, 1);
|
||||
|
||||
$requestTime = 0;
|
||||
$origin = $this->signatureService->checkRequest($this->request, $requestTime);
|
||||
$origin = $this->signatureService->checkRequest($this->request, $body,$requestTime);
|
||||
$this->fediverseService->authorized($origin);
|
||||
|
||||
// TODO - check the recipient <-> username
|
||||
|
|
|
@ -40,18 +40,17 @@ use OCA\Social\AP;
|
|||
use OCA\Social\Exceptions\HostMetaException;
|
||||
use OCA\Social\Exceptions\InvalidOriginException;
|
||||
use OCA\Social\Exceptions\InvalidResourceException;
|
||||
use OCA\Social\Exceptions\ItemUnknownException;
|
||||
use OCA\Social\Exceptions\RedundancyLimitException;
|
||||
use OCA\Social\Exceptions\RequestContentException;
|
||||
use OCA\Social\Exceptions\RequestResultNotJsonException;
|
||||
use OCA\Social\Exceptions\RetrieveAccountFormatException;
|
||||
use OCA\Social\Exceptions\RequestNetworkException;
|
||||
use OCA\Social\Exceptions\RequestResultNotJsonException;
|
||||
use OCA\Social\Exceptions\RequestResultSizeException;
|
||||
use OCA\Social\Exceptions\RequestServerException;
|
||||
use OCA\Social\Exceptions\RetrieveAccountFormatException;
|
||||
use OCA\Social\Exceptions\SocialAppConfigException;
|
||||
use OCA\Social\Exceptions\ItemUnknownException;
|
||||
use OCA\Social\Exceptions\UnauthorizedFediverseException;
|
||||
use OCA\Social\Model\ActivityPub\Actor\Person;
|
||||
use OCA\Social\Model\ActivityPub\Actor\Service;
|
||||
|
||||
class CurlService {
|
||||
|
||||
|
@ -274,10 +273,13 @@ class CurlService {
|
|||
|
||||
$curl = $this->initRequest($request);
|
||||
|
||||
$this->initRequestGet($request);
|
||||
$this->initRequestPost($curl, $request);
|
||||
$this->initRequestPut($curl, $request);
|
||||
$this->initRequestDelete($curl, $request);
|
||||
|
||||
$this->initRequestHeaders($curl, $request);
|
||||
|
||||
$result = curl_exec($curl);
|
||||
|
||||
if ($this->maxDownloadSizeReached === true) {
|
||||
|
@ -359,9 +361,6 @@ class CurlService {
|
|||
private function initRequest(Request $request) {
|
||||
|
||||
$curl = $this->generateCurlRequest($request);
|
||||
$headers = $request->getHeaders();
|
||||
|
||||
$headers[] = 'Accept: application/ld+json; profile="https://www.w3.org/ns/activitystreams"';
|
||||
|
||||
curl_setopt($curl, CURLOPT_USERAGENT, $request->getUserAgent());
|
||||
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, $request->getTimeout());
|
||||
|
@ -369,7 +368,6 @@ class CurlService {
|
|||
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($curl, CURLOPT_BINARYTRANSFER, $request->isBinary());
|
||||
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
|
||||
|
||||
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
|
||||
|
@ -420,6 +418,23 @@ class CurlService {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
*/
|
||||
private function initRequestGet(Request $request) {
|
||||
if ($request->getType() !== Request::TYPE_GET) {
|
||||
return;
|
||||
}
|
||||
|
||||
$request->addHeader(
|
||||
'Accept: application/json; profile="https://www.w3.org/ns/activitystreams"'
|
||||
);
|
||||
$request->addHeader(
|
||||
'Accept: application/ld+json; profile="https://www.w3.org/ns/activitystreams"'
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param resource $curl
|
||||
* @param Request $request
|
||||
|
@ -429,6 +444,10 @@ class CurlService {
|
|||
return;
|
||||
}
|
||||
|
||||
$request->addHeader(
|
||||
'Content-Type: application/ld+json; profile="https://www.w3.org/ns/activitystreams"'
|
||||
);
|
||||
|
||||
curl_setopt($curl, CURLOPT_POST, true);
|
||||
curl_setopt($curl, CURLOPT_POSTFIELDS, $request->getDataBody());
|
||||
}
|
||||
|
@ -462,6 +481,17 @@ class CurlService {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param resource $curl
|
||||
* @param Request $request
|
||||
*/
|
||||
private function initRequestHeaders($curl, Request $request) {
|
||||
$headers = $request->getHeaders();
|
||||
|
||||
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param resource $curl
|
||||
* @param Request $request
|
||||
|
|
|
@ -50,6 +50,7 @@ use OCA\Social\Exceptions\SocialAppConfigException;
|
|||
use OCA\Social\Exceptions\ItemUnknownException;
|
||||
use OCA\Social\Exceptions\UnauthorizedFediverseException;
|
||||
use OCA\Social\Exceptions\UrlCloudException;
|
||||
use OCA\Social\Model\ActivityPub\ACore;
|
||||
use OCA\Social\Model\ActivityPub\Object\Follow;
|
||||
use OCA\Social\Model\ActivityPub\Activity\Undo;
|
||||
use OCA\Social\Model\ActivityPub\Actor\Person;
|
||||
|
|
|
@ -156,44 +156,68 @@ class SignatureService {
|
|||
|
||||
$localActorLink =
|
||||
$this->configService->getUrlSocial() . '@' . $localActor->getPreferredUsername();
|
||||
$signature = "(request-target): post " . $path->getPath() . "\nhost: " . $path->getAddress()
|
||||
. "\ndate: " . $date;
|
||||
|
||||
$digest = $this->generateDigest($request->getDataBody());
|
||||
$contentSize = strlen($request->getDataBody());
|
||||
|
||||
$signature = '';
|
||||
// $signature .= "(request-target): post " . $path->getPath() . "\n";
|
||||
$signature .= 'content-length: ' . $contentSize . "\n";
|
||||
$signature .= 'date: ' . $date . "\n";
|
||||
$signature .= 'digest: ' . $digest . "\n";
|
||||
$signature .= 'host: ' . $path->getAddress();
|
||||
|
||||
openssl_sign($signature, $signed, $localActor->getPrivateKey(), OPENSSL_ALGO_SHA256);
|
||||
$signed = base64_encode($signed);
|
||||
|
||||
$header = 'keyId="' . $localActorLink
|
||||
. '",algorithm="rsa-sha256",headers="(request-target) host date",signature="'
|
||||
$header = 'keyId="' . $localActorLink . '#main-key'
|
||||
. '",algorithm="rsa-sha256",headers="content-length date digest host",signature="'
|
||||
. $signed . '"';
|
||||
|
||||
|
||||
$request->addHeader('Content-length: ' . $contentSize);
|
||||
$request->addHeader('Host: ' . $path->getAddress());
|
||||
$request->addHeader('Date: ' . $date);
|
||||
$request->addHeader('Digest: ' . $digest);
|
||||
$request->addHeader('Signature: ' . $header);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $data
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function generateDigest(string $data): string {
|
||||
$encoded = hash("sha256", utf8_encode($data), true);
|
||||
|
||||
return 'SHA-256=' . base64_encode($encoded);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param IRequest $request
|
||||
*
|
||||
* @param string $data
|
||||
* @param int $time
|
||||
*
|
||||
* @return string
|
||||
* @throws DateTimeException
|
||||
* @throws InvalidOriginException
|
||||
* @throws InvalidResourceException
|
||||
* @throws ItemUnknownException
|
||||
* @throws MalformedArrayException
|
||||
* @throws RedundancyLimitException
|
||||
* @throws RequestNetworkException
|
||||
* @throws RequestResultNotJsonException
|
||||
* @throws RequestResultSizeException
|
||||
* @throws RequestServerException
|
||||
* @throws SignatureException
|
||||
* @throws SignatureIsGoneException
|
||||
* @throws SocialAppConfigException
|
||||
* @throws ItemUnknownException
|
||||
* @throws RequestResultNotJsonException
|
||||
* @throws DateTimeException
|
||||
* @throws UnauthorizedFediverseException
|
||||
*/
|
||||
public function checkRequest(IRequest $request, int &$time = 0): string {
|
||||
public function checkRequest(IRequest $request, string $data, int &$time = 0): string {
|
||||
try {
|
||||
$dTime = new DateTime($request->getHeader('date'));
|
||||
$time = $dTime->getTimestamp();
|
||||
|
@ -208,7 +232,7 @@ class SignatureService {
|
|||
}
|
||||
|
||||
try {
|
||||
$origin = $this->checkRequestSignature($request);
|
||||
$origin = $this->checkRequestSignature($request, $data);
|
||||
} catch (RequestContentException $e) {
|
||||
throw new SignatureIsGoneException();
|
||||
}
|
||||
|
@ -298,25 +322,28 @@ class SignatureService {
|
|||
/**
|
||||
* @param IRequest $request
|
||||
*
|
||||
* @param string $data
|
||||
*
|
||||
* @return string
|
||||
* @throws InvalidOriginException
|
||||
* @throws InvalidResourceException
|
||||
* @throws ItemUnknownException
|
||||
* @throws MalformedArrayException
|
||||
* @throws RedundancyLimitException
|
||||
* @throws RequestContentException
|
||||
* @throws RequestNetworkException
|
||||
* @throws RequestResultNotJsonException
|
||||
* @throws RequestResultSizeException
|
||||
* @throws RequestServerException
|
||||
* @throws SignatureException
|
||||
* @throws SocialAppConfigException
|
||||
* @throws ItemUnknownException
|
||||
* @throws RequestContentException
|
||||
* @throws RequestResultSizeException
|
||||
* @throws RequestResultNotJsonException
|
||||
* @throws UnauthorizedFediverseException
|
||||
*/
|
||||
private function checkRequestSignature(IRequest $request): string {
|
||||
private function checkRequestSignature(IRequest $request, string $data): string {
|
||||
$signatureHeader = $request->getHeader('Signature');
|
||||
|
||||
$sign = $this->parseSignatureHeader($signatureHeader);
|
||||
|
||||
$this->mustContains(['keyId', 'headers', 'signature'], $sign);
|
||||
|
||||
$keyId = $sign['keyId'];
|
||||
|
@ -326,11 +353,17 @@ class SignatureService {
|
|||
$signed = base64_decode($sign['signature']);
|
||||
$estimated = $this->generateEstimatedSignature($headers, $request);
|
||||
|
||||
// TODO: check digest
|
||||
// $this->generateDigest($data);
|
||||
|
||||
$publicKey = $this->retrieveKey($keyId);
|
||||
$algorithm = $this->getAlgorithmFromSignature($sign);
|
||||
if ($publicKey === ''
|
||||
|| openssl_verify($estimated, $signed, $publicKey, $algorithm) !== 1) {
|
||||
throw new SignatureException('signature cannot be checked');
|
||||
throw new SignatureException(
|
||||
'signature cannot be checked key: ' . $publicKey . ' - algo: ' . $algorithm
|
||||
. ' - estimated: ' . $estimated
|
||||
);
|
||||
}
|
||||
|
||||
return $origin;
|
||||
|
|
|
@ -46,8 +46,11 @@ if (!array_key_exists('resource', $_GET)) {
|
|||
$subject = $_GET['resource'];
|
||||
|
||||
$urlGenerator = OC::$server->getURLGenerator();
|
||||
$type = '';
|
||||
|
||||
if (strpos($subject, 'acct:') === 0) {
|
||||
list($type, $account) = explode(':', $subject, 2);
|
||||
$type .= ':';
|
||||
} else {
|
||||
$account = $subject;
|
||||
}
|
||||
|
@ -88,7 +91,7 @@ if (substr($href, -1) === '/') {
|
|||
}
|
||||
|
||||
$finger = [
|
||||
'subject' => 'acct:' . $username . '@' . $instance,
|
||||
'subject' => $type . $username . '@' . $instance,
|
||||
'links' => [
|
||||
[
|
||||
'rel' => 'self',
|
||||
|
@ -106,7 +109,6 @@ $finger = [
|
|||
]
|
||||
];
|
||||
|
||||
|
||||
header('Content-type: application/json');
|
||||
|
||||
echo json_encode($finger);
|
||||
|
|
Ładowanie…
Reference in New Issue