diff --git a/example/sp-wsgi/sp.py b/example/sp-wsgi/sp.py index f1d1490..1f1de9a 100755 --- a/example/sp-wsgi/sp.py +++ b/example/sp-wsgi/sp.py @@ -3,7 +3,9 @@ from __future__ import print_function import logging import re import argparse +import os from saml2.extension.pefim import SPCertEnc +from saml2.metadata import create_metadata_string import service_conf from Cookie import SimpleCookie @@ -753,6 +755,21 @@ def add_urls(): # ---------------------------------------------------------------------------- +def metadata(environ, start_response): + try: + path = _args.path + if path is None or len(path) == 0: + path = os.path.dirname(os.path.abspath( __file__ )) + if path[-1] != "/": + path += "/" + metadata = create_metadata_string(path+"sp_conf.py", None, + _args.valid, _args.cert, _args.keyfile, + _args.id, _args.name, _args.sign) + start_response('200 OK', [('Content-Type', "text/xml")]) + return metadata + except Exception as ex: + logger.error("An error occured while creating metadata:" + ex.message) + return not_found(environ, start_response) def application(environ, start_response): """ @@ -769,6 +786,8 @@ def application(environ, start_response): path = environ.get('PATH_INFO', '').lstrip('/') logger.debug(" PATH: '%s'" % path) + if path == "metadata": + return metadata(environ, start_response) logger.debug("Finding callback to run") try: @@ -822,6 +841,18 @@ if __name__ == '__main__': _parser.add_argument('-W', dest='wayf', action='store_true', help="Which WAYF url to use") _parser.add_argument("config", help="SAML client config") + _parser.add_argument('-p', dest='path', help='Path to configuration file.') + _parser.add_argument('-v', dest='valid', default="4", + help="How long, in days, the metadata is valid from the time of creation") + _parser.add_argument('-c', dest='cert', help='certificate') + _parser.add_argument('-i', dest='id', + help="The ID of the entities descriptor in the metadata") + _parser.add_argument('-k', dest='keyfile', + help="A file with a key to sign the metadata with") + _parser.add_argument('-n', dest='name') + _parser.add_argument('-S', dest='sign', action='store_true', + help="sign the metadata") + ARGS = {} _args = _parser.parse_args() diff --git a/example/sp-wsgi/sp.xml b/example/sp-wsgi/sp.xml deleted file mode 100644 index f452f02..0000000 --- a/example/sp-wsgi/sp.xml +++ /dev/null @@ -1,34 +0,0 @@ - -http://www.geant.net/uri/dataprotection-code-of-conduct/v1MIIC8jCCAlugAwIBAgIJAJHg2V5J31I8MA0GCSqGSIb3DQEBBQUAMFoxCzAJBgNV -BAYTAlNFMQ0wCwYDVQQHEwRVbWVhMRgwFgYDVQQKEw9VbWVhIFVuaXZlcnNpdHkx -EDAOBgNVBAsTB0lUIFVuaXQxEDAOBgNVBAMTB1Rlc3QgU1AwHhcNMDkxMDI2MTMz -MTE1WhcNMTAxMDI2MTMzMTE1WjBaMQswCQYDVQQGEwJTRTENMAsGA1UEBxMEVW1l -YTEYMBYGA1UEChMPVW1lYSBVbml2ZXJzaXR5MRAwDgYDVQQLEwdJVCBVbml0MRAw -DgYDVQQDEwdUZXN0IFNQMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDkJWP7 -bwOxtH+E15VTaulNzVQ/0cSbM5G7abqeqSNSs0l0veHr6/ROgW96ZeQ57fzVy2MC -FiQRw2fzBs0n7leEmDJyVVtBTavYlhAVXDNa3stgvh43qCfLx+clUlOvtnsoMiiR -mo7qf0BoPKTj7c0uLKpDpEbAHQT4OF1HRYVxMwIDAQABo4G/MIG8MB0GA1UdDgQW -BBQ7RgbMJFDGRBu9o3tDQDuSoBy7JjCBjAYDVR0jBIGEMIGBgBQ7RgbMJFDGRBu9 -o3tDQDuSoBy7JqFepFwwWjELMAkGA1UEBhMCU0UxDTALBgNVBAcTBFVtZWExGDAW -BgNVBAoTD1VtZWEgVW5pdmVyc2l0eTEQMA4GA1UECxMHSVQgVW5pdDEQMA4GA1UE -AxMHVGVzdCBTUIIJAJHg2V5J31I8MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEF -BQADgYEAMuRwwXRnsiyWzmRikpwinnhTmbooKm5TINPE7A7gSQ710RxioQePPhZO -zkM27NnHTrCe2rBVg0EGz7QTd1JIwLPvgoj4VTi/fSha/tXrYUaqc9AqU1kWI4WN -+vffBGQ09mo+6CffuFTZYeOhzP/2stAPwCTU4kxEoiy0KpZMANI= -MIIC8jCCAlugAwIBAgIJAJHg2V5J31I8MA0GCSqGSIb3DQEBBQUAMFoxCzAJBgNV -BAYTAlNFMQ0wCwYDVQQHEwRVbWVhMRgwFgYDVQQKEw9VbWVhIFVuaXZlcnNpdHkx -EDAOBgNVBAsTB0lUIFVuaXQxEDAOBgNVBAMTB1Rlc3QgU1AwHhcNMDkxMDI2MTMz -MTE1WhcNMTAxMDI2MTMzMTE1WjBaMQswCQYDVQQGEwJTRTENMAsGA1UEBxMEVW1l -YTEYMBYGA1UEChMPVW1lYSBVbml2ZXJzaXR5MRAwDgYDVQQLEwdJVCBVbml0MRAw -DgYDVQQDEwdUZXN0IFNQMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDkJWP7 -bwOxtH+E15VTaulNzVQ/0cSbM5G7abqeqSNSs0l0veHr6/ROgW96ZeQ57fzVy2MC -FiQRw2fzBs0n7leEmDJyVVtBTavYlhAVXDNa3stgvh43qCfLx+clUlOvtnsoMiiR -mo7qf0BoPKTj7c0uLKpDpEbAHQT4OF1HRYVxMwIDAQABo4G/MIG8MB0GA1UdDgQW -BBQ7RgbMJFDGRBu9o3tDQDuSoBy7JjCBjAYDVR0jBIGEMIGBgBQ7RgbMJFDGRBu9 -o3tDQDuSoBy7JqFepFwwWjELMAkGA1UEBhMCU0UxDTALBgNVBAcTBFVtZWExGDAW -BgNVBAoTD1VtZWEgVW5pdmVyc2l0eTEQMA4GA1UECxMHSVQgVW5pdDEQMA4GA1UE -AxMHVGVzdCBTUIIJAJHg2V5J31I8MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEF -BQADgYEAMuRwwXRnsiyWzmRikpwinnhTmbooKm5TINPE7A7gSQ710RxioQePPhZO -zkM27NnHTrCe2rBVg0EGz7QTd1JIwLPvgoj4VTi/fSha/tXrYUaqc9AqU1kWI4WN -+vffBGQ09mo+6CffuFTZYeOhzP/2stAPwCTU4kxEoiy0KpZMANI= -My SP serviceExample SP diff --git a/src/saml2/config.py b/src/saml2/config.py index 4c0cb12..9cd36f6 100644 --- a/src/saml2/config.py +++ b/src/saml2/config.py @@ -49,8 +49,8 @@ ONTS = { } COMMON_ARGS = [ - "entityid", "xmlsec_binary", "debug", "key_file", "cert_file", - "encryption_type", "secret", "accepted_time_diff", "name", "ca_certs", + "entityid", "xmlsec_binary", "debug", "key_file", "cert_file", "encryption_keypairs", "additional_cert_files", + "metadata_key_usage", "secret", "accepted_time_diff", "name", "ca_certs", "description", "valid_for", "verify_ssl_cert", "organization", "contact_person", @@ -190,7 +190,9 @@ class Config(object): self.debug = False self.key_file = None self.cert_file = None - self.encryption_type = 'both' + self.encryption_keypairs = None + self.additional_cert_files = None + self.metadata_key_usage = 'both' self.secret = None self.accepted_time_diff = None self.name = None diff --git a/src/saml2/metadata.py b/src/saml2/metadata.py index 980a7b8..700508b 100644 --- a/src/saml2/metadata.py +++ b/src/saml2/metadata.py @@ -191,36 +191,37 @@ def do_contact_person_info(lava): return cps -def do_key_descriptor(cert, use="both"): - if use == "both": - return [ - md.KeyDescriptor( - key_info=ds.KeyInfo( - x509_data=ds.X509Data( - x509_certificate=ds.X509Certificate(text=cert) - ) - ), - use="encryption" - ), - md.KeyDescriptor( - key_info=ds.KeyInfo( - x509_data=ds.X509Data( - x509_certificate=ds.X509Certificate(text=cert) - ) - ), - use="signing" - ) - ] - elif use in ["signing", "encryption"]: - return md.KeyDescriptor( - key_info=ds.KeyInfo( - x509_data=ds.X509Data( - x509_certificate=ds.X509Certificate(text=cert) +def do_key_descriptor(cert=None, enc_cert=None, use="both"): + kd_list = [] + if use in ["signing", "both"] and cert is not None: + if not isinstance(cert, list): + cert = [cert] + for _cert in cert: + kd_list.append( + md.KeyDescriptor( + key_info=ds.KeyInfo( + x509_data=ds.X509Data( + x509_certificate=ds.X509Certificate(text=_cert) + ) + ), + use="signing" ) - ), - use=use - ) - else: + ) + if use in ["both", "encryption"] and enc_cert is not None: + if not isinstance(enc_cert, list): + enc_cert = [enc_cert] + for _enc_cert in enc_cert: + kd_list.append( + md.KeyDescriptor( + key_info=ds.KeyInfo( + x509_data=ds.X509Data( + x509_certificate=ds.X509Certificate(text=_enc_cert) + ) + ), + use="encryption" + ) + ) + if len(kd_list) == 0 and cert is not None: return md.KeyDescriptor( key_info=ds.KeyInfo( x509_data=ds.X509Data( @@ -228,6 +229,7 @@ def do_key_descriptor(cert, use="both"): ) ) ) + return kd_list def do_requested_attribute(attributes, acs, is_required="false"): @@ -502,7 +504,7 @@ def do_attribute_consuming_service(conf, spsso): spsso.attribute_consuming_service = [ac_serv] -def do_spsso_descriptor(conf, cert=None): +def do_spsso_descriptor(conf, cert=None, enc_cert=None): spsso = md.SPSSODescriptor() spsso.protocol_support_enumeration = samlp.NAMESPACE @@ -537,9 +539,9 @@ def do_spsso_descriptor(conf, cert=None): spsso.extensions = md.Extensions() spsso.extensions.add_extension_element(do_uiinfo(ui_info)) - if cert: - encryption_type = conf.encryption_type - spsso.key_descriptor = do_key_descriptor(cert, encryption_type) + if cert or enc_cert: + metadata_key_usage = conf.metadata_key_usage + spsso.key_descriptor = do_key_descriptor(cert=cert, enc_cert=enc_cert, use=metadata_key_usage) for key in ["want_assertions_signed", "authn_requests_signed"]: try: @@ -557,7 +559,7 @@ def do_spsso_descriptor(conf, cert=None): return spsso -def do_idpsso_descriptor(conf, cert=None): +def do_idpsso_descriptor(conf, cert=None, enc_cert=None): idpsso = md.IDPSSODescriptor() idpsso.protocol_support_enumeration = samlp.NAMESPACE @@ -586,8 +588,8 @@ def do_idpsso_descriptor(conf, cert=None): idpsso.extensions = md.Extensions() idpsso.extensions.add_extension_element(do_uiinfo(ui_info)) - if cert: - idpsso.key_descriptor = do_key_descriptor(cert) + if cert or enc_cert: + idpsso.key_descriptor = do_key_descriptor(cert, enc_cert, use=conf.metadata_key_usage) for key in ["want_authn_requests_signed"]: #"want_authn_requests_only_with_valid_cert"]: @@ -603,7 +605,7 @@ def do_idpsso_descriptor(conf, cert=None): return idpsso -def do_aa_descriptor(conf, cert): +def do_aa_descriptor(conf, cert=None, enc_cert=None): aad = md.AttributeAuthorityDescriptor() aad.protocol_support_enumeration = samlp.NAMESPACE @@ -616,8 +618,8 @@ def do_aa_descriptor(conf, cert): _do_nameid_format(aad, conf, "aa") - if cert: - aad.key_descriptor = do_key_descriptor(cert) + if cert or enc_cert: + aad.key_descriptor = do_key_descriptor(cert, enc_cert, use=conf.metadata_key_usage) attributes = conf.getattr("attribute", "aa") if attributes: @@ -632,7 +634,7 @@ def do_aa_descriptor(conf, cert): return aad -def do_aq_descriptor(conf, cert): +def do_aq_descriptor(conf, cert=None, enc_cert=None): aqs = md.AuthnAuthorityDescriptor() aqs.protocol_support_enumeration = samlp.NAMESPACE @@ -645,13 +647,13 @@ def do_aq_descriptor(conf, cert): _do_nameid_format(aqs, conf, "aq") - if cert: - aqs.key_descriptor = do_key_descriptor(cert) + if cert or enc_cert: + aqs.key_descriptor = do_key_descriptor(cert, enc_cert, use=conf.metadata_key_usage) return aqs -def do_pdp_descriptor(conf, cert): +def do_pdp_descriptor(conf, cert=None, enc_cert=None): """ Create a Policy Decision Point descriptor """ pdp = md.PDPDescriptor() @@ -667,13 +669,24 @@ def do_pdp_descriptor(conf, cert): _do_nameid_format(pdp, conf, "pdp") if cert: - pdp.key_descriptor = do_key_descriptor(cert) + pdp.key_descriptor = do_key_descriptor(cert, enc_cert, use=conf.metadata_key_usage) return pdp def entity_descriptor(confd): - mycert = "".join(open(confd.cert_file).readlines()[1:-1]) + mycert = None + enc_cert = None + if confd.cert_file is not None: + mycert = [] + mycert.append("".join(open(confd.cert_file).readlines()[1:-1])) + if confd.additional_cert_files is not None: + for _cert_file in confd.additional_cert_files: + mycert.append("".join(open(_cert_file).readlines()[1:-1])) + if confd.encryption_keypairs is not None: + enc_cert = [] + for _encryption in confd.encryption_keypairs: + enc_cert.append("".join(open(_encryption["cert_file"]).readlines()[1:-1])) entd = md.EntityDescriptor() entd.entity_id = confd.entityid @@ -701,19 +714,19 @@ def entity_descriptor(confd): if "sp" in serves: confd.context = "sp" - entd.spsso_descriptor = do_spsso_descriptor(confd, mycert) + entd.spsso_descriptor = do_spsso_descriptor(confd, mycert, enc_cert) if "idp" in serves: confd.context = "idp" - entd.idpsso_descriptor = do_idpsso_descriptor(confd, mycert) + entd.idpsso_descriptor = do_idpsso_descriptor(confd, mycert, enc_cert) if "aa" in serves: confd.context = "aa" - entd.attribute_authority_descriptor = do_aa_descriptor(confd, mycert) + entd.attribute_authority_descriptor = do_aa_descriptor(confd, mycert, enc_cert) if "pdp" in serves: confd.context = "pdp" - entd.pdp_descriptor = do_pdp_descriptor(confd, mycert) + entd.pdp_descriptor = do_pdp_descriptor(confd, mycert, enc_cert) if "aq" in serves: confd.context = "aq" - entd.authn_authority_descriptor = do_aq_descriptor(confd, mycert) + entd.authn_authority_descriptor = do_aq_descriptor(confd, mycert, enc_cert) return entd diff --git a/src/saml2/sigver.py b/src/saml2/sigver.py index df09720..0409610 100644 --- a/src/saml2/sigver.py +++ b/src/saml2/sigver.py @@ -1055,6 +1055,12 @@ def security_context(conf, debug=None): raise SigverError('Unknown crypto_backend %s' % ( repr(conf.crypto_backend))) + enc_key_files = [] + if conf.encryption_keypairs is not None: + for _encryption_keypair in conf.encryption_keypairs: + if "key_file" in _encryption_keypair: + enc_key_files.append(_encryption_keypair["key_file"]) + return SecurityContext( crypto, conf.key_file, cert_file=conf.cert_file, metadata=metadata, debug=debug, only_use_keys_in_metadata=_only_md, @@ -1062,7 +1068,8 @@ def security_context(conf, debug=None): generate_cert_info=conf.generate_cert_info, tmp_cert_file=conf.tmp_cert_file, tmp_key_file=conf.tmp_key_file, - validate_certificate=conf.validate_certificate) + validate_certificate=conf.validate_certificate, + enc_key_files=enc_key_files, encryption_keypairs=conf.encryption_keypairs) def encrypt_cert_from_item(item): @@ -1239,19 +1246,30 @@ class SecurityContext(object): debug=False, template="", encrypt_key_type="des-192", only_use_keys_in_metadata=False, cert_handler_extra_class=None, generate_cert_info=None, tmp_cert_file=None, - tmp_key_file=None, validate_certificate=None): + tmp_key_file=None, validate_certificate=None, enc_key_files=None, enc_key_type="pem", + encryption_keypairs=None, enc_cert_type="pem"): self.crypto = crypto assert (isinstance(self.crypto, CryptoBackend)) - # Your private key + # Your private key for signing self.key_file = key_file self.key_type = key_type - # Your public key + # Your public key for signing self.cert_file = cert_file self.cert_type = cert_type + # Your private key for encryption + self.enc_key_files = enc_key_files + self.enc_key_type = enc_key_type + + # Your public key for encryption + self.encryption_keypairs = encryption_keypairs + self.enc_cert_type = enc_cert_type + + + self.my_cert = read_cert_from_file(cert_file, cert_type) self.cert_handler = CertHandler(self, cert_file, cert_type, key_file, @@ -1320,11 +1338,14 @@ class SecurityContext(object): :param enctext: The encrypted text as a string :return: The decrypted text """ + _enctext = None if not isinstance(keys, list): keys = [keys] - _enctext = self.crypto.decrypt(enctext, self.key_file) - if _enctext is not None and len(_enctext) > 0: - return _enctext + if self.enc_key_files is not None: + for _enc_key_file in self.enc_key_files: + _enctext = self.crypto.decrypt(enctext, _enc_key_file) + if _enctext is not None and len(_enctext) > 0: + return _enctext for _key in keys: if _key is not None and len(_key.strip()) > 0: _, key_file = make_temp("%s" % _key, decode=False) @@ -1339,9 +1360,12 @@ class SecurityContext(object): :param enctext: The encrypted text as a string :return: The decrypted text """ - _enctext = self.crypto.decrypt(enctext, self.key_file) - if _enctext is not None and len(_enctext) > 0: - return _enctext + _enctext = None + if self.enc_key_files is not None: + for _enc_key_file in self.enc_key_files: + _enctext = self.crypto.decrypt(enctext, _enc_key_file) + if _enctext is not None and len(_enctext) > 0: + return _enctext if key_file is not None and len(key_file.strip()) > 0: _enctext = self.crypto.decrypt(enctext, key_file) if _enctext is not None and len(_enctext) > 0: diff --git a/tests/metadata_sp_1.xml b/tests/metadata_sp_1.xml index 57441dd..24e189a 100644 --- a/tests/metadata_sp_1.xml +++ b/tests/metadata_sp_1.xml @@ -32,21 +32,38 @@ - MIICsDCCAhmgAwIBAgIJAJrzqSSwmDY9MA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV - BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX - aWRnaXRzIFB0eSBMdGQwHhcNMDkxMDA2MTk0OTQxWhcNMDkxMTA1MTk0OTQxWjBF - MQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50 - ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB - gQDJg2cms7MqjniT8Fi/XkNHZNPbNVQyMUMXE9tXOdqwYCA1cc8vQdzkihscQMXy - 3iPw2cMggBu6gjMTOSOxECkuvX5ZCclKr8pXAJM5cY6gVOaVO2PdTZcvDBKGbiaN - efiEw5hnoZomqZGp8wHNLAUkwtH9vjqqvxyS/vclc6k2ewIDAQABo4GnMIGkMB0G - A1UdDgQWBBRePsKHKYJsiojE78ZWXccK9K4aJTB1BgNVHSMEbjBsgBRePsKHKYJs - iojE78ZWXccK9K4aJaFJpEcwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUt - U3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZIIJAJrzqSSw - mDY9MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAJSrKOEzHO7TL5cy6 - h3qh+3+JAk8HbGBW+cbX6KBCAw/mzU8flK25vnWwXS3dv2FF3Aod0/S7AWNfKib5 - U/SA9nJaz/mWeF9S0farz9AQFc8/NSzAzaVq7YbM4F6f6N2FRl7GikdXRCed45j6 - mrPzGzk3ECbupFnqyREH3+ZPSdk= + MIICHzCCAYgCAQEwDQYJKoZIhvcNAQELBQAwWDELMAkGA1UEBhMCenoxCzAJBgNV + BAgMAnp6MQ0wCwYDVQQHDAR6enp6MQ4wDAYDVQQKDAVaenp6ejEOMAwGA1UECwwF + Wnp6enoxDTALBgNVBAMMBHRlc3QwHhcNMTUwNjAyMDc0MzAxWhcNMjUwNTMwMDc0 + MzAxWjBYMQswCQYDVQQGEwJ6ejELMAkGA1UECAwCenoxDTALBgNVBAcMBHp6enox + DjAMBgNVBAoMBVp6enp6MQ4wDAYDVQQLDAVaenp6ejENMAsGA1UEAwwEdGVzdDCB + nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA41tJCTPuG2lirbztuGbBlzbzSipM + EzM+zluWegUaoUjqtlgNHOTQqTJOqw/GdjkxRKJT6IxI3/HVcnfw7P4a4xSkL/ME + IG3VyzedWEyLIHeofoQSTvr84ZdD0+Gk+zNCSqOQC7UuqpOLbMKK1tgZ8Mr7BkgI + p8H3lreLf29Sd5MCAwEAATANBgkqhkiG9w0BAQsFAAOBgQB0EXxy5+hsB7Rid7Gy + CZrAObpaC4nbyPPW/vccFKmEkYtlygEPgky7D9AGsVSaTc/YxPZcanY+vKoRIsiR + 6ZitIUU5b+NnHcdj6289tUQ0iHj5jgVyv8wYHvPntTnqH2S7he0talLER8ITYToh + 2wz3u7waz/GypMeA/suhoEfxew== + + + + + + + + + MIICHzCCAYgCAQEwDQYJKoZIhvcNAQELBQAwWDELMAkGA1UEBhMCenoxCzAJBgNV + BAgMAnp6MQ0wCwYDVQQHDAR6enp6MQ4wDAYDVQQKDAVaenp6ejEOMAwGA1UECwwF + Wnp6enoxDTALBgNVBAMMBHRlc3QwHhcNMTUwNjAyMDc0MjI2WhcNMjUwNTMwMDc0 + MjI2WjBYMQswCQYDVQQGEwJ6ejELMAkGA1UECAwCenoxDTALBgNVBAcMBHp6enox + DjAMBgNVBAoMBVp6enp6MQ4wDAYDVQQLDAVaenp6ejENMAsGA1UEAwwEdGVzdDCB + nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAx3I/NFlP1wbHfRZckJn4z1HX5nnY + QhQ3ekxEJmTTaj/1BvlZBmvgV40SBzH4nP1sT02xoQo7+vHItFAzaJlF2oBXsSxj + aZMGu/gkVbaHP9cYKvskhOjOJ4XArrUnKMTb1jZ+XkkOuot1NLE7/dTILF8ahHU2 + omYNASLnxHN3bnkCAwEAATANBgkqhkiG9w0BAQsFAAOBgQCQam1Oz7iQcD9+OurB + M5a+Hth53m5hbAFuguSvERPCuJ/CfP1+g7CIZN/GnsIsg9QW77NvdOyxjXxzoJJm + okl1qz/qy3FY3mJ0gIUxDyPD9DL3c9/03MDv5YmWsoP+HNqK8QtNJ/JDEOhBr/Eo + /MokRo4gtMNeLF/soveWNoNiUg== diff --git a/tests/pki/test_1.crt b/tests/pki/test_1.crt new file mode 100644 index 0000000..d43cc1d --- /dev/null +++ b/tests/pki/test_1.crt @@ -0,0 +1,14 @@ +-----BEGIN CERTIFICATE----- +MIICHzCCAYgCAQEwDQYJKoZIhvcNAQELBQAwWDELMAkGA1UEBhMCenoxCzAJBgNV +BAgMAnp6MQ0wCwYDVQQHDAR6enp6MQ4wDAYDVQQKDAVaenp6ejEOMAwGA1UECwwF +Wnp6enoxDTALBgNVBAMMBHRlc3QwHhcNMTUwNjAyMDc0MjI2WhcNMjUwNTMwMDc0 +MjI2WjBYMQswCQYDVQQGEwJ6ejELMAkGA1UECAwCenoxDTALBgNVBAcMBHp6enox +DjAMBgNVBAoMBVp6enp6MQ4wDAYDVQQLDAVaenp6ejENMAsGA1UEAwwEdGVzdDCB +nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAx3I/NFlP1wbHfRZckJn4z1HX5nnY +QhQ3ekxEJmTTaj/1BvlZBmvgV40SBzH4nP1sT02xoQo7+vHItFAzaJlF2oBXsSxj +aZMGu/gkVbaHP9cYKvskhOjOJ4XArrUnKMTb1jZ+XkkOuot1NLE7/dTILF8ahHU2 +omYNASLnxHN3bnkCAwEAATANBgkqhkiG9w0BAQsFAAOBgQCQam1Oz7iQcD9+OurB +M5a+Hth53m5hbAFuguSvERPCuJ/CfP1+g7CIZN/GnsIsg9QW77NvdOyxjXxzoJJm +okl1qz/qy3FY3mJ0gIUxDyPD9DL3c9/03MDv5YmWsoP+HNqK8QtNJ/JDEOhBr/Eo +/MokRo4gtMNeLF/soveWNoNiUg== +-----END CERTIFICATE----- diff --git a/tests/pki/test_1.key b/tests/pki/test_1.key new file mode 100644 index 0000000..284ca42 --- /dev/null +++ b/tests/pki/test_1.key @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXgIBAAKBgQDHcj80WU/XBsd9FlyQmfjPUdfmedhCFDd6TEQmZNNqP/UG+VkG +a+BXjRIHMfic/WxPTbGhCjv68ci0UDNomUXagFexLGNpkwa7+CRVtoc/1xgq+ySE +6M4nhcCutScoxNvWNn5eSQ66i3U0sTv91MgsXxqEdTaiZg0BIufEc3dueQIDAQAB +AoGBAIhWkN44L1vORpA7uQsgNfWC/ROQN0T0jPgNKokUY3E+R0F9Ml4xYCp5RNmm +T00B8AhGFCcB1/6zSX/5Uystm5GNO/V8pNnM7qTrTtnwX/umyceIVxq03z4RCVYb +Gdv67opQAy/Mjy+cHBdYBcIg4ihDbr9CX5qedf9buG4140wBAkEA4nKWZX7DEnEh +sbLnU9KhxwEjadzeZb0JKxoWUjfTTrBlIkHbm6toabV6TVqNENWMSCe0fcjJ7tr7 +xPBdOGIlTwJBAOF5ka0khatTH5zSUMRiz8LkqXmy+F0RMXYJeuvNvTSlj3EM9/tK +eWGunHgxv4n1IhGybmfkiXt9MA3sAmUKTbcCQG7nUfM5Zw6EK81c4mCyOxs82nxB +eQZ406GxcBcqUioqyA1EFesiwstq3xA9dfM1szOvhn1INmXuB/qHAhDYOI8CQQCT +zc56ErPxMCdL9O5vHlsVZjHWjkSTNZ8XwnUquI6sQU97i0XQG+zf5Me7XtkxhVjV +AwOu5ThelBz5M1oKhCuXAkEAjDqWQQAiMR2JOFiG/PIHSnPzpmALmf4+A+bjIzbg +VIDhB0LMS5PZikLUWvXPFzdY5e3UKyNTKCxqxqLEYpLWGQ== +-----END RSA PRIVATE KEY----- diff --git a/tests/pki/test_2.crt b/tests/pki/test_2.crt new file mode 100644 index 0000000..609a94b --- /dev/null +++ b/tests/pki/test_2.crt @@ -0,0 +1,14 @@ +-----BEGIN CERTIFICATE----- +MIICHzCCAYgCAQEwDQYJKoZIhvcNAQELBQAwWDELMAkGA1UEBhMCenoxCzAJBgNV +BAgMAnp6MQ0wCwYDVQQHDAR6enp6MQ4wDAYDVQQKDAVaenp6ejEOMAwGA1UECwwF +Wnp6enoxDTALBgNVBAMMBHRlc3QwHhcNMTUwNjAyMDc0MzAxWhcNMjUwNTMwMDc0 +MzAxWjBYMQswCQYDVQQGEwJ6ejELMAkGA1UECAwCenoxDTALBgNVBAcMBHp6enox +DjAMBgNVBAoMBVp6enp6MQ4wDAYDVQQLDAVaenp6ejENMAsGA1UEAwwEdGVzdDCB +nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA41tJCTPuG2lirbztuGbBlzbzSipM +EzM+zluWegUaoUjqtlgNHOTQqTJOqw/GdjkxRKJT6IxI3/HVcnfw7P4a4xSkL/ME +IG3VyzedWEyLIHeofoQSTvr84ZdD0+Gk+zNCSqOQC7UuqpOLbMKK1tgZ8Mr7BkgI +p8H3lreLf29Sd5MCAwEAATANBgkqhkiG9w0BAQsFAAOBgQB0EXxy5+hsB7Rid7Gy +CZrAObpaC4nbyPPW/vccFKmEkYtlygEPgky7D9AGsVSaTc/YxPZcanY+vKoRIsiR +6ZitIUU5b+NnHcdj6289tUQ0iHj5jgVyv8wYHvPntTnqH2S7he0talLER8ITYToh +2wz3u7waz/GypMeA/suhoEfxew== +-----END CERTIFICATE----- diff --git a/tests/pki/test_2.key b/tests/pki/test_2.key new file mode 100644 index 0000000..367a287 --- /dev/null +++ b/tests/pki/test_2.key @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXAIBAAKBgQDjW0kJM+4baWKtvO24ZsGXNvNKKkwTMz7OW5Z6BRqhSOq2WA0c +5NCpMk6rD8Z2OTFEolPojEjf8dVyd/Ds/hrjFKQv8wQgbdXLN51YTIsgd6h+hBJO ++vzhl0PT4aT7M0JKo5ALtS6qk4tsworW2BnwyvsGSAinwfeWt4t/b1J3kwIDAQAB +AoGAGsVz+y5vOjEVmomloFIRN6IT0cbbQGOHYLsuI94X/afdY21I1f8nhtTSqJfp +8Z/YalGG+doS9rO+Q4VWDEH7nkrD32kX7GVHDArixjYNYtO4iOk+XW0lzGr1+ghJ +p9+zguQRwAiUFJE6/pqKvFlwhoKppJGtfUsniQpy7ANfyNkCQQD6arntqjlJsYml +cKgpgbA9rhZl7ebVKf1edd15kp411NH/FDWhIlxvg9c3HcAH3jQgnc4Gf4bdvZ6Z +UVDSa63HAkEA6Gzww5cXgGHqQrJoQW/qVaqBAVakeS5uf0CCyb6xvIcHRPS3lLlu +1upuHeA87IjVeRis8yULgaPzvVyiT/IX1QJBAJvhq/PCLv8swR53TnboACmlINQ6 +j6LKDKqsfD2dg1bHMCG1Ft1DYn8YdvQcVNmQ/KoBEasB35ZQ31VZRRJ3bSkCQEXg +UrYK27buORaaOnvJ4MKmgyha2xHPosrBI1Dx8s+CLO5PQE4HPcqBKl/zBX37WWqR +v5VOAtqT5vh8PBQa7Y0CQGXFzSKBBp+Zmxab2t85qaZ2VNiQLvqsNA9v8YgNTT2j +jYHRzwnAZymfO4JCfKnsT3KiVy1xbcYsNEO9+DYpqBA= +-----END RSA PRIVATE KEY----- diff --git a/tests/pki/test_3.crt b/tests/pki/test_3.crt new file mode 100644 index 0000000..5273869 --- /dev/null +++ b/tests/pki/test_3.crt @@ -0,0 +1,14 @@ +-----BEGIN CERTIFICATE----- +MIICHzCCAYgCAQEwDQYJKoZIhvcNAQELBQAwWDELMAkGA1UEBhMCenoxCzAJBgNV +BAgMAnp6MQ0wCwYDVQQHDAR6enp6MQ4wDAYDVQQKDAVaenp6ejEOMAwGA1UECwwF +Wnp6enoxDTALBgNVBAMMBHRlc3QwHhcNMTUwNjAyMTEyMzQ2WhcNMjUwNTMwMTEy +MzQ2WjBYMQswCQYDVQQGEwJ6ejELMAkGA1UECAwCenoxDTALBgNVBAcMBHp6enox +DjAMBgNVBAoMBVp6enp6MQ4wDAYDVQQLDAVaenp6ejENMAsGA1UEAwwEdGVzdDCB +nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArxklvHr3cJJEHImPJCfsdId/yfhg +kZsbKzhoLTYX10gC9Qz1SbGxUJ4GKQn+IlaMWY4WTle5JUPibDIN5sYtF3GC5JPW +pI/sKeba7ni7JWBOCeAgcgQMGYvuX4VkR2HYuMkKOs/O3d1tAfQdEh8e0I1rXzyS +2TEiV2GECUec1JUCAwEAATANBgkqhkiG9w0BAQsFAAOBgQCbgMfVhmLWasoguB43 +UtIc77T+AZwnxhPKpd8WNx6C03KFK+WoKViZuLR+8i6K/jwJhjiJ8nZzPDIomb4r +hnA/jvOVQKzzgZCr6FBWIVQjDFdIR6MCkGW+JKUVeTQTtsQ7DgL3QjnVDQLL96B7 +ZYA44pe1CSmcdFPmZJyRwFQm/g== +-----END CERTIFICATE----- diff --git a/tests/pki/test_3.key b/tests/pki/test_3.key new file mode 100644 index 0000000..8f37659 --- /dev/null +++ b/tests/pki/test_3.key @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICWwIBAAKBgQCvGSW8evdwkkQciY8kJ+x0h3/J+GCRmxsrOGgtNhfXSAL1DPVJ +sbFQngYpCf4iVoxZjhZOV7klQ+JsMg3mxi0XcYLkk9akj+wp5trueLslYE4J4CBy +BAwZi+5fhWRHYdi4yQo6z87d3W0B9B0SHx7QjWtfPJLZMSJXYYQJR5zUlQIDAQAB +AoGACRxT3FTBnzfdF2cI7aauJPoP6iBkVe8uILeUpBWWc/spPDrqYGVAhqNSSrxc +XskGEHrWKkliNtArbdnE42cYXXPbwxHOwzoXxaHlLYIORDH0b90ukv1Pp6DhzQaW +guFb3yrxRO7tILhfA9V+nvYU4EcPLwRxRzLUipT7eNfIhYECQQDcTMWr3bvgLpD2 +KD8Pn6iihskBiAsvvz1uVOjfSS1bKGzsyYjtKdq/bO0AM0e8uUdSWHXH2yeEkG/f +IMz9CXQlAkEAy3kqpl7uU+0Qe19mC+Icx/DbjJUV6Kv7dLozze3yjBzQFBMPQwi8 +b4zA+4lcuX5u9b8f1kpqC8hNMcE9jGM7sQJAClwp550z2qUV+B2IaamueoYwKbxG +Gma58thXYzjDw0exZ6lKoSyYtuvecWX3964W5o52a4Go6BkKycl3Gmc5aQJAAsT3 +a6RHIiVL4CIARZEiSyZgFp3A2pXcqk4OfnMKphWOT3ei8Yqg5fPIfKP1+yBZakbb +rBL/NoHXayHyMIL5QQJATnVslSzO10RzxBI+k1F+Mr1VRj1KnP4rjYP1gHQ9KqVP +CveP1Cqnu7+tZ9HezUMZSlFZ60A+D6uB8AGB/Z8EHg== +-----END RSA PRIVATE KEY----- diff --git a/tests/server_conf.py b/tests/server_conf.py index bb9de90..b7309e1 100644 --- a/tests/server_conf.py +++ b/tests/server_conf.py @@ -19,6 +19,8 @@ CONFIG = { "debug": 1, "key_file": full_path("test.key"), "cert_file": full_path("test.pem"), + "encryption_keypairs": [{"key_file": "pki/test_1.key", "cert_file": "pki/test_1.crt"}, + {"key_file": "pki/test_2.key", "cert_file": "pki/test_2.crt"}], "ca_certs": full_path("cacerts.txt"), "xmlsec_binary": xmlsec_path, "metadata": [{ diff --git a/tests/test_40_sigver.py b/tests/test_40_sigver.py index fd40cbe..993532b 100644 --- a/tests/test_40_sigver.py +++ b/tests/test_40_sigver.py @@ -25,6 +25,8 @@ SIMPLE_SAML_PHP_RESPONSE = full_path("simplesamlphp_authnresponse.xml") PUB_KEY = full_path("test.pem") PRIV_KEY = full_path("test.key") +ENC_PUB_KEY = full_path("pki/test_1.crt") +ENC_PRIV_KEY = full_path("pki/test.key") def _eq(l1, l2): return set(l1) == set(l2) @@ -96,6 +98,8 @@ class FakeConfig(): metadata = None cert_file = PUB_KEY key_file = PRIV_KEY + encryption_keypairs = [{"key_file": ENC_PRIV_KEY, "cert_file": ENC_PUB_KEY}] + enc_key_files = [ENC_PRIV_KEY] debug = False cert_handler_extra_class = None generate_cert_func = None @@ -503,8 +507,8 @@ def test_xmlsec_err(): if __name__ == "__main__": - # t = TestSecurity() - # t.setup_class() - # t.test_non_verify_2() + t = TestSecurity() + t.setup_class() + t.test_verify_1() - test_xmlsec_err() + #test_xmlsec_err() diff --git a/tests/test_50_server.py b/tests/test_50_server.py index 04a5609..1b57d4b 100644 --- a/tests/test_50_server.py +++ b/tests/test_50_server.py @@ -1,6 +1,7 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- import base64 +import copy import os from contextlib import closing from urlparse import parse_qs @@ -609,7 +610,15 @@ class TestServer1(): id_attr="") assert valid - decr_text = self.server.sec.decrypt(signed_resp, self.client.config.key_file) + decr_text_old = copy.deepcopy("%s" % signed_resp) + + decr_text = self.server.sec.decrypt(signed_resp, self.client.config.encryption_keypairs[0]["key_file"]) + + assert decr_text == decr_text_old + + decr_text = self.server.sec.decrypt(signed_resp, self.client.config.encryption_keypairs[1]["key_file"]) + + assert decr_text != decr_text_old resp = samlp.response_from_string(decr_text) @@ -694,7 +703,7 @@ class TestServer1(): id_attr="") assert valid - decr_text = self.server.sec.decrypt(signed_resp, self.client.config.key_file) + decr_text = self.server.sec.decrypt(signed_resp, self.client.config.encryption_keypairs[1]["key_file"]) resp = samlp.response_from_string(decr_text) @@ -783,7 +792,7 @@ class TestServer1(): assert sresponse.signature is None - decr_text_1 = self.server.sec.decrypt(_resp, self.client.config.key_file) + decr_text_1 = self.server.sec.decrypt(_resp, self.client.config.encryption_keypairs[1]["key_file"]) _, key_file = make_temp("%s" % cert_key_str_advice, decode=False) @@ -846,7 +855,7 @@ class TestServer1(): assert sresponse.signature is None - decr_text = self.server.sec.decrypt(_resp, self.client.config.key_file) + decr_text = self.server.sec.decrypt(_resp, self.client.config.encryption_keypairs[1]["key_file"]) resp = samlp.response_from_string(decr_text) @@ -877,7 +886,7 @@ class TestServer1(): assert sresponse.signature is None - decr_text = self.server.sec.decrypt(_resp, self.client.config.key_file) + decr_text = self.server.sec.decrypt(_resp, self.client.config.encryption_keypairs[1]["key_file"]) resp = samlp.response_from_string(decr_text) @@ -943,9 +952,9 @@ class TestServer1(): assert sresponse.signature is None - decr_text_1 = self.server.sec.decrypt(_resp, self.client.config.key_file) + decr_text_1 = self.server.sec.decrypt(_resp, self.client.config.encryption_keypairs[1]["key_file"]) - decr_text_2 = self.server.sec.decrypt(decr_text_1, self.client.config.key_file) + decr_text_2 = self.server.sec.decrypt(decr_text_1, self.client.config.encryption_keypairs[1]["key_file"]) resp = samlp.response_from_string(decr_text_2) @@ -1270,4 +1279,4 @@ class TestServerLogout(): if __name__ == "__main__": ts = TestServer1() ts.setup_class() - ts.test_encrypted_signed_response_1() + ts.test_encrypted_signed_response_4() diff --git a/tests/test_51_client.py b/tests/test_51_client.py index e69e337..9c108a8 100644 --- a/tests/test_51_client.py +++ b/tests/test_51_client.py @@ -767,7 +767,7 @@ class TestClient: assertion=_ass ) - enctext = _sec.crypto.encrypt_assertion(response, _sec.cert_file, + enctext = _sec.crypto.encrypt_assertion(response, self.client.sec.encryption_keypairs[0]["cert_file"], pre_encryption_part()) seresp = samlp.response_from_string(enctext) @@ -837,7 +837,7 @@ class TestClient: # or as part of a bunch of tests. xmldoc = add_subelement(xmldoc, "EncryptedAssertion", sigass) - enctext = _sec.crypto.encrypt_assertion(xmldoc, _sec.cert_file, + enctext = _sec.crypto.encrypt_assertion(xmldoc, self.client.sec.encryption_keypairs[1]["cert_file"], pre_encryption_part()) #seresp = samlp.response_from_string(enctext) @@ -912,7 +912,7 @@ class TestClient: node_xpath = ''.join(["/*[local-name()=\"%s\"]" % v for v in ["Response", "Assertion", "Advice", "EncryptedAssertion", "Assertion"]]) - enctext = _sec.crypto.encrypt_assertion(response, _sec.cert_file, + enctext = _sec.crypto.encrypt_assertion(response, self.client.sec.encryption_keypairs[0]["cert_file"], pre_encryption_part(), node_xpath=node_xpath) #seresp = samlp.response_from_string(enctext) @@ -1048,7 +1048,7 @@ class TestClient: node_xpath = ''.join(["/*[local-name()=\"%s\"]" % v for v in ["Response", "Assertion", "Advice", "EncryptedAssertion", "Assertion"]]) - enctext = _sec.crypto.encrypt_assertion(response, self.client.sec.cert_file, + enctext = _sec.crypto.encrypt_assertion(response, self.client.sec.encryption_keypairs[1]["cert_file"], pre_encryption_part(), node_xpath=node_xpath) response = samlp.response_from_string(enctext) @@ -1071,7 +1071,7 @@ class TestClient: node_xpath = ''.join(["/*[local-name()=\"%s\"]" % v for v in ["Response", "Assertion", "Advice", "EncryptedAssertion", "Assertion"]]) - enctext = _sec.crypto.encrypt_assertion(response, self.client.sec.cert_file, + enctext = _sec.crypto.encrypt_assertion(response, self.client.sec.encryption_keypairs[0]["cert_file"], pre_encryption_part(), node_xpath=node_xpath) response = samlp.response_from_string(enctext) @@ -1087,7 +1087,8 @@ class TestClient: key_file=self.server.sec.key_file, node_id=assertion_1.id) - enctext = _sec.crypto.encrypt_assertion(response, self.client.sec.cert_file, pre_encryption_part()) + enctext = _sec.crypto.encrypt_assertion(response, self.client.sec.encryption_keypairs[1]["cert_file"], + pre_encryption_part()) response = samlp.response_from_string(enctext) @@ -1098,7 +1099,6 @@ class TestClient: response.assertion.advice.encrypted_assertion = [] response.assertion.advice.encrypted_assertion.append(EncryptedAssertion()) - response.assertion.advice.encrypted_assertion[0].add_extension_element(a_assertion_3) advice_tag = response.assertion.advice._to_element_tree().tag @@ -1114,7 +1114,7 @@ class TestClient: node_xpath = ''.join(["/*[local-name()=\"%s\"]" % v for v in ["Response", "Assertion", "Advice", "EncryptedAssertion", "Assertion"]]) - enctext = _sec.crypto.encrypt_assertion(response, self.client.sec.cert_file, + enctext = _sec.crypto.encrypt_assertion(response, self.client.sec.encryption_keypairs[0]["cert_file"], pre_encryption_part(), node_xpath=node_xpath) response = samlp.response_from_string(enctext) @@ -1138,7 +1138,7 @@ class TestClient: node_xpath = ''.join(["/*[local-name()=\"%s\"]" % v for v in ["Response", "Assertion", "Advice", "EncryptedAssertion", "Assertion"]]) - enctext = _sec.crypto.encrypt_assertion(response, self.client.sec.cert_file, + enctext = _sec.crypto.encrypt_assertion(response, self.client.sec.encryption_keypairs[1]["cert_file"], pre_encryption_part(), node_xpath=node_xpath) response = samlp.response_from_string(enctext) @@ -1349,4 +1349,4 @@ class TestClientWithDummy(): if __name__ == "__main__": tc = TestClient() tc.setup_class() - tc.test_response_8() + tc.test_sign_then_encrypt_assertion()