Skip to content

Commit e9b4721

Browse files
author
Roland Hedberg
committed
Providing a certificate when the metadata is not signed should not result in an error. Refactored the code so there is less duplication.
1 parent 3e6b4c9 commit e9b4721

File tree

1 file changed

+61
-44
lines changed

1 file changed

+61
-44
lines changed

src/saml2/mdstore.py

Lines changed: 61 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,8 @@ def __init__(self, onts, attrc, metadata='', node_name=None,
119119
self.onts = onts
120120
self.attrc = attrc
121121
self.metadata = metadata
122+
self.entity = None
123+
self.cert = None
122124

123125
def items(self):
124126
'''
@@ -324,6 +326,10 @@ def __init__(self, onts, attrc, metadata="", node_name=None,
324326
self.entities_descr = None
325327
self.entity_descr = None
326328
self.check_validity = check_validity
329+
try:
330+
self.filter = kwargs["filter"]
331+
except KeyError:
332+
self.filter = None
327333

328334
def items(self):
329335
return self.entity.items()
@@ -391,6 +397,11 @@ def do_entity_descriptor(self, entity_descr):
391397
else:
392398
flag += 1
393399

400+
if self.filter:
401+
_ent = self.filter(_ent)
402+
if not _ent:
403+
flag = 0
404+
394405
if flag:
395406
self.entity[entity_descr.entity_id] = _ent
396407

@@ -536,6 +547,34 @@ def certs(self, entity_id, descriptor, use="signing"):
536547
res.append(dat["x509_certificate"]["text"])
537548
return res
538549

550+
def signed(self):
551+
if self.entities_descr and self.entities_descr.signature:
552+
return True
553+
554+
if self.entity_descr and self.entity_descr.signature:
555+
return True
556+
else:
557+
return False
558+
559+
def parse_and_check_signature(self, txt):
560+
self.parse(txt)
561+
562+
if self.cert:
563+
if not self.signed():
564+
return True
565+
566+
node_name = self.node_name \
567+
or "%s:%s" % (md.EntitiesDescriptor.c_namespace,
568+
md.EntitiesDescriptor.c_tag)
569+
570+
if self.security.verify_signature(
571+
txt, node_name=node_name, cert_file=self.cert):
572+
return True
573+
else:
574+
return False
575+
else:
576+
return True
577+
539578

540579
class MetaDataFile(InMemoryMetaData):
541580
"""
@@ -554,19 +593,7 @@ def get_metadata_content(self):
554593

555594
def load(self):
556595
_txt = self.get_metadata_content()
557-
if self.cert:
558-
node_name = self.node_name \
559-
or "%s:%s" % (md.EntitiesDescriptor.c_namespace,
560-
md.EntitiesDescriptor.c_tag)
561-
562-
if self.security.verify_signature(_txt,
563-
node_name=node_name,
564-
cert_file=self.cert):
565-
self.parse(_txt)
566-
return True
567-
else:
568-
self.parse(_txt)
569-
return True
596+
return self.parse_and_check_signature(_txt)
570597

571598

572599
class MetaDataLoader(MetaDataFile):
@@ -633,10 +660,9 @@ def __init__(self, onts, attrc, url=None, security=None, cert=None,
633660
raise SAMLError('URL not specified.')
634661
else:
635662
self.url = url
636-
if not cert:
637-
raise SAMLError('No certificate specified.')
638-
else:
639-
self.cert = cert
663+
664+
# No cert is only an error if the metadata is unsigned
665+
self.cert = cert
640666

641667
self.security = security
642668
self.http = http
@@ -648,20 +674,8 @@ def load(self):
648674
"""
649675
response = self.http.send(self.url)
650676
if response.status_code == 200:
651-
node_name = self.node_name \
652-
or "%s:%s" % (md.EntitiesDescriptor.c_namespace,
653-
md.EntitiesDescriptor.c_tag)
654-
655677
_txt = response.text.encode("utf-8")
656-
if self.cert:
657-
if self.security.verify_signature(_txt,
658-
node_name=node_name,
659-
cert_file=self.cert):
660-
self.parse(_txt)
661-
return True
662-
else:
663-
self.parse(_txt)
664-
return True
678+
return self.parse_and_check_signature(_txt)
665679
else:
666680
logger.info("Response status: %s" % response.status_code)
667681
return False
@@ -724,14 +738,7 @@ def __getitem__(self, item):
724738

725739
_txt = response.text.encode("utf-8")
726740

727-
if self.cert:
728-
if self.security.verify_signature(_txt,
729-
node_name=node_name,
730-
cert_file=self.cert):
731-
self.parse(_txt)
732-
return self.entity[item]
733-
else:
734-
self.parse(_txt)
741+
if self.parse_and_check_signature(_txt):
735742
return self.entity[item]
736743
else:
737744
logger.info("Response status: %s" % response.status_code)
@@ -741,7 +748,8 @@ def __getitem__(self, item):
741748
class MetadataStore(object):
742749
def __init__(self, onts, attrc, config, ca_certs=None,
743750
check_validity=True,
744-
disable_ssl_certificate_validation=False):
751+
disable_ssl_certificate_validation=False,
752+
filter=None):
745753
"""
746754
:params onts:
747755
:params attrc:
@@ -761,29 +769,35 @@ def __init__(self, onts, attrc, config, ca_certs=None,
761769
self.ii = 0
762770
self.metadata = {}
763771
self.check_validity = check_validity
772+
self.filter = filter
764773

765774
def load(self, typ, *args, **kwargs):
775+
if self.filter:
776+
_args = {"filter": self.filter}
777+
else:
778+
_args = {}
779+
766780
if typ == "local":
767781
key = args[0]
768782
# if library read every file in the library
769783
if os.path.isdir(key):
770784
files = [f for f in os.listdir(key) if isfile(join(key, f))]
771785
for fil in files:
772786
_fil = join(key, fil)
773-
_md = MetaDataFile(self.onts, self.attrc, _fil)
787+
_md = MetaDataFile(self.onts, self.attrc, _fil, **_args)
774788
_md.load()
775789
self.metadata[_fil] = _md
776790
return
777791
else:
778792
# else it's just a plain old file so read it
779-
_md = MetaDataFile(self.onts, self.attrc, key)
793+
_md = MetaDataFile(self.onts, self.attrc, key, **_args)
780794
elif typ == "inline":
781795
self.ii += 1
782796
key = self.ii
797+
kwargs.update(_args)
783798
_md = MetaData(self.onts, self.attrc, args[0], **kwargs)
784799
elif typ == "remote":
785800
key = kwargs["url"]
786-
_args = {}
787801
for _key in ["node_name", "check_validity"]:
788802
try:
789803
_args[_key] = kwargs[_key]
@@ -794,10 +808,10 @@ def load(self, typ, *args, **kwargs):
794808
kwargs["cert"], self.http, **_args)
795809
elif typ == "mdfile":
796810
key = args[0]
797-
_md = MetaDataMD(self.onts, self.attrc, args[0])
811+
_md = MetaDataMD(self.onts, self.attrc, args[0], **_args)
798812
elif typ == "loader":
799813
key = args[0]
800-
_md = MetaDataLoader(self.onts, self.attrc, args[0])
814+
_md = MetaDataLoader(self.onts, self.attrc, args[0], **_args)
801815
else:
802816
raise SAMLError("Unknown metadata type '%s'" % typ)
803817
_md.load()
@@ -837,6 +851,9 @@ def imp(self, spec):
837851
else:
838852
kwargs = {}
839853

854+
if self.filter:
855+
kwargs["filter"] = self.filter
856+
840857
for key in item['metadata']:
841858
# Separately handle MetaDataFile and directory
842859
if MDloader == MetaDataFile and os.path.isdir(key[0]):

0 commit comments

Comments
 (0)