diff options
author | Jaime Pérez <jaime.perez@uninett.no> | 2016-07-28 14:21:01 +0200 |
---|---|---|
committer | Jaime Pérez <jaime.perez@uninett.no> | 2016-07-28 14:21:01 +0200 |
commit | 977b8e869898b32052e70c4f0d1c58c6369222c7 (patch) | |
tree | ec2bf75f8c355e13c08ed90b7100c996b88c9f83 /lib/SimpleSAML | |
parent | c23722a47dc196428f9ab5d68fd25ad74a3c6cdf (diff) | |
download | simplesamlphp-977b8e869898b32052e70c4f0d1c58c6369222c7.zip simplesamlphp-977b8e869898b32052e70c4f0d1c58c6369222c7.tar.gz simplesamlphp-977b8e869898b32052e70c4f0d1c58c6369222c7.tar.bz2 |
bugfix: Allow attributes to contain raw XML as their values.
A recent change in simplesamlphp/saml2#60 made the library return a DOMNodeList object when the contents of the AttributeValue element are not text. This lead to a bug, since the returned value is not serializable, and when storing it in the session it will go away as soon as we serialize the session to store it in the backend (whatever that is). This is always, as the SP will always redirect to the URL originating authentication. The result was an empty DOMNodeList object where there should be some value.
This commit makes the SimpleSAML_Session to implement the Serializable interface. When obtaining the attributes during login (doLogin() method), the code will now look for DOMNodeList objects, and dump them as a string with the XML representation of their contents in the 'RawAttributes' array inside $this->authData[$authority]. This allows us to parse the XML back when unserializing, and restore the original DOMNodeList object as the value of the attribute.
The issue was reported originally in the mailing list by Enrico Cavalli, affecting eduPersonTargetedID. This resolves #424.
Diffstat (limited to 'lib/SimpleSAML')
-rw-r--r-- | lib/SimpleSAML/Session.php | 88 |
1 files changed, 87 insertions, 1 deletions
diff --git a/lib/SimpleSAML/Session.php b/lib/SimpleSAML/Session.php index a5f831b..91d65b2 100644 --- a/lib/SimpleSAML/Session.php +++ b/lib/SimpleSAML/Session.php @@ -7,11 +7,16 @@ * information about all the currently logged in SPs. This is used when the user initiates a * Single-Log-Out. * + * Bear in mind that the session object implements the Serializable interface, and as such, + * all its contents MUST be serializable. If you need to store something in the session object + * that is not serializable, make sure to convert it first to a representation that can be + * serialized. + * * @author Andreas Åkre Solberg, UNINETT AS. <andreas.solberg@uninett.no> * @author Jaime Pérez Crespo, UNINETT AS <jaime.perez@uninett.no> * @package SimpleSAMLphp */ -class SimpleSAML_Session +class SimpleSAML_Session implements Serializable { /** @@ -181,6 +186,56 @@ class SimpleSAML_Session } } + + /** + * Serialize this session object. + * + * This method will be invoked by any calls to serialize(). + * + * @return string The serialized representation of this session object. + */ + public function serialize() + { + $serialized = serialize(get_object_vars($this)); + return $serialized; + } + + + /** + * Unserialize a session object and load it.. + * + * This method will be invoked by any calls to unserialize(), allowing us to restore any data that might not + * be serializable in its original form (e.g.: DOM objects). + * + * @param string $serialized The serialized representation of a session that we want to restore. + */ + public function unserialize($serialized) + { + $session = unserialize($serialized); + if (is_array($session)) { + foreach ($session as $k => $v) { + $this->$k = $v; + } + } + + // look for any raw attributes and load them in the 'Attributes' array + foreach ($this->authData as $authority => $parameters) { + if (!array_key_exists('RawAttributes', $parameters)) { + continue; + } + + foreach ($parameters['RawAttributes'] as $attribute => $values) { + foreach ($values as $idx => $value) { + // this should be originally a DOMNodeList + $dom = new \DOMDocument(); + $dom->loadXML($value); + $this->authData[$authority]['Attributes'][$attribute][$idx] = $dom->childNodes; + } + } + } + } + + /** * Retrieves the current session. Creates a new session if there's not one. * @@ -554,6 +609,37 @@ class SimpleSAML_Session $data['Expire'] = $maxSessionExpire; } + // check if we have non-serializable attribute values + foreach ($data['Attributes'] as $attribute => $values) { + foreach ($values as $idx => $value) { + if (is_string($value) || is_int($value)) { + continue; + } + + // at this point, this should be a DOMNodeList object... + if (!is_a($value, 'DOMNodeList')) { + continue; + } + + /* @var \DOMNodeList $value */ + if ($value->length === 0) { + continue; + } + + // ... and we have at least one DOMElement in there, so we dump back to XML to be able to serialize + $original = $value->item(0)->ownerDocument; + $new = new DOMDocument($original->version, $original->encoding); + $n = $value->length; + for ($i = 0; $i < $n; $i++) { + $new->appendChild($new->importNode($value->item($i), true)); + } + $new->saveXML(); + + // save the XML representation to 'RawAttributes', using the same attribute name and index + $data['RawAttributes'][$attribute][$idx] = $new->saveXML(); + } + } + $this->authData[$authority] = $data; $this->authToken = SimpleSAML\Utils\Random::generateID(); |