streams/Zotlabs/Zot6/Receiver.php

233 lines
5.6 KiB
PHP
Raw Normal View History

2018-04-23 01:51:46 +00:00
<?php
namespace Zotlabs\Zot6;
use Zotlabs\Lib\Config;
2018-06-01 02:42:13 +00:00
use Zotlabs\Lib\Libzot;
2018-12-17 04:37:43 +00:00
use Zotlabs\Lib\Crypto;
2018-05-30 06:52:08 +00:00
use Zotlabs\Web\HTTPSig;
2018-04-23 01:51:46 +00:00
class Receiver {
protected $data;
protected $encrypted;
protected $error;
protected $messagetype;
protected $sender;
2018-06-26 03:55:53 +00:00
protected $site_id;
2018-04-23 01:51:46 +00:00
protected $validated;
protected $recipients;
protected $response;
protected $handler;
protected $prvkey;
2018-05-30 04:08:52 +00:00
protected $rawdata;
protected $sigdata;
2018-04-23 01:51:46 +00:00
2018-06-25 01:54:29 +00:00
function __construct($handler, $localdata = null) {
2018-04-23 01:51:46 +00:00
$this->error = false;
$this->validated = false;
$this->messagetype = '';
$this->response = [ 'success' => false ];
$this->handler = $handler;
$this->data = null;
2018-05-30 04:08:52 +00:00
$this->rawdata = null;
2018-06-26 03:55:53 +00:00
$this->site_id = null;
2018-04-23 01:51:46 +00:00
$this->prvkey = Config::get('system','prvkey');
2018-06-25 01:54:29 +00:00
if($localdata) {
$this->rawdata = $localdata;
}
else {
$this->rawdata = file_get_contents('php://input');
2018-04-23 01:51:46 +00:00
2018-06-25 01:54:29 +00:00
// All access to the zot endpoint must use http signatures
2018-05-30 06:52:08 +00:00
2018-06-25 01:54:29 +00:00
if (! $this->Valid_Httpsig()) {
logger('signature failed');
2018-07-03 03:51:20 +00:00
$this->error = true;
$this->response['message'] = 'signature invalid';
return;
2018-06-25 01:54:29 +00:00
}
2018-05-30 04:08:52 +00:00
}
2018-06-25 01:54:29 +00:00
logger('received raw: ' . print_r($this->rawdata,true), LOGGER_DATA);
2018-05-30 06:52:08 +00:00
if ($this->rawdata) {
2018-05-30 04:08:52 +00:00
$this->data = json_decode($this->rawdata,true);
if(($this->data) && (! is_array($this->data)) && (substr($this->data,0,1) === "{")) {
// Multiple json encoding has been seen in the wild and needs to be fixed on the sending side.
// Proceed anyway and log the event with a backtrace.
btlogger('multiple encoding detected');
$this->data = json_decode($this->data,true);
}
2018-04-23 01:51:46 +00:00
}
else {
$this->error = true;
$this->response['message'] = 'no data';
}
2018-06-25 01:54:29 +00:00
logger('received_json: ' . json_encode($this->data,JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES), LOGGER_DATA);
2018-05-31 03:32:59 +00:00
logger('received: ' . print_r($this->data,true), LOGGER_DATA);
2018-05-29 02:42:40 +00:00
2018-05-30 06:52:08 +00:00
if ($this->data && is_array($this->data)) {
$this->encrypted = ((array_key_exists('encrypted',$this->data) && intval($this->data['encrypted'])) ? true : false);
2018-04-23 01:51:46 +00:00
2018-05-30 06:52:08 +00:00
if ($this->encrypted && $this->prvkey) {
2018-12-17 04:37:43 +00:00
$uncrypted = Crypto::unencapsulate($this->data,$this->prvkey);
2018-05-30 06:52:08 +00:00
if ($uncrypted) {
2018-04-23 01:51:46 +00:00
$this->data = json_decode($uncrypted,true);
}
else {
$this->error = true;
$this->response['message'] = 'no data';
}
}
}
}
function run() {
2018-05-30 06:52:08 +00:00
if ($this->error) {
2018-04-23 01:51:46 +00:00
// make timing attacks on the decryption engine a bit more difficult
usleep(mt_rand(10000,100000));
2018-06-25 01:54:29 +00:00
return($this->response);
2018-04-23 01:51:46 +00:00
}
2018-05-30 06:52:08 +00:00
if ($this->data) {
2018-07-03 03:51:20 +00:00
if (array_key_exists('type',$this->data)) {
2018-04-23 01:51:46 +00:00
$this->messagetype = $this->data['type'];
2018-07-03 03:51:20 +00:00
}
2018-04-23 01:51:46 +00:00
2018-05-30 06:52:08 +00:00
if (! $this->messagetype) {
2018-04-23 01:51:46 +00:00
$this->error = true;
$this->response['message'] = 'no datatype';
2018-07-03 03:51:20 +00:00
return $this->response;
2018-04-23 01:51:46 +00:00
}
2018-06-26 03:55:53 +00:00
$this->sender = ((array_key_exists('sender',$this->data)) ? $this->data['sender'] : null);
2018-04-23 01:51:46 +00:00
$this->recipients = ((array_key_exists('recipients',$this->data)) ? $this->data['recipients'] : null);
2018-06-26 03:55:53 +00:00
$this->site_id = ((array_key_exists('site_id',$this->data)) ? $this->data['site_id'] : null);
2018-04-23 01:51:46 +00:00
}
2018-05-30 06:52:08 +00:00
if ($this->sender) {
2018-06-25 01:54:29 +00:00
$result = $this->ValidateSender();
2018-07-30 06:49:37 +00:00
if (! $result) {
2018-07-03 03:51:20 +00:00
$this->error = true;
2018-06-25 01:54:29 +00:00
return $this->response;
}
2018-05-30 06:52:08 +00:00
}
2018-05-30 04:08:52 +00:00
2018-06-25 01:54:29 +00:00
return $this->Dispatch();
2018-04-23 01:51:46 +00:00
}
function ValidateSender() {
2018-05-30 04:08:52 +00:00
2018-06-26 03:55:53 +00:00
$hub = Libzot::valid_hub($this->sender,$this->site_id);
2018-05-29 02:42:40 +00:00
2018-06-25 01:54:29 +00:00
if (! $hub) {
2018-07-30 03:19:02 +00:00
$x = Libzot::register_hub($this->sigdata['signer']);
if($x['success']) {
$hub = Libzot::valid_hub($this->sender,$this->site_id);
}
if(! $hub) {
$this->response['message'] = 'sender unknown';
return false;
}
2018-07-03 03:51:20 +00:00
}
2018-07-30 06:49:37 +00:00
if (! check_siteallowed($hub['hubloc_url'])) {
2018-07-03 03:51:20 +00:00
$this->response['message'] = 'forbidden';
return false;
}
2018-07-30 06:49:37 +00:00
if (! check_channelallowed($this->sender)) {
2018-07-03 03:51:20 +00:00
$this->response['message'] = 'forbidden';
2018-06-26 03:55:53 +00:00
return false;
2018-04-23 01:51:46 +00:00
}
2018-06-26 03:55:53 +00:00
Libzot::update_hub_connected($hub,$this->site_id);
2018-06-25 01:54:29 +00:00
2018-04-23 01:51:46 +00:00
$this->validated = true;
2018-06-25 01:54:29 +00:00
$this->hub = $hub;
return true;
2018-04-23 01:51:46 +00:00
}
2018-05-30 04:08:52 +00:00
function Valid_Httpsig() {
2018-05-30 06:52:08 +00:00
$result = false;
2018-05-30 04:08:52 +00:00
2020-07-15 11:10:02 +00:00
$this->sigdata = HTTPSig::verify($this->rawdata, EMPTY_STR, 'zot6');
2018-07-30 03:19:02 +00:00
2018-07-30 06:49:37 +00:00
if ($this->sigdata && $this->sigdata['header_signed'] && $this->sigdata['header_valid']) {
2018-05-30 06:52:08 +00:00
$result = true;
// It is OK to not have signed content - not all messages provide content.
// But if it is signed, it has to be valid
if (($this->sigdata['content_signed']) && (! $this->sigdata['content_valid'])) {
2020-07-15 11:10:02 +00:00
$result = false;
2018-05-30 04:08:52 +00:00
}
}
2018-05-30 06:52:08 +00:00
return $result;
2018-05-30 04:08:52 +00:00
}
2018-04-23 01:51:46 +00:00
function Dispatch() {
2018-05-30 06:52:08 +00:00
switch ($this->messagetype) {
2018-04-23 01:51:46 +00:00
case 'purge':
2018-06-26 03:55:53 +00:00
$this->response = $this->handler->Purge($this->sender,$this->recipients,$this->hub);
2018-04-23 01:51:46 +00:00
break;
case 'refresh':
2021-03-11 00:51:42 +00:00
$this->response = $this->handler->Refresh($this->sender,$this->recipients,$this->hub,false);
break;
case 'force_refresh':
$this->response = $this->handler->Refresh($this->sender,$this->recipients,$this->hub,true);
2018-04-23 01:51:46 +00:00
break;
case 'rekey':
2018-06-26 03:55:53 +00:00
$this->response = $this->handler->Rekey($this->sender, $this->data,$this->hub);
2018-04-23 01:51:46 +00:00
break;
case 'activity':
2018-07-10 23:42:16 +00:00
case 'response': // upstream message
case 'sync':
2018-04-23 01:51:46 +00:00
default:
2019-06-14 01:23:48 +00:00
// Only accept these message types with a valid sender
if ($this->sender) {
$this->response = $this->handler->Notify($this->data,$this->hub);
}
2018-04-23 01:51:46 +00:00
break;
2018-06-26 03:55:53 +00:00
2018-04-23 01:51:46 +00:00
}
2018-07-30 06:49:37 +00:00
logger('response_to_return: ' . print_r($this->response,true),LOGGER_DATA);
2018-06-26 03:55:53 +00:00
if ($this->encrypted) {
2018-06-25 01:54:29 +00:00
$this->EncryptResponse();
}
return($this->response);
2018-04-23 01:51:46 +00:00
}
2018-06-25 01:54:29 +00:00
function EncryptResponse() {
$algorithm = Libzot::best_algorithm($this->hub['site_crypto']);
2018-07-30 06:49:37 +00:00
if ($algorithm) {
2018-12-17 04:37:43 +00:00
$this->response = Crypto::encapsulate(json_encode($this->response),$this->hub['hubloc_sitekey'], $algorithm);
2018-06-25 01:54:29 +00:00
}
}
2018-04-23 01:51:46 +00:00
}