From 411f3b86a45eeaef0df493393cf9b4149d3335fc Mon Sep 17 00:00:00 2001 From: Mikael Nordfeldth Date: Sat, 31 May 2014 12:51:51 +0200 Subject: [PATCH] Use locally cached Salmon keys for profiles Please note that we're not yet actually caching them ourselves. --- plugins/OStatus/lib/magicenvelope.php | 35 ++++++++++++++++++++++++--- plugins/OStatus/lib/salmonaction.php | 19 ++++++++++++--- 2 files changed, 46 insertions(+), 8 deletions(-) diff --git a/plugins/OStatus/lib/magicenvelope.php b/plugins/OStatus/lib/magicenvelope.php index 9990053904..1a4abb5e1b 100644 --- a/plugins/OStatus/lib/magicenvelope.php +++ b/plugins/OStatus/lib/magicenvelope.php @@ -59,12 +59,33 @@ class MagicEnvelope } } + /** + * Retrieve Salmon keypair first by checking local database, but + * if it's not found, attempt discovery if it has been requested. + * + * @param Profile $profile The profile we're looking up keys for. + * @param boolean $discovery Network discovery if no local cache? + */ + public function getKeyPair(Profile $profile, $discovery=false) { + $magicsig = Magicsig::getKV('user_id', $profile->id); + if ($discovery && !$magicsig instanceof Magicsig) { + $signer_uri = $profile->getUri(); + if (empty($signer_uri)) { + throw new ServerException(sprintf('Profile missing URI (id==%d)', $profile->id)); + } + $magicsig = $this->discoverKeyPair($signer_uri); + } elseif (!$magicsig instanceof Magicsig) { // No discovery request, so we'll give up. + throw new ServerException(sprintf('No public key found for profile (id==%d)', $profile->id)); + } + return $magicsig; + } + /** * Get the Salmon keypair from a URI, uses XRD Discovery etc. * * @return Magicsig with loaded keypair */ - public function getKeyPair($signer_uri) + public function discoverKeyPair($signer_uri) { $disco = new Discovery(); @@ -228,9 +249,11 @@ class MagicEnvelope * * Details of failure conditions are dumped to output log and not exposed to caller. * + * @param Profile $profile optional profile used to get locally cached public signature key. + * * @return boolean */ - public function verify() + public function verify(Profile $profile=null) { if ($this->alg != 'RSA-SHA256') { common_log(LOG_DEBUG, "Salmon error: bad algorithm"); @@ -243,8 +266,12 @@ class MagicEnvelope } try { - $signer_uri = $this->getAuthorUri(); - $magicsig = $this->getKeyPair($signer_uri); + if ($profile instanceof Profile) { + $magicsig = $this->getKeyPair($profile, true); // Do discovery too if necessary + } else { + $signer_uri = $this->getAuthorUri(); + $magicsig = $this->discoverKeyPair($signer_uri); + } } catch (Exception $e) { common_log(LOG_DEBUG, "Salmon error: ".$e->getMessage()); return false; diff --git a/plugins/OStatus/lib/salmonaction.php b/plugins/OStatus/lib/salmonaction.php index 4366822ffd..6e44ff2eb6 100644 --- a/plugins/OStatus/lib/salmonaction.php +++ b/plugins/OStatus/lib/salmonaction.php @@ -28,6 +28,8 @@ class SalmonAction extends Action { protected $needPost = true; + protected $verified = false; + var $xml = null; var $activity = null; var $target = null; @@ -45,15 +47,24 @@ class SalmonAction extends Action $envxml = file_get_contents('php://input'); $magic_env = new MagicEnvelope($envxml); // parse incoming XML as a MagicEnvelope - if (!$magic_env->verify()) { + + $entry = $magic_env->getPayload(); // Not cryptographically verified yet! + $this->activity = new Activity($entry->documentElement); + + try { + $profile = Profile::fromUri($this->activity->actor->id); + $this->verified = $magic_env->verify($profile); + } catch (UnknownUriException $e) { + // If we don't know the profile, perform some discovery instead + $this->verified = $magic_env->verify(); + } + + if (!$this->verified) { common_log(LOG_DEBUG, "Salmon signature verification failed."); // TRANS: Client error. $this->clientError(_m('Salmon signature verification failed.')); } - $entry = $magic_env->getPayload(); - - $this->activity = new Activity($entry->documentElement); return true; }