diff options
-rw-r--r-- | Zotlabs/Daemon/Cron.php | 10 | ||||
-rw-r--r-- | Zotlabs/Module/Settings.php | 12 | ||||
-rw-r--r-- | include/auth.php | 1 | ||||
-rw-r--r-- | include/connections.php | 6 | ||||
-rw-r--r-- | include/permissions.php | 56 | ||||
-rw-r--r-- | include/security.php | 74 |
6 files changed, 136 insertions, 23 deletions
diff --git a/Zotlabs/Daemon/Cron.php b/Zotlabs/Daemon/Cron.php index c6e82b13a..c66b62f55 100644 --- a/Zotlabs/Daemon/Cron.php +++ b/Zotlabs/Daemon/Cron.php @@ -64,12 +64,16 @@ class Cron { // delete expired access tokens - q("delete from atoken where atoken_expires != '%s' && atoken_expires < %s", + $r = q("select atoken_id from atoken where atoken_expires != '%s' && atoken_expires < %s", dbesc(NULL_DATE), db_utcnow() ); - - + if($r) { + require_once('include/security.php'); + foreach($r as $rr) { + atoken_delete($rr['atoken_id']); + } + } // Ensure that every channel pings a directory server once a month. This way we can discover // channels and sites that quietly vanished and prevent the directory from accumulating stale diff --git a/Zotlabs/Module/Settings.php b/Zotlabs/Module/Settings.php index 48ab6b8bf..ecf6d03d6 100644 --- a/Zotlabs/Module/Settings.php +++ b/Zotlabs/Module/Settings.php @@ -2,7 +2,7 @@ namespace Zotlabs\Module; /** @file */ require_once('include/zot.php'); - +require_once('include/security.php'); class Settings extends \Zotlabs\Web\Controller { @@ -781,6 +781,8 @@ class Settings extends \Zotlabs\Web\Controller { if((argc() > 1) && (argv(1) === 'tokens')) { $atoken = null; + $atoken_xchan = ''; + if(argc() > 2) { $id = argv(2); @@ -793,12 +795,14 @@ class Settings extends \Zotlabs\Web\Controller { $atoken = $atoken[0]; $atoken_xchan = substr($channel['channel_hash'],0,16) . '.' . $atoken['atoken_name']; } + if($atoken && argc() > 3 && argv(3) === 'drop') { - $r = q("delete from atoken where atoken_id = %d", - intval($id) - ); + atoken_delete($id); + $atoken = null; + $atoken_xchan = ''; } } + $t = q("select * from atoken where atoken_uid = %d", intval(local_channel()) ); 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). |