Signed-off-by: Maxence Lange <maxence@artificial-owl.com>
pull/619/head
Maxence Lange 2019-07-09 18:54:51 -01:00
rodzic 502d94316b
commit c16f477e73
5 zmienionych plików z 93 dodań i 27 usunięć

Wyświetl plik

@ -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

Wyświetl plik

@ -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

Wyświetl plik

@ -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;

Wyświetl plik

@ -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;

Wyświetl plik

@ -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);