def test_decrypt(self):
        attr_stat = saml.attribute_statement_from_string(
                            open("encrypted_attribute_statement.xml").read())

        assert len(attr_stat.attribute) == 0
        assert len(attr_stat.encrypted_attribute) == 4

        xmlsec = get_xmlsec_binary()
        sec = SecurityContext(xmlsec, key_file="private_key.pem")

        resp = AuthnResponse(sec, None, "entity_id")
        resp.decrypt_attributes(attr_stat)

        assert len(attr_stat.attribute) == 4
        assert len(attr_stat.encrypted_attribute) == 4
Exemple #2
0
def saml_enum_account_aliases(auth_response: AuthnResponse) -> Dict[str, str]:
    """
    Return the mapping between AWS Account IDs and their aliases.
    """
    return dict(
        pair.split(",") for pair in auth_response.get_identity()
        ["https://github.com/eliezio/sari/AccountAlias"])
    def authn_resp(self):
        authn_resp = AuthnResponse(security_context(SPConfig()), None, 'https://sp.example.com',
                                   allow_unsolicited=True, return_addrs=['http://sp.example.com/demo1/index.php?acs'])

        xmlstr = """<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="_8e8dc5f69a98cc4c1ff3427e5ce34606fd672f91e6" Version="2.0" IssueInstant="2014-07-17T01:01:48Z" Destination="http://sp.example.com/acs" InResponseTo="abc123">
              <saml:Issuer>https://idp.example.com</saml:Issuer>
              <samlp:Status>
                <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
              </samlp:Status>
              <saml:Assertion xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" ID="_d71a3a8e9fcc45c9e9d248ef7049393fc8f04e5f75" Version="2.0" IssueInstant="2014-07-17T01:01:48Z">
                <saml:Issuer>https://idp.example.com</saml:Issuer>
                <saml:Subject>
                  <saml:NameID SPNameQualifier="https://sp.example.com" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient">_ce3d2948b4cf20146dee0a0b3dd6f69b6cf86f62d7</saml:NameID>
                  <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
                    <saml:SubjectConfirmationData NotOnOrAfter="2024-01-18T06:21:48Z" Recipient="https://sp.example.com/acs" InResponseTo="abc123"/>
                  </saml:SubjectConfirmation>
                </saml:Subject>
                <saml:Conditions NotBefore="2014-07-17T01:01:18Z" NotOnOrAfter="2024-01-18T06:21:48Z">
                  <saml:AudienceRestriction>
                    <saml:Audience>https://sp.example.com</saml:Audience>
                  </saml:AudienceRestriction>
                </saml:Conditions>
                <saml:AuthnStatement AuthnInstant="2014-07-17T01:01:48Z" SessionNotOnOrAfter="2024-07-17T09:01:48Z" SessionIndex="_be9967abd904ddcae3c0eb4189adbe3f71e327cf93">
                  <saml:AuthnContext>
                    <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef>
                  </saml:AuthnContext>
                </saml:AuthnStatement>
                <saml:AttributeStatement>
      <saml:Attribute Name="uid" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
        <saml:AttributeValue xsi:type="xs:string">test</saml:AttributeValue>
      </saml:Attribute>
      <saml:Attribute Name="mail" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
        <saml:AttributeValue xsi:type="xs:string">[email protected]</saml:AttributeValue>
      </saml:Attribute>
      <saml:Attribute Name="eduPersonAffiliation" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
        <saml:AttributeValue xsi:type="xs:string">users</saml:AttributeValue>
        <saml:AttributeValue xsi:type="xs:string">examplerole1</saml:AttributeValue>
      </saml:Attribute>
    </saml:AttributeStatement>
              </saml:Assertion>
            </samlp:Response>"""

        authn_resp.loads(xmlstr)
        authn_resp.parse_assertion()
        return authn_resp
Exemple #4
0
    def authn_resp(self):
        authn_resp = AuthnResponse(
            security_context(SPConfig()),
            None,
            'https://sp.example.com',
            allow_unsolicited=True,
            return_addrs=['http://sp.example.com/demo1/index.php?acs'])

        xmlstr = """<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="_8e8dc5f69a98cc4c1ff3427e5ce34606fd672f91e6" Version="2.0" IssueInstant="2014-07-17T01:01:48Z" Destination="http://sp.example.com/acs" InResponseTo="abc123">
              <saml:Issuer>https://idp.example.com</saml:Issuer>
              <samlp:Status>
                <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
              </samlp:Status>
              <saml:Assertion xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" ID="_d71a3a8e9fcc45c9e9d248ef7049393fc8f04e5f75" Version="2.0" IssueInstant="2014-07-17T01:01:48Z">
                <saml:Issuer>https://idp.example.com</saml:Issuer>
                <saml:Subject>
                  <saml:NameID SPNameQualifier="https://sp.example.com" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient">_ce3d2948b4cf20146dee0a0b3dd6f69b6cf86f62d7</saml:NameID>
                  <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
                    <saml:SubjectConfirmationData NotOnOrAfter="2024-01-18T06:21:48Z" Recipient="https://sp.example.com/acs" InResponseTo="abc123"/>
                  </saml:SubjectConfirmation>
                </saml:Subject>
                <saml:Conditions NotBefore="2014-07-17T01:01:18Z" NotOnOrAfter="2024-01-18T06:21:48Z">
                  <saml:AudienceRestriction>
                    <saml:Audience>https://sp.example.com</saml:Audience>
                  </saml:AudienceRestriction>
                </saml:Conditions>
                <saml:AuthnStatement AuthnInstant="2014-07-17T01:01:48Z" SessionNotOnOrAfter="2024-07-17T09:01:48Z" SessionIndex="_be9967abd904ddcae3c0eb4189adbe3f71e327cf93">
                  <saml:AuthnContext>
                    <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef>
                  </saml:AuthnContext>
                </saml:AuthnStatement>
                <saml:AttributeStatement>
      <saml:Attribute Name="uid" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
        <saml:AttributeValue xsi:type="xs:string">test</saml:AttributeValue>
      </saml:Attribute>
      <saml:Attribute Name="mail" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
        <saml:AttributeValue xsi:type="xs:string">[email protected]</saml:AttributeValue>
      </saml:Attribute>
      <saml:Attribute Name="eduPersonAffiliation" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
        <saml:AttributeValue xsi:type="xs:string">users</saml:AttributeValue>
        <saml:AttributeValue xsi:type="xs:string">examplerole1</saml:AttributeValue>
      </saml:Attribute>
    </saml:AttributeStatement>
              </saml:Assertion>
            </samlp:Response>"""

        authn_resp.loads(xmlstr)
        authn_resp.parse_assertion()
        return authn_resp
Exemple #5
0
def saml_enum_aws_roles(
        auth_response: AuthnResponse) -> Dict[str, Tuple[str, str]]:
    """
    Return the Role/Principal pairs defined stored as a pair of attributes in the SAML assertion.

    :return: a dictionary that maps an AWS account to a pair RoleARN/PrincipalARN.
    """
    def group_by_account(role_arn,
                         provider_arn) -> Tuple[str, Tuple[str, str]]:
        acc1 = get_aws_account_from_arn(role_arn)
        acc2 = get_aws_account_from_arn(provider_arn)
        if acc1 != acc2:
            raise ValueError(f"Account mismatch: ${acc1} != ${acc2}")
        return acc1, (role_arn, provider_arn)

    # See
    # https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_saml_assertions.html#saml_role-attribute
    return dict([
        group_by_account(*pair.split(","))
        for pair in auth_response.get_identity()
        ["https://aws.amazon.com/SAML/Attributes/Role"]
    ])
Exemple #6
0
    def handle_acs(self, acs, session, environ, start_response, post):
        if session[self.SPHANDLERVERIFYTYPE] == "OP":
            if post:
                acs = acs.post()
            else:
                acs = acs.redirect()
            resp = self.handle_response_to_op_handler(acs, environ["HTTP_COOKIE"], session)
        else:
            if self.sp_conf.COPY_ASSERTION:
                try:

                    kwargs = {
                        "outstanding_queries": session[self.SPHANDLERSSOCACHE].outstanding_queries,
                        "allow_unsolicited": self.sp.allow_unsolicited,
                        "want_assertions_signed": False,
                        "want_response_signed": self.sp.want_response_signed,
                        "return_addrs": self.sp.service_urls(),
                        "entity_id": self.sp.config.entityid,
                        "attribute_converters": self.sp.config.attribute_converters,
                        "allow_unknown_attributes": self.sp.config.allow_unknown_attributes,
                    }
                    authn_response = AuthnResponse(self.sp.sec, **kwargs)

                    _dict = HttpHandler.query_dictionary(environ)
                    saml_response = _dict["SAMLResponse"]

                    if isinstance(saml_response, list):
                        saml_response = saml_response[0]
                    xmlstr = self.sp.unravel(saml_response, BINDING_HTTP_POST, AuthnResponse.msgtype)

                    authn_response.loads(xmlstr, False)

                    namespace_dict = {}
                    response_search = xmlstr.split(">")
                    for item_resp in response_search:
                        if item_resp.find(":Response") >= 0:
                            str_split = item_resp.split(" ")
                            for item in str_split:
                                if item.find("xmlns:") >= 0:
                                    try:
                                        tmp_namespace = item.split("=")
                                        namespace_dict[tmp_namespace[0].split(":")[1]] = \
                                            (tmp_namespace[1], item)
                                    except Exception:
                                        pass
                            break


                    split_name = "EncryptedAssertion"
                    if xmlstr.find(split_name) < 0:
                        split_name = "Assertion"
                    xmlstr_list = xmlstr.split(split_name)

                    start_index = (xmlstr_list[0][::-1].find("<") + 1) * -1
                    str_assertion = xmlstr_list[0][start_index:] + split_name + xmlstr_list[
                        1] + split_name + ">"

                    str_encrypted_assertion = None
                    if split_name == "EncryptedAssertion":
                        str_encrypted_assertion = str_assertion
                        str_assertion = None

                    """
                    authn_response = authn_response.loads(xmlstr, False)
                    assertion = authn_response.response.assertion[0]
                    if len(authn_response.response.encrypted_assertion) == 1:
                        assertion = authn_response.response.encrypted_assertion[0]

                    str_assertion = str(assertion)
                    """

                    uid = hashlib.sha256(Random.new().read(24)).hexdigest()
                    sp_handler_cache = self.get_sp_handler_cache(uid)
                    if sp_handler_cache is None:
                        sp_handler_cache = SpHandlerCache()
                    sp_handler_cache.uid = uid
                    sp_handler_cache.timeout = authn_response.not_on_or_after
                    sp_handler_cache.attributes = {
                        'eduPersonPrincipalName': [hashlib.sha256(Random.new().read(24)).hexdigest()]
                    }
                    sp_handler_cache.assertion = str_assertion
                    sp_handler_cache.encrypted_assertion = str_encrypted_assertion
                    sp_handler_cache.authnresponse = xmlstr
                    sp_handler_cache.namespace_dict = namespace_dict

                    sp_handler_cache.auth = True
                    self.set_sp_handler_cache(uid, sp_handler_cache)

                    session[SpHandler.SPHANDLERFORUID] = uid
                    resp = self.sp_authentication.authn_redirect(environ)
                    return resp(environ, start_response)
                    #resp = self.sp._parse_response(_dict["SAMLResponse"], AuthnResponse,
                    #   "assertion_consumer_service",BINDING_HTTP_POST, **kwargs)
                except Exception, exc:
                    logger.info("%s" % exc)
                    raise
            else:
Exemple #7
0
    "want_response_signed": conf._sp_want_response_signed,
    "return_addrs": conf.endpoint("assertion_consumer_service", binding, "sp"),
    "entity_id": conf.entityid,
    "attribute_converters": conf.attribute_converters,
    "allow_unknown_attributes": conf.allow_unknown_attributes,
    'conv_info': conv_info
}

# xml unravel fails bacause of b64 inflate method
# pr = client.parse_authn_request_response(saml_auth_response_b64,
# binding,
# outstanding=outstanding,
# outstanding_certs=None,
# conv_info=None)

authn_response = AuthnResponse(client.sec, **kwargs)

# response.loads(xmlstr, False, origxml=origxml)
# authn_response.loads(xmlstr, False, origxml=xmlstr)

# response.py -> AuthnResponse
# in response.loads -> ._loads ->
# authn_response.signature_check(xmldata, origdoc=origxml, must=self.require_signature,
# require_response_signature=self.require_response_signature,
# **args)

# HERE err=18;msg=self signed certificate !
#samlp_response = authn_response.signature_check(xmlstr, must=0, require_response_signature=0)

# ea = samlp_response.encrypted_assertion[0]
# ea.encrypted_data.cipher_data.cipher_value.text
Exemple #8
0
    def handle_acs(self, acs, session, environ, start_response, post):
        if session[self.SPHANDLERVERIFYTYPE] == "OP":
            if post:
                acs = acs.post()
            else:
                acs = acs.redirect()
            resp = self.handle_response_to_op_handler(acs,
                                                      environ["HTTP_COOKIE"],
                                                      session)
        else:
            if self.sp_conf.COPY_ASSERTION:
                try:

                    kwargs = {
                        "outstanding_queries":
                        session[self.SPHANDLERSSOCACHE].outstanding_queries,
                        "allow_unsolicited":
                        self.sp.allow_unsolicited,
                        "want_assertions_signed":
                        False,
                        "want_response_signed":
                        self.sp.want_response_signed,
                        "return_addrs":
                        self.sp.service_urls(),
                        "entity_id":
                        self.sp.config.entityid,
                        "attribute_converters":
                        self.sp.config.attribute_converters,
                        "allow_unknown_attributes":
                        self.sp.config.allow_unknown_attributes,
                    }
                    authn_response = AuthnResponse(self.sp.sec, **kwargs)

                    _dict = HttpHandler.query_dictionary(environ)
                    saml_response = _dict["SAMLResponse"]

                    if isinstance(saml_response, list):
                        saml_response = saml_response[0]
                    xmlstr = self.sp.unravel(saml_response, BINDING_HTTP_POST,
                                             AuthnResponse.msgtype)

                    authn_response.loads(xmlstr, False)

                    namespace_dict = {}
                    response_search = xmlstr.split(">")
                    for item_resp in response_search:
                        if item_resp.find(":Response") >= 0:
                            str_split = item_resp.split(" ")
                            for item in str_split:
                                if item.find("xmlns:") >= 0:
                                    try:
                                        tmp_namespace = item.split("=")
                                        namespace_dict[tmp_namespace[0].split(":")[1]] = \
                                            (tmp_namespace[1], item)
                                    except Exception:
                                        pass
                            break

                    split_name = "EncryptedAssertion"
                    if xmlstr.find(split_name) < 0:
                        split_name = "Assertion"
                    xmlstr_list = xmlstr.split(split_name)

                    start_index = (xmlstr_list[0][::-1].find("<") + 1) * -1
                    str_assertion = xmlstr_list[0][
                        start_index:] + split_name + xmlstr_list[
                            1] + split_name + ">"

                    str_encrypted_assertion = None
                    if split_name == "EncryptedAssertion":
                        str_encrypted_assertion = str_assertion
                        str_assertion = None
                    """
                    authn_response = authn_response.loads(xmlstr, False)
                    assertion = authn_response.response.assertion[0]
                    if len(authn_response.response.encrypted_assertion) == 1:
                        assertion = authn_response.response.encrypted_assertion[0]

                    str_assertion = str(assertion)
                    """

                    uid = hashlib.sha256(Random.new().read(24)).hexdigest()
                    sp_handler_cache = self.get_sp_handler_cache(uid)
                    if sp_handler_cache is None:
                        sp_handler_cache = SpHandlerCache()
                    sp_handler_cache.uid = uid
                    sp_handler_cache.timeout = authn_response.not_on_or_after
                    sp_handler_cache.attributes = {
                        'eduPersonPrincipalName':
                        [hashlib.sha256(Random.new().read(24)).hexdigest()]
                    }
                    sp_handler_cache.assertion = str_assertion
                    sp_handler_cache.encrypted_assertion = str_encrypted_assertion
                    sp_handler_cache.authnresponse = xmlstr
                    sp_handler_cache.namespace_dict = namespace_dict

                    sp_handler_cache.auth = True
                    self.set_sp_handler_cache(uid, sp_handler_cache)

                    session[SpHandler.SPHANDLERFORUID] = uid
                    resp = self.sp_authentication.authn_redirect(environ)
                    return resp(environ, start_response)
                    #resp = self.sp._parse_response(_dict["SAMLResponse"], AuthnResponse,
                    #   "assertion_consumer_service",BINDING_HTTP_POST, **kwargs)
                except Exception, exc:
                    logger.info("%s" % exc)
                    raise
            else:
Exemple #9
0
    def handle_sp_requests(self, environ, start_response, path, session):
        """
        Handles all url:s that are intended for the sp.
        :param environ: WSGI enviroment.
        :param start_response: WSGI start response.
        :return: The response created by underlying methods. For example;
                 Redirect to a discovery server.
                 Redirect to a SAML Idp.
                 URL to the authorization endpoint.
                 400 bad request.
        """
        if path == "sp_metadata":
            start_response('200 OK', [('Content-Type', "text/xml")])
            return self.sp_metadata

        if self.SPHANDLERSSOCACHE not in session or session[self.SPHANDLERSSOCACHE] is None:
            session[self.SPHANDLERSSOCACHE] = Cache()
        if re.search(self.sp_conf.SPVERIFYBASE, path) or re.search(self.sp_conf.SPVERIFYBASEIDP, path):
            if self.sp_conf.SPVERIFYBASE == path:
                session[self.SPHANDLERVERIFYTYPE] = "OP"
            else:
                session[self.SPHANDLERVERIFYTYPE] = "IDP"
            _sso = SSO(self.sp, environ, start_response, self.logger, session[self.SPHANDLERSSOCACHE], **self.args)
            return _sso.do(self.sp_authentication.sp_certificate(environ),
                           self.sp_authentication.sp_encrypt_certificate(environ))
        for regex in self.sp_conf.ASCVERIFYPOSTLIST:
            match = re.search(regex, path)
            if match is not None:
                acs = ACS(self.sp, self.authnmethod, environ, start_response, self.logger,
                          session[self.SPHANDLERSSOCACHE])
                if session[self.SPHANDLERVERIFYTYPE] == "OP":
                    resp = self.handle_response_to_op_handler(acs.post(), environ["HTTP_COOKIE"], session)
                else:
                    if self.sp_conf.COPY_ASSERTION:
                        try:

                            kwargs = {
                                "outstanding_queries": session[self.SPHANDLERSSOCACHE].outstanding_queries,
                                "allow_unsolicited": self.sp.allow_unsolicited,
                                "want_assertions_signed": False,
                                "want_response_signed": self.sp.want_response_signed,
                                "return_addrs": self.sp.service_urls(),
                                "entity_id": self.sp.config.entityid,
                                "attribute_converters": self.sp.config.attribute_converters,
                                "allow_unknown_attributes": self.sp.config.allow_unknown_attributes,
                            }
                            authn_response = AuthnResponse(self.sp.sec, **kwargs)

                            _dict = HttpHandler.query_dictionary(environ)
                            saml_response = _dict["SAMLResponse"]

                            if isinstance(saml_response, list):
                                saml_response = saml_response[0]
                            xmlstr = self.sp.unravel(saml_response, BINDING_HTTP_POST, AuthnResponse.msgtype)

                            authn_response.loads(xmlstr, False)

                            namespace_dict = {}
                            response_search = xmlstr.split(">")
                            for item_resp in response_search:
                                if item_resp.find(":Response") >= 0:
                                    str_split = item_resp.split(" ")
                                    for item in str_split:
                                        if item.find("xmlns:") >= 0:
                                            try:
                                                tmp_namespace = item.split("=")
                                                namespace_dict[tmp_namespace[0].split(":")[1]] = \
                                                    (tmp_namespace[1], item)
                                            except Exception:
                                                pass
                                    break


                            split_name = "EncryptedAssertion"
                            if xmlstr.find(split_name) < 0:
                                split_name = "Assertion"
                            xmlstr_list = xmlstr.split(split_name)

                            start_index = (xmlstr_list[0][::-1].find("<") + 1) * -1
                            str_assertion = xmlstr_list[0][start_index:] + split_name + xmlstr_list[
                                1] + split_name + ">"

                            str_encrypted_assertion = None
                            if split_name == "EncryptedAssertion":
                                str_encrypted_assertion = str_assertion
                                str_assertion = None

                            """
                            authn_response = authn_response.loads(xmlstr, False)
                            assertion = authn_response.response.assertion[0]
                            if len(authn_response.response.encrypted_assertion) == 1:
                                assertion = authn_response.response.encrypted_assertion[0]

                            str_assertion = str(assertion)
                            """

                            uid = hashlib.sha256(Random.new().read(24)).hexdigest()
                            sp_handler_cache = self.get_sp_handler_cache(uid)
                            if sp_handler_cache is None:
                                sp_handler_cache = SpHandlerCache()
                            sp_handler_cache.uid = uid
                            sp_handler_cache.timeout = authn_response.not_on_or_after
                            sp_handler_cache.attributes = {
                                'eduPersonPrincipalName': [hashlib.sha256(Random.new().read(24)).hexdigest()]
                            }
                            sp_handler_cache.assertion = str_assertion
                            sp_handler_cache.encrypted_assertion = str_encrypted_assertion
                            sp_handler_cache.authnresponse = xmlstr
                            sp_handler_cache.namespace_dict = namespace_dict

                            sp_handler_cache.auth = True
                            self.set_sp_handler_cache(uid, sp_handler_cache)

                            session[SpHandler.SPHANDLERFORUID] = uid
                            resp = self.sp_authentication.authn_redirect(environ)
                            return resp(environ, start_response)
                            #resp = self.sp._parse_response(_dict["SAMLResponse"], AuthnResponse,
                            #   "assertion_consumer_service",BINDING_HTTP_POST, **kwargs)
                        except Exception, exc:
                            logger.info("%s" % exc)
                            raise
                    else:
                        resp = self.handle_response_to_idp_handler(acs.post(), environ["HTTP_COOKIE"], session, environ)
                return resp(environ, start_response)