/**
  * BC compatible version of the signature check
  *
  * @param SAML2_SignedElement      $element
  * @param SAML2_Certificate_X509[] $pemCandidates
  *
  * @throws Exception
  *
  * @return bool
  */
 protected function validateElementWithKeys(SAML2_SignedElement $element, $pemCandidates)
 {
     $lastException = NULL;
     foreach ($pemCandidates as $index => $candidateKey) {
         $key = new XMLSecurityKey(XMLSecurityKey::RSA_SHA1, array('type' => 'public'));
         $key->loadKey($candidateKey->getCertificate());
         try {
             /*
              * Make sure that we have a valid signature on either the response or the assertion.
              */
             $result = $element->validate($key);
             if ($result) {
                 $this->logger->debug(sprintf('Validation with key "#%d" succeeded', $index));
                 return TRUE;
             }
             $this->logger->debug(sprintf('Validation with key "#%d" failed without exception.', $index));
         } catch (Exception $e) {
             $this->logger->debug(sprintf('Validation with key "#%d" failed with exception: %s', $index, $e->getMessage()));
             $lastException = $e;
         }
     }
     if ($lastException !== NULL) {
         throw $lastException;
     } else {
         return FALSE;
     }
 }
示例#2
0
 public function canValidate(SAML2_SignedElement $signedElement, SAML2_Configuration_CertificateProvider $configuration)
 {
     if ($configuration->getCertificateFingerprints() === NULL) {
         $this->logger->debug('Configuration does not have "certFingerprint" value, cannot validate signature with fingerprint');
         return FALSE;
     }
     // use internal cache to prevent doing certificate extraction twice.
     $this->certificates = $signedElement->getCertificates();
     if (empty($this->certificates)) {
         $this->logger->debug('Signed element does not have certificates, cannot validate signature with fingerprint');
         return FALSE;
     }
     return TRUE;
 }
示例#3
0
 /**
  * Check the signature on a SAML2 message or assertion.
  *
  * @param SimpleSAML_Configuration $srcMetadata  The metadata of the sender.
  * @param SAML2_SignedElement $element  Either a SAML2_Response or a SAML2_Assertion.
  */
 public static function checkSign(SimpleSAML_Configuration $srcMetadata, SAML2_SignedElement $element)
 {
     /* Find the public key that should verify signatures by this entity. */
     $keys = $srcMetadata->getPublicKeys('signing');
     if ($keys !== NULL) {
         $pemKeys = array();
         foreach ($keys as $key) {
             switch ($key['type']) {
                 case 'X509Certificate':
                     $pemKeys[] = "-----BEGIN CERTIFICATE-----\n" . chunk_split($key['X509Certificate'], 64) . "-----END CERTIFICATE-----\n";
                     break;
                 default:
                     SimpleSAML_Logger::debug('Skipping unknown key type: ' . $key['type']);
             }
         }
     } elseif ($srcMetadata->hasValue('certFingerprint')) {
         $certFingerprint = $srcMetadata->getArrayizeString('certFingerprint');
         foreach ($certFingerprint as &$fp) {
             $fp = strtolower(str_replace(':', '', $fp));
         }
         $certificates = $element->getCertificates();
         /*
          * We don't have the full certificate stored. Try to find it
          * in the message or the assertion instead.
          */
         if (count($certificates) === 0) {
             /* We need the full certificate in order to match it against the fingerprint. */
             SimpleSAML_Logger::debug('No certificate in message when validating against fingerprint.');
             return FALSE;
         } else {
             SimpleSAML_Logger::debug('Found ' . count($certificates) . ' certificates in ' . get_class($element));
         }
         $pemCert = self::findCertificate($certFingerprint, $certificates);
         $pemKeys = array($pemCert);
     } else {
         throw new SimpleSAML_Error_Exception('Missing certificate in metadata for ' . var_export($srcMetadata->getString('entityid'), TRUE));
     }
     SimpleSAML_Logger::debug('Has ' . count($pemKeys) . ' candidate keys for validation.');
     $lastException = NULL;
     foreach ($pemKeys as $i => $pem) {
         $key = new XMLSecurityKey(XMLSecurityKey::RSA_SHA1, array('type' => 'public'));
         $key->loadKey($pem);
         try {
             /*
              * Make sure that we have a valid signature on either the response
              * or the assertion.
              */
             $res = $element->validate($key);
             if ($res) {
                 SimpleSAML_Logger::debug('Validation with key #' . $i . ' succeeded.');
                 return TRUE;
             }
             SimpleSAML_Logger::debug('Validation with key #' . $i . ' failed without exception.');
         } catch (Exception $e) {
             SimpleSAML_Logger::debug('Validation with key #' . $i . ' failed with exception: ' . $e->getMessage());
             $lastException = $e;
         }
     }
     /* We were unable to validate the signature with any of our keys. */
     if ($lastException !== NULL) {
         throw $lastException;
     } else {
         return FALSE;
     }
 }
示例#4
0
 /**
  * Sign the generated EntitiesDescriptor.
  */
 protected function addSignature(SAML2_SignedElement $element)
 {
     if ($this->signKey === NULL) {
         return;
     }
     $privateKey = new XMLSecurityKey(XMLSecurityKey::RSA_SHA1, array('type' => 'private'));
     if ($this->signKeyPass !== NULL) {
         $privateKey->passphrase = $this->signKeyPass;
     }
     $privateKey->loadKey($this->signKey, FALSE);
     $element->setSignatureKey($privateKey);
     if ($this->signCert !== NULL) {
         $element->setCertificates(array($this->signCert));
     }
 }
示例#5
0
 /**
  * Check the signature on a SAML2 message or assertion.
  *
  * @param SimpleSAML_Configuration $srcMetadata  The metadata of the sender.
  * @param SAML2_SignedElement $element  Either a SAML2_Response or a SAML2_Assertion.
  */
 public static function checkSign(SimpleSAML_Configuration $srcMetadata, SAML2_SignedElement $element)
 {
     $certificates = $element->getCertificates();
     SimpleSAML_Logger::debug('Found ' . count($certificates) . ' certificates in ' . get_class($element));
     /* Find the certificate that should verify signatures by this entity. */
     $certArray = SimpleSAML_Utilities::loadPublicKey($srcMetadata, FALSE);
     if ($certArray !== NULL) {
         if (array_key_exists('PEM', $certArray)) {
             $pemCert = $certArray['PEM'];
         } else {
             /*
              * We don't have the full certificate stored. Try to find it
              * in the message or the assertion instead.
              */
             if (count($certificates) === 0) {
                 /* We need the full certificate in order to match it against the fingerprint. */
                 SimpleSAML_Logger::debug('No certificate in message when validating against fingerprint.');
                 return FALSE;
             }
             $certFingerprints = $certArray['certFingerprint'];
             if (count($certFingerprints) === 0) {
                 /* For some reason, we have a certFingerprint entry without any fingerprints. */
                 throw new SimpleSAML_Error_Exception('certFingerprint array was empty.');
             }
             $pemCert = self::findCertificate($certFingerprints, $certificates);
         }
     } else {
         /* Attempt CA validation. */
         $caFile = $srcMetadata->getString('caFile', NULL);
         if ($caFile === NULL) {
             throw new SimpleSAML_Error_Exception('Missing certificate in metadata for ' . var_export($srcMetadata->getString('entityid'), TRUE));
         }
         $caFile = SimpleSAML_Utilities::resolveCert($caFile);
         if (count($certificates) === 0) {
             /* We need the full certificate in order to check it against the CA file. */
             SimpleSAML_Logger::debug('No certificate in message when validating with CA.');
             return FALSE;
         }
         /* We assume that it is the first certificate that was used to sign the message. */
         $pemCert = "-----BEGIN CERTIFICATE-----\n" . chunk_split($certificates[0], 64) . "-----END CERTIFICATE-----\n";
         SimpleSAML_Utilities::validateCA($pemCert, $caFile);
     }
     /* Extract the public key from the certificate for validation. */
     $key = new XMLSecurityKey(XMLSecurityKey::RSA_SHA1, array('type' => 'public'));
     $key->loadKey($pemCert);
     /*
      * Make sure that we have a valid signature on either the response
      * or the assertion.
      */
     return $element->validate($key);
 }