Viewing file: SignedElementHelper.php (4.88 KB) -rwxrwxr-x Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
<?php
/** * Helper class for processing signed elements. * * Can either be inherited from, or can be used by proxy. * * @package simpleSAMLphp * @version $Id$ */ class SAML2_SignedElementHelper implements SAML2_SignedElement {
/** * The private key we should use to sign the message. * * The private key can be NULL, in which case the message is sent unsigned. * * @var XMLSecurityKey|NULL */ private $signatureKey;
/** * List of certificates that should be included in the message. * * @var array */ private $certificates;
/** * Available methods for validating this message. * * @var array */ private $validators;
/** * Initialize the helper class. * * @param DOMElement|NULL $xml The XML element which may be signed. */ protected function __construct(DOMElement $xml = NULL) {
$this->certificates = array(); $this->validators = array();
if ($xml === NULL) { return; }
/* Validate the signature element of the message. */ try { $sig = SAML2_Utils::validateElement($xml);
if ($sig !== FALSE) { $this->certificates = $sig['Certificates']; $this->validators[] = array( 'Function' => array('SAML2_Utils', 'validateSignature'), 'Data' => $sig, ); }
} catch (Exception $e) { /* Ignore signature validation errors. */ } }
/** * Add a method for validating this element. * * This function is used for custom validation extensions * * @param callback $function The function which should be called. * @param mixed $data The data that should be included as the first parameter to the function. */ public function addValidator($function, $data) { assert('is_callable($function)');
$this->validators[] = array( 'Function' => $function, 'Data' => $data, ); }
/** * Validate this element against a public key. * * TRUE is returned on success, FALSE is returned if we don't have any * signature we can validate. An exception is thrown if the signature * validation fails. * * @param XMLSecurityKey $key The key we should check against. * @return boolean TRUE on success, FALSE when we don't have a signature. */ public function validate(XMLSecurityKey $key) {
if (count($this->validators) === 0) { return FALSE; }
$exceptions = array();
foreach ($this->validators as $validator) { $function = $validator['Function']; $data = $validator['Data'];
try { call_user_func($function, $data, $key); /* We were able to validate the message with this validator. */ return TRUE; } catch (Exception $e) { $exceptions[] = $e; } }
/* No validators were able to validate the message. */ throw $exceptions[0]; }
/** * Retrieve the private key we should use to sign the message. * * @return XMLSecurityKey|NULL The key, or NULL if no key is specified. */ public function getSignatureKey() { return $this->signatureKey; }
/** * Set the private key we should use to sign the message. * * If the key is NULL, the message will be sent unsigned. * * @param XMLSecurityKey|NULL $key */ public function setSignatureKey(XMLsecurityKey $signatureKey = NULL) { $this->signatureKey = $signatureKey; }
/** * Set the certificates that should be included in the message. * * The certificates should be strings with the PEM encoded data. * * @param array $certificates An array of certificates. */ public function setCertificates(array $certificates) { $this->certificates = $certificates; }
/** * Retrieve the certificates that are included in the message. * * @return array An array of certificates. */ public function getCertificates() { return $this->certificates; }
/** * Retrieve certificates that sign this element. * * @return array Array with certificates. */ public function getValidatingCertificates() {
$ret = array(); foreach ($this->certificates as $cert) {
/* We have found a matching fingerprint. */ $pemCert = "-----BEGIN CERTIFICATE-----\n" . chunk_split($cert, 64) . "-----END CERTIFICATE-----\n";
/* Extract the public key from the certificate for validation. */ $key = new XMLSecurityKey(XMLSecurityKey::RSA_SHA1, array('type'=>'public')); $key->loadKey($pemCert);
try { /* Check the signature. */ if ($this->validate($key)) { $ret[] = $cert; } } catch (Exception $e) { /* This certificate does not sign this element. */ } }
return $ret; }
/** * Sign the given XML element. * * @param DOMElement $root The element we should sign. * @param DOMElement|NULL $insertBefore The element we should insert the signature node before. */ protected function signElement(DOMElement $root, DOMElement $insertBefore = NULL) {
if ($this->signatureKey === NULL) { /* We cannot sign this element. */ return; }
SAML2_Utils::insertSignature($this->signatureKey, $this->certificates, $root, $insertBefore);
return $root; }
}
|