From b5e25931e9fee559d737e2ab99f239cc990a60a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Pe=CC=81rez?= <jaime.perez@uninett.no> Date: Fri, 29 Jul 2016 07:27:30 +0200 Subject: [PATCH] Backport of bugfix for issue #424. This is basically commits 977b8e869898b32052e70c4f0d1c58c6369222c7, f261dfc1463ce867838b947f763470c61774e385 and 6d215c0b4ebce4957e4541f2cb6cb0bcb154a438, making sure the SAML2 classes are called using their old names. --- lib/SimpleSAML/Session.php | 78 ++++++++++++++++++++++++++++++- templates/includes/attributes.php | 28 +++++++++++ 2 files changed, 105 insertions(+), 1 deletion(-) diff --git a/lib/SimpleSAML/Session.php b/lib/SimpleSAML/Session.php index c40a6c9af..661b38b47 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 { /** @@ -173,6 +178,54 @@ 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 + /* @var SAML2_XML_saml_AttributeValue $value */ + $this->authData[$authority]['Attributes'][$attribute][$idx] = $value->element->childNodes; + } + } + } + } + + /** * Retrieves the current session. Creates a new session if there's not one. * @@ -542,6 +595,29 @@ 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; + } + + // create an AttributeValue object and save it to 'RawAttributes', using same attribute name and index + $attrval = new SAML2_XML_saml_AttributeValue($value->item(0)->parentNode); + $data['RawAttributes'][$attribute][$idx] = $attrval; + } + } + $this->authData[$authority] = $data; $this->authToken = SimpleSAML\Utils\Random::generateID(); diff --git a/templates/includes/attributes.php b/templates/includes/attributes.php index 2f960c46c..77f6f06bd 100644 --- a/templates/includes/attributes.php +++ b/templates/includes/attributes.php @@ -71,6 +71,34 @@ function present_attributes($t, $attributes, $nameParent) { $str .= '</td>'; if ($nameraw === 'jpegPhoto') { $str .= '<td class="attrvalue"><img src="data:image/jpeg;base64,' . htmlspecialchars($value[0]) . '" /></td></tr>'; + } elseif (is_a($value[0], 'DOMNodeList')) { + // try to see if we have a NameID here + $n = $value[0]->length; + for ($idx = 0; $idx < $n; $idx++) { + /* @var DOMNodeList[] $value */ + $elem = $value[0]->item($idx); + /* @var DOMNode $elem */ + if (!($elem->localName === 'NameID' && $elem->namespaceURI === SAML2_Const::NS_SAML)) { + continue; + } + $nameID = new SAML2_XML_saml_NameID($elem); + $eptid = array( + 'NameID' => array($nameID->value), + ); + if (!empty($nameID->Format)) { + $eptid['Format'] = array($nameID->Format); + } + if (!empty($nameID->NameQualifier)) { + $eptid['NameQualifier'] = array($nameID->NameQualifier); + } + if (!empty($nameID->SPNameQualifier)) { + $eptid['SPNameQualifier'] = array($nameID->SPNameQualifier); + } + $str .= '<td class="attrvalue">'; + $str .= present_assoc($eptid); + break; // we only support one NameID here + } + $str .= '</td></tr>'; } else { $str .= '<td class="attrvalue">' . htmlspecialchars($value[0]) . '</td></tr>'; } -- GitLab