summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--setup.cfg2
-rw-r--r--src/saml2/config.py7
-rw-r--r--src/saml2/mdstore.py8
-rw-r--r--src/saml2/response.py11
-rw-r--r--tests/invalid_metadata_file.xml1
-rw-r--r--tests/test_30_mdstore.py13
-rw-r--r--tests/test_50_server.py14
7 files changed, 44 insertions, 12 deletions
diff --git a/setup.cfg b/setup.cfg
index b9bfe09a..e04c5520 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -54,7 +54,7 @@ install_requires =
requests >= 1.0.0
six
importlib_resources
- xmlschema
+ xmlschema >= 1.2.1
[options.packages.find]
diff --git a/src/saml2/config.py b/src/saml2/config.py
index 8b865dcb..6687a60f 100644
--- a/src/saml2/config.py
+++ b/src/saml2/config.py
@@ -404,7 +404,12 @@ class Config(object):
if endps and service in endps:
for endpspec in endps[service]:
try:
- endp, bind = endpspec
+ # endspec sometime is str, sometime is a tuple
+ if type(endpspec) in (tuple, list):
+ # slice prevents 3-tuple, eg: sp's assertion_consumer_service
+ endp, bind = endpspec[0:2]
+ else:
+ endp, bind = endpspec
if binding is None or bind == binding:
spec.append(endp)
except ValueError:
diff --git a/src/saml2/mdstore.py b/src/saml2/mdstore.py
index 96acfa1e..44930773 100644
--- a/src/saml2/mdstore.py
+++ b/src/saml2/mdstore.py
@@ -7,12 +7,12 @@ import os
import sys
from itertools import chain
from warnings import warn as _warn
-
from hashlib import sha1
from os.path import isfile
from os.path import join
import requests
+
import six
from saml2 import md
@@ -24,7 +24,6 @@ from saml2 import SAMLError
from saml2 import BINDING_HTTP_REDIRECT
from saml2 import BINDING_HTTP_POST
from saml2 import BINDING_SOAP
-
from saml2.httpbase import HTTPBase
from saml2.extension.idpdisc import BINDING_DISCO
from saml2.extension.idpdisc import DiscoveryResponse
@@ -612,7 +611,10 @@ class InMemoryMetaData(MetaData):
self.entity[entity_descr.entity_id] = _ent
def parse(self, xmlstr):
- self.entities_descr = md.entities_descriptor_from_string(xmlstr)
+ try:
+ self.entities_descr = md.entities_descriptor_from_string(xmlstr)
+ except Exception as e:
+ raise SAMLError(f'Failed to parse metadata file: {self.filename}') from e
if not self.entities_descr:
self.entity_descr = md.entity_descriptor_from_string(xmlstr)
diff --git a/src/saml2/response.py b/src/saml2/response.py
index 70e2a8c1..fcb682b4 100644
--- a/src/saml2/response.py
+++ b/src/saml2/response.py
@@ -98,6 +98,9 @@ class StatusAuthnFailed(StatusError):
class StatusInvalidAttrNameOrValue(StatusError):
pass
+class StatusInvalidAuthnResponseStatement(StatusError):
+ pass
+
class StatusInvalidNameidPolicy(StatusError):
pass
@@ -1103,13 +1106,17 @@ class AuthnResponse(StatusResponse):
return {"name_id": self.name_id, "came_from": self.came_from,
"issuer": self.issuer(), "not_on_or_after": nooa,
"authz_decision_info": self.authz_decision_info()}
- else:
+ elif getattr(self.assertion, 'authn_statement', None):
authn_statement = self.assertion.authn_statement[0]
return {"ava": self.ava, "name_id": self.name_id,
"came_from": self.came_from, "issuer": self.issuer(),
"not_on_or_after": nooa, "authn_info": self.authn_info(),
"session_index": authn_statement.session_index}
-
+ else:
+ raise StatusInvalidAuthnResponseStatement(
+ "The Authn Response Statement is not valid"
+ )
+
def __str__(self):
return self.xmlstr
diff --git a/tests/invalid_metadata_file.xml b/tests/invalid_metadata_file.xml
new file mode 100644
index 00000000..249c87ce
--- /dev/null
+++ b/tests/invalid_metadata_file.xml
@@ -0,0 +1 @@
+this content is invalid
diff --git a/tests/test_30_mdstore.py b/tests/test_30_mdstore.py
index 4dfa80f3..bfe261dd 100644
--- a/tests/test_30_mdstore.py
+++ b/tests/test_30_mdstore.py
@@ -7,6 +7,8 @@ from collections import OrderedDict
from unittest.mock import Mock
from unittest.mock import patch
+from pytest import raises
+
import responses
from six.moves.urllib import parse
@@ -19,6 +21,7 @@ from saml2.mdstore import locations
from saml2.mdstore import name
from saml2 import sigver
from saml2.httpbase import HTTPBase
+from saml2 import SAMLError
from saml2 import BINDING_SOAP
from saml2 import BINDING_HTTP_REDIRECT
from saml2 import BINDING_HTTP_POST
@@ -156,6 +159,10 @@ METADATACONF = {
"class": "saml2.mdstore.MetaDataFile",
"metadata": [(full_path("swamid-2.0.xml"),)],
}],
+ "14": [{
+ "class": "saml2.mdstore.MetaDataFile",
+ "metadata": [(full_path("invalid_metadata_file.xml"),)],
+ }],
}
@@ -170,6 +177,12 @@ def _fix_valid_until(xmlstring):
xmlstring)
+def test_invalid_metadata():
+ mds = MetadataStore(ATTRCONV, sec_config, disable_ssl_certificate_validation=True)
+ with raises(SAMLError):
+ mds.imp(METADATACONF["14"])
+
+
def test_swami_1():
UMU_IDP = 'https://idp.umu.se/saml2/idp/metadata.php'
mds = MetadataStore(ATTRCONV, sec_config,
diff --git a/tests/test_50_server.py b/tests/test_50_server.py
index dfc24eee..07ef4b91 100644
--- a/tests/test_50_server.py
+++ b/tests/test_50_server.py
@@ -6,6 +6,7 @@ import os
from contextlib import closing
from six.moves.urllib.parse import parse_qs
import uuid
+import re
from saml2.cert import OpenSSLWrapper
from saml2.sigver import make_temp, DecryptError, EncryptError, CertificateError
@@ -129,8 +130,10 @@ class TestServer1():
self.verify_assertion(assertion)
assert assertion[0].signature is None
- assert 'EncryptedAssertion><encas1:Assertion xmlns:encas0="http://www.w3.org/2001/XMLSchema-instance" ' \
- 'xmlns:encas1="urn:oasis:names:tc:SAML:2.0:assertion"' in decr_text
+ assert re.search(
+ r':EncryptedAssertion><encas[0-9]:Assertion ([^ >]* )*xmlns:encas[0-9]="urn:oasis:names:tc:SAML:2.0:assertion"',
+ decr_text,
+ )
def verify_advice_assertion(self, resp, decr_text):
assert resp.assertion[0].signature is None
@@ -1188,9 +1191,10 @@ class TestServer1NonAsciiAva():
def verify_encrypted_assertion(self, assertion, decr_text):
self.verify_assertion(assertion)
assert assertion[0].signature is None
-
- assert 'EncryptedAssertion><encas1:Assertion xmlns:encas0="http://www.w3.org/2001/XMLSchema-instance" ' \
- 'xmlns:encas1="urn:oasis:names:tc:SAML:2.0:assertion"' in decr_text
+ assert re.search(
+ r':EncryptedAssertion><encas[0-9]:Assertion ([^ >]* )*xmlns:encas[0-9]="urn:oasis:names:tc:SAML:2.0:assertion"',
+ decr_text,
+ )
def verify_advice_assertion(self, resp, decr_text):
assert resp.assertion[0].signature is None