Skip to content

Commit

Permalink
Include eIDAS definitation in the validator - expose saml2.xml.schema…
Browse files Browse the repository at this point in the history
…:validate

Signed-off-by: Ivan Kanakarakis <[email protected]>
  • Loading branch information
c00kiemon5ter committed Aug 10, 2022
1 parent 14c649a commit 63fca12
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 66 deletions.
16 changes: 2 additions & 14 deletions src/saml2/sigver.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
from saml2.xmlenc import CipherData
from saml2.xmlenc import CipherValue
from saml2.xmlenc import EncryptedData
from saml2.xml.schema import node_to_schema
from saml2.xml.schema import validate as validate_doc_with_schema
from saml2.xml.schema import XMLSchemaError


Expand Down Expand Up @@ -1427,20 +1427,8 @@ def _check_signature(self, decoded_xml, item, node_name=NODE_NAME, origdoc=None,
if not certs:
raise MissingKey(_issuer)

# validate XML with the appropriate schema
try:
_schema = node_to_schema[node_name]
except KeyError as e:
error_context = {
"message": "Signature verification failed. Unknown node type.",
"issuer": _issuer,
"type": node_name,
"document": decoded_xml,
}
raise SignatureError(error_context) from e

try:
_schema.validate(str(item))
validate_doc_with_schema(str(item))
except XMLSchemaError as e:
error_context = {
"message": "Signature verification failed. Invalid document format.",
Expand Down
118 changes: 66 additions & 52 deletions src/saml2/xml/schema/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,71 +8,85 @@
from importlib_resources import files as _resource_files

from xmlschema import XMLSchema as _XMLSchema
from xmlschema.exceptions import XMLSchemaException as XMLSchemaError
from xmlschema.exceptions import XMLSchemaException as _XMLSchemaException

import saml2.data.schemas as _data_schemas


def _create_xml_schema_validator(source, **kwargs):
class XMLSchemaError(Exception):
"""Generic error raised when the schema does not validate with a document"""


def _create_xml_schema_validator(source=None, **kwargs):
schema_resources = _resource_files(_data_schemas)
path_schema_xml = str(schema_resources.joinpath("xml.xsd"))
path_schema_envelope = str(schema_resources.joinpath("envelope.xsd"))
path_schema_xenc = str(schema_resources.joinpath("xenc-schema.xsd"))
path_schema_xmldsig_core = str(schema_resources.joinpath("xmldsig-core-schema.xsd"))
path_schema_saml_assertion = str(
schema_resources.joinpath("saml-schema-assertion-2.0.xsd")
)
path_schema_saml_metadata = str(
schema_resources.joinpath("saml-schema-metadata-2.0.xsd")
)
path_schema_saml_protocol = str(
schema_resources.joinpath("saml-schema-protocol-2.0.xsd")
)
path_schema_eidas_metadata_servicelist= str(
schema_resources.joinpath("eidas-schema-metadata-servicelist.xsd")
)
path_schema_eidas_saml_extensions = str(
schema_resources.joinpath("eidas-schema-saml-extensions.xsd")
)
path_schema_eidas_attribute_naturalperson = str(
schema_resources.joinpath("eidas-schema-attribute-naturalperson.xsd")
)
path_schema_eidas_attribute_legalperson = str(
schema_resources.joinpath("eidas-schema-attribute-legalperson.xsd")
)

source = source if source else path_schema_saml_protocol
locations = {
"http://www.w3.org/XML/1998/namespace": path_schema_xml,
"http://schemas.xmlsoap.org/soap/envelope/": path_schema_envelope,
"http://www.w3.org/2001/04/xmlenc#": path_schema_xenc,
"http://www.w3.org/2000/09/xmldsig#": path_schema_xmldsig_core,
"urn:oasis:names:tc:SAML:2.0:assertion": path_schema_saml_assertion,
"urn:oasis:names:tc:SAML:2.0:metadata": path_schema_saml_metadata,
"urn:oasis:names:tc:SAML:2.0:protocol": path_schema_saml_protocol,
"http://eidas.europa.eu/metadata/servicelist": path_schema_eidas_metadata_servicelist,
"http://eidas.europa.eu/saml-extensions": path_schema_eidas_saml_extensions,
"http://eidas.europa.eu/attributes/naturalperson": path_schema_eidas_attribute_naturalperson,
"http://eidas.europa.eu/attributes/legalperson": path_schema_eidas_attribute_legalperson,
}

kwargs = {
**kwargs,
"validation": "strict",
"locations": _locations,
"locations": locations,
"base_url": source,
"allow": "sandbox",
"use_fallback": False,
}
return _XMLSchema(source, **kwargs)


_schema_resources = _resource_files(_data_schemas)
_path_schema_xml = str(_schema_resources.joinpath("xml.xsd"))
_path_schema_envelope = str(_schema_resources.joinpath("envelope.xsd"))
_path_schema_xenc = str(_schema_resources.joinpath("xenc-schema.xsd"))
_path_schema_xmldsig_core = str(_schema_resources.joinpath("xmldsig-core-schema.xsd"))
_path_schema_saml_assertion = str(
_schema_resources.joinpath("saml-schema-assertion-2.0.xsd")
)
_path_schema_saml_metadata = str(
_schema_resources.joinpath("saml-schema-metadata-2.0.xsd")
)
_path_schema_saml_protocol = str(
_schema_resources.joinpath("saml-schema-protocol-2.0.xsd")
)

_locations = {
"http://www.w3.org/XML/1998/namespace": _path_schema_xml,
"http://schemas.xmlsoap.org/soap/envelope/": _path_schema_envelope,
"http://www.w3.org/2001/04/xmlenc#": _path_schema_xenc,
"http://www.w3.org/2000/09/xmldsig#": _path_schema_xmldsig_core,
"urn:oasis:names:tc:SAML:2.0:assertion": _path_schema_saml_assertion,
"urn:oasis:names:tc:SAML:2.0:metadata": _path_schema_saml_metadata,
"urn:oasis:names:tc:SAML:2.0:protocol": _path_schema_saml_protocol,
}
_schema_validator_default = _create_xml_schema_validator()

schema_saml_assertion = _create_xml_schema_validator(_path_schema_saml_assertion)
schema_saml_metadata = _create_xml_schema_validator(_path_schema_saml_metadata)
schema_saml_protocol = _create_xml_schema_validator(_path_schema_saml_protocol)

node_to_schema = {
# AssertionType
"urn:oasis:names:tc:SAML:2.0:assertion:Assertion": schema_saml_assertion,
# EntitiesDescriptorType
"urn:oasis:names:tc:SAML:2.0:metadata:EntitiesDescriptor": schema_saml_metadata,
# EntityDescriptorType
"urn:oasis:names:tc:SAML:2.0:metadata:EntityDescriptor": schema_saml_metadata,
# RequestAbstractType
"urn:oasis:names:tc:SAML:2.0:protocol:AssertionIDRequest": schema_saml_protocol,
"urn:oasis:names:tc:SAML:2.0:protocol:SubjectQuery": schema_saml_protocol,
"urn:oasis:names:tc:SAML:2.0:protocol:AuthnRequest": schema_saml_protocol,
"urn:oasis:names:tc:SAML:2.0:protocol:ArtifactResolve": schema_saml_protocol,
"urn:oasis:names:tc:SAML:2.0:protocol:ManageNameIDRequest": schema_saml_protocol,
"urn:oasis:names:tc:SAML:2.0:protocol:LogoutRequest": schema_saml_protocol,
"urn:oasis:names:tc:SAML:2.0:protocol:NameIDMappingRequest": schema_saml_protocol,
# StatusResponseType
"urn:oasis:names:tc:SAML:2.0:protocol:Response": schema_saml_protocol,
"urn:oasis:names:tc:SAML:2.0:protocol:ArtifactResponse": schema_saml_protocol,
"urn:oasis:names:tc:SAML:2.0:protocol:ManageNameIDResponse": schema_saml_protocol,
"urn:oasis:names:tc:SAML:2.0:protocol:LogoutResponse": schema_saml_protocol,
"urn:oasis:names:tc:SAML:2.0:protocol:NameIDMappingResponse": schema_saml_protocol,
}
def validate(doc, validator=None):
validator = _schema_validator_default if validator is None else validator
try:
validator.validate(doc)
except _XMLSchemaException as e:
error_context = {
"doc": doc,
"error": str(e),
}
raise XMLSchemaError(error_context) from e
except Exception as e:
error_context = {
"doc": doc,
"error": str(e),
}
raise XMLSchemaError(error_context) from e

0 comments on commit 63fca12

Please sign in to comment.