summaryrefslogtreecommitdiff
path: root/tests
Commit message (Collapse)AuthorAgeFilesLines
* Support arbitrary entity attributesIvan Kanakarakis2020-07-112-23/+73
| | | | | | | | | | | | | | | | | | Introduce new configuration option `entity_attributes` that defines a list of dictionaries each of which represents an <Attribute> element. Each dicrionary has fields for the NameFormat, the Name, the FriendName and a list of strings that are used to create <AttributeValue> elements, each with the string as the text node. "entity_attributes": [ { "name_format": "urn:oasis:names:tc:SAML:2.0:attrname-format:uri", "name": "urn:oasis:names:tc:SAML:profiles:subject-id:req", # "friendly_name" is not set "values": ["any"], }, ] Signed-off-by: Ivan Kanakarakis <ivan.kanak@gmail.com>
* Differentiate between metadata NameIDFormat and AuthnRequest NameIDPolicy FormatIvan Kanakarakis2020-07-103-19/+31
| | | | | | | | | | | | | | | | | | | | | | | | | | | The `name_id_format` configuration option is used to define 1. the value of the `<NameIDFormat>` metadata element 2. and the value of the `<NameIDPolicy>` `Format` attribute in an `AuthnRequest` The configuration option to set what the value of `<NameIDFormat>` element is in the metadata should be different from the configuration option to specify what should be requested in an `AuthnRequest` through the `<NameIDPolicy Format="...">` attribute. Introduce a new option (`name_id_policy_format`), or use the same name but scoped in a specific section for metadata and AuthnRequest. On the side of this, pysaml2 defaults to _transient_ as the `<NameIDPolicy Format="...">` attribute value. To omit requesting a value for the `<NameIDPolicy Format="">` attribute the value `"None"` (a string) must be set in the configuration. This is unintuitive. It is better to be explicit and set transient to request a transient NameID, than not setting a value and requesting transient by default. If no value is set, no specific `<NameIDPolicy Format="...">` should be requested. - Refactor the name_id_format usage - Add name_id_policy_format configuration option - Remove the "None" convention value Signed-off-by: Ivan Kanakarakis <ivan.kanak@gmail.com>
* Add test for generation of signed metadataNate Otto2020-07-041-2/+17
|
* Fix testsIvan Kanakarakis2020-06-051-27/+20
| | | | Signed-off-by: Ivan Kanakarakis <ivan.kanak@gmail.com>
* Add requested_attributes paramNikos Sklikas2020-05-282-3/+39
| | | | Add requested_attributes param to create_authn_request
* Fix xmlsec1 --id-attr optionIvan Kanakarakis2020-05-265-76/+43
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | We need to know _the name of the attribute_ that represents the identifier of the node that is being signed, or encrypted, or verified. We guess the name -by trying `ID`, `Id` and `id`- and pass it to `xmlsec1` using the `--id-attr` command line option. _Why is this needed?_ Shouldn't the attribute names be specified by the corresponding specifications? Let's look into the specs to find out. * saml-core: * `StatusResponseType` uses `ID` * `RequestAbstractType` uses `ID` * `Assertion` uses `ID` * xmldsig-core: * `SignatureType` uses `Id` * xmlenc-core: * `EncryptedType` uses `Id` So, the answer is _yes_ - the attribute names are defined and, instead of guessing, we should be passing in the id-attribute names as defined by the specs. _Note_: But, do we even need to do this? If the names are standardized, why do we bother with this? In fact, the manual for `xmlsec1` explicitly says that --id-attr[:<attr-name>] [<node-namespace-uri>:]<node-name> adds attributes <attr-name> (default value "id") from all nodes with<node-name> and namespace <node-namespace-uri> to the list of known ID attributes; this is a hack and if you can use DTD or schema to declare ID attributes instead (see "--dtd-file" option), I don't know what else might be broken in your application when you use this hack However, it seems that `xmlsec1` by default will only look for an attribute with name `id`. The right way to solve this is to pass in a DTD file. Then, `xmlsec1` will understand that it needs to look up a different attribute name. Unfortunately, there are no official DTDs (or even unofficial, to my knowledge) for SAML. The SAML specifications instead provide XSD files. Even though `xmlsec1` mentions _schema_, there doesn't seem to be a way to pass in an XSD file. So, we have to resort to this "hack". When we sign a document, we need to point to the node that will be signed. The nodes that we are signing are always SAML nodes (Assertion, StatusResponseType (Response, etc), RequestAbstractType (AuthnRequest, etc)). All SAML nodes that will be signed use `ID` as the attribute name. So, in order to sign and verify a signature, we need to pass in `ID`. When encrypting a document, we need to point to the node whose content will be encrypted. Currently, we use XPath to point to that node, without the use of an id. But, we could be using an identifier to locate the node, and if we did so, we would still be using `ID`. When decrypting a document, we need to point to the node that contains the encrypted data. This is where things change. Since the SAML node itself is encrypted we cannot point to an `ID` attribute, as we did in the other cases. Instead, it is specified that a node named `EncryptedData` exists, that may have an `Id` attribute. This is where we want to point to. So, we need to use `Id`. Signed-off-by: Ivan Kanakarakis <ivan.kanak@gmail.com>
* Remove logger configurationIvan Kanakarakis2020-05-121-47/+2
| | | | | | | | | | | | | | | | | | | | ``` ************* Module saml2.config src/saml2/config.py:464:23: E1135: Value '_logconf' doesn't support membership test (unsupported-membership-test) src/saml2/config.py:466:27: E1136: Value '_logconf' is unsubscriptable (unsubscriptable-object) src/saml2/config.py:481:50: E1136: Value '_logconf' is unsubscriptable (unsubscriptable-object) src/saml2/config.py:486:22: E1120: No value for argument 'filename' in constructor call (no-value-for-parameter) src/saml2/config.py:488:23: E1135: Value '_logconf' doesn't support membership test (unsupported-membership-test) src/saml2/config.py:489:42: E1136: Value '_logconf' is unsubscriptable (unsubscriptable-object) src/saml2/config.py:505:43: E1136: Value '_logconf' is unsubscriptable (unsubscriptable-object) src/saml2/config.py:552:19: E1136: Value 'self.virtual_organization' is unsubscriptable (unsubscriptable-object) ``` this seems right; the operations upon the Logger object do not make sense. There is no need to "fix" this, we just remove the relevant code. We should come back to this and refactor how the logger is configured for the library. Signed-off-by: Ivan Kanakarakis <ivan.kanak@gmail.com>
* Fix compile warningsIvan Kanakarakis2020-02-101-7/+7
| | | | | | | | | Test for compile warning using: find src/ -iname '*.py' | xargs -P 4 -I{} python -Wall -m py_compile {} find tests/ -iname '*.py' | xargs -P 4 -I{} python -Wall -m py_compile {} Signed-off-by: Ivan Kanakarakis <ivan.kanak@gmail.com>
* Update test metadata expiration dateJohn Paraskevopoulos2020-02-101-3/+3
| | | | Signed-off-by: Ivan Kanakarakis <ivan.kanak@gmail.com>
* Fix XML Signature Wrapping (XSW) vulnerabilitiesIvan Kanakarakis2020-01-092-0/+50
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | PySAML2 did not check that the signature in a SAML document is enveloped and thus XML signature wrapping (XSW) was effective. The signature information and the node/object that is signed can be in different places and thus the signature verification will succeed, but the wrong data will be used. This specifically affects the verification of assertions that have been signed. This was assigned CVE-2020-5390 Thanks to Alexey Sintsov and Yuri Goltsev from HERE Technologies to report this. + + + + + + + + In more detail: libxml2 follows the xmldsig-core specification. The xmldsig specification is way too general. saml-core reuses the xmldsig specification, but constrains it to use of specific facilities. The implementation of the SAML specification is responsible to enforce those constraints. libxml2/xmlsec1 are not aware of those constraints and thus process the document based on the full/general xmldsig rules. What is happening is the following: - xmldsig-core allows the signature-information and the data that was signed to be in different places. This works by setting the URI attribute of the Reference element. The URI attribute contains an optional identifier of the object being signed. (see "4.4.3 The Reference Element" -- https://www.w3.org/TR/xmldsig-core1/#sec-Reference) This identifier is actually a pointer that can be defined in many different ways; from XPath expressions that need to be executed(!), to a full URL that should be fetched(!) in order to recalculate the signature. - saml-core section "5.4 XML Signature Profile" defines constrains on the xmldsig-core facilities. It explicitly dictates that enveloped signatures are the only signatures allowed. This mean that: * Assertion/RequestType/ResponseType elements must have an ID attribute * signatures must have a single Reference element * the Reference element must have a URI attribute * the URI attribute contains an anchor * the anchor points to the enclosing element's ID attribute xmlsec1 does the right thing - it follows the reference URI pointer and validates the assertion. But, the pointer points to an assertion in another part of the document; not the assertion in which the signature is embedded/enveloped. SAML processing thinks that the signature is fine (that's what xmlsec1 said), and gets the assertion data from the assertion that contains the signature - but that assertion was never validated. The issue is that pysaml2 does not enforce the constrains on the signature validation facilities of xmldsig-core, that the saml-core spec defines. The solution is simple; all we need is to make sure that assertions with signatures (1) contain one reference element that (2) has a URI attribute (3) that is an anchor that (4) points to the assertion in which the signature is embedded. If those conditions are met then we're good, otherwise we should fail the verification. Signed-off-by: Ivan Kanakarakis <ivan.kanak@gmail.com>
* Reformat and rearrange codeIvan Kanakarakis2019-12-261-15/+46
| | | | Signed-off-by: Ivan Kanakarakis <ivan.kanak@gmail.com>
* Add freshness period feature for MetaDataMDXNikos Sklikas2019-12-261-0/+24
| | | | | Add a configurable period for which the metadata is valid, this is only available when using MDX.
* Fix bug in time_util libraryNikos Sklikas2019-12-261-3/+3
| | | | | | The add_duration library didn't calculate the days correctly. These fixes make it compliant with the format described in https://www.w3.org/TR/xmlschema-2/#adding-durations-to-dateTimes
* Remove deprecated saml2.aes moduleIvan Kanakarakis2019-12-261-8/+8
| | | | | | Use saml2.cryptography.symmetric instead Signed-off-by: Ivan Kanakarakis <ivan.kanak@gmail.com>
* Convenience method for getting supported algorithms from metadataJohan Lundberg2019-12-161-0/+14
|
* Fix validation limits for mocked external testsIvan Kanakarakis2019-12-042-418/+241
| | | | Signed-off-by: Ivan Kanakarakis <ivan.kanak@gmail.com>
* Run tests without network connectionIvan Kanakarakis2019-11-274-3/+162172
| | | | Signed-off-by: Ivan Kanakarakis <ivan.kanak@gmail.com>
* Extract `PYSAML2_DELETE_TMPFILES` option to config.pyJohn Paraskevopoulos2019-11-262-0/+2
| | | | | | | | | | | | | | | | - Moves parsing PYSAML2_DELETE_TMPFILES option to config.py and uses the value as a Config class property (`delete_tmpfiles`). This attribute is part of the configuration so its place is in the config.py and the corresponding class. This may add the config object dependency to classes/functions that are calling the `make_temp` function, but at the same time keeps a more layered approach since this config option is now processed and set up in the correct layer; that is the Config class and the config module. Scripts that (in)directly use classes that have methods that use the `make_temp` functions were not changed since those methods are not called when these scripts run and they are out of the scripts' scope (that is, the script functionality does not create any temp file). Those scripts are `verify_metadata`, `merge_metadata` and `mdexport`
* Read from env var PYSAML2_DELETE_TMPFILESIvan Kanakarakis2019-11-262-52/+36
| | | | Signed-off-by: Ivan Kanakarakis <ivan.kanak@gmail.com>
* Extend checks for IPv6 addressesIvan Kanakarakis2019-11-261-0/+17
| | | | | | | | - Make sure enclosing brackets match. - Use the built-in classes/checks for the IPv6/IPv4 address format. - Extend tests to bad cases Signed-off-by: Ivan Kanakarakis <ivan.kanak@gmail.com>
* Fix ipv6 validation for addresses with bracketsScott Koranda2019-11-261-0/+8
| | | | | | | | Fix ipv6 validation for addresses that include the brackets, such as [2001:8003:5555:9999:555a:5555:c77:d5c5]. See https://tools.ietf.org/html/rfc4038#section-5.1 regarding the inclusion of brackets in the address. The Shibboleth IdP sends ipv6 addresses that include the brackets.
* Cleanup importsIvan Kanakarakis2019-10-082-17/+2
| | | | Signed-off-by: Ivan Kanakarakis <ivan.kanak@gmail.com>
* Deprecate saml2.extension.ui - use saml2.extension.mduiIvan Kanakarakis2019-10-083-4/+1
| | | | Signed-off-by: Ivan Kanakarakis <ivan.kanak@gmail.com>
* Added test file for tests around authentication requestsScott Koranda2019-08-261-0/+37
| | | | | | | Added a file for holding tests around authentication requests and added a first test to test that the IdP code can pick the correct location from SAML metadata using the AssertionConsumerServiceIndex from an authentication request.
* Added second HTTP-POST binding in metadata for test SPScott Koranda2019-08-261-0/+1
| | | | | Added a second HTTP-POST binding to the SAML metadata for test SP so that it can be used for various tests.
* Formatting of SP SAML metadata used for testsScott Koranda2019-08-261-4/+64
| | | | | Formatted some of the SP SAML metadata used for tests so that it can be read by a human.
* Validate the audience of assertions regardless of a response being unsolicitedIvan Kanakarakis2019-08-241-2/+2
| | | | | | Fixes #609 Signed-off-by: Ivan Kanakarakis <ivan.kanak@gmail.com>
* Fix tests to be compatible with latest pytestIvan Kanakarakis2019-07-0811-64/+100
| | | | Signed-off-by: Ivan Kanakarakis <ivan.kanak@gmail.com>
* Set force_authn when the value is "true" or "1"Ivan Kanakarakis2019-06-271-7/+29
| | | | | | | | | | | | | | Following d257d3054f36b4f3dfaba8b7394a2e8bab0aaf2e the ForceAuthn attribute is an xsd:boolean value which can be any of "false", "true", "0" or "1". We must set force_authn when the value is "true" or "1". We set the value into kwargs, which is then mirrored onto _args, which is merged with args, which is finally given to the saml2.samlp.AuthnRequest class to construct the object. Previously, we set the value into args directly, which would be overwritten by the call to _filter_args. Signed-off-by: Ivan Kanakarakis <ivan.kanak@gmail.com>
* Restructure to_eptid_value functionIvan Kanakarakis2019-06-171-9/+14
| | | | | | | Use "text" instead of "value" as the key that denotes the text-value of the NameID node. Signed-off-by: Ivan Kanakarakis <ivan.kanak@gmail.com>
* Enable NameQualifier and SPNameQualifier attributes for ePTIDScott Koranda2019-06-041-0/+18
| | | | | | | | | | | | | The attribute value for eduPersonTargetedID (ePTID) is a NameID element. The SAML specification allows the NameID element to include the two optional attributes 'NameQualifier' and 'SPNameQualifier'. This patch enables specifying a dictionary as the internal or local attribute value instead of a string. When the local attribute value is a dictionary with keys 'value', 'NameQualifier', and 'SPNameQualifier' then the resulting XML NameID element will include the 'NameQualifier' and 'SPNameQualifier' attributes with values taken from the values of the dictionary. The value for the NameID element is taken from the value associated with tthe 'value' key.
* Format codeIvan Kanakarakis2019-05-292-54/+72
| | | | Signed-off-by: Ivan Kanakarakis <ivan.kanak@gmail.com>
* Use `extension_elements` to extract `KeyInfo`Alex Bublichenko2019-05-282-4/+8
| | | | Instead of explicitly declaring `KeyInfo` as child of `SubjectConfirmationData`, use `extension_elements` to extract `KeyInfo` element(s).
* Gracefully handle invalid HOK assertionsAlex Bublichenko2019-05-242-9/+54
|
* Clean up and fix tests for python 3.* versionsAlex Bublichenko2019-05-242-35/+46
|
* Parse assertions with Holder-of-Key profileAlex Bublichenko2019-05-234-16/+162
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Problem: Holder-of-Key assertions are used to achieve higher levels of federation security, compared to bearer assertions, by having Relying Party challenge subscriber to prove possession of the key specified in the assertion that represents subscriber in addition to verifying the assertion itself signed by Identity Provider. More information about it can be found in https://pages.nist.gov/800-63-3/sp800-63c.html This library fails to parase SAML respones containing assertions with Holder-of-Key profile, for example: ``` <ns1:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:holder-of-key"> <ns1:SubjectConfirmationData InResponseTo="id-KHlas49TtW2VdC8WN" NotOnOrAfter="2019-05-14T20:36:13Z" Recipient="https://sp:443/.auth/saml/login"> <ns2:KeyInfo> <ns2:X509Data> <ns2:X509Certificate>MIICITCCAYoCAQEwDQYJKoZIhvcNAQELBQAwWDELMAkGA1UEBhMCenoxCzAJBgNVBAgMAnp6MQ0wCwYDVQQHDAR6enp6MQ4wDAYDVQQKDAVaenp6ejEOMAwGA1UECwwFWnp6enoxDTALBgNVBAMMBHRlc3QwIBcNMTkwNDEyMTk1MDM0WhgPMzAxODA4MTMxOTUwMzRaMFgxCzAJBgNVBAYTAnp6MQswCQYDVQQIDAJ6ejENMAsGA1UEBwwEenp6ejEOMAwGA1UECgwFWnp6enoxDjAMBgNVBAsMBVp6enp6MQ0wCwYDVQQDDAR0ZXN0MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDHcj80WU/XBsd9FlyQmfjPUdfmedhCFDd6TEQmZNNqP/UG+VkGa+BXjRIHMfic/WxPTbGhCjv68ci0UDNomUXagFexLGNpkwa7+CRVtoc/1xgq+ySE6M4nhcCutScoxNvWNn5eSQ66i3U0sTv91MgsXxqEdTaiZg0BIufEc3dueQIDAQABMA0GCSqGSIb3DQEBCwUAA4GBAGUV5B+USHvaRa8kgCNJSuNpo6ARlv0ekrk8bbdNRBiEUdCMyoGJFfuM9K0zybX6Vr25wai3nvaog294Vx/jWjX2g5SDbjItH6VGy6C9GCGf1A07VxFRCfJn5tA9HuJjPKiE+g/BmrV5N4CealzFxPHWYkNOzoRU8qI7OqUai1kL</ns2:X509Certificate> </ns2:X509Data> </ns2:KeyInfo> </ns1:SubjectConfirmationData> </ns1:SubjectConfirmation> ``` fails to be parsed with the following error: ``` ERROR saml2.response:response.py:836 get subject Traceback (most recent call last): File "/home/abublich/repos/abliqo-pysaml2/venv/local/lib/python2.7/site-packages/pysaml2-4.7.0-py2.7.egg/saml2/response.py", line 828, in _assertion self.get_subject() File "/home/abublich/repos/abliqo-pysaml2/venv/local/lib/python2.7/site-packages/pysaml2-4.7.0-py2.7.egg/saml2/response.py", line 753, in get_subject if not self._holder_of_key_confirmed(_data): File "/home/abublich/repos/abliqo-pysaml2/venv/local/lib/python2.7/site-packages/pysaml2-4.7.0-py2.7.egg/saml2/response.py", line 730, in _holder_of_key_confirmed [samlp, saml, xenc, ds]): File "/home/abublich/repos/abliqo-pysaml2/venv/local/lib/python2.7/site-packages/pysaml2-4.7.0-py2.7.egg/saml2/__init__.py", line 1004, in extension_elements_to_elements for extension_element in extension_elements: TypeError: 'SubjectConfirmationData' object is not iterable ``` The root cause is two-fold: 1. The type SubjectConfirmationDataType_ does not declare KeyInfo as child element. 2. The bug in function _holder_of_key_confirmed: it should check KeyInfo child element of SubjectConfirmationData instead of SubjectConfirmationData itself. Solution: Fixed the root cause and added new unit tests that verify successful parsing of Holder-of-Key assertions.
* Merge pull request #606 from bmwiedemann/fix2025Ivan Kanakarakis2019-05-147-48/+60
|\ | | | | Make tests pass after 2024
| * Make tests pass after 2024Bernhard M. Wiedemann2019-04-127-48/+60
| | | | | | | | | | | | | | | | | | | | | | Background: As part of my work on reproducible builds for openSUSE, I check that software still gives identical build results in the future. The usual offset is +15 years, because that is how long I expect some software will be used in some places. This showed up failing tests in our package build. See https://reproducible-builds.org/ for why this matters. This patch made tests pass in 2037
* | Merge pull request #613 from skoranda/more_flexible_entity_category_importIvan Kanakarakis2019-05-143-0/+139
|\ \ | | | | | | Make entity category imports more flexible
| * | Added tests for new entity category import functionalityScott Koranda2019-05-073-0/+139
| |/ | | | | | | | | | | Added tests for the new entity category import functionality that searches for entity category modules on the general import path before searching in saml2.entity_category.<module>.
* | update tests with regards to AllowCreateFredrik Thulin2019-05-082-4/+4
|/ | | | AllowCreate is not supposed to be present for transient Name IDs.
* Merge pull request #581 from bmwiedemann/test2020Ivan Kanakarakis2019-02-024-4/+4
|\ | | | | Allow tests to pass after 2020
| * Allow tests to pass after 2020Bernhard M. Wiedemann2019-01-074-4/+4
| | | | | | | | | | This helps to verify reproducible builds. See https://reproducible-builds.org/ for why this matters.
* | Convert exception expectation to with-raises idiomIvan Kanakarakis2019-01-142-60/+33
| | | | | | | | Signed-off-by: Ivan Kanakarakis <ivan.kanak@gmail.com>
* | Reformat code for test_40_sigverIvan Kanakarakis2019-01-141-49/+74
| | | | | | | | Signed-off-by: Ivan Kanakarakis <ivan.kanak@gmail.com>
* | Raise XmlsecError if xmlsec1 returns an errorIvan Kanakarakis2019-01-141-2/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | When xmlsec1 fails, it returns a non-zero returncode. The returncode was checked only for values less than zero, and not greater than zero. This results in situations where xmlsec1 fails to run a command, but the executation continues as nothing failed. This happens to be ok, because, the result we depend upon is coupled to xmlsec1's output stream. When xmlsec1 fails, the output stream is empty and the error stream will have information relevant to the failure cause. Now, the check expects a returncode with value zero, otherwise an XmlsecError exception is raised, to be handled by the caller up the stack. This could have been a major security issue, but we stood lucky. Special thanks to @pjsg for bringing this to our attention. Signed-off-by: Ivan Kanakarakis <ivan.kanak@gmail.com>
* | Remove validate_output parameter from _run_xmlsecIvan Kanakarakis2019-01-111-3/+1
| | | | | | | | | | | | | | All callers set it to false, but one which calls the validation method itself after the call to _run_xmlsec (which means that validation is done twice). Signed-off-by: Ivan Kanakarakis <ivan.kanak@gmail.com>
* | Remove configurable exception typeIvan Kanakarakis2019-01-101-1/+2
|/ | | | | | | | _run_xmlsec function allowed to pass the kind of exception that would be raised in case of error. This was parameter was ignored. As such, it is not needed and is removed completely. Signed-off-by: Ivan Kanakarakis <ivan.kanak@gmail.com>
* Remove the python-future module and use sixIvan Kanakarakis2018-12-062-18/+16
| | | | Signed-off-by: Ivan Kanakarakis <ivan.kanak@gmail.com>
* Handle non standard response error status codesJohan Lundberg2018-12-051-1/+32
|