]> git.mxchange.org Git - quix0rs-gnu-social.git/commitdiff
Move around some code related to Magic_envelope and signing
authorMikael Nordfeldth <mmn@hethane.se>
Sat, 3 Oct 2015 21:25:02 +0000 (23:25 +0200)
committerMikael Nordfeldth <mmn@hethane.se>
Sat, 3 Oct 2015 21:35:46 +0000 (23:35 +0200)
plugins/OStatus/lib/magicenvelope.php
plugins/OStatus/lib/salmon.php
plugins/OStatus/lib/salmonaction.php

index dfd3abaeabd401cc6852e6721b59474a19eddc17..533cd7d201560c3e00cea17b748f3d35dcaed822 100644 (file)
@@ -32,6 +32,8 @@ class MagicEnvelope
 
     const NS = 'http://salmon-protocol.org/ns/magic-env';
 
+    protected $actor = null;    // Profile of user who has signed the envelope
+
     protected $data      = null;    // When stored here it is _always_ base64url encoded
     protected $data_type = null;
     protected $encoding  = null;
@@ -48,7 +50,7 @@ class MagicEnvelope
      * @fixme may give fatal errors if some elements are missing or invalid XML
      * @fixme calling DOMDocument::loadXML statically triggers warnings in strict mode
      */
-    public function __construct($xml=null) {
+    public function __construct($xml=null, Profile $actor=null) {
         if (!empty($xml)) {
             $dom = new DOMDocument();
             if (!$dom->loadXML($xml)) {
@@ -56,6 +58,15 @@ class MagicEnvelope
             } elseif (!$this->fromDom($dom)) {
                 throw new ServerException('Could not load MagicEnvelope from DOM');
             }
+        } elseif ($actor instanceof Profile) {
+            // So far we only allow setting with _either_ $xml _or_ $actor as that's
+            // all our circumstances require. But it may be confusing for new developers.
+            // The idea is that feeding XML must be followed by interpretation and then
+            // running $magic_env->verify($profile), just as in SalmonAction->prepare(...)
+            // and supplying an $actor (which right now has to be a User) will require
+            // defining the $data, $data_type etc. attributes manually afterwards before
+            // signing the envelope..
+            $this->setActor($actor);
         }
     }
 
@@ -162,8 +173,21 @@ class MagicEnvelope
      *
      * @throws Exception of various kinds on signing failure
      */
-    public function signMessage($text, $mimetype, Magicsig $magicsig)
+    public function signMessage($text, $mimetype)
     {
+        if (!$this->actor instanceof Profile) {
+            throw new ServerException('No profile to sign message with is set.');
+        } elseif (!$this->actor->isLocal()) {
+            throw new ServerException('Cannot sign magic envelopes with remote users since we have no private key.');
+        }
+
+        // Find already stored key
+        $magicsig = Magicsig::getKV('user_id', $this->actor->getID());
+        if (!$magicsig instanceof Magicsig) {
+            // and if it doesn't exist, it is time to create one!
+            $magicsig = Magicsig::generate($this->actor->getUser());
+        }
+        assert($magicsig instanceof Magicsig);
         assert($magicsig->privateKey instanceof Crypt_RSA);
 
         // Prepare text and metadata for signing
@@ -290,7 +314,12 @@ class MagicEnvelope
             return false;
         }
 
-        return $magicsig->verify($this->signingText(), $this->getSignature());
+        if (!$magicsig->verify($this->signingText(), $this->getSignature())) {
+            // TRANS: Client error when incoming salmon slap signature does not verify cryptographically.
+            throw new ClientException(_m('Salmon signature verification failed.'));
+        }
+        $this->setActor($profile);
+        return true;
     }
 
     /**
@@ -323,6 +352,22 @@ class MagicEnvelope
         return true;
     }
 
+    public function setActor(Profile $actor)
+    {
+        if ($this->actor instanceof Profile) {
+            throw new ServerException('Cannot set a new actor profile for MagicEnvelope object.');
+        }
+        $this->actor = $actor;
+    }
+
+    public function getActor()
+    {
+        if (!$this->actor instanceof Profile) {
+            throw new ServerException('No actor set for this magic envelope.');
+        }
+        return $this->actor;
+    }
+
     /**
      * Encode the given string as a signed MagicEnvelope XML document,
      * using the keypair for the given local user profile. We can of
@@ -342,16 +387,8 @@ class MagicEnvelope
      */
     public static function signAsUser($text, User $user)
     {
-        // Find already stored key
-        $magicsig = Magicsig::getKV('user_id', $user->id);
-        if (!$magicsig instanceof Magicsig) {
-            $magicsig = Magicsig::generate($user);
-        }
-        assert($magicsig instanceof Magicsig);
-        assert($magicsig->privateKey instanceof Crypt_RSA);
-
-        $magic_env = new MagicEnvelope();
-        $magic_env->signMessage($text, 'application/atom+xml', $magicsig);
+        $magic_env = new MagicEnvelope(null, $user->getProfile());
+        $magic_env->signMessage($text, 'application/atom+xml');
 
         return $magic_env;
     }
index 2097ffa77f87e04378037e8f91c09922176ee793..f81c9bdc22d910620a57db40f5cad3378c7f5101 100644 (file)
@@ -55,12 +55,13 @@ class Salmon
 
         try {
             $magic_env = MagicEnvelope::signAsUser($xml, $user);
-            $envxml = $magic_env->toXML();
         } catch (Exception $e) {
             common_log(LOG_ERR, "Salmon unable to sign: " . $e->getMessage());
             return false;
         }
 
+        $envxml = $magic_env->toXML();
+
         $headers = array('Content-Type: application/magic-envelope+xml');
 
         try {
@@ -73,8 +74,10 @@ class Salmon
         }
 
         // Diaspora wants a slightly different formatting on the POST (other Content-type, so body needs "xml=")
+        // This also gives us the opportunity to send the specially formatted Diaspora salmon slap, which
+        // encrypts the content of me:data
         if ($response->getStatus() === 422) {
-            common_debug(sprintf('Salmon (from profile %d) endpoint %s returned status %s. Diaspora? Will try again! Body: %s',
+            common_debug(sprintf('Salmon (from profile %d) endpoint %s returned status %s. We assume it is a Diaspora seed, will adapt and try again! Body: %s',
                                 $user->id, $endpoint_uri, $response->getStatus(), $response->getBody()));
             $headers = array('Content-Type: application/x-www-form-urlencoded');
             $client->setBody('xml=' . Magicsig::base64_url_encode($envxml));
index 320ea6cdfa6f980b9d51ad7e7301d4953bfd5e30..3cb76ca336b5bb11ad65ac4ecd9c8aa33c2fe116 100644 (file)
@@ -79,12 +79,8 @@ class SalmonAction extends Action
             $this->clientError($e->getMessage());
         }
 
-        // Cryptographic verification test
-        if (!$magic_env->verify($this->actor)) {
-            common_log(LOG_DEBUG, "Salmon signature verification failed.");
-            // TRANS: Client error.
-            $this->clientError(_m('Salmon signature verification failed.'));
-        }
+        // Cryptographic verification test, throws exception on failure
+        $magic_env->verify($this->actor);
 
         return true;
     }