Merge branch 'master' of https://github.com/friendica/red
This commit is contained in:
commit
f49837d7ee
@ -489,62 +489,6 @@ function unmark_for_death($contact) {
|
||||
);
|
||||
}}
|
||||
|
||||
if(! function_exists('contact_photo_menu')){
|
||||
function contact_photo_menu($contact) {
|
||||
|
||||
$a = get_app();
|
||||
|
||||
$contact_url="";
|
||||
$pm_url="";
|
||||
$status_link="";
|
||||
$photos_link="";
|
||||
$posts_link="";
|
||||
$poke_link="";
|
||||
|
||||
$sparkle = false;
|
||||
if($contact['xchan_network'] === NETWORK_ZOT) {
|
||||
$sparkle = true;
|
||||
$profile_link = $a->get_baseurl() . '/magic?f=&id=' . $contact['abook_id'];
|
||||
}
|
||||
else
|
||||
$profile_link = $contact['xchan_url'];
|
||||
|
||||
if($sparkle) {
|
||||
$status_link = $profile_link . "&url=status";
|
||||
$photos_link = $profile_link . "&url=photos";
|
||||
$profile_link = $profile_link . "&url=profile";
|
||||
$pm_url = $a->get_baseurl() . '/message/new/' . $contact['xchan_hash'];
|
||||
}
|
||||
|
||||
$poke_link = $a->get_baseurl() . '/poke/?f=&c=' . $contact['abook_id'];
|
||||
$contact_url = $a->get_baseurl() . '/connections/' . $contact['abook_id'];
|
||||
$posts_link = $a->get_baseurl() . '/network/?cid=' . $contact['abook_id'];
|
||||
|
||||
$menu = Array(
|
||||
t("Poke") => $poke_link,
|
||||
t("View Status") => $status_link,
|
||||
t("View Profile") => $profile_link,
|
||||
t("View Photos") => $photos_link,
|
||||
t("Network Posts") => $posts_link,
|
||||
t("Edit Contact") => $contact_url,
|
||||
t("Send PM") => $pm_url,
|
||||
);
|
||||
|
||||
|
||||
$args = array('contact' => $contact, 'menu' => &$menu);
|
||||
|
||||
call_hooks('contact_photo_menu', $args);
|
||||
|
||||
$o = "";
|
||||
foreach($menu as $k=>$v){
|
||||
if ($v!="") {
|
||||
$o .= "<li><a href=\"$v\">$k</a></li>\n";
|
||||
}
|
||||
}
|
||||
return $o;
|
||||
}}
|
||||
|
||||
|
||||
function random_profile() {
|
||||
$r = q("select xchan_url from xchan where 1 order by rand() limit 1");
|
||||
if($r)
|
||||
@ -553,26 +497,3 @@ function random_profile() {
|
||||
}
|
||||
|
||||
|
||||
function contacts_not_grouped($uid,$start = 0,$count = 0) {
|
||||
|
||||
if(! $count) {
|
||||
$r = q("select count(*) as total from contact where uid = %d and self = 0 and id not in (select distinct(`contact-id`) from group_member where uid = %d) ",
|
||||
intval($uid),
|
||||
intval($uid)
|
||||
);
|
||||
|
||||
return $r;
|
||||
|
||||
|
||||
}
|
||||
|
||||
$r = q("select * from contact where uid = %d and self = 0 and id not in (select distinct(`contact-id`) from group_member where uid = %d) and blocked = 0 and pending = 0 limit %d, %d",
|
||||
intval($uid),
|
||||
intval($uid),
|
||||
intval($start),
|
||||
intval($count)
|
||||
);
|
||||
|
||||
return $r;
|
||||
}
|
||||
|
||||
|
@ -1084,7 +1084,7 @@ function format_categories(&$item,$writeable) {
|
||||
if(! trim($term))
|
||||
continue;
|
||||
$removelink = (($writeable) ? z_root() . '/filerm/' . $item['id'] . '?f=&cat=' . urlencode($t['term']) : '');
|
||||
$categories[] = array('term' => $term, 'writeable' => $writeable, 'removelink' => $removelink, 'url' => $t['url']);
|
||||
$categories[] = array('term' => $term, 'writeable' => $writeable, 'removelink' => $removelink, 'url' => zid($t['url']));
|
||||
}
|
||||
}
|
||||
$s = replace_macros(get_markup_template('item_categories.tpl'),array(
|
||||
|
@ -691,6 +691,16 @@ function import_xchan($arr,$ud_flags = 1) {
|
||||
dbesc($xchan_hash)
|
||||
);
|
||||
|
||||
// See if a primary is specified
|
||||
|
||||
$has_primary = false;
|
||||
foreach($arr['locations'] as $location) {
|
||||
if($location['primary']) {
|
||||
$has_primary = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
foreach($arr['locations'] as $location) {
|
||||
if(! rsa_verify($location['url'],base64url_decode($location['url_sig']),$arr['key'])) {
|
||||
logger('import_xchan: Unable to verify site signature for ' . $location['url']);
|
||||
@ -698,6 +708,12 @@ function import_xchan($arr,$ud_flags = 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ensure that they have one primary hub
|
||||
|
||||
if(! $has_primary)
|
||||
$location['primary'] = true;
|
||||
|
||||
|
||||
for($x = 0; $x < count($xisting); $x ++) {
|
||||
if(($xisting[$x]['hubloc_url'] === $location['url']) && ($xisting[$x]['hubloc_sitekey'] === $location['sitekey'])) {
|
||||
$xisting[$x]['updated'] = true;
|
||||
|
@ -669,7 +669,6 @@ function connections_content(&$a) {
|
||||
$contacts[] = array(
|
||||
'img_hover' => sprintf( t('%1$s [%2$s]'),$rr['xchan_name'],$rr['xchan_url']),
|
||||
'edit_hover' => t('Edit contact'),
|
||||
'photo_menu' => contact_photo_menu($rr),
|
||||
'id' => $rr['abook_id'],
|
||||
'alt_text' => $alt_text,
|
||||
'dir_icon' => $dir_icon,
|
||||
|
108
mod/magic.php
108
mod/magic.php
@ -13,64 +13,20 @@ function magic_init(&$a) {
|
||||
$dest = ((x($_REQUEST,'dest')) ? $_REQUEST['dest'] : '');
|
||||
$rev = ((x($_REQUEST,'rev')) ? intval($_REQUEST['rev']) : 0);
|
||||
|
||||
if($hash) {
|
||||
$x = q("select xchan.xchan_url, hubloc.* from xchan left join hubloc on xchan_hash = hubloc_hash
|
||||
where hubloc_hash = '%s' and (hubloc_flags & %d) order by hubloc_id desc limit 1",
|
||||
dbesc($hash),
|
||||
intval(HUBLOC_FLAGS_PRIMARY)
|
||||
);
|
||||
}
|
||||
elseif($addr) {
|
||||
$x = q("select hubloc.* from xchan left join hubloc on xchan_hash = hubloc_hash
|
||||
where xchan_addr = '%s' and (hubloc_flags & %d) order by hubloc_id desc limit 1",
|
||||
dbesc($addr),
|
||||
intval(HUBLOC_FLAGS_PRIMARY)
|
||||
);
|
||||
}
|
||||
else {
|
||||
|
||||
// See if we know anybody at the dest site that will unlock the door for us
|
||||
// This is the equivalent of buzzing every apartment in an apartment block
|
||||
// to get inside the front gate. The thing about magic auth is that we're
|
||||
// authenticating to the other site. Permissions provided by various
|
||||
// channels will still affect what we can do once authenticated.
|
||||
$parsed = parse_url($dest);
|
||||
if(! $parsed)
|
||||
goaway($dest);
|
||||
|
||||
$b = explode('/',$dest);
|
||||
|
||||
if(count($b) >= 2) {
|
||||
$u = $b[0] . '//' . $b[2];
|
||||
|
||||
if(local_user()) {
|
||||
// first look for a connection or anybody who knows us
|
||||
$x = q("select xchan.xchan_url, hubloc.* from xchan left join hubloc on xchan_hash = hubloc_hash
|
||||
left join abook on abook_xchan = hubloc_hash
|
||||
where abook_channel = %d and hubloc_url = '%s' order by hubloc_id desc limit 5",
|
||||
intval(local_user()),
|
||||
dbesc($u)
|
||||
);
|
||||
}
|
||||
if(! $x) {
|
||||
// no luck - ok anybody will do
|
||||
$x = q("select xchan.xchan_url, hubloc.* from xchan left join hubloc on xchan_hash = hubloc_hash
|
||||
where hubloc_url = '%s' order by hubloc_id desc limit 5",
|
||||
dbesc($u)
|
||||
);
|
||||
}
|
||||
|
||||
if($x) {
|
||||
// They must have a valid hubloc_addr
|
||||
while(! strpos($x[0]['hubloc_addr'],'@')) {
|
||||
array_shift($x);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
$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) {
|
||||
|
||||
// Finger them if they've never been seen here before
|
||||
// Somebody new? Finger them if they've never been seen here before
|
||||
|
||||
if($addr) {
|
||||
$ret = zot_finger($addr,null);
|
||||
@ -78,10 +34,11 @@ function magic_init(&$a) {
|
||||
$j = json_decode($ret['body'],true);
|
||||
if($j)
|
||||
import_xchan($j);
|
||||
$x = q("select hubloc.* from xchan left join hubloc on xchan_hash = hubloc_hash
|
||||
where xchan_addr = '%s' and (hubloc_flags & %d) order by hubloc_id desc limit 1",
|
||||
dbesc($addr),
|
||||
intval(HUBLOC_FLAGS_PRIMARY)
|
||||
|
||||
// Now try again
|
||||
|
||||
$x = q("select * from hubloc where hubloc_url = '%s' order by hubloc_connected desc limit 1",
|
||||
dbesc($basepath)
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -91,8 +48,8 @@ function magic_init(&$a) {
|
||||
if($rev)
|
||||
goaway($dest);
|
||||
else {
|
||||
logger('mod_magic: channel not found.' . print_r($_REQUEST,true));
|
||||
notice( t('Channel not found.') . EOL);
|
||||
logger('mod_magic: no channels found for requested hub.' . print_r($_REQUEST,true));
|
||||
notice( t('Hub not found.') . EOL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -112,25 +69,10 @@ function magic_init(&$a) {
|
||||
if(! $arr['proceed'])
|
||||
goaway($dest);
|
||||
|
||||
if($x[0]['hubloc_url'] === z_root()) {
|
||||
$webbie = substr($x[0]['hubloc_addr'],0,strpos('@',$x[0]['hubloc_addr']));
|
||||
switch($dest) {
|
||||
case 'channel':
|
||||
$desturl = z_root() . '/channel/' . $webbie;
|
||||
break;
|
||||
case 'photos':
|
||||
$desturl = z_root() . '/photos/' . $webbie;
|
||||
break;
|
||||
case 'profile':
|
||||
$desturl = z_root() . '/profile/' . $webbie;
|
||||
break;
|
||||
default:
|
||||
$desturl = $dest;
|
||||
break;
|
||||
}
|
||||
if((get_observer_hash()) && ($x[0]['hubloc_url'] === z_root())) {
|
||||
// We are already authenticated on this site and a registered observer.
|
||||
// Just redirect.
|
||||
goaway($desturl);
|
||||
goaway($dest);
|
||||
}
|
||||
|
||||
if(local_user()) {
|
||||
@ -142,20 +84,15 @@ function magic_init(&$a) {
|
||||
$channel['token'] = $token;
|
||||
$channel['token_sig'] = $token_sig;
|
||||
|
||||
|
||||
$recip = array(array('guid' => $x[0]['hubloc_guid'],'guid_sig' => $x[0]['hubloc_guid_sig']));
|
||||
|
||||
$hash = random_string();
|
||||
|
||||
$r = q("insert into verify ( type, channel, token, meta, created) values ('%s','%d','%s','%s','%s')",
|
||||
dbesc('auth'),
|
||||
intval($channel['channel_id']),
|
||||
dbesc($token),
|
||||
dbesc($x[0]['hubloc_hash']),
|
||||
dbesc($x[0]['hubloc_url']),
|
||||
dbesc(datetime_convert())
|
||||
);
|
||||
|
||||
$target_url = $x[0]['hubloc_callback'] . '/' . substr($x[0]['hubloc_addr'],0,strpos($x[0]['hubloc_addr'],'@')) ;
|
||||
$target_url = $x[0]['hubloc_callback'];
|
||||
logger('mod_magic: redirecting to: ' . $target_url, LOGGER_DEBUG);
|
||||
|
||||
goaway($target_url
|
||||
@ -163,7 +100,6 @@ function magic_init(&$a) {
|
||||
. '&sec=' . $token . '&dest=' . urlencode($dest) . '&version=' . ZOT_REVISION);
|
||||
}
|
||||
|
||||
if(strpos($dest,'/'))
|
||||
goaway($dest);
|
||||
goaway(z_root());
|
||||
goaway($dest);
|
||||
|
||||
}
|
||||
|
@ -1,65 +0,0 @@
|
||||
<?php
|
||||
|
||||
require_once('include/Contact.php');
|
||||
require_once('include/socgraph.php');
|
||||
require_once('include/contact_selectors.php');
|
||||
|
||||
function nogroup_init(&$a) {
|
||||
|
||||
if(! local_user())
|
||||
return;
|
||||
|
||||
require_once('include/group.php');
|
||||
require_once('include/contact_widgets.php');
|
||||
|
||||
if(! x($a->page,'aside'))
|
||||
$a->page['aside'] = '';
|
||||
|
||||
$a->page['aside'] .= group_side('contacts','group',false,0,$contact_id);
|
||||
}
|
||||
|
||||
|
||||
function nogroup_content(&$a) {
|
||||
|
||||
if(! local_user()) {
|
||||
notice( t('Permission denied.') . EOL);
|
||||
return '';
|
||||
}
|
||||
|
||||
require_once('include/Contact.php');
|
||||
$r = contacts_not_grouped(local_user());
|
||||
if(count($r)) {
|
||||
$a->set_pager_total($r[0]['total']);
|
||||
}
|
||||
$r = contacts_not_grouped(local_user(),$a->pager['start'],$a->pager['itemspage']);
|
||||
if(count($r)) {
|
||||
foreach($r as $rr) {
|
||||
|
||||
|
||||
$contacts[] = array(
|
||||
'img_hover' => sprintf( t('Visit %s\'s profile [%s]'),$rr['name'],$rr['url']),
|
||||
'edit_hover' => t('Edit contact'),
|
||||
'photo_menu' => contact_photo_menu($rr),
|
||||
'id' => $rr['id'],
|
||||
'alt_text' => $alt_text,
|
||||
'dir_icon' => $dir_icon,
|
||||
'thumb' => $rr['thumb'],
|
||||
'name' => $rr['name'],
|
||||
'username' => $rr['name'],
|
||||
'sparkle' => $sparkle,
|
||||
'itemurl' => $rr['url'],
|
||||
'link' => $url,
|
||||
'network' => network_to_name($rr['network']),
|
||||
);
|
||||
}
|
||||
}
|
||||
$tpl = get_markup_template("nogroup-template.tpl");
|
||||
$o .= replace_macros($tpl,array(
|
||||
'$header' => t('Contacts who are not members of a group'),
|
||||
'$contacts' => $contacts,
|
||||
'$paginate' => paginate($a),
|
||||
));
|
||||
|
||||
return $o;
|
||||
|
||||
}
|
248
mod/post.php
248
mod/post.php
@ -18,27 +18,26 @@ function post_init(&$a) {
|
||||
* Magic Auth
|
||||
* ==========
|
||||
*
|
||||
* So-called "magic auth" takes place by a special exchange. On the remote computer, a redirection is made to the zot endpoint with special GET parameters.
|
||||
* So-called "magic auth" takes place by a special exchange. On the site where the "channel to be authenticated" lives (e.g. $mysite),
|
||||
* a redirection is made via $mysite/magic to the zot endpoint of the remote site ($remotesite) with special GET parameters.
|
||||
*
|
||||
* Endpoint: https://example.com/post/name (name is now optional - we are authenticating to a site, not a channel)
|
||||
* The endpoint is typically https://$remotesite/post - or whatever was specified as the callback url in prior communications
|
||||
* (we will bootstrap an address and fetch a zot info packet if possible where no prior communications exist)
|
||||
*
|
||||
* where 'name' is the left hand side of the channel webbie, for instance 'mike' where the webbie is 'mike@zothub.com'
|
||||
* Four GET parameters are supplied:
|
||||
*
|
||||
* Additionally four GET parameters are supplied:
|
||||
*
|
||||
** auth => the webbie of the person requesting access
|
||||
** auth => the urlencoded webbie (channel@host.domain) of the channel requesting access
|
||||
** dest => the desired destination URL (urlencoded)
|
||||
** sec => a random string which is also stored locally for use during the verification phase.
|
||||
** sec => a random string which is also stored on $mysite for use during the verification phase.
|
||||
** version => the zot revision
|
||||
*
|
||||
* When this packet is received, a zot message is sent to the site hosting the request auth identity.
|
||||
* When this packet is received, an "auth-check" zot message is sent to $mysite.
|
||||
* (e.g. if $_GET['auth'] is foobar@podunk.edu, a zot packet is sent to the podunk.edu zot endpoint, which is typically /post)
|
||||
* If no information has been recorded about the requesting identity a zot information packet will be retrieved before
|
||||
* continuing.
|
||||
*
|
||||
* The sender of this packet is the name attached to the request endpoint. e.g. 'mike' in this example. If this channel
|
||||
* cannot be located, we will choose any local channel as the sender. The recipients will be a single recipient corresponding
|
||||
* to the guid and guid_sig we have associated with the auth identity
|
||||
* The sender of this packet is a random site channel. The recipients will be a single recipient corresponding
|
||||
* to the guid and guid_sig we have associated with the requesting auth identity
|
||||
*
|
||||
*
|
||||
* {
|
||||
@ -72,63 +71,35 @@ function post_init(&$a) {
|
||||
* }
|
||||
*
|
||||
* 'confirm' in this case is the base64url encoded RSA signature of the concatenation of 'secret' with the
|
||||
* base64url encoded whirlpool hash of the source guid and guid_sig; signed with the source channel private key.
|
||||
* base64url encoded whirlpool hash of the requestor's guid and guid_sig; signed with the source channel private key.
|
||||
* This prevents a man-in-the-middle from inserting a rogue success packet. Upon receipt and successful
|
||||
* verification of this packet, the destination site will redirect to the original destination URL and indicate a successful remote login.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
if(argc() > 1) {
|
||||
$webbie = argv(1);
|
||||
}
|
||||
else
|
||||
$webbie = '';
|
||||
|
||||
if(array_key_exists('auth',$_REQUEST)) {
|
||||
logger('mod_zot: auth request received.');
|
||||
$address = $_REQUEST['auth'];
|
||||
$dest = $_REQUEST['dest'];
|
||||
$desturl = $_REQUEST['dest'];
|
||||
$sec = $_REQUEST['sec'];
|
||||
$version = $_REQUEST['version'];
|
||||
|
||||
switch($dest) {
|
||||
case 'channel':
|
||||
$desturl = z_root() . '/channel/' . $webbie;
|
||||
break;
|
||||
case 'photos':
|
||||
$desturl = z_root() . '/photos/' . $webbie;
|
||||
break;
|
||||
case 'profile':
|
||||
$desturl = z_root() . '/profile/' . $webbie;
|
||||
break;
|
||||
default:
|
||||
$desturl = $dest;
|
||||
break;
|
||||
}
|
||||
if($webbie) {
|
||||
$c = q("select * from channel where channel_address = '%s' limit 1",
|
||||
dbesc($webbie)
|
||||
);
|
||||
}
|
||||
|
||||
// They are authenticating ultimately to the site and not to a particular channel.
|
||||
// Any channel will do, providing it's currently active. We just need to have an
|
||||
// identity to attach to the packet we send back. So find one.
|
||||
|
||||
$c = q("select * from channel where not ( channel_pageflags & %d ) limit 1",
|
||||
intval(PAGE_REMOVED)
|
||||
);
|
||||
|
||||
if(! $c) {
|
||||
// nobody here
|
||||
|
||||
// They are authenticating ultimately to the site and not to a particular channel.
|
||||
// Any channel will do, providing it's currently active. We just need to have an
|
||||
// identity to attach to the packet we send back. So find one.
|
||||
|
||||
$c = q("select * from channel where not ( channel_pageflags & %d ) limit 1",
|
||||
intval(PAGE_REMOVED)
|
||||
);
|
||||
|
||||
if(! $c) {
|
||||
|
||||
// nobody here
|
||||
|
||||
logger('mod_zot: auth: unable to find channel ' . $webbie);
|
||||
goaway($desturl);
|
||||
}
|
||||
logger('mod_zot: auth: unable to find a response channel');
|
||||
goaway($desturl);
|
||||
}
|
||||
|
||||
// Try and find a hubloc for the person attempting to auth
|
||||
@ -153,7 +124,7 @@ function post_init(&$a) {
|
||||
goaway($desturl);
|
||||
}
|
||||
|
||||
logger('mod_zot: auth request received from ' . $x[0]['xchan_addr'] . ' for ' . (($webbie) ? $webbie : 'undefined'));
|
||||
logger('mod_zot: auth request received from ' . $x[0]['xchan_addr'] );
|
||||
|
||||
// check credentials and access
|
||||
|
||||
@ -166,10 +137,12 @@ function post_init(&$a) {
|
||||
$already_authed = ((($remote) && ($x[0]['hubloc_hash'] == $remote)) ? true : false);
|
||||
|
||||
if(! $already_authed) {
|
||||
// Auth packets MUST use ultra top-secret hush-hush mode
|
||||
$p = zot_build_packet($c[0],$type = 'auth_check',
|
||||
array(array('guid' => $x[0]['hubloc_guid'],'guid_sig' => $x[0]['hubloc_guid_sig'])),
|
||||
$x[0]['hubloc_sitekey'], $sec);
|
||||
|
||||
// Auth packets MUST use ultra top-secret hush-hush mode - e.g. the entire packet is encrypted using the site private key
|
||||
// The actual channel sending the packet ($c[0]) is not important, but this provides a generic zot packet with a sender
|
||||
// which can be verified
|
||||
|
||||
$p = zot_build_packet($c[0],$type = 'auth_check', array(array('guid' => $x[0]['hubloc_guid'],'guid_sig' => $x[0]['hubloc_guid_sig'])), $x[0]['hubloc_sitekey'], $sec);
|
||||
$result = zot_zot($x[0]['hubloc_callback'],$p);
|
||||
if(! $result['success']) {
|
||||
logger('mod_zot: auth_check callback failed.');
|
||||
@ -211,7 +184,7 @@ function post_init(&$a) {
|
||||
logger('mod_zot: auth success from ' . $x[0]['xchan_addr'] . ' for ' . $webbie);
|
||||
|
||||
} else {
|
||||
logger('mod_zot: still not authenticated: ' . $x[0]['xchan_addr']);
|
||||
logger('mod_zot: magic-auth failure - not authenticated: ' . $x[0]['xchan_addr']);
|
||||
q("update hubloc set hubloc_status = (hubloc_status | %d ) where hubloc_addr = '%s'",
|
||||
intval(HUBLOC_RECEIVE_ERROR),
|
||||
dbesc($x[0]['xchan_addr'])
|
||||
@ -391,6 +364,7 @@ function post_post(&$a) {
|
||||
|
||||
logger('mod_zot: ' . print_r($_REQUEST,true), LOGGER_DEBUG);
|
||||
|
||||
$encrypted_packet = false;
|
||||
$ret = array('success' => false);
|
||||
|
||||
$data = json_decode($_REQUEST['data'],true);
|
||||
@ -403,17 +377,10 @@ function post_post(&$a) {
|
||||
*/
|
||||
|
||||
if(array_key_exists('iv',$data)) {
|
||||
$encrypted_packet = true;
|
||||
$data = crypto_unencapsulate($data,get_config('system','prvkey'));
|
||||
logger('mod_zot: decrypt1: ' . $data, LOGGER_DATA);
|
||||
|
||||
// susceptible to Bleichenbacher's attack
|
||||
// if(! $data) {
|
||||
// $ret['message'] = 'Decryption failed.';
|
||||
// json_return_and_die($ret);
|
||||
// }
|
||||
|
||||
$data = json_decode($data,true);
|
||||
|
||||
}
|
||||
|
||||
if(! $data) {
|
||||
@ -552,6 +519,8 @@ function post_post(&$a) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* All other message types require us to verify the sender. This is a generic check, so we
|
||||
* will do it once here and bail if anything goes wrong.
|
||||
@ -606,6 +575,91 @@ function post_post(&$a) {
|
||||
if(array_key_exists('recipients',$data))
|
||||
$recipients = $data['recipients'];
|
||||
|
||||
|
||||
if($msgtype === 'auth_check') {
|
||||
|
||||
/**
|
||||
* Requestor visits /magic/?dest=somewhere on their own site with a browser
|
||||
* magic redirects them to $destsite/post [with auth args....]
|
||||
* $destsite sends an auth_check packet to originator site
|
||||
* The auth_check packet is handled here by the originator's site
|
||||
* - the browser session is still waiting
|
||||
* inside $destsite/post for everything to verify
|
||||
* If everything checks out we'll return a token to $destsite
|
||||
* and then $destsite will verify the token, authenticate the browser
|
||||
* session and then redirect to the original destination.
|
||||
* If authentication fails, the redirection to the original destination
|
||||
* will still take place but without authentication.
|
||||
*/
|
||||
logger('mod_zot: auth_check', LOGGER_DEBUG);
|
||||
|
||||
if(! $encrypted_packet) {
|
||||
logger('mod_zot: auth_check packet was not encrypted.');
|
||||
json_return_and_die($ret);
|
||||
}
|
||||
|
||||
$arr = $data['sender'];
|
||||
$sender_hash = base64url_encode(hash('whirlpool',$arr['guid'] . $arr['guid_sig'], true));
|
||||
|
||||
// garbage collect any old unused notifications
|
||||
q("delete from verify where type = 'auth' and created < UTC_TIMESTAMP() - INTERVAL 10 MINUTE");
|
||||
|
||||
$y = q("select xchan_pubkey from xchan where xchan_hash = '%s' limit 1",
|
||||
dbesc($sender_hash)
|
||||
);
|
||||
|
||||
// We created a unique hash in mod/magic.php when we invoked remote auth, and stored it in
|
||||
// the verify table. It is now coming back to us as 'secret' and is signed by a channel at the other end.
|
||||
// First verify their signature. We will have obtained a zot-info packet from them as part of the sender
|
||||
// verification.
|
||||
|
||||
if((! $y) || (! rsa_verify($data['secret'],base64url_decode($data['secret_sig']),$y[0]['xchan_pubkey']))) {
|
||||
logger('mod_zot: auth_check: sender not found or secret_sig invalid.');
|
||||
json_return_and_die($ret);
|
||||
}
|
||||
|
||||
// There should be exactly one recipient, the original auth requestor
|
||||
|
||||
if($data['recipients']) {
|
||||
|
||||
$arr = $data['recipients'][0];
|
||||
$recip_hash = base64url_encode(hash('whirlpool',$arr['guid'] . $arr['guid_sig'], true));
|
||||
$c = q("select channel_id, channel_prvkey from channel where channel_hash = '%s' limit 1",
|
||||
dbesc($recip_hash)
|
||||
);
|
||||
if(! $c) {
|
||||
logger('mod_zot: auth_check: recipient channel not found.');
|
||||
json_return_and_die($ret);
|
||||
}
|
||||
|
||||
$confirm = base64url_encode(rsa_sign($data['secret'] . $recip_hash,$c[0]['channel_prvkey']));
|
||||
|
||||
// This additionally checks for forged sites since we already stored the expected result in meta
|
||||
// and we've already verified that this is them via zot_gethub() and that their key signed our token
|
||||
|
||||
$z = q("select id from verify where channel = %d and type = 'auth' and token = '%s' and meta = '%s' limit 1",
|
||||
intval($c[0]['channel_id']),
|
||||
dbesc($data['secret']),
|
||||
dbesc($data['sender']['url'])
|
||||
);
|
||||
if(! $z) {
|
||||
logger('mod_zot: auth_check: verification key not found.');
|
||||
json_return_and_die($ret);
|
||||
}
|
||||
$r = q("delete from verify where id = %d limit 1",
|
||||
intval($z[0]['id'])
|
||||
);
|
||||
|
||||
logger('mod_zot: auth_check: success', LOGGER_DEBUG);
|
||||
$ret['success'] = true;
|
||||
$ret['confirm'] = $confirm;
|
||||
json_return_and_die($ret);
|
||||
|
||||
}
|
||||
json_return_and_die($ret);
|
||||
}
|
||||
|
||||
|
||||
if($msgtype === 'purge') {
|
||||
if($recipients) {
|
||||
// basically this means "unfriend"
|
||||
@ -696,66 +750,6 @@ function post_post(&$a) {
|
||||
|
||||
}
|
||||
|
||||
if($msgtype === 'auth_check') {
|
||||
logger('mod_zot: auth_check');
|
||||
$arr = $data['sender'];
|
||||
$sender_hash = base64url_encode(hash('whirlpool',$arr['guid'] . $arr['guid_sig'], true));
|
||||
|
||||
// garbage collect any old unused notifications
|
||||
q("delete from verify where type = 'auth' and created < UTC_TIMESTAMP() - INTERVAL 10 MINUTE");
|
||||
|
||||
$y = q("select xchan_pubkey from xchan where xchan_hash = '%s' limit 1",
|
||||
dbesc($sender_hash)
|
||||
);
|
||||
// We created a unique hash in mod/magic.php when we invoked remote auth, and stored it in
|
||||
// the verify table. It is now coming back to us as 'secret' and is signed by the other site.
|
||||
// First verify their signature.
|
||||
|
||||
if((! $y) || (! rsa_verify($data['secret'],base64url_decode($data['secret_sig']),$y[0]['xchan_pubkey']))) {
|
||||
logger('mod_zot: auth_check: sender not found or secret_sig invalid.');
|
||||
json_return_and_die($ret);
|
||||
}
|
||||
|
||||
// There should be exactly one recipient
|
||||
if($data['recipients']) {
|
||||
|
||||
$arr = $data['recipients'][0];
|
||||
$recip_hash = base64url_encode(hash('whirlpool',$arr['guid'] . $arr['guid_sig'], true));
|
||||
$c = q("select channel_id, channel_prvkey from channel where channel_hash = '%s' limit 1",
|
||||
dbesc($recip_hash)
|
||||
);
|
||||
if(! $c) {
|
||||
logger('mod_zot: auth_check: recipient channel not found.');
|
||||
json_return_and_die($ret);
|
||||
}
|
||||
|
||||
$confirm = base64url_encode(rsa_sign($data['secret'] . $recip_hash,$c[0]['channel_prvkey']));
|
||||
|
||||
// This additionally checks for forged senders since we already stored the expected result in meta
|
||||
// and we've already verified that this is them via zot_gethub() and that their key signed our token
|
||||
|
||||
$z = q("select id from verify where channel = %d and type = 'auth' and token = '%s' and meta = '%s' limit 1",
|
||||
intval($c[0]['channel_id']),
|
||||
dbesc($data['secret']),
|
||||
dbesc($sender_hash)
|
||||
);
|
||||
if(! $z) {
|
||||
logger('mod_zot: auth_check: verification key not found.');
|
||||
json_return_and_die($ret);
|
||||
}
|
||||
$r = q("delete from verify where id = %d limit 1",
|
||||
intval($z[0]['id'])
|
||||
);
|
||||
|
||||
logger('mod_zot: auth_check: success', LOGGER_DEBUG);
|
||||
$ret['success'] = true;
|
||||
$ret['confirm'] = $confirm;
|
||||
json_return_and_die($ret);
|
||||
|
||||
}
|
||||
json_return_and_die($ret);
|
||||
}
|
||||
|
||||
|
||||
// catchall
|
||||
json_return_and_die($ret);
|
||||
|
@ -1 +1 @@
|
||||
2013-12-01.514
|
||||
2013-12-02.515
|
||||
|
@ -3,7 +3,7 @@
|
||||
color: #000;
|
||||
}
|
||||
.abook-them {
|
||||
margin-left: 225px;
|
||||
margin-left: 375px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.abook-me {
|
||||
|
@ -1834,6 +1834,7 @@ a.mail-list-link {
|
||||
border-radius: $radiuspx;
|
||||
padding: 5px;
|
||||
font-weight: bold;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
|
||||
|
@ -23,11 +23,6 @@
|
||||
<div id="sidebar-new-group">
|
||||
<a href="group/new">{{$createtext}}</a>
|
||||
</div>
|
||||
{{if $ungrouped}}
|
||||
<div id="sidebar-ungrouped">
|
||||
<a href="nogroup">{{$ungrouped}}</a>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user