diff options
author | friendica <info@friendica.com> | 2013-01-21 19:16:21 -0800 |
---|---|---|
committer | friendica <info@friendica.com> | 2013-01-21 19:16:21 -0800 |
commit | 5949607d17bceb51d61c73b5c0dbc0fcc063bd04 (patch) | |
tree | c3c59d435e146bd46a27d4503fc9b33878664b3f | |
parent | 6421c09cff6bebd9c7f191d36239a8c4efe74bdf (diff) | |
download | volse-hubzilla-5949607d17bceb51d61c73b5c0dbc0fcc063bd04.tar.gz volse-hubzilla-5949607d17bceb51d61c73b5c0dbc0fcc063bd04.tar.bz2 volse-hubzilla-5949607d17bceb51d61c73b5c0dbc0fcc063bd04.zip |
magic auth - it's mostly done or at least all the code bits are written and it looks in theory to be pretty secure and it doesn't white screen. Getting it to actually work(?), well we won't know how hard that will be until we get it on a couple of systems and try it. Magic auth on one box is a no-op because you're already authenticated.
-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); + + +} |