Skip to content

Commit cb1b82d

Browse files
committed
Merge pull request mehcode#2 from AMeng/verify-bad-signatures
Dont raise exceptions for bad signatures
2 parents 5c497bf + fb4a234 commit cb1b82d

File tree

5 files changed

+59
-19
lines changed

5 files changed

+59
-19
lines changed

Diff for: .travis.yml

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ python:
55
- '3.4'
66

77
before_install:
8+
- 'travis_retry sudo apt-get update'
89
- 'travis_retry sudo apt-get install python-dev libxml2-dev libxmlsec1-dev'
910
- 'travis_retry pip install Cython --use-mirrors'
1011

Diff for: saml/__init__.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,15 @@
99
"""
1010
# Version of the library.
1111
from ._version import __version__, __version_info__ # noqa
12-
VERSION = __version__
1312

1413
# Version of the SAML standard supported.
1514
from .schema import VERSION as SAML_VERSION
1615

1716
from .signature import sign, verify
1817
from . import client
1918

19+
VERSION = __version__
20+
2021
__all__ = [
2122
'VERSION',
2223
'SAML_VERSION',

Diff for: saml/schema/base.py

+8-5
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ def _is_derived(cls, name, bases):
5555
# This is not derived at all from Resource (eg. is base).
5656
return False
5757

58+
@classmethod
59+
def _get_attributes_dict(cls, obj):
60+
return {n: getattr(obj, n) for n in dir(obj)}
61+
5862
def __new__(cls, name, bases, attrs):
5963
# Only continue if we are dervied from declarative.
6064
if not cls._is_derived(name, bases):
@@ -64,20 +68,19 @@ def __new__(cls, name, bases, attrs):
6468
# Gather the attributes of all options classes.
6569
# Start with the base configuration.
6670
metadata = {}
67-
values = lambda x: {n: getattr(x, n) for n in dir(x)}
6871

6972
# Expand the options class with the gathered metadata.
7073
base_meta = []
7174
cls._gather_metadata(base_meta, bases)
7275

7376
# Apply the configuration from each class in the chain.
7477
for meta in base_meta:
75-
metadata.update(**values(meta))
78+
metadata.update(**cls._get_attributes_dict(meta))
7679

7780
# Apply the configuration from the current class.
7881
cur_meta = {}
7982
if attrs.get('Meta'):
80-
cur_meta = values(attrs['Meta'])
83+
cur_meta = cls._get_attributes_dict(attrs['Meta'])
8184
metadata.update(**cur_meta)
8285

8386
# Gather and construct the options object.
@@ -93,8 +96,8 @@ def __new__(cls, name, bases, attrs):
9396
attrs['_items'].update(values)
9497

9598
# Collect attributes from current class.
96-
test = lambda x: issubclass(type(x[1]), Component)
97-
attrs_l = list(filter(test, attrs.items()))
99+
attrs_l = list(filter(lambda x: issubclass(type(x[1]), Component),
100+
attrs.items()))
98101
attrs_l.sort(key=lambda x: x[1].creation_counter)
99102
for key, attr in attrs_l:
100103
# If name reference is null; default to camel-cased name.

Diff for: saml/signature.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ def verify(xml, stream):
4848
signature_node = xmlsec.tree.find_node(xml, xmlsec.Node.SIGNATURE)
4949
if signature_node is None:
5050
# No `signature` node found; we cannot verify
51-
return None
51+
return False
5252

5353
# Create a digital signature context (no key manager is needed).
5454
ctx = xmlsec.SignatureContext()
@@ -72,4 +72,7 @@ def verify(xml, stream):
7272
ctx.key = key
7373

7474
# Verify the signature.
75-
return ctx.verify(signature_node)
75+
try:
76+
return ctx.verify(signature_node)
77+
except RuntimeError:
78+
return False

Diff for: tests/test_schema.py

+43-11
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import saml
2+
import xmlsec
23
from saml import schema
34
from saml.schema import utils
45
from datetime import datetime
@@ -279,13 +280,27 @@ def test_signed_deserialize(name):
279280
assert_node(expected, result)
280281

281282

282-
# NAMES = [
283-
# 'assertion',
284-
# 'response',
285-
# 'logout-response',
286-
# 'artifact-resolve',
287-
# 'artifact-response'
288-
# ]
283+
@mark.parametrize('name', NAMES)
284+
def test_generic_deserialize(name):
285+
filename = path.join(BASE_DIR, '%s-simple.xml' % name)
286+
parser = etree.XMLParser(
287+
ns_clean=True, remove_blank_text=True, remove_comments=True)
288+
target = etree.parse(filename, parser).getroot()
289+
290+
build_fn_name = ('build-%s-simple' % name).replace('-', '_')
291+
expected = globals()[build_fn_name]().serialize()
292+
293+
result = schema.deserialize(target).serialize()
294+
295+
assert_node(expected, result)
296+
297+
298+
def test_generic_deserialize_outside_registry():
299+
xml = build_authentication_request_simple().serialize()
300+
xml.tag = 'BadTagName'
301+
result = schema.deserialize(xml)
302+
303+
assert result is None
289304

290305

291306
@mark.parametrize('name', NAMES)
@@ -306,10 +321,6 @@ def test_sign(name):
306321
# Sign the result.
307322
saml.sign(result, stream)
308323

309-
# print()
310-
# print(etree.tostring(result).decode('utf8'))
311-
# print()
312-
313324
# Compare the nodes.
314325
assert_node(expected, result)
315326

@@ -323,3 +334,24 @@ def test_verify(name):
323334
# Sign the result.
324335
with open(path.join(BASE_DIR, 'rsapub.pem'), 'r') as stream:
325336
assert saml.verify(expected, stream)
337+
338+
339+
@mark.parametrize('name', NAMES)
340+
def test_verify_with_bad_signature_returns_False(name):
341+
filename = path.join(BASE_DIR, '%s-signed.xml' % name)
342+
expected = etree.parse(filename).getroot()
343+
344+
signature_node = xmlsec.tree.find_node(expected, xmlsec.Node.SIGNATURE)
345+
signature_node.clear()
346+
347+
with open(path.join(BASE_DIR, 'rsapub.pem'), 'r') as stream:
348+
assert saml.verify(expected, stream) is False
349+
350+
351+
@mark.parametrize('name', NAMES)
352+
def test_verify_with_no_signature_returns_False(name):
353+
filename = path.join(BASE_DIR, '%s-simple.xml' % name)
354+
expected = etree.parse(filename).getroot()
355+
356+
with open(path.join(BASE_DIR, 'rsapub.pem'), 'r') as stream:
357+
assert saml.verify(expected, stream) is False

0 commit comments

Comments
 (0)