/** * @param array|string $formats * @param string $blob * @return Message * @throws InvalidMessageException */ public function decode($formats, $blob) { $formats = (array) $formats; $prefixLen = 0; foreach ($formats as $format) { $prefixLen = max($prefixLen, strlen($format)); } list($prefix) = explode(Constants::PROTOCOL_DELIM, substr($blob, 0, $prefixLen + 1)); if (!in_array($prefix, $formats)) { if (in_array(GarbledMessage::NAME, $formats)) { return GarbledMessage::decode($blob); } else { throw new InvalidMessageException("Unexpected message type."); } } switch ($prefix) { case StdMessage::NAME: return StdMessage::decode($this->cxnStore, $blob); case InsecureMessage::NAME: return InsecureMessage::decode($blob); case RegistrationMessage::NAME: return RegistrationMessage::decode($this->appStore, $blob); case AppMetasMessage::NAME: return AppMetasMessage::decode($this->certValidator, $blob); default: throw new InvalidMessageException("Unrecognized message type."); } }
/** * @param AppStoreInterface $appStore * @param string $blob * @return array * Decoded data. */ public static function decode($appStore, $blob) { $parts = explode(Constants::PROTOCOL_DELIM, $blob, 5); if (count($parts) != 5) { throw new InvalidMessageException('Invalid message: insufficient parameters'); } list($wireProt, $wireAppId, $rsaCiphertextB64, $signature, $body) = $parts; if ($wireProt !== self::NAME) { throw new InvalidMessageException('Invalid message: wrong protocol name'); } $appPrivKey = $appStore->getPrivateKey($wireAppId); if (!$appPrivKey) { throw new InvalidMessageException('Received message intended for unknown app.'); } $rsaCiphertext = base64_decode($rsaCiphertextB64); if (strlen($rsaCiphertext) !== Constants::RSA_MSG_BYTES) { throw new InvalidMessageException("RSA ciphertext has incorrect length"); } $secret = UserError::adapt('Civi\\Cxn\\Rpc\\Exception\\InvalidMessageException', function () use($rsaCiphertext, $appPrivKey) { return RegistrationMessage::getRsa($appPrivKey, 'private')->decrypt($rsaCiphertext); }); if (empty($secret)) { throw new InvalidMessageException("Invalid message: decryption produced empty secret"); } $plaintext = AesHelper::authenticateThenDecrypt($secret, $body, $signature); return json_decode($plaintext, TRUE); }
public function decode($formats, $message) { $prefixLen = 0; foreach ($formats as $format) { $prefixLen = max($prefixLen, strlen($format)); } list($prefix) = explode(Constants::PROTOCOL_DELIM, substr($message, 0, $prefixLen + 1)); if (!in_array($prefix, $formats)) { throw new InvalidMessageException("Unexpected message type."); } switch ($prefix) { case StdMessage::NAME: return StdMessage::decode($this->cxnStore, $message); case InsecureMessage::NAME: return InsecureMessage::decode($message); case RegistrationMessage::NAME: return RegistrationMessage::decode($this->appId, $this->appPrivKey, $message); default: throw new InvalidMessageException("Unrecognized message type"); } }
/** * @param $appMeta * @param $entity * @param $action * @param $params * @param $cxn * @return array * @throws Exception\InvalidMessageException */ protected function doCall($appMeta, $entity, $action, $params, $cxn) { $appCert = new \File_X509(); $appCert->loadX509($appMeta['appCert']); $req = new RegistrationMessage($cxn['appId'], $appCert->getPublicKey(), array('cxn' => $cxn, 'entity' => $entity, 'action' => $action, 'params' => $params)); list($respHeaders, $respCiphertext, $respCode) = $this->http->send('POST', $cxn['appUrl'], $req->encode()); $respMessage = $this->decode(array(StdMessage::NAME, InsecureMessage::NAME, GarbledMessage::NAME), $respCiphertext); if ($respMessage instanceof GarbledMessage) { return array($respCode, array('is_error' => 1, 'error_message' => 'Received garbled message', 'original_message' => $respMessage->getData())); } elseif ($respMessage instanceof InsecureMessage) { return array($respCode, array('is_error' => 1, 'error_message' => 'Received insecure error message', 'original_message' => $respMessage->getData())); } if ($respMessage->getCxnId() != $cxn['cxnId']) { // Tsk, tsk, Mallory! throw new \RuntimeException('Received response from incorrect connection.'); } return array($respCode, $respMessage->getData()); }