diff options
-rw-r--r-- | boot.php | 9 | ||||
-rw-r--r-- | include/auth.php | 21 | ||||
-rw-r--r-- | include/zot.php | 11 | ||||
-rw-r--r-- | mod/magic.php | 119 | ||||
-rw-r--r-- | mod/post.php | 151 |
5 files changed, 232 insertions, 79 deletions
@@ -454,7 +454,7 @@ if(! class_exists('App')) { private $widgets = array(); // widgets for this page - + public $groups; public $language; public $module_loaded = false; public $query_string; @@ -749,6 +749,13 @@ if(! class_exists('App')) { $this->apps = $arr; } + function set_groups($g) { + $this->groups = $g; + } + + function get_groups() { + return $this->groups; + } function set_widget($title,$html, $location = 'aside') { $this->widgets[] = array('title' => $title, 'html' => $html, 'location' => $location); diff --git a/include/auth.php b/include/auth.php index c12432449..75a450dc8 100644 --- a/include/auth.php +++ b/include/auth.php @@ -64,14 +64,19 @@ if((isset($_SESSION)) && (x($_SESSION,'authenticated')) && ((! (x($_POST,'auth-p goaway(z_root()); } -// if(x($_SESSION,'visitor_id') && (! x($_SESSION,'uid'))) { -// $r = q("SELECT * FROM `contact` WHERE `id` = %d LIMIT 1", -// intval($_SESSION['visitor_id']) -// ); -// if(count($r)) { -// $a->contact = $r[0]; -// } -// } + if(x($_SESSION,'visitor_id') && (! x($_SESSION,'uid'))) { + $r = q("select * from hubloc left join xchan on xchan_hash = hubloc_hash where hubloc_addr = '%s' limit 1", + dbesc($_SESSION['visitor_id']) + ); + if($r) { + get_app()->set_observer($r[0]); + } + else { + unset($_SESSION['visitor_id']); + unset($_SESSION['authenticated']); + } + $a->set_groups(init_groups_visitor($_SESSION['visitor_id'])); + } if(x($_SESSION,'uid') || x($_SESSION,'account_id')) { diff --git a/include/zot.php b/include/zot.php index fc1241ff2..38bac5e93 100644 --- a/include/zot.php +++ b/include/zot.php @@ -101,18 +101,13 @@ function zot_build_packet($channel,$type = 'notify',$recipients = null, $remote_ 'version' => ZOT_REVISION ); - // These fields are present when using magic auth - - if(array_key_exists('token',$channel)) { - $data['sender']['token'] = $channel['token']; - $data['sender']['token_sig'] = $channel['token_sig']; - } - if($recipients) $data['recipients'] = $recipients; - if($secret) + if($secret) { $data['secret'] = $secret; + $data['secret_sig'] = base64url_encode(rsa_sign($secret,$channel['channel_prvkey'])); + } logger('zot_build_packet: ' . print_r($data,true)); diff --git a/mod/magic.php b/mod/magic.php index 2ea686b1b..c5aeb4c8e 100644 --- a/mod/magic.php +++ b/mod/magic.php @@ -4,58 +4,74 @@ function magic_init(&$a) { - $url = ((x($_REQUEST,'url')) ? $_REQUEST['url'] : ''); $addr = ((x($_REQUEST,'addr')) ? $_REQUEST['addr'] : ''); $hash = ((x($_REQUEST,'hash')) ? $_REQUEST['hash'] : ''); $dest = ((x($_REQUEST,'dest')) ? $_REQUEST['dest'] : ''); + if($hash) { + $x = q("select xchan.xchan_url, hubloc.* from xchan left join hubloc on xchan_hash = hubloc_hash + where hublock_hash = '%s' and (hubloc_flags & %d) limit 1", + 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) limit 1", + dbesc($addr), + intval(HUBLOC_FLAGS_PRIMARY) + ); + } - if(local_user()) { - - if($hash) { - $x = q("select xchan.xchan_url, hubloc.* from xchan left join hubloc on xchan_hash = hubloc_hash - where hublock_hash = '%s' and (hubloc_flags & %d) limit 1", - 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) limit 1", - dbesc($addr), - intval(HUBLOC_FLAGS_PRIMARY) - ); + if(! $x) { + + // Finger them if they've never been seen here before + + if($addr) { + $ret = zot_finger($addr,null); + if($ret['success']) { + $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) limit 1", + dbesc($addr), + intval(HUBLOC_FLAGS_PRIMARY) + ); + } } + } - if(! $x) { - notice( t('Channel not found.') . EOL); - return; - } + if(! $x) { + notice( t('Channel not found.') . EOL); + return; + } - 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; - } - // We are already authenticated on this site and a registered observer. - // Just redirect. - goaway($desturl); + 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; } + // We are already authenticated on this site and a registered observer. + // Just redirect. + goaway($desturl); + } - $channel = $a->get_channel(); + if(local_user()) { + $channel = $a->get_channel(); $token = random_string(); - $token_sig = rsa_sign($token,$channel['channel_prvkey']); + $token_sig = base64url_encode(rsa_sign($token,$channel['channel_prvkey'])); $channel['token'] = $token; $channel['token_sig'] = $token_sig; @@ -73,25 +89,12 @@ function magic_init(&$a) { dbesc(datetime_convert()) ); - $packet = zot_build_packet($channel,'auth',$recip,$x[0]['hubloc_sitekey'],$hash); - $result = zot_zot($x[0]['hubloc_callback'],$packet); - if($result['success']) { - $j = json_decode($result['body'],true); - if($j['iv']) { - $y = aes_unencapsulate($j,$channel['prvkey']); - $j = json_decode($y,true); - } - if($j['token'] && $j['ticket'] && $j['token'] === $token) { - $r = q("delete from verify where token = '%s' and type = '%s' and channel = %d limit 1", - dbesc($token), - dbesc('auth'), - intval($channel['channel_id']) - ); - goaway($x[0]['callback'] . '?f=&ticket=' . $ticket . '&dest=' . $dest); - } - } - goaway($dest); + goaway($x[0]['hubloc_callback'] . '/' . substr($x[0]['hubloc_addr'],0,strpos($x[0]['hubloc_addr'],'@')) + . '/?f=&auth=' . $channel['channel_address'] . '@' . $a->get_hostname() + . '&sec=' . $token . '&dest=' . $dest . '&version=' . ZOT_REVISION); } + if(strpos($dest,'/')) + goaway($dest); goaway(z_root()); } diff --git a/mod/post.php b/mod/post.php index ee21f2ffb..bfcc99022 100644 --- a/mod/post.php +++ b/mod/post.php @@ -6,6 +6,110 @@ require_once('include/zot.php'); + + +function post_init(&$a) { + + // All other access to this endpoint is via the post method. + // Here we will pick out the magic auth params which arrive + // as a get request. + + if(argc() > 1) { + + $webbie = argv(1); + + if(array_key_exists('auth',$_REQUEST)) { + + $address = $_REQUEST['auth']; + $dest = $_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; + } + $c = q("select * from channel where channel_address = '%s' limit 1", + dbesc($webbie) + ); + if(! $c) { + logger('mod_zot: auth: unable to find channel ' . $webbie); + // They'll get a notice when they hit the page, we don't need two. + goaway($desturl); + } + + // Try and find a hubloc for the person attempting to auth + $x = q("select * from hubloc left join xchan on xchan_hash = hubloc_hash where hubloc_addr = '%s' limit 1", + dbesc($address) + ); + + if(! $x) { + // finger them if they can't be found. + $ret = zot_finger($addr,null); + if($ret['success']) { + $j = json_decode($ret['body'],true); + if($j) + import_xchan($j); + $x = q("select * from hubloc left join xchan on xchan_hash = hubloc_hash where hubloc_addr = '%s' limit 1", + dbesc($address) + ); + } + } + if(! $x) + goaway($desturl); + + // check credentials and access + + // Auth packets MUST use ultra top-secret hush-hush mode + + $p = zot_build_packet($c[0],$type = 'auth_check',array('guid' => $x[0]['hubloc_guid'],'guid_sig' => $x[0]['hubloc_guid_sig']), $x[0]['hubloc_prvkey'], $sec); + $result = zot_zot($x[0]['hubloc_url'],$p); + + if($result['success']) { + $j = json_decode($result['body'],true); + if($j['result']) { + // everything is good... maybe + if(local_user()) { + notice( t('Remote authentication blocked. You are logged into this site locally. Please logout and retry') . EOL); + goaway($desturl); + } + // log them in + $_SESSION['authenticated'] = 1; + $_SESSION['visitor_id'] = $x[0]['xchan_hash']; + $a->set_observer($x[0]); + $a->set_groups(init_groups_visitor($_SESSION['visitor_id'])); + notice(sprintf( t('Welcome %s. Remote authentication successful.'),$x[0]['xchan_name'])); + } + } + + + + + + + goaway($desturl); + } + + logger('mod_zot: invalid args: ' . print_r($a->argv,true)); + killme(); + } + + return; +} + + + + function post_post(&$a) { @@ -165,12 +269,51 @@ function post_post(&$a) { } - if($msgtype === 'auth') { - logger('mod_post: auth: ' . print_r($data,true)); - + if($msgtype === 'auth_check') { + $arr = $data['sender']; + $sender_hash = base64url_encode(hash('whirlpool',$arr['guid'] . $arr['guid_sig'], true)); + $y = q("select xchan_pubkey from xchan where xchan_hash = '%s' limit 1", + dbesc($sender_hash) + ); + if((! $y) || (! rsa_verify($data['secret'],$data['secret_sig'],$y[0]['xchan_pubkey']))) { + logger('mod_zot: auth_check: sender not found or secret_sig invalid.'); + json_return_and_die($ret); + } + if($data['recipients']) { + + $arr = $data['recipients'][0]; + $recip_hash = base64url_encode(hash('whirlpool',$arr['guid'] . $arr['guid_sig'], true)); + $c = q("select channel_id 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); + } + $z = q("select id from verify where channel = %d and type = 'auth' and token = '%s' limit 1", + intval($c[0]['channel_id']), + dbesc($data['secret']) + ); + 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']) + ); + + $ret['result'] = true; + json_return_and_die($ret); + + } + json_return_and_die($ret); } -} + // catchall + json_return_and_die($ret); + + +} |