Esempio n. 1
0
 protected function prepare(array $args = array())
 {
     GNUsocial::setApi(true);
     // Send smaller error pages
     parent::prepare($args);
     if (!isset($_SERVER['CONTENT_TYPE'])) {
         // TRANS: Client error. Do not translate "Content-type"
         $this->clientError(_m('Salmon requires a Content-type header.'));
     }
     $envxml = null;
     switch ($_SERVER['CONTENT_TYPE']) {
         case 'application/magic-envelope+xml':
             $envxml = file_get_contents('php://input');
             break;
         case 'application/x-www-form-urlencoded':
             $envxml = Magicsig::base64_url_decode($this->trimmed('xml'));
             break;
         default:
             // TRANS: Client error. Do not translate the quoted "application/[type]" strings.
             $this->clientError(_m('Salmon requires "application/magic-envelope+xml". For Diaspora we also accept "application/x-www-form-urlencoded" with an "xml" parameter.', 415));
     }
     try {
         if (empty($envxml)) {
             throw new ClientException('No magic envelope supplied in POST.');
         }
         $magic_env = new MagicEnvelope($envxml);
         // parse incoming XML as a MagicEnvelope
         $entry = $magic_env->getPayload();
         // Not cryptographically verified yet!
         $this->activity = new Activity($entry->documentElement);
         if (empty($this->activity->actor->id)) {
             common_log(LOG_ERR, "broken actor: " . var_export($this->activity->actor->id, true));
             common_log(LOG_ERR, "activity with no actor: " . var_export($this->activity, true));
             // TRANS: Exception.
             throw new Exception(_m('Received a salmon slap from unidentified actor.'));
         }
         // ensureProfiles sets $this->actor and $this->oprofile
         $this->ensureProfiles();
     } catch (Exception $e) {
         common_debug('Salmon envelope parsing failed with: ' . $e->getMessage());
         $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.'));
     }
     return true;
 }
Esempio n. 2
0
 /**
  *
  * @param string $signed_bytes as raw byte string
  * @param string $signature as base64
  * @return boolean
  */
 public function verify($signed_bytes, $signature)
 {
     $signature = Magicsig::base64_url_decode($signature);
     return $this->publicKey->verify($signed_bytes, $signature);
 }
 public function verify($env)
 {
     if ($env['alg'] != 'RSA-SHA256') {
         common_log(LOG_DEBUG, "Salmon error: bad algorithm");
         return false;
     }
     if ($env['encoding'] != MagicEnvelope::ENCODING) {
         common_log(LOG_DEBUG, "Salmon error: bad encoding");
         return false;
     }
     $text = Magicsig::base64_url_decode($env['data']);
     $signer_uri = $this->getAuthor($text);
     try {
         $keypair = $this->getKeyPair($signer_uri);
     } catch (Exception $e) {
         common_log(LOG_DEBUG, "Salmon error: " . $e->getMessage());
         return false;
     }
     $verifier = Magicsig::fromString($keypair);
     if (!$verifier) {
         common_log(LOG_DEBUG, "Salmon error: unable to parse keypair");
         return false;
     }
     return $verifier->verify($env['data'], $env['sig']);
 }
Esempio n. 4
0
 public function getPayload()
 {
     $dom = new DOMDocument();
     if (!$dom->loadXML(Magicsig::base64_url_decode($this->data))) {
         throw new ServerException('Malformed XML in Salmon payload');
     }
     switch ($this->data_type) {
         case 'application/atom+xml':
             if ($dom->documentElement->namespaceURI !== Activity::ATOM || $dom->documentElement->tagName !== 'entry') {
                 throw new ServerException(_m('Salmon post must be an Atom entry.'));
             }
             $prov = $dom->createElementNS(self::NS, 'me:provenance');
             $prov->setAttribute('xmlns:me', self::NS);
             $data = $dom->createElementNS(self::NS, 'me:data', $this->data);
             $data->setAttribute('type', $this->data_type);
             $prov->appendChild($data);
             $enc = $dom->createElementNS(self::NS, 'me:encoding', $this->encoding);
             $prov->appendChild($enc);
             $alg = $dom->createElementNS(self::NS, 'me:alg', $this->alg);
             $prov->appendChild($alg);
             $sig = $dom->createElementNS(self::NS, 'me:sig', $this->getSignature());
             $prov->appendChild($sig);
             $dom->documentElement->appendChild($prov);
             break;
         default:
             throw new ServerException('Unknown Salmon payload data type');
     }
     return $dom;
 }
Esempio n. 5
0
 /**
  * Fill out $this->privateKey or $this->publicKey with a Crypt_RSA object
  * representing the give key (as mod/exponent pair).
  *
  * @param string $mod base64-encoded
  * @param string $exp base64-encoded exponent
  * @param string $type one of 'public' or 'private'
  */
 public function loadKey($mod, $exp, $type = 'public')
 {
     $rsa = new Crypt_RSA();
     $rsa->setSignatureMode(CRYPT_RSA_SIGNATURE_PKCS1);
     $rsa->setHash($this->getHash());
     $rsa->modulus = new Math_BigInteger(Magicsig::base64_url_decode($mod), 256);
     $rsa->k = strlen($rsa->modulus->toBytes());
     $rsa->exponent = new Math_BigInteger(Magicsig::base64_url_decode($exp), 256);
     if ($type == 'private') {
         $this->privateKey = $rsa;
     } else {
         $this->publicKey = $rsa;
     }
 }