Clean up
This commit is contained in:
@@ -29,19 +29,23 @@ from saml2.attribute_converter import to_local
|
|||||||
|
|
||||||
def _use_on_or_after(condition, slack):
|
def _use_on_or_after(condition, slack):
|
||||||
now = time.mktime(time.gmtime())
|
now = time.mktime(time.gmtime())
|
||||||
|
#print "NOW: %d" % now
|
||||||
not_on_or_after = time.mktime(str_to_time(condition.not_on_or_after))
|
not_on_or_after = time.mktime(str_to_time(condition.not_on_or_after))
|
||||||
|
#print "not_on_or_after: %d" % not_on_or_after
|
||||||
# slack is +-
|
# slack is +-
|
||||||
high = not_on_or_after+slack
|
high = not_on_or_after+slack
|
||||||
if now > high:
|
if now > high:
|
||||||
# To old ignore
|
# To old ignore
|
||||||
print "(%d > %d)" % (now,high)
|
#print "(%d > %d)" % (now,high)
|
||||||
raise Exception("To old can't use it!")
|
raise Exception("To old can't use it!")
|
||||||
return not_on_or_after
|
return not_on_or_after
|
||||||
|
|
||||||
def _use_before(condition, slack):
|
def _use_before(condition, slack):
|
||||||
not_before = time.mktime(str_to_time(condition.not_before))
|
|
||||||
now = time.mktime(time.gmtime())
|
now = time.mktime(time.gmtime())
|
||||||
|
#print "NOW: %s" % now
|
||||||
|
not_before = time.mktime(str_to_time(condition.not_before))
|
||||||
|
#print "not_before: %d" % not_before
|
||||||
|
|
||||||
if not_before > now + slack:
|
if not_before > now + slack:
|
||||||
# Can't use it yet
|
# Can't use it yet
|
||||||
raise Exception("Can't use it yet %s <= %s" % (not_before, now))
|
raise Exception("Can't use it yet %s <= %s" % (not_before, now))
|
||||||
@@ -54,8 +58,11 @@ def for_me(condition, myself ):
|
|||||||
if audience.text.strip() == myself:
|
if audience.text.strip() == myself:
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
print "%s != %s" % (audience.text.strip(), myself)
|
#print "Not for me: %s != %s" % (audience.text.strip(), myself)
|
||||||
|
pass
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
class IncorrectlySigned(Exception):
|
class IncorrectlySigned(Exception):
|
||||||
@@ -64,7 +71,7 @@ class IncorrectlySigned(Exception):
|
|||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
def authn_response(conf, requestor, outstanding_queries=None, log=None,
|
def authn_response(conf, requestor, outstanding_queries=None, log=None,
|
||||||
timeslack=0):
|
timeslack=0, debug=0):
|
||||||
sec = security_context(conf)
|
sec = security_context(conf)
|
||||||
if not timeslack:
|
if not timeslack:
|
||||||
try:
|
try:
|
||||||
@@ -73,7 +80,7 @@ def authn_response(conf, requestor, outstanding_queries=None, log=None,
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
return AuthnResponse(sec, conf.attribute_converters, requestor,
|
return AuthnResponse(sec, conf.attribute_converters, requestor,
|
||||||
outstanding_queries, log, timeslack)
|
outstanding_queries, log, timeslack, debug)
|
||||||
|
|
||||||
class AuthnResponse(object):
|
class AuthnResponse(object):
|
||||||
|
|
||||||
@@ -95,6 +102,8 @@ class AuthnResponse(object):
|
|||||||
self.clear()
|
self.clear()
|
||||||
|
|
||||||
def loads(self, xmldata, decode=True):
|
def loads(self, xmldata, decode=True):
|
||||||
|
if self.debug:
|
||||||
|
self.log.info("--- Loads AuthnResponse ---")
|
||||||
if decode:
|
if decode:
|
||||||
decoded_xml = base64.b64decode(xmldata)
|
decoded_xml = base64.b64decode(xmldata)
|
||||||
else:
|
else:
|
||||||
@@ -102,7 +111,13 @@ class AuthnResponse(object):
|
|||||||
|
|
||||||
# own copy
|
# own copy
|
||||||
self.xmlstr = decoded_xml[:]
|
self.xmlstr = decoded_xml[:]
|
||||||
self.response = self.sc.correctly_signed_response(decoded_xml)
|
if self.debug:
|
||||||
|
self.log.info("xmlstr: %s" % (self.xmlstr,))
|
||||||
|
try:
|
||||||
|
self.response = self.sc.correctly_signed_response(decoded_xml)
|
||||||
|
except Exception, excp:
|
||||||
|
self.log.info("EXCEPTION: %s", excp)
|
||||||
|
raise
|
||||||
|
|
||||||
if not self.response:
|
if not self.response:
|
||||||
if self.log:
|
if self.log:
|
||||||
@@ -111,7 +126,7 @@ class AuthnResponse(object):
|
|||||||
raise IncorrectlySigned()
|
raise IncorrectlySigned()
|
||||||
|
|
||||||
if self.debug:
|
if self.debug:
|
||||||
self.log.debug("response: %s" % (response,))
|
self.log.info("response: %s" % (self.response,))
|
||||||
|
|
||||||
return self
|
return self
|
||||||
|
|
||||||
@@ -127,6 +142,7 @@ class AuthnResponse(object):
|
|||||||
def status_ok(self):
|
def status_ok(self):
|
||||||
if self.response.status:
|
if self.response.status:
|
||||||
status = self.response.status
|
status = self.response.status
|
||||||
|
self.log.info("status: %s" % (status,))
|
||||||
if status.status_code.value != samlp.STATUS_SUCCESS:
|
if status.status_code.value != samlp.STATUS_SUCCESS:
|
||||||
if self.log:
|
if self.log:
|
||||||
self.log.info("Not successfull operation: %s" % status)
|
self.log.info("Not successfull operation: %s" % status)
|
||||||
@@ -151,7 +167,8 @@ class AuthnResponse(object):
|
|||||||
try:
|
try:
|
||||||
self.not_on_or_after = _use_on_or_after(condition, self.timeslack)
|
self.not_on_or_after = _use_on_or_after(condition, self.timeslack)
|
||||||
_use_before(condition, self.timeslack)
|
_use_before(condition, self.timeslack)
|
||||||
except Exception:
|
except Exception,excp:
|
||||||
|
self.log.error("Exception on condition: %s" % (excp,))
|
||||||
if not lax:
|
if not lax:
|
||||||
raise
|
raise
|
||||||
else:
|
else:
|
||||||
@@ -166,9 +183,14 @@ class AuthnResponse(object):
|
|||||||
def get_identity(self):
|
def get_identity(self):
|
||||||
# The assertion can contain zero or one attributeStatements
|
# The assertion can contain zero or one attributeStatements
|
||||||
if not self.assertion.attribute_statement:
|
if not self.assertion.attribute_statement:
|
||||||
|
self.log.error("Missing Attribute Statement")
|
||||||
ava = {}
|
ava = {}
|
||||||
else:
|
else:
|
||||||
assert len(self.assertion.attribute_statement) == 1
|
assert len(self.assertion.attribute_statement) == 1
|
||||||
|
self.log.info("Attribute Statement: %s" % (
|
||||||
|
self.assertion.attribute_statement[0],))
|
||||||
|
for ac in self.attribute_converters():
|
||||||
|
self.log.info("Converts name format: %s" % (ac.format,))
|
||||||
ava = to_local(self.attribute_converters(),
|
ava = to_local(self.attribute_converters(),
|
||||||
self.assertion.attribute_statement[0])
|
self.assertion.attribute_statement[0])
|
||||||
return ava
|
return ava
|
||||||
@@ -179,11 +201,11 @@ class AuthnResponse(object):
|
|||||||
subject = self.assertion.subject
|
subject = self.assertion.subject
|
||||||
for subject_confirmation in subject.subject_confirmation:
|
for subject_confirmation in subject.subject_confirmation:
|
||||||
data = subject_confirmation.subject_confirmation_data
|
data = subject_confirmation.subject_confirmation_data
|
||||||
if data.in_response_to in self.outstanding:
|
if data.in_response_to in self.outstanding_queries:
|
||||||
self.came_from = self.outstanding[data.in_response_to]
|
self.came_from = self.outstanding_queries[data.in_response_to]
|
||||||
del self.outstanding[data.in_response_to]
|
del self.outstanding_queries[data.in_response_to]
|
||||||
else:
|
else:
|
||||||
print data.in_response_to, self.outstanding.keys()
|
print data.in_response_to, self.outstanding_queries.keys()
|
||||||
raise Exception(
|
raise Exception(
|
||||||
"Combination of session id and requestURI I don't recall")
|
"Combination of session id and requestURI I don't recall")
|
||||||
|
|
||||||
@@ -195,9 +217,10 @@ class AuthnResponse(object):
|
|||||||
self.assertion = assertion
|
self.assertion = assertion
|
||||||
|
|
||||||
if self.debug:
|
if self.debug:
|
||||||
self.log.info("assertion context: %s" % (context,))
|
self.log.info("assertion context: %s" % (self.context,))
|
||||||
self.log.info("assertion keys: %s" % (assertion.keyswv()))
|
self.log.info("assertion keys: %s" % (assertion.keyswv()))
|
||||||
self.log.info("outstanding: %s" % (outstanding))
|
self.log.info("outstanding_queries: %s" % (
|
||||||
|
self.outstanding_queries))
|
||||||
|
|
||||||
if self.context == "AuthNReq":
|
if self.context == "AuthNReq":
|
||||||
self.authn_statement_ok()
|
self.authn_statement_ok()
|
||||||
@@ -205,10 +228,13 @@ class AuthnResponse(object):
|
|||||||
if not self.condition_ok():
|
if not self.condition_ok():
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
if self.debug:
|
||||||
|
self.log.info("--- Getting Identity ---")
|
||||||
|
|
||||||
self.ava = self.get_identity()
|
self.ava = self.get_identity()
|
||||||
|
|
||||||
if self.debug:
|
if self.debug:
|
||||||
self.log.debug("AVA: %s" % (self.ava,))
|
self.log.info("--- AVA: %s" % (self.ava,))
|
||||||
|
|
||||||
self.get_subject()
|
self.get_subject()
|
||||||
|
|
||||||
@@ -218,18 +244,18 @@ class AuthnResponse(object):
|
|||||||
decrypt_xml = self.sc.decrypt(self.xmlstr)
|
decrypt_xml = self.sc.decrypt(self.xmlstr)
|
||||||
|
|
||||||
if self.debug:
|
if self.debug:
|
||||||
self.log.debug("Decryption successfull")
|
self.log.info("Decryption successfull")
|
||||||
|
|
||||||
self.response = samlp.response_from_string(decrypt_xml)
|
self.response = samlp.response_from_string(decrypt_xml)
|
||||||
if self.debug:
|
if self.debug:
|
||||||
self.log.debug("Parsed decrypted assertion successfull")
|
self.log.info("Parsed decrypted assertion successfull")
|
||||||
|
|
||||||
enc = self.response.encrypted_assertion[0].extension_elements[0]
|
enc = self.response.encrypted_assertion[0].extension_elements[0]
|
||||||
assertion = extension_element_to_element(enc,
|
assertion = extension_element_to_element(enc,
|
||||||
saml.ELEMENT_FROM_STRING,
|
saml.ELEMENT_FROM_STRING,
|
||||||
namespace=saml.NAMESPACE)
|
namespace=saml.NAMESPACE)
|
||||||
if self.debug:
|
if self.debug:
|
||||||
self.log.debug("Decrypted Assertion: %s" % assertion)
|
self.log.info("Decrypted Assertion: %s" % assertion)
|
||||||
return self._assertion(assertion)
|
return self._assertion(assertion)
|
||||||
|
|
||||||
def parse_assertion(self):
|
def parse_assertion(self):
|
||||||
@@ -240,11 +266,12 @@ class AuthnResponse(object):
|
|||||||
raise Exception("No assertion part")
|
raise Exception("No assertion part")
|
||||||
|
|
||||||
if self.response.assertion:
|
if self.response.assertion:
|
||||||
self.debug and self.log.debug("***Unencrypted response***")
|
self.debug and self.log.info("***Unencrypted response***")
|
||||||
return self._assertion(self.response.assertion[0])
|
return self._assertion(self.response.assertion[0])
|
||||||
else:
|
else:
|
||||||
self.debug and self.log.info("***Encrypted response***")
|
self.debug and self.log.info("***Encrypted response***")
|
||||||
return self._encrypted_assertion(outstanding)
|
return self._encrypted_assertion(
|
||||||
|
self.response.encrypted_assertion[0])
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@@ -266,7 +293,7 @@ class AuthnResponse(object):
|
|||||||
return self.response.id
|
return self.response.id
|
||||||
|
|
||||||
def session_info(self):
|
def session_info(self):
|
||||||
return { "ava": self.ava, "name_id": name_id,
|
return { "ava": self.ava, "name_id": self.name_id,
|
||||||
"came_from": self.came_from, "issuer": self.issuer(),
|
"came_from": self.came_from, "issuer": self.issuer(),
|
||||||
"not_on_or_after": self.not_on_or_after }
|
"not_on_or_after": self.not_on_or_after }
|
||||||
|
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ LAX = False
|
|||||||
class Saml2Client(object):
|
class Saml2Client(object):
|
||||||
""" The basic pySAML2 service provider class """
|
""" The basic pySAML2 service provider class """
|
||||||
|
|
||||||
def __init__(self, environ, config=None):
|
def __init__(self, environ, config=None, debug=0):
|
||||||
"""
|
"""
|
||||||
:param environ:
|
:param environ:
|
||||||
:param config: A saml2.config.Config instance
|
:param config: A saml2.config.Config instance
|
||||||
@@ -62,7 +62,9 @@ class Saml2Client(object):
|
|||||||
if "metadata" in config:
|
if "metadata" in config:
|
||||||
self.metadata = config["metadata"]
|
self.metadata = config["metadata"]
|
||||||
self.sc = security_context(config)
|
self.sc = security_context(config)
|
||||||
|
|
||||||
|
self.debug = debug
|
||||||
|
|
||||||
def _init_request(self, request, destination):
|
def _init_request(self, request, destination):
|
||||||
#request.id = sid()
|
#request.id = sid()
|
||||||
request.version = VERSION
|
request.version = VERSION
|
||||||
@@ -112,7 +114,8 @@ class Saml2Client(object):
|
|||||||
if post.has_key("SAMLResponse"):
|
if post.has_key("SAMLResponse"):
|
||||||
saml_response = post['SAMLResponse'].value
|
saml_response = post['SAMLResponse'].value
|
||||||
if saml_response:
|
if saml_response:
|
||||||
ar = authn_response(self.conf, requestor, outstanding, log)
|
ar = authn_response(self.config, requestor, outstanding, log,
|
||||||
|
debug=self.debug)
|
||||||
ar.loads(saml_response)
|
ar.loads(saml_response)
|
||||||
return ar.verify()
|
return ar.verify()
|
||||||
|
|
||||||
@@ -324,7 +327,7 @@ class Saml2Client(object):
|
|||||||
if response:
|
if response:
|
||||||
log and log.info("Verifying response")
|
log and log.info("Verifying response")
|
||||||
|
|
||||||
ar = authn_response(self.conf, issuer, {session_id:""}, log)
|
ar = authn_response(self.config, issuer, {session_id:""}, log)
|
||||||
session_info = ar.loads(response).verify().session_info()
|
session_info = ar.loads(response).verify().session_info()
|
||||||
|
|
||||||
log and log.info("session: %s" % session_info)
|
log and log.info("session: %s" % session_info)
|
||||||
|
|||||||
@@ -200,7 +200,7 @@ class Server(object):
|
|||||||
try:
|
try:
|
||||||
request = self.sc.correctly_signed_authn_request(request_xml)
|
request = self.sc.correctly_signed_authn_request(request_xml)
|
||||||
if self.log and self.debug:
|
if self.log and self.debug:
|
||||||
self.log.error("Request was correctly signed")
|
self.log.info("Request was correctly signed")
|
||||||
except Exception:
|
except Exception:
|
||||||
if self.log:
|
if self.log:
|
||||||
self.log.error("Request was not correctly signed")
|
self.log.error("Request was not correctly signed")
|
||||||
@@ -238,7 +238,7 @@ class Server(object):
|
|||||||
|
|
||||||
response["consumer_url"] = consumer_url
|
response["consumer_url"] = consumer_url
|
||||||
response["request"] = request
|
response["request"] = request
|
||||||
self.log and self.log.info("AuthNRequest: %s" % request)
|
|
||||||
return response
|
return response
|
||||||
|
|
||||||
def wants(self, sp_entity_id):
|
def wants(self, sp_entity_id):
|
||||||
@@ -407,8 +407,7 @@ class Server(object):
|
|||||||
in_response_to, # in_response_to
|
in_response_to, # in_response_to
|
||||||
sp_entity_id, # sp_entity_id
|
sp_entity_id, # sp_entity_id
|
||||||
identity, # identity as dictionary
|
identity, # identity as dictionary
|
||||||
name_id,
|
name_id
|
||||||
userid
|
|
||||||
)
|
)
|
||||||
except MissingValue, exc:
|
except MissingValue, exc:
|
||||||
response = self.error_response(destination, in_response_to,
|
response = self.error_response(destination, in_response_to,
|
||||||
|
|||||||
Reference in New Issue
Block a user