Handle different problems pointed out by Seth Arnold.
This commit is contained in:
@@ -20,6 +20,7 @@ from saml2 import BINDING_HTTP_REDIRECT
|
|||||||
from saml2 import BINDING_HTTP_POST
|
from saml2 import BINDING_HTTP_POST
|
||||||
from saml2 import server
|
from saml2 import server
|
||||||
from saml2 import time_util
|
from saml2 import time_util
|
||||||
|
from saml2.authn import is_equal
|
||||||
|
|
||||||
from saml2.authn_context import AuthnBroker
|
from saml2.authn_context import AuthnBroker
|
||||||
from saml2.authn_context import PASSWORD
|
from saml2.authn_context import PASSWORD
|
||||||
@@ -131,20 +132,20 @@ class Service(object):
|
|||||||
else:
|
else:
|
||||||
# saml_msg may also contain Signature and SigAlg
|
# saml_msg may also contain Signature and SigAlg
|
||||||
if "Signature" in saml_msg:
|
if "Signature" in saml_msg:
|
||||||
args = {"signature": saml_msg["signature"],
|
kwargs = {"signature": saml_msg["signature"],
|
||||||
"sigalg": saml_msg["SigAlg"]}
|
"sigalg": saml_msg["SigAlg"]}
|
||||||
else:
|
else:
|
||||||
args = {}
|
kwargs = {}
|
||||||
try:
|
try:
|
||||||
_encrypt_cert = encrypt_cert_from_item(
|
_encrypt_cert = encrypt_cert_from_item(
|
||||||
saml_msg["req_info"].message)
|
saml_msg["req_info"].message)
|
||||||
return self.do(saml_msg["SAMLRequest"], binding,
|
return self.do(saml_msg["SAMLRequest"], binding,
|
||||||
saml_msg["RelayState"],
|
saml_msg["RelayState"],
|
||||||
encrypt_cert=_encrypt_cert, **args)
|
encrypt_cert=_encrypt_cert, **kwargs)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
# Can live with no relay state # TODO or can we, for inacademia?
|
# Can live with no relay state # TODO or can we, for inacademia?
|
||||||
return self.do(saml_msg["SAMLRequest"], binding,
|
return self.do(saml_msg["SAMLRequest"], binding,
|
||||||
saml_msg["RelayState"], **args)
|
saml_msg["RelayState"], **kwargs)
|
||||||
|
|
||||||
def artifact_operation(self, saml_msg):
|
def artifact_operation(self, saml_msg):
|
||||||
if not saml_msg:
|
if not saml_msg:
|
||||||
@@ -454,10 +455,9 @@ class SSO(Service):
|
|||||||
except TypeError:
|
except TypeError:
|
||||||
resp = Unauthorized()
|
resp = Unauthorized()
|
||||||
else:
|
else:
|
||||||
logger.debug("Authz_info: %s" % _info)
|
|
||||||
try:
|
try:
|
||||||
(user, passwd) = _info.split(":")
|
(user, passwd) = _info.split(":")
|
||||||
if PASSWD[user] != passwd:
|
if is_equal(PASSWD[user], passwd):
|
||||||
resp = Unauthorized()
|
resp = Unauthorized()
|
||||||
self.user = user
|
self.user = user
|
||||||
self.environ[
|
self.environ[
|
||||||
@@ -931,12 +931,16 @@ def metadata(environ, start_response):
|
|||||||
|
|
||||||
def staticfile(environ, start_response):
|
def staticfile(environ, start_response):
|
||||||
try:
|
try:
|
||||||
path = args.path
|
path = args.path[:]
|
||||||
if path is None or len(path) == 0:
|
if path is None or len(path) == 0:
|
||||||
path = os.path.dirname(os.path.abspath(__file__))
|
path = os.path.dirname(os.path.abspath(__file__))
|
||||||
if path[-1] != "/":
|
if path[-1] != "/":
|
||||||
path += "/"
|
path += "/"
|
||||||
path += environ.get('PATH_INFO', '').lstrip('/')
|
path += environ.get('PATH_INFO', '').lstrip('/')
|
||||||
|
path = os.path.realpath(path)
|
||||||
|
if not path.startswith(args.path):
|
||||||
|
resp = Unauthorized()
|
||||||
|
return resp(environ, start_response)
|
||||||
start_response('200 OK', [('Content-Type', "text/xml")])
|
start_response('200 OK', [('Content-Type', "text/xml")])
|
||||||
return open(path, 'r').read()
|
return open(path, 'r').read()
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
|
@@ -10,6 +10,7 @@ from hashlib import sha1
|
|||||||
from urlparse import parse_qs
|
from urlparse import parse_qs
|
||||||
from Cookie import SimpleCookie
|
from Cookie import SimpleCookie
|
||||||
import os
|
import os
|
||||||
|
from saml2.authn import is_equal
|
||||||
from saml2.profile import ecp
|
from saml2.profile import ecp
|
||||||
|
|
||||||
from saml2 import server
|
from saml2 import server
|
||||||
@@ -73,12 +74,14 @@ def get_eptid(idp, req_info, session):
|
|||||||
req_info.sender(), session["permanent_id"],
|
req_info.sender(), session["permanent_id"],
|
||||||
session["authn_auth"])
|
session["authn_auth"])
|
||||||
|
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
def dict2list_of_tuples(d):
|
def dict2list_of_tuples(d):
|
||||||
return [(k, v) for k, v in d.items()]
|
return [(k, v) for k, v in d.items()]
|
||||||
|
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
@@ -95,7 +98,7 @@ class Service(object):
|
|||||||
return dict([(k, v[0]) for k, v in parse_qs(_qs).items()])
|
return dict([(k, v[0]) for k, v in parse_qs(_qs).items()])
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def unpack_post(self):
|
def unpack_post(self):
|
||||||
_dict = parse_qs(get_post(self.environ))
|
_dict = parse_qs(get_post(self.environ))
|
||||||
logger.debug("unpack_post:: %s" % _dict)
|
logger.debug("unpack_post:: %s" % _dict)
|
||||||
@@ -103,14 +106,14 @@ class Service(object):
|
|||||||
return dict([(k, v[0]) for k, v in _dict.items()])
|
return dict([(k, v[0]) for k, v in _dict.items()])
|
||||||
except Exception:
|
except Exception:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def unpack_soap(self):
|
def unpack_soap(self):
|
||||||
try:
|
try:
|
||||||
query = get_post(self.environ)
|
query = get_post(self.environ)
|
||||||
return {"SAMLRequest": query, "RelayState": ""}
|
return {"SAMLRequest": query, "RelayState": ""}
|
||||||
except Exception:
|
except Exception:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def unpack_either(self):
|
def unpack_either(self):
|
||||||
if self.environ["REQUEST_METHOD"] == "GET":
|
if self.environ["REQUEST_METHOD"] == "GET":
|
||||||
_dict = self.unpack_redirect()
|
_dict = self.unpack_redirect()
|
||||||
@@ -292,7 +295,7 @@ class SSO(Service):
|
|||||||
|
|
||||||
if not _resp:
|
if not _resp:
|
||||||
identity = USERS[self.user].copy()
|
identity = USERS[self.user].copy()
|
||||||
#identity["eduPersonTargetedID"] = get_eptid(IDP, query, session)
|
# identity["eduPersonTargetedID"] = get_eptid(IDP, query, session)
|
||||||
logger.info("Identity: %s" % (identity,))
|
logger.info("Identity: %s" % (identity,))
|
||||||
|
|
||||||
if REPOZE_ID_EQUIVALENT:
|
if REPOZE_ID_EQUIVALENT:
|
||||||
@@ -357,7 +360,8 @@ class SSO(Service):
|
|||||||
|
|
||||||
_req = self.req_info.message
|
_req = self.req_info.message
|
||||||
|
|
||||||
if "SigAlg" in saml_msg and "Signature" in saml_msg: # Signed request
|
if "SigAlg" in saml_msg and "Signature" in saml_msg: # Signed
|
||||||
|
# request
|
||||||
issuer = _req.issuer.text
|
issuer = _req.issuer.text
|
||||||
_certs = IDP.metadata.certs(issuer, "any", "signing")
|
_certs = IDP.metadata.certs(issuer, "any", "signing")
|
||||||
verified_ok = False
|
verified_ok = False
|
||||||
@@ -405,7 +409,7 @@ class SSO(Service):
|
|||||||
return self.not_authn(key, _req.requested_authn_context)
|
return self.not_authn(key, _req.requested_authn_context)
|
||||||
|
|
||||||
# def artifact(self):
|
# def artifact(self):
|
||||||
# # Can be either by HTTP_Redirect or HTTP_POST
|
# # Can be either by HTTP_Redirect or HTTP_POST
|
||||||
# _req = self._store_request(self.unpack_either())
|
# _req = self._store_request(self.unpack_either())
|
||||||
# if isinstance(_req, basestring):
|
# if isinstance(_req, basestring):
|
||||||
# return self.not_authn(_req)
|
# return self.not_authn(_req)
|
||||||
@@ -424,10 +428,9 @@ class SSO(Service):
|
|||||||
except TypeError:
|
except TypeError:
|
||||||
resp = Unauthorized()
|
resp = Unauthorized()
|
||||||
else:
|
else:
|
||||||
logger.debug("Authz_info: %s" % _info)
|
|
||||||
try:
|
try:
|
||||||
(user, passwd) = _info.split(":")
|
(user, passwd) = _info.split(":")
|
||||||
if PASSWD[user] != passwd:
|
if is_equal(PASSWD[user], passwd):
|
||||||
resp = Unauthorized()
|
resp = Unauthorized()
|
||||||
self.user = user
|
self.user = user
|
||||||
self.environ[
|
self.environ[
|
||||||
@@ -449,6 +452,7 @@ class SSO(Service):
|
|||||||
self.op_type = "ecp"
|
self.op_type = "ecp"
|
||||||
return self.operation(_dict, BINDING_SOAP)
|
return self.operation(_dict, BINDING_SOAP)
|
||||||
|
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
# === Authentication ====
|
# === Authentication ====
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
@@ -474,11 +478,11 @@ def do_authentication(environ, start_response, authn_context, key,
|
|||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
PASSWD = {
|
PASSWD = {
|
||||||
"daev0001": "qwerty",
|
"daev0001": "qwerty",
|
||||||
"haho0032": "qwerty",
|
"haho0032": "qwerty",
|
||||||
"roland": "dianakra",
|
"roland": "dianakra",
|
||||||
"babs": "howes",
|
"babs": "howes",
|
||||||
"upper": "crust"}
|
"upper": "crust"}
|
||||||
|
|
||||||
|
|
||||||
def username_password_authn(environ, start_response, reference, key,
|
def username_password_authn(environ, start_response, reference, key,
|
||||||
@@ -552,7 +556,7 @@ def not_found(environ, start_response):
|
|||||||
# === Single log out ===
|
# === Single log out ===
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
#def _subject_sp_info(req_info):
|
# def _subject_sp_info(req_info):
|
||||||
# # look for the subject
|
# # look for the subject
|
||||||
# subject = req_info.subject_id()
|
# subject = req_info.subject_id()
|
||||||
# subject = subject.text.strip()
|
# subject = subject.text.strip()
|
||||||
@@ -570,7 +574,7 @@ class SLO(Service):
|
|||||||
logger.error("Bad request: %s" % exc)
|
logger.error("Bad request: %s" % exc)
|
||||||
resp = BadRequest("%s" % exc)
|
resp = BadRequest("%s" % exc)
|
||||||
return resp(self.environ, self.start_response)
|
return resp(self.environ, self.start_response)
|
||||||
|
|
||||||
msg = req_info.message
|
msg = req_info.message
|
||||||
if msg.name_id:
|
if msg.name_id:
|
||||||
lid = IDP.ident.find_local_id(msg.name_id)
|
lid = IDP.ident.find_local_id(msg.name_id)
|
||||||
@@ -587,16 +591,16 @@ class SLO(Service):
|
|||||||
logger.error("ServiceError: %s" % exc)
|
logger.error("ServiceError: %s" % exc)
|
||||||
resp = ServiceError("%s" % exc)
|
resp = ServiceError("%s" % exc)
|
||||||
return resp(self.environ, self.start_response)
|
return resp(self.environ, self.start_response)
|
||||||
|
|
||||||
resp = IDP.create_logout_response(msg, [binding])
|
resp = IDP.create_logout_response(msg, [binding])
|
||||||
|
|
||||||
try:
|
try:
|
||||||
hinfo = IDP.apply_binding(binding, "%s" % resp, "", relay_state)
|
hinfo = IDP.apply_binding(binding, "%s" % resp, "", relay_state)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
logger.error("ServiceError: %s" % exc)
|
logger.error("ServiceError: %s" % exc)
|
||||||
resp = ServiceError("%s" % exc)
|
resp = ServiceError("%s" % exc)
|
||||||
return resp(self.environ, self.start_response)
|
return resp(self.environ, self.start_response)
|
||||||
|
|
||||||
#_tlh = dict2list_of_tuples(hinfo["headers"])
|
#_tlh = dict2list_of_tuples(hinfo["headers"])
|
||||||
delco = delete_cookie(self.environ, "idpauthn")
|
delco = delete_cookie(self.environ, "idpauthn")
|
||||||
if delco:
|
if delco:
|
||||||
@@ -604,35 +608,36 @@ class SLO(Service):
|
|||||||
logger.info("Header: %s" % (hinfo["headers"],))
|
logger.info("Header: %s" % (hinfo["headers"],))
|
||||||
resp = Response(hinfo["data"], headers=hinfo["headers"])
|
resp = Response(hinfo["data"], headers=hinfo["headers"])
|
||||||
return resp(self.environ, self.start_response)
|
return resp(self.environ, self.start_response)
|
||||||
|
|
||||||
|
|
||||||
# ----------------------------------------------------------------------------
|
# ----------------------------------------------------------------------------
|
||||||
# Manage Name ID service
|
# Manage Name ID service
|
||||||
# ----------------------------------------------------------------------------
|
# ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
class NMI(Service):
|
class NMI(Service):
|
||||||
|
|
||||||
def do(self, query, binding, relay_state="", encrypt_cert=None):
|
def do(self, query, binding, relay_state="", encrypt_cert=None):
|
||||||
logger.info("--- Manage Name ID Service ---")
|
logger.info("--- Manage Name ID Service ---")
|
||||||
req = IDP.parse_manage_name_id_request(query, binding)
|
req = IDP.parse_manage_name_id_request(query, binding)
|
||||||
request = req.message
|
request = req.message
|
||||||
|
|
||||||
# Do the necessary stuff
|
# Do the necessary stuff
|
||||||
name_id = IDP.ident.handle_manage_name_id_request(
|
name_id = IDP.ident.handle_manage_name_id_request(
|
||||||
request.name_id, request.new_id, request.new_encrypted_id,
|
request.name_id, request.new_id, request.new_encrypted_id,
|
||||||
request.terminate)
|
request.terminate)
|
||||||
|
|
||||||
logger.debug("New NameID: %s" % name_id)
|
logger.debug("New NameID: %s" % name_id)
|
||||||
|
|
||||||
_resp = IDP.create_manage_name_id_response(request)
|
_resp = IDP.create_manage_name_id_response(request)
|
||||||
|
|
||||||
# It's using SOAP binding
|
# It's using SOAP binding
|
||||||
hinfo = IDP.apply_binding(BINDING_SOAP, "%s" % _resp, "",
|
hinfo = IDP.apply_binding(BINDING_SOAP, "%s" % _resp, "",
|
||||||
relay_state, response=True)
|
relay_state, response=True)
|
||||||
|
|
||||||
resp = Response(hinfo["data"], headers=hinfo["headers"])
|
resp = Response(hinfo["data"], headers=hinfo["headers"])
|
||||||
return resp(self.environ, self.start_response)
|
return resp(self.environ, self.start_response)
|
||||||
|
|
||||||
|
|
||||||
# ----------------------------------------------------------------------------
|
# ----------------------------------------------------------------------------
|
||||||
# === Assertion ID request ===
|
# === Assertion ID request ===
|
||||||
# ----------------------------------------------------------------------------
|
# ----------------------------------------------------------------------------
|
||||||
@@ -648,9 +653,9 @@ class AIDR(Service):
|
|||||||
except Unknown:
|
except Unknown:
|
||||||
resp = NotFound(aid)
|
resp = NotFound(aid)
|
||||||
return resp(self.environ, self.start_response)
|
return resp(self.environ, self.start_response)
|
||||||
|
|
||||||
hinfo = IDP.apply_binding(BINDING_URI, "%s" % assertion, response=True)
|
hinfo = IDP.apply_binding(BINDING_URI, "%s" % assertion, response=True)
|
||||||
|
|
||||||
logger.debug("HINFO: %s" % hinfo)
|
logger.debug("HINFO: %s" % hinfo)
|
||||||
resp = Response(hinfo["data"], headers=hinfo["headers"])
|
resp = Response(hinfo["data"], headers=hinfo["headers"])
|
||||||
return resp(self.environ, self.start_response)
|
return resp(self.environ, self.start_response)
|
||||||
@@ -680,6 +685,7 @@ class ARS(Service):
|
|||||||
resp = Response(hinfo["data"], headers=hinfo["headers"])
|
resp = Response(hinfo["data"], headers=hinfo["headers"])
|
||||||
return resp(self.environ, self.start_response)
|
return resp(self.environ, self.start_response)
|
||||||
|
|
||||||
|
|
||||||
# ----------------------------------------------------------------------------
|
# ----------------------------------------------------------------------------
|
||||||
# === Authn query service ===
|
# === Authn query service ===
|
||||||
# ----------------------------------------------------------------------------
|
# ----------------------------------------------------------------------------
|
||||||
@@ -734,6 +740,7 @@ class ATTR(Service):
|
|||||||
resp = Response(hinfo["data"], headers=hinfo["headers"])
|
resp = Response(hinfo["data"], headers=hinfo["headers"])
|
||||||
return resp(self.environ, self.start_response)
|
return resp(self.environ, self.start_response)
|
||||||
|
|
||||||
|
|
||||||
# ----------------------------------------------------------------------------
|
# ----------------------------------------------------------------------------
|
||||||
# Name ID Mapping service
|
# Name ID Mapping service
|
||||||
# When an entity that shares an identifier for a principal with an identity
|
# When an entity that shares an identifier for a principal with an identity
|
||||||
@@ -757,17 +764,17 @@ class NIM(Service):
|
|||||||
except PolicyError:
|
except PolicyError:
|
||||||
resp = BadRequest("Unknown entity")
|
resp = BadRequest("Unknown entity")
|
||||||
return resp(self.environ, self.start_response)
|
return resp(self.environ, self.start_response)
|
||||||
|
|
||||||
info = IDP.response_args(request)
|
info = IDP.response_args(request)
|
||||||
_resp = IDP.create_name_id_mapping_response(name_id, **info)
|
_resp = IDP.create_name_id_mapping_response(name_id, **info)
|
||||||
|
|
||||||
# Only SOAP
|
# Only SOAP
|
||||||
hinfo = IDP.apply_binding(BINDING_SOAP, "%s" % _resp, "", "",
|
hinfo = IDP.apply_binding(BINDING_SOAP, "%s" % _resp, "", "",
|
||||||
response=True)
|
response=True)
|
||||||
|
|
||||||
resp = Response(hinfo["data"], headers=hinfo["headers"])
|
resp = Response(hinfo["data"], headers=hinfo["headers"])
|
||||||
return resp(self.environ, self.start_response)
|
return resp(self.environ, self.start_response)
|
||||||
|
|
||||||
|
|
||||||
# ----------------------------------------------------------------------------
|
# ----------------------------------------------------------------------------
|
||||||
# Cookie handling
|
# Cookie handling
|
||||||
@@ -862,10 +869,10 @@ def metadata(environ, start_response):
|
|||||||
try:
|
try:
|
||||||
path = args.path
|
path = args.path
|
||||||
if path is None or len(path) == 0:
|
if path is None or len(path) == 0:
|
||||||
path = os.path.dirname(os.path.abspath( __file__ ))
|
path = os.path.dirname(os.path.abspath(__file__))
|
||||||
if path[-1] != "/":
|
if path[-1] != "/":
|
||||||
path += "/"
|
path += "/"
|
||||||
metadata = create_metadata_string(path+args.config, IDP.config,
|
metadata = create_metadata_string(path + args.config, IDP.config,
|
||||||
args.valid, args.cert, args.keyfile,
|
args.valid, args.cert, args.keyfile,
|
||||||
args.id, args.name, args.sign)
|
args.id, args.name, args.sign)
|
||||||
start_response('200 OK', [('Content-Type', "text/xml")])
|
start_response('200 OK', [('Content-Type', "text/xml")])
|
||||||
@@ -874,6 +881,7 @@ def metadata(environ, start_response):
|
|||||||
logger.error("An error occured while creating metadata:" + ex.message)
|
logger.error("An error occured while creating metadata:" + ex.message)
|
||||||
return not_found(environ, start_response)
|
return not_found(environ, start_response)
|
||||||
|
|
||||||
|
|
||||||
def staticfile(environ, start_response):
|
def staticfile(environ, start_response):
|
||||||
try:
|
try:
|
||||||
path = args.path
|
path = args.path
|
||||||
@@ -882,12 +890,17 @@ def staticfile(environ, start_response):
|
|||||||
if path[-1] != "/":
|
if path[-1] != "/":
|
||||||
path += "/"
|
path += "/"
|
||||||
path += environ.get('PATH_INFO', '').lstrip('/')
|
path += environ.get('PATH_INFO', '').lstrip('/')
|
||||||
|
path = os.path.realpath(path)
|
||||||
|
if not path.startswith(args.path):
|
||||||
|
resp = Unauthorized()
|
||||||
|
return resp(environ, start_response)
|
||||||
start_response('200 OK', [('Content-Type', "text/xml")])
|
start_response('200 OK', [('Content-Type', "text/xml")])
|
||||||
return open(path, 'r').read()
|
return open(path, 'r').read()
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
logger.error("An error occured while creating metadata:" + ex.message)
|
logger.error("An error occured while creating metadata:" + ex.message)
|
||||||
return not_found(environ, start_response)
|
return not_found(environ, start_response)
|
||||||
|
|
||||||
|
|
||||||
def application(environ, start_response):
|
def application(environ, start_response):
|
||||||
"""
|
"""
|
||||||
The main WSGI application. Dispatch the current request to
|
The main WSGI application. Dispatch the current request to
|
||||||
@@ -924,7 +937,6 @@ def application(environ, start_response):
|
|||||||
except KeyError:
|
except KeyError:
|
||||||
user = None
|
user = None
|
||||||
|
|
||||||
|
|
||||||
url_patterns = AUTHN_URLS
|
url_patterns = AUTHN_URLS
|
||||||
if not user:
|
if not user:
|
||||||
logger.info("-- No USER --")
|
logger.info("-- No USER --")
|
||||||
@@ -956,7 +968,7 @@ def application(environ, start_response):
|
|||||||
# by moving some initialization out of __name__ == '__main__' section.
|
# by moving some initialization out of __name__ == '__main__' section.
|
||||||
# uwsgi -s 0.0.0.0:8088 --protocol http --callable application --module idp
|
# uwsgi -s 0.0.0.0:8088 --protocol http --callable application --module idp
|
||||||
|
|
||||||
args = type('Config', (object,), { })
|
args = type('Config', (object,), {})
|
||||||
args.config = 'idp_conf'
|
args.config = 'idp_conf'
|
||||||
args.mako_root = './'
|
args.mako_root = './'
|
||||||
args.path = None
|
args.path = None
|
||||||
@@ -984,7 +996,8 @@ if __name__ == '__main__':
|
|||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
parser.add_argument('-p', dest='path', help='Path to configuration file.')
|
parser.add_argument('-p', dest='path', help='Path to configuration file.')
|
||||||
parser.add_argument('-v', dest='valid',
|
parser.add_argument('-v', dest='valid',
|
||||||
help="How long, in days, the metadata is valid from the time of creation")
|
help="How long, in days, the metadata is valid from "
|
||||||
|
"the time of creation")
|
||||||
parser.add_argument('-c', dest='cert', help='certificate')
|
parser.add_argument('-c', dest='cert', help='certificate')
|
||||||
parser.add_argument('-i', dest='id',
|
parser.add_argument('-i', dest='id',
|
||||||
help="The ID of the entities descriptor")
|
help="The ID of the entities descriptor")
|
||||||
|
@@ -19,6 +19,7 @@ from saml2 import BINDING_SOAP
|
|||||||
from saml2 import BINDING_HTTP_REDIRECT
|
from saml2 import BINDING_HTTP_REDIRECT
|
||||||
from saml2 import BINDING_HTTP_POST
|
from saml2 import BINDING_HTTP_POST
|
||||||
from saml2 import time_util
|
from saml2 import time_util
|
||||||
|
from saml2.authn import is_equal
|
||||||
|
|
||||||
from saml2.authn_context import AuthnBroker
|
from saml2.authn_context import AuthnBroker
|
||||||
from saml2.authn_context import PASSWORD
|
from saml2.authn_context import PASSWORD
|
||||||
@@ -414,7 +415,7 @@ class SSO(Service):
|
|||||||
logger.debug("Authz_info: %s" % _info)
|
logger.debug("Authz_info: %s" % _info)
|
||||||
try:
|
try:
|
||||||
(user, passwd) = _info.split(":")
|
(user, passwd) = _info.split(":")
|
||||||
if PASSWD[user] != passwd:
|
if is_equal(PASSWD[user], passwd):
|
||||||
resp = Unauthorized()
|
resp = Unauthorized()
|
||||||
self.user = user
|
self.user = user
|
||||||
except (ValueError, TypeError):
|
except (ValueError, TypeError):
|
||||||
|
@@ -39,6 +39,16 @@ class UserAuthnMethod(object):
|
|||||||
raise NotImplemented
|
raise NotImplemented
|
||||||
|
|
||||||
|
|
||||||
|
def is_equal(a, b):
|
||||||
|
if len(a) != len(b):
|
||||||
|
return False
|
||||||
|
|
||||||
|
result = 0
|
||||||
|
for x, y in zip(a, b):
|
||||||
|
result |= x ^ y
|
||||||
|
return result == 0
|
||||||
|
|
||||||
|
|
||||||
def url_encode_params(params=None):
|
def url_encode_params(params=None):
|
||||||
if not isinstance(params, dict):
|
if not isinstance(params, dict):
|
||||||
raise EncodeError("You must pass in a dictionary!")
|
raise EncodeError("You must pass in a dictionary!")
|
||||||
@@ -137,7 +147,7 @@ class UsernamePasswordMako(UserAuthnMethod):
|
|||||||
return resp
|
return resp
|
||||||
|
|
||||||
def _verify(self, pwd, user):
|
def _verify(self, pwd, user):
|
||||||
assert pwd == self.passwd[user]
|
assert is_equal(pwd, self.passwd[user])
|
||||||
|
|
||||||
def verify(self, request, **kwargs):
|
def verify(self, request, **kwargs):
|
||||||
"""
|
"""
|
||||||
@@ -149,7 +159,7 @@ class UsernamePasswordMako(UserAuthnMethod):
|
|||||||
wants the user after authentication.
|
wants the user after authentication.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
logger.debug("verify(%s)" % request)
|
#logger.debug("verify(%s)" % request)
|
||||||
if isinstance(request, basestring):
|
if isinstance(request, basestring):
|
||||||
_dict = parse_qs(request)
|
_dict = parse_qs(request)
|
||||||
elif isinstance(request, dict):
|
elif isinstance(request, dict):
|
||||||
@@ -157,8 +167,6 @@ class UsernamePasswordMako(UserAuthnMethod):
|
|||||||
else:
|
else:
|
||||||
raise ValueError("Wrong type of input")
|
raise ValueError("Wrong type of input")
|
||||||
|
|
||||||
logger.debug("dict: %s" % _dict)
|
|
||||||
logger.debug("passwd: %s" % self.passwd)
|
|
||||||
# verify username and password
|
# verify username and password
|
||||||
try:
|
try:
|
||||||
self._verify(_dict["password"][0], _dict["login"][0])
|
self._verify(_dict["password"][0], _dict["login"][0])
|
||||||
|
Reference in New Issue
Block a user