summaryrefslogtreecommitdiffstats
path: root/lib/SAML2
Commit message (Collapse)AuthorAgeFilesLines
* Start using SAML2 library from GitHub.Olav Morken2013-11-1563-9690/+0
| | | | | | | | | This patch also starts using Composer for other dependencies (i.e. php-openid and xmlseclibs). Thanks to Boy Baukema for implementing this! git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@3290 44740490-163a-0410-bde0-09ae8108e29a
* Bugfix. Thanks to Boy Baukema for reporting issue #579.Jaime Pérez Crespo2013-10-291-1/+1
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@3287 44740490-163a-0410-bde0-09ae8108e29a
* Bugfix. Thanks to Boy Baukema for reporting issue #581.Jaime Pérez Crespo2013-10-291-1/+1
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@3286 44740490-163a-0410-bde0-09ae8108e29a
* Bugfix. Thanks to Boy Baukema for reporting issue #580.Jaime Pérez Crespo2013-10-291-1/+1
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@3285 44740490-163a-0410-bde0-09ae8108e29a
* Bugfix. Thanks to Boy Baukema for reporting issue #578.Jaime Pérez Crespo2013-10-291-0/+2
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@3284 44740490-163a-0410-bde0-09ae8108e29a
* Fixed a typo. Thanks to Boy Baukema for reporting issue #582.Jaime Pérez Crespo2013-10-251-1/+1
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@3283 44740490-163a-0410-bde0-09ae8108e29a
* Add support for sending AttributeConsumingService and ↵Olav Morken2013-09-021-8/+47
| | | | | | | | | | | AssertionConsumerServiceIndex. This patch adds support for sending the AttributeConsumingService and AssertionConsumerServiceIndex attributes in the authentication request. Thanks to Dale Clarke for providing this patch! git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@3266 44740490-163a-0410-bde0-09ae8108e29a
* SAML2: Add Scoping-element to AuthnRequest even if IDPList isn't specified.Olav Morken2013-09-021-1/+1
| | | | | | | | | | The Scoping-element should be added as soom as we want to include RequesterID, IDPList or ProxyCount in the message. We must therefore add it even if IDPList isn't specified. Thanks to Lucas van Lierop for finding this bug! git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@3265 44740490-163a-0410-bde0-09ae8108e29a
* SAML2: Fix generation of mdui:Keyword with ampersand in keyword.Olav Morken2013-05-221-3/+4
| | | | | | Same problem as fixed in r3241. git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@3242 44740490-163a-0410-bde0-09ae8108e29a
* SAML2: Fix generation of mdui:Logo element with ampersand in URL.Olav Morken2013-05-221-1/+1
| | | | | | Thanks to Dick Visser for reporting this bug! git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@3241 44740490-163a-0410-bde0-09ae8108e29a
* md:EntitiesDescriptor: Add sanitycheck for Name-attribute.Olav Morken2012-10-301-0/+1
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@3199 44740490-163a-0410-bde0-09ae8108e29a
* md:EntityDescriptor: Add Name-attribute to output.Olav Morken2012-10-301-0/+4
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@3198 44740490-163a-0410-bde0-09ae8108e29a
* SAML2_HTTPRedirect: Fix warning with value-less paramtere.Olav Morken2012-10-291-1/+8
| | | | | | | | | | This patch fixes warnings from query strings like: http://.../endpoint.php?foo&bar=test (Where the parameter "foo" doesn't have a value.) git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@3197 44740490-163a-0410-bde0-09ae8108e29a
* Added support for RegistrationInfo element in SAML 2.0 metadata.Jaime Pérez Crespo2012-10-052-0/+88
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@3185 44740490-163a-0410-bde0-09ae8108e29a
* Support for RSA_SHA256, RSA_SHA384 and RSA_SHA512 in HTTP Redirect binding. ↵Jaime Pérez Crespo2012-10-012-26/+21
| | | | | | Signature algorithm can now be set also in the remote IdP metadata, with more priority than the one specified in hosted SP metadata. git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@3181 44740490-163a-0410-bde0-09ae8108e29a
* Added support for RSA-SHA256, RSA-SHA384 and RSA-SHA512 signature ↵Jaime Pérez Crespo2012-09-201-3/+27
| | | | | | algorithms. New hosted IdP metadata option 'signature.algorithm' to configure this, defaults to SHA1 for backwards compatibility. git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@3164 44740490-163a-0410-bde0-09ae8108e29a
* SAML2_HTTPRedirect: Fix misspelling of "Exception".Olav Morken2012-09-131-1/+1
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@3161 44740490-163a-0410-bde0-09ae8108e29a
* Fix for issue #509. Check symmetric key length once decrypted, to make sure ↵Jaime Pérez Crespo2012-08-241-0/+4
| | | | | | it is the same size as expected. git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@3145 44740490-163a-0410-bde0-09ae8108e29a
* SAML2: Add algorithm blacklist support.Olav Morken2012-08-024-11/+25
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@3138 44740490-163a-0410-bde0-09ae8108e29a
* SAML2_Utils: Fix for attack against PKCS#1 v1.5 described in a new paper.Olav Morken2012-08-021-3/+7
| | | | | | | | | | | | | See: http://www.nds.rub.de/research/publications/breaking-xml-encryption-pkcs15/ This fix avoids the problems described in that paper by taking two measures: - Require that decrypted contents is at least 4 bytes, since that is the shortest length of an XML element. - Generate a (invalid) symmetric key that is deterministic for a given encrypted key and private key. git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@3132 44740490-163a-0410-bde0-09ae8108e29a
* SAML2: IDPSSODescriptor: Fix AssertionIDRequestService parsing.Olav Morken2012-05-301-1/+1
| | | | | | Thanks to Marco Ferrante for reporting this bug! git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@3107 44740490-163a-0410-bde0-09ae8108e29a
* Add support for the MDUI extension.Olav Morken2012-05-045-0/+437
| | | | | | | | | | | | This patch adds support parsing and generating metadata with the mdui:UIInfo and mdui:DiscoHints elements. Support for generating metadata with the extensions is added to the SAML 2.0 IdP. It should also work through the metadata aggregator. Thanks to Timothy Ace at Synacor, Inc. for implementing this! git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@3088 44740490-163a-0410-bde0-09ae8108e29a
* Add support for validating signatures with the rsa-sha256 algorithm.Olav Morken2012-03-301-0/+38
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@3064 44740490-163a-0410-bde0-09ae8108e29a
* Support for holder-of-key profile.Olav Morken2012-03-293-1/+48
| | | | | | | | | This patch adds support for the holder-of-key profile for both the SAML 2.0 SP and the SAML 2.0 IdP. Thanks to Andreas Mayer for implementing this! git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@3061 44740490-163a-0410-bde0-09ae8108e29a
* SAML2_XML_md_EndpointType: Add support for arbitrary namespace-prefixed ↵Olav Morken2012-03-231-0/+100
| | | | | | attributes. git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@3058 44740490-163a-0410-bde0-09ae8108e29a
* SAML2_HTTPArtifact: $idpmetadata check (issue #481).Andjelko Horvat2012-03-051-0/+3
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@3035 44740490-163a-0410-bde0-09ae8108e29a
* SAML2: Update link to Shibboleth metadata profile.Olav Morken2011-12-211-1/+1
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@3003 44740490-163a-0410-bde0-09ae8108e29a
* SAML2_Utils: Change extractLocalizedStrings to take the namespaceURI and ↵Olav Morken2011-11-034-12/+17
| | | | | | localname instead of an XPath query. git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2972 44740490-163a-0410-bde0-09ae8108e29a
* SAML2_Utils: Change extractStrings to take the namespaceURI and localname ↵Olav Morken2011-11-038-14/+19
| | | | | | instead of an XPath query. git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2971 44740490-163a-0410-bde0-09ae8108e29a
* SAML2_XML_md_Extensions: Fix namespaceURL => namespaceURI.Olav Morken2011-10-281-1/+1
| | | | | | Thanks to Georg Gollmann for reporting this bug. git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2963 44740490-163a-0410-bde0-09ae8108e29a
* SAML2_Utils: Add protection against key oracle attacks when decrypting data.Olav Morken2011-10-271-1/+28
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2953 44740490-163a-0410-bde0-09ae8108e29a
* Do not show detailed exceptions about decryption failures.Olav Morken2011-10-271-1/+29
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2951 44740490-163a-0410-bde0-09ae8108e29a
* SAML2: Add mdrpi:PublicationInfo extension.Olav Morken2011-10-183-0/+119
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2946 44740490-163a-0410-bde0-09ae8108e29a
* SAML2_HTTPPost::send: use SimpleSAML_Utilities::postRedirect (issue 417).Andjelko Horvat2011-07-291-26/+4
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2877 44740490-163a-0410-bde0-09ae8108e29a
* saml/SP: support for samlp:Extensions.Andjelko Horvat2011-07-051-0/+3
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2868 44740490-163a-0410-bde0-09ae8108e29a
* SAML2: Properly initialize DOM elements.Olav Morken2011-07-052-0/+2
| | | | | | | Failure to add the elements to the DOMDocument will result in canonicalization silently failing. git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2865 44740490-163a-0410-bde0-09ae8108e29a
* SAML2_Binding: Only look at the relevant data when detecting the current ↵Olav Morken2011-05-241-4/+4
| | | | | | binding. git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2845 44740490-163a-0410-bde0-09ae8108e29a
* SAML2_Binding: Log more information when unable to determine the current ↵Olav Morken2011-05-241-0/+12
| | | | | | binding. git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2844 44740490-163a-0410-bde0-09ae8108e29a
* SAML2_Binding: Allow the use of a POST request for transmitting artifacts.Olav Morken2011-04-271-0/+2
| | | | | | | | | The specification allows the SAMLart parameter to be sent as POST data. Update the code to allow this. Thanks to Ofer Gigi for locating this bug. git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2819 44740490-163a-0410-bde0-09ae8108e29a
* SAML2_Utils: Don't replace ID in messages and assertions during signing.Olav Morken2011-03-151-1/+1
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2778 44740490-163a-0410-bde0-09ae8108e29a
* SAML2_SOAPClient: Don't throw exception when https key isn't included in ↵Olav Morken2011-03-071-1/+2
| | | | | | metadata. git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2766 44740490-163a-0410-bde0-09ae8108e29a
* SAML2: Sign responses sent using the SOAP binding.Olav Morken2011-03-071-1/+1
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2758 44740490-163a-0410-bde0-09ae8108e29a
* SAML2_SOAP: Log messages received and sent.Olav Morken2011-03-071-0/+2
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2757 44740490-163a-0410-bde0-09ae8108e29a
* SAML2_LogoutRequest: Add support for NotOnOrAfter attribute.Olav Morken2011-03-071-0/+38
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2755 44740490-163a-0410-bde0-09ae8108e29a
* SAML2_HTTPRedirect: Log debug info for redirect.Olav Morken2011-03-071-0/+1
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2753 44740490-163a-0410-bde0-09ae8108e29a
* SAML2_AuthnRequest: Add support for AssertionConsumerServiceIndex.Olav Morken2011-03-071-0/+34
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2751 44740490-163a-0410-bde0-09ae8108e29a
* SAML2_SOAPClient: Add option to disable the inclusion of client certificates.Olav Morken2011-03-071-3/+6
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2750 44740490-163a-0410-bde0-09ae8108e29a
* SAML_Assertion: Support encryption of NameID.Olav Morken2011-03-071-2/+38
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2747 44740490-163a-0410-bde0-09ae8108e29a
* SAML2: Log encryption/decryption of NameID in LogoutRequest and Assertiion.Olav Morken2011-03-072-0/+3
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2746 44740490-163a-0410-bde0-09ae8108e29a
* SAML2_Assertion: Turn AuthnInstant into an indicator about whether the user ↵Olav Morken2011-01-281-5/+6
| | | | | | is authenticated or not. git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2726 44740490-163a-0410-bde0-09ae8108e29a
* Fix for handling empty set of entityattributes. element without childrenAndreas Åkre Solberg2011-01-211-2/+4
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2722 44740490-163a-0410-bde0-09ae8108e29a
* Fix parsing of entity attributesAndreas Åkre Solberg2011-01-201-0/+7
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2721 44740490-163a-0410-bde0-09ae8108e29a
* saml:IdP: Extract extensions from authentication request.Olav Morken2011-01-052-0/+78
| | | | | | Thanks to Andjelko Horvat for implementing this! git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2701 44740490-163a-0410-bde0-09ae8108e29a
* SAML2_XML_Chunk: Properly save localName and namespaceURI attributes.Olav Morken2011-01-051-1/+1
| | | | | | Thanks to Andjelko Horvat for finding and fixing this bug! git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2700 44740490-163a-0410-bde0-09ae8108e29a
* SAML2_Assertion: Separate out SubjectConfirmation from the other attributes.Olav Morken2010-09-201-116/+34
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2554 44740490-163a-0410-bde0-09ae8108e29a
* SAML2_Assertion: Use the new SubjectConfirmation class.Olav Morken2010-09-201-29/+21
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2552 44740490-163a-0410-bde0-09ae8108e29a
* SAML: Add XML classes for NameID, SubjectConfirmation and ↵Olav Morken2010-09-203-0/+333
| | | | | | SubjectConfirmationData. git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2551 44740490-163a-0410-bde0-09ae8108e29a
* Utilities::debugMessage: Allow DOMelement as $message parameter.Olav Morken2010-09-131-4/+2
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2546 44740490-163a-0410-bde0-09ae8108e29a
* Log encrypted and decrypted messages.Olav Morken2010-09-101-0/+7
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2544 44740490-163a-0410-bde0-09ae8108e29a
* Log received XML messages to log file when debug is set to TRUE.Olav Morken2010-09-103-0/+14
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2541 44740490-163a-0410-bde0-09ae8108e29a
* SAML_SOAPClient: Allow received message to be validated based on the SSL ↵Olav Morken2010-09-101-0/+65
| | | | | | certificate. git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2540 44740490-163a-0410-bde0-09ae8108e29a
* SAML2_SOAPClient: Always create stream context.Olav Morken2010-09-101-26/+21
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2539 44740490-163a-0410-bde0-09ae8108e29a
* SAML2_HTTPArtifact: Avoid PHP warnings when receiving ArtifactResponse ↵Olav Morken2010-09-091-0/+5
| | | | | | without data. git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2537 44740490-163a-0410-bde0-09ae8108e29a
* SAML2_ArtifactResponse: Allow empty ArtifactResponse.Olav Morken2010-09-091-3/+5
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2533 44740490-163a-0410-bde0-09ae8108e29a
* SOAPClient: Support for multiple signing certificates.Olav Morken2010-08-101-2/+10
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2512 44740490-163a-0410-bde0-09ae8108e29a
* SOAPClient: Use the $required parameter on Utilities::loadPublicKey.Olav Morken2010-08-101-29/+25
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2511 44740490-163a-0410-bde0-09ae8108e29a
* SAML2_LogoutRequest: Add support for encrypted NameID.Olav Morken2010-08-091-7/+96
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2502 44740490-163a-0410-bde0-09ae8108e29a
* SAML2/LogoutRequest: Add support for multiple SessionIndex entries in the ↵Olav Morken2010-08-091-10/+41
| | | | | | message. git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2493 44740490-163a-0410-bde0-09ae8108e29a
* IdP/Artifact: Use the new datastore to store artifacts.Olav Morken2010-08-091-1/+8
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2491 44740490-163a-0410-bde0-09ae8108e29a
* Add peer certificate validation to SoapClient.Olav Morken2010-08-041-2/+39
| | | | | | | | | | This commit introduces a new idpMetadata parameter to SoapClient::send, which is used to check peer certificate. If this parameter is present, but no certData is set, an Exception will be raised. Thanks to Adam Lantos for providing this patch. git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2475 44740490-163a-0410-bde0-09ae8108e29a
* SAML2/SignedElementHelper: Fix getValidatingCertificates.Olav Morken2010-08-031-3/+7
| | | | | | | | This function did not properly validate signatures containing multiple certificates (as is typical for metadata with certificate chains. The fix is to ignore exceptions during validation. git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2461 44740490-163a-0410-bde0-09ae8108e29a
* SAML2_Binding: Proper check for content type.Olav Morken2010-07-221-6/+8
| | | | | | In r2423, I committed an incomplete fix. This is the proper fix. git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2429 44740490-163a-0410-bde0-09ae8108e29a
* SAML2/SOAPClient: Rename $spMetadata to $srcMetadata.Olav Morken2010-07-221-7/+8
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2426 44740490-163a-0410-bde0-09ae8108e29a
* SAML2/SOAPClient: Allow other message types than SAML2_ArtifactResolve.Olav Morken2010-07-221-7/+7
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2425 44740490-163a-0410-bde0-09ae8108e29a
* SAML2/SOAPClient: Fix logcall.Olav Morken2010-07-221-1/+1
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2424 44740490-163a-0410-bde0-09ae8108e29a
* SAML2/Binding: Handle charset parameter in SOAP Content-Type.Olav Morken2010-07-221-1/+6
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2423 44740490-163a-0410-bde0-09ae8108e29a
* saml: Move Message-class from saml2 to saml module.Olav Morken2010-06-291-1/+1
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2372 44740490-163a-0410-bde0-09ae8108e29a
* <?phpEnrique de la Hoz2010-06-031-3/+177
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | /** * Class representing a SAML 2 assertion. * * @package simpleSAMLphp * @version $Id$ */ class SAML2_Assertion implements SAML2_SignedElement { /** * The identifier of this assertion. * * @var string */ private $id; /** * The issue timestamp of this assertion, as an UNIX timestamp. * * @var int */ private $issueInstant; /** * The entity id of the issuer of this assertion. * * @var string */ private $issuer; /** * The NameId of the subject in the assertion. * * If the NameId is NULL, no subject was included in the assertion. * * @var array|NULL */ private $nameId; /** * The encrypted NameId of the subject. * * If this is not NULL, the NameId needs decryption before it can be accessed. * * @var DOMElement|NULL */ private $encryptedNameId; /** * The encrypted Attributes. * * If this is not NULL, the Attributes needs decryption before it can be accessed. * * @var array|NULL */ private $encryptedAttribute; /** * The earliest time this assertion is valid, as an UNIX timestamp. * * @var int */ private $notBefore; /** * The time this assertion expires, as an UNIX timestamp. * * @var int */ private $notOnOrAfter; /** * The destination URL for this assertion. * * @var string|NULL */ private $destination; /** * The id of the request this assertion is sent as a response to. * * This should be NULL if this isn't a response to a request. * * @var string|NULL */ private $inResponseTo; /** * The set of audiences that are allowed to receive this assertion. * * This is an array of valid service providers. * * If no restrictions on the audience are present, this variable contains NULL. * * @var array|NULL */ private $validAudiences; /** * The session expiration timestamp. * * @var int|NULL */ private $sessionNotOnOrAfter; /** * The session index for this user on the IdP. * * Contains NULL if no session index is present. * * @var string|NULL */ private $sessionIndex; /** * The timestamp the user was authenticated, as an UNIX timestamp. * * @var int */ private $authnInstant; /** * The authentication context for this assertion. * * @var string|NULL */ private $authnContext; /** * The list of AuthenticatingAuthorities for this assertion. * * @var array */ private $AuthenticatingAuthority; /** * The attributes, as an associative array. * * @var array */ private $attributes; /** * The NameFormat used on all attributes. * * If more than one NameFormat is used, this will contain * the unspecified nameformat. * * @var string */ private $nameFormat; /** * The private key we should use to sign the assertion. * * The private key can be NULL, in which case the assertion is sent unsigned. * * @var XMLSecurityKey|NULL */ private $signatureKey; /** * List of certificates that should be included in the assertion. * * @var array */ private $certificates; /** * The data needed to verify the signature. * * @var array|NULL */ private $signatureData; /** * Boolean that indicates if attributes are encrypted in the * assertion or not. * * @var boolean */ private $requiredEncAttributes; /** * Constructor for SAML 2 assertions. * * @param DOMElement|NULL $xml The input assertion. */ public function __construct(DOMElement $xml = NULL) { $this->id = SimpleSAML_Utilities::generateID(); $this->issueInstant = time(); $this->issuer = ''; $this->authnInstant = time(); $this->attributes = array(); $this->nameFormat = SAML2_Const::NAMEFORMAT_UNSPECIFIED; $this->certificates = array(); $this->AuthenticatingAuthority = array(); if ($xml === NULL) { return; } if (!$xml->hasAttribute('ID')) { throw new Exception('Missing ID attribute on SAML assertion.'); } $this->id = $xml->getAttribute('ID'); if ($xml->getAttribute('Version') !== '2.0') { /* Currently a very strict check. */ throw new Exception('Unsupported version: ' . $xml->getAttribute('Version')); } $this->issueInstant = SimpleSAML_Utilities::parseSAML2Time($xml->getAttribute('IssueInstant')); $issuer = SAML2_Utils::xpQuery($xml, './saml_assertion:Issuer'); if (empty($issuer)) { throw new Exception('Missing <saml:Issuer> in assertion.'); } $this->issuer = trim($issuer[0]->textContent); $this->parseSubject($xml); $this->parseConditions($xml); $this->parseAuthnStatement($xml); $this->parseAttributes($xml); $this->parseEncryptedAttributes($xml); $this->parseSignature($xml); } /** * Parse subject in assertion. * * @param DOMElement $xml The assertion XML element. */ private function parseSubject(DOMElement $xml) { $subject = SAML2_Utils::xpQuery($xml, './saml_assertion:Subject'); if (empty($subject)) { /* No Subject node. */ return; } elseif (count($subject) > 1) { throw new Exception('More than one <saml:Subject> in <saml:Assertion>.'); } $subject = $subject[0]; $nameId = SAML2_Utils::xpQuery($subject, './saml_assertion:NameID | ./saml_assertion:EncryptedID/xenc:EncryptedData'); if (empty($nameId)) { throw new Exception('Missing <saml:NameID> or <saml:EncryptedID> in <saml:Subject>.'); } elseif (count($nameId) > 1) { throw new Exception('More than one <saml:NameID> or <saml:EncryptedD> in <saml:Subject>.'); } $nameId = $nameId[0]; if ($nameId->localName === 'EncryptedData') { /* The NameID element is encrypted. */ $this->encryptedNameId = $nameId; } else { $this->nameId = SAML2_Utils::parseNameId($nameId); } $subjectConfirmation = SAML2_Utils::xpQuery($subject, './saml_assertion:SubjectConfirmation'); if (empty($subjectConfirmation)) { throw new Exception('Missing <saml:SubjectConfirmation> in <saml:Subject>.'); } elseif (count($subjectConfirmation) > 1) { throw new Exception('More than one <saml:SubjectConfirmation> in <saml:Subject>.'); } $subjectConfirmation = $subjectConfirmation[0]; if (!$subjectConfirmation->hasAttribute('Method')) { throw new Exception('Missing required attribute "Method" on <saml:SubjectConfirmation>-node.'); } $method = $subjectConfirmation->getAttribute('Method'); if ($method !== SAML2_Const::CM_BEARER) { throw new Exception('Unsupported subject confirmation method: ' . var_export($method, TRUE)); } $confirmationData = SAML2_Utils::xpQuery($subjectConfirmation, './saml_assertion:SubjectConfirmationData'); if (empty($confirmationData)) { return; } elseif (count($confirmationData) > 1) { throw new Exception('More than one <saml:SubjectConfirmationData> in <saml:SubjectConfirmation> is currently unsupported.'); } $confirmationData = $confirmationData[0]; if ($confirmationData->hasAttribute('NotBefore')) { $notBefore = SimpleSAML_Utilities::parseSAML2Time($confirmationData->getAttribute('NotBefore')); if ($this->notBefore === NULL || $this->notBefore < $notBefore) { $this->notBefore = $notBefore; } } if ($confirmationData->hasAttribute('NotOnOrAfter')) { $notOnOrAfter = SimpleSAML_Utilities::parseSAML2Time($confirmationData->getAttribute('NotOnOrAfter')); if ($this->notOnOrAfter === NULL || $this->notOnOrAfter > $notOnOrAfter) { $this->notOnOrAfter = $notOnOrAfter; } } if ($confirmationData->hasAttribute('InResponseTo')) { $this->inResponseTo = $confirmationData->getAttribute('InResponseTo');; } if ($confirmationData->hasAttribute('Recipient')) { $this->destination = $confirmationData->getAttribute('Recipient');; } } /** * Parse conditions in assertion. * * @param DOMElement $xml The assertion XML element. */ private function parseConditions(DOMElement $xml) { $conditions = SAML2_Utils::xpQuery($xml, './saml_assertion:Conditions'); if (empty($conditions)) { /* No <saml:Conditions> node. */ return; } elseif (count($conditions) > 1) { throw new Exception('More than one <saml:Conditions> in <saml:Assertion>.'); } $conditions = $conditions[0]; if ($conditions->hasAttribute('NotBefore')) { $notBefore = SimpleSAML_Utilities::parseSAML2Time($conditions->getAttribute('NotBefore')); if ($this->notBefore === NULL || $this->notBefore < $notBefore) { $this->notBefore = $notBefore; } } if ($conditions->hasAttribute('NotOnOrAfter')) { $notOnOrAfter = SimpleSAML_Utilities::parseSAML2Time($conditions->getAttribute('NotOnOrAfter')); if ($this->notOnOrAfter === NULL || $this->notOnOrAfter > $notOnOrAfter) { $this->notOnOrAfter = $notOnOrAfter; } } for ($node = $conditions->firstChild; $node !== NULL; $node = $node->nextSibling) { if ($node instanceof DOMText) { continue; } if ($node->namespaceURI !== SAML2_Const::NS_SAML) { throw new Exception('Unknown namespace of condition: ' . var_export($node->namespaceURI, TRUE)); } switch ($node->localName) { case 'AudienceRestriction': $audiences = SAML2_Utils::extractStrings($node, './saml_assertion:Audience'); if ($this->validAudiences === NULL) { /* The first (and probably last) AudienceRestriction element. */ $this->validAudiences = $audiences; } else { /* * The set of AudienceRestriction are ANDed together, so we need * the subset that are present in all of them. */ $this->validAudiences = array_intersect($this->validAudiences, $audiences); } break; case 'OneTimeUse': /* Currently ignored. */ break; case 'ProxyRestriction': /* Currently ignored. */ break; default: throw new Exception('Unknown condition: ' . var_export($node->localName, TRUE)); } } } /** * Parse AuthnStatement in assertion. * * @param DOMElement $xml The assertion XML element. */ private function parseAuthnStatement(DOMElement $xml) { $as = SAML2_Utils::xpQuery($xml, './saml_assertion:AuthnStatement'); if (empty($as)) { return; } elseif (count($as) > 1) { throw new Exception('More that one <saml:AuthnStatement> in <saml:Assertion> not supported.'); } $as = $as[0]; $this->authnStatement = array(); if (!$as->hasAttribute('AuthnInstant')) { throw new Exception('Missing required AuthnInstant attribute on <saml:AuthnStatement>.'); } $this->authnInstant = SimpleSAML_Utilities::parseSAML2Time($as->getAttribute('AuthnInstant')); if ($as->hasAttribute('SessionNotOnOrAfter')) { $this->sessionNotOnOrAfter = SimpleSAML_Utilities::parseSAML2Time($as->getAttribute('SessionNotOnOrAfter')); } if ($as->hasAttribute('SessionIndex')) { $this->sessionIndex = $as->getAttribute('SessionIndex'); } $ac = SAML2_Utils::xpQuery($as, './saml_assertion:AuthnContext'); if (empty($ac)) { throw new Exception('Missing required <saml:AuthnContext> in <saml:AuthnStatement>.'); } elseif (count($ac) > 1) { throw new Exception('More than one <saml:AuthnContext> in <saml:AuthnStatement>.'); } $ac = $ac[0]; $accr = SAML2_Utils::xpQuery($ac, './saml_assertion:AuthnContextClassRef'); if (empty($accr)) { $acdr = SAML2_Utils::xpQuery($ac, './saml_assertion:AuthnContextDeclRef'); if (empty($acdr)) { throw new Exception('Neither <saml:AuthnContextClassRef> nor <saml:AuthnContextDeclRef> found in <saml:AuthnContext>.'); } elseif (count($accr) > 1) { throw new Exception('More than one <saml:AuthnContextDeclRef> in <saml:AuthnContext>.'); } $this->authnContext = trim($acdr[0]->textContent); } elseif (count($accr) > 1) { throw new Exception('More than one <saml:AuthnContextClassRef> in <saml:AuthnContext>.'); } else { $this->authnContext = trim($accr[0]->textContent); } $this->AuthenticatingAuthority = SAML2_Utils::extractStrings($ac, './saml_assertion:AuthenticatingAuthority'); } /** * Parse attribute statements in assertion. * * @param DOMElement $xml The XML element with the assertion. */ private function parseAttributes(DOMElement $xml) { $firstAttribute = TRUE; $attributes = SAML2_Utils::xpQuery($xml, './saml_assertion:AttributeStatement/saml_assertion:Attribute'); foreach ($attributes as $attribute) { if (!$attribute->hasAttribute('Name')) { throw new Exception('Missing name on <saml:Attribute> element.'); } $name = $attribute->getAttribute('Name'); if ($attribute->hasAttribute('NameFormat')) { $nameFormat = $attribute->getAttribute('NameFormat'); } else { $nameFormat = SAML2_Const::NAMEFORMAT_UNSPECIFIED; } if ($firstAttribute) { $this->nameFormat = $nameFormat; $firstAttribute = FALSE; } else { if ($this->nameFormat !== $nameFormat) { $this->nameFormat = SAML2_Const::NAMEFORMAT_UNSPECIFIED; } } if (!array_key_exists($name, $this->attributes)) { $this->attributes[$name] = array(); } $values = SAML2_Utils::xpQuery($attribute, './saml_assertion:AttributeValue'); foreach ($values as $value) { $this->attributes[$name][] = trim($value->textContent); } } } /** * Parse encrypted attribute statements in assertion. * * @param DOMElement $xml The XML element with the assertion. */ private function parseEncryptedAttributes(DOMElement $xml) { $this->encryptedAttribute = SAML2_Utils::xpQuery($xml, './saml_assertion:AttributeStatement/saml_assertion:EncryptedAttribute'); } /** * Parse signature on assertion. * * @param DOMElement $xml The assertion XML element. */ private function parseSignature(DOMElement $xml) { /* Validate the signature element of the message. */ $sig = SAML2_Utils::validateElement($xml); if ($sig !== FALSE) { $this->certificates = $sig['Certificates']; $this->signatureData = $sig; } } /** * Validate this assertion against a public key. * * If no signature was present on the assertion, we will return FALSE. * Otherwise, TRUE will be returned. An exception is thrown if the * signature validation fails. * * @param XMLSecurityKey $key The key we should check against. * @return boolean TRUE if successful, FALSE if it is unsigned. */ public function validate(XMLSecurityKey $key) { assert('$key->type === XMLSecurityKey::RSA_SHA1'); if ($this->signatureData === NULL) { return FALSE; } SAML2_Utils::validateSignature($this->signatureData, $key); return TRUE; } /** * Retrieve the identifier of this assertion. * * @return string The identifier of this assertion. */ public function getId() { return $this->id; } /** * Set the identifier of this assertion. * * @param string $id The new identifier of this assertion. */ public function setId($id) { assert('is_string($id)'); $this->id = $id; } /** * Retrieve the issue timestamp of this assertion. * * @return int The issue timestamp of this assertion, as an UNIX timestamp. */ public function getIssueInstant() { return $this->issueInstant; } /** * Set the issue timestamp of this assertion. * * @param int $issueInstant The new issue timestamp of this assertion, as an UNIX timestamp. */ public function setIssueInstant($issueInstant) { assert('is_int($issueInstant)'); $this->issueInstant = $issueInstant; } /** * Retrieve the issuer if this assertion. * * @return string The issuer of this assertion. */ public function getIssuer() { return $this->issuer; } /** * Set the issuer of this message. * * @param string $issuer The new issuer of this assertion. */ public function setIssuer($issuer) { assert('is_string($issuer)'); $this->issuer = $issuer; } /** * Retrieve the NameId of the subject in the assertion. * * The returned NameId is in the format used by SAML2_Utils::addNameId(). * * @see SAML2_Utils::addNameId() * @return array|NULL The name identifier of the assertion. */ public function getNameId() { if ($this->encryptedNameId !== NULL) { throw new Exception('Attempted to retrieve encrypted NameID without decrypting it first.'); } return $this->nameId; } /** * Set the NameId of the subject in the assertion. * * The NameId must be in the format accepted by SAML2_Utils::addNameId(). * * @see SAML2_Utils::addNameId() * @param array|NULL $nameId The name identifier of the assertion. */ public function setNameId($nameId) { assert('is_array($nameId) || is_null($nameId)'); $this->nameId = $nameId; } /** * Check whether the NameId is encrypted. * * @return TRUE if the NameId is encrypted, FALSE if not. */ public function isNameIdEncrypted() { if ($this->encryptedNameId !== NULL) { return TRUE; } return FALSE; } /** * Decrypt the NameId of the subject in the assertion. * * @param XMLSecurityKey $key The decryption key. */ public function decryptNameId(XMLSecurityKey $key) { if ($this->encryptedNameId === NULL) { /* No NameID to decrypt. */ return; } $nameId = SAML2_Utils::decryptElement($this->encryptedNameId, $key); $this->nameId = SAML2_Utils::parseNameId($nameId); $this->encryptedNameId = NULL; } public function decryptAttributes($key){ if($this->encryptedAttribute === null){ return; } $attributes = $this->encryptedAttribute; foreach ($attributes as $attributeEnc) { /*Decrypt node <EncryptedAttribute>*/ $attribute = SAML2_Utils::decryptElement($attributeEnc->getElementsByTagName('EncryptedData')->item(0), $key); if (!$attribute->hasAttribute('Name')) { throw new Exception('Missing name on <saml:Attribute> element.'); } $name = $attribute->getAttribute('Name'); if ($attribute->hasAttribute('NameFormat')) { $nameFormat = $attribute->getAttribute('NameFormat'); } else { $nameFormat = SAML2_Const::NAMEFORMAT_UNSPECIFIED; } if ($firstAttribute) { $this->nameFormat = $nameFormat; $firstAttribute = FALSE; } else { if ($this->nameFormat !== $nameFormat) { $this->nameFormat = SAML2_Const::NAMEFORMAT_UNSPECIFIED; } } if (!array_key_exists($name, $this->attributes)) { $this->attributes[$name] = array(); } $values = SAML2_Utils::xpQuery($attribute, './saml_assertion:AttributeValue'); foreach ($values as $value) { $this->attributes[$name][] = trim($value->textContent); } } } /** * Retrieve the earliest timestamp this assertion is valid. * * This function returns NULL if there are no restrictions on how early the * assertion can be used. * * @return int|NULL The earliest timestamp this assertion is valid. */ public function getNotBefore() { return $this->notBefore; } /** * Set the earliest timestamp this assertion can be used. * * Set this to NULL if no limit is required. * * @param int|NULL $notBefore The earliest timestamp this assertion is valid. */ public function setNotBefore($notBefore) { assert('is_int($notBefore) || is_null($notBefore)'); $this->notBefore = $notBefore; } /** * Retrieve the expiration timestamp of this assertion. * * This function returns NULL if there are no restrictions on how * late the assertion can be used. * * @return int|NULL The latest timestamp this assertion is valid. */ public function getNotOnOrAfter() { return $this->notOnOrAfter; } /** * Set the expiration timestamp of this assertion. * * Set this to NULL if no limit is required. * * @param int|NULL $notOnOrAfter The latest timestamp this assertion is valid. */ public function setNotOnOrAfter($notOnOrAfter) { assert('is_int($notOnOrAfter) || is_null($notOnOrAfter)'); $this->notOnOrAfter = $notOnOrAfter; } /** * Retrieve the destination URL of this assertion. * * This function returns NULL if there are no restrictions on which URL can * receive the assertion. * * @return string|NULL The destination URL of this assertion. */ public function getDestination() { return $this->destination; } /** * Set the destination URL of this assertion. * * @return string|NULL The destination URL of this assertion. */ public function setDestination($destination) { assert('is_string($destination) || is_null($destination)'); $this->destination = $destination; } /** * Set $EncryptedAttributes if attributes will send encrypted * * @param boolean $ea TRUE to encrypt attributes in the assertion. */ public function setEncryptedAttributes($ea) { $this->requiredEncAttributes = $ea; } /** * Retrieve the request this assertion is sent in response to. * * Can be NULL, in which case this assertion isn't sent in response to a specific request. * * @return string|NULL The id of the request this assertion is sent in response to. */ public function getInResponseTo() { return $this->inResponseTo; } /** * Set the request this assertion is sent in response to. * * Can be set to NULL, in which case this assertion isn't sent in response to a specific request. * * @param string|NULL $inResponseTo The id of the request this assertion is sent in response to. */ public function setInResponseTo($inResponseTo) { assert('is_string($inResponseTo) || is_null($inResponseTo)'); $this->inResponseTo = $inResponseTo; } /** * Retrieve the audiences that are allowed to receive this assertion. * * This may be NULL, in which case all audiences are allowed. * * @return array|NULL The allowed audiences. */ public function getValidAudiences() { return $this->validAudiences; } /** * Set the audiences that are allowed to receive this assertion. * * This may be NULL, in which case all audiences are allowed. * * @param array|NULL $validAudiences The allowed audiences. */ public function setValidAudiences(array $validAudiences = NULL) { $this->validAudiences = $validAudiences; } /** * Retrieve the AuthnInstant of the assertion. * * @return int The timestamp the user was authenticated. */ public function getAuthnInstant() { return $this->authnInstant; } /** * Set the AuthnInstant of the assertion. * * @param int $authnInstant The timestamp the user was authenticated. */ public function setAuthnInstant($authnInstant) { assert('is_int($authnInstant)'); $this->authnInstant = $authnInstant; } /** * Retrieve the session expiration timestamp. * * This function returns NULL if there are no restrictions on the * session lifetime. * * @return int|NULL The latest timestamp this session is valid. */ public function getSessionNotOnOrAfter() { return $this->sessionNotOnOrAfter; } /** * Set the session expiration timestamp. * * Set this to NULL if no limit is required. * * @param int|NULL $sessionLifetime The latest timestamp this session is valid. */ public function setSessionNotOnOrAfter($sessionNotOnOrAfter) { assert('is_int($sessionNotOnOrAfter) || is_null($sessionNotOnOrAfter)'); $this->sessionNotOnOrAfter = $sessionNotOnOrAfter; } /** * Retrieve the session index of the user at the IdP. * * @return string|NULL The session index of the user at the IdP. */ public function getSessionIndex() { return $this->sessionIndex; } /** * Set the session index of the user at the IdP. * * Note that the authentication context must be set before the * session index can be inluded in the assertion. * * @param string|NULL $sessionIndex The session index of the user at the IdP. */ public function setSessionIndex($sessionIndex) { assert('is_string($sessionIndex) || is_null($sessionIndex)'); $this->sessionIndex = $sessionIndex; } /** * Retrieve the authentication method used to authenticate the user. * * This will return NULL if no authentication statement was * included in the assertion. * * @return string|NULL The authentication method. */ public function getAuthnContext() { return $this->authnContext; } /** * Set the authentication method used to authenticate the user. * * If this is set to NULL, no authentication statement will be * included in the assertion. The default is NULL. * * @param string|NULL $authnContext The authentication method. */ public function setAuthnContext($authnContext) { assert('is_string($authnContext) || is_null($authnContext)'); $this->authnContext = $authnContext; } /** * Retrieve the AuthenticatingAuthority. * * * @return array */ public function getAuthenticatingAuthority() { return $this->AuthenticatingAuthority; } /** * Set the AuthenticatingAuthority * * * @param array. */ public function setAuthenticatingAuthority($AuthenticatingAuthority) { $this->AuthenticatingAuthority = $AuthenticatingAuthority; } /** * Retrieve all attributes. * * @return array All attributes, as an associative array. */ public function getAttributes() { return $this->attributes; } /** * Replace all attributes. * * @param array $attributes All new attributes, as an associative array. */ public function setAttributes(array $attributes) { $this->attributes = $attributes; } /** * Retrieve the NameFormat used on all attributes. * * If more than one NameFormat is used in the received attributes, this * returns the unspecified NameFormat. * * @return string The NameFormat used on all attributes. */ public function getAttributeNameFormat() { return $this->nameFormat; } /** * Set the NameFormat used on all attributes. * * @param string $nameFormat The NameFormat used on all attributes. */ public function setAttributeNameFormat($nameFormat) { assert('is_string($nameFormat)'); $this->nameFormat = $nameFormat; } /** * Retrieve the private key we should use to sign the assertion. * * @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 assertion. * * If the key is NULL, the assertion will be sent unsigned. * * @param XMLSecurityKey|NULL $key */ public function setSignatureKey(XMLsecurityKey $signatureKey = NULL) { $this->signatureKey = $signatureKey; } /** * Return the key we should use to encrypt the assertion. * * @return XMLSecurityKey|NULL The key, or NULL if no key is specified.. * */ public function getEncryptionKey() { return $this->encryptionKey; } /** * Set the private key we should use to encrypt the attributes. * * @param XMLSecurityKey|NULL $key */ public function setEncryptionKey(XMLSecurityKey $Key = NULL) { $this->encryptionKey = $Key; } /** * Set the certificates that should be included in the assertion. * * 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 assertion. * * @return array An array of certificates. */ public function getCertificates() { return $this->certificates; } /** * Convert this assertion to an XML element. * * @param DOMNode|NULL $parentElement The DOM node the assertion should be created in. * @return DOMElement This assertion. */ public function toXML(DOMNode $parentElement = NULL) { if ($parentElement === NULL) { $document = new DOMDocument(); $parentElement = $document; } else { $document = $parentElement->ownerDocument; } $root = $document->createElementNS(SAML2_Const::NS_SAML, 'saml:' . 'Assertion'); $parentElement->appendChild($root); /* Ugly hack to add another namespace declaration to the root element. */ $root->setAttributeNS(SAML2_Const::NS_SAMLP, 'samlp:tmp', 'tmp'); $root->removeAttributeNS(SAML2_Const::NS_SAMLP, 'tmp'); $root->setAttributeNS(SAML2_Const::NS_XSI, 'xsi:tmp', 'tmp'); $root->removeAttributeNS(SAML2_Const::NS_XSI, 'tmp'); $root->setAttributeNS(SAML2_Const::NS_XS, 'xs:tmp', 'tmp'); $root->removeAttributeNS(SAML2_Const::NS_XS, 'tmp'); $root->setAttribute('ID', $this->id); $root->setAttribute('Version', '2.0'); $root->setAttribute('IssueInstant', gmdate('Y-m-d\TH:i:s\Z', $this->issueInstant)); $issuer = SAML2_Utils::addString($root, SAML2_Const::NS_SAML, 'saml:Issuer', $this->issuer); $this->addSubject($root); $this->addConditions($root); $this->addAuthnStatement($root); if($this->requiredEncAttributes == false) $this->addAttributeStatement($root); else $this->addEncryptedAttributeStatement($root); if ($this->signatureKey !== NULL) { SAML2_Utils::insertSignature($this->signatureKey, $this->certificates, $root, $issuer->nextSibling); } return $root; } /** * Add a Subject-node to the assertion. * * @param DOMElement $root The assertion element we should add the subject to. */ private function addSubject(DOMElement $root) { if ($this->nameId === NULL) { /* We don't have anything to create a Subject node for. */ return; } $subject = $root->ownerDocument->createElementNS(SAML2_Const::NS_SAML, 'saml:Subject'); $root->appendChild($subject); SAML2_Utils::addNameId($subject, $this->nameId); $sc = $root->ownerDocument->createElementNS(SAML2_Const::NS_SAML, 'saml:SubjectConfirmation'); $subject->appendChild($sc); $sc->setAttribute('Method', SAML2_Const::CM_BEARER); $scd = $root->ownerDocument->createElementNS(SAML2_Const::NS_SAML, 'saml:SubjectConfirmationData'); $sc->appendChild($scd); if ($this->notOnOrAfter !== NULL) { $scd->setAttribute('NotOnOrAfter', gmdate('Y-m-d\TH:i:s\Z', $this->notOnOrAfter)); } if ($this->destination !== NULL) { $scd->setAttribute('Recipient', $this->destination); } if ($this->inResponseTo !== NULL) { $scd->setAttribute('InResponseTo', $this->inResponseTo); } } /** * Add a Conditions-node to the assertion. * * @param DOMElement $root The assertion element we should add the conditions to. */ private function addConditions(DOMElement $root) { $document = $root->ownerDocument; $conditions = $document->createElementNS(SAML2_Const::NS_SAML, 'saml:Conditions'); $root->appendChild($conditions); if ($this->notBefore !== NULL) { $conditions->setAttribute('NotBefore', gmdate('Y-m-d\TH:i:s\Z', $this->notBefore)); } if ($this->notOnOrAfter !== NULL) { $conditions->setAttribute('NotOnOrAfter', gmdate('Y-m-d\TH:i:s\Z', $this->notOnOrAfter)); } if ($this->validAudiences !== NULL) { $ar = $document->createElementNS(SAML2_Const::NS_SAML, 'saml:AudienceRestriction'); $conditions->appendChild($ar); SAML2_Utils::addStrings($ar, SAML2_Const::NS_SAML, 'saml:Audience', FALSE, $this->validAudiences); } } /** * Add a AuthnStatement-node to the assertion. * * @param DOMElement $root The assertion element we should add the authentication statement to. */ private function addAuthnStatement(DOMElement $root) { if ($this->authnContext === NULL) { /* No authentication context => no authentication statement. */ return; } $document = $root->ownerDocument; $as = $document->createElementNS(SAML2_Const::NS_SAML, 'saml:AuthnStatement'); $root->appendChild($as); $as->setAttribute('AuthnInstant', gmdate('Y-m-d\TH:i:s\Z', $this->authnInstant)); if ($this->sessionNotOnOrAfter !== NULL) { $as->setAttribute('SessionNotOnOrAfter', gmdate('Y-m-d\TH:i:s\Z', $this->sessionNotOnOrAfter)); } if ($this->sessionIndex !== NULL) { $as->setAttribute('SessionIndex', $this->sessionIndex); } $ac = $document->createElementNS(SAML2_Const::NS_SAML, 'saml:AuthnContext'); $as->appendChild($ac); SAML2_Utils::addString($ac, SAML2_Const::NS_SAML, 'saml:AuthnContextClassRef', $this->authnContext); SAML2_Utils::addStrings($ac, SAML2_Const::NS_SAML, 'saml:AuthenticatingAuthority', false, $this->AuthenticatingAuthority); } /** * Add an AttributeStatement-node to the assertion. * * @param DOMElement $root The assertion element we should add the subject to. */ private function addAttributeStatement(DOMElement $root) { if (empty($this->attributes)) { return; } $document = $root->ownerDocument; $attributeStatement = $document->createElementNS(SAML2_Const::NS_SAML, 'saml:AttributeStatement'); $root->appendChild($attributeStatement); foreach ($this->attributes as $name => $values) { $attribute = $document->createElementNS(SAML2_Const::NS_SAML, 'saml:Attribute'); $attributeStatement->appendChild($attribute); $attribute->setAttribute('Name', $name); if ($this->nameFormat !== SAML2_Const::NAMEFORMAT_UNSPECIFIED) { $attribute->setAttribute('NameFormat', $this->nameFormat); } foreach ($values as $value) { if (is_string($value)) { $type = 'xs:string'; } elseif (is_int($value)) { $type = 'xs:integer'; } else { $type = NULL; } $attributeValue = $document->createElementNS(SAML2_Const::NS_SAML, 'saml:AttributeValue'); $attribute->appendChild($attributeValue); if ($type !== NULL) { $attributeValue->setAttributeNS(SAML2_Const::NS_XSI, 'xsi:type', $type); } if ($value instanceof DOMNodeList) { for ($i = 0; $i < $value->length; $i++) { $node = $document->importNode($value->item($i), TRUE); $attributeValue->appendChild($node); } } else { $attributeValue->appendChild($document->createTextNode($value)); } } } } /** * Add an EncryptedAttribute Statement-node to the assertion. * * @param DOMElement $root The assertion element we should add the Encrypted Attribute Statement to. */ private function addEncryptedAttributeStatement(DOMElement $root) { if ($this->requiredEncAttributes == FALSE) return; $document = $root->ownerDocument; $attributeStatement = $document->createElementNS(SAML2_Const::NS_SAML, 'saml:AttributeStatement'); $root->appendChild($attributeStatement); foreach ($this->attributes as $name => $values) { $document2 = new DOMDocument(); $attribute = $document2->createElementNS(SAML2_Const::NS_SAML, 'saml:Attribute'); $attribute->setAttribute('Name', $name); $document2->appendChild($attribute); if ($this->nameFormat !== SAML2_Const::NAMEFORMAT_UNSPECIFIED) { $attribute->setAttribute('NameFormat', $this->nameFormat); } foreach ($values as $value) { if (is_string($value)) { $type = 'xs:string'; } elseif (is_int($value)) { $type = 'xs:integer'; } else { $type = NULL; } $attributeValue = $document2->createElementNS(SAML2_Const::NS_SAML, 'saml:AttributeValue'); $attribute->appendChild($attributeValue); if ($type !== NULL) { $attributeValue->setAttributeNS(SAML2_Const::NS_XSI, 'xsi:type', $type); } if ($value instanceof DOMNodeList) { for ($i = 0; $i < $value->length; $i++) { $node = $document2->importNode($value->item($i), TRUE); $attributeValue->appendChild($node); } } else { $attributeValue->appendChild($document2->createTextNode($value)); } } /*Once the attribute nodes are built, the are encrypted*/ $EncAssert = new XMLSecEnc(); $EncAssert->setNode($document2->documentElement); $EncAssert->type = 'http://www.w3.org/2001/04/xmlenc#Element'; /* * Attributes are encrypted with a session key and this one with * $EncryptionKey */ $symmetricKey = new XMLSecurityKey(XMLSecurityKey::AES256_CBC); $symmetricKey->generateSessionKey(); $EncAssert->encryptKey($this->encryptionKey, $symmetricKey); $EncrNode = $EncAssert->encryptNode($symmetricKey); $EncAttribute = $document->createElementNS(SAML2_Const::NS_SAML, 'saml:EncryptedAttribute'); $attributeStatement->appendChild($EncAttribute); $n = $document->importNode($EncrNode,true); $EncAttribute->appendChild($n); } } } git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2341 44740490-163a-0410-bde0-09ae8108e29a
* Artifact support for the SP.Olav Morken2010-05-193-4/+196
| | | | | | | | | | This patch adds the necessary code for receiving authentication responses using the HTTP-Artifact binding. Thanks to Shoaib Ali and Bill Young from New Zealand for spending the time to implement this. git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2305 44740490-163a-0410-bde0-09ae8108e29a
* SAML2: Add createKeyDescriptor() helper-function.Olav Morken2010-05-111-0/+25
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2291 44740490-163a-0410-bde0-09ae8108e29a
* Scoping for authsources. Includes support for IDPList, ProxyCount,Mads Freek Petersen2010-05-043-13/+107
| | | | | | | AuthenticatingAuthority and RequesterID. git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2278 44740490-163a-0410-bde0-09ae8108e29a
* SAML2/Binding: Fix misspelling of array_key_exists.Olav Morken2010-04-271-1/+1
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2272 44740490-163a-0410-bde0-09ae8108e29a
* SAML2/LogoutRequest: Fix incorrect assertion on setSessionIndex().Olav Morken2010-04-271-1/+1
| | | | | | The $sesionIndex parameter is allowed to be NULL here. git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2271 44740490-163a-0410-bde0-09ae8108e29a
* SAML2: Metadata XML classes.Olav Morken2010-04-2130-0/+3256
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2261 44740490-163a-0410-bde0-09ae8108e29a
* SAML2_Utils: Allow DOMDocument as parameter for xpQuery().Olav Morken2010-04-211-2/+8
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2257 44740490-163a-0410-bde0-09ae8108e29a
* SAML2_Utils: add copyElement function.Olav Morken2010-04-211-0/+44
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2256 44740490-163a-0410-bde0-09ae8108e29a
* SAML2_Utils: Handle signatures of the DOMDocument element.Olav Morken2010-04-201-0/+4
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2252 44740490-163a-0410-bde0-09ae8108e29a
* SAML2_Utils: Add the new addStrings()-function.Olav Morken2010-03-052-6/+28
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2201 44740490-163a-0410-bde0-09ae8108e29a
* SAML2_Utils: Add the new addString()-function.Olav Morken2010-03-057-26/+32
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2200 44740490-163a-0410-bde0-09ae8108e29a
* SAML2_Utils: Add the new extractStrings()-function.Olav Morken2010-03-052-4/+20
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2199 44740490-163a-0410-bde0-09ae8108e29a
* SAML2_Utils: Add the new extractLocalizedStrings()-function.Olav Morken2010-03-051-2/+24
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2198 44740490-163a-0410-bde0-09ae8108e29a
* SAML2: Metadata namespace.Olav Morken2010-03-052-0/+6
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2197 44740490-163a-0410-bde0-09ae8108e29a
* SAML2_Assertion: Support AuthnInstant.Olav Morken2010-01-261-1/+34
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2135 44740490-163a-0410-bde0-09ae8108e29a
* SAML2_Const: Add partial logout status code.Olav Morken2010-01-221-0/+5
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2126 44740490-163a-0410-bde0-09ae8108e29a
* Add support for sending responses with the HTTP-Artifact binding.Olav Morken2010-01-158-0/+271
| | | | | | | | | | | | | This patch implements support for sending responses to authentication requests via the HTTP-Artifact binding. To enable, add 'saml20.sendartifact' => TRUE in saml20-idp-hosted metadata. The IdP should then send HTTP-Artifact responses to SPs that request it. Note that this requires a working memcache server. Thanks to Danny Bollaert for implementing support for this. git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@2121 44740490-163a-0410-bde0-09ae8108e29a
* SAML2_AuthnRequest: Support for RequestedAuthnContext.Olav Morken2009-11-121-1/+70
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@1983 44740490-163a-0410-bde0-09ae8108e29a
* SAML2_AuthnRequest: Move Scoping-element to after NameIDPolicy as per spec.Olav Morken2009-11-121-12/+12
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@1982 44740490-163a-0410-bde0-09ae8108e29a
* lib/SAML2: Fix up changed namespace prefix on NameID element.Olav Morken2009-10-261-1/+1
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@1897 44740490-163a-0410-bde0-09ae8108e29a
* SAML2_Assertion: Support for decryption of encrypted NameId.Olav Morken2009-10-011-4/+58
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@1808 44740490-163a-0410-bde0-09ae8108e29a
* SAML2_EncryptedAssertion: Use SAML2_Utils::decryptElement().Olav Morken2009-10-011-68/+1
| | | | git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@1807 44740490-163a-0410-bde0-09ae8108e29a