]> git.mxchange.org Git - quix0rs-gnu-social.git/blobdiff - plugins/Diaspora/DiasporaPlugin.php
Script for removing remote files until a given date
[quix0rs-gnu-social.git] / plugins / Diaspora / DiasporaPlugin.php
index 68f23a438231bdf8369c6f5a4c6f15836c1383b7..c054d3b767658cfd32cd5629e428569bb402bb62 100644 (file)
@@ -33,9 +33,6 @@ if (!defined('GNUSOCIAL')) { exit(1); }
 // Depends on OStatus of course.
 addPlugin('OStatus');
 
-//Since Magicsig hasn't loaded yet
-require_once('Crypt/AES.php');
-
 class DiasporaPlugin extends Plugin
 {
     const REL_SEED_LOCATION = 'http://joindiaspora.com/seed_location';
@@ -46,7 +43,7 @@ class DiasporaPlugin extends Plugin
     {
         // So far we've only handled RSA keys, but it can change in the future,
         // so be prepared. And remember to change the statically assigned type attribute below!
-        assert($magicsig->publicKey instanceof Crypt_RSA);
+        assert($magicsig->publicKey instanceof \phpseclib\Crypt\RSA);
         $xrd->links[] = new XML_XRD_Element_Link(self::REL_PUBLIC_KEY,
                                     base64_encode($magicsig->exportPublicKey()), 'RSA');
 
@@ -56,10 +53,33 @@ 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',
-                            'version' => '0.1',
+                            'version' => '0.2',
                             'author' => 'Mikael Nordfeldth',
                             'homepage' => 'https://gnu.io/social',
                             // TRANS: Plugin description.
@@ -81,16 +101,20 @@ class DiasporaPlugin extends Plugin
 
         /**
          * https://wiki.diasporafoundation.org/Federation_protocol_overview
+         * http://www.rubydoc.info/github/Raven24/diaspora-federation/master/DiasporaFederation/Salmon/EncryptedSlap
          *
          * Constructing the encryption header
          */
 
+        // For some reason diaspora wants the salmon slap in a <diaspora> header.
+        $xs->elementStart('diaspora', array('xmlns'=>'https://joindiaspora.com/protocol'));
+
         /**
          * Choose an AES key and initialization vector, suitable for the
          * aes-256-cbc cipher. I shall refer to this as the “inner key”
          * and the “inner initialization vector (iv)”.
          */
-        $inner_key = new Crypt_AES(CRYPT_AES_MODE_CBC);
+        $inner_key = new \phpseclib\Crypt\AES(\phpseclib\Crypt\AES::MODE_CBC);
         $inner_key->setKeyLength(256);  // set length to 256 bits (could be calculated, but let's be sure)
         $inner_key->setKey(common_random_rawstr(32));   // 32 bytes from a (pseudo) random source
         $inner_key->setIV(common_random_rawstr(16));    // 16 bytes is the block length
@@ -116,7 +140,7 @@ class DiasporaPlugin extends Plugin
          * for the aes-256-cbc cipher. I shall refer to this as the
          * “outer key” and the “outer initialization vector (iv)”.
          */
-        $outer_key = new Crypt_AES(CRYPT_AES_MODE_CBC);
+        $outer_key = new \phpseclib\Crypt\AES(\phpseclib\Crypt\AES::MODE_CBC);
         $outer_key->setKeyLength(256);  // set length to 256 bits (could be calculated, but let's be sure)
         $outer_key->setKey(common_random_rawstr(32));   // 32 bytes from a (pseudo) random source
         $outer_key->setIV(common_random_rawstr(16));    // 16 bytes is the block length
@@ -126,7 +150,7 @@ class DiasporaPlugin extends Plugin
          * and “outer iv” (using the aes-256-cbc cipher). This encrypted
          * blob shall be referred to as “the ciphertext”. 
          */
-        $ciphertext = $outer_key->encrypt($decrypted_header);
+        $ciphertext = $outer_key->encrypt($decrypted_header, \phpseclib\Crypt\RSA::PADDING_PKCS1);
 
         /**
          * Construct the following JSON object, which shall be referred to
@@ -144,9 +168,10 @@ 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);
+        $enc_outer = $remote_keys->publicKey->encrypt($outer_bundle, \phpseclib\Crypt\RSA::PADDING_PKCS1);
 
         /**
          * Construct the following JSON object, which I shall refer to as
@@ -176,7 +201,10 @@ class DiasporaPlugin extends Plugin
          *      chose earlier.
          * 2. Base64-encode the encrypted payload message.
          */
-        $payload = $inner_key->encrypt($magic_env->getData());
+        $payload = $inner_key->encrypt($magic_env->getData(), \phpseclib\Crypt\RSA::PADDING_PKCS1);
+        //FIXME: This means we don't actually put an <atom:entry> in the payload,
+        // since Diaspora has its own update method! Silly me. Read up on:
+        // https://wiki.diasporafoundation.org/Federation_Message_Semantics
         $magic_env->signMessage(base64_encode($payload), 'application/xml');
 
 
@@ -190,12 +218,19 @@ class DiasporaPlugin extends Plugin
         $xs->element('me:sig', null, $magic_env->getSignature());
         $xs->elementEnd('me:env');
 
+        $xs->elementEnd('entry');
+
         return false;
     }
 
     public function onSalmonSlap($endpoint_uri, MagicEnvelope $magic_env, Profile $target=null)
     {
-        $envxml = $magic_env->toXML($target, 'diaspora');
+        try {
+            $envxml = $magic_env->toXML($target, 'diaspora');
+        } catch (Exception $e) {
+            common_log(LOG_ERR, sprintf('Could not generate Magic Envelope XML (diaspora flavour) for profile id=='.$target->getID().': '.$e->getMessage()));
+            return false;
+        }
 
         // Diaspora wants another POST format (base64url-encoded POST variable 'xml')
         $headers = array('Content-Type: application/x-www-form-urlencoded');
@@ -207,7 +242,7 @@ class DiasporaPlugin extends Plugin
             $client = new HTTPClient();
             $client->setBody('xml=' . Magicsig::base64_url_encode($envxml));
             $response = $client->post($endpoint_uri, $headers);
-        } catch (HTTP_Request2_Exception $e) {
+        } catch (Exception $e) {
             common_log(LOG_ERR, "Diaspora-flavoured Salmon post to $endpoint_uri failed: " . $e->getMessage());
             return false;
         }
@@ -216,7 +251,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;
         }