From b65e4b278b1d1c1bdf152d36664a254bf4a5bfe1 Mon Sep 17 00:00:00 2001 From: rabuzarus Date: Tue, 19 Jun 2018 16:15:28 +0200 Subject: [PATCH] port hubzillas OpenWebAuth - use Contact::getIdForURL to query for contact entry --- src/Model/Profile.php | 34 +++++++++++----------------------- src/Module/Magic.php | 27 +++++++++++---------------- src/Module/Owa.php | 17 ++++++----------- src/Network/Probe.php | 17 ++++------------- src/Util/HTTPSig.php | 7 ++++--- 5 files changed, 36 insertions(+), 66 deletions(-) diff --git a/src/Model/Profile.php b/src/Model/Profile.php index 0064a75c30..9741f2a74d 100644 --- a/src/Model/Profile.php +++ b/src/Model/Profile.php @@ -19,7 +19,6 @@ use Friendica\Database\DBM; use Friendica\Model\Contact; use Friendica\Model\Verify; use Friendica\Protocol\Diaspora; -use Friendica\Network\Probe; use Friendica\Util\DateTimeFormat; use Friendica\Util\Network; use Friendica\Util\Temporal; @@ -1013,22 +1012,14 @@ class Profile Addon::callHooks('zrl_init', $arr); // Try to find the public contact entry of the visitor. - $fields = ["id", "url"]; - $condition = ['uid' => 0, 'nurl' => normalise_link($my_url)]; - - $contact = dba::selectFirst('contact',$fields, $condition); - - // Not found? Try to probe the visitor. - if (!DBM::is_result($contact)) { - Probe::uri($my_url, '', -1, true, true); - $contact = dba::selectFirst('contact',$fields, $condition); - } - - if (!DBM::is_result($contact)) { + $cid = Contact::getIdForURL($my_url); + if (!$cid) { logger('No contact record found for ' . $my_url, LOGGER_DEBUG); return; } + $contact = dba::selectFirst('contact',['id', 'url'], ['id' => $cid]); + if (DBM::is_result($contact) && remote_user() && remote_user() === $contact['id']) { // The visitor is already authenticated. return; @@ -1039,12 +1030,12 @@ class Profile // Try to avoid recursion - but send them home to do a proper magic auth. $query = str_replace(array('?zrl=', '&zid='), array('?rzrl=', '&rzrl='), $a->query_string); // The other instance needs to know where to redirect. - $dest = urlencode(System::baseUrl() . "/" . $query); + $dest = urlencode(System::baseUrl() . '/' . $query); // We need to extract the basebath from the profile url // to redirect the visitors '/magic' module. // Note: We should have the basepath of a contact also in the contact table. - $urlarr = explode("/profile/", $contact['url']); + $urlarr = explode('/profile/', $contact['url']); $basepath = $urlarr[0]; if ($basepath != System::baseUrl() && !strstr($dest, '/magic') && !strstr($dest, '/rmagic')) { @@ -1077,18 +1068,14 @@ class Profile } // Try to find the public contact entry of the visitor. - $condition = ["uid" => 0, "addr" => $visitor_handle]; - $visitor = dba::selectFirst("contact", [], $condition); - - if (!DBM::is_result($visitor)) { - Probe::uri($visitor_handle, '', -1, true, true); - $visitor = dba::selectFirst("contact", [], $condition); - } - if(!DBM::is_result($visitor)) { + $cid = Contact::getIdForURL($visitor_handle); + if(!$cid) { logger('owt: unable to finger ' . $visitor_handle, LOGGER_DEBUG); return; } + $visitor = dba::selectFirst('contact', [], ['id' => $cid]); + // Authenticate the visitor. $_SESSION['authenticated'] = 1; $_SESSION['visitor_id'] = $visitor['id']; @@ -1108,6 +1095,7 @@ class Profile * * \e array \b session */ Addon::callHooks('magic_auth_success', $arr); + $a->contact = $visitor; info(L10n::t('OpenWebAuth: %1$s welcomes %2$s', $a->get_hostname(), $visitor['name'])); diff --git a/src/Module/Magic.php b/src/Module/Magic.php index 1b364a3319..86e9e44d8b 100644 --- a/src/Module/Magic.php +++ b/src/Module/Magic.php @@ -5,8 +5,7 @@ namespace Friendica\Module; use Friendica\BaseModule; -use Friendica\Database\DBM; -use Friendica\Network\Probe; +use Friendica\Model\Contact; use Friendica\Util\HTTPSig; use Friendica\Util\Network; @@ -35,32 +34,28 @@ class Magic extends BaseModule // NOTE: I guess $dest isn't just the profile url (could be also // other profile pages e.g. photo). We need to find a solution // to be able to redirct to other pages than the contact profile. - $fields = ["id", "nurl", "url"]; - $condition = ["nurl" => normalise_link($dest)]; + $cid = Contact::getIdForURL($dest); - $contact = dba::selectFirst("contact", $fields, $condition); - - if (!DBM::is_result($contact)) { - // If we don't have a contact record, try to probe it. - /// @todo: Also check against the $addr. - Probe::uri($dest, '', -1, true, true); - $contact = dba::selectFirst("contact", $fields, $condition); + if (!$cid && !empty($addr)) { + $cid = Contact::getIdForURL($addr); } - if (!DBM::is_result($contact)) { - logger("No contact record found: " . print_r($_REQUEST, true), LOGGER_DEBUG); + if (!$cid) { + logger('No contact record found: ' . print_r($_REQUEST, true), LOGGER_DEBUG); goaway($dest); } + $contact = dba::selectFirst('contact', ['id', 'nurl', 'url'], ['id' => $cid]); + // Redirect if the contact is already authenticated on this site. - if (array_key_exists("id", $a->contact) && strpos($contact['nurl'], normalise_link(self::getApp()->get_baseurl())) !== false) { + if (array_key_exists('id', $a->contact) && strpos($contact['nurl'], normalise_link(self::getApp()->get_baseurl())) !== false) { if($test) { $ret['success'] = true; $ret['message'] .= 'Local site - you are already authenticated.' . EOL; return $ret; } - logger("Contact is already authenticated", LOGGER_DEBUG); + logger('Contact is already authenticated', LOGGER_DEBUG); goaway($dest); } @@ -73,7 +68,7 @@ class Magic extends BaseModule // NOTE: we need another solution because this does only work // for friendica contacts :-/ . We should have the basepath // of a contact also in the contact table. - $exp = explode("/profile/", $contact['url']); + $exp = explode('/profile/', $contact['url']); $basepath = $exp[0]; $headers = []; diff --git a/src/Module/Owa.php b/src/Module/Owa.php index 337c0554fe..6c580704f7 100644 --- a/src/Module/Owa.php +++ b/src/Module/Owa.php @@ -7,9 +7,8 @@ namespace Friendica\Module; use Friendica\BaseModule; use Friendica\Core\System; use Friendica\Database\DBM; +use Friendica\Model\Contact; use Friendica\Model\Verify; -use Friendica\Network\Probe; -use Friendica\Util\DateTimeFormat; use Friendica\Util\HTTPSig; use dba; @@ -46,17 +45,13 @@ class Owa extends BaseModule if ($keyId) { // Try to find the public contact entry of the handle. - $handle = str_replace("acct:", "", $keyId); - $fields = ["id", "url", "addr", "pubkey"]; - $condition = ["addr" => $handle, "uid" => 0]; + $handle = str_replace('acct:', '', $keyId); - $contact = dba::selectFirst("contact", $fields, $condition); + $cid = Contact::getIdForURL($handle); + $fields = ['id', 'url', 'addr', 'pubkey']; + $condition = ['id' => $cid]; - // Not found? Try to probe with the handle. - if(!DBM::is_result($contact)) { - Probe::uri($handle, '', -1, true, true); - $contact = dba::selectFirst("contact", $fields, $condition); - } + $contact = dba::selectFirst('contact', $fields, $condition); if (DBM::is_result($contact)) { // Try to verify the signed header with the public key of the contact record diff --git a/src/Network/Probe.php b/src/Network/Probe.php index 7f41b2304b..5f665814b4 100644 --- a/src/Network/Probe.php +++ b/src/Network/Probe.php @@ -311,11 +311,10 @@ class Probe * @param string $network Test for this specific network * @param integer $uid User ID for the probe (only used for mails) * @param boolean $cache Use cached values? - * @param boolean $insert Insert the contact into the contact table. * * @return array uri data */ - public static function uri($uri, $network = "", $uid = -1, $cache = true, $insert = false) + public static function uri($uri, $network = "", $uid = -1, $cache = true) { if ($cache) { $result = Cache::get("Probe::uri:".$network.":".$uri); @@ -464,19 +463,11 @@ class Probe $condition = ['nurl' => normalise_link($data["url"]), 'self' => false, 'uid' => 0]; // "$old_fields" will return a "false" when the contact doesn't exist. - // This won't trigger an insert except $insert is set to true. - // This is intended, since we only need public contacts - // for everyone we store items from. We don't need to store - // every contact on the planet. + // This won't trigger an insert. This is intended, since we only need + // public contacts for everyone we store items from. + // We don't need to store every contact on the planet. $old_fields = dba::selectFirst('contact', $fieldnames, $condition); - // When the contact doesn't exist, the value "true" will trigger an insert - if (!$old_fields && $insert) { - $old_fields = true; - $fields['blocked'] = false; - $fields['pending'] = false; - } - $fields['name-date'] = DateTimeFormat::utcNow(); $fields['uri-date'] = DateTimeFormat::utcNow(); $fields['success_update'] = DateTimeFormat::utcNow(); diff --git a/src/Util/HTTPSig.php b/src/Util/HTTPSig.php index 96ea2afb5c..b78cca8964 100644 --- a/src/Util/HTTPSig.php +++ b/src/Util/HTTPSig.php @@ -26,9 +26,10 @@ class HTTPSig * * @see https://tools.ietf.org/html/rfc5843 * - * @param string $body The value to create the digest for - * @param boolean $set (optional, default true) + * @param string $body The value to create the digest for + * @param boolean $set (optional, default true) * If set send a Digest HTTP header + * * @return string The generated digest of $body */ public static function generateDigest($body, $set = true) @@ -119,7 +120,7 @@ class HTTPSig $algorithm = 'sha512'; } - if ($key && function_exists($key)) { /// @todo What function do we check for - maybe we check now for a method !!! + if ($key && function_exists($key)) { $result['signer'] = $sig_block['keyId']; $key = $key($sig_block['keyId']); }