aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Zotlabs/Daemon/Cron.php10
-rw-r--r--Zotlabs/Module/Settings.php12
-rw-r--r--include/auth.php1
-rw-r--r--include/connections.php6
-rw-r--r--include/permissions.php56
-rw-r--r--include/security.php74
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).