Exemple #1
0
    def create_logout_request(self, destination, issuer_entity_id,
                              subject_id=None, name_id=None,
                              reason=None, expire=None, message_id=0,
                              consent=None, extensions=None, sign=False,
                              session_indexes=None, sign_alg=None,
                              digest_alg=None):
        """ Constructs a LogoutRequest

        :param destination: Destination of the request
        :param issuer_entity_id: The entity ID of the IdP the request is
            target at.
        :param subject_id: The identifier of the subject
        :param name_id: A NameID instance identifying the subject
        :param reason: An indication of the reason for the logout, in the
            form of a URI reference.
        :param expire: The time at which the request expires,
            after which the recipient may discard the message.
        :param message_id: Request identifier
        :param consent: Whether the principal have given her consent
        :param extensions: Possible extensions
        :param sign: Whether the query should be signed or not.
        :param session_indexes: SessionIndex instances or just values
        :return: A LogoutRequest instance
        """

        if subject_id:
            if self.entity_type == "idp":
                name_id = NameID(text=self.users.get_entityid(subject_id,
                                                              issuer_entity_id,
                                                              False))
            else:
                name_id = NameID(text=subject_id)

        if not name_id:
            raise SAMLError("Missing subject identification")

        args = {}
        if session_indexes:
            sis = []
            for si in session_indexes:
                if isinstance(si, SessionIndex):
                    sis.append(si)
                else:
                    sis.append(SessionIndex(text=si))
            args["session_index"] = sis

        return self._message(LogoutRequest, destination, message_id,
                             consent, extensions, sign, name_id=name_id,
                             reason=reason, not_on_or_after=expire,
                             issuer=self._issuer(), sign_alg=sign_alg,
                             digest_alg=digest_alg, **args)
Exemple #2
0
    def create_logout_request(self,
                              destination,
                              issuer_entity_id,
                              subject_id=None,
                              name_id=None,
                              reason=None,
                              expire=None,
                              message_id=0,
                              consent=None,
                              extensions=None,
                              sign=False):
        """ Constructs a LogoutRequest

        :param destination: Destination of the request
        :param issuer_entity_id: The entity ID of the IdP the request is
            target at.
        :param subject_id: The identifier of the subject
        :param name_id: A NameID instance identifying the subject
        :param reason: An indication of the reason for the logout, in the
            form of a URI reference.
        :param expire: The time at which the request expires,
            after which the recipient may discard the message.
        :param message_id: Request identifier
        :param consent: Whether the principal have given her consent
        :param extensions: Possible extensions
        :param sign: Whether the query should be signed or not.
        :return: A LogoutRequest instance
        """

        if subject_id:
            if self.entity_type == "idp":
                name_id = NameID(text=self.users.get_entityid(
                    subject_id, issuer_entity_id, False))
            else:
                name_id = NameID(text=subject_id)

        if not name_id:
            raise Exception("Missing subject identification")

        return self._message(LogoutRequest,
                             destination,
                             message_id,
                             consent,
                             extensions,
                             sign,
                             name_id=name_id,
                             reason=reason,
                             not_on_or_after=expire)
def test_basic():
    sp = Saml2Client(config_file="servera_conf")
    idp = Server(config_file="idp_all_conf")

    # -------- @SP ------------
    binding, destination = sp.pick_binding("manage_name_id_service",
                                           entity_id=idp.config.entityid)

    nameid = NameID(format=NAMEID_FORMAT_TRANSIENT, text="foobar")
    newid = NewID(text="Barfoo")

    mid, mreq = sp.create_manage_name_id_request(destination,
                                                 name_id=nameid,
                                                 new_id=newid)

    print(mreq)
    rargs = sp.apply_binding(binding, "%s" % mreq, destination, "")

    # --------- @IDP --------------

    _req = idp.parse_manage_name_id_request(rargs["data"], binding)

    print(_req.message)

    assert mid == _req.message.id
Exemple #4
0
def test_assertion_with_zero_attributes():
    ava = {}
    ast = Assertion(ava)
    policy = Policy({
        "default": {
            "lifetime": {
                "minutes": 240
            },
            "attribute_restrictions": None,  # means all I have
            "name_form": NAME_FORMAT_URI
        },
    })
    name_id = NameID(format=NAMEID_FORMAT_TRANSIENT, text="foobar")
    issuer = Issuer(text="entityid", format=NAMEID_FORMAT_ENTITY)
    msg = ast.construct("sp_entity_id",
                        "in_response_to",
                        "consumer_url",
                        name_id, [AttributeConverterNOOP(NAME_FORMAT_URI)],
                        policy,
                        issuer=issuer,
                        authn_decl=ACD,
                        authn_auth="authn_authn")

    print(msg)
    assert msg.attribute_statement == []
Exemple #5
0
    def get_nameid(self, userid, nformat, sp_name_qualifier, name_qualifier):
        if nformat == NAMEID_FORMAT_PERSISTENT:
            nameid = self.match_local_id(userid, sp_name_qualifier,
                                         name_qualifier)
            if nameid:
                logger.debug(
                    "Found existing persistent NameId {nid} for user {uid}".
                    format(nid=nameid, uid=userid))
                return nameid

        _id = self.create_id(nformat, name_qualifier, sp_name_qualifier)

        if nformat == NAMEID_FORMAT_EMAILADDRESS:
            if not self.domain:
                raise SAMLError("Can't issue email nameids, unknown domain")

            _id = "%s@%s" % (_id, self.domain)

        nameid = NameID(
            format=nformat,
            sp_name_qualifier=sp_name_qualifier,
            name_qualifier=name_qualifier,
            text=_id,
        )

        self.store(userid, nameid)
        return nameid
    def to_(self, attrvals):
        """ Create a list of Attribute instances.

        :param attrvals: A dictionary of attributes and values
        :return: A list of Attribute instances
        """
        attributes = []
        for key, value in attrvals.items():
            name = self._to.get(key.lower())
            if name:
                if name == "urn:oid:1.3.6.1.4.1.5923.1.1.1.10":
                    # special case for eduPersonTargetedID
                    attr_value = do_ava(
                        NameID(format=NAMEID_FORMAT_PERSISTENT,
                               text=value).to_string())
                else:
                    attr_value = do_ava(value)
                attributes.append(
                    factory(saml.Attribute,
                            name=name,
                            name_format=self.name_format,
                            friendly_name=key,
                            attribute_value=attr_value))
            else:
                attributes.append(
                    factory(saml.Attribute,
                            name=key,
                            attribute_value=do_ava(value)))

        return attributes
def test_assertion_with_noop_attribute_conv():
    ava = {"urn:oid:2.5.4.4": "Roland", "urn:oid:2.5.4.42": "Hedberg" }
    ast = Assertion(ava)
    policy = Policy({
        "default": {
            "lifetime": {"minutes": 240},
            "attribute_restrictions": None,  # means all I have
            "name_form": NAME_FORMAT_URI
        },
    })
    name_id = NameID(format=NAMEID_FORMAT_TRANSIENT, text="foobar")
    issuer = Issuer(text="entityid", format=NAMEID_FORMAT_ENTITY)
    msg = ast.construct("sp_entity_id", "in_response_to", "consumer_url",
                        name_id, [AttributeConverterNOOP(NAME_FORMAT_URI)],
                        policy, issuer=issuer, authn_decl=ACD ,
                        authn_auth="authn_authn")

    print(msg)
    for attr in msg.attribute_statement[0].attribute:
        assert attr.name_format == NAME_FORMAT_URI
        assert len(attr.attribute_value) == 1
        if attr.name == "urn:oid:2.5.4.42":
            assert attr.attribute_value[0].text == "Hedberg"
        elif attr.name == "urn:oid:2.5.4.4":
            assert attr.attribute_value[0].text == "Roland"
Exemple #8
0
def test_assertion_with_authn_instant():
    ava = {}
    ast = Assertion(ava)
    policy = Policy({
        "default": {
            "lifetime": {
                "minutes": 240
            },
            "attribute_restrictions": None,  # means all I have
            "name_form": NAME_FORMAT_URI
        },
    })
    name_id = NameID(format=NAMEID_FORMAT_TRANSIENT, text="foobar")
    issuer = Issuer(text="entityid", format=NAMEID_FORMAT_ENTITY)

    farg = add_path(
        {}, ['subject', 'subject_confirmation', 'method', saml.SCM_BEARER])
    add_path(farg['subject']['subject_confirmation'],
             ['subject_confirmation_data', 'in_response_to', 'in_response_to'])
    add_path(farg['subject']['subject_confirmation'],
             ['subject_confirmation_data', 'recipient', 'consumer_url'])

    msg = ast.construct("sp_entity_id",
                        [AttributeConverterNOOP(NAME_FORMAT_URI)],
                        policy,
                        issuer=issuer,
                        authn_decl=ACD,
                        authn_auth="authn_authn",
                        authn_instant=1234567890,
                        name_id=name_id,
                        farg=farg)

    print(msg)
    assert msg.authn_statement[0].authn_instant == "2009-02-13T23:31:30Z"
Exemple #9
0
def get_auth_token():
    samlServer = server.Server("idp_conf")
    nid = NameID(format=NAMEID_FORMAT_UNSPECIFIED, text="ganderson")
    authn_dict = {
        "decl": "authn_decl",
        "class_ref": UNSPECIFIED,
        "authn_instant": time.time(),
    }
    samlResp = samlServer.create_authn_response(
        identity={},
        in_response_to="",
        userid="ganderson",
        destination=
        "https://uat.envestnet.com/openenv/api/auth/login?firm=edelman",
        sp_entity_id=None,
        sign_assertion=True,
        name_id=nid,
        authn=authn_dict,
    )

    url = "https://uat.envestnet.com/openenv/api/auth/login?firm=edelman"

    headers = DEFAULT_HEADERS.copy()
    headers["Content-Type"] = "application/xml; charset=utf-8"

    resp = webServiceCall(url, headers, data=samlResp)
    return resp.headers["Token"]
Exemple #10
0
 def test_from_local_nest_eduPersonTargetedID_in_NameID(self):
     ava = {"edupersontargetedid": "test value"}
     attributes = from_local(self.acs, ava, URI_NF)
     assert len(attributes) == 1
     assert len(attributes[0].attribute_value) == 1
     assert attributes[0].attribute_value[0].text == NameID(
         format=NAMEID_FORMAT_PERSISTENT,
         text="test value").to_string().decode("utf-8")
def test_request_response():
    sp = Saml2Client(config_file="servera_conf")

    with closing(Server(config_file="idp_all_conf")) as idp:
        binding, destination = sp.pick_binding("name_id_mapping_service",
                                               entity_id=idp.config.entityid)

        policy = NameIDPolicy(format=NAMEID_FORMAT_TRANSIENT,
                              sp_name_qualifier="urn:mace:swamid:junk",
                              allow_create="true")

        nameid = NameID(format=NAMEID_FORMAT_TRANSIENT, text="foobar")

        mid, nmr = sp.create_name_id_mapping_request(policy, nameid,
                                                     destination)

        print nmr

        args = sp.use_soap(nmr, destination)

        # ------- IDP ------------

        req = idp.parse_name_id_mapping_request(args["data"], binding)

        in_response_to = req.message.id
        name_id = NameID(format=NAMEID_FORMAT_PERSISTENT, text="foobar")

        idp_response = idp.create_name_id_mapping_response(
            name_id, in_response_to=in_response_to)

        print idp_response

        ht_args = sp.use_soap(idp_response)

        # ------- SP ------------

        _resp = sp.parse_name_id_mapping_request_response(
            ht_args["data"], binding)

        print _resp.response

        r_name_id = _resp.response.name_id

        assert r_name_id.format == NAMEID_FORMAT_PERSISTENT
        assert r_name_id.text == "foobar"
Exemple #12
0
 def test_create_authn_request_with_subject(self, context, idp_conf, sp_conf, internal_response):
     name_id_value = 'somenameid'
     name_id = NameID(format=NAMEID_FORMAT_UNSPECIFIED, text=name_id_value)
     subject = Subject(name_id=name_id)
     samlfrontend = self.setup_for_authn_req(
         context, idp_conf, sp_conf, subject=subject
     )
     _, internal_req = samlfrontend.handle_authn_request(context, BINDING_HTTP_REDIRECT)
     assert internal_req.subject_id == name_id_value
Exemple #13
0
    def _create_idp_response(
            self,
            authn_request_id='2aaaeb7692471eb4ba00d5546877a7fd',
            cls=Response):
        issue_instant = datetime.utcnow().isoformat() + 'Z'
        not_before = (datetime.utcnow() -
                      timedelta(minutes=5)).isoformat() + 'Z'
        not_on_or_after = (datetime.utcnow() +
                           timedelta(minutes=5)).isoformat() + 'Z'
        issuer = Issuer(format=NAMEID_FORMAT_ENTITY, text='http://nohost/auth')
        signature = pre_signature_part(
            's2998eb2e03b5006acb0a931d0fb558b0e4ec360c7')
        status = Status(status_code=StatusCode(value=STATUS_SUCCESS))
        subject_confirmation_data = SubjectConfirmationData(
            not_on_or_after=not_on_or_after,
            in_response_to=authn_request_id,
            recipient='http://nohost/')
        subject_confirmation = SubjectConfirmation(
            method=SCM_BEARER,
            subject_confirmation_data=subject_confirmation_data)
        subject = Subject(name_id=NameID(text='AABVSVesMLYDiHtowyX4MDu6UopU',
                                         format=NAMEID_FORMAT_TRANSIENT),
                          subject_confirmation=subject_confirmation)
        conditions = Conditions(not_before=not_before,
                                not_on_or_after=not_on_or_after,
                                audience_restriction=AudienceRestriction(
                                    Audience('http://nohost/')),
                                one_time_use=OneTimeUse())
        authn_context = AuthnContext(authn_context_decl_ref=AuthnContextClassRef(
            'urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport'
        ))
        authn_statement = AuthnStatement(authn_instant=issue_instant,
                                         authn_context=authn_context,
                                         session_index=self.session_index)
        attribute_statement = attribute_statement_from_string(
            self.attribute_xml)
        assertion = Assertion(
            id='s2bb879ef893d1b27fb90903e7c7e2779a3e7502c1',
            version='2.0',
            issue_instant=issue_instant,
            issuer=issuer,
            subject=subject,
            conditions=conditions,
            authn_statement=authn_statement,
            attribute_statement=attribute_statement,
        )

        return cls(id='s2998eb2e03b5006acb0a931d0fb558b0e4ec360c7',
                   in_response_to=authn_request_id,
                   version='2.0',
                   issue_instant=issue_instant,
                   destination='http://nohost/',
                   issuer=issuer,
                   signature=signature,
                   status=status,
                   assertion=assertion)
Exemple #14
0
def decode(txt):
    _nid = NameID()
    for part in txt.split(","):
        if part.find("=") != -1:
            i, val = part.split("=")
            try:
                setattr(_nid, ATTR[int(i)], unquote(val))
            except:
                pass
    return _nid
Exemple #15
0
def decode(txt):
    """Turns a coded string by code() into a NameID class instance.

    :param txt: The coded string
    """
    _nid = NameID()
    for part in txt.split(","):
        if part.find("=") != -1:
            i, val = part.split("=")
            try:
                setattr(_nid, ATTR[int(i)], unquote(val))
            except:
                pass
    return _nid
Exemple #16
0
    def get_nameid(self, userid, nformat, sp_name_qualifier, name_qualifier):
        _id = self.create_id(nformat, name_qualifier, sp_name_qualifier)

        if nformat == NAMEID_FORMAT_EMAILADDRESS:
            if not self.domain:
                raise SAMLError("Can't issue email nameids, unknown domain")

            _id = "%s@%s" % (_id, self.domain)

        nameid = NameID(format=nformat, sp_name_qualifier=sp_name_qualifier,
                        name_qualifier=name_qualifier, text=_id)

        self.store(userid, nameid)
        return nameid
Exemple #17
0
def test_basic():
    sp = Saml2Client(config_file="servera_conf")
    with closing(Server(config_file="idp_all_conf")) as idp:
        srvs = sp.metadata.authn_query_service(idp.config.entityid)

        destination = srvs[0]["location"]
        authn_context = requested_authn_context(INTERNETPROTOCOLPASSWORD)

        subject = Subject(text="abc",
                          name_id=NameID(format=NAMEID_FORMAT_TRANSIENT))

        _id, aq = sp.create_authn_query(subject, destination, authn_context)

        print(aq)

        assert isinstance(aq, AuthnQuery)
Exemple #18
0
def post_auth(authData):
    for t in authData:
        if t[0] == 'Stripped-User-Name':
            userName = t[1][1:-1]
        elif t[0] == 'User-Password':
            userPassword = t[1][1:-1]

    identity = ldap_attributes(userName, userPassword)
    if identity == None:
        return radiusd.RLM_MODULE_FAIL

    indentityFiltered = {
        k: identity[k]
        for k in set(ATTRS) & set(identity.keys())
    }
    print {k: identity[k] for k in set(ATTRS) & set(identity.keys())}

    policy = Policy({
        'default': {
            'lifetime': {
                'minutes': 60
            },
            'attribute_restrictions': None,
            'name_form': NAME_FORMAT_URI
        }
    })

    name_id = NameID(format=NAMEID_FORMAT_TRANSIENT,
                     text='urn:mace:' + LDAP_SERVER)
    issuer = Issuer(text='moonshot.' + LDAP_SERVER,
                    format=NAMEID_FORMAT_ENTITY)
    ast = Assertion(indentityFiltered)
    assertion = ast.construct('',
                              '',
                              '',
                              name_id,
                              [AttributeConverterNOOP(NAME_FORMAT_URI)],
                              policy,
                              issuer=issuer)

    assertion = str(assertion).replace('\n', '')

    attr = 'SAML-AAA-Assertion'
    result = (tuple([(attr, x) for x in eq_len_parts('%s' % assertion)]))
    return radiusd.RLM_MODULE_UPDATED, result, None
Exemple #19
0
def test_base_request():
    sp = Saml2Client(config_file="servera_conf")
    idp = Server(config_file="idp_all_conf")

    binding, destination = sp.pick_binding("name_id_mapping_service",
                                           entity_id=idp.config.entityid)

    policy = NameIDPolicy(format=NAMEID_FORMAT_TRANSIENT,
                          sp_name_qualifier="urn:mace:swamid:junk",
                          allow_create="true")

    nameid = NameID(format=NAMEID_FORMAT_TRANSIENT, text="foobar")

    nmr = sp.create_name_id_mapping_request(policy, nameid, destination)

    print nmr

    assert isinstance(nmr, NameIDMappingRequest)
def test_flow():
    sp = Saml2Client(config_file="servera_conf")
    idp = Server(config_file="idp_all_conf")

    binding, destination = sp.pick_binding("manage_name_id_service",
                                           entity_id=idp.config.entityid)

    nameid = NameID(format=NAMEID_FORMAT_TRANSIENT, text="foobar")
    newid = NewID(text="Barfoo")

    mid, mreq = sp.create_manage_name_id_request(destination,
                                                 name_id=nameid,
                                                 new_id=newid)

    print(mreq)
    rargs = sp.apply_binding(binding, "%s" % mreq, destination, "")

    # --------- @IDP --------------

    _req = idp.parse_manage_name_id_request(rargs["data"], binding)

    print((_req.message))

    mnir = idp.create_manage_name_id_response(_req.message, None)

    if binding != BINDING_SOAP:
        binding, destination = idp.pick_binding("manage_name_id_service",
                                                entity_id=sp.config.entityid)
    else:
        destination = ""

    respargs = idp.apply_binding(binding, "%s" % mnir, destination, "")

    print(respargs)

    # ---------- @SP ---------------

    _response = sp.parse_manage_name_id_request_response(
        respargs["data"], binding)

    print((_response.response))

    assert _response.response.id == mnir.id
Exemple #21
0
    def _handle_authn_response(self, context, internal_response, idp):
        """
        See super class satosa.frontends.base.FrontendModule

        :type context: satosa.context.Context
        :type internal_response: satosa.internal_data.InternalResponse
        :type idp: saml.server.Server

        :param context: The current context
        :param internal_response: The internal response
        :param idp: The saml frontend idp server
        :return: A saml response
        """
        request_state = self.load_state(context.state)

        resp_args = request_state["resp_args"]
        ava = self.converter.from_internal(self.attribute_profile,
                                           internal_response.get_attributes())

        auth_info = {}
        if self.acr_mapping:
            auth_info["class_ref"] = self.acr_mapping.get(internal_response.auth_info.issuer, self.acr_mapping[""])
        else:
            auth_info["class_ref"] = internal_response.auth_info.auth_class_ref

        name_id = NameID(text=internal_response.get_user_id(),
                         format=get_saml_name_id_format(internal_response.user_id_hash_type),
                         sp_name_qualifier=None,
                         name_qualifier=None)

        # Will signed the response by default
        resp = self.construct_authn_response(idp,
                                             context.state,
                                             ava,
                                             name_id=name_id,
                                             authn=auth_info,
                                             resp_args=resp_args,
                                             relay_state=request_state["relay_state"],
                                             sign_response=True)

        return resp
Exemple #22
0
def test_assertion_with_noop_attribute_conv():
    ava = {"urn:oid:2.5.4.4": "Roland", "urn:oid:2.5.4.42": "Hedberg"}
    ast = Assertion(ava)
    policy = Policy({
        "default": {
            "lifetime": {
                "minutes": 240
            },
            "attribute_restrictions": None,  # means all I have
            "name_form": NAME_FORMAT_URI
        },
    })
    name_id = NameID(format=NAMEID_FORMAT_TRANSIENT, text="foobar")
    issuer = Issuer(text="entityid", format=NAMEID_FORMAT_ENTITY)

    farg = add_path(
        {}, ['subject', 'subject_confirmation', 'method', saml.SCM_BEARER])
    add_path(farg['subject']['subject_confirmation'],
             ['subject_confirmation_data', 'in_response_to', 'in_response_to'])
    add_path(farg['subject']['subject_confirmation'],
             ['subject_confirmation_data', 'recipient', 'consumer_url'])

    msg = ast.construct("sp_entity_id",
                        [AttributeConverterNOOP(NAME_FORMAT_URI)],
                        policy,
                        issuer=issuer,
                        farg=farg,
                        authn_decl=ACD,
                        name_id=name_id,
                        authn_auth="authn_authn")

    print(msg)
    for attr in msg.attribute_statement[0].attribute:
        assert attr.name_format == NAME_FORMAT_URI
        assert len(attr.attribute_value) == 1
        if attr.name == "urn:oid:2.5.4.42":
            assert attr.attribute_value[0].text == "Hedberg"
        elif attr.name == "urn:oid:2.5.4.4":
            assert attr.attribute_value[0].text == "Roland"
Exemple #23
0
def saml_logout():
    saml_client = saml_client_for(
        current_app.config.get('SECURITY_SAML_IDP_METADATA').split(',')[0])
    nid = NameID(format=NAMEID_FORMAT_UNSPECIFIED,
                 text="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified")

    logout_url = LogoutUrl(
        text=url_for("saml.saml_logout_postback", _external=True))
    destination = current_app.config.get('SECURITY_SAML_FA_URL')

    extensions = Extensions(extension_elements=[logout_url])

    req_id, logout_request = saml_client.create_logout_request(
        name_id=nid,
        destination=destination,
        issuer_entity_id=current_app.config.get('SECURITY_SAML_ENTITY_ID'),
        sign=True,
        consent="urn:oasis:names:tc:SAML:2.0:logout:user",
        extensions=extensions)

    post_message = http_form_post_message(message=logout_request,
                                          location=destination)
    return post_message['data']
from saml2 import extension_elements_to_elements
from saml2 import s_utils
from saml2 import sigver
from saml2 import time_util
from saml2.s_utils import OtherError
from saml2.s_utils import do_attribute_statement
from saml2.s_utils import factory
from saml2.soap import make_soap_enveloped_saml_thingy
from saml2 import BINDING_HTTP_POST
from saml2 import BINDING_HTTP_REDIRECT

from py.test import raises
from pathutils import full_path

nid = NameID(name_qualifier="foo",
             format=NAMEID_FORMAT_TRANSIENT,
             text="123456")

AUTHN = {
    "class_ref": INTERNETPROTOCOLPASSWORD,
    "authn_auth": "http://www.example.com/login"
}


def _eq(l1, l2):
    return set(l1) == set(l2)


BASEDIR = os.path.abspath(os.path.dirname(__file__))

Exemple #25
0
    def _handle_authn_response(self, context, internal_response, idp):
        """
        See super class satosa.frontends.base.FrontendModule

        :type context: satosa.context.Context
        :type internal_response: satosa.internal.InternalData
        :type idp: saml.server.Server

        :param context: The current context
        :param internal_response: The internal response
        :param idp: The saml frontend idp server
        :return: A saml response
        """
        request_state = self.load_state(context.state)

        resp_args = request_state["resp_args"]
        sp_entity_id = resp_args["sp_entity_id"]
        internal_response.attributes = self._filter_attributes(
            idp, internal_response, context)
        ava = self.converter.from_internal(
            self.attribute_profile, internal_response.attributes)

        auth_info = {}
        if self.acr_mapping:
            auth_info["class_ref"] = self.acr_mapping.get(
                internal_response.auth_info.issuer, self.acr_mapping[""])
        else:
            auth_info["class_ref"] = internal_response.auth_info.auth_class_ref

        auth_info["authn_auth"] = internal_response.auth_info.issuer

        if self.custom_attribute_release:
            custom_release = util.get_dict_defaults(
                self.custom_attribute_release,
                internal_response.auth_info.issuer,
                sp_entity_id)
            attributes_to_remove = custom_release.get("exclude", [])
            for k in attributes_to_remove:
                ava.pop(k, None)

        nameid_value = internal_response.subject_id
        nameid_format = subject_type_to_saml_nameid_format(
            internal_response.subject_type
        )

        # If the backend did not receive a SAML <NameID> and so
        # name_id is set to None then do not create a NameID instance.
        # Instead pass None as the name name_id to the IdP server
        # instance and it will use its configured policy to construct
        # a <NameID>, with the default to create a transient <NameID>.
        name_id = None if not nameid_value else NameID(
            text=nameid_value,
            format=nameid_format,
            sp_name_qualifier=None,
            name_qualifier=None,
        )

        msg = "returning attributes {}".format(json.dumps(ava))
        logline = lu.LOG_FMT.format(id=lu.get_session_id(context.state), message=msg)
        logger.debug(logline)

        idp_conf = self.idp_config.get('service', {}).get('idp', {})
        policies = idp_conf.get('policy', {})
        sp_policy = policies.get('default', {})
        sp_policy.update(policies.get(sp_entity_id, {}))

        sign_assertion = sp_policy.get('sign_assertion', False)
        sign_response = sp_policy.get('sign_response', True)
        encrypt_assertion = sp_policy.get('encrypt_assertion', False)
        encrypted_advice_attributes = sp_policy.get('encrypted_advice_attributes', False)

        signing_algorithm = idp_conf.get('signing_algorithm')
        digest_algorithm = idp_conf.get('digest_algorithm')
        sign_alg_attr = sp_policy.get('sign_alg', 'SIG_RSA_SHA256')
        digest_alg_attr = sp_policy.get('digest_alg', 'DIGEST_SHA256')

        # Construct arguments for method create_authn_response
        # on IdP Server instance
        args = {
            # Add the SP details
            **resp_args,
            # AuthnResponse data
            'identity': ava,
            'name_id': name_id,
            'authn': auth_info,
            'sign_response': sign_response,
            'sign_assertion': sign_assertion,
            'encrypt_assertion': encrypt_assertion,
            'encrypted_advice_attributes': encrypted_advice_attributes,
        }

        args['sign_alg'] = signing_algorithm
        if not args['sign_alg']:
            try:
                args['sign_alg'] = getattr(xmldsig, sign_alg_attr)
            except AttributeError as e:
                msg = "Unsupported sign algorithm {}".format(sign_alg)
                logline = lu.LOG_FMT.format(id=lu.get_session_id(context.state), message=msg)
                logger.error(logline)
                raise Exception(msg) from e

        msg = "signing with algorithm {}".format(args['sign_alg'])
        logline = lu.LOG_FMT.format(id=lu.get_session_id(context.state), message=msg)
        logger.debug(logline)

        args['digest_alg'] = digest_algorithm
        if not args['digest_alg']:
            try:
                args['digest_alg'] = getattr(xmldsig, digest_alg_attr)
            except AttributeError as e:
                msg = "Unsupported digest algorithm {}".format(digest_alg)
                logline = lu.LOG_FMT.format(id=lu.get_session_id(context.state), message=msg)
                logger.error(logline)
                raise Exception(msg) from e

        msg = "using digest algorithm {}".format(args['digest_alg'])
        logline = lu.LOG_FMT.format(id=lu.get_session_id(context.state), message=msg)
        logger.debug(logline)

        if sign_alg_attr or digest_alg_attr:
            msg = (
                "sign_alg and digest_alg are deprecated; "
                "instead, use signing_algorithm and digest_algorithm "
                "under the service/idp configuration path "
                "(not under policy/default)."
            )
            logline = lu.LOG_FMT.format(id=lu.get_session_id(context.state), message=msg)
            logger.warning(msg)

        resp = idp.create_authn_response(**args)
        http_args = idp.apply_binding(
            resp_args["binding"], str(resp), resp_args["destination"],
            request_state["relay_state"], response=True)

        # Set the common domain cookie _saml_idp if so configured.
        if self.config.get('common_domain_cookie'):
            self._set_common_domain_cookie(internal_response, http_args, context)

        del context.state[self.name]
        return make_saml_response(resp_args["binding"], http_args)
Exemple #26
0
    def _handle_authn_response(self, context, internal_response, idp):
        """
        See super class satosa.frontends.base.FrontendModule

        :type context: satosa.context.Context
        :type internal_response: satosa.internal.InternalData
        :type idp: saml.server.Server

        :param context: The current context
        :param internal_response: The internal response
        :param idp: The saml frontend idp server
        :return: A saml response
        """
        request_state = self.load_state(context.state)

        resp_args = request_state["resp_args"]
        sp_entity_id = resp_args["sp_entity_id"]
        internal_response.attributes = self._filter_attributes(
            idp, internal_response, context)
        ava = self.converter.from_internal(self.attribute_profile,
                                           internal_response.attributes)

        auth_info = {}
        if self.acr_mapping:
            auth_info["class_ref"] = self.acr_mapping.get(
                internal_response.auth_info.issuer, self.acr_mapping[""])
        else:
            auth_info["class_ref"] = internal_response.auth_info.auth_class_ref

        auth_info["authn_auth"] = internal_response.auth_info.issuer

        if self.custom_attribute_release:
            custom_release = util.get_dict_defaults(
                self.custom_attribute_release,
                internal_response.auth_info.issuer, sp_entity_id)
            attributes_to_remove = custom_release.get("exclude", [])
            for k in attributes_to_remove:
                ava.pop(k, None)

        nameid_value = internal_response.subject_id
        nameid_format = subject_type_to_saml_nameid_format(
            internal_response.subject_type)

        # If the backend did not receive a SAML <NameID> and so
        # name_id is set to None then do not create a NameID instance.
        # Instead pass None as the name name_id to the IdP server
        # instance and it will use its configured policy to construct
        # a <NameID>, with the default to create a transient <NameID>.
        name_id = None if not nameid_value else NameID(
            text=nameid_value,
            format=nameid_format,
            sp_name_qualifier=None,
            name_qualifier=None,
        )

        dbgmsg = "returning attributes %s" % json.dumps(ava)
        satosa_logging(logger, logging.DEBUG, dbgmsg, context.state)

        policies = self.idp_config.get('service',
                                       {}).get('idp', {}).get('policy', {})
        sp_policy = policies.get('default', {})
        sp_policy.update(policies.get(sp_entity_id, {}))

        sign_assertion = sp_policy.get('sign_assertion', False)
        sign_response = sp_policy.get('sign_response', True)
        sign_alg = sp_policy.get('sign_alg', 'SIG_RSA_SHA256')
        digest_alg = sp_policy.get('digest_alg', 'DIGEST_SHA256')

        # Construct arguments for method create_authn_response
        # on IdP Server instance
        args = {
            'identity': ava,
            'name_id': name_id,
            'authn': auth_info,
            'sign_response': sign_response,
            'sign_assertion': sign_assertion,
        }

        # Add the SP details
        args.update(**resp_args)

        try:
            args['sign_alg'] = getattr(xmldsig, sign_alg)
        except AttributeError as e:
            errmsg = "Unsupported sign algorithm %s" % sign_alg
            satosa_logging(logger, logging.ERROR, errmsg, context.state)
            raise Exception(errmsg) from e
        else:
            dbgmsg = "signing with algorithm %s" % args['sign_alg']
            satosa_logging(logger, logging.DEBUG, dbgmsg, context.state)

        try:
            args['digest_alg'] = getattr(xmldsig, digest_alg)
        except AttributeError as e:
            errmsg = "Unsupported digest algorithm %s" % digest_alg
            satosa_logging(logger, logging.ERROR, errmsg, context.state)
            raise Exception(errmsg) from e
        else:
            dbgmsg = "using digest algorithm %s" % args['digest_alg']
            satosa_logging(logger, logging.DEBUG, dbgmsg, context.state)

        resp = idp.create_authn_response(**args)
        http_args = idp.apply_binding(resp_args["binding"],
                                      str(resp),
                                      resp_args["destination"],
                                      request_state["relay_state"],
                                      response=True)

        # Set the common domain cookie _saml_idp if so configured.
        if self.config.get('common_domain_cookie'):
            self._set_common_domain_cookie(internal_response, http_args,
                                           context)

        del context.state[self.name]
        return make_saml_response(resp_args["binding"], http_args)
Exemple #27
0
from saml2.saml import NameID
from saml2.saml import NAMEID_FORMAT_TRANSIENT

__author__ = 'rolandh'

from saml2 import config
from saml2.client import Saml2Client
from saml2.time_util import str_to_time, in_a_while

SESSION_INFO_PATTERN = {"ava": {}, "came from": "", "not_on_or_after": 0,
                        "issuer": "", "session_id": -1}

nid = NameID(name_qualifier="foo", format=NAMEID_FORMAT_TRANSIENT,
             text="abcdefgh")
nid0 = NameID(name_qualifier="foo", format=NAMEID_FORMAT_TRANSIENT,
              text="01234567")


def add_derek_info(sp):
    not_on_or_after = str_to_time(in_a_while(days=1))
    session_info = SESSION_INFO_PATTERN.copy()
    session_info["ava"] = {"givenName": ["Derek"], "umuselin": ["deje0001"]}
    session_info["issuer"] = "urn:mace:example.com:saml:idp"
    session_info["name_id"] = nid
    session_info["not_on_or_after"] = not_on_or_after
    # subject_id, entity_id, info, timestamp
    sp.users.add_information_about_person(session_info)


class TestVirtualOrg():
    def setup_class(self):
Exemple #28
0
def decode(txt):
    _nid = NameID()
    for part in txt.split(","):
        i, val = part.split("=")
        setattr(_nid, ATTR[int(i)], unquote(val))
    return _nid
Exemple #29
0
    "not_on_or_after": 0,
    "issuer": "",
    "session_id": -1
}


def _eq(l1, l2):
    return set(l1) == set(l2)


def nid_eq(l1, l2):
    return _eq([code(c) for c in l1], [code(c) for c in l2])


nid = [
    NameID(name_qualifier="foo", format=NAMEID_FORMAT_TRANSIENT, text="1234"),
    NameID(name_qualifier="foo", format=NAMEID_FORMAT_TRANSIENT, text="9876"),
    NameID(name_qualifier="foo", format=NAMEID_FORMAT_TRANSIENT, text="1000")
]


class TestClass:
    def setup_class(self):
        self.cache = Cache()

    def test_set(self):
        not_on_or_after = str_to_time(in_a_while(days=1))
        session_info = SESSION_INFO_PATTERN.copy()
        session_info["ava"] = {"givenName": ["Derek"]}
        self.cache.set(nid[0], "abcd", session_info, not_on_or_after)