better signature handling

This commit is contained in:
zotlabs 2018-10-09 21:08:57 -07:00
parent 2e9e82662a
commit c4ea93e6a6
13 changed files with 91 additions and 87 deletions

View file

@ -13,6 +13,7 @@ class ActivityStreams {
public $raw = null;
public $data = null;
public $valid = false;
public $deleted = false;
public $id = '';
public $parent_id = '';
public $type = '';
@ -67,6 +68,13 @@ class ActivityStreams {
$this->valid = true;
if(array_key_exists('type',$this->data) && array_key_exists('actor',$this->data) && array_key_exists('object',$this->data)) {
if($this->data['type'] === 'Delete' && $this->data['actor'] === $this->data['object']) {
$this->deleted = $this->data['actor'];
$this->valid = false;
}
}
}
if($this->is_valid()) {

View file

@ -12,10 +12,18 @@ class Zotfinger {
return false;
}
if($channel) {
$m = parse_url($resource);
$data = json_encode([ 'zot_token' => random_string() ]);
if($channel && $m) {
$headers = [
'Accept' => 'application/x-zot+json',
'Content-Type' => 'application/x-zot+json',
'X-Zot-Token' => random_string(),
'Digest' => HTTPSig::generate_digest_header($data),
'Host' => $m['host'],
];
$h = HTTPSig::create_sig($headers,$channel['channel_prvkey'],channel_url($channel),false);
}
@ -27,7 +35,7 @@ class Zotfinger {
$redirects = 0;
$x = z_fetch_url($resource,false,$redirects, [ 'headers' => $h ] );
$x = z_post_url($resource,$data,$redirects, [ 'headers' => $h ] );
if($x['success']) {

View file

@ -77,7 +77,7 @@ class Channel extends Controller {
if(Libzot::is_zot_request()) {
$sigdata = HTTPSig::verify(EMPTY_STR);
$sigdata = HTTPSig::verify(file_get_contents('php://input'));
if($sigdata && $sigdata['signer'] && $sigdata['header_valid']) {
$data = json_encode(Libzot::zotinfo([ 'address' => $channel['channel_address'], 'target_url' => $sigdata['signer'] ]));

View file

@ -39,8 +39,19 @@ class Inbox extends Controller {
//logger('debug: ' . $AS->debug());
if(! $AS->is_valid())
if(! $AS->is_valid()) {
if($AS->deleted) {
// process mastodon user deletion activities, but only if we can validate the signature
if($hsig['header_valid'] && $hsig['content_valid'] && $hsig['portable_id']) {
logger('removing deleted actor');
remove_all_xchan_resources($hsig['portable_id']);
}
else {
logger('ignoring deleted actor');
}
}
return;
}
// $observer_hash in this case is the sender

View file

@ -25,6 +25,7 @@ class Magic extends \Zotlabs\Web\Controller {
$dest = hex2bin($bdest);
$parsed = parse_url($dest);
if(! $parsed) {
if($test) {
$ret['message'] .= 'could not parse ' . $dest . EOL;
@ -35,56 +36,12 @@ class Magic extends \Zotlabs\Web\Controller {
$basepath = $parsed['scheme'] . '://' . $parsed['host'] . (($parsed['port']) ? ':' . $parsed['port'] : '');
$x = q("select * from hubloc where hubloc_url = '%s' order by hubloc_connected desc limit 1",
dbesc($basepath)
);
if(! $x) {
/*
* We have no records for, or prior communications with this hub.
* If an address was supplied, let's finger them to create a hub record.
* Otherwise we'll use the special address '[system]' which will return
* either a system channel or the first available normal channel. We don't
* really care about what channel is returned - we need the hub information
* from that response so that we can create signed auth packets destined
* for that hub.
*
*/
$j = \Zotlabs\Zot\Finger::run((($addr) ? $addr : '[system]@' . $parsed['host']),null);
if($j['success']) {
Libzot::import_xchan($j);
// Now try again
$x = q("select * from hubloc where hubloc_url = '%s' order by hubloc_connected desc limit 1",
dbesc($basepath)
);
}
}
if(! $x) {
if($rev)
goaway($dest);
else {
logger('mod_magic: no channels found for requested hub.' . print_r($_REQUEST,true));
if($test) {
$ret['message'] .= 'This site has no previous connections with ' . $basepath . EOL;
return $ret;
}
notice( t('Hub not found.') . EOL);
return;
}
}
// This is ready-made for a plugin that provides a blacklist or "ask me" before blindly authenticating.
// By default, we'll proceed without asking.
$arr = array(
'channel_id' => local_channel(),
'xchan' => $x[0],
'destination' => $dest,
'proceed' => true
);
@ -137,11 +94,16 @@ class Magic extends \Zotlabs\Web\Controller {
$dest = strip_zids($dest);
$dest = strip_query_param($dest,'f');
$data = json_encode([ 'OpenWebAuth' => random_string() ]);
$headers = [];
$headers['Accept'] = 'application/x-zot+json' ;
$headers['X-Open-Web-Auth'] = random_string();
$headers['Digest'] = HTTPSig::generate_digest_header($data);
$headers['Host'] = $parsed['host'];
$headers = HTTPSig::create_sig($headers,$channel['channel_prvkey'], channel_url($channel),true,'sha512');
$x = z_fetch_url($basepath . '/owa',false,$redirects,[ 'headers' => $headers ]);
$x = z_post_url($basepath . '/owa',$data,$redirects,[ 'headers' => $headers ]);
if($x['success']) {
$j = json_decode($x['body'],true);

View file

@ -52,8 +52,8 @@ class Owa extends \Zotlabs\Web\Controller {
}
if($r) {
foreach($r as $hubloc) {
$verified = HTTPSig::verify('');
if($verified && $verified['header_signed'] && $verified['header_valid']) {
$verified = HTTPSig::verify(file_get_contents('php://input'));
if($verified && $verified['header_signed'] && $verified['header_valid'] && ( $verified['content_valid'] || (! $verified['content_signed']))) {
logger('OWA header: ' . print_r($verified,true),LOGGER_DATA);
logger('OWA success: ' . $hubloc['hubloc_addr'],LOGGER_DATA);
$ret['success'] = true;

View file

@ -1,6 +1,9 @@
<?php
namespace Zotlabs\Module;
use Zotlabs\Lib\Zotfinger;
use Zotlabs\Web\Controller;
/**
* With args, register a directory server for this realm.
* With no args, return a JSON array of directory servers for this realm.
@ -14,7 +17,7 @@ namespace Zotlabs\Module;
* @param App &$a
*/
class Regdir extends \Zotlabs\Web\Controller {
class Regdir extends Controller {
function init() {
@ -25,7 +28,7 @@ class Regdir extends \Zotlabs\Web\Controller {
$valid = 0;
// we probably don't need the realm as we will find out in the probe.
// What we may want to die is throw an error if you're trying to register in a different realm
// What we may want to do is throw an error if you're trying to register in a different realm
// so this configuration issue can be discovered.
$realm = $_REQUEST['realm'];
@ -59,16 +62,13 @@ class Regdir extends \Zotlabs\Web\Controller {
json_return_and_die($result);
}
$j = \Zotlabs\Zot\Finger::run('[system]@' . $m['host']);
if($j['success'] && $j['guid']) {
$x = import_xchan($j);
if($x['success']) {
$j = Zotfinger::exec($url);
if($j) {
$result['success'] = true;
}
}
if(! $result['success'])
else {
$valid = 0;
}
q("update site set site_valid = %d where site_url = '%s'",
intval($valid),
@ -76,17 +76,14 @@ class Regdir extends \Zotlabs\Web\Controller {
);
json_return_and_die($result);
} else {
// We can put this in the sql without the condition after 31 august 2015 assuming
// most directory servers will have updated by then
// This just makes sure it happens if I forget
}
else {
$sql_extra = ((datetime_convert() > datetime_convert('UTC','UTC','2015-08-31')) ? ' and site_valid = 1 ' : '' );
if ($dirmode == DIRECTORY_MODE_STANDALONE) {
$r = array(array('site_url' => z_root()));
} else {
$r = q("select site_url from site where site_flags in ( 1, 2 ) and site_realm = '%s' and site_type = %d $sql_extra ",
$r = q("select site_url from site where site_flags in ( 1, 2 ) and site_realm = '%s' and site_type = %d and site_valid = 1 ",
dbesc(get_directory_realm()),
intval(SITE_TYPE_ZOT)
);

View file

@ -19,9 +19,9 @@ class Zot_probe extends \Zotlabs\Web\Controller {
if(x($_GET,'addr')) {
$addr = $_GET['addr'];
$channel = (($_GET['auth']) ? \App::get_channel() : null);
$x = Zotfinger::exec($addr);
$x = Zotfinger::exec($addr,$channel);
$o .= '<pre>' . htmlspecialchars(print_array($x)) . '</pre>';

View file

@ -120,6 +120,21 @@ class HTTPSig {
if(array_key_exists($h,$headers)) {
$signed_data .= $h . ': ' . $headers[$h] . "\n";
}
if($h === 'host' && (strpos(strtolower(\App::get_hostname()),strtolower($headers[$h])) === false)) {
logger('bad host: ' . $sig_block['keyId'] . ' != ' . $headers[$h]);
return $result;
}
if($h === 'date') {
$d = new \DateTime($headers[$h]);
$d->setTimeZone(new \DateTimeZone('UTC'));
$dplus = datetime_convert('UTC','UTC','now + 1 day');
$dminus = datetime_convert('UTC','UTC','now - 1 day');
$c = $d->format('Y-m-d H:i:s');
if($c > $dplus || $c < $dminus) {
logger('bad time: ' . $c);
return $result;
}
}
}
$signed_data = rtrim($signed_data,"\n");

View file

@ -86,7 +86,7 @@ class Auth {
if(! $x) {
// finger them if they can't be found.
$j = Finger::run($address, null);
$j = false; // Finger::run($address, null);
if ($j['success']) {
import_xchan($j);
$x = q("select * from hubloc left join xchan on xchan_hash = hubloc_hash

View file

@ -62,7 +62,7 @@ class Finger {
if($r) {
$url = $r[0]['hubloc_url'];
if($r[0]['hubloc_network'] && $r[0]['hubloc_network'] !== 'zot') {
if($r[0]['hubloc_network'] && (! in_array($r[0]['hubloc_network'], ['zot','zot6']))) {
logger('zot_finger: alternate network: ' . $webbie);
logger('url: ' . $url . ', net: ' . var_export($r[0]['hubloc_network'],true), LOGGER_DATA, LOG_DEBUG);
return $ret;

View file

@ -278,17 +278,20 @@ function owt_init($token) {
}
$r = q("select * from hubloc left join xchan on xchan_hash = hubloc_hash
where hubloc_addr = '%s' order by hubloc_id desc",
where hubloc_addr = '%s' or hubloc_id_url = '%s' or hubloc_hash = '%s' order by hubloc_id desc",
dbesc($ob_hash),
dbesc($ob_hash),
dbesc($ob_hash)
);
if(! $r) {
// finger them if they can't be found.
$j = \Zotlabs\Zot\Finger::run($ob_hash, null);
if ($j['success']) {
import_xchan($j);
$wf = discover_by_webbie($ob_hash);
if($wf) {
$r = q("select * from hubloc left join xchan on xchan_hash = hubloc_hash
where hubloc_addr = '%s' order by hubloc_id desc",
where hubloc_addr = '%s' or hubloc_id_url = '%s' or hubloc_hash = '%s' order by hubloc_id desc",
dbesc($ob_hash),
dbesc($ob_hash),
dbesc($ob_hash)
);
}

View file

@ -64,13 +64,13 @@ function process_command($line) {
fresh_help();
break;
case 'finger':
if(argv(1)) {
$x = Zotlabs\Zot\Finger::run(argv(1),$channel);
if($x['success'])
echo jindent($x);
}
break;
// case 'finger':
// if(argv(1)) {
// $x = Zotlabs\Zot\Finger::run(argv(1),$channel);
// if($x['success'])
// echo jindent($x);
// }
// break;
case 'login':
if(argv(1)) {