Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-pysaml2 for openSUSE:Factory 
checked in at 2021-07-03 20:51:01
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-pysaml2 (Old)
 and      /work/SRC/openSUSE:Factory/.python-pysaml2.new.2625 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-pysaml2"

Sat Jul  3 20:51:01 2021 rev:25 rq:903859 version:7.0.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-pysaml2/python-pysaml2.changes    
2021-05-03 22:08:04.884513970 +0200
+++ /work/SRC/openSUSE:Factory/.python-pysaml2.new.2625/python-pysaml2.changes  
2021-07-03 20:51:31.060460104 +0200
@@ -1,0 +2,29 @@
+Fri Jul  2 20:25:49 UTC 2021 - Michael Str??der <[email protected]>
+
+- removed obsolete 
0001-Always-use-base64.encodebytes-base64.encodestring-ha.patch
+- Update to 7.0.1:
+  * 7.0.1 (2021-05-20)
+    - Preserve order of response bindings on IdP-initiated logout
+    - Fix use of expected binding on SP logout
+  * 7.0.0 (2021-05-18)
+    - **BREAKING** Replace encryption method rsa-1_5 with rsa-oaep-mgf1p
+    - Add documentation next to the code
+  * 6.5.2 (2021-05-18)
+    - Add shibmd_scopes metadata extractor
+    - Allow the Issuer element on a Response to be missing
+    - Respect the preferred_binding configuration for the single_logout_service
+    - Fix logout signature flags for redirect, post and soap requests
+    - Respect the logout_requests_signed configuration option
+    - Fix crash when applying policy on RequestedAttribute without a 
friendlyName
+    - Correctly validate IssueInstant
+    - Correctly handle AudienceRestriction elements with no value
+    - Raise InvalidAssertion exception when assertion requirements are not met
+    - Raise SAMLError on failure to parse a metadata file
+    - Raise StatusInvalidAuthnResponseStatement when the AuthnStatement is not 
valid
+    - Handle all forms of ACS endpoint specifications
+    - tests: Always use base64.encodebytes; base64.encodestring has been 
dropped
+    - build: Set minimum version needed for xmlschema
+    - docs: Update Travis CI badge from travis-ci.org to travis-ci.com
+    - examples: Fix example code
+
+-------------------------------------------------------------------

Old:
----
  0001-Always-use-base64.encodebytes-base64.encodestring-ha.patch
  v6.5.1.tar.gz

New:
----
  v7.0.1.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-pysaml2.spec ++++++
--- /var/tmp/diff_new_pack.8cAo5s/_old  2021-07-03 20:51:31.568456198 +0200
+++ /var/tmp/diff_new_pack.8cAo5s/_new  2021-07-03 20:51:31.572456167 +0200
@@ -20,14 +20,12 @@
 %global modname pysaml2
 %global skip_python2 1
 Name:           python-pysaml2
-Version:        6.5.1
+Version:        7.0.1
 Release:        0
 Summary:        Python implementation of SAML Version 2 to be used in a WSGI 
environment
 License:        Apache-2.0
 URL:            https://github.com/IdentityPython/pysaml2
 Source:         
https://github.com/IdentityPython/pysaml2/archive/v%{version}.tar.gz
-# PATCH-FIX-UPSTREAM: https://github.com/IdentityPython/pysaml2/pull/797
-Patch1:         0001-Always-use-base64.encodebytes-base64.encodestring-ha.patch
 BuildRequires:  %{python_module Paste}
 BuildRequires:  %{python_module cryptography >= 1.4}
 BuildRequires:  %{python_module dbm}
@@ -78,7 +76,6 @@
 
 %prep
 %setup -q -n %{modname}-%{version}
-%autopatch -p1
 
 # delete shebang of files not in executable path
 find src/ -name '*.py' -print0 | xargs -0 sed -i '1s/#!.*$//'

++++++ v6.5.1.tar.gz -> v7.0.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pysaml2-6.5.1/CHANGELOG.md 
new/pysaml2-7.0.1/CHANGELOG.md
--- old/pysaml2-6.5.1/CHANGELOG.md      2021-01-21 00:08:02.000000000 +0100
+++ new/pysaml2-7.0.1/CHANGELOG.md      2021-05-20 18:56:31.000000000 +0200
@@ -1,6 +1,38 @@
 # Changelog
 
 
+## 7.0.1 (2021-05-20)
+
+- Preserve order of response bindings on IdP-initiated logout
+- Fix use of expected binding on SP logout
+
+
+## 7.0.0 (2021-05-18)
+
+- **BREAKING** Replace encryption method rsa-1_5 with rsa-oaep-mgf1p
+- Add documentation next to the code
+
+
+## 6.5.2 (2021-05-18)
+
+- Add shibmd_scopes metadata extractor
+- Allow the Issuer element on a Response to be missing
+- Respect the preferred_binding configuration for the single_logout_service
+- Fix logout signature flags for redirect, post and soap requests
+- Respect the logout_requests_signed configuration option
+- Fix crash when applying policy on RequestedAttribute without a friendlyName
+- Correctly validate IssueInstant
+- Correctly handle AudienceRestriction elements with no value
+- Raise InvalidAssertion exception when assertion requirements are not met
+- Raise SAMLError on failure to parse a metadata file
+- Raise StatusInvalidAuthnResponseStatement when the AuthnStatement is not 
valid
+- Handle all forms of ACS endpoint specifications
+- tests: Always use base64.encodebytes; base64.encodestring has been dropped
+- build: Set minimum version needed for xmlschema
+- docs: Update Travis CI badge from travis-ci.org to travis-ci.com
+- examples: Fix example code
+
+
 ## 6.5.1 (2021-01-21)
 
 - Fix the parser to take into account both the xs and xsd namespace prefixes
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pysaml2-6.5.1/README.rst new/pysaml2-7.0.1/README.rst
--- old/pysaml2-6.5.1/README.rst        2021-01-21 00:08:02.000000000 +0100
+++ new/pysaml2-7.0.1/README.rst        2021-05-20 18:56:31.000000000 +0200
@@ -5,8 +5,8 @@
 :Version: see VERSION_
 :Documentation: https://pysaml2.readthedocs.io/
 
-.. image:: https://api.travis-ci.org/IdentityPython/pysaml2.png?branch=master
-    :target: https://travis-ci.org/IdentityPython/pysaml2
+.. image:: https://api.travis-ci.com/IdentityPython/pysaml2.png?branch=master
+    :target: https://travis-ci.com/IdentityPython/pysaml2
 
 .. image:: https://img.shields.io/pypi/pyversions/pysaml2.svg
     :target: https://pypi.org/project/pysaml2/
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pysaml2-6.5.1/VERSION new/pysaml2-7.0.1/VERSION
--- old/pysaml2-6.5.1/VERSION   2021-01-21 00:08:02.000000000 +0100
+++ new/pysaml2-7.0.1/VERSION   2021-05-20 18:56:31.000000000 +0200
@@ -1 +1 @@
-6.5.1
+7.0.1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pysaml2-6.5.1/docs/howto/config.rst 
new/pysaml2-7.0.1/docs/howto/config.rst
--- old/pysaml2-6.5.1/docs/howto/config.rst     2021-01-21 00:08:02.000000000 
+0100
+++ new/pysaml2-7.0.1/docs/howto/config.rst     2021-05-20 18:56:31.000000000 
+0200
@@ -400,6 +400,7 @@
 * assertion_id_request_service
 * artifact_resolution_service
 * attribute_consuming_service
+* single_logout_service
 
 
 service
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pysaml2-6.5.1/example/idp2/idp.py 
new/pysaml2-7.0.1/example/idp2/idp.py
--- old/pysaml2-6.5.1/example/idp2/idp.py       2021-01-21 00:08:02.000000000 
+0100
+++ new/pysaml2-7.0.1/example/idp2/idp.py       2021-05-20 18:56:31.000000000 
+0200
@@ -999,7 +999,7 @@
             args.sign,
         )
         start_response("200 OK", [("Content-Type", "text/xml")])
-        return metadata
+        return [metadata]
     except Exception as ex:
         logger.error("An error occured while creating metadata: %s", 
ex.message)
         return not_found(environ, start_response)
@@ -1041,7 +1041,7 @@
 
     path = environ.get("PATH_INFO", "").lstrip("/")
 
-    if path == "metadata":
+    if path == "idp.xml":
         return metadata(environ, start_response)
 
     kaka = environ.get("HTTP_COOKIE", None)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pysaml2-6.5.1/setup.cfg new/pysaml2-7.0.1/setup.cfg
--- old/pysaml2-6.5.1/setup.cfg 2021-01-21 00:08:02.000000000 +0100
+++ new/pysaml2-7.0.1/setup.cfg 2021-05-20 18:56:31.000000000 +0200
@@ -54,7 +54,7 @@
     requests >= 1.0.0
     six
     importlib_resources
-    xmlschema
+    xmlschema >= 1.2.1
 
 
 [options.packages.find]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pysaml2-6.5.1/src/saml2/__init__.py 
new/pysaml2-7.0.1/src/saml2/__init__.py
--- old/pysaml2-6.5.1/src/saml2/__init__.py     2021-01-21 00:08:02.000000000 
+0100
+++ new/pysaml2-7.0.1/src/saml2/__init__.py     2021-05-20 18:56:31.000000000 
+0200
@@ -60,12 +60,20 @@
 DECISION_TYPE_INDETERMINATE = "Indeterminate"
 
 VERSION = "2.0"
-
+# http://docs.oasis-open.org/security/saml/v2.0/saml-bindings-2.0-os.pdf
+# The specification was later updated with errata, and the new version is here:
+# 
http://www.oasis-open.org/committees/download.php/56779/sstc-saml-bindings-errata-2.0-wd-06.pdf
+# parse a SOAP header, make a SOAP request, and receive a SOAP response
 BINDING_SOAP = 'urn:oasis:names:tc:SAML:2.0:bindings:SOAP'
+# parse a PAOS header, make a PAOS request, and receive a PAOS response
 BINDING_PAOS = 'urn:oasis:names:tc:SAML:2.0:bindings:PAOS'
+# URI encoded messages
 BINDING_HTTP_REDIRECT = 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect'
+# HTML encoded messages
 BINDING_HTTP_POST = 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST'
+# sensitive messages are transported over a backchannel
 BINDING_HTTP_ARTIFACT = 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact'
+# as uri response encoded message
 BINDING_URI = 'urn:oasis:names:tc:SAML:2.0:bindings:URI'
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pysaml2-6.5.1/src/saml2/assertion.py 
new/pysaml2-7.0.1/src/saml2/assertion.py
--- old/pysaml2-6.5.1/src/saml2/assertion.py    2021-01-21 00:08:02.000000000 
+0100
+++ new/pysaml2-7.0.1/src/saml2/assertion.py    2021-05-20 18:56:31.000000000 
+0200
@@ -454,7 +454,16 @@
 
         def post_entity_categories(maps, sp_entity_id=None, mds=None, 
required=None):
             restrictions = {}
-            required = [d['friendly_name'].lower() for d in (required or [])]
+            required_friendly_names = [
+                d.get('friendly_name') or get_local_name(
+                    acs=self.acs, attr=d['name'], name_format=d['name_format']
+                )
+                for d in (required or [])
+            ]
+            required = [
+                friendly_name.lower()
+                for friendly_name in required_friendly_names
+            ]
 
             if mds:
                 ecs = mds.entity_categories(sp_entity_id)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pysaml2-6.5.1/src/saml2/client.py 
new/pysaml2-7.0.1/src/saml2/client.py
--- old/pysaml2-6.5.1/src/saml2/client.py       2021-01-21 00:08:02.000000000 
+0100
+++ new/pysaml2-7.0.1/src/saml2/client.py       2021-05-20 18:56:31.000000000 
+0200
@@ -251,85 +251,122 @@
         not_done = entity_ids[:]
         responses = {}
 
+        bindings_slo_preferred = 
self.config.preferred_binding["single_logout_service"]
+
         for entity_id in entity_ids:
             logger.debug("Logout from '%s'", entity_id)
-            # for all where I can use the SOAP binding, do those first
-            for binding in [BINDING_SOAP, BINDING_HTTP_POST, 
BINDING_HTTP_REDIRECT]:
-                if expected_binding and binding != expected_binding:
-                    continue
-
-                try:
-                    srvs = self.metadata.single_logout_service(
-                        entity_id, binding, "idpsso"
-                    )
-                except:
-                    srvs = None
-
-                if not srvs:
-                    logger.debug("No SLO '%s' service", binding)
-                    continue
-
-                destination = next(locations(srvs), None)
-                logger.info("destination to provider: %s", destination)
-
-                try:
-                    session_info = self.users.get_info_from(
-                        name_id, entity_id, False
-                    )
-                    session_indexes = [session_info['session_index']]
-                except KeyError:
-                    session_indexes = None
-
-                sign_post = False if binding == BINDING_HTTP_REDIRECT else sign
-                sign_redirect = False if binding == BINDING_HTTP_POST and sign 
else sign
-
-                req_id, request = self.create_logout_request(
-                    destination,
-                    entity_id,
-                    name_id=name_id,
-                    reason=reason,
-                    expire=expire,
-                    session_indexes=session_indexes,
-                    sign=sign_post,
-                    sign_alg=sign_alg,
-                    digest_alg=digest_alg,
+
+            bindings_slo_supported = self.metadata.single_logout_service(
+                entity_id=entity_id, typ="idpsso"
+            )
+            bindings_slo_preferred_and_supported = (
+                binding
+                for binding in bindings_slo_preferred
+                if binding in bindings_slo_supported
+            )
+            bindings_slo_choices = filter(
+                lambda x: x,
+                (
+                    expected_binding,
+                    *bindings_slo_preferred_and_supported,
+                    *bindings_slo_supported,
                 )
+            )
+            binding = next(bindings_slo_choices, None)
+            if not binding:
+                logger.info(
+                    {
+                        "message": "Entity does not support SLO",
+                        "entity": entity_id,
+                    }
+                )
+                continue
 
-                relay_state = self._relay_state(req_id)
-                http_info = self.apply_binding(
-                    binding,
-                    str(request),
-                    destination,
-                    relay_state,
-                    sign=sign_redirect,
-                    sigalg=sign_alg,
+            service_info = bindings_slo_supported[binding]
+            service_location = next(locations(service_info), None)
+            if not service_location:
+                logger.info(
+                    {
+                        "message": "Entity SLO service does not have a 
location",
+                        "entity": entity_id,
+                        "service_location": service_location,
+                    }
                 )
+                continue
 
-                if binding == BINDING_SOAP:
-                    response = self.send(**http_info)
-                    if response and response.status_code == 200:
-                        not_done.remove(entity_id)
-                        response = response.text
-                        logger.info("Response: %s", response)
-                        res = self.parse_logout_request_response(response, 
binding)
-                        responses[entity_id] = res
-                    else:
-                        logger.info("NOT OK response from %s", destination)
+            session_info = self.users.get_info_from(name_id, entity_id, False)
+            session_index = session_info.get('session_index')
+            session_indexes = [session_index] if session_index else None
+
+            sign = sign if sign is not None else self.logout_requests_signed
+            sign_post = sign and (
+                binding == BINDING_HTTP_POST or binding == BINDING_SOAP
+            )
+            sign_redirect = sign and binding == BINDING_HTTP_REDIRECT
+
+            log_report = {
+                "message": "Invoking SLO on entity",
+                "entity": entity_id,
+                "binding": binding,
+                "location": service_location,
+                "session_indexes": session_indexes,
+                "sign": sign,
+            }
+            logger.info(log_report)
+
+            req_id, request = self.create_logout_request(
+                service_location,
+                entity_id,
+                name_id=name_id,
+                reason=reason,
+                expire=expire,
+                session_indexes=session_indexes,
+                sign=sign_post,
+                sign_alg=sign_alg,
+                digest_alg=digest_alg,
+            )
+            relay_state = self._relay_state(req_id)
+            http_info = self.apply_binding(
+                binding,
+                str(request),
+                service_location,
+                relay_state,
+                sign=sign_redirect,
+                sigalg=sign_alg,
+            )
+
+            if binding == BINDING_SOAP:
+                response = self.send(**http_info)
+                if response and response.status_code == 200:
+                    not_done.remove(entity_id)
+                    response_text = response.text
+                    log_report_response = {
+                        **log_report,
+                        "message": "Response from SLO service",
+                        "response_text": response_text,
+                    }
+                    logger.debug(log_report_response)
+                    res = self.parse_logout_request_response(response_text, 
binding)
+                    responses[entity_id] = res
                 else:
-                    self.state[req_id] = {
-                        "entity_id": entity_id,
-                        "operation": "SLO",
-                        "entity_ids": entity_ids,
-                        "name_id": code(name_id),
-                        "reason": reason,
-                        "not_on_or_after": expire,
-                        "sign": sign,
+                    log_report_response = {
+                        **log_report,
+                        "message": "Bad status_code response from SLO service",
+                        "status_code": (response and response.status_code),
                     }
-                    responses[entity_id] = (binding, http_info)
-                    not_done.remove(entity_id)
-
-                # only try one binding
-                break
+                    logger.info(log_report_response)
+            else:
+                self.state[req_id] = {
+                    "entity_id": entity_id,
+                    "operation": "SLO",
+                    "entity_ids": entity_ids,
+                    "name_id": code(name_id),
+                    "reason": reason,
+                    "not_on_or_after": expire,
+                    "sign": sign,
+                }
+                responses[entity_id] = (binding, http_info)
+                not_done.remove(entity_id)
 
         if not_done:
             # upstream should try later
@@ -629,12 +666,11 @@
             status = status_message_factory("Wrong user",
                                             STATUS_UNKNOWN_PRINCIPAL)
 
-        if binding == BINDING_SOAP:
-            response_bindings = [BINDING_SOAP]
-        elif binding in [BINDING_HTTP_POST, BINDING_HTTP_REDIRECT]:
-            response_bindings = [BINDING_HTTP_POST, BINDING_HTTP_REDIRECT]
-        else:
-            response_bindings = 
self.config.preferred_binding["single_logout_service"]
+        response_bindings = {
+            BINDING_SOAP: [BINDING_SOAP],
+            BINDING_HTTP_POST: [BINDING_HTTP_POST, BINDING_HTTP_REDIRECT],
+            BINDING_HTTP_REDIRECT: [BINDING_HTTP_REDIRECT, BINDING_HTTP_POST],
+        }.get(binding)
 
         if sign is None:
             sign = self.logout_responses_signed
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pysaml2-6.5.1/src/saml2/config.py 
new/pysaml2-7.0.1/src/saml2/config.py
--- old/pysaml2-6.5.1/src/saml2/config.py       2021-01-21 00:08:02.000000000 
+0100
+++ new/pysaml2-7.0.1/src/saml2/config.py       2021-05-20 18:56:31.000000000 
+0200
@@ -404,7 +404,12 @@
         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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/pysaml2-6.5.1/src/saml2/data/templates/template_enc.xml 
new/pysaml2-7.0.1/src/saml2/data/templates/template_enc.xml
--- old/pysaml2-6.5.1/src/saml2/data/templates/template_enc.xml 2021-01-21 
00:08:02.000000000 +0100
+++ new/pysaml2-7.0.1/src/saml2/data/templates/template_enc.xml 2021-05-20 
18:56:31.000000000 +0200
@@ -2,12 +2,10 @@
 <EncryptedData
         xmlns="http://www.w3.org/2001/04/xmlenc#";
         Type="http://www.w3.org/2001/04/xmlenc#Element";>
-    <EncryptionMethod Algorithm=
-                              
"http://www.w3.org/2001/04/xmlenc#tripledes-cbc"/>
+    <EncryptionMethod 
Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc"/>
     <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#";>
         <EncryptedKey xmlns="http://www.w3.org/2001/04/xmlenc#";>
-            <EncryptionMethod Algorithm=
-                                      
"http://www.w3.org/2001/04/xmlenc#rsa-1_5"/>
+            <EncryptionMethod 
Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p"/>
             <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#";>
                 <KeyName/>
             </KeyInfo>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pysaml2-6.5.1/src/saml2/entity.py 
new/pysaml2-7.0.1/src/saml2/entity.py
--- old/pysaml2-6.5.1/src/saml2/entity.py       2021-01-21 00:08:02.000000000 
+0100
+++ new/pysaml2-7.0.1/src/saml2/entity.py       2021-05-20 18:56:31.000000000 
+0200
@@ -65,6 +65,7 @@
 from saml2.sigver import SigverError
 from saml2.sigver import SignatureError
 from saml2.sigver import make_temp
+from saml2.sigver import get_pem_wrapped_unwrapped
 from saml2.sigver import pre_encryption_part
 from saml2.sigver import pre_signature_part
 from saml2.sigver import pre_encrypt_assertion
@@ -241,7 +242,11 @@
         :return: A dictionary
         """
 
-        # XXX sig-allowed should be configurable
+        # XXX SIG_ALLOWED_ALG should be configurable
+        # XXX should_sign stems from authn_requests_signed and sign_response
+        # XXX based on the type of the entity
+        # XXX but should also take into account the type of message 
(Authn/Logout/etc)
+        # XXX should_sign should be split and the exact config options should 
be checked
         sign = sign if sign is not None else self.should_sign
         sign_alg = sigalg or self.signing_algorithm
         if sign_alg not in [long_name for short_name, long_name in 
SIG_ALLOWED_ALG]:
@@ -300,7 +305,7 @@
 
         sfunc = getattr(self.metadata, service)
 
-        if bindings is None:
+        if not bindings:
             if request and request.protocol_binding:
                 bindings = [request.protocol_binding]
             else:
@@ -650,19 +655,19 @@
             _certs = self.metadata.certs(sp_entity_id, "any", "encryption")
         exception = None
         for _cert in _certs:
+            wrapped_cert, unwrapped_cert = get_pem_wrapped_unwrapped(_cert)
             try:
-                begin_cert = "-----BEGIN CERTIFICATE-----\n"
-                end_cert = "\n-----END CERTIFICATE-----\n"
-                if begin_cert not in _cert:
-                    _cert = "%s%s" % (begin_cert, _cert)
-                if end_cert not in _cert:
-                    _cert = "%s%s" % (_cert, end_cert)
-                tmp = make_temp(_cert.encode('ascii'),
-                                decode=False,
-                                delete_tmpfiles=self.config.delete_tmpfiles)
-                response = self.sec.encrypt_assertion(response, tmp.name,
-                                                      pre_encryption_part(),
-                                                      node_xpath=node_xpath)
+                tmp = make_temp(
+                    wrapped_cert.encode('ascii'),
+                    decode=False,
+                    delete_tmpfiles=self.config.delete_tmpfiles,
+                )
+                response = self.sec.encrypt_assertion(
+                    response,
+                    tmp.name,
+                    pre_encryption_part(encrypt_cert=unwrapped_cert),
+                    node_xpath=node_xpath,
+                )
                 return response
             except Exception as ex:
                 exception = ex
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pysaml2-6.5.1/src/saml2/mdstore.py 
new/pysaml2-7.0.1/src/saml2/mdstore.py
--- old/pysaml2-6.5.1/src/saml2/mdstore.py      2021-01-21 00:08:02.000000000 
+0100
+++ new/pysaml2-7.0.1/src/saml2/mdstore.py      2021-05-20 18:56:31.000000000 
+0200
@@ -7,12 +7,13 @@
 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
+from re import compile as regex_compile
 
 import requests
+
 import six
 
 from saml2 import md
@@ -24,7 +25,6 @@
 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
@@ -59,6 +59,8 @@
 from saml2.extension.mdrpi import NAMESPACE as NS_MDRPI
 from saml2.extension.mdrpi import RegistrationInfo
 from saml2.extension.mdrpi import RegistrationPolicy
+from saml2.extension.shibmd import NAMESPACE as NS_SHIBMD
+from saml2.extension.shibmd import Scope
 
 
 logger = logging.getLogger(__name__)
@@ -84,6 +86,7 @@
     "service_nameid_mapping": "{ns}&{tag}".format(ns=NS_MD, 
tag=NameIDMappingService.c_tag),
     "mdrpi_registration_info": "{ns}&{tag}".format(ns=NS_MDRPI, 
tag=RegistrationInfo.c_tag),
     "mdrpi_registration_policy": "{ns}&{tag}".format(ns=NS_MDRPI, 
tag=RegistrationPolicy.c_tag),
+    "shibmd_scope": "{ns}&{tag}".format(ns=NS_SHIBMD, tag=Scope.c_tag)
 }
 
 ENTITY_CATEGORY = "http://macedir.org/entity-category";
@@ -612,7 +615,10 @@
             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)
@@ -1227,8 +1233,6 @@
         # IDP + SP
         if typ is None:
             raise AttributeError("Missing type specification")
-        if binding is None:
-            binding = BINDING_HTTP_REDIRECT
         return self.service(entity_id, "%s_descriptor" % typ,
                             "single_logout_service", binding)
 
@@ -1477,6 +1481,41 @@
         )
         return elements
 
+    def sbibmd_scopes(self, entity_id, typ=None):
+        try:
+            md = self[entity_id]
+        except KeyError:
+            md = {}
+
+        descriptor_scopes = (
+            {
+                "regexp": is_regexp,
+                "text": regex_compile(text) if is_regexp else text,
+            }
+            for elem in md.get("extensions", {}).get("extension_elements", [])
+            if elem.get("__class__") == classnames["shibmd_scope"]
+            for is_regexp, text in [
+                (elem.get("regexp", "").lower() == "true", elem.get("text", 
"")),
+            ]
+        )
+
+        services_of_type = md.get(typ) or []
+        services_of_type_scopes = (
+            {
+                "regexp": is_regexp,
+                "text": regex_compile(text) if is_regexp else text,
+            }
+            for srv in services_of_type
+            for elem in srv.get("extensions", {}).get("extension_elements", [])
+            if elem.get("__class__") == classnames["shibmd_scope"]
+            for is_regexp, text in [
+                (elem.get("regexp", "").lower() == "true", elem.get("text", 
"")),
+            ]
+        )
+
+        scopes = chain(descriptor_scopes, services_of_type_scopes)
+        return scopes
+
     def mdui_uiinfo(self, entity_id):
         try:
             data = self[entity_id]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pysaml2-6.5.1/src/saml2/response.py 
new/pysaml2-7.0.1/src/saml2/response.py
--- old/pysaml2-6.5.1/src/saml2/response.py     2021-01-21 00:08:02.000000000 
+0100
+++ new/pysaml2-7.0.1/src/saml2/response.py     2021-05-20 18:56:31.000000000 
+0200
@@ -67,6 +67,10 @@
     pass
 
 
+class InvalidAssertion(SAMLError):
+    pass
+
+
 class DecryptionFailed(SAMLError):
     pass
 
@@ -94,6 +98,9 @@
 class StatusInvalidAttrNameOrValue(StatusError):
     pass
 
+class StatusInvalidAuthnResponseStatement(StatusError):
+    pass
+
 
 class StatusInvalidNameidPolicy(StatusError):
     pass
@@ -209,10 +216,10 @@
         if not restriction.audience:
             continue
         for audience in restriction.audience:
-            if audience.text.strip() == myself:
+            if audience.text and audience.text.strip() == myself:
                 return True
             else:
-                logger.debug("AudienceRestriction - One condition not 
satisfied: %s != %s" % (audience.text.strip(), myself))
+                logger.debug("AudienceRestriction - One condition not 
satisfied: {} != {}".format(audience.text, myself))
     logger.debug("AudienceRestrictions not satisfied!")
     return False
 
@@ -428,7 +435,12 @@
         self.response = mold.response
 
     def issuer(self):
-        return self.response.issuer.text.strip()
+        issuer_value = (
+            self.response.issuer.text
+            if self.response.issuer is not None
+            else ""
+        ).strip()
+        return issuer_value
 
 
 class LogoutResponse(StatusResponse):
@@ -920,7 +932,7 @@
             n_assertions = len(self.response.assertion)
             n_assertions_enc = len(self.response.encrypted_assertion)
             if n_assertions != 1 and n_assertions_enc != 1 and self.assertion 
is None:
-                raise Exception(
+                raise InvalidAssertion(
                     "Invalid number of assertions in Response: {n}".format(
                         n=n_assertions+n_assertions_enc
                     )
@@ -1037,7 +1049,7 @@
             logger.error("Verification error on the response: %s", err)
             raise
         else:
-            if res is None:
+            if not res:
                 return None
 
         if not isinstance(self.response, samlp.Response):
@@ -1099,12 +1111,16 @@
             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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pysaml2-6.5.1/src/saml2/saml.py 
new/pysaml2-7.0.1/src/saml2/saml.py
--- old/pysaml2-6.5.1/src/saml2/saml.py 2021-01-21 00:08:02.000000000 +0100
+++ new/pysaml2-7.0.1/src/saml2/saml.py 2021-05-20 18:56:31.000000000 +0200
@@ -3,6 +3,17 @@
 #
 # Generated Mon May  2 14:23:33 2011 by parse_xsd.py version 0.4.
 #
+# A summary of available specifications can be found at:
+# https://wiki.oasis-open.org/security/FrontPage
+#
+# saml core specifications to be found at:
+# if any question arise please query the following pdf.
+# http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf
+# The specification was later updated with errata, and the new version is here:
+# 
https://www.oasis-open.org/committees/download.php/56776/sstc-saml-core-errata-2.0-wd-07.pdf
+#
+
+
 import base64
 
 from saml2.validate import valid_ipv4, MustValueError
@@ -17,32 +28,53 @@
 from saml2 import xmldsig as ds
 from saml2 import xmlenc as xenc
 
+# authentication information fields
 NAMESPACE = 'urn:oasis:names:tc:SAML:2.0:assertion'
 
-XSI_NAMESPACE = 'http://www.w3.org/2001/XMLSchema-instance'
+# xmlschema definition
+XSD = "xs"
+# xmlschema templates and extensions
 XS_NAMESPACE = 'http://www.w3.org/2001/XMLSchema'
-
+# xmlschema-instance, which contains several builtin attributes
+XSI_NAMESPACE = 'http://www.w3.org/2001/XMLSchema-instance'
+# xml soap namespace
+NS_SOAP_ENC = "http://schemas.xmlsoap.org/soap/encoding/";
+# type definitions for xmlschemas
 XSI_TYPE = '{%s}type' % XSI_NAMESPACE
+# nil type definition for xmlschemas 
 XSI_NIL = '{%s}nil' % XSI_NAMESPACE
 
+# idp and sp communicate usually about a subject(NameID)
+# the format determines the category the subject is in
+
+# custom subject
 NAMEID_FORMAT_UNSPECIFIED = (
     "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified")
+# subject as email address
 NAMEID_FORMAT_EMAILADDRESS = (
     "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress")
+# subject as x509 key
 NAMEID_FORMAT_X509SUBJECTNAME = (
     "urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName")
+# subject as windows domain name
 NAMEID_FORMAT_WINDOWSDOMAINQUALIFIEDNAME = (
     "urn:oasis:names:tc:SAML:1.1:nameid-format:WindowsDomainQualifiedName")
+# subject from a kerberos instance
 NAMEID_FORMAT_KERBEROS = (
     "urn:oasis:names:tc:SAML:2.0:nameid-format:kerberos")
+# subject as name
 NAMEID_FORMAT_ENTITY = (
     "urn:oasis:names:tc:SAML:2.0:nameid-format:entity")
+# linked subject
 NAMEID_FORMAT_PERSISTENT = (
     "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent")
+# annonymous subject
 NAMEID_FORMAT_TRANSIENT = (
     "urn:oasis:names:tc:SAML:2.0:nameid-format:transient")
+# subject avaiable in encrypted format
 NAMEID_FORMAT_ENCRYPTED = (
     "urn:oasis:names:tc:SAML:2.0:nameid-format:encrypted")
+# dicc for avaiable formats
 NAMEID_FORMATS_SAML2 = (
     ('NAMEID_FORMAT_EMAILADDRESS', NAMEID_FORMAT_EMAILADDRESS),
     ('NAMEID_FORMAT_ENCRYPTED', NAMEID_FORMAT_ENCRYPTED),
@@ -51,41 +83,80 @@
     ('NAMEID_FORMAT_TRANSIENT', NAMEID_FORMAT_TRANSIENT),
     ('NAMEID_FORMAT_UNSPECIFIED', NAMEID_FORMAT_UNSPECIFIED),
 )
+
+# a profile outlines a set of rules describing how to embed SAML assertions.
+# https://docs.oasis-open.org/security/saml/v2.0/saml-profiles-2.0-os.pdf
+# The specification was later updated with errata, and the new version is here:
+# 
https://www.oasis-open.org/committees/download.php/56782/sstc-saml-profiles-errata-2.0-wd-07.pdf
+
+# XML based values for SAML attributes  
 PROFILE_ATTRIBUTE_BASIC = (
     "urn:oasis:names:tc:SAML:2.0:profiles:attribute:basic")
 
+# an AuthnRequest is made to initiate authentication
+# authenticate the request with login credentials
 AUTHN_PASSWORD = "urn:oasis:names:tc:SAML:2.0:ac:classes:Password"
+# authenticate the request with login credentials, over tls/https
 AUTHN_PASSWORD_PROTECTED = \
     "urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport"
 
+# attribute statements is key:value metadata shared with your app
+
+# custom format
 NAME_FORMAT_UNSPECIFIED = (
     "urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified")
+# uri format
 NAME_FORMAT_URI = "urn:oasis:names:tc:SAML:2.0:attrname-format:uri"
+# XML-based format
 NAME_FORMAT_BASIC = "urn:oasis:names:tc:SAML:2.0:attrname-format:basic"
+# dicc for avaiable formats
 NAME_FORMATS_SAML2 = (
     ('NAME_FORMAT_BASIC', NAME_FORMAT_BASIC),
     ('NAME_FORMAT_URI', NAME_FORMAT_URI),
     ('NAME_FORMAT_UNSPECIFIED', NAME_FORMAT_UNSPECIFIED),
 )
+
+# the SAML authority's decision can be predetermined by arbitrary context
+
+# the specified action is permitted
 DECISION_TYPE_PERMIT = "Permit"
+# the specified action is denied
 DECISION_TYPE_DENY = "Deny"
+# the SAML authority cannot determine if the action is permitted or denied
 DECISION_TYPE_INDETERMINATE = "Indeterminate"
 
+
+# consent attributes determine wether consent has been given and under
+# what conditions
+
+# no claim to consent is made
 CONSENT_UNSPECIFIED = "urn:oasis:names:tc:SAML:2.0:consent:unspecified"
+# consent has been obtained
 CONSENT_OBTAINED = "urn:oasis:names:tc:SAML:2.0:consent:obtained"
+# consent has been obtained before the message has been initiated
 CONSENT_PRIOR = "urn:oasis:names:tc:SAML:2.0:consent:prior"
+# consent has been obtained implicitly
 CONSENT_IMPLICIT = "urn:oasis:names:tc:SAML:2.0:consent:current-implicit"
+# consent has been obtained explicitly
 CONSENT_EXPLICIT = "urn:oasis:names:tc:SAML:2.0:consent:current-explicit"
+# no consent has been obtained
 CONSENT_UNAVAILABLE = "urn:oasis:names:tc:SAML:2.0:consent:unavailable"
+# no consent is needed.
 CONSENT_INAPPLICABLE = "urn:oasis:names:tc:SAML:2.0:consent:inapplicable"
 
+
+# Subject confirmation methods(scm), can be issued, besides the subject itself
+# by third parties.
+# http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.0.pdf
+
+# the 3rd party is identified on behalf of the subject given private/public key
 SCM_HOLDER_OF_KEY = "urn:oasis:names:tc:SAML:2.0:cm:holder-of-key"
+# the 3rd party is identified by subject confirmation and must include a 
security header
+# signing its content.
 SCM_SENDER_VOUCHES = "urn:oasis:names:tc:SAML:2.0:cm:sender-vouches"
+# a bearer token is issued instead.
 SCM_BEARER = "urn:oasis:names:tc:SAML:2.0:cm:bearer"
 
-XSD = "xs"
-NS_SOAP_ENC = "http://schemas.xmlsoap.org/soap/encoding/";
-
 
 class AttributeValueBase(SamlBase):
     def __init__(self,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pysaml2-6.5.1/src/saml2/sigver.py 
new/pysaml2-7.0.1/src/saml2/sigver.py
--- old/pysaml2-6.5.1/src/saml2/sigver.py       2021-01-21 00:08:02.000000000 
+0100
+++ new/pysaml2-7.0.1/src/saml2/sigver.py       2021-05-20 18:56:31.000000000 
+0200
@@ -7,6 +7,7 @@
 import itertools
 import logging
 import os
+import re
 import six
 from uuid import uuid4 as gen_random_key
 from time import mktime
@@ -59,9 +60,10 @@
 
 SIG = '{{{ns}#}}{attribute}'.format(ns=ds.NAMESPACE, attribute='Signature')
 
+# RSA_1_5 is considered deprecated
 RSA_1_5 = 'http://www.w3.org/2001/04/xmlenc#rsa-1_5'
 TRIPLE_DES_CBC = 'http://www.w3.org/2001/04/xmlenc#tripledes-cbc'
-
+RSA_OAEP_MGF1P = "http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p";
 
 class SigverError(SAMLError):
     pass
@@ -100,6 +102,14 @@
     pass
 
 
+def get_pem_wrapped_unwrapped(cert):
+    begin_cert = "-----BEGIN CERTIFICATE-----\n"
+    end_cert = "\n-----END CERTIFICATE-----\n"
+    unwrapped_cert = re.sub(f'{begin_cert}|{end_cert}', '', cert)
+    wrapped_cert = f'{begin_cert}{unwrapped_cert}{end_cert}'
+    return wrapped_cert, unwrapped_cert
+
+
 def read_file(*args, **kwargs):
     with open(*args, **kwargs) as handler:
         return handler.read()
@@ -1085,10 +1095,8 @@
         pass
 
     if _encrypt_cert is not None:
-        if _encrypt_cert.find('-----BEGIN CERTIFICATE-----\n') == -1:
-            _encrypt_cert = '-----BEGIN CERTIFICATE-----\n' + _encrypt_cert
-        if _encrypt_cert.find('\n-----END CERTIFICATE-----') == -1:
-            _encrypt_cert = _encrypt_cert + '\n-----END CERTIFICATE-----'
+        wrapped_cert, unwrapped_cert = get_pem_wrapped_unwrapped(_encrypt_cert)
+        _encrypt_cert = wrapped_cert
     return _encrypt_cert
 
 
@@ -1835,6 +1843,7 @@
     if identifier:
         signature.id = 'Signature{n}'.format(n=identifier)
 
+    # XXX remove - do not embed the cert
     if public_key:
         x509_data = ds.X509Data(
             x509_certificate=[ds.X509Certificate(text=public_key)])
@@ -1872,23 +1881,34 @@
 # </EncryptedData>
 
 
-def pre_encryption_part(msg_enc=TRIPLE_DES_CBC, key_enc=RSA_1_5, 
key_name='my-rsa-key',
-        encrypted_key_id=None, encrypted_data_id=None):
-    """
-
-    :param msg_enc:
-    :param key_enc:
-    :param key_name:
-    :return:
-    """
+def pre_encryption_part(
+    *,
+    msg_enc=TRIPLE_DES_CBC,
+    key_enc=RSA_OAEP_MGF1P,
+    key_name='my-rsa-key',
+    encrypted_key_id=None,
+    encrypted_data_id=None,
+    encrypt_cert=None,
+):
     ek_id = encrypted_key_id or "EK_{id}".format(id=gen_random_key())
     ed_id = encrypted_data_id or "ED_{id}".format(id=gen_random_key())
     msg_encryption_method = EncryptionMethod(algorithm=msg_enc)
     key_encryption_method = EncryptionMethod(algorithm=key_enc)
+
+    x509_data = (
+        ds.X509Data(x509_certificate=ds.X509Certificate(text=encrypt_cert))
+        if encrypt_cert
+        else None
+    )
+    key_info = ds.KeyInfo(
+        key_name=ds.KeyName(text=key_name),
+        x509_data=x509_data,
+    )
+
     encrypted_key = EncryptedKey(
         id=ek_id,
         encryption_method=key_encryption_method,
-        key_info=ds.KeyInfo(key_name=ds.KeyName(text=key_name)),
+        key_info=key_info,
         cipher_data=CipherData(cipher_value=CipherValue(text='')),
     )
     key_info = ds.KeyInfo(encrypted_key=encrypted_key)
@@ -1897,7 +1917,8 @@
         type='http://www.w3.org/2001/04/xmlenc#Element',
         encryption_method=msg_encryption_method,
         key_info=key_info,
-        cipher_data=CipherData(cipher_value=CipherValue(text='')))
+        cipher_data=CipherData(cipher_value=CipherValue(text='')),
+    )
     return encrypted_data
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pysaml2-6.5.1/tests/entity_no_friendly_name_sp.xml 
new/pysaml2-7.0.1/tests/entity_no_friendly_name_sp.xml
--- old/pysaml2-6.5.1/tests/entity_no_friendly_name_sp.xml      1970-01-01 
01:00:00.000000000 +0100
+++ new/pysaml2-7.0.1/tests/entity_no_friendly_name_sp.xml      2021-05-20 
18:56:31.000000000 +0200
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ns0:EntityDescriptor xmlns:ns0="urn:oasis:names:tc:SAML:2.0:metadata" 
xmlns:ns1="http://www.w3.org/2000/09/xmldsig#"; 
xmlns:mdrpi="urn:oasis:names:tc:SAML:metadata:rpi" 
entityID="https://no-friendly-name.example.edu/saml2/metadata/";>
+  <ns0:Extensions>
+      <mdrpi:RegistrationInfo registrationAuthority="http://geant.example.eu/"; 
registrationInstant="2018-05-10T09:45:00Z" />
+      <mdattr:EntityAttributes 
xmlns:mdattr="urn:oasis:names:tc:SAML:metadata:attribute">
+          <saml:Attribute xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" 
Name="http://macedir.org/entity-category"; 
NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
+              
<saml:AttributeValue>http://www.geant.net/uri/dataprotection-code-of-conduct/v1</saml:AttributeValue></saml:Attribute>
+      </mdattr:EntityAttributes></ns0:Extensions>
+  <ns0:SPSSODescriptor AuthnRequestsSigned="false" WantAssertionsSigned="true" 
protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
+    <ns0:KeyDescriptor use="encryption">
+      <ns1:KeyInfo>
+        <ns1:X509Data>
+          
<ns1:X509Certificate>MIIDvDCCAqQCCQDXVjecpE8ibTANBgkqhkiG9w0BAQUFADCBnzELMAkGA1UEBhMC
+U0UxEjAQBgNVBAgMCVN0b2NraG9sbTESMBAGA1UEBwwJU3RvY2tob2xtMQ4wDAYD
+VQQKDAVFRFVJRDEaMBgGA1UECwwRZWR1aWQuZXhhbXBsZS5jb20xGjAYBgNVBAMM
+EWVkdWlkLmV4YW1wbGUuY29tMSAwHgYJKoZIhvcNAQkBFhFlZHVpZEBleGFtcGxl
+LmNvbTAeFw0xMzA2MTIxMTU5NTdaFw0yMzA2MTAxMTU5NTdaMIGfMQswCQYDVQQG
+EwJTRTESMBAGA1UECAwJU3RvY2tob2xtMRIwEAYDVQQHDAlTdG9ja2hvbG0xDjAM
+BgNVBAoMBUVEVUlEMRowGAYDVQQLDBFlZHVpZC5leGFtcGxlLmNvbTEaMBgGA1UE
+AwwRZWR1aWQuZXhhbXBsZS5jb20xIDAeBgkqhkiG9w0BCQEWEWVkdWlkQGV4YW1w
+bGUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwHzXvBlv+DN1
+0tV9z6M79RFKJEE1HoBpo/vuQzcIP8SZZNhzwQpYxTVTQ9ocagX1onfJn2ZjoWsi
+p45tSMnwLM9a9+UETYAV8O/AUq3gNDp+Mu6sS3smNhdykVR4STscIiP/hWMkZbJ4
+4dmJ2ccT3H6VosXR/OIVTjyalanmvMpDb6ZkKqmuQCDvRMii/R0HhbYUCytToDiy
+Bxw1tQG946g8pe5RhZxxzmxVwAGwOyDn1dwi+j4wH2eCDyLu8hLanPHNFNiy5hiN
+5B40N24V5YixlksgdT0pF46DfkJRrOCsNWHWnMSN+Xvo1oXLRFXEnfsCB1cw0EAp
+SMMGX4dhSwIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQA8+faeCQVTadTrXpB8jzfE
+MJq6+V4oajnWb0LJ5ZZcKSlQZ5sfYJ1385CaXGh60Tg4uhtwTOgpRi1R1cZMLTz9
+ST6WPF+2vDJv7dGPuglzyQLvA2fd6BLnyGV6kLUc2XNOyCmD/tWuMvKvW62j4Y3B
+XZvRFZZdHNgay4Wgvs8D6wyozWpkWpawXkQ3LqbXO6GChYC4VLru+uJuMKvvKCd/
+I125dzkP2nf9zkGV0cil3oIVSBPBtSRTF/M+oZhkHTwoM6hhonRvdOLuvobKfZ2Q
+wHyaxzYldWmVC5omkgZeAdCGpJ316GQF8Zwg/yDOUzm4cvGeIESf1Q6ZxBwI6zGE
+</ns1:X509Certificate>
+        </ns1:X509Data>
+      </ns1:KeyInfo>
+    </ns0:KeyDescriptor>
+    <ns0:KeyDescriptor use="signing">
+      <ns1:KeyInfo>
+        <ns1:X509Data>
+          
<ns1:X509Certificate>MIIDvDCCAqQCCQDXVjecpE8ibTANBgkqhkiG9w0BAQUFADCBnzELMAkGA1UEBhMC
+U0UxEjAQBgNVBAgMCVN0b2NraG9sbTESMBAGA1UEBwwJU3RvY2tob2xtMQ4wDAYD
+VQQKDAVFRFVJRDEaMBgGA1UECwwRZWR1aWQuZXhhbXBsZS5jb20xGjAYBgNVBAMM
+EWVkdWlkLmV4YW1wbGUuY29tMSAwHgYJKoZIhvcNAQkBFhFlZHVpZEBleGFtcGxl
+LmNvbTAeFw0xMzA2MTIxMTU5NTdaFw0yMzA2MTAxMTU5NTdaMIGfMQswCQYDVQQG
+EwJTRTESMBAGA1UECAwJU3RvY2tob2xtMRIwEAYDVQQHDAlTdG9ja2hvbG0xDjAM
+BgNVBAoMBUVEVUlEMRowGAYDVQQLDBFlZHVpZC5leGFtcGxlLmNvbTEaMBgGA1UE
+AwwRZWR1aWQuZXhhbXBsZS5jb20xIDAeBgkqhkiG9w0BCQEWEWVkdWlkQGV4YW1w
+bGUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwHzXvBlv+DN1
+0tV9z6M79RFKJEE1HoBpo/vuQzcIP8SZZNhzwQpYxTVTQ9ocagX1onfJn2ZjoWsi
+p45tSMnwLM9a9+UETYAV8O/AUq3gNDp+Mu6sS3smNhdykVR4STscIiP/hWMkZbJ4
+4dmJ2ccT3H6VosXR/OIVTjyalanmvMpDb6ZkKqmuQCDvRMii/R0HhbYUCytToDiy
+Bxw1tQG946g8pe5RhZxxzmxVwAGwOyDn1dwi+j4wH2eCDyLu8hLanPHNFNiy5hiN
+5B40N24V5YixlksgdT0pF46DfkJRrOCsNWHWnMSN+Xvo1oXLRFXEnfsCB1cw0EAp
+SMMGX4dhSwIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQA8+faeCQVTadTrXpB8jzfE
+MJq6+V4oajnWb0LJ5ZZcKSlQZ5sfYJ1385CaXGh60Tg4uhtwTOgpRi1R1cZMLTz9
+ST6WPF+2vDJv7dGPuglzyQLvA2fd6BLnyGV6kLUc2XNOyCmD/tWuMvKvW62j4Y3B
+XZvRFZZdHNgay4Wgvs8D6wyozWpkWpawXkQ3LqbXO6GChYC4VLru+uJuMKvvKCd/
+I125dzkP2nf9zkGV0cil3oIVSBPBtSRTF/M+oZhkHTwoM6hhonRvdOLuvobKfZ2Q
+wHyaxzYldWmVC5omkgZeAdCGpJ316GQF8Zwg/yDOUzm4cvGeIESf1Q6ZxBwI6zGE
+</ns1:X509Certificate>
+        </ns1:X509Data>
+      </ns1:KeyInfo>
+    </ns0:KeyDescriptor>
+    <ns0:SingleLogoutService 
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" 
Location="https://no-friendly-name.example.edu/saml2/ls/"/>
+    <ns0:AssertionConsumerService 
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" 
Location="https://no-friendly-name.example.edu/saml2/acs/"; index="1"/>
+    <!-- Require eduPersonTargetedID -->
+    <ns0:AttributeConsumingService index="0">
+        <ns0:ServiceName xml:lang="en">no-friendlyName-SP</ns0:ServiceName>
+        <ns0:ServiceDescription xml:lang="en">No friendlyName 
SP</ns0:ServiceDescription>
+        <ns0:RequestedAttribute Name="urn:oid:1.3.6.1.4.1.5923.1.1.1.10" 
NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true" 
/>
+    </ns0:AttributeConsumingService>
+  </ns0:SPSSODescriptor>
+  <ns0:Organization>
+    <ns0:OrganizationName xml:lang="es">Example CO</ns0:OrganizationName>
+    <ns0:OrganizationName xml:lang="en">Example CO</ns0:OrganizationName>
+    <ns0:OrganizationDisplayName 
xml:lang="es">Example</ns0:OrganizationDisplayName>
+    <ns0:OrganizationDisplayName 
xml:lang="en">Example</ns0:OrganizationDisplayName>
+    <ns0:OrganizationURL 
xml:lang="es">http://www.example.edu</ns0:OrganizationURL>
+    <ns0:OrganizationURL 
xml:lang="en">http://www.example.com</ns0:OrganizationURL>
+  </ns0:Organization>
+  <ns0:ContactPerson contactType="technical">
+    <ns0:Company>Example CO</ns0:Company>
+    <ns0:GivenName>Sysadmin</ns0:GivenName>
+    <ns0:SurName/>
+    <ns0:EmailAddress>[email protected]</ns0:EmailAddress>
+  </ns0:ContactPerson>
+  <ns0:ContactPerson contactType="administrative">
+    <ns0:Company>Example CO</ns0:Company>
+    <ns0:GivenName>Admin</ns0:GivenName>
+    <ns0:SurName>CEO</ns0:SurName>
+    <ns0:EmailAddress>[email protected]</ns0:EmailAddress>
+  </ns0:ContactPerson>
+</ns0:EntityDescriptor>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pysaml2-6.5.1/tests/idp_uiinfo.xml 
new/pysaml2-7.0.1/tests/idp_uiinfo.xml
--- old/pysaml2-6.5.1/tests/idp_uiinfo.xml      2021-01-21 00:08:02.000000000 
+0100
+++ new/pysaml2-7.0.1/tests/idp_uiinfo.xml      2021-05-20 18:56:31.000000000 
+0200
@@ -1,17 +1,19 @@
 <?xml version='1.0' encoding='UTF-8'?>
-<ns0:EntitiesDescriptor xmlns:ns0="urn:oasis:names:tc:SAML:2.0:metadata" 
xmlns:ns1="urn:mace:shibboleth:metadata:1.0" 
xmlns:ns2="urn:oasis:names:tc:SAML:metadata:ui" 
xmlns:ns3="http://www.w3.org/2000/09/xmldsig#";><ns0:EntityDescriptor 
entityID="http://example.com/saml2/idp.xml";><ns0:IDPSSODescriptor 
WantAuthnRequestsSigned="false" 
protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"><ns0:Extensions><ns1:Scope
 regexp="false">example.org</ns1:Scope><ns2:UIInfo><ns2:Keywords 
xml:lang="en">foo bar</ns2:Keywords><ns2:Logo height="40" 
width="30">http://example.com/logo.jpg</ns2:Logo><ns2:InformationURL>http://example.com/saml2/info.html</ns2:InformationURL><ns2:DisplayName>Example
 Co.</ns2:DisplayName><ns2:Description xml:lang="se">Exempel 
bolag</ns2:Description><ns2:PrivacyStatementURL>http://example.com/saml2/privacyStatement.html</ns2:PrivacyStatementURL></ns2:UIInfo></ns0:Extensions><ns0:KeyDescriptor><ns3:KeyInfo><ns3:X509Data><ns3:X509Certificate>MIICsDCCAhmgAwIBAgIJAJr
 zqSSwmDY9MA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
-BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX
-aWRnaXRzIFB0eSBMdGQwHhcNMDkxMDA2MTk0OTQxWhcNMDkxMTA1MTk0OTQxWjBF
-MQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50
-ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB
-gQDJg2cms7MqjniT8Fi/XkNHZNPbNVQyMUMXE9tXOdqwYCA1cc8vQdzkihscQMXy
-3iPw2cMggBu6gjMTOSOxECkuvX5ZCclKr8pXAJM5cY6gVOaVO2PdTZcvDBKGbiaN
-efiEw5hnoZomqZGp8wHNLAUkwtH9vjqqvxyS/vclc6k2ewIDAQABo4GnMIGkMB0G
-A1UdDgQWBBRePsKHKYJsiojE78ZWXccK9K4aJTB1BgNVHSMEbjBsgBRePsKHKYJs
-iojE78ZWXccK9K4aJaFJpEcwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUt
-U3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZIIJAJrzqSSw
-mDY9MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAJSrKOEzHO7TL5cy6
-h3qh+3+JAk8HbGBW+cbX6KBCAw/mzU8flK25vnWwXS3dv2FF3Aod0/S7AWNfKib5
-U/SA9nJaz/mWeF9S0farz9AQFc8/NSzAzaVq7YbM4F6f6N2FRl7GikdXRCed45j6
-mrPzGzk3ECbupFnqyREH3+ZPSdk=
-</ns3:X509Certificate></ns3:X509Data></ns3:KeyInfo></ns0:KeyDescriptor><ns0:SingleSignOnService
 Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" 
Location="http://example.com/saml2/"; 
/></ns0:IDPSSODescriptor></ns0:EntityDescriptor></ns0:EntitiesDescriptor>
+<ns0:EntitiesDescriptor xmlns:ns0="urn:oasis:names:tc:SAML:2.0:metadata" 
xmlns:ns1="urn:mace:shibboleth:metadata:1.0" 
xmlns:ns2="urn:oasis:names:tc:SAML:metadata:ui" 
xmlns:ns3="http://www.w3.org/2000/09/xmldsig#";>
+    <ns0:EntityDescriptor entityID="http://example.com/saml2/idp.xml";>
+        <ns0:Extensions>
+            <ns1:Scope regexp="false">descriptor-example.org</ns1:Scope>
+            <ns1:Scope regexp="true">descriptor-example[^0-9]*\.org</ns1:Scope>
+        </ns0:Extensions>
+        <ns0:IDPSSODescriptor WantAuthnRequestsSigned="false" 
protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
+            <ns0:Extensions>
+                <ns1:Scope 
regexp="false">idpssodescriptor-example.org</ns1:Scope>
+                <ns2:UIInfo><ns2:Keywords xml:lang="en">foo 
bar</ns2:Keywords><ns2:Logo height="40" 
width="30">http://example.com/logo.jpg</ns2:Logo><ns2:InformationURL>http://example.com/saml2/info.html</ns2:InformationURL><ns2:DisplayName>Example
 Co.</ns2:DisplayName><ns2:Description xml:lang="se">Exempel 
bolag</ns2:Description><ns2:PrivacyStatementURL>http://example.com/saml2/privacyStatement.html</ns2:PrivacyStatementURL></ns2:UIInfo>
+            </ns0:Extensions>
+            <ns0:KeyDescriptor>
+                
<ns3:KeyInfo><ns3:X509Data><ns3:X509Certificate>MIICsDCCAhmgAwIBAgIJAJrzqSSwmDY9MA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwHhcNMDkxMDA2MTk0OTQxWhcNMDkxMTA1MTk0OTQxWjBFMQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDJg2cms7MqjniT8Fi/XkNHZNPbNVQyMUMXE9tXOdqwYCA1cc8vQdzkihscQMXy3iPw2cMggBu6gjMTOSOxECkuvX5ZCclKr8pXAJM5cY6gVOaVO2PdTZcvDBKGbiaNefiEw5hnoZomqZGp8wHNLAUkwtH9vjqqvxyS/vclc6k2ewIDAQABo4GnMIGkMB0GA1UdDgQWBBRePsKHKYJsiojE78ZWXccK9K4aJTB1BgNVHSMEbjBsgBRePsKHKYJsiojE78ZWXccK9K4aJaFJpEcwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZIIJAJrzqSSwmDY9MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAJSrKOEzHO7TL5cy6h3qh+3+JAk8HbGBW+cbX6KBCAw/mzU8flK25vnWwXS3dv2FF3Aod0/S7AWNfKib5U/SA9nJaz/mWeF9S0farz9AQFc8/NSzAzaVq7YbM4F6f6N2FRl7GikdXRCed45j6mrPzGzk3ECbupFnqyREH3+ZPSdk=</ns3:X50
 9Certificate></ns3:X509Data></ns3:KeyInfo>
+            </ns0:KeyDescriptor>
+            <ns0:SingleSignOnService 
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" 
Location="http://example.com/saml2/"; />
+        </ns0:IDPSSODescriptor>
+    </ns0:EntityDescriptor>
+</ns0:EntitiesDescriptor>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pysaml2-6.5.1/tests/invalid_metadata_file.xml 
new/pysaml2-7.0.1/tests/invalid_metadata_file.xml
--- old/pysaml2-6.5.1/tests/invalid_metadata_file.xml   1970-01-01 
01:00:00.000000000 +0100
+++ new/pysaml2-7.0.1/tests/invalid_metadata_file.xml   2021-05-20 
18:56:31.000000000 +0200
@@ -0,0 +1 @@
+this content is invalid
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pysaml2-6.5.1/tests/test_30_mdstore.py 
new/pysaml2-7.0.1/tests/test_30_mdstore.py
--- old/pysaml2-6.5.1/tests/test_30_mdstore.py  2021-01-21 00:08:02.000000000 
+0100
+++ new/pysaml2-7.0.1/tests/test_30_mdstore.py  2021-05-20 18:56:31.000000000 
+0200
@@ -3,10 +3,13 @@
 import datetime
 import os
 import re
+from re import compile as regex_compile
 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 +22,7 @@
 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 +160,14 @@
         "class": "saml2.mdstore.MetaDataFile",
         "metadata": [(full_path("swamid-2.0.xml"),)],
     }],
+    "14": [{
+        "class": "saml2.mdstore.MetaDataFile",
+        "metadata": [(full_path("invalid_metadata_file.xml"),)],
+    }],
+    "15": [{
+        "class": "saml2.mdstore.MetaDataFile",
+        "metadata": [(full_path("idp_uiinfo.xml"),)],
+    }],
 }
 
 
@@ -170,6 +182,12 @@
                   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,
@@ -595,5 +613,50 @@
     assert mds.extension("entity2", "idpsso_descriptor", "test")
 
 
+def test_shibmd_scope_no_regex_no_descriptor_type():
+    mds = MetadataStore(ATTRCONV, sec_config, 
disable_ssl_certificate_validation=True)
+    mds.imp(METADATACONF["15"])
+
+    scopes = mds.sbibmd_scopes(entity_id='http://example.com/saml2/idp.xml')
+    all_scopes = list(scopes)
+
+    expected = [
+        {
+            "regexp": False,
+            "text": "descriptor-example.org",
+        },
+        {
+            "regexp": True,
+            "text": regex_compile("descriptor-example[^0-9]*\.org"),
+        },
+    ]
+    assert len(all_scopes) == 2
+    assert all_scopes == expected
+
+
+def test_shibmd_scope_no_regex_all_descriptors():
+    mds = MetadataStore(ATTRCONV, sec_config, 
disable_ssl_certificate_validation=True)
+    mds.imp(METADATACONF["15"])
+
+    scopes = mds.sbibmd_scopes(entity_id='http://example.com/saml2/idp.xml', 
typ="idpsso_descriptor")
+    all_scopes = list(scopes)
+    expected = [
+        {
+            "regexp": False,
+            "text": "descriptor-example.org",
+        },
+        {
+            "regexp": True,
+            "text": regex_compile("descriptor-example[^0-9]*\.org"),
+        },
+        {
+            "regexp": False,
+            "text": "idpssodescriptor-example.org",
+        },
+    ]
+    assert len(all_scopes) == 3
+    assert all_scopes == expected
+
+
 if __name__ == "__main__":
     test_metadata_extension_algsupport()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pysaml2-6.5.1/tests/test_37_entity_categories.py 
new/pysaml2-7.0.1/tests/test_37_entity_categories.py
--- old/pysaml2-6.5.1/tests/test_37_entity_categories.py        2021-01-21 
00:08:02.000000000 +0100
+++ new/pysaml2-7.0.1/tests/test_37_entity_categories.py        2021-05-20 
18:56:31.000000000 +0200
@@ -1,11 +1,16 @@
 from contextlib import closing
-from saml2 import sigver
+
+from pathutils import full_path
 from saml2 import config
+from saml2 import sigver
 from saml2.assertion import Policy
 from saml2.attribute_converter import ac_factory
-from pathutils import full_path
+from saml2.extension import mdattr
+from saml2.mdie import to_dict
 from saml2.mdstore import MetadataStore
+from saml2.saml import Attribute, NAME_FORMAT_URI
 from saml2.server import Server
+from saml2.md import RequestedAttribute
 
 
 ATTRCONV = ac_factory(full_path("attributemaps"))
@@ -228,3 +233,48 @@
             "sn"
         ]
     )
+
+
+def test_filter_ava_required_attributes_with_no_friendly_name():
+    entity_id = "https://no-friendly-name.example.edu/saml2/metadata/";
+    mds = MetadataStore(ATTRCONV, sec_config, 
disable_ssl_certificate_validation=True)
+    mds.imp(
+        [
+            {
+                "class": "saml2.mdstore.MetaDataFile",
+                "metadata": [(full_path("entity_no_friendly_name_sp.xml"),)]
+            }
+        ]
+    )
+
+    policy_conf = {
+        "default": {
+            "lifetime": {"minutes": 15},
+            "entity_categories": ["swamid"]
+        }
+    }
+    policy = Policy(policy_conf, mds)
+
+    ava = {
+        "givenName": ["Derek"],
+        "sn": ["Jeter"],
+        "mail": ["[email protected]"],
+        "c": ["USA"],
+        "eduPersonTargetedID": "foo!bar!xyz",
+        "norEduPersonNIN": "19800101134",
+    }
+
+    attribute_requirements = mds.attribute_requirement(entity_id)
+    required = attribute_requirements.get("required", [])
+    optional = attribute_requirements.get("optional", [])
+
+    # ensure the requirements define the eduPersonTargetedID
+    # without the friendlyName attribute
+    oid_eptid = 'urn:oid:1.3.6.1.4.1.5923.1.1.1.10'
+    requested_attribute_eptid = RequestedAttribute(
+        name=oid_eptid, name_format=NAME_FORMAT_URI, is_required='true'
+    )
+    assert required == [to_dict(requested_attribute_eptid, onts=[mdattr])]
+
+    ava = policy.filter(ava, entity_id, required=required, optional=optional)
+    assert _eq(list(ava.keys()), ["eduPersonTargetedID"])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pysaml2-6.5.1/tests/test_41_response.py 
new/pysaml2-7.0.1/tests/test_41_response.py
--- old/pysaml2-6.5.1/tests/test_41_response.py 2021-01-21 00:08:02.000000000 
+0100
+++ new/pysaml2-7.0.1/tests/test_41_response.py 2021-05-20 18:56:31.000000000 
+0200
@@ -48,28 +48,38 @@
 
             self._resp_ = server.create_authn_response(
                 IDENTITY,
-                "id12",  # in_response_to
-                "http://lingon.catalogix.se:8087/";,
-                # consumer_url
-                "urn:mace:example.com:saml:roland:sp",
-                # sp_entity_id
-                name_id=name_id)
+                in_response_to="id12",
+                destination="http://lingon.catalogix.se:8087/";,
+                sp_entity_id="urn:mace:example.com:saml:roland:sp",
+                name_id=name_id,
+            )
 
             self._sign_resp_ = server.create_authn_response(
                 IDENTITY,
-                "id12",  # in_response_to
-                "http://lingon.catalogix.se:8087/";,  # consumer_url
-                "urn:mace:example.com:saml:roland:sp",  # sp_entity_id
+                in_response_to="id12",
+                destination="http://lingon.catalogix.se:8087/";,
+                sp_entity_id="urn:mace:example.com:saml:roland:sp",
                 name_id=name_id,
-                sign_assertion=True)
+                sign_assertion=True,
+            )
 
             self._resp_authn = server.create_authn_response(
                 IDENTITY,
-                "id12",  # in_response_to
-                "http://lingon.catalogix.se:8087/";,  # consumer_url
-                "urn:mace:example.com:saml:roland:sp",  # sp_entity_id
+                in_response_to="id12",
+                destination="http://lingon.catalogix.se:8087/";,
+                sp_entity_id="urn:mace:example.com:saml:roland:sp",
+                name_id=name_id,
+                authn=AUTHN,
+            )
+
+            self._resp_issuer_none = server.create_authn_response(
+                IDENTITY,
+                in_response_to="id12",
+                destination="http://lingon.catalogix.se:8087/";,
+                sp_entity_id="urn:mace:example.com:saml:roland:sp",
                 name_id=name_id,
-                authn=AUTHN)
+            )
+            self._resp_issuer_none.issuer = None
 
             conf = config.SPConfig()
             conf.load_file("server_conf")
@@ -77,27 +87,45 @@
 
     def test_1(self):
         xml_response = ("%s" % (self._resp_,))
-        resp = response_factory(xml_response, self.conf,
-                                return_addrs=[
-                                    "http://lingon.catalogix.se:8087/";],
-                                outstanding_queries={
-                                    "id12": "http://localhost:8088/sso"},
-                                timeslack=TIMESLACK, decode=False)
+        resp = response_factory(
+            xml_response, self.conf,
+            return_addrs=["http://lingon.catalogix.se:8087/";],
+            outstanding_queries={"id12": "http://localhost:8088/sso"},
+            timeslack=TIMESLACK,
+            decode=False,
+        )
 
         assert isinstance(resp, StatusResponse)
         assert isinstance(resp, AuthnResponse)
 
     def test_2(self):
         xml_response = self._sign_resp_
-        resp = response_factory(xml_response, self.conf,
-                                return_addrs=[
-                                    "http://lingon.catalogix.se:8087/";],
-                                outstanding_queries={
-                                    "id12": "http://localhost:8088/sso"},
-                                timeslack=TIMESLACK, decode=False)
+        resp = response_factory(
+            xml_response,
+            self.conf,
+            return_addrs=["http://lingon.catalogix.se:8087/";],
+            outstanding_queries={"id12": "http://localhost:8088/sso"},
+            timeslack=TIMESLACK,
+            decode=False,
+        )
+
+        assert isinstance(resp, StatusResponse)
+        assert isinstance(resp, AuthnResponse)
+
+    def test_issuer_none(self):
+        xml_response = ("%s" % (self._resp_issuer_none,))
+        resp = response_factory(
+            xml_response,
+            self.conf,
+            return_addrs=["http://lingon.catalogix.se:8087/";],
+            outstanding_queries={"id12": "http://localhost:8088/sso"},
+            timeslack=TIMESLACK,
+            decode=False,
+        )
 
         assert isinstance(resp, StatusResponse)
         assert isinstance(resp, AuthnResponse)
+        assert resp.issuer() == ""
 
     @mock.patch('saml2.time_util.datetime')
     def test_false_sign(self, mock_datetime):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pysaml2-6.5.1/tests/test_42_enc.py 
new/pysaml2-7.0.1/tests/test_42_enc.py
--- old/pysaml2-6.5.1/tests/test_42_enc.py      2021-01-21 00:08:02.000000000 
+0100
+++ new/pysaml2-7.0.1/tests/test_42_enc.py      2021-05-20 18:56:31.000000000 
+0200
@@ -12,8 +12,8 @@
 
 __author__ = 'roland'
 
-TMPL_NO_HEADER = """<ns0:EncryptedData 
xmlns:ns0="http://www.w3.org/2001/04/xmlenc#"; 
xmlns:ns1="http://www.w3.org/2000/09/xmldsig#"; Id="{ed_id}" 
Type="http://www.w3.org/2001/04/xmlenc#Element";><ns0:EncryptionMethod 
Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc"; 
/><ns1:KeyInfo><ns0:EncryptedKey Id="{ek_id}"><ns0:EncryptionMethod 
Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5"; 
/><ns1:KeyInfo><ns1:KeyName>my-rsa-key</ns1:KeyName></ns1:KeyInfo><ns0:CipherData><ns0:CipherValue
 
/></ns0:CipherData></ns0:EncryptedKey></ns1:KeyInfo><ns0:CipherData><ns0:CipherValue
 /></ns0:CipherData></ns0:EncryptedData>"""
-TMPL = "<?xml version='1.0' encoding='UTF-8'?>\n%s" % TMPL_NO_HEADER
+TMPL_NO_HEADER = """<ns0:EncryptedData 
xmlns:ns0="http://www.w3.org/2001/04/xmlenc#"; 
xmlns:ns1="http://www.w3.org/2000/09/xmldsig#"; Id="{ed_id}" 
Type="http://www.w3.org/2001/04/xmlenc#Element";><ns0:EncryptionMethod 
Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc"; 
/><ns1:KeyInfo><ns0:EncryptedKey Id="{ek_id}"><ns0:EncryptionMethod 
Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p"; 
/><ns1:KeyInfo><ns1:KeyName>my-rsa-key</ns1:KeyName></ns1:KeyInfo><ns0:CipherData><ns0:CipherValue
 
/></ns0:CipherData></ns0:EncryptedKey></ns1:KeyInfo><ns0:CipherData><ns0:CipherValue
 /></ns0:CipherData></ns0:EncryptedData>"""
+TMPL = f"<?xml version='1.0' encoding='UTF-8'?>\n{TMPL_NO_HEADER}"
 
 IDENTITY = {"eduPersonAffiliation": ["staff", "member"],
             "surName": ["Jeter"], "givenName": ["Derek"],
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pysaml2-6.5.1/tests/test_50_server.py 
new/pysaml2-7.0.1/tests/test_50_server.py
--- old/pysaml2-6.5.1/tests/test_50_server.py   2021-01-21 00:08:02.000000000 
+0100
+++ new/pysaml2-7.0.1/tests/test_50_server.py   2021-05-20 18:56:31.000000000 
+0200
@@ -6,6 +6,7 @@
 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 @@
         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 @@
     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
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pysaml2-6.5.1/tests/test_60_sp.py 
new/pysaml2-7.0.1/tests/test_60_sp.py
--- old/pysaml2-6.5.1/tests/test_60_sp.py       2021-01-21 00:08:02.000000000 
+0100
+++ new/pysaml2-7.0.1/tests/test_60_sp.py       2021-05-20 18:56:31.000000000 
+0200
@@ -1,7 +1,8 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
-import base64
+from base64 import encodebytes as b64encode
+
 import pytest
 from saml2.authn_context import INTERNETPROTOCOLPASSWORD
 from saml2.saml import NAMEID_FORMAT_TRANSIENT
@@ -73,7 +74,7 @@
             "urn:mace:example.com:saml:roland:sp", trans_name_policy,
             "[email protected]", authn=AUTHN)
 
-        resp_str = base64.encodestring(resp_str.encode('utf-8'))
+        resp_str = b64encode(resp_str.encode('utf-8'))
         self.sp.outstanding_queries = {"id1": "http://www.example.com/service"}
         session_info = self.sp._eval_authn_response(
             {}, {"SAMLResponse": [resp_str]})

Reply via email to