From 5004b55d3e6ca19d9a3bdd96aa6b845b2d454162 Mon Sep 17 00:00:00 2001 From: Roland Haeder Date: Fri, 27 Mar 2015 21:55:45 +0100 Subject: [PATCH] Check scope, else a privacy leaks happens this way: 1) Bob and Alice follow each other and write private notices (this->scope=2) to each other. 2) Bob uses tags in his private notice to alice (which she can read from him). 3) Alice adds that notice (with tags) to her favorites ("faving") it. 4) The tags from Bob's private notice becomes visible in Alice's profile. This has the simple background that the scope is not being re-checked. This has to be done here at this point because given above scenario is a privacy leak as the tags may be *really* private (nobody else shall see them) such as initmate words or very political words. Signed-off-by: Roland Haeder --- classes/Notice.php | 67 ++++++++++++++++++++----------- lib/activity.php | 1 + plugins/Favorite/classes/Fave.php | 2 +- 3 files changed, 46 insertions(+), 24 deletions(-) diff --git a/classes/Notice.php b/classes/Notice.php index d3d4ef37a3..764b4edd8b 100644 --- a/classes/Notice.php +++ b/classes/Notice.php @@ -565,8 +565,7 @@ class Notice extends Managed_DataObject throw new ClientException(_('You cannot repeat your own notice.')); } - if ($repeat->scope != Notice::SITE_SCOPE && - $repeat->scope != Notice::PUBLIC_SCOPE) { + if ($repeat->isPrivateScope()) { // TRANS: Client error displayed when trying to repeat a non-public notice. throw new ClientException(_('Cannot repeat a private notice.'), 403); } @@ -2689,6 +2688,38 @@ class Notice extends Managed_DataObject */ public function getTags() { + // Check default scope (non-private notices) + $inScope = (!$this->isPrivateScope()); + + // Get current user + $user = common_current_user(); + + // Is the general scope check okay and the user in logged in? + if (($inScope === TRUE) && ($user instanceof User)) { + // Get profile from it + $profile = $user->getProfile(); + + /* + * Check scope, else a privacy leaks happens this way: + * + * 1) Bob and Alice follow each other and write private notices + * (this->scope=2) to each other. + * 2) Bob uses tags in his private notice to alice (which she can + * read from him). + * 3) Alice adds that notice (with tags) to her favorites + * ("faving") it. + * 4) The tags from Bob's private notice becomes visible in Alice's + * profile. + * + * This has the simple background that the scope is not being + * re-checked. This has to be done here at this point because given + * above scenario is a privacy leak as the tags may be *really* + * private (nobody else shall see them) such as initmate words or + * very political words. + */ + $inScope = $this->inScope($profile); + } + $tags = array(); $keypart = sprintf('notice:tags:%d', $this->id); @@ -2700,7 +2731,9 @@ class Notice extends Managed_DataObject } else { $tag = new Notice_tag(); $tag->notice_id = $this->id; - if ($tag->find()) { + + // Check scope for privacy-leak protection (see some lines above why) + if (($inScope === TRUE) && ($tag->find())) { while ($tag->fetch()) { $tags[] = $tag->tag; } @@ -3248,26 +3281,14 @@ class Notice extends Managed_DataObject } } - public function delPref($namespace, $topic) { - return Notice_prefs::setData($this, $namespace, $topic, null); - } - - public function getPref($namespace, $topic, $default=null) { - // If you want an exception to be thrown, call Notice_prefs::getData directly - try { - return Notice_prefs::getData($this, $namespace, $topic, $default); - } catch (NoResultException $e) { - return null; - } - } - - // The same as getPref but will fall back to common_config value for the same namespace/topic - public function getConfigPref($namespace, $topic) + /** + * Checks whether this notice is in "private scope" (non-public notice) + * + * @return $isPrivate Whether this notice is private + */ + public function isPrivateScope () { - return Notice_prefs::getConfigData($this, $namespace, $topic); - } - - public function setPref($namespace, $topic, $data) { - return Notice_prefs::setData($this, $namespace, $topic, $data); + return ($this->scope != Notice::SITE_SCOPE && + $this->scope != Notice::PUBLIC_SCOPE); } } diff --git a/lib/activity.php b/lib/activity.php index daf9f4b22e..e6a0f66b6e 100644 --- a/lib/activity.php +++ b/lib/activity.php @@ -107,6 +107,7 @@ class Activity public $selfLink; // public $editLink; // public $generator; // ActivityObject representing the generating application + /** * Turns a regular old Atom into a magical activity * diff --git a/plugins/Favorite/classes/Fave.php b/plugins/Favorite/classes/Fave.php index fb5575c0d4..c16aad1e1a 100644 --- a/plugins/Favorite/classes/Fave.php +++ b/plugins/Favorite/classes/Fave.php @@ -280,7 +280,7 @@ class Fave extends Managed_DataObject * * @return array Array of Fave objects */ - static public function byNotice($notice) + static public function byNotice(Notice $notice) { if (!isset(self::$_faves[$notice->id])) { self::fillFaves(array($notice->id)); -- 2.39.5