def test():
    with closing(Server(config_file=dotname("idp_all_conf"))) as idp:
        conf = SPConfig()
        conf.load_file(dotname("servera_conf"))
        sp = Saml2Client(conf)

        srvs = sp.metadata.single_sign_on_service(idp.config.entityid,
                                                  BINDING_HTTP_REDIRECT)

        destination = srvs[0]["location"]
        req_id, req = sp.create_authn_request(destination, id="id1")

        info = http_redirect_message(
            req,
            destination,
            relay_state="RS",
            typ="SAMLRequest",
            sigalg=SIG_RSA_SHA1,
            sign=True,
            backend=sp.sec.sec_backend,
        )

        verified_ok = False

        for param, val in info["headers"]:
            if param == "Location":
                _dict = parse_qs(val.split("?")[1])
                _certs = idp.metadata.certs(sp.config.entityid, "any",
                                            "signing")
                for cert in _certs:
                    if verify_redirect_signature(list_values2simpletons(_dict),
                                                 sp.sec.sec_backend, cert[1]):
                        verified_ok = True

        assert verified_ok
    def slo(self, request):
        """
        generate a SAML2 logout request; reset session; return IDP URL
        """
        session = request.SESSION
        session.set(self.session_auth_key, False)
        del session[self.session_user_properties]

        config = self._saml2_config()
        scl = Saml2Client(config)
        samluid = session.get(self.session_samluid_key, "")
        entityid = config.metadata.keys()[0]
        sp_url = self.saml2_sp_url
        actual_url = request.get("ACTUAL_URL", "")
        if not actual_url.startswith(sp_url):
            # the request was made from within a context we cannot handle
            return None
        session.set(self.session_storedurl_key, request.URL1)
        # we cannot simply call global_logout on the client since it doesn't know about our user...
        srvs = scl.metadata.single_logout_service(entityid, BINDING_HTTP_REDIRECT, "idpsso")
        destination = destinations(srvs)[0]
        samlrequest = scl.create_logout_request(destination, entityid, name_id=saml.NameID(text=samluid))
        samlrequest.session_index = samlp.SessionIndex(session.get(self.session_samlsessionindex_key))
        to_sign = []
        samlrequest = signed_instance_factory(samlrequest, scl.sec, to_sign)
        logger.info("SSO logout request: %s" % samlrequest.to_string())
        session_id = samlrequest.id
        rstate = scl._relay_state(session_id)
        msg = http_redirect_message(samlrequest, destination, rstate)
        headers = dict(msg["headers"])
        location = headers["Location"]
        logger.info("attempting to post: {loc}".format(loc=headers["Location"]))
        return location
def test():
    with closing(Server(config_file=dotname("idp_all_conf"))) as idp:
        conf = SPConfig()
        conf.load_file(dotname("servera_conf"))
        sp = Saml2Client(conf)

        srvs = sp.metadata.single_sign_on_service(idp.config.entityid,
                                                  BINDING_HTTP_REDIRECT)

        destination = srvs[0]["location"]
        req_id, req = sp.create_authn_request(destination, id="id1")

        try:
            key = sp.sec.key
        except AttributeError:
            key = import_rsa_key_from_file(sp.sec.key_file)

        info = http_redirect_message(req, destination, relay_state="RS",
                                     typ="SAMLRequest", sigalg=SIG_RSA_SHA1,
                                     key=key)

        verified_ok = False

        for param, val in info["headers"]:
            if param == "Location":
                _dict = parse_qs(val.split("?")[1])
                _certs = idp.metadata.certs(sp.config.entityid, "any", "signing")
                for cert in _certs:
                    if verify_redirect_signature(_dict, cert):
                        verified_ok = True

        assert verified_ok
Exemple #4
0
    def use_http_get(message,
                     destination,
                     relay_state,
                     typ="SAMLRequest",
                     sigalg="",
                     signer=None,
                     **kwargs):
        """
        Send a message using GET, this is the HTTP-Redirect case so
        no direct response is expected to this request.

        :param message:
        :param destination:
        :param relay_state:
        :param typ: Whether a Request, Response or Artifact
        :param sigalg: Which algorithm the signature function will use to sign
            the message
        :param signer: A signing function that can be used to sign the message
        :return: dictionary
        """
        if not isinstance(message, six.string_types):
            message = "%s" % (message, )

        return http_redirect_message(message, destination, relay_state, typ,
                                     sigalg, signer)
def test():
    srvs = sp.metadata.single_sign_on_service(idp.config.entityid,
                                              BINDING_HTTP_REDIRECT)

    destination = srvs[0]["location"]
    req = sp.create_authn_request(destination, id="id1")

    try:
        key = sp.sec.key
    except AttributeError:
        key = rsa_load(sp.sec.key_file)

    info = http_redirect_message(req, destination, relay_state="RS",
                                 typ="SAMLRequest", sigalg=RSA_SHA1, key=key)

    verified_ok = False

    for param, val in info["headers"]:
        if param == "Location":
            _dict = parse_qs(val.split("?")[1])
            _certs = idp.metadata.certs(sp.config.entityid, "any", "signing")
            for cert in _certs:
                if verify_redirect_signature(_dict, cert):
                    verified_ok = True

    assert verified_ok
Exemple #6
0
def test():
    srvs = sp.metadata.single_sign_on_service(idp.config.entityid,
                                              BINDING_HTTP_REDIRECT)

    destination = srvs[0]["location"]
    req_id, req = sp.create_authn_request(destination, id="id1")

    try:
        key = sp.sec.key
    except AttributeError:
        key = import_rsa_key_from_file(sp.sec.key_file)

    info = http_redirect_message(req,
                                 destination,
                                 relay_state="RS",
                                 typ="SAMLRequest",
                                 sigalg=RSA_SHA1,
                                 key=key)

    verified_ok = False

    for param, val in info["headers"]:
        if param == "Location":
            _dict = parse_qs(val.split("?")[1])
            _certs = idp.metadata.certs(sp.config.entityid, "any", "signing")
            for cert in _certs:
                if verify_redirect_signature(_dict, cert):
                    verified_ok = True

    assert verified_ok
Exemple #7
0
def sp_initiated(idp_name):

    app.logger.debug('Space key: {}'.format(""))
    app.logger.debug('idp_name key: {}'.format(idp_name))
    saml_client = saml_client_for(idp_name)

    reqCtx = requested_authn_context([config.get('authn_request_level')],
                                     comparison='exact')

    srvs = saml_client.metadata.single_sign_on_service(
        config.get('test_idp_url'), BINDING_HTTP_POST)

    reqid, req = saml_client.create_authn_request_spid(
        srvs[0]["location"],
        requested_authn_context=reqCtx,
        issuer=Issuer(
            name_qualifier=saml_client.config.getattr('organization').get(
                'url'),
            format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity",
            text=config.get('hostname')),
        sign=False,
        allow_create=None,
        nsprefix={
            "saml": saml.NAMESPACE,
            "samlp": samlp.NAMESPACE
        })

    app.logger.debug('reqid: {}'.format(reqid))
    app.logger.debug('req: {}'.format(req))
    redirect_url = None

    # Select the IdP URL to send the AuthN request to

    signer = saml_client.sec.sec_backend.get_signer(SIG_RSA_SHA256)
    # signer = saml_client.sec.sec_backend.get_signer(SIG_RSA_SHA1)

    info = http_redirect_message(req,
                                 srvs[0]["location"],
                                 relay_state="user",
                                 typ="SAMLRequest",
                                 sigalg=SIG_RSA_SHA256,
                                 signer=signer)

    # info = http_redirect_message(
    #     req, srvs[0]["location"], relay_state="RS",
    #     typ="SAMLRequest")

    app.logger.debug('info: {}'.format(info))
    for key, value in info['headers']:
        if key is 'Location':
            redirect_url = value

    response = redirect(redirect_url, code=302)
    response.headers['Cache-Control'] = 'no-cache, no-store'
    response.headers['Pragma'] = 'no-cache'
    return response
Exemple #8
0
    def use_http_get(self, message, destination, relay_state,
                     typ="SAMLRequest", sign=False):
        """
        Send a message using GET, this is the HTTP-Redirect case so
        no direct response is expected to this request.

        :param message:
        :param destination:
        :param relay_state:
        :param typ: Whether a Request, Response or Artifact
        :return: dictionary
        """
        if not isinstance(message, basestring):
            message = "%s" % (message,)
        if sign:
            key = import_rsa_key_from_file(self.config.key_file)
            return http_redirect_message(message, destination, relay_state,
                                         typ, sigalg=RSA_SHA1, key=key)
        else:
            return http_redirect_message(message, destination,
                                         relay_state, typ)
Exemple #9
0
    def use_http_get(self, message, destination, relay_state):
        """
        Send a message using GET, this is the HTTP-Redirect case so
        no direct response is expected to this request.

        :param request:
        :param destination:
        :param relay_state:
        :return: tuple (header, None)
        """
        if not isinstance(message, basestring):
            request = "%s" % (message, )

        return http_redirect_message(message, destination, relay_state)
Exemple #10
0
    def use_http_get(self, message, destination, relay_state):
        """
        Send a message using GET, this is the HTTP-Redirect case so
        no direct response is expected to this request.

        :param request:
        :param destination:
        :param relay_state:
        :return: tuple (header, None)
        """
        if not isinstance(message, basestring):
            request = "%s" % (message,)

        return http_redirect_message(message, destination, relay_state)
Exemple #11
0
    def use_http_get(message, destination, relay_state, typ="SAMLRequest"):
        """
        Send a message using GET, this is the HTTP-Redirect case so
        no direct response is expected to this request.

        :param message:
        :param destination:
        :param relay_state:
        :param typ: Whether a Request, Response or Artifact
        :return: dictionary
        """
        if not isinstance(message, str):
            message = "%s" % (message, )

        return http_redirect_message(message, destination, relay_state, typ)
Exemple #12
0
    def use_http_get(self, message, destination, relay_state, typ="SAMLRequest"):
        """
        Send a message using GET, this is the HTTP-Redirect case so
        no direct response is expected to this request.

        :param message:
        :param destination:
        :param relay_state:
        :param typ: Whether a Request, Response or Artifact
        :return: dictionary
        """
        if not isinstance(message, basestring):
            message = "%s" % (message,)

        return http_redirect_message(message, destination, relay_state, typ)
Exemple #13
0
    def use_http_get(message, destination, relay_state,
                     typ="SAMLRequest", sigalg="", key=None, **kwargs):
        """
        Send a message using GET, this is the HTTP-Redirect case so
        no direct response is expected to this request.

        :param message:
        :param destination:
        :param relay_state:
        :param typ: Whether a Request, Response or Artifact
        :param sigalg: The signature algorithm to use.
        :param key: Key to use for signing
        :return: dictionary
        """
        if not isinstance(message, six.string_types):
            message = "%s" % (message,)

        return http_redirect_message(message, destination, relay_state, typ,
                                     sigalg, key)
Exemple #14
0
    def use_http_get(message, destination, relay_state,
                     typ="SAMLRequest", sigalg="", key=None, **kwargs):
        """
        Send a message using GET, this is the HTTP-Redirect case so
        no direct response is expected to this request.

        :param message:
        :param destination:
        :param relay_state:
        :param typ: Whether a Request, Response or Artifact
        :param sigalg: The signature algorithm to use.
        :param key: Key to use for signing
        :return: dictionary
        """
        if not isinstance(message, six.string_types):
            message = "%s" % (message,)

        return http_redirect_message(message, destination, relay_state, typ,
                                     sigalg, key)
Exemple #15
0
    def use_http_get(message, destination, relay_state,
                     typ="SAMLRequest", sigalg="", signer=None, **kwargs):
        """
        Send a message using GET, this is the HTTP-Redirect case so
        no direct response is expected to this request.

        :param message:
        :param destination:
        :param relay_state:
        :param typ: Whether a Request, Response or Artifact
        :param sigalg: Which algorithm the signature function will use to sign
            the message
        :param signer: A signing function that can be used to sign the message
        :return: dictionary
        """
        if not isinstance(message, six.string_types):
            message = "%s" % (message,)

        return http_redirect_message(message, destination, relay_state, typ,
                                     sigalg, signer)
    def http_redirect_logout_request_check_session_index(self, get, session_index, log=None):
        """ Deal with a LogoutRequest received through HTTP redirect

        :param get: The request as a dictionary 
        :param subject_id: the id of the current logged user
        :return: a tuple with a list of header tuples (presently only location)
        """
        msg = {}

        try:
            saml_request = get['SAMLRequest']
        except KeyError:
            return None

        if saml_request:
            xml = decode_base64_and_inflate(saml_request)
            logger.info('logout request: %s' % xml)
            request = samlp.logout_request_from_string(xml)
            logger.debug(request)

            if request.session_index[0].text == session_index:
                status = samlp.STATUS_SUCCESS
            else:
                status = samlp.STATUS_REQUEST_DENIED

            response, destination = self .make_logout_response(
                                                        request.issuer.text,
                                                        request.id,
                                                        status)

            logger.info("RESPONSE: {0:>s}".format(response))

            if 'RelayState' in get:
                rstate = get['RelayState']
            else:
                rstate = ""
            msg = http_redirect_message(str(response),
                                        destination,
                                        rstate, 'SAMLResponse')

        return msg
Exemple #17
0
    def http_redirect_logout_request_check_session_index(
            self, get, session_index, log=None):
        """ Deal with a LogoutRequest received through HTTP redirect

        :param get: The request as a dictionary 
        :param subject_id: the id of the current logged user
        :return: a tuple with a list of header tuples (presently only location)
        """
        msg = {}

        try:
            saml_request = get['SAMLRequest']
        except KeyError:
            return None

        if saml_request:
            xml = decode_base64_and_inflate(saml_request)
            logger.info('logout request: %s' % xml)
            request = samlp.logout_request_from_string(xml)
            logger.debug(request)

            if request.session_index[0].text == session_index:
                status = samlp.STATUS_SUCCESS
            else:
                status = samlp.STATUS_REQUEST_DENIED

            response, destination = self.make_logout_response(
                request.issuer.text, request.id, status)

            logger.info("RESPONSE: {0:>s}".format(response))

            if 'RelayState' in get:
                rstate = get['RelayState']
            else:
                rstate = ""
            msg = http_redirect_message(str(response), destination, rstate,
                                        'SAMLResponse')

        return msg
    def slo(self, request):
        """
        generate a SAML2 logout request; reset session; return IDP URL
        """
        session = request.SESSION
        session.set(self.session_auth_key, False)
        del session[self.session_user_properties]

        config = self._saml2_config()
        scl = Saml2Client(config)
        samluid = session.get(self.session_samluid_key, '')
        entityid = config.metadata.keys()[0]
        sp_url = self.saml2_sp_url
        actual_url = request.get("ACTUAL_URL", '')
        if not actual_url.startswith(sp_url):
            # the request was made from within a context we cannot handle
            return None
        session.set(self.session_storedurl_key, request.URL1)
        # we cannot simply call global_logout on the client since it doesn't know about our user...
        srvs = scl.metadata.single_logout_service(entityid,
                                                  BINDING_HTTP_REDIRECT,
                                                  "idpsso")
        destination = destinations(srvs)[0]
        samlrequest = scl.create_logout_request(
            destination, entityid, name_id=saml.NameID(text=samluid))
        samlrequest.session_index = samlp.SessionIndex(
            session.get(self.session_samlsessionindex_key))
        to_sign = []
        samlrequest = signed_instance_factory(samlrequest, scl.sec, to_sign)
        logger.info('SSO logout request: %s' % samlrequest.to_string())
        session_id = samlrequest.id
        rstate = scl._relay_state(session_id)
        msg = http_redirect_message(samlrequest, destination, rstate)
        headers = dict(msg['headers'])
        location = headers['Location']
        logger.info(
            'attempting to post: {loc}'.format(loc=headers['Location']))
        return location
Exemple #19
0
    def _send(self, srv):
        _client = self.client
        loc = srv["location"]
        self.qargs["destination"] = loc
        self.response_args = {}
        use_artifact = getattr(self.oper, "use_artifact", False)

        try:
            req = self.oper.args["message"]
        except KeyError:
            req = self.qfunc(**self.qargs)

        req_id, self.request = self.oper.pre_processing(req, self.args)
        str_req = "%s" % self.request

        if use_artifact:
            saml_art = _client.use_artifact(str_req, self.args["entity_id"])
            logger.info("SAML Artifact: %s" % saml_art)
            info_typ = "SAMLart"
        else:
            logger.info("SAML Request: %s" % str_req)
            info_typ = "SAMLRequest"
            # depending on binding send the query

        if self.args["request_binding"] is BINDING_SOAP:
            res = _client.send_using_soap(str_req, loc)
            if res.status_code >= 400:
                logger.info("Received a HTTP error (%d) '%s'" % (
                    res.status_code, res.text))
                raise HTTPError(res.text)
            else:
                self.response_args["binding"] = BINDING_SOAP
        else:
            self.response_args["binding"] = self.args["response_binding"]
            if self.args["request_binding"] is BINDING_HTTP_REDIRECT:
                htargs = http_redirect_message(str_req, loc, self.relay_state,
                                               info_typ)
                self.response_args["outstanding"] = {self.request.id: "/"}
                #
                res = _client.send(htargs["headers"][0][1], "GET")
            elif self.args["request_binding"] is BINDING_HTTP_POST:
                htargs = http_form_post_message(str_req, loc, self.relay_state,
                                                info_typ)
                info = unpack_form(htargs["data"][3])
                data = form_post(info)
                self.response_args["outstanding"] = {self.request.id: "/"}
                htargs["data"] = data
                htargs["headers"] = [("Content-type",
                                      'application/x-www-form-urlencoded')]
                res = _client.send(loc, "POST", **htargs)
            elif self.args["request_binding"] == BINDING_URI:
                self.response_args["binding"] = BINDING_URI
                htargs = _client.use_http_uri(str_req, "SAMLRequest", loc)
                res = _client.send(htargs["url"], "GET")
            else:
                res = None

            if res is not None and res.status_code >= 400:
                logger.info("Received a HTTP error (%d) '%s'" % (
                    res.status_code, res.text))
                raise HTTPError(res.text)

        self.last_response = res
        try:
            self.last_content = res.text
        except AttributeError:
            self.last_content = None

        return res
Exemple #20
0
    def _send(self, srv):
        _client = self.client
        loc = srv["location"]
        self.qargs["destination"] = loc
        self.response_args = {}
        use_artifact = getattr(self.oper, "use_artifact", False)

        try:
            req = self.oper.args["message"]
        except KeyError:
            req = self.qfunc(**self.qargs)

        req_id, self.request = self.oper.pre_processing(req, self.args)
        str_req = "%s" % self.request

        if use_artifact:
            saml_art = _client.use_artifact(str_req, self.args["entity_id"])
            logger.info("SAML Artifact: %s", saml_art)
            info_typ = "SAMLart"
        else:
            logger.info("SAML Request: %s", str_req)
            info_typ = "SAMLRequest"
            # depending on binding send the query

        if self.args["request_binding"] is BINDING_SOAP:
            res = _client.send_using_soap(str_req, loc)
            if res.status_code >= 400:
                logger.info("Received a HTTP error (%d) '%s'",
                    res.status_code, res.text)
                raise HTTPError(res.text)
            else:
                self.response_args["binding"] = BINDING_SOAP
        else:
            self.response_args["binding"] = self.args["response_binding"]
            if self.args["request_binding"] is BINDING_HTTP_REDIRECT:
                htargs = http_redirect_message(str_req, loc, self.relay_state,
                                               info_typ)
                self.response_args["outstanding"] = {self.request.id: "/"}
                #
                res = _client.send(htargs["headers"][0][1], "GET")
            elif self.args["request_binding"] is BINDING_HTTP_POST:
                htargs = http_form_post_message(str_req, loc, self.relay_state,
                                                info_typ)
                info = unpack_form(htargs["data"][3])
                data = form_post(info)
                self.response_args["outstanding"] = {self.request.id: "/"}
                htargs["data"] = data
                htargs["headers"] = [("Content-type",
                                      'application/x-www-form-urlencoded')]
                res = _client.send(loc, "POST", **htargs)
            elif self.args["request_binding"] == BINDING_URI:
                self.response_args["binding"] = BINDING_URI
                htargs = _client.use_http_uri(str_req, "SAMLRequest", loc)
                res = _client.send(htargs["url"], "GET")
            else:
                res = None

            if res is not None and res.status_code >= 400:
                logger.info("Received a HTTP error (%d) '%s'",
                    res.status_code, res.text)
                raise HTTPError(res.text)

        self.last_response = res
        try:
            self.last_content = res.text
        except AttributeError:
            self.last_content = None

        return res