def _redirect_to_auth(self, _cli, entity_id, query, vorg_name=""): try: binding, destination = _cli.pick_binding( "single_sign_on_service", self.bindings, "idpsso", entity_id=entity_id) logger.debug("binding: %s, destination: %s" % (binding, destination)) extensions = None if _cli.authn_requests_signed: _sid = saml2.s_utils.sid(_cli.seed) req_id, msg_str = _cli.create_authn_request(destination, vorg=vorg_name, sign=_cli.authn_requests_signed, message_id=_sid, extensions=extensions) _sid = req_id else: req_id, req = _cli.create_authn_request(destination, vorg=vorg_name, sign=False) msg_str = "%s" % req _sid = req_id _rstate = rndstr() #self.cache.relay_state[_rstate] = came_from ht_args = _cli.apply_binding(binding, msg_str, destination, relay_state=_rstate) logger.debug("ht_args: %s" % ht_args) except Exception, exc: logger.exception(exc) raise ServiceErrorException( "Failed to construct the AuthnRequest: %s" % exc)
def do_verify(environ, start_response, _): query = parse_qs(get_post(environ)) logger.debug("do_verify: %s" % query) try: _ok, user = verify_username_and_password(query) except KeyError: _ok = False user = None if not _ok: resp = Unauthorized("Unknown user or wrong password") else: uid = rndstr(24) IDP.cache.uid2user[uid] = user IDP.cache.user2uid[user] = uid logger.debug("Register %s under '%s'" % (user, uid)) kaka = set_cookie("idpauthn", "/", uid, query["authn_reference"][0]) lox = "%s?id=%s&key=%s" % (query["redirect_uri"][0], uid, query["key"][0]) logger.debug("Redirect => %s" % lox) resp = Redirect(lox, headers=[kaka], content="text/html") return resp(environ, start_response)
def _redirect_to_auth(self, _cli, entity_id, came_from, vorg_name="", cert_str=None, cert_key_str=None): try: _binding, destination = _cli.pick_binding( "single_sign_on_service", self.bindings, "idpsso", entity_id=entity_id) self.logger.debug("binding: %s, destination: %s" % (_binding, destination)) extensions = None if cert_key_str is not None: spcertenc = SPCertEnc(x509_data=ds.X509Data(x509_certificate=ds.X509Certificate(text=cert_key_str))) extensions = Extensions(extension_elements=[element_to_extension_element(spcertenc)]) if _cli.authn_requests_signed: _sid = saml2.s_utils.sid(_cli.seed) req_id, msg_str = _cli.create_authn_request(destination, vorg=vorg_name, sign=_cli.authn_requests_signed, message_id=_sid, client_crt=cert_str, extensions=extensions) _sid = req_id else: req_id, req = _cli.create_authn_request(destination, vorg=vorg_name, sign=False) msg_str = "%s" % req _sid = req_id _rstate = rndstr() self.cache.relay_state[_rstate] = came_from ht_args = _cli.apply_binding(_binding, msg_str, destination, relay_state=_rstate) self.logger.debug("ht_args: %s" % ht_args) except Exception, exc: self.logger.exception(exc) raise ServiceErrorException( "Failed to construct the AuthnRequest: %s" % exc)
def do_verify(environ, start_response, _, session): query = parse_qs(get_post(environ)) logger.debug("do_verify: %s" % query) try: _ok, user = verify_username_and_password(query) except KeyError: _ok = False user = None if not _ok: resp = Unauthorized("Unknown user or wrong password") else: uid = rndstr(24) IDP.cache.uid2user[uid] = user IDP.cache.user2uid[user] = uid logger.debug("Register %s under '%s'" % (user, uid)) cval = {"uid": user, "authn_ref": query["authn_reference"][0]} headers = [CookieHandler.create_cookie("%s" % (cval,), "sso", COOKIE_NAME)] lox = "%s?id=%s&key=%s" % (query["redirect_uri"][0], uid, query["key"][0]) logger.debug("Redirect => %s" % lox) resp = Redirect(lox, content="text/html", headers=headers) return resp(environ, start_response)
def _redirect_to_auth(self, _cli, entity_id, came_from, vorg_name="", dont_send=False): try: _binding, destination = _cli.pick_binding( "single_sign_on_service", self.bindings, "idpsso", entity_id=entity_id) logger.debug("binding: %s, destination: %s" % (_binding, destination)) if "accr" in self.kwargs: kwargs = { "requested_authn_context": RequestedAuthnContext( authn_context_class_ref=AuthnContextClassRef( text=self.kwargs["accr"] ) ) } else: kwargs = {} req = _cli.create_authn_request(destination, vorg=vorg_name, **kwargs) _rstate = rndstr() self.cache.relay_state[_rstate] = came_from ht_args = _cli.apply_binding(_binding, "%s" % req, destination, relay_state=_rstate) _sid = req.id SESSIONDB[_sid] = self.kwargs logger.debug("ht_args: %s" % ht_args) except Exception, exc: logger.exception(exc) resp = ServiceError( "Failed to construct the AuthnRequest: %s" % exc) return resp(self.environ, self.start_response)
def redirect_to_auth(self, _cli, entity_id, came_from): try: # Picks a binding to use for sending the Request to the IDP _binding, destination = _cli.pick_binding( "single_sign_on_service", self.bindings, "idpsso", entity_id=entity_id) logger.debug("binding: %s, destination: %s" % (_binding, destination)) # Binding here is the response binding that is which binding the # IDP should use to return the response. acs = _cli.config.getattr("endpoints", "sp")[ "assertion_consumer_service"] # just pick one endp, return_binding = acs[0] req_id, req = _cli.create_authn_request(destination, binding=return_binding) _rstate = rndstr() self.cache.relay_state[_rstate] = came_from ht_args = _cli.apply_binding(_binding, "%s" % req, destination, relay_state=_rstate) _sid = req_id except Exception, exc: logger.exception(exc) resp = ServiceError( "Failed to construct the AuthnRequest: %s" % exc) return resp
def _redirect_to_auth(self, _cli, entity_id, came_from, vorg_name=""): try: _binding, destination = _cli.pick_binding( "single_sign_on_service", self.bindings, "idpsso", entity_id=entity_id) self.logger.debug("binding: %s, destination: %s" % (_binding, destination)) if _cli.authn_requests_signed: req_id, req = _cli.create_authn_request(destination, vorg=vorg_name, sign=_cli.authn_requests_signed) else: req_id, req = _cli.create_authn_request(destination, vorg=vorg_name, sign=False) msg_str = "%s" % req _rstate = rndstr() self.cache.relay_state[_rstate] = came_from ht_args = _cli.apply_binding(_binding, "%s" % req, destination, relay_state=_rstate) _sid = req_id self.logger.debug("ht_args: %s" % ht_args) except Exception, exc: self.logger.exception(exc) resp = ServiceError( "Failed to construct the AuthnRequest: %s" % exc) return resp(self.environ, self.start_response)
def _create_id(self, nformat, name_qualifier="", sp_name_qualifier=""): _id = sha256(rndstr(32)) _id.update(nformat) if name_qualifier: _id.update(name_qualifier) if sp_name_qualifier: _id.update(sp_name_qualifier) return _id.hexdigest()
def set_cookie(self, user): uid = rndstr(32) self.uid2user[uid] = user cookie = SimpleCookie() cookie[self.cookie_name] = uid cookie[self.cookie_name]['path'] = "/" cookie[self.cookie_name]["expires"] = _expiration(480) logger.debug("Cookie expires: %s", cookie[self.cookie_name]["expires"]) return cookie.output().encode("UTF-8").split(": ", 1)
def user2kaka(self, user): uid = rndstr(32) self.uid2user[uid] = user cookie = SimpleCookie() cookie[self.cookie_name] = uid cookie[self.cookie_name]['path'] = "/" cookie[self.cookie_name]["expires"] = _expiration(480) logger.debug("Cookie expires: %s" % cookie[self.cookie_name]["expires"]) return tuple(cookie.output().split(": ", 1))
def __init__(self, config=None, identity_cache=None, state_cache=None, virtual_organization="",config_file=""): """ :param config: A saml2.config.Config instance :param identity_cache: Where the class should store identity information :param state_cache: Where the class should keep state information :param virtual_organization: A specific virtual organization """ self.users = Population(identity_cache) # for server state storage if state_cache is None: self.state = {} # in memory storage else: self.state = state_cache if config: self.config = config elif config_file: self.config = config_factory("sp", config_file) else: raise Exception("Missing configuration") if self.config.vorg: for vo in self.config.vorg.values(): vo.sp = self self.metadata = self.config.metadata self.config.setup_logger() # we copy the config.debug variable in an internal # field for convenience and because we may need to # change it during the tests self.debug = self.config.debug self.sec = security_context(self.config) if virtual_organization: if isinstance(virtual_organization, basestring): self.vorg = self.config.vorg[virtual_organization] elif isinstance(virtual_organization, VirtualOrg): self.vorg = virtual_organization else: self.vorg = {} for foo in ["allow_unsolicited", "authn_requests_signed", "logout_requests_signed"]: if self.config.getattr("sp", foo) == 'true': setattr(self, foo, True) else: setattr(self, foo, False) # extra randomness self.seed = rndstr(32) self.logout_requests_signed_default = True self.allow_unsolicited = self.config.getattr("allow_unsolicited", "sp")
def set_cookie(self, user): uid = rndstr(32) self.uid2user[uid] = user cookie = SimpleCookie() cookie[self.cookie_name] = uid cookie[self.cookie_name]["path"] = "/" cookie[self.cookie_name]["expires"] = _expiration(480) logger.debug("Cookie expires: %s", cookie[self.cookie_name]["expires"]) return cookie.output().split(": ", 1)
def __init__(self, entity_type, config=None, config_file="", virtual_organization=""): self.entity_type = entity_type self.users = None if config: self.config = config elif config_file: self.config = config_factory(entity_type, config_file) else: raise SAMLError("Missing configuration") for item in ["cert_file", "key_file", "ca_certs"]: _val = getattr(self.config, item, None) if not _val: continue if _val.startswith("http"): r = requests.request("GET", _val) if r.status_code == 200: _, filename = make_temp(r.text, ".pem", False) setattr(self.config, item, filename) else: raise Exception("Could not fetch certificate from %s" % _val) HTTPBase.__init__(self, self.config.verify_ssl_cert, self.config.ca_certs, self.config.key_file, self.config.cert_file) if self.config.vorg: for vo in self.config.vorg.values(): vo.sp = self self.metadata = self.config.metadata self.config.setup_logger() self.debug = self.config.debug self.seed = rndstr(32) self.sec = security_context(self.config) if virtual_organization: if isinstance(virtual_organization, basestring): self.vorg = self.config.vorg[virtual_organization] elif isinstance(virtual_organization, VirtualOrg): self.vorg = virtual_organization else: self.vorg = None self.artifact = {} if self.metadata: self.sourceid = self.metadata.construct_source_id() else: self.sourceid = {}
def redirect_to_auth(self, _cli, entity_id, came_from, sigalg=None): try: # Picks a binding to use for sending the Request to the IDP _binding, destination = _cli.pick_binding( "single_sign_on_service", self.bindings, "idpsso", entity_id=entity_id) logger.debug("binding: %s, destination: %s", _binding, destination) # Binding here is the response binding that is which binding the # IDP should use to return the response. acs = _cli.config.getattr("endpoints", "sp")[ "assertion_consumer_service"] # just pick one endp, return_binding = acs[0] logger.debug("Binding response to: {}, {}".format(return_binding, endp)) extensions = None cert = None logger.debug("cli config: {}".format(dir(_cli.config))) if _cli.config.generate_cert_func is not None: cert_str, req_key_str = _cli.config.generate_cert_func() cert = { "cert": cert_str, "key": req_key_str } spcertenc = SPCertEnc(x509_data=ds.X509Data( x509_certificate=ds.X509Certificate(text=cert_str))) extensions = Extensions(extension_elements=[ element_to_extension_element(spcertenc)]) req_id, req = _cli.create_authn_request(destination, binding=return_binding, extensions=extensions, nameid_format=NAMEID_FORMAT_PERSISTENT) _rstate = rndstr() self.cache.relay_state[_rstate] = came_from apply_binding_kwargs = dict(relay_state=_rstate) if sigalg: apply_binding_kwargs['sigalg'] = sigalg ht_args = _cli.apply_binding(_binding, "%s" % req, destination, **apply_binding_kwargs) _sid = req_id if cert is not None: self.cache.outstanding_certs[_sid] = cert except Exception as exc: logger.exception(exc) resp = ServiceError( "Failed to construct the AuthnRequest: %s" % exc) return resp # remember the request self.cache.outstanding_queries[_sid] = came_from return self.response(_binding, ht_args, do_not_start_response=True)
def setup_idp(self, user, reference, redirect_uri, key): uid = rndstr(24) self.idphandler.idp_server.cache.uid2user[uid] = user self.idphandler.idp_server.cache.user2uid[user] = uid logger.debug("Register %s under '%s'" % (user, uid)) cookie = self.idphandler.set_authorization_cookie(uid, reference) lox = "%s?id=%s&key=%s" % (redirect_uri, uid, key) logger.debug("Redirect => %s" % lox) resp = Redirect(lox, headers=[cookie], content="text/html") return resp
def redirect_to_auth(self, _cli, entity_id, came_from, sigalg=None): try: # Picks a binding to use for sending the Request to the IDP _binding, destination = _cli.pick_binding("single_sign_on_service", self.bindings, "idpsso", entity_id=entity_id) logger.debug("binding: %s, destination: %s", _binding, destination) # Binding here is the response binding that is which binding the # IDP should use to return the response. acs = _cli.config.getattr("endpoints", "sp")["assertion_consumer_service"] # just pick one endp, return_binding = acs[0] logger.debug("Binding response to: {}, {}".format( return_binding, endp)) extensions = None cert = None logger.debug("cli config: {}".format(dir(_cli.config))) if _cli.config.generate_cert_func is not None: cert_str, req_key_str = _cli.config.generate_cert_func() cert = {"cert": cert_str, "key": req_key_str} spcertenc = SPCertEnc(x509_data=ds.X509Data( x509_certificate=ds.X509Certificate(text=cert_str))) extensions = Extensions(extension_elements=[ element_to_extension_element(spcertenc) ]) req_id, req = _cli.create_authn_request( destination, binding=return_binding, extensions=extensions, nameid_format=NAMEID_FORMAT_PERSISTENT) _rstate = rndstr() self.cache.relay_state[_rstate] = came_from apply_binding_kwargs = dict(relay_state=_rstate) if sigalg: apply_binding_kwargs['sigalg'] = sigalg ht_args = _cli.apply_binding(_binding, "%s" % req, destination, **apply_binding_kwargs) _sid = req_id if cert is not None: self.cache.outstanding_certs[_sid] = cert except Exception as exc: logger.exception(exc) resp = ServiceError("Failed to construct the AuthnRequest: %s" % exc) return resp # remember the request self.cache.outstanding_queries[_sid] = came_from return self.response(_binding, ht_args, do_not_start_response=True)
def _redirect_to_auth(self, _cli, entity_id, query, end_point_index, vorg_name=""): try: binding, destination = _cli.pick_binding("single_sign_on_service", self.bindings, "idpsso", entity_id=entity_id) logger.debug("binding: %s, destination: %s" % (binding, destination)) extensions = None kwargs = {} if end_point_index: kwargs["assertion_consumer_service_index"] = str( end_point_index[binding]) if _cli.authn_requests_signed: _sid = saml2.s_utils.sid(_cli.seed) req_id, msg_str = _cli.create_authn_request( destination, vorg=vorg_name, sign=_cli.authn_requests_signed, message_id=_sid, extensions=extensions, **kwargs) _sid = req_id else: req_id, req = _cli.create_authn_request(destination, vorg=vorg_name, sign=False, **kwargs) msg_str = "%s" % req _sid = req_id _rstate = rndstr() # self.cache.relay_state[_rstate] = came_from ht_args = _cli.apply_binding(binding, msg_str, destination, relay_state=_rstate) logger.debug("ht_args: %s" % ht_args) except Exception as exc: logger.exception(exc) raise ServiceErrorException( "Failed to construct the AuthnRequest: %s" % exc) # remember the request self.cache_outstanding_queries[_sid] = self.return_to return self.response(binding, ht_args, query)
def do(self): _cli = self.sp # Which page was accessed to get here came_from = geturl(self.environ) logger.debug("[sp.challenge] RelayState >> '%s'" % came_from) # Am I part of a virtual organization or more than one ? try: vorg_name = _cli.vorg._name except AttributeError: vorg_name = "" logger.info("[sp.challenge] VO: %s" % vorg_name) # If more than one idp and if none is selected, I have to do wayf (done, response) = self._pick_idp(came_from) # Three cases: -1 something went wrong or Discovery service used # 0 I've got an IdP to send a request to # >0 ECP in progress logger.debug("_idp_pick returned: %s" % done) if done == -1: return response elif done > 0: self.cache.outstanding_queries[done] = came_from return ECP_response(response) else: entity_id = response # Do the AuthnRequest try: _binding, destination = _cli.pick_binding( "single_sign_on_service", self.bindings, "idpsso", entity_id=entity_id) logger.debug("binding: %s, destination: %s" % (_binding, destination)) req = _cli.create_authn_request(destination, vorg=vorg_name) _rstate = rndstr() self.cache.relay_state[_rstate] = came_from ht_args = _cli.apply_binding(_binding, "%s" % req, destination, relay_state=_rstate) _sid = req.id logger.debug("ht_args: %s" % ht_args) except Exception, exc: logger.exception(exc) resp = ServiceError( "Failed to construct the AuthnRequest: %s" % exc) return resp(self.environ, self.start_response) # remember the request self.cache.outstanding_queries[_sid] = came_from return self.response(_binding, ht_args)
def __init__(self, entity_type, config=None, config_file="", virtual_organization=""): self.entity_type = entity_type self.users = None if config: self.config = config elif config_file: self.config = config_factory(entity_type, config_file) else: raise SAMLError("Missing configuration") for item in ["cert_file", "key_file", "ca_certs"]: _val = getattr(self.config, item, None) if not _val: continue if _val.startswith("http"): r = requests.request("GET", _val) if r.status_code == 200: _, filename = make_temp(r.text, ".pem", False) setattr(self.config, item, filename) else: raise Exception( "Could not fetch certificate from %s" % _val) HTTPBase.__init__(self, self.config.verify_ssl_cert, self.config.ca_certs, self.config.key_file, self.config.cert_file) if self.config.vorg: for vo in self.config.vorg.values(): vo.sp = self self.metadata = self.config.metadata self.config.setup_logger() self.debug = self.config.debug self.seed = rndstr(32) self.sec = security_context(self.config) if virtual_organization: if isinstance(virtual_organization, basestring): self.vorg = self.config.vorg[virtual_organization] elif isinstance(virtual_organization, VirtualOrg): self.vorg = virtual_organization else: self.vorg = None self.artifact = {} if self.metadata: self.sourceid = self.metadata.construct_source_id() else: self.sourceid = {}
def _redirect_to_auth(self, _cli, entity_id, came_from, vorg_name="", cert_str=None, cert_key_str=None): try: _binding, destination = _cli.pick_binding("single_sign_on_service", self.bindings, "idpsso", entity_id=entity_id) self.logger.debug("binding: %s, destination: %s" % (_binding, destination)) extensions = None if cert_key_str is not None: spcertenc = SPCertEnc(x509_data=ds.X509Data( x509_certificate=ds.X509Certificate(text=cert_key_str))) extensions = Extensions(extension_elements=[ element_to_extension_element(spcertenc) ]) if _cli.authn_requests_signed: _sid = saml2.s_utils.sid(_cli.seed) req_id, msg_str = _cli.create_authn_request( destination, vorg=vorg_name, sign=_cli.authn_requests_signed, message_id=_sid, client_crt=cert_str, extensions=extensions) _sid = req_id else: req_id, req = _cli.create_authn_request(destination, vorg=vorg_name, sign=False) msg_str = "%s" % req _sid = req_id _rstate = rndstr() self.cache.relay_state[_rstate] = came_from ht_args = _cli.apply_binding(_binding, msg_str, destination, relay_state=_rstate) self.logger.debug("ht_args: %s" % ht_args) except Exception, exc: self.logger.exception(exc) raise ServiceErrorException( "Failed to construct the AuthnRequest: %s" % exc)
def use_artifact(self, message, endpoint_index=0): """ :param message: :param endpoint_index: :return: """ message_handle = sha1("%s" % message) message_handle.update(rndstr()) mhd = message_handle.digest() saml_art = create_artifact(self.config.entityid, mhd, endpoint_index) self.artifact[saml_art] = message return saml_art
def __init__(self, config_file="", config=None, cache=None, stype="idp", symkey=""): Entity.__init__(self, stype, config, config_file) self.init_config(stype) self.cache = cache self.ticket = {} # self.session_db = self.choose_session_storage() # Needed for self.symkey = symkey self.seed = rndstr() self.iv = os.urandom(16) self.eptid = None
def __init__(self, config_file="", config=None, cache=None, stype="idp", symkey="", msg_cb=None): Entity.__init__(self, stype, config, config_file, msg_cb=msg_cb) self.eptid = None self.init_config(stype) self.cache = cache self.ticket = {} # self.session_db = self.choose_session_storage() # Needed for self.symkey = symkey self.seed = rndstr() self.iv = os.urandom(16) self.lock = threading.Lock()
def __init__(self, config_file="", config=None, cache=None, stype="idp", symkey="", msg_cb=None): Entity.__init__(self, stype, config, config_file, msg_cb=msg_cb) self.eptid = None self.init_config(stype) self.cache = cache self.ticket = {} self.session_db = self.choose_session_storage() if symkey: self.symkey = symkey.encode() else: self.symkey = saml2.cryptography.symmetric.Default.generate_key() self.seed = rndstr() self.lock = threading.Lock()
def create_authn_request(self): try: #sid_ = sid() #self.outstanding_queries[sid_] = came_from idps = self.sp.metadata.with_descriptor("idpsso") if len(idps) == 1: self.entity_id = idps.keys()[0] elif len(idps) > 1: raise Exception("TestSp only supports 1 idp in the metadata!") else: Exception("No IdP metadata found!") _binding, destination = self.sp.pick_binding("single_sign_on_service", self.bindings, "idpsso", entity_id=self.entity_id) self.cert_str, self.cert_key_str = self.generate_cert() cert = { "cert": self.cert_str, "key": self.cert_key_str } spcertenc = SPCertEnc( x509_data=xmldsig.X509Data(x509_certificate=xmldsig.X509Certificate(text=self.cert_str))) extensions = Extensions(extension_elements=[element_to_extension_element(spcertenc)]) try: vorg_name = self.sp.vorg._name except AttributeError: vorg_name = "" if self.sp.authn_requests_signed: self.sid = s_utils.sid() req_id, self.msg_str = self.sp.create_authn_request(destination, vorg=vorg_name, sign=self.sp.authn_requests_signed, message_id=self.sid, extensions=extensions) self.sid = req_id else: req_id, req = self.sp.create_authn_request(destination, vorg=vorg_name, sign=False) self.msg_str = "%s" % req self.sid = req_id if cert is not None: self.outstanding_certs[self.sid] = cert self.rstate = rndstr() self.ht_args = self.sp.apply_binding(_binding, self.msg_str, destination, relay_state=self.rstate) url = self.ht_args["headers"][0][1] except Exception, exc: raise Exception("Failed to construct the AuthnRequest: %s" % exc)
def call_verification(self, data, cookies): prov = self.settings['saml_provider'] authn, _ = prov.authn_broker.pick()[0] name = authn.verify(self.get_argument("random")) if not name is None: uid = rndstr(24) prov.cache.uid2user[uid] = name prov.cache.user2uid[name] = uid self.set_secure_cookie("pysaml", str(uid)) self.redirect("{0}?id={1}&key={2}".format( "/saml/sso/redirect", uid, self.get_argument("key", ""))) else: self.redirect("{0}".format("/saml/sso/redirect"))
def redirect_to_auth(self, _cli, entity_id, came_from): try: # Picks a binding to use for sending the Request to the IDP _binding, destination = _cli.pick_binding( "single_sign_on_service", self.bindings, "idpsso", entity_id=entity_id) logger.debug("binding: %s, destination: %s" % (_binding, destination)) # Binding here is the response binding that is which binding the # IDP should use to return the response. acs = _cli.config.getattr("endpoints", "sp")[ "assertion_consumer_service"] # just pick one endp, return_binding = acs[0] extensions = None cert = None if _cli.config.generate_cert_func is not None: cert_str, req_key_str = _cli.config.generate_cert_func() cert = { "cert": cert_str, "key": req_key_str } spcertenc = SPCertEnc(x509_data=ds.X509Data( x509_certificate=ds.X509Certificate(text=cert_str))) extensions = Extensions(extension_elements=[ element_to_extension_element(spcertenc)]) req_id, req = _cli.create_authn_request(destination, binding=return_binding, extensions=extensions) _rstate = rndstr() self.cache.relay_state[_rstate] = came_from ht_args = _cli.apply_binding(_binding, "%s" % req, destination, relay_state=_rstate) _sid = req_id if cert is not None: self.cache.outstanding_certs[_sid] = cert except Exception, exc: logger.exception(exc) resp = ServiceError( "Failed to construct the AuthnRequest: %s" % exc) return resp
def redirect_to_auth(self, _cli, entity_id, came_from, vorg_name=""): try: _binding, destination = _cli.pick_binding( "single_sign_on_service", self.bindings, "idpsso", entity_id=entity_id) logger.debug("binding: %s, destination: %s" % (_binding, destination)) req_id, req = _cli.create_authn_request(destination, vorg=vorg_name) _rstate = rndstr() self.cache.relay_state[_rstate] = came_from ht_args = _cli.apply_binding(_binding, "%s" % req, destination, relay_state=_rstate) _sid = req_id logger.debug("ht_args: %s" % ht_args) except Exception, exc: logger.exception(exc) resp = ServiceError( "Failed to construct the AuthnRequest: %s" % exc) return resp(self.environ, self.start_response)
def __init__(self, entity_type, config=None, config_file="", virtual_organization=""): self.entity_type = entity_type self.users = None if config: self.config = config elif config_file: self.config = config_factory(entity_type, config_file) else: raise Exception("Missing configuration") HTTPBase.__init__(self, self.config.verify_ssl_cert, self.config.ca_certs, self.config.key_file, self.config.cert_file) if self.config.vorg: for vo in self.config.vorg.values(): vo.sp = self self.metadata = self.config.metadata self.config.setup_logger() self.debug = self.config.debug self.seed = rndstr(32) self.sec = security_context(self.config) if virtual_organization: if isinstance(virtual_organization, basestring): self.vorg = self.config.vorg[virtual_organization] elif isinstance(virtual_organization, VirtualOrg): self.vorg = virtual_organization else: self.vorg = None self.artifact = {} if self.metadata: self.sourceid = self.metadata.construct_source_id() else: self.sourceid = {}
def _redirect_to_auth(self, _cli, entity_id, came_from, vorg_name=""): try: _binding, destination = _cli.pick_binding( "single_sign_on_service", self.bindings, "idpsso", entity_id=entity_id) logger.debug("binding: %s, destination: %s" % (_binding, destination)) id, req = _cli.create_authn_request(destination, vorg=vorg_name) _rstate = rndstr() self.cache.relay_state[_rstate] = came_from ht_args = _cli.apply_binding(_binding, "%s" % (req,), destination, relay_state=_rstate) _sid = req.id logger.debug("ht_args: %s" % ht_args) except Exception, exc: logger.exception(exc) resp = ServiceError( "Failed to construct the AuthnRequest: %s" % exc) return resp
def _redirect_to_auth(self, _cli, entity_id, query, end_point_index, vorg_name=""): try: binding, destination = _cli.pick_binding( "single_sign_on_service", self.bindings, "idpsso", entity_id=entity_id) logger.debug("binding: %s, destination: %s" % (binding, destination)) extensions = None kwargs = {} if end_point_index: kwargs["assertion_consumer_service_index"] = str(end_point_index[binding]) if _cli.authn_requests_signed: _sid = saml2.s_utils.sid(_cli.seed) req_id, msg_str = _cli.create_authn_request( destination, vorg=vorg_name, sign=_cli.authn_requests_signed, message_id=_sid, extensions=extensions, **kwargs) _sid = req_id else: req_id, req = _cli.create_authn_request(destination, vorg=vorg_name, sign=False, **kwargs) msg_str = "%s" % req _sid = req_id _rstate = rndstr() # self.cache.relay_state[_rstate] = came_from ht_args = _cli.apply_binding(binding, msg_str, destination, relay_state=_rstate) logger.debug("ht_args: %s" % ht_args) except Exception as exc: logger.exception(exc) raise ServiceErrorException( "Failed to construct the AuthnRequest: %s" % exc) # remember the request self.cache_outstanding_queries[_sid] = self.return_to return self.response(binding, ht_args, query)
def do_verify(environ, start_response, _user): query = parse_qs(get_post(environ)) logger.debug("do_verify: %s" % query) _ok, user = verify_username_and_password(query) if not _ok: resp = Unauthorized("Unknown user or wrong password") else: id = rndstr() IDP.authn[id] = user logger.debug("Register %s under '%s'" % (user, id)) kaka = set_cookie("idpauthn", "/", id) lox = "http://%s%s?id=%s&key=%s" % (environ["HTTP_HOST"], query["came_from"][0], id, query["key"][0]) logger.debug("Redirect => %s" % lox) resp = Redirect(lox, headers=[kaka], content="text/html") return resp(environ, start_response)
def _redirect_to_auth(self, _cli, entity_id, came_from, vorg_name="", dont_send=False): try: _binding, destination = _cli.pick_binding("single_sign_on_service", self.bindings, "idpsso", entity_id=entity_id) logger.debug("binding: %s, destination: %s" % (_binding, destination)) if "accr" in self.kwargs: kwargs = { "requested_authn_context": RequestedAuthnContext( authn_context_class_ref=AuthnContextClassRef( text=self.kwargs["accr"])) } else: kwargs = {} req = _cli.create_authn_request(destination, vorg=vorg_name, **kwargs) _rstate = rndstr() self.cache.relay_state[_rstate] = came_from ht_args = _cli.apply_binding(_binding, "%s" % req, destination, relay_state=_rstate) _sid = req.id SESSIONDB[_sid] = self.kwargs logger.debug("ht_args: %s" % ht_args) except Exception, exc: logger.exception(exc) resp = ServiceError("Failed to construct the AuthnRequest: %s" % exc) return resp(self.environ, self.start_response)
def setup_request(self): query = self.oper.request _client = self.client _oper = self.oper self.response_func = getattr(_client, "parse_%s_response" % query) qargs = self.args.copy() self.relay_state = rndstr() if "message" not in _oper.args: self.qfunc = getattr(_client, "create_%s" % query) # remove args the create function can't handle fargs = inspect.getargspec(self.qfunc).args if _oper._class: fargs.extend([p for p, c, r in _oper._class.c_attributes.values()]) fargs.extend([p for p, c in _oper._class.c_children.values()]) for arg in qargs.keys(): if arg not in fargs: del qargs[arg] self.qargs = qargs
def __init__(self, entity_type, config=None, config_file="", virtual_organization=""): self.entity_type = entity_type self.users = None if config: self.config = config elif config_file: self.config = config_factory(entity_type, config_file) else: raise SAMLError("Missing configuration") HTTPBase.__init__(self, self.config.verify_ssl_cert, self.config.ca_certs, self.config.key_file, self.config.cert_file) if self.config.vorg: for vo in self.config.vorg.values(): vo.sp = self self.metadata = self.config.metadata self.config.setup_logger() self.debug = self.config.debug self.seed = rndstr(32) self.sec = security_context(self.config) if virtual_organization: if isinstance(virtual_organization, basestring): self.vorg = self.config.vorg[virtual_organization] elif isinstance(virtual_organization, VirtualOrg): self.vorg = virtual_organization else: self.vorg = None self.artifact = {} if self.metadata: self.sourceid = self.metadata.construct_source_id() else: self.sourceid = {}
def _redirect_to_auth(self, _cli, entity_id, query, vorg_name=""): try: binding, destination = _cli.pick_binding( "single_sign_on_service", self.bindings, "idpsso", entity_id=entity_id) logger.debug("binding: %s, destination: %s" % (binding, destination)) extensions = None if _cli.authn_requests_signed: _sid = saml2.s_utils.sid(_cli.seed) req_id, msg_str = _cli.create_authn_request( destination, vorg=vorg_name, sign=_cli.authn_requests_signed, message_id=_sid, extensions=extensions) _sid = req_id else: req_id, req = _cli.create_authn_request(destination, vorg=vorg_name, sign=False) msg_str = "%s" % req _sid = req_id _rstate = rndstr() #self.cache.relay_state[_rstate] = came_from ht_args = _cli.apply_binding(binding, msg_str, destination, relay_state=_rstate) logger.debug("ht_args: %s" % ht_args) except Exception, exc: logger.exception(exc) raise ServiceErrorException( "Failed to construct the AuthnRequest: %s" % exc)
def do_single_sign_on(self, authn_request): """Creates the SAML <AuthnRequest> request for single sign on for single sign on. Returns the appropriate HTTP response. """ identity_provider_entity_id = self.select_identity_provider(authn_request.preferred_identity_provider) binding, destination = self.get_identity_provider_destination(identity_provider_entity_id) kwargs = authn_request.kwargs state = authn_request.state relay_state = authn_request.relay_state kwargs['is_passive'] = 'true' if authn_request.is_passive else None if authn_request.service_provider_url: kwargs['assertion_consumer_service_urls'] = (authn_request.service_provider_url,) sid, message = self.sp.create_authn_request(destination, binding=authn_request.reply_binding, **kwargs) if state or relay_state: relay_state = relay_state or rndstr() self.relay_states[relay_state] = state http_args = self.sp.apply_binding(binding, message, destination, relay_state=relay_state) self.outstanding_queries[sid] = authn_request.service_provider_url return SamlHTTPResponse(http_args, binding)
nagios_args=None): try: _check = Check(client, conf.INTERACTION) except Exception, err: print_status(None, nagios, "CRITICAL", nagios_args, "%s" % err, suppress_output, 0) return RETURN_CODE["CRITICAL"] if login_time: _login_time = _check.login_time else: _login_time = 0 _client = _check.client relay_state = rndstr() _id, htargs = _client.prepare_for_authenticate(entity_id, relay_state=relay_state) resp = _client.send(htargs["headers"][0][1], "GET") if resp.status_code >= 400: print_status(resp, nagios, "CRITICAL", nagios_args, "HTTP status code: %d" % resp.status_code, suppress_output, _login_time) return RETURN_CODE["CRITICAL"] # resp should be dictionary with keys RelayState, SAMLResponse and endpoint try: resp = _check.intermit(resp) except Exception, err: print_status(None, nagios, "UNKNOWN", nagios_args, "%s" % err,
def entcat_test(tinfo): for prof in tinfo['profiles']: if prof == 'entcat' or prof.startswith('entcat:'): return True return False test_id, app_args = setup('wb') app = Flask('saml2test') app.config.update(dict( TESTS=app_args["flows"], DISCOVERY_SERVICE=app_args.get("discovery_service", None), SECRET_KEY=app_args.get("secret_key", rndstr()), RESULT_DB='result_db' )) session_opts = { # TODO can't be server-side due to pyff redirecting to disco endpoint twice "session.type": "memory", "session.validate_key": app.config["SECRET_KEY"] } app.wsgi_app = SessionMiddleware(app.wsgi_app, session_opts) app.session_interface = BeakerSessionInterface() def get_db(): if not hasattr(g, 'result_db'):
"xmlsec_binary" : xmlsec_path, "metadata": { "local": ["idp.xml"], }, "subject_data": "subject_data.db", "accepted_time_diff": 60, "attribute_map_dir" : "attributemaps", } conf = config.SPConfig() conf.load(cnf_dict) client = Saml2Client(conf) binding= BINDING_HTTP_POST query_id = rndstr() service_url = "https://example.com" authn_request = { #===== AuthRequest ===== "subject":{ "base_id":{ "name_qualifier":None, "sp_name_qualifier":None, "text":None, "extension_elements":None, "extension_attributes":None, }, "name_id":{ "name_qualifier":None, "sp_name_qualifier":None,
nagios=False, nagios_args=None, dump=False): try: _check = Check(client) except Exception, err: print_status(nagios, "CRITICAL", nagios_args, "%s" % err, suppress_output, 0, "%s" % err, dump) return RETURN_CODE["CRITICAL"] if login_time: _login_time = _check.login_time else: _login_time = 0 _client = _check.client relay_state = rndstr() _id, htargs = _client.prepare_for_authenticate(entity_id, relay_state=relay_state) _url = htargs["headers"][0][1] resp = _client.send(_url, "GET") up = urlparse(_url) if resp.status_code >= 400: print_status(nagios, "CRITICAL", nagios_args, entity_id, suppress_output, _login_time, resp.content, dump) return RETURN_CODE["CRITICAL"] # resp should be dictionary with keys RelayState, SAMLResponse and endpoint try: resp = _check.intermit(resp,up) except Exception, err:
def _pick_idp(self, came_from): """ If more than one idp and if none is selected, I have to do wayf or disco """ _cli = self.sp logger.debug("[_pick_idp] %s", self.environ) if "HTTP_PAOS" in self.environ: if self.environ["HTTP_PAOS"] == PAOS_HEADER_INFO: if MIME_PAOS in self.environ["HTTP_ACCEPT"]: # Where should I redirect the user to # entityid -> the IdP to use # relay_state -> when back from authentication logger.debug("- ECP client detected -") _rstate = rndstr() self.cache.relay_state[_rstate] = geturl(self.environ) _entityid = _cli.config.ecp_endpoint( self.environ["REMOTE_ADDR"]) if not _entityid: return -1, ServiceError("No IdP to talk to") logger.debug("IdP to talk to: %s", _entityid) return ecp.ecp_auth_request(_cli, _entityid, _rstate) else: return -1, ServiceError("Faulty Accept header") else: return -1, ServiceError("unknown ECP version") # Find all IdPs idps = self.sp.metadata.with_descriptor("idpsso") idp_entity_id = None kaka = self.environ.get("HTTP_COOKIE", "") if kaka: try: (idp_entity_id, _) = parse_cookie("ve_disco", "SEED_SAW", kaka) except ValueError: pass except TypeError: pass # Any specific IdP specified in a query part query = self.environ.get("QUERY_STRING") if not idp_entity_id and query: try: _idp_entity_id = dict(parse_qs(query))[self.idp_query_param][0] if _idp_entity_id in idps: idp_entity_id = _idp_entity_id except KeyError: logger.debug("No IdP entity ID in query: %s", query) pass if not idp_entity_id: if self.wayf: if query: try: wayf_selected = dict( parse_qs(query))["wayf_selected"][0] except KeyError: return self._wayf_redirect(came_from) idp_entity_id = wayf_selected else: return self._wayf_redirect(came_from) elif self.discosrv: if query: idp_entity_id = _cli.parse_discovery_service_response( query=self.environ.get("QUERY_STRING")) if not idp_entity_id: sid_ = sid() self.cache.outstanding_queries[sid_] = came_from logger.debug("Redirect to Discovery Service function") eid = _cli.config.entityid ret = _cli.config.getattr("endpoints", "sp")["discovery_response"][0][0] ret += "?sid=%s" % sid_ loc = _cli.create_discovery_service_request( self.discosrv, eid, **{"return": ret}) return -1, SeeOther(loc) elif len(idps) == 1: # idps is a dictionary idp_entity_id = list(idps.keys())[0] elif not len(idps): return -1, ServiceError("Misconfiguration") else: return -1, NotImplemented("No WAYF or DS present!") logger.info("Chosen IdP: '%s'", idp_entity_id) return 0, idp_entity_id
def pre_processing(self, message, **kwargs): message.assertion.in_response_to = "invalid_rand_" + rndstr(6) return message
def _pick_idp(self, came_from): """ If more than one idp and if none is selected, I have to do wayf or disco """ _cli = self.sp logger.info("[_pick_idp] %s" % self.environ) if "HTTP_PAOS" in self.environ: if self.environ["HTTP_PAOS"] == PAOS_HEADER_INFO: if 'application/vnd.paos+xml' in self.environ["HTTP_ACCEPT"]: # Where should I redirect the user to # entityid -> the IdP to use # relay_state -> when back from authentication logger.info("- ECP client detected -") _rstate = rndstr() self.cache.relay_state[_rstate] = geturl(self.environ) _entityid = _cli.config.ecp_endpoint( self.environ["REMOTE_ADDR"]) if not _entityid: return -1, ServiceError("No IdP to talk to") logger.info("IdP to talk to: %s" % _entityid) return ecp.ecp_auth_request(_cli, _entityid, _rstate) else: return -1, ServiceError('Faulty Accept header') else: return -1, ServiceError('unknown ECP version') # Find all IdPs idps = self.sp.metadata.with_descriptor("idpsso") idp_entity_id = None # Any specific IdP specified in a query part query = self.environ.get("QUERY_STRING") if query: qdict = dict(parse_qs(query)) try: _idp_entity_id = qdict[self.idp_query_param][0] if _idp_entity_id in idps: idp_entity_id = _idp_entity_id except KeyError: logger.debug("No IdP entity ID in query: %s" % query) pass if idp_entity_id is None: if len(idps) == 1: # idps is a dictionary idp_entity_id = idps.keys()[0] elif not len(idps): return -1, ServiceError('Misconfiguration') else: logger.info("ENVIRON: %s" % self.environ) if self.wayf: if query: try: wayf_selected = dict( parse_qs(query))["wayf_selected"][0] except KeyError: return self._wayf_redirect(came_from) idp_entity_id = wayf_selected else: return self._wayf_redirect(came_from) elif self.discosrv: if query and "foo" in qdict: idp_entity_id = _cli.parse_discovery_service_response( query=query) else: sid_ = sid() SESSIONDB[sid_] = self.kwargs self.cache.outstanding_queries[sid_] = came_from logger.info("Redirect to Discovery Service function") eid = _cli.config.entityid ret = _cli.config.getattr( "endpoints", "sp")["discovery_response"][0][0] ret += "?sid=%s" % sid_ loc = _cli.create_discovery_service_request( self.discosrv, eid, **{"return": ret}) return -1, SeeOther(headers=[('Location', loc)]) else: return -1, NotImplemented("No WAYF or DS present!") logger.info("Chosen IdP: '%s'" % idp_entity_id) return 0, idp_entity_id
def pre_processing(self, message, **kwargs): _confirmation = message.assertion.subject.subject_confirmation _confirmation[0].subject_confirmation_data.recipient = rndstr(16) return message
logger.error("UnsupportedBinding: %s" % (excp, )) resp = ServiceError("UnsupportedBinding: %s" % (excp, )) return resp(self.environ, self.start_response) except VerificationError, err: resp = ServiceError("Verification error: %s" % (err, )) return resp(self.environ, self.start_response) except Exception, err: resp = ServiceError("Other error: %s" % (err, )) return resp(self.environ, self.start_response) logger.info("parsed OK") _resp = self.response.response logger.debug("%s" % _resp) session_id = rndstr(16) _info = [ ("Client Address", ip_addresses()), ("Identity Provider", _resp.issuer.text), ("SSO Protocol", samlp.NAMESPACE), ] assertion = simplify(to_dict(_resp, ONTS.values())) SESSIONDB[session_id] = {"info": _info, "assertion": assertion} resp = Response(mako_template="result.mako", template_lookup=LOOKUP, headers=[]) uinfo = [] for key, val in self.response.ava.items(): if len(val) == 1:
def _pick_idp(self, came_from): """ If more than one idp and if none is selected, I have to do wayf or disco """ _cli = self.sp logger.debug("[_pick_idp] %s", self.environ) if "HTTP_PAOS" in self.environ: if self.environ["HTTP_PAOS"] == PAOS_HEADER_INFO: if 'application/vnd.paos+xml' in self.environ["HTTP_ACCEPT"]: # Where should I redirect the user to # entityid -> the IdP to use # relay_state -> when back from authentication logger.debug("- ECP client detected -") _rstate = rndstr() self.cache.relay_state[_rstate] = geturl(self.environ) _entityid = _cli.config.ecp_endpoint( self.environ["REMOTE_ADDR"]) if not _entityid: return -1, ServiceError("No IdP to talk to") logger.debug("IdP to talk to: %s", _entityid) return ecp.ecp_auth_request(_cli, _entityid, _rstate) else: return -1, ServiceError('Faulty Accept header') else: return -1, ServiceError('unknown ECP version') # Find all IdPs idps = self.sp.metadata.with_descriptor("idpsso") idp_entity_id = None kaka = self.environ.get("HTTP_COOKIE", '') if kaka: try: (idp_entity_id, _) = parse_cookie("ve_disco", "SEED_SAW", kaka) except ValueError: pass except TypeError: pass # Any specific IdP specified in a query part query = self.environ.get("QUERY_STRING") if not idp_entity_id and query: try: _idp_entity_id = dict(parse_qs(query))[ self.idp_query_param][0] if _idp_entity_id in idps: idp_entity_id = _idp_entity_id except KeyError: logger.debug("No IdP entity ID in query: %s", query) pass if not idp_entity_id: if self.wayf: if query: try: wayf_selected = dict(parse_qs(query))[ "wayf_selected"][0] except KeyError: return self._wayf_redirect(came_from) idp_entity_id = wayf_selected else: return self._wayf_redirect(came_from) elif self.discosrv: if query: idp_entity_id = _cli.parse_discovery_service_response( query=self.environ.get("QUERY_STRING")) if not idp_entity_id: sid_ = sid() self.cache.outstanding_queries[sid_] = came_from logger.debug("Redirect to Discovery Service function") eid = _cli.config.entityid ret = _cli.config.getattr("endpoints", "sp")["discovery_response"][0][0] ret += "?sid=%s" % sid_ loc = _cli.create_discovery_service_request( self.discosrv, eid, **{"return": ret}) return -1, SeeOther(loc) elif len(idps) == 1: # idps is a dictionary idp_entity_id = idps.keys()[0] elif not len(idps): return -1, ServiceError('Misconfiguration') else: return -1, NotImplemented("No WAYF or DS present!") logger.info("Chosen IdP: '%s'", idp_entity_id) return 0, idp_entity_id
def __init__(self, config=None, identity_cache=None, state_cache=None, virtual_organization="", config_file=""): """ :param config: A saml2.config.Config instance :param identity_cache: Where the class should store identity information :param state_cache: Where the class should keep state information :param virtual_organization: A specific virtual organization """ self.users = Population(identity_cache) # for server state storage if state_cache is None: self.state = {} # in memory storage else: self.state = state_cache if config: self.config = config elif config_file: self.config = config_factory("sp", config_file) else: raise Exception("Missing configuration") HTTPBase.__init__(self, self.config.verify_ssl_cert, self.config.ca_certs, self.config.key_file, self.config.cert_file) if self.config.vorg: for vo in self.config.vorg.values(): vo.sp = self self.metadata = self.config.metadata self.config.setup_logger() # we copy the config.debug variable in an internal # field for convenience and because we may need to # change it during the tests self.debug = self.config.debug self.sec = security_context(self.config) if virtual_organization: if isinstance(virtual_organization, basestring): self.vorg = self.config.vorg[virtual_organization] elif isinstance(virtual_organization, VirtualOrg): self.vorg = virtual_organization else: self.vorg = None for foo in [ "allow_unsolicited", "authn_requests_signed", "logout_requests_signed" ]: if self.config.getattr("sp", foo) == 'true': setattr(self, foo, True) else: setattr(self, foo, False) # extra randomness self.seed = rndstr(32) self.logout_requests_signed_default = True self.allow_unsolicited = self.config.getattr("allow_unsolicited", "sp")
def pre_processing(self, message, **kwargs): message.assertion.in_response_to = rndstr(16) return message
def do(self, query, binding_in, relay_state="", session=None): try: resp_args, _resp = self.verify_request(query, binding_in) except UnknownPrincipal, excp: logger.error("UnknownPrincipal: %s" % (excp,)) resp = ServiceError("UnknownPrincipal: %s" % (excp,)) return resp(self.environ, self.start_response) except UnsupportedBinding, excp: logger.error("UnsupportedBinding: %s" % (excp,)) resp = ServiceError("UnsupportedBinding: %s" % (excp,)) return resp(self.environ, self.start_response) if not _resp: # Contact the RS to get user info _state = rndstr(16) IDP.cache.spq[_state] = {"resp_args": resp_args, "relay_state": relay_state, "req_info": self.req_info, "binding_out": self.binding_out, "destination": self.destination} user_resp = USERS(UIDMAP[self.user], resp_args["sp_entity_id"], state=_state) if isinstance(user_resp, oicResponse): if user_resp.status == "200 OK": user_resp = json.loads(user_resp.message)["resource"] else: return user_resp(self.environ, self.start_response) return self._identity(user_resp, resp_args, relay_state, session)