/**
  * The application does not want to verify the authenticity of the app list,
  * so it's valid - even if signed by someone else.
  */
 public function testUnsignedValid()
 {
     list($caKeyPair, $caCert) = $this->createCA();
     $distPointKeyPair = KeyPair::create();
     $distPointCert = CA::signCSR($caKeyPair, $caCert, CA::createDirSvcCSR($distPointKeyPair, 'O=Someone, CN=else'));
     $msg = new AppMetasMessage($distPointCert, $distPointKeyPair, array('app-2' => array('appId' => 'app-2')));
     $appMetas = AppMetasMessage::decode(NULL, $msg->encode())->getData();
     $this->assertEquals('app-2', $appMetas['app-2']['appId']);
 }
Example #2
0
 /**
  * @param CertificateValidatorInterface|NULL $certValidator
  * @param string $blob
  * @return AppMetasMessage
  *   Validated message.
  * @throws InvalidMessageException
  */
 public static function decode($certValidator, $blob)
 {
     $parts = explode(Constants::PROTOCOL_DELIM, $blob, 4);
     if (count($parts) != 4) {
         throw new InvalidMessageException('Invalid message: insufficient parameters');
     }
     list($wireProt, $wireCert, $wireSig, $wireEnvelope) = $parts;
     if ($wireProt != self::NAME) {
         throw new InvalidMessageException('Invalid message: wrong protocol name');
     }
     if ($certValidator !== NULL) {
         $certValidator->validateCert($wireCert);
         $wireCertX509 = new \File_X509();
         $wireCertX509->loadX509($wireCert);
         $cn = $wireCertX509->getDNProp('CN');
         if (count($cn) != 1 || $cn[0] != Constants::OFFICIAL_APPMETAS_CN) {
             throw new InvalidMessageException('Invalid message: signed by unauthorized party');
         }
         $isValid = UserError::adapt('Civi\\Cxn\\Rpc\\Exception\\InvalidMessageException', function () use($wireCertX509, $wireEnvelope, $wireSig) {
             return AppMetasMessage::getRsaFromCert($wireCertX509)->verify($wireEnvelope, base64_decode($wireSig));
         });
         if (!$isValid) {
             throw new InvalidMessageException("Invalid message: incorrect signature");
         }
     }
     $envelope = json_decode($wireEnvelope, TRUE);
     if (empty($envelope)) {
         throw new InvalidMessageException("Invalid message: malformed envelope");
     }
     if (Time::getTime() > $envelope['ttl']) {
         throw new InvalidMessageException("Invalid message: expired");
     }
     return new AppMetasMessage($wireCert, NULL, json_decode($envelope['r'], TRUE));
 }
Example #3
0
 /**
  * @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.");
     }
 }