sspmod_saml_Message::checkSign PHP Method

checkSign() public static method

Check the signature on a SAML2 message or assertion.
public static checkSign ( SimpleSAML_Configuration $srcMetadata, SAML2\SignedElement $element )
$srcMetadata SimpleSAML_Configuration The metadata of the sender.
$element SAML2\SignedElement 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')) {
            SimpleSAML\Logger::notice("Validating certificates by fingerprint is deprecated. Please use " . "certData or certificate options in your remote metadata configuration.");
            $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;
        }
    }

Usage Example

コード例 #1
0
 private function authenticate()
 {
     $client_is_authenticated = false;
     /* Authenticate the requestor by verifying the TLS certificate used for the HTTP query */
     if (array_key_exists('SSL_CLIENT_VERIFY', $_SERVER)) {
         SimpleSAML_Logger::debug('[aa] Request was made using the following certificate: ' . var_export($_SERVER['SSL_CLIENT_VERIFY'], 1));
     }
     if (array_key_exists('SSL_CLIENT_VERIFY', $_SERVER) && $_SERVER['SSL_CLIENT_VERIFY'] && $_SERVER['SSL_CLIENT_VERIFY'] != 'NONE') {
         /* compare certificate fingerprints */
         $clientCertData = trim(preg_replace('/--.* CERTIFICATE-+-/', '', $_SERVER['SSL_CLIENT_CERT']));
         $clientCertFingerprint = strtolower(sha1(base64_decode($clientCertData)));
         if (!$clientCertFingerprint) {
             throw new SimpleSAML_Error_Exception('[aa] Can not calculate certificate fingerprint from the request.');
         }
         $spCertArray = SimpleSAML_Utilities::loadPublicKey($this->spMetadata);
         if (!$spCertArray) {
             throw new SimpleSAML_Error_Exception('[aa] Can not find the public key of the requestor in the metadata!');
         }
         foreach ($spCertArray['certFingerprint'] as $fingerprint) {
             if ($fingerprint && $clientCertFingerprint == $fingerprint) {
                 $client_is_authenticated = true;
                 SimpleSAML_Logger::debug('[aa] SSL certificate is checked and valid.');
                 break;
             }
         }
         /* Reject the request if the TLS certificate used for the request does not match metadata */
         if (!$client_is_authenticated) {
             throw new SimpleSAML_Error_Exception('[aa] SSL certificate check failed.');
         }
     } else {
         /* The request may be signed, so this is not fatal */
         SimpleSAML_Logger::debug('[aa] SSL client certificate does not exist.');
     }
     /* Authenticate the requestor by verifying the XML signature on the query */
     $certs_of_query = $this->query->getCertificates();
     if (count($certs_of_query) > 0) {
         if (sspmod_saml_Message::checkSign($this->spMetadata, $this->query)) {
             $client_is_authenticated = true;
             SimpleSAML_Logger::debug('[aa] AttributeQuery signature is checked and valid.');
         } else {
             /* An invalid or unverifiable signature is fatal */
             throw new SimpleSAML_Error_Exception('[aa] The signature of the AttributeQuery is wrong!');
         }
     } else {
         /* The request may be protected by HTTP TLS (X.509) authentication, so this is not fatal */
         SimpleSAML_Logger::debug('[aa] AttributeQuery has no signature.');
     }
     if (!$client_is_authenticated) {
         SimpleSAML_Logger::info('[aa] Attribute query was not authenticated. Drop.');
         header('HTTP/1.1 401 Unauthorized');
         header('WWW-Authenticate: None', false);
         echo 'Not authenticated. Neither query signature nor SSL client certificate was available.';
         exit;
     } else {
         SimpleSAML_Logger::debug('[aa] Attribute query was authenticated.');
     }
 }
All Usage Examples Of sspmod_saml_Message::checkSign