From 5254147ccc18417f0b16ec4d8b8325d7790b4fde Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 23 Sep 2019 22:13:20 +0000 Subject: [PATCH] Fix "redir" loop --- boot.php | 15 ++++++++-- mod/photos.php | 13 ++------- mod/redir.php | 65 ++++++++++++++++++++++++++++++++++++++++-- src/Content/Widget.php | 11 ++----- src/Core/Session.php | 12 ++++++++ src/Model/Profile.php | 2 +- src/Util/Security.php | 14 ++------- 7 files changed, 93 insertions(+), 39 deletions(-) diff --git a/boot.php b/boot.php index 028ba1e829..4c9a1a5e8c 100644 --- a/boot.php +++ b/boot.php @@ -413,7 +413,7 @@ function public_contact() * * @return int|bool visitor_id or false */ -function remote_user() +function remote_user($uid = 0) { // You cannot be both local and remote. // Unncommented by rabuzarus because remote authentication to local @@ -422,13 +422,22 @@ function remote_user() // return false; // } - if (empty($_SESSION)) { + if (empty($_SESSION['authenticated'])) { return false; } - if (!empty($_SESSION['authenticated']) && !empty($_SESSION['visitor_id'])) { + if (!empty($uid) && !empty($_SESSION['remote'])) { + foreach ($_SESSION['remote'] as $visitor) { + if ($visitor['uid'] == $uid) { + return $visitor['cid']; + } + } + } + + if (!empty($_SESSION['visitor_id'])) { return intval($_SESSION['visitor_id']); } + return false; } diff --git a/mod/photos.php b/mod/photos.php index fb43619b6e..50f40b248c 100644 --- a/mod/photos.php +++ b/mod/photos.php @@ -154,17 +154,8 @@ function photos_post(App $a) if (local_user() && (local_user() == $page_owner_uid)) { $can_post = true; - } elseif ($community_page && remote_user()) { - $contact_id = 0; - - if (!empty($_SESSION['remote']) && is_array($_SESSION['remote'])) { - foreach ($_SESSION['remote'] as $v) { - if ($v['uid'] == $page_owner_uid) { - $contact_id = $v['cid']; - break; - } - } - } + } elseif ($community_page && remote_user($page_owner_uid)) { + $contact_id = remote_user($page_owner_uid); if ($contact_id > 0) { if (DBA::exists('contact', ['id' => $contact_id, 'uid' => $page_owner_uid, 'blocked' => false, 'pending' => false])) { diff --git a/mod/redir.php b/mod/redir.php index c99e1823c7..7c93c9f39a 100644 --- a/mod/redir.php +++ b/mod/redir.php @@ -15,16 +15,16 @@ function redir_init(App $a) { $url = defaults($_GET, 'url', ''); $quiet = !empty($_GET['quiet']) ? '&quiet=1' : ''; - $con_url = defaults($_GET, 'conurl', ''); if ($a->argc > 1 && intval($a->argv[1])) { $cid = intval($a->argv[1]); - } elseif (local_user() && !empty($con_url)) { - $cid = Contact::getIdForURL($con_url, local_user()); } else { $cid = 0; } + // Try magic auth before the legacy stuff + redir_magic($a, $cid, $url); + if (!empty($cid)) { $fields = ['id', 'uid', 'nurl', 'url', 'addr', 'name', 'network', 'poll', 'issued-id', 'dfrn-id', 'duplex', 'pending']; $contact = DBA::selectFirst('contact', $fields, ['id' => $cid, 'uid' => [0, local_user()]]); @@ -140,3 +140,62 @@ function redir_init(App $a) { notice(L10n::t('Contact not found.')); $a->internalRedirect(); } + +function redir_magic($a, $cid, $url) +{ + $visitor = Profile::getMyURL(); + if (!empty($visitor)) { + Logger::info('Got my url', ['visitor' => $visitor]); + } + + if (empty(visitor) && remote_user()) { + $contact = DBA::selectFirst('contact', ['url'], ['id' => remote_user()]); + if (!empty($contact['url'])) { + $visitor = $contact['url']; + Logger::info('Got remote user', ['visitor' => $visitor]); + } + } + + if (empty(visitor) && local_user()) { + $contact = DBA::selectFirst('contact', ['url'], ['id' => local_user()]); + if (!empty($contact['url'])) { + $visitor = $contact['url']; + Logger::info('Got local user', ['visitor' => $visitor]); + } + } + + $contact = DBA::selectFirst('contact', ['url'], ['id' => $cid]); + if (!DBA::isResult($contact)) { + Logger::info('Contact not found', ['id' => $cid]); + // Shouldn't happen under normal conditions + notice(L10n::t('Contact not found.')); + if (!empty($url)) { + $a->redirect($url); + } else { + $a->internalRedirect(); + } + } else { + $contact_url = $contact['url']; + $target_url = defaults($url, $contact_url); + } + + $basepath = Contact::getBasepath($contact_url); + + // We don't use magic auth when there is no visitor, we are on the same system or we visit our own stuff + if (empty($visitor) || Strings::compareLink($basepath, System::baseUrl()) || Strings::compareLink($contact_url, $visitor)) { + Logger::info('Redirecting without magic', ['target' => $target_url, 'visitor' => $visitor, 'contact' => $contact_url]); + $a->redirect($target_url); + } + + // Test for magic auth on the target system + $serverret = Network::curl($basepath . '/magic'); + if ($serverret->isSuccess()) { + $separator = strpos($target_url, '?') ? '&' : '?'; + $target_url .= $separator . 'zrl=' . urlencode($visitor); + + Logger::info('Redirecting with magic', ['target' => $target_url, 'visitor' => $visitor, 'contact' => $contact_url]); + $a->redirect($target_url); + } else { + Logger::info('No magic for contact', ['contact' => $contact_url]); + } +} diff --git a/src/Content/Widget.php b/src/Content/Widget.php index a1482ae943..9097442796 100644 --- a/src/Content/Widget.php +++ b/src/Content/Widget.php @@ -337,16 +337,9 @@ class Widget return; } - $cid = $zcid = 0; + $zcid = 0; - if (!empty($_SESSION['remote'])) { - foreach ($_SESSION['remote'] as $visitor) { - if ($visitor['uid'] == $profile_uid) { - $cid = $visitor['cid']; - break; - } - } - } + $cid = remote_user($profile_uid); if (!$cid) { if (Profile::getMyURL()) { diff --git a/src/Core/Session.php b/src/Core/Session.php index 22909a6e6e..8186c4745d 100644 --- a/src/Core/Session.php +++ b/src/Core/Session.php @@ -9,8 +9,10 @@ use Friendica\App; use Friendica\Core\Session\CacheSessionHandler; use Friendica\Core\Session\DatabaseSessionHandler; use Friendica\Database\DBA; +use Friendica\Model\Contact; use Friendica\Model\User; use Friendica\Util\DateTimeFormat; +use Friendica\Util\Strings; /** * High-level Session service class @@ -120,6 +122,16 @@ class Session 'addr' => defaults($_SERVER, 'REMOTE_ADDR', '0.0.0.0'), ]); + $remote_contacts = DBA::select('contact', ['id', 'uid'], ['nurl' => Strings::normaliseLink($_SESSION['my_url']), 'rel' => [Contact::FOLLOWER, Contact::FRIEND]]); + while ($contact = DBA::fetch($remote_contacts)) { + if (($contact['uid'] == 0) || Contact::isBlockedByUser($contact['id'], $contact['uid'])) { + continue; + } + + $_SESSION['remote'][] = ['cid' => $contact['id'], 'uid' => $contact['uid'], 'url' => $_SESSION['my_url']]; + } + DBA::close($remote_contacts); + $member_since = strtotime($user_record['register_date']); self::set('new_member', time() < ($member_since + ( 60 * 60 * 24 * 14))); diff --git a/src/Model/Profile.php b/src/Model/Profile.php index 9ea22a65ee..37f7028a51 100644 --- a/src/Model/Profile.php +++ b/src/Model/Profile.php @@ -248,7 +248,7 @@ class Profile */ public static function getByNickname($nickname, $uid = 0, $profile_id = 0) { - if (remote_user() && !empty($_SESSION['remote'])) { + if (remote_user($uid) && !empty($_SESSION['remote'])) { foreach ($_SESSION['remote'] as $visitor) { if ($visitor['uid'] == $uid) { $contact = DBA::selectFirst('contact', ['profile-id'], ['id' => $visitor['cid']]); diff --git a/src/Util/Security.php b/src/Util/Security.php index 1c934d6fe6..0c09b745d8 100644 --- a/src/Util/Security.php +++ b/src/Util/Security.php @@ -33,7 +33,7 @@ class Security extends BaseObject return true; } - if (remote_user()) { + if (remote_user($owner)) { // use remembered decision and avoid a DB lookup for each and every display item // DO NOT use this function if there are going to be multiple owners // We have a contact-id for an authenticated remote user, this block determines if the contact @@ -44,17 +44,7 @@ class Security extends BaseObject } elseif ($verified === 1) { return false; } else { - $cid = 0; - - if (!empty($_SESSION['remote'])) { - foreach ($_SESSION['remote'] as $visitor) { - if ($visitor['uid'] == $owner) { - $cid = $visitor['cid']; - break; - } - } - } - + $cid = remote_user($owner); if (!$cid) { return false; }