diff options
author | Roland Hedberg <roland@catalogix.se> | 2017-09-28 15:11:37 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-09-28 15:11:37 +0200 |
commit | 34c3b87764c48c60799a53b98f2b01469eee9675 (patch) | |
tree | 9a9f9d5fd8826aad3f9bc7a061f13c3eb4861ff0 | |
parent | 7b5cb73ac232ac7d1ed0f2a1bf19efdbaec1301e (diff) | |
parent | 232696285745f19f1d828519e34ec66427ad72a4 (diff) | |
download | pysaml2-34c3b87764c48c60799a53b98f2b01469eee9675.tar.gz |
Merge branch 'master' into fix_sane_defaults
-rw-r--r-- | src/saml2/attribute_converter.py | 2 | ||||
-rw-r--r-- | src/saml2/pack.py | 49 | ||||
-rw-r--r-- | src/saml2/validate.py | 14 | ||||
-rw-r--r-- | tests/test_51_client.py | 10 | ||||
-rw-r--r-- | tests/test_65_authn_query.py | 2 | ||||
-rw-r--r-- | tests/test_68_assertion_id.py | 2 |
6 files changed, 52 insertions, 27 deletions
diff --git a/src/saml2/attribute_converter.py b/src/saml2/attribute_converter.py index 3d52a816..3d32d226 100644 --- a/src/saml2/attribute_converter.py +++ b/src/saml2/attribute_converter.py @@ -246,7 +246,7 @@ def get_local_name(acs, attr, name_format): for aconv in acs: #print(ac.format, name_format) if aconv.name_format == name_format: - return aconv._fro[attr] + return aconv._fro.get(attr) def d_to_local_name(acs, attr): diff --git a/src/saml2/pack.py b/src/saml2/pack.py index 728a516f..3bf39fc8 100644 --- a/src/saml2/pack.py +++ b/src/saml2/pack.py @@ -40,12 +40,35 @@ except ImportError: import defusedxml.ElementTree NAMESPACE = "http://schemas.xmlsoap.org/soap/envelope/" -FORM_SPEC = """<form method="post" action="%s"> - <input type="hidden" name="%s" value="%s" /> - <input type="hidden" name="RelayState" value="%s" /> - <input type="submit" value="Submit" /> -</form>""" +FORM_SPEC = """\ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8" /> + </head> + <body onload="document.forms[0].submit()"> + <noscript> + <p> + <strong>Note:</strong> Since your browser does not support JavaScript, + you must press the Continue button once to proceed. + </p> + </noscript> + + <form action="{action}" method="post"> + <div> + <input type="hidden" name="RelayState" value="{relay_state}"/> + + <input type="hidden" name="{saml_type}" value="{saml_response}"/> + </div> + <noscript> + <div> + <input type="submit" value="Continue"/> + </div> + </noscript> + </form> + </body> +</html>""" def http_form_post_message(message, location, relay_state="", typ="SAMLRequest", **kwargs): @@ -58,8 +81,6 @@ def http_form_post_message(message, location, relay_state="", :param relay_state: for preserving and conveying state information :return: A tuple containing header information and a HTML message. """ - response = ["<head>", """<title>SAML 2.0 POST</title>""", "</head><body>"] - if not isinstance(message, six.string_types): message = str(message) if not isinstance(message, six.binary_type): @@ -71,17 +92,17 @@ def http_form_post_message(message, location, relay_state="", _msg = message _msg = _msg.decode('ascii') - response.append(FORM_SPEC % (location, typ, _msg, relay_state)) + args = { + 'action' : location, + 'saml_type' : typ, + 'relay_state' : relay_state, + 'saml_response' : _msg + } - response.append("""<script type="text/javascript">""") - response.append(" window.onload = function ()") - response.append(" { document.forms[0].submit(); }") - response.append("""</script>""") - response.append("</body>") + response = FORM_SPEC.format(**args) return {"headers": [("Content-type", "text/html")], "data": response} - def http_post_message(message, relay_state="", typ="SAMLRequest", **kwargs): """ diff --git a/src/saml2/validate.py b/src/saml2/validate.py index de68fc00..9fe12c4d 100644 --- a/src/saml2/validate.py +++ b/src/saml2/validate.py @@ -3,6 +3,7 @@ from six.moves.urllib.parse import urlparse import re import struct import base64 +import time from saml2 import time_util @@ -42,8 +43,8 @@ NCNAME = re.compile("(?P<NCName>[a-zA-Z_](\w|[_.-])*)") def valid_ncname(name): match = NCNAME.match(name) - if not match: - raise NotValid("NCName") + #if not match: # hack for invalid authnRequest/ID from meteor saml lib + # raise NotValid("NCName") return True @@ -90,8 +91,10 @@ def validate_on_or_after(not_on_or_after, slack): now = time_util.utc_now() nooa = calendar.timegm(time_util.str_to_time(not_on_or_after)) if now > nooa + slack: + now_str=time.strftime('%Y-%M-%dT%H:%M:%SZ', time.gmtime(now)) raise ResponseLifetimeExceed( - "Can't use it, it's too old %d > %d" % (now - slack, nooa)) + "Can't use repsonse, too old (now=%s + slack=%d > " \ + "not_on_or_after=%s" % (now_str, slack, not_on_or_after)) return nooa else: return False @@ -102,8 +105,9 @@ def validate_before(not_before, slack): now = time_util.utc_now() nbefore = calendar.timegm(time_util.str_to_time(not_before)) if nbefore > now + slack: - raise ToEarly("Can't use it yet %d <= %d" % (now + slack, nbefore)) - + now_str = time.strftime('%Y-%M-%dT%H:%M:%SZ', time.gmtime(now)) + raise ToEarly("Can't use response yet: (now=%s + slack=%d) " + "<= notbefore=%s" % (now_str, slack, not_before)) return True diff --git a/tests/test_51_client.py b/tests/test_51_client.py index 688d73d7..42651fbe 100644 --- a/tests/test_51_client.py +++ b/tests/test_51_client.py @@ -1404,7 +1404,7 @@ class TestClient: binding, info = resp[entity_ids[0]] assert binding == BINDING_HTTP_POST - _dic = unpack_form(info["data"][3]) + _dic = unpack_form(info["data"]) res = self.server.parse_logout_request(_dic["SAMLRequest"], BINDING_HTTP_POST) assert b'<ns0:SessionIndex>_foo</ns0:SessionIndex>' in res.xmlstr @@ -1434,7 +1434,7 @@ class TestClient: binding, info = resp[entity_ids[0]] assert binding == BINDING_HTTP_POST - _dic = unpack_form(info["data"][3]) + _dic = unpack_form(info["data"]) res = self.server.parse_logout_request(_dic["SAMLRequest"], BINDING_HTTP_POST) assert b'<ns0:SessionIndex>_foo</ns0:SessionIndex>' in res.xmlstr @@ -1531,7 +1531,7 @@ class TestClientWithDummy(): sid, http_args = self.client.prepare_for_authenticate( "urn:mace:example.com:saml:roland:idp", relay_state="really", binding=binding, response_binding=response_binding) - _dic = unpack_form(http_args["data"][3]) + _dic = unpack_form(http_args["data"]) req = self.server.parse_authn_request(_dic["SAMLRequest"], binding) resp_args = self.server.response_args(req.message, [response_binding]) @@ -1566,7 +1566,7 @@ class TestClientWithDummy(): sid, auth_binding, http_args = self.client.prepare_for_negotiated_authenticate( "urn:mace:example.com:saml:roland:idp", relay_state="really", binding=binding, response_binding=response_binding) - _dic = unpack_form(http_args["data"][3]) + _dic = unpack_form(http_args["data"]) assert binding == auth_binding @@ -1586,7 +1586,7 @@ class TestClientWithDummy(): response = self.client.send(**http_args) print(response.text) - _dic = unpack_form(response.text[3], "SAMLResponse") + _dic = unpack_form(response.text, "SAMLResponse") resp = self.client.parse_authn_request_response(_dic["SAMLResponse"], BINDING_HTTP_POST, {sid: "/"}) diff --git a/tests/test_65_authn_query.py b/tests/test_65_authn_query.py index bd258238..77ccaa9e 100644 --- a/tests/test_65_authn_query.py +++ b/tests/test_65_authn_query.py @@ -28,7 +28,7 @@ def get_msg(hinfo, binding): if binding == BINDING_SOAP: xmlstr = hinfo["data"] elif binding == BINDING_HTTP_POST: - _inp = hinfo["data"][3] + _inp = hinfo["data"] i = _inp.find(TAG1) i += len(TAG1) + 1 j = _inp.find('"', i) diff --git a/tests/test_68_assertion_id.py b/tests/test_68_assertion_id.py index 60e85828..31b7e8e0 100644 --- a/tests/test_68_assertion_id.py +++ b/tests/test_68_assertion_id.py @@ -27,7 +27,7 @@ def get_msg(hinfo, binding, response=False): if binding == BINDING_SOAP: msg = hinfo["data"] elif binding == BINDING_HTTP_POST: - _inp = hinfo["data"][3] + _inp = hinfo["data"] i = _inp.find(TAG1) i += len(TAG1) + 1 j = _inp.find('"', i) |