Skip to content

Commit 8a60225

Browse files
Merge pull request #794 from johanlundberg/lundberg_fix_missing_friendly_name
Fix crash when applying policy on RequestedAttribute without a friendlyName
2 parents 4c550f5 + 8d3fd70 commit 8a60225

File tree

3 files changed

+155
-3
lines changed

3 files changed

+155
-3
lines changed

src/saml2/assertion.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -454,7 +454,16 @@ def get_entity_categories(self, sp_entity_id, mds=None, required=None):
454454

455455
def post_entity_categories(maps, sp_entity_id=None, mds=None, required=None):
456456
restrictions = {}
457-
required = [d['friendly_name'].lower() for d in (required or [])]
457+
required_friendly_names = [
458+
d.get('friendly_name') or get_local_name(
459+
acs=self.acs, attr=d['name'], name_format=d['name_format']
460+
)
461+
for d in (required or [])
462+
]
463+
required = [
464+
friendly_name.lower()
465+
for friendly_name in required_friendly_names
466+
]
458467

459468
if mds:
460469
ecs = mds.entity_categories(sp_entity_id)

tests/entity_no_friendly_name_sp.xml

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<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/">
3+
<ns0:Extensions>
4+
<mdrpi:RegistrationInfo registrationAuthority="http://geant.example.eu/" registrationInstant="2018-05-10T09:45:00Z" />
5+
<mdattr:EntityAttributes xmlns:mdattr="urn:oasis:names:tc:SAML:metadata:attribute">
6+
<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">
7+
<saml:AttributeValue>http://www.geant.net/uri/dataprotection-code-of-conduct/v1</saml:AttributeValue></saml:Attribute>
8+
</mdattr:EntityAttributes></ns0:Extensions>
9+
<ns0:SPSSODescriptor AuthnRequestsSigned="false" WantAssertionsSigned="true" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
10+
<ns0:KeyDescriptor use="encryption">
11+
<ns1:KeyInfo>
12+
<ns1:X509Data>
13+
<ns1:X509Certificate>MIIDvDCCAqQCCQDXVjecpE8ibTANBgkqhkiG9w0BAQUFADCBnzELMAkGA1UEBhMC
14+
U0UxEjAQBgNVBAgMCVN0b2NraG9sbTESMBAGA1UEBwwJU3RvY2tob2xtMQ4wDAYD
15+
VQQKDAVFRFVJRDEaMBgGA1UECwwRZWR1aWQuZXhhbXBsZS5jb20xGjAYBgNVBAMM
16+
EWVkdWlkLmV4YW1wbGUuY29tMSAwHgYJKoZIhvcNAQkBFhFlZHVpZEBleGFtcGxl
17+
LmNvbTAeFw0xMzA2MTIxMTU5NTdaFw0yMzA2MTAxMTU5NTdaMIGfMQswCQYDVQQG
18+
EwJTRTESMBAGA1UECAwJU3RvY2tob2xtMRIwEAYDVQQHDAlTdG9ja2hvbG0xDjAM
19+
BgNVBAoMBUVEVUlEMRowGAYDVQQLDBFlZHVpZC5leGFtcGxlLmNvbTEaMBgGA1UE
20+
AwwRZWR1aWQuZXhhbXBsZS5jb20xIDAeBgkqhkiG9w0BCQEWEWVkdWlkQGV4YW1w
21+
bGUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwHzXvBlv+DN1
22+
0tV9z6M79RFKJEE1HoBpo/vuQzcIP8SZZNhzwQpYxTVTQ9ocagX1onfJn2ZjoWsi
23+
p45tSMnwLM9a9+UETYAV8O/AUq3gNDp+Mu6sS3smNhdykVR4STscIiP/hWMkZbJ4
24+
4dmJ2ccT3H6VosXR/OIVTjyalanmvMpDb6ZkKqmuQCDvRMii/R0HhbYUCytToDiy
25+
Bxw1tQG946g8pe5RhZxxzmxVwAGwOyDn1dwi+j4wH2eCDyLu8hLanPHNFNiy5hiN
26+
5B40N24V5YixlksgdT0pF46DfkJRrOCsNWHWnMSN+Xvo1oXLRFXEnfsCB1cw0EAp
27+
SMMGX4dhSwIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQA8+faeCQVTadTrXpB8jzfE
28+
MJq6+V4oajnWb0LJ5ZZcKSlQZ5sfYJ1385CaXGh60Tg4uhtwTOgpRi1R1cZMLTz9
29+
ST6WPF+2vDJv7dGPuglzyQLvA2fd6BLnyGV6kLUc2XNOyCmD/tWuMvKvW62j4Y3B
30+
XZvRFZZdHNgay4Wgvs8D6wyozWpkWpawXkQ3LqbXO6GChYC4VLru+uJuMKvvKCd/
31+
I125dzkP2nf9zkGV0cil3oIVSBPBtSRTF/M+oZhkHTwoM6hhonRvdOLuvobKfZ2Q
32+
wHyaxzYldWmVC5omkgZeAdCGpJ316GQF8Zwg/yDOUzm4cvGeIESf1Q6ZxBwI6zGE
33+
</ns1:X509Certificate>
34+
</ns1:X509Data>
35+
</ns1:KeyInfo>
36+
</ns0:KeyDescriptor>
37+
<ns0:KeyDescriptor use="signing">
38+
<ns1:KeyInfo>
39+
<ns1:X509Data>
40+
<ns1:X509Certificate>MIIDvDCCAqQCCQDXVjecpE8ibTANBgkqhkiG9w0BAQUFADCBnzELMAkGA1UEBhMC
41+
U0UxEjAQBgNVBAgMCVN0b2NraG9sbTESMBAGA1UEBwwJU3RvY2tob2xtMQ4wDAYD
42+
VQQKDAVFRFVJRDEaMBgGA1UECwwRZWR1aWQuZXhhbXBsZS5jb20xGjAYBgNVBAMM
43+
EWVkdWlkLmV4YW1wbGUuY29tMSAwHgYJKoZIhvcNAQkBFhFlZHVpZEBleGFtcGxl
44+
LmNvbTAeFw0xMzA2MTIxMTU5NTdaFw0yMzA2MTAxMTU5NTdaMIGfMQswCQYDVQQG
45+
EwJTRTESMBAGA1UECAwJU3RvY2tob2xtMRIwEAYDVQQHDAlTdG9ja2hvbG0xDjAM
46+
BgNVBAoMBUVEVUlEMRowGAYDVQQLDBFlZHVpZC5leGFtcGxlLmNvbTEaMBgGA1UE
47+
AwwRZWR1aWQuZXhhbXBsZS5jb20xIDAeBgkqhkiG9w0BCQEWEWVkdWlkQGV4YW1w
48+
bGUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwHzXvBlv+DN1
49+
0tV9z6M79RFKJEE1HoBpo/vuQzcIP8SZZNhzwQpYxTVTQ9ocagX1onfJn2ZjoWsi
50+
p45tSMnwLM9a9+UETYAV8O/AUq3gNDp+Mu6sS3smNhdykVR4STscIiP/hWMkZbJ4
51+
4dmJ2ccT3H6VosXR/OIVTjyalanmvMpDb6ZkKqmuQCDvRMii/R0HhbYUCytToDiy
52+
Bxw1tQG946g8pe5RhZxxzmxVwAGwOyDn1dwi+j4wH2eCDyLu8hLanPHNFNiy5hiN
53+
5B40N24V5YixlksgdT0pF46DfkJRrOCsNWHWnMSN+Xvo1oXLRFXEnfsCB1cw0EAp
54+
SMMGX4dhSwIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQA8+faeCQVTadTrXpB8jzfE
55+
MJq6+V4oajnWb0LJ5ZZcKSlQZ5sfYJ1385CaXGh60Tg4uhtwTOgpRi1R1cZMLTz9
56+
ST6WPF+2vDJv7dGPuglzyQLvA2fd6BLnyGV6kLUc2XNOyCmD/tWuMvKvW62j4Y3B
57+
XZvRFZZdHNgay4Wgvs8D6wyozWpkWpawXkQ3LqbXO6GChYC4VLru+uJuMKvvKCd/
58+
I125dzkP2nf9zkGV0cil3oIVSBPBtSRTF/M+oZhkHTwoM6hhonRvdOLuvobKfZ2Q
59+
wHyaxzYldWmVC5omkgZeAdCGpJ316GQF8Zwg/yDOUzm4cvGeIESf1Q6ZxBwI6zGE
60+
</ns1:X509Certificate>
61+
</ns1:X509Data>
62+
</ns1:KeyInfo>
63+
</ns0:KeyDescriptor>
64+
<ns0:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://no-friendly-name.example.edu/saml2/ls/"/>
65+
<ns0:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://no-friendly-name.example.edu/saml2/acs/" index="1"/>
66+
<!-- Require eduPersonTargetedID -->
67+
<ns0:AttributeConsumingService index="0">
68+
<ns0:ServiceName xml:lang="en">no-friendlyName-SP</ns0:ServiceName>
69+
<ns0:ServiceDescription xml:lang="en">No friendlyName SP</ns0:ServiceDescription>
70+
<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" />
71+
</ns0:AttributeConsumingService>
72+
</ns0:SPSSODescriptor>
73+
<ns0:Organization>
74+
<ns0:OrganizationName xml:lang="es">Example CO</ns0:OrganizationName>
75+
<ns0:OrganizationName xml:lang="en">Example CO</ns0:OrganizationName>
76+
<ns0:OrganizationDisplayName xml:lang="es">Example</ns0:OrganizationDisplayName>
77+
<ns0:OrganizationDisplayName xml:lang="en">Example</ns0:OrganizationDisplayName>
78+
<ns0:OrganizationURL xml:lang="es">http://www.example.edu</ns0:OrganizationURL>
79+
<ns0:OrganizationURL xml:lang="en">http://www.example.com</ns0:OrganizationURL>
80+
</ns0:Organization>
81+
<ns0:ContactPerson contactType="technical">
82+
<ns0:Company>Example CO</ns0:Company>
83+
<ns0:GivenName>Sysadmin</ns0:GivenName>
84+
<ns0:SurName/>
85+
<ns0:EmailAddress>[email protected]</ns0:EmailAddress>
86+
</ns0:ContactPerson>
87+
<ns0:ContactPerson contactType="administrative">
88+
<ns0:Company>Example CO</ns0:Company>
89+
<ns0:GivenName>Admin</ns0:GivenName>
90+
<ns0:SurName>CEO</ns0:SurName>
91+
<ns0:EmailAddress>[email protected]</ns0:EmailAddress>
92+
</ns0:ContactPerson>
93+
</ns0:EntityDescriptor>

tests/test_37_entity_categories.py

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
from contextlib import closing
2-
from saml2 import sigver
2+
3+
from pathutils import full_path
34
from saml2 import config
5+
from saml2 import sigver
46
from saml2.assertion import Policy
57
from saml2.attribute_converter import ac_factory
6-
from pathutils import full_path
8+
from saml2.extension import mdattr
9+
from saml2.mdie import to_dict
710
from saml2.mdstore import MetadataStore
11+
from saml2.saml import Attribute, NAME_FORMAT_URI
812
from saml2.server import Server
13+
from saml2.md import RequestedAttribute
914

1015

1116
ATTRCONV = ac_factory(full_path("attributemaps"))
@@ -228,3 +233,48 @@ def test_entity_category_import_from_path():
228233
"sn"
229234
]
230235
)
236+
237+
238+
def test_filter_ava_required_attributes_with_no_friendly_name():
239+
entity_id = "https://no-friendly-name.example.edu/saml2/metadata/"
240+
mds = MetadataStore(ATTRCONV, sec_config, disable_ssl_certificate_validation=True)
241+
mds.imp(
242+
[
243+
{
244+
"class": "saml2.mdstore.MetaDataFile",
245+
"metadata": [(full_path("entity_no_friendly_name_sp.xml"),)]
246+
}
247+
]
248+
)
249+
250+
policy_conf = {
251+
"default": {
252+
"lifetime": {"minutes": 15},
253+
"entity_categories": ["swamid"]
254+
}
255+
}
256+
policy = Policy(policy_conf, mds)
257+
258+
ava = {
259+
"givenName": ["Derek"],
260+
"sn": ["Jeter"],
261+
"mail": ["[email protected]"],
262+
"c": ["USA"],
263+
"eduPersonTargetedID": "foo!bar!xyz",
264+
"norEduPersonNIN": "19800101134",
265+
}
266+
267+
attribute_requirements = mds.attribute_requirement(entity_id)
268+
required = attribute_requirements.get("required", [])
269+
optional = attribute_requirements.get("optional", [])
270+
271+
# ensure the requirements define the eduPersonTargetedID
272+
# without the friendlyName attribute
273+
oid_eptid = 'urn:oid:1.3.6.1.4.1.5923.1.1.1.10'
274+
requested_attribute_eptid = RequestedAttribute(
275+
name=oid_eptid, name_format=NAME_FORMAT_URI, is_required='true'
276+
)
277+
assert required == [to_dict(requested_attribute_eptid, onts=[mdattr])]
278+
279+
ava = policy.filter(ava, entity_id, required=required, optional=optional)
280+
assert _eq(list(ava.keys()), ["eduPersonTargetedID"])

0 commit comments

Comments
 (0)