From 3a7d3e3a542ef9297a8a20e3548f01f43fb37f0e Mon Sep 17 00:00:00 2001 From: redmatrix Date: Mon, 1 Aug 2016 20:12:52 -0700 Subject: This checkin should make all permission modes work correctly with atokens (they should be able to post content if allowed to). It also removes the strict linkage between permissions and connections so any individual permission can be set for any xchan; even those for which you have no connections. --- include/auth.php | 1 + include/connections.php | 6 ++++ include/permissions.php | 56 +++++++++++++++++++++++++++---------- include/security.php | 74 ++++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 121 insertions(+), 16 deletions(-) (limited to 'include') diff --git a/include/auth.php b/include/auth.php index f3592cee3..fdcecec36 100644 --- a/include/auth.php +++ b/include/auth.php @@ -57,6 +57,7 @@ function account_verify_password($login, $pass) { ); if($x) { $ret['xchan'] = atoken_xchan($x[0]); + atoken_create_xchan($ret['xchan']); return $ret; } } diff --git a/include/connections.php b/include/connections.php index 9f55820cc..4f685388c 100644 --- a/include/connections.php +++ b/include/connections.php @@ -566,6 +566,7 @@ function contact_remove($channel_id, $abook_id) { drop_item($rr['id'],false); } } + q("delete from abook where abook_id = %d and abook_channel = %d", intval($abook['abook_id']), @@ -588,6 +589,11 @@ function contact_remove($channel_id, $abook_id) { intval($channel_id) ); + $r = q("delete from abconfig where chan = %d and xchan = '%s'", + intval($channel_id), + dbesc($abook['abook_xchan']) + ); + return true; } diff --git a/include/permissions.php b/include/permissions.php index a1e05d120..637193973 100644 --- a/include/permissions.php +++ b/include/permissions.php @@ -122,13 +122,21 @@ function get_all_perms($uid, $observer_xchan, $internal_use = true) { dbesc($observer_xchan) ); if(! $x) { - // not in address book, see if they've got an xchan - $y = q("select xchan_network from xchan where xchan_hash = '%s' limit 1", - dbesc($observer_xchan) - ); - // no xchan either, see if they've got a guest access token - if(! $y) - $x = atoken_abook($uid,$observer_xchan); + // see if they've got a guest access token; these are treated as connections + $y = atoken_abook($uid,$observer_xchan); + if($y) + $x = array($y); + + if(! $x) { + // not in address book and no guest token, see if they've got an xchan + // these *may* have individual (PERMS_SPECIFIC) permissions, but are not connections + $y = q("select xchan_network from xchan where xchan_hash = '%s' limit 1", + dbesc($observer_xchan) + ); + if($y) { + $x = array(pseudo_abook($y[0])); + } + } } $abook_checked = true; @@ -190,7 +198,7 @@ function get_all_perms($uid, $observer_xchan, $internal_use = true) { // If we're still here, we have an observer, check the network. if($channel_perm & PERMS_NETWORK) { - if(($x && $x[0]['xchan_network'] === 'zot') || ($y && $y[0]['xchan_network'] === 'zot')) { + if($x && $x[0]['xchan_network'] === 'zot') { $ret[$perm_name] = true; continue; } @@ -238,6 +246,12 @@ function get_all_perms($uid, $observer_xchan, $internal_use = true) { // They're a contact, so they have permission if($channel_perm & PERMS_CONTACTS) { + // it was a fake abook entry, not really a connection + if(array_key_exists('abook_pseudo',$x[0]) && intval($x[0]['abook_pseudo'])) { + $ret[$perm_name] = false; + continue; + } + $ret[$perm_name] = true; continue; } @@ -334,13 +348,21 @@ function perm_is_allowed($uid, $observer_xchan, $permission) { return false; if(! $x) { - // not in address book, see if they've got an xchan - $y = q("select xchan_network from xchan where xchan_hash = '%s' limit 1", - dbesc($observer_xchan) - ); - // no xchan either, see if they've got a guest access token - if(! $y) - $x = atoken_abook($uid,$observer_xchan); + // see if they've got a guest access token + $y = atoken_abook($uid,$observer_xchan); + if($y) + $x = array($y); + + if(! $x) { + // not in address book and no guest token, see if they've got an xchan + $y = q("select xchan_network from xchan where xchan_hash = '%s' limit 1", + dbesc($observer_xchan) + ); + if($y) { + $x = array(pseudo_abook($y[0])); + } + } + } $abperms = load_abconfig($uid,$observer_xchan,'my_perms'); } @@ -410,6 +432,10 @@ function perm_is_allowed($uid, $observer_xchan, $permission) { // They're a contact, so they have permission if($channel_perm & PERMS_CONTACTS) { + // it was a fake abook entry, not really a connection + if(array_key_exists('abook_pseudo',$x[0]) && intval($x[0]['abook_pseudo'])) { + return false; + } return true; } diff --git a/include/security.php b/include/security.php index 7d2a49bdf..83bf51bc0 100644 --- a/include/security.php +++ b/include/security.php @@ -108,6 +108,7 @@ function atoken_xchan($atoken) { 'xchan_name' => $atoken['atoken_name'], 'xchan_addr' => t('guest:') . $atoken['atoken_name'] . '@' . \App::get_hostname(), 'xchan_network' => 'unknown', + 'xchan_url' => z_root(), 'xchan_hidden' => 1, 'xchan_photo_mimetype' => 'image/jpeg', 'xchan_photo_l' => get_default_profile_photo(300), @@ -119,6 +120,62 @@ function atoken_xchan($atoken) { return null; } +function atoken_delete($atoken_id) { + + $r = q("select * from atoken where atoken_id = %d", + intval($atoken_id) + ); + if(! $r) + return; + + $c = q("select channel_id, channel_hash from channel where channel_id = %d", + intval($r[0]['atoken_uid']) + ); + if(! $c) + return; + + $atoken_xchan = substr($c[0]['channel_hash'],0,16) . '.' . $r[0]['atoken_name']; + + q("delete from atoken where atoken_id = %d", + intval($atoken_id) + ); + q("delete from abconfig where chan = %d and xchan = '%s'", + intval($c[0]['channel_id']), + dbesc($atoken_xchan) + ); +} + + + +// in order for atoken logins to create content (such as posts) they need a stored xchan. +// we'll create one on the first atoken_login; it can't really ever go away but perhaps +// @fixme we should set xchan_deleted if it's expired or removed + +function atoken_create_xchan($xchan) { + + $r = q("select xchan_hash from xchan where xchan_hash = '%s'", + dbesc($xchan['xchan_hash']) + ); + if($r) + return; + + $r = q("insert into xchan ( xchan_hash, xchan_guid, xchan_addr, xchan_url, xchan_name, xchan_network, xchan_photo_mimetype, xchan_photo_l, xchan_photo_m, xchan_photo_s ) + values ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s') ", + dbesc($xchan['xchan_hash']), + dbesc($xchan['xchan_hash']), + dbesc($xchan['xchan_addr']), + dbesc($xchan['xchan_url']), + dbesc($xchan['xchan_name']), + dbesc($xchan['xchan_network']), + dbesc($xchan['xchan_photo_mimetype']), + dbesc($xchan['xchan_photo_l']), + dbesc($xchan['xchan_photo_m']), + dbesc($xchan['xchan_photo_s']) + ); + + return true; +} + function atoken_abook($uid,$xchan_hash) { if(substr($xchan_hash,16,1) != '.') @@ -149,6 +206,21 @@ function atoken_abook($uid,$xchan_hash) { } +function pseudo_abook($xchan) { + if(! $xchan) + return false; + + // set abook_pseudo to flag that we aren't really connected. + + $xchan['abook_pseudo'] = 1; + $xchan['abook_blocked'] = 0; + $xchan['abook_ignored'] = 0; + $xchan['abook_pending'] = 0; + return $xchan; + +} + + /** * @brief Change to another channel with current logged-in account. * @@ -424,7 +496,7 @@ function public_permissions_sql($observer_hash) { * In this implementation, a security token is reusable (if the user submits a form, goes back and resubmits the form, maybe with small changes; * or if the security token is used for ajax-calls that happen several times), but only valid for a certain amout of time (3hours). * The "typename" seperates the security tokens of different types of forms. This could be relevant in the following case: - * A security token is used to protekt a link from CSRF (e.g. the "delete this profile"-link). + * A security token is used to protekt a link from CSRF (e.g. the "delete this profile"-link). * If the new page contains by any chance external elements, then the used security token is exposed by the referrer. * Actually, important actions should not be triggered by Links / GET-Requests at all, but somethimes they still are, * so this mechanism brings in some damage control (the attacker would be able to forge a request to a form of this type, but not to forms of other types). -- cgit v1.2.3