From af1b0915f48676e25fe0428b26f8987b59abb818 Mon Sep 17 00:00:00 2001 From: Mikael Nordfeldth Date: Sun, 4 Oct 2015 17:26:35 +0200 Subject: [PATCH] Magic signature discovery and envelope changes --- plugins/Diaspora/DiasporaPlugin.php | 26 +++++++++++++++++++- plugins/OStatus/OStatusPlugin.php | 4 +-- plugins/OStatus/lib/magicenvelope.php | 35 +++++++++++++++++++-------- 3 files changed, 52 insertions(+), 13 deletions(-) diff --git a/plugins/Diaspora/DiasporaPlugin.php b/plugins/Diaspora/DiasporaPlugin.php index 68f23a4382..75dba7384a 100644 --- a/plugins/Diaspora/DiasporaPlugin.php +++ b/plugins/Diaspora/DiasporaPlugin.php @@ -56,6 +56,29 @@ class DiasporaPlugin extends Plugin strtolower($magicsig->toFingerprint())); } + public function onMagicsigPublicKeyFromXRD(XML_XRD $xrd, &$pubkey) + { + // See if we have a Diaspora public key in the XRD response + $link = $xrd->get(self::REL_PUBLIC_KEY, 'RSA'); + if (!is_null($link)) { + // If we do, decode it so we have the PKCS1 format (starts with -----BEGIN PUBLIC KEY-----) + $pkcs1 = base64_decode($link->href); + $magicsig = new Magicsig(Magicsig::DEFAULT_SIGALG); // Diaspora uses RSA-SHA256 (we do too) + try { + // Try to load the public key so we can get it in the standard Magic signature format + $magicsig->loadPublicKeyPKCS1($pkcs1); + // We found it and will now store it in $pubkey in a proper format! + // This is how it would be found in a well implemented XRD according to the standard. + $pubkey = 'data:application/magic-public-key,'.$magicsig->toString(); + common_debug('magic-public-key found in diaspora-public-key: '.$pubkey); + return false; + } catch (ServerException $e) { + common_log(LOG_WARNING, $e->getMessage()); + } + } + return true; + } + public function onPluginVersion(array &$versions) { $versions[] = array('name' => 'Diaspora', @@ -144,6 +167,7 @@ class DiasporaPlugin extends Plugin * Encrypt the “outer aes key bundle” with Bob’s RSA public key. * I shall refer to this as the “encrypted outer aes key bundle”. */ + common_debug('Diaspora creating "outer aes key bundle", will require magic-public-key'); $key_fetcher = new MagicEnvelope(); $remote_keys = $key_fetcher->getKeyPair($target, true); // actually just gets the public key $enc_outer = $remote_keys->publicKey->encrypt($outer_bundle); @@ -216,7 +240,7 @@ class DiasporaPlugin extends Plugin // 202 Accepted is what we get from Diaspora for example if (!in_array($response->getStatus(), array(200, 202))) { common_log(LOG_ERR, sprintf('Salmon (from profile %d) endpoint %s returned status %s: %s', - $user->id, $endpoint_uri, $response->getStatus(), $response->getBody())); + $magic_env->getActor()->getID(), $endpoint_uri, $response->getStatus(), $response->getBody())); return true; } diff --git a/plugins/OStatus/OStatusPlugin.php b/plugins/OStatus/OStatusPlugin.php index d1eea869a7..86befd58cd 100644 --- a/plugins/OStatus/OStatusPlugin.php +++ b/plugins/OStatus/OStatusPlugin.php @@ -1381,7 +1381,7 @@ class OStatusPlugin extends Plugin return false; } if ($response->getStatus() === 422) { - common_debug(sprintf('Salmon (from profile %d) endpoint %s returned status %s. We assume it is a Diaspora seed, will adapt and try again if that plugin is enabled!')); + common_debug(sprintf('Salmon (from profile %d) endpoint %s returned status %s. We assume it is a Diaspora seed; will adapt and try again if that plugin is enabled!', $magic_env->getActor()->getID(), $endpoint_uri, $response->getStatus())); return true; } @@ -1389,7 +1389,7 @@ class OStatusPlugin extends Plugin // 202 Accepted is what we get from Diaspora for example if (!in_array($response->getStatus(), array(200, 202))) { common_log(LOG_ERR, sprintf('Salmon (from profile %d) endpoint %s returned status %s: %s', - $user->id, $endpoint_uri, $response->getStatus(), $response->getBody())); + $magic_env->getActor()->getID(), $endpoint_uri, $response->getStatus(), $response->getBody())); return true; } diff --git a/plugins/OStatus/lib/magicenvelope.php b/plugins/OStatus/lib/magicenvelope.php index e96862bbad..6786bfa298 100644 --- a/plugins/OStatus/lib/magicenvelope.php +++ b/plugins/OStatus/lib/magicenvelope.php @@ -78,14 +78,16 @@ class MagicEnvelope * @param boolean $discovery Network discovery if no local cache? */ public function getKeyPair(Profile $profile, $discovery=false) { - $magicsig = Magicsig::getKV('user_id', $profile->id); + if (!$profile->isLocal()) common_debug('Getting magic-public-key for non-local profile id=='.$profile->getID()); + $magicsig = Magicsig::getKV('user_id', $profile->getID()); if ($discovery && !$magicsig instanceof Magicsig) { + if (!$profile->isLocal()) common_debug('magic-public-key not found, will do discovery for profile id=='.$profile->getID()); // Throws exception on failure, but does not try to _load_ the keypair string. $keypair = $this->discoverKeyPair($profile); $magicsig = new Magicsig(); - $magicsig->user_id = $profile->id; + $magicsig->user_id = $profile->getID(); $magicsig->importKeys($keypair); // save the public key for this profile in our database. // TODO: If the profile generates a new key remotely, we must be able to replace @@ -113,28 +115,41 @@ class MagicEnvelope { $signer_uri = $profile->getUri(); if (empty($signer_uri)) { - throw new ServerException(sprintf('Profile missing URI (id==%d)', $profile->id)); + throw new ServerException(sprintf('Profile missing URI (id==%d)', $profile->getID())); } $disco = new Discovery(); // Throws exception on lookup problems - $xrd = $disco->lookup($signer_uri); + try { + $xrd = $disco->lookup($signer_uri); + } catch (Exception $e) { + // Diaspora seems to require us to request the acct: uri + $xrd = $disco->lookup($profile->getAcctUri()); + } - $link = $xrd->get(Magicsig::PUBLICKEYREL); - if (is_null($link)) { - // TRANS: Exception. - throw new Exception(_m('Unable to locate signer public key.')); + common_debug('Will try to find magic-public-key from XRD of profile id=='.$profile->getID()); + $pubkey = null; + if (Event::handle('MagicsigPublicKeyFromXRD', array($xrd, &$pubkey))) { + $link = $xrd->get(Magicsig::PUBLICKEYREL); + if (is_null($link)) { + // TRANS: Exception. + throw new Exception(_m('Unable to locate signer public key.')); + } + $pubkey = $link->href; + } + if (empty($pubkey)) { + throw new ServerException('Empty Magicsig public key. A bug?'); } // We have a public key element, let's hope it has proper key data. $keypair = false; - $parts = explode(',', $link->href); + $parts = explode(',', $pubkey); if (count($parts) == 2) { $keypair = $parts[1]; } else { // Backwards compatibility check for separator bug in 0.9.0 - $parts = explode(';', $link->href); + $parts = explode(';', $pubkey); if (count($parts) == 2) { $keypair = $parts[1]; } -- 2.39.5