From ceb641234b569c1ffbd4fad1e530ed0b5d37b1cf Mon Sep 17 00:00:00 2001 From: Olav Morken <olav.morken@uninett.no> Date: Tue, 3 Jun 2008 12:50:38 +0000 Subject: [PATCH] Metadata/SAMLParser: Added support for validating the signature in EntityDescriptor elements. git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@591 44740490-163a-0410-bde0-09ae8108e29a --- lib/SimpleSAML/Metadata/SAMLParser.php | 83 ++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/lib/SimpleSAML/Metadata/SAMLParser.php b/lib/SimpleSAML/Metadata/SAMLParser.php index db8cc0e39..25706015b 100644 --- a/lib/SimpleSAML/Metadata/SAMLParser.php +++ b/lib/SimpleSAML/Metadata/SAMLParser.php @@ -1,6 +1,7 @@ <?php require_once((isset($SIMPLESAML_INCPREFIX)?$SIMPLESAML_INCPREFIX:'') . 'SimpleSAML/Utilities.php'); +require_once((isset($SIMPLESAML_INCPREFIX)?$SIMPLESAML_INCPREFIX:'') . 'SimpleSAML/XML/Validator.php'); /** * This is class for parsing of SAML 1.x and SAML 2.0 metadata. @@ -81,6 +82,14 @@ class SimpleSAML_Metadata_SAMLParser { private $idpDescriptors; + /** + * This is a SimpleSAML_XML_Validator class if this EntityDescriptor is signed. + * The validator can be used to check the fingerprint of the certificate which was used to sign + * the EntityDescriptor. + */ + private $validator; + + /** * This is the constructor for the SAMLParser class. * @@ -111,6 +120,10 @@ class SimpleSAML_Metadata_SAMLParser { continue; } + if(SimpleSAML_Utilities::isDOMElementOfType($child, 'Signature', '@ds') === TRUE) { + $this->processSignature($child); + } + if(SimpleSAML_Utilities::isDOMElementOfType($child, 'SPSSODescriptor', '@md') === TRUE) { $this->processSPSSODescriptor($child); } @@ -916,6 +929,76 @@ class SimpleSAML_Metadata_SAMLParser { return $supProt; } + + /** + * This function processes a signature element in an EntityDescriptor element. + * + * It will attempt to validate the EntityDescriptor element using the signature. If the signature + * is good, it will and will store the fingerprint the certificate in the $validatedFingerprint variable. + * + * @param $element The ds:Signature element. + */ + private function processSignature($element) { + assert('$element instanceof DOMElement'); + + /* We want to validate the EntityDescriptor which contains the signature. */ + $entityDescriptor = $element->parentNode; + assert('$entityDescriptor instanceof DOMElement'); + + /* xmlseclib works on DOMDocuments. We need to make sure that the EntityDescriptor is the only + * element in the document. + */ + $document = $entityDescriptor->ownerDocument; + if(!$entityDescriptor->isSameNode($document->firstChild) || + !$entityDescriptor->isSameNode($document->lastChild)) { + + /* This EntityDescriptor element isn't the only element in the document. Copy + * the DOMNode with the EntityDescriptor into its own document. + */ + $document = new DOMDocument($document->version, $document->encoding); + $entityDescriptor = $document->importNode($entityDescriptor, TRUE); + $document->appendChild($entityDescriptor); + } + + /* Attempt to check the signature. */ + try { + $validator = new SimpleSAML_XML_Validator($document, 'ID'); + + if($validator->isNodeValidated($entityDescriptor)) { + /* The EntityDescriptor is signed. Store the validator in $this->validator, so + * that it can be used to verify the fingerprint of the certificate later. + */ + $this->validator = $validator; + } + } catch(Exception $e) { + /* Ignore validation errors and pretend that this EntityDescriptor is unsigned. */ + } + } + + + /** + * This function checks if this EntityDescriptor was signed with a certificate with the + * given fingerprint. + * + * @param $fingerprint Fingerprint of the certificate which should have been used to sign this + * EntityDescriptor. + * @return TRUE if it was signed with the certificate with the given fingerprint, FALSE otherwise. + */ + public function validateFingerprint($fingerprint) { + + if($this->validator === NULL) { + return FALSE; + } + + try { + $this->validator->validateFingerprint($fingerprint); + return TRUE; + } catch(Exception $e) { + /* Validation failed. */ + return FALSE; + } + } + } ?> \ No newline at end of file -- GitLab