diff --git a/src/saml2/config.py b/src/saml2/config.py index 9d35a0a..43414f7 100644 --- a/src/saml2/config.py +++ b/src/saml2/config.py @@ -18,7 +18,6 @@ from saml2 import BINDING_HTTP_ARTIFACT from saml2.attribute_converter import ac_factory from saml2.assertion import Policy -from saml2.sigver import get_xmlsec_binary from saml2.mdstore import MetadataStore from saml2.virtual_org import VirtualOrg @@ -191,6 +190,7 @@ class Config(object): self.domain = "" self.name_qualifier = "" self.entity_category = "" + self.crypto_backend = 'xmlsec1' def setattr(self, context, attr, val): if context == "": @@ -303,16 +303,6 @@ class Config(object): except KeyError: pass - if not metadata_construction: - if not self.xmlsec_binary: - self.xmlsec_binary = get_xmlsec_binary() - - # verify that xmlsec is where it's supposed to be - if not os.path.exists(self.xmlsec_binary): - #if not os.access(, os.F_OK): - raise Exception( - "xmlsec binary not in '%s' !" % self.xmlsec_binary) - self.load_complex(cnf, metadata_construction=metadata_construction) self.context = self.def_context diff --git a/src/saml2/ecp_client.py b/src/saml2/ecp_client.py index 7a6253c..b092f89 100644 --- a/src/saml2/ecp_client.py +++ b/src/saml2/ecp_client.py @@ -48,28 +48,33 @@ class Client(Entity): def __init__(self, user, passwd, sp="", idp=None, metadata_file=None, xmlsec_binary=None, verbose=0, ca_certs="", disable_ssl_certificate_validation=True, key_file=None, - cert_file=None): + cert_file=None, config=None): """ :param user: user name :param passwd: user password :param sp: The SP URL :param idp: The IdP PAOS endpoint :param metadata_file: Where the metadata file is if used - :param xmlsec_binary: Where the xmlsec1 binary can be found + :param xmlsec_binary: Where the xmlsec1 binary can be found (*) :param verbose: Chatty or not :param ca_certs: is the path of a file containing root CA certificates - for SSL server certificate validation. + for SSL server certificate validation (*) :param disable_ssl_certificate_validation: If disable_ssl_certificate_validation is true, SSL cert validation - will not be performed. + will not be performed (*) + :param key_file: Private key filename (*) + :param cert_file: Certificate filename (*) + :param config: Config() instance, overrides all the parameters marked + with an asterisk (*) above """ - config = Config() - config.disable_ssl_certificate_validation = \ - disable_ssl_certificate_validation - config.key_file = key_file - config.cert_file = cert_file - config.ca_certs = ca_certs - config.xmlsec_binary = xmlsec_binary + if not config: + config = Config() + config.disable_ssl_certificate_validation = \ + disable_ssl_certificate_validation + config.key_file = key_file + config.cert_file = cert_file + config.ca_certs = ca_certs + config.xmlsec_binary = xmlsec_binary Entity.__init__(self, "sp", config) self._idp = idp diff --git a/src/saml2/encdec.py b/src/saml2/encdec.py deleted file mode 100644 index 24d5dbf..0000000 --- a/src/saml2/encdec.py +++ /dev/null @@ -1,271 +0,0 @@ -import logging -import os -import sys - -from subprocess import Popen -from subprocess import PIPE - -from tempfile import NamedTemporaryFile - -from saml2.sigver import make_temp -from saml2.sigver import parse_xmlsec_output -from saml2.sigver import XmlsecError -from saml2 import saml - -__author__ = 'rohe0002' - -import xmlenc as enc - -logger = logging.getLogger(__name__) - -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# - -class DecryptionError(Exception): - pass - -ID_ATTR = "ID" -#NODE_NAME = "urn:oasis:names:tc:SAML:2.0:assertion:Assertion" -ENC_DATA = "urn:oasis:names:tc:SAML:2.0:assertion:EncryptedData" -ENC_KEY_CLASS = "EncryptedKey" - -RSA_15 = "http://www.w3.org/2001/04/xmlenc#rsa-1_5" -RSA_OAEP = "http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p" -AES128_CBC="http://www.w3.org/2001/04/xmlenc#aes128-cbc" -TRIPLE_DES = "http://www.w3.org/2001/04/xmlenc#tripledes-cbc" - -LOG_LINE = 60*"="+"\n%s\n"+60*"-"+"\n%s"+60*"=" -LOG_LINE_2 = 60*"="+"\n%s\n%s\n"+60*"-"+"\n%s"+60*"=" - -# registered xmlsec transforms -TRANSFORMS = ["base64","enveloped-signature","c14n","c14n-with-comments", - "c14n11","c14n11-with-comments","exc-c14n", - "exc-c14n-with-comments","xpath","xpath2","xpointer","xslt", - "aes128-cbc","aes192-cbc","aes256-cbc","kw-aes128","kw-aes192", - "kw-aes256","tripledes-cbc","kw-tripledes","dsa-sha1","hmac-md5", - "hmac-ripemd160","hmac-sha1","hmac-sha224","hmac-sha256", - "hmac-sha384","hmac-sha512","md5","ripemd160","rsa-md5", - "rsa-ripemd160","rsa-sha1","rsa-sha224","rsa-sha256","rsa-sha384", - "rsa-sha512","rsa-1_5","rsa-oaep-mgf1p","sha1","sha224","sha256", - "sha384","sha512"] - -ALGORITHM = { - "tripledes-cbc": TRIPLE_DES, - "aes128-cbc": AES128_CBC, - "rsa-1_5": RSA_15, - "rsa-oaep-mgf1p": RSA_OAEP -} - -def template(ident=None, session_key="tripledes-cbc"): - """ - If an assertion is to be signed the signature part has to be preset - with which algorithms to be used, this function returns such a - preset part. - - :param ident: The identifier of the assertion, so you know which assertion - was signed - :return: A preset signature part - """ - - cipher_data = enc.CipherData(cipher_value=enc.CipherValue()) - encryption_method = enc.EncryptionMethod(algorithm=ALGORITHM[session_key]) - #key_info = ds.KeyInfo(key_name=ds.KeyName()) - encrypted_data = enc.EncryptedData( - type = "http://www.w3.org/2001/04/xmlenc#Element", - encryption_method=encryption_method, - #key_info=key_info, - cipher_data=cipher_data) - - if ident: - encrypted_data.id = "%s" % ident - - return encrypted_data - -# xmlsec decrypt --privkey-pem userkey.pem doc-encrypted.xml - -def decrypt_message(enctext, xmlsec_binary, key_file=None, - key_file_type="privkey-pem", cafile=None, - epath=None, id_attr="", - node_name="", node_id=None, debug=False): - """ Decrypts an encrypted part of a XML document. - - :param enctext: XML document containing an encrypted part - :param xmlsec_binary: The xmlsec1 binaries to be used - :param key_file: The key used to decrypt the message - :param key_file_type: The key file type - :param node_name: The SAML class of the root node in the message - :param node_id: The identifier of the root node if any - :param id_attr: Should normally be one of "id", "Id" or "ID" - :param debug: To debug or not - :return: The decrypted document if all was OK otherwise will raise an - exception. - """ - - if not id_attr: - id_attr = ID_ATTR - - _, fil = make_temp(enctext, decode=False) - - com_list = [xmlsec_binary, "--decrypt", - "--%s" % key_file_type, key_file] - - if key_file_type in ["privkey-pem", "privkey-der", "pkcs8-pem", - "pkcs8-der"]: - if isinstance(cafile, basestring): - com_list.append(cafile) - else: - com_list.extend(cafile) - - if id_attr: - com_list.extend(["--id-attr:%s" % id_attr, node_name]) - - elif epath: - xpath = create_xpath(epath) - com_list.extend(['--node-xpath', xpath]) - - # if debug: -# com_list.append("--store-signatures") - - if node_id: - com_list.extend(["--node-id", node_id]) - - com_list.append(fil) - - if debug: - try: - print " ".join(com_list) - except TypeError: - print "key_file_type", key_file_type - print "key_file", key_file - print "node_name", node_name - print "fil", fil - raise - print "%s: %s" % (key_file, os.access(key_file, os.F_OK)) - print "%s: %s" % (fil, os.access(fil, os.F_OK)) - - pof = Popen(com_list, stderr=PIPE, stdout=PIPE) - p_out = pof.stdout.read() - try: - p_err = pof.stderr.read() - if debug: - print p_err - verified = parse_xmlsec_output(p_err) - except XmlsecError, exc: - logger(LOG_LINE % (p_out, exc)) - raise DecryptionError("%s" % (exc,)) - - return verified - -# Whole document -#xmlsec1 encrypt --pubkey-pem ServerKeys/pubkey.pem --session-key des-192 -# --xml-data ClientRequest.xml -# --output ClientEncrypted.xml EncryptionTemplate.xml - -# single value -#/opt/local/bin/xmlsec1 encrypt --pubkey-cert-pem pubkey.pem -# --session-key des-192 --xml-data pre_saml2_response.xml -# --node-xpath '/*[local-name()="Response"]/*[local-name()="Assertion"]/*[local-name()="Subject"]/*[local-name()="EncryptedID"]/text()' -# encryption_template.xml > enc.out - -def create_xpath(path): - """ - :param path: list of element names - """ - - return "/*".join(['[local-name()="%s"]' % e for e in path]) + "/text()" - -def encrypt_using_xmlsec(xmlsec, data, template, epath=None, key=None, - key_file=None, key_file_type="pubkey-pem", - session_key=None): - """encrypting a value using xmlsec. - - :param xmlsec: Path to the xmlsec1 binary - :param data: A XML document from which the value should be picked. - :param template: The encyption part template - :param epath: Which value to encrypt, if not the whole document - should be encrypted. - :param key: The key to be used for the encrypting, either this or - :param key_file: The file where the key can be found - :param key_file_type: pubkey-pem, pubkey-der, pubkey-cert-pem, - pubkey-cert-der, privkey-der, privkey-pem, ... - :param session_key: Key algorithm - :return: The signed statement - """ - - if not key_file and key: - _, key_file = make_temp("%s" % key, ".pem") - - ntf = NamedTemporaryFile() - xpath = create_xpath(epath) - - com_list = [xmlsec, "encrypt", - "--output", ntf.name, - "--xml-data", data, - '--node-xpath', xpath, - key_file_type, key_file - ] - - if session_key: - com_list.extend(["--session-key", session_key]) - - _, fil = make_temp("%s" % template, decode=False) - com_list.append(fil) - - pof = Popen(com_list, stderr=PIPE, stdout=PIPE) - p_out = pof.stdout.read() - p_err = pof.stderr.read() - - # this doesn't work if --store-signatures are used - if p_out == "": - ntf.seek(0) - encrypted_statement = ntf.read() - if not encrypted_statement: - logger.error(p_err) - raise Exception("Encryption failed") - else: - return encrypted_statement - else: - logger.error(LOG_LINE % (p_out, p_err)) - raise Exception("Encryption failed") - -def encrypt_id(response, xmlsec, key_file, key_file_type, identifier, - session_key, node_id=""): - """ - :param response: The response as a Response class instance - :param xmlsec: Where the xmlsec1 binaries reside - :param key_file: Which key file to use - :param key_file_type: The type of key file - :param identifier: The subject identifier - :param session_key: The type of key used to encrypt - :return: statement with the subject identifier encrypted - """ - if not response.assertion[0].subject.encrypted_id: - response.assertion[0].subject.encrypted_id = saml.EncryptedID( - identifier) - - statement = encrypt_using_xmlsec(xmlsec, "%s" % response, - template=template(ident=node_id, - session_key=session_key), - epath=["Response","Assertion","Subject","NameID"], - key_file=key_file, - key_file_type=key_file_type, - session_key=session_key) - - return statement diff --git a/src/saml2/sigver.py b/src/saml2/sigver.py index c0b6063..029e250 100644 --- a/src/saml2/sigver.py +++ b/src/saml2/sigver.py @@ -72,7 +72,7 @@ def signed(item): return False -def get_xmlsec_binary(paths=None): +def _get_xmlsec_binary(paths=None): """ Tries to find the xmlsec1 binary. @@ -107,18 +107,17 @@ def get_xmlsec_binary(paths=None): raise Exception("Can't find %s" % bin_name) +def _get_xmlsec_cryptobackend(path=None, search_paths=None, debug=False): + """ + Initialize a CryptoBackendXmlSec1 crypto backend. -def get_xmlsec_cryptobackend(path=None, search_paths=None, debug=False): + This function is now internal to this module. + """ if path is None: - path=get_xmlsec_binary(paths=search_paths) + path=_get_xmlsec_binary(paths=search_paths) return CryptoBackendXmlSec1(path, debug=debug) -try: - XMLSEC_BINARY = get_xmlsec_binary() -except Exception: - XMLSEC_BINARY = "" - ID_ATTR = "ID" NODE_NAME = "urn:oasis:names:tc:SAML:2.0:assertion:Assertion" ENC_NODE_NAME = "urn:oasis:names:tc:SAML:2.0:assertion:EncryptedAssertion" @@ -145,14 +144,6 @@ class DecryptError(Exception): # -------------------------------------------------------------------------- -def xmlsec_version(execname): - com_list = [execname, "--version"] - pof = Popen(com_list, stderr=PIPE, stdout=PIPE) - try: - return pof.stdout.read().split(" ")[1] - except Exception: - return "" - def _make_vals(val, klass, seccont, klass_inst=None, prop=None, part=False, base64encode=False, elements_to_sign=None): @@ -601,6 +592,9 @@ class CryptoBackend(): def __init__(self, debug=False): self.debug = debug + def version(self): + raise NotImplementedError() + def encrypt(self, text, recv_key, template, key_type): raise NotImplementedError() @@ -629,6 +623,14 @@ class CryptoBackendXmlSec1(CryptoBackend): assert(isinstance(xmlsec_binary, basestring)) self.xmlsec = xmlsec_binary + def version(self): + com_list = [self.xmlsec, "--version"] + pof = Popen(com_list, stderr=PIPE, stdout=PIPE) + try: + return pof.stdout.read().split(" ")[1] + except Exception: + return "" + def encrypt(self, text, recv_key, template, key_type): logger.info("Encryption input len: %d" % len(text)) _, fil = make_temp("%s" % text, decode=False) @@ -782,6 +784,11 @@ class CryptoBackendXMLSecurity(CryptoBackend): CryptoBackend.__init__(self) self.debug = debug + def version(): + # XXX if XMLSecurity.__init__ included a __version__, that would be + # better than static 0.0 here. + return "XMLSecurity 0.0" + def sign_statement(self, statement, _class_name, key_file, _nodeid, _id_attr): """ @@ -842,10 +849,22 @@ def security_context(conf, debug=None): if _only_md is None: _only_md = False - crypto = get_xmlsec_cryptobackend(conf.xmlsec_binary, debug=debug) - # Uncomment this to enable the new and somewhat untested pyXMLSecurity - # crypto backend. - #crypto = CryptoBackendXMLSecurity(debug=debug) + if conf.crypto_backend == 'xmlsec1': + xmlsec_binary = conf.xmlsec_binary + if not xmlsec_binary: + xmlsec_binary = _get_xmlsec_binary() + # verify that xmlsec is where it's supposed to be + if not os.path.exists(xmlsec_binary): + #if not os.access(, os.F_OK): + raise Exception( + "xmlsec binary not in '%s' !" % xmlsec_binary) + crypto = _get_xmlsec_cryptobackend(xmlsec_binary, debug=debug) + elif conf.crypto_backend == 'XMLSecurity': + # new and somewhat untested pyXMLSecurity crypto backend. + crypto = CryptoBackendXMLSecurity(debug=debug) + else: + raise Exception('Unknown crypto_backend %s' % ( + repr(conf.crypto_backend))) return SecurityContext(crypto, conf.key_file, cert_file=conf.cert_file, metadata=metadata, diff --git a/tests/aa_conf.py b/tests/aa_conf.py index faa26a7..fbeaff1 100644 --- a/tests/aa_conf.py +++ b/tests/aa_conf.py @@ -2,7 +2,7 @@ from saml2 import BINDING_SOAP, BINDING_HTTP_REDIRECT, NAME_FORMAT_URI BASE = "http://localhost:8089/" -from pathutils import full_path, xmlsec_path +from pathutils import full_path CONFIG={ @@ -27,7 +27,7 @@ CONFIG={ "debug" : 1, "key_file" : full_path("test.key"), "cert_file" : full_path("test.pem"), - #"xmlsec_binary" : xmlsec_path, + #"xmlsec_binary" : None, "metadata": { "local": [full_path("metadata.xml"), full_path("vo_metadata.xml")], }, diff --git a/tests/disco_conf.py b/tests/disco_conf.py index 1b9417f..1f7554d 100644 --- a/tests/disco_conf.py +++ b/tests/disco_conf.py @@ -1,6 +1,6 @@ from saml2.extension.idpdisc import BINDING_DISCO -from pathutils import full_path, xmlsec_path +from pathutils import full_path BASE = "http://localhost:8088" @@ -17,7 +17,7 @@ CONFIG = { }, }, "debug" : 1, - "xmlsec_binary" : xmlsec_path, + "xmlsec_binary" : None, "metadata": { "local": [full_path("servera.xml")], }, diff --git a/tests/idp_all_conf.py b/tests/idp_all_conf.py index 1fc072b..860b8b1 100644 --- a/tests/idp_all_conf.py +++ b/tests/idp_all_conf.py @@ -7,7 +7,7 @@ from saml2 import BINDING_HTTP_ARTIFACT from saml2.saml import NAMEID_FORMAT_PERSISTENT from saml2.saml import NAME_FORMAT_URI -from pathutils import full_path, xmlsec_path +from pathutils import full_path BASE = "http://localhost:8088" @@ -85,7 +85,7 @@ CONFIG = { "debug" : 1, "key_file" : full_path("test.key"), "cert_file" : full_path("test.pem"), - "xmlsec_binary" : xmlsec_path, + "xmlsec_binary" : None, "metadata": { "local": [full_path("servera.xml"), full_path("vo_metadata.xml")], diff --git a/tests/idp_conf.py b/tests/idp_conf.py index a60d6e9..cc205b3 100644 --- a/tests/idp_conf.py +++ b/tests/idp_conf.py @@ -2,7 +2,7 @@ from saml2 import BINDING_SOAP, BINDING_HTTP_REDIRECT, BINDING_HTTP_POST from saml2.saml import NAMEID_FORMAT_PERSISTENT from saml2.saml import NAME_FORMAT_URI -from pathutils import full_path, xmlsec_path +from pathutils import full_path BASE = "http://localhost:8088" @@ -41,7 +41,7 @@ CONFIG = { "debug": 1, "key_file": full_path("test.key"), "cert_file": full_path("test.pem"), - "xmlsec_binary": xmlsec_path, + "xmlsec_binary": None, "metadata": { "local": [full_path("metadata_sp_1.xml"), full_path("vo_metadata.xml")], diff --git a/tests/idp_conf_mdb.py b/tests/idp_conf_mdb.py index f997263..847c50a 100644 --- a/tests/idp_conf_mdb.py +++ b/tests/idp_conf_mdb.py @@ -7,7 +7,7 @@ from saml2 import BINDING_HTTP_ARTIFACT from saml2.saml import NAMEID_FORMAT_PERSISTENT from saml2.saml import NAME_FORMAT_URI -from pathutils import full_path, xmlsec_path +from pathutils import full_path BASE = "http://localhost:8088" @@ -86,7 +86,7 @@ CONFIG = { "debug": 1, "key_file": full_path("test.key"), "cert_file": full_path("test.pem"), - "xmlsec_binary": xmlsec_path, + "xmlsec_binary": None, "metadata": { "local": [full_path("servera.xml"), full_path("vo_metadata.xml")], diff --git a/tests/idp_conf_mdb2.py b/tests/idp_conf_mdb2.py index edd86c5..ede0d5d 100644 --- a/tests/idp_conf_mdb2.py +++ b/tests/idp_conf_mdb2.py @@ -7,7 +7,7 @@ from saml2 import BINDING_HTTP_ARTIFACT from saml2.saml import NAMEID_FORMAT_PERSISTENT from saml2.saml import NAME_FORMAT_URI -from pathutils import full_path, xmlsec_path +from pathutils import full_path BASE = "http://localhost:8089" @@ -86,7 +86,7 @@ CONFIG = { "debug": 1, "key_file": full_path("test.key"), "cert_file": full_path("test.pem"), - "xmlsec_binary": xmlsec_path, + "xmlsec_binary": None, "metadata": { "local": [full_path("servera.xml"), full_path("vo_metadata.xml")], diff --git a/tests/idp_slo_redirect_conf.py b/tests/idp_slo_redirect_conf.py index c38eb44..530f0fe 100644 --- a/tests/idp_slo_redirect_conf.py +++ b/tests/idp_slo_redirect_conf.py @@ -2,7 +2,7 @@ from saml2 import BINDING_HTTP_REDIRECT from saml2.saml import NAMEID_FORMAT_PERSISTENT from saml2.saml import NAME_FORMAT_URI -from pathutils import full_path, xmlsec_path +from pathutils import full_path CONFIG = { "entityid" : "urn:mace:example.com:saml:roland:idp", @@ -32,7 +32,7 @@ CONFIG = { "debug" : 1, "key_file" : full_path("test.key"), "cert_file" : full_path("test.pem"), - "xmlsec_binary" : xmlsec_path, + "xmlsec_binary" : None, "metadata": { "local": [full_path("sp_slo_redirect.xml")], }, diff --git a/tests/idp_soap_conf.py b/tests/idp_soap_conf.py index 580d95f..110bccd 100644 --- a/tests/idp_soap_conf.py +++ b/tests/idp_soap_conf.py @@ -36,7 +36,7 @@ CONFIG={ "debug" : 1, "key_file" : full_path("test.key"), "cert_file" : full_path("test.pem"), - #"xmlsec_binary" : xmlsec_path, + #"xmlsec_binary" : None, "metadata": { "local": [full_path("metadata.xml"), full_path("vo_metadata.xml")], }, diff --git a/tests/idp_sp_conf.py b/tests/idp_sp_conf.py index e4da5e6..2f7a7b5 100644 --- a/tests/idp_sp_conf.py +++ b/tests/idp_sp_conf.py @@ -6,7 +6,7 @@ from saml2.saml import NAME_FORMAT_URI BASE = "http://localhost:8088/" -from pathutils import full_path, xmlsec_path +from pathutils import full_path CONFIG = { "entityid" : "urn:mace:example.com:saml:roland:idp", @@ -49,7 +49,7 @@ CONFIG = { "debug" : 1, "key_file" : full_path("test.key"), "cert_file" : full_path("test.pem"), - "xmlsec_binary" : xmlsec_path, + "xmlsec_binary" : None, "metadata": { "local": [full_path("metadata.xml"), full_path("vo_metadata.xml")], }, diff --git a/tests/pathutils.py b/tests/pathutils.py index cae0ef7..a651060 100644 --- a/tests/pathutils.py +++ b/tests/pathutils.py @@ -12,15 +12,3 @@ def dotname(module): return 'tests.' + module else: return module - - -try: - from saml2.sigver import get_xmlsec_binary -except ImportError: - get_xmlsec_binary = None - - -if get_xmlsec_binary: - xmlsec_path = get_xmlsec_binary(["/opt/local/bin"]) -else: - xmlsec_path = '/usr/bin/xmlsec1' diff --git a/tests/restrictive_idp_conf.py b/tests/restrictive_idp_conf.py index c12e1ce..468c978 100644 --- a/tests/restrictive_idp_conf.py +++ b/tests/restrictive_idp_conf.py @@ -3,7 +3,7 @@ from saml2.saml import NAME_FORMAT_URI BASE = "http://localhost:8089/" -from pathutils import full_path, xmlsec_path +from pathutils import full_path CONFIG = { "entityid" : "urn:mace:example.com:saml:roland:idpr", @@ -36,7 +36,7 @@ CONFIG = { }, "key_file" : full_path("test.key"), "cert_file" : full_path("test.pem"), - "xmlsec_binary" : xmlsec_path, + "xmlsec_binary" : None, "metadata": { "local": [full_path("sp_0.metadata")], }, diff --git a/tests/server2_conf.py b/tests/server2_conf.py index 47de834..bd098db 100644 --- a/tests/server2_conf.py +++ b/tests/server2_conf.py @@ -1,4 +1,4 @@ -from pathutils import full_path, xmlsec_path +from pathutils import full_path CONFIG = { "entityid" : "urn:mace:example.com:saml:roland:sp", @@ -18,7 +18,7 @@ CONFIG = { "debug" : 1, "key_file" : full_path("test.key"), "cert_file" : full_path("test.pem"), - "xmlsec_binary" : xmlsec_path, + "xmlsec_binary" : None, "metadata": { "local": [full_path("idp_soap.xml"), full_path("vo_metadata.xml")], }, diff --git a/tests/server3_conf.py b/tests/server3_conf.py index 1da1b23..764fec4 100644 --- a/tests/server3_conf.py +++ b/tests/server3_conf.py @@ -1,4 +1,4 @@ -from pathutils import full_path, xmlsec_path +from pathutils import full_path CONFIG = { "entityid" : "urn:mace:example.com:saml:roland:sp", @@ -18,7 +18,7 @@ CONFIG = { "debug" : 1, "key_file" : full_path("test.key"), "cert_file" : full_path("test.pem"), - "xmlsec_binary" : xmlsec_path, + "xmlsec_binary" : None, "metadata": { "local": [full_path("idp_aa.xml"), full_path("vo_metadata.xml")], }, diff --git a/tests/server_conf.py b/tests/server_conf.py index c571a1d..1430912 100644 --- a/tests/server_conf.py +++ b/tests/server_conf.py @@ -1,4 +1,4 @@ -from pathutils import full_path, xmlsec_path +from pathutils import full_path CONFIG={ "entityid" : "urn:mace:example.com:saml:roland:sp", @@ -19,7 +19,7 @@ CONFIG={ "key_file": full_path("test.key"), "cert_file": full_path("test.pem"), "ca_certs": full_path("cacerts.txt"), - "xmlsec_binary": xmlsec_path, + "xmlsec_binary": None, "metadata": { "local": [full_path("idp.xml"), full_path("vo_metadata.xml")], }, diff --git a/tests/server_conf_syslog.py b/tests/server_conf_syslog.py index e76b528..72e6a74 100644 --- a/tests/server_conf_syslog.py +++ b/tests/server_conf_syslog.py @@ -20,7 +20,7 @@ CONFIG={ "debug" : 1, "key_file" : full_path("test.key"), "cert_file" : full_path("test.pem"), - #"xmlsec_binary" : xmlsec_path, + #"xmlsec_binary" : None, "metadata": { "local": [full_path("idp.xml"), full_path("vo_metadata.xml")], }, diff --git a/tests/servera_conf.py b/tests/servera_conf.py index 7aec90d..dbec3fc 100644 --- a/tests/servera_conf.py +++ b/tests/servera_conf.py @@ -7,7 +7,7 @@ from saml2 import BINDING_HTTP_ARTIFACT from saml2.saml import NAMEID_FORMAT_TRANSIENT from saml2.saml import NAMEID_FORMAT_PERSISTENT -from pathutils import full_path, xmlsec_path +from pathutils import full_path BASE = "http://lingon.catalogix.se:8087" @@ -49,7 +49,7 @@ CONFIG = { "key_file": full_path("test.key"), "cert_file": full_path("test.pem"), "ca_certs": full_path("cacerts.txt"), - "xmlsec_binary": xmlsec_path, + "xmlsec_binary" : None, "metadata": { "local": [full_path("idp_all.xml"), full_path("vo_metadata.xml")], }, diff --git a/tests/sp_1_conf.py b/tests/sp_1_conf.py index aee542c..e39be48 100644 --- a/tests/sp_1_conf.py +++ b/tests/sp_1_conf.py @@ -1,4 +1,4 @@ -from pathutils import full_path, xmlsec_path +from pathutils import full_path CONFIG = { @@ -18,7 +18,7 @@ CONFIG = { "debug" : 1, "key_file" : full_path("test.key"), "cert_file" : full_path("test.pem"), - "xmlsec_binary" : xmlsec_path, + "xmlsec_binary" : None, "metadata": { "local": [full_path("idp.xml"), full_path("vo_metadata.xml")], }, diff --git a/tests/sp_2_conf.py b/tests/sp_2_conf.py index a8023bd..b07f0f2 100644 --- a/tests/sp_2_conf.py +++ b/tests/sp_2_conf.py @@ -1,4 +1,4 @@ -from pathutils import full_path, xmlsec_path +from pathutils import full_path CONFIG = { "entityid" : "urn:mace:example.com:saml:roland:sp", @@ -17,7 +17,7 @@ CONFIG = { "debug" : 1, "key_file" : full_path("test.key"), "cert_file" : full_path("test.pem"), - "xmlsec_binary" : xmlsec_path, + "xmlsec_binary" : None, "metadata": { "local": [full_path("idp_2.xml")], }, diff --git a/tests/sp_slo_redirect_conf.py b/tests/sp_slo_redirect_conf.py index 912653e..7856c11 100644 --- a/tests/sp_slo_redirect_conf.py +++ b/tests/sp_slo_redirect_conf.py @@ -2,7 +2,7 @@ from saml2 import BINDING_HTTP_REDIRECT from saml2.saml import NAMEID_FORMAT_PERSISTENT from saml2.saml import NAME_FORMAT_URI -from pathutils import full_path, xmlsec_path +from pathutils import full_path HOME = "http://lingon.catalogix.se:8087/" CONFIG = { @@ -26,7 +26,7 @@ CONFIG = { "debug" : 1, "key_file" : full_path("test.key"), "cert_file" : full_path("test.pem"), - "xmlsec_binary" : xmlsec_path, + "xmlsec_binary" : None, "metadata": { "local": [full_path("idp_slo_redirect.xml")], }, diff --git a/tests/test_40_sigver.py b/tests/test_40_sigver.py index 8ad8b2e..a5a9905 100644 --- a/tests/test_40_sigver.py +++ b/tests/test_40_sigver.py @@ -11,7 +11,6 @@ from saml2 import time_util from saml2 import saml, samlp from saml2 import config from saml2.s_utils import factory, do_attribute_statement -from saml2.sigver import xmlsec_version, get_xmlsec_cryptobackend, get_xmlsec_binary from py.test import raises @@ -84,12 +83,33 @@ def test_cert_from_instance_ssp(): print str(decoder.decode(der)).replace('.', "\n.") assert decoder.decode(der) +class FakeConfig(): + """ + Configuration parameters for signature validation test cases. + """ + xmlsec_binary = None + crypto_backend = 'xmlsec1' + only_use_keys_in_metadata = False + metadata = None + cert_file = PUB_KEY + key_file = PRIV_KEY + debug = False class TestSecurity(): + def setup_class(self): - crypto = get_xmlsec_cryptobackend() - self.sec = sigver.SecurityContext(crypto, key_file=PRIV_KEY, - cert_file=PUB_KEY, debug=1) + # This would be one way to initialize the security context : + # + # conf = config.SPConfig() + # conf.load_file("server_conf") + # conf.only_use_keys_in_metadata = False + # + # but instead, FakeConfig() is used to really only use the minimal + # set of parameters needed for these test cases. Other test cases + # (TestSecurityMetadata below) excersise the SPConfig() mechanism. + # + conf = FakeConfig() + self.sec = sigver.security_context(FakeConfig()) self._assertion = factory( saml.Assertion, @@ -122,8 +142,7 @@ class TestSecurity(): def test_sign_assertion(self): ass = self._assertion print ass - sign_ass = self.sec.sign_assertion_using_xmlsec("%s" % ass, - node_id=ass.id) + sign_ass = self.sec.sign_assertion("%s" % ass, node_id=ass.id) #print sign_ass sass = saml.assertion_from_string(sign_ass) #print sass @@ -133,7 +152,7 @@ class TestSecurity(): assert sass.id == "11111" assert time_util.str_to_time(sass.issue_instant) - print xmlsec_version(get_xmlsec_binary()) + print "Crypto version : %s" % (self.sec.crypto.version()) item = self.sec.check_signature(sass, class_name(sass), sign_ass) @@ -153,7 +172,7 @@ class TestSecurity(): assert sass.id == "11111" assert time_util.str_to_time(sass.issue_instant) - print xmlsec_version(get_xmlsec_binary()) + print "Crypto version : %s" % (self.sec.crypto.version()) item = self.sec.check_signature(sass, class_name(sass), sign_ass, must=True) @@ -366,9 +385,9 @@ class TestSecurityMetadata(): md = MetadataStore([saml, samlp], None, conf) md.load("local", full_path("metadata_cert.xml")) - crypto = get_xmlsec_cryptobackend() - self.sec = sigver.SecurityContext(crypto, key_file=PRIV_KEY, - cert_file=PUB_KEY, debug=1, metadata=md) + conf.metadata = md + conf.only_use_keys_in_metadata = False + self.sec = sigver.security_context(conf) self._assertion = factory( saml.Assertion, version="2.0", @@ -384,8 +403,7 @@ class TestSecurityMetadata(): def test_sign_assertion(self): ass = self._assertion print ass - sign_ass = self.sec.sign_assertion_using_xmlsec("%s" % ass, - node_id=ass.id) + sign_ass = self.sec.sign_assertion("%s" % ass, node_id=ass.id) #print sign_ass sass = saml.assertion_from_string(sign_ass) #print sass @@ -395,7 +413,7 @@ class TestSecurityMetadata(): assert sass.id == "11111" assert time_util.str_to_time(sass.issue_instant) - print xmlsec_version(get_xmlsec_binary()) + print "Crypto version : %s" % (self.sec.crypto.version()) item = self.sec.check_signature(sass, class_name(sass), sign_ass) diff --git a/tests/test_63_ecp.py b/tests/test_63_ecp.py index b423e52..41f2e93 100644 --- a/tests/test_63_ecp.py +++ b/tests/test_63_ecp.py @@ -14,7 +14,7 @@ from saml2 import create_class_from_xml_string from saml2.profile import ecp as ecp_prof from saml2.client import Saml2Client -from pathutils import dotname, full_path, xmlsec_path +from pathutils import dotname, full_path __author__ = 'rolandh' @@ -38,8 +38,7 @@ class DummyResponse(object): def test_complete_flow(): client = ecp_client.Client("user", "password", - metadata_file=full_path("idp_all.xml"), - xmlsec_binary=xmlsec_path) + metadata_file=full_path("idp_all.xml")) sp = Saml2Client(config_file=dotname("servera_conf")) idp = Server(config_file=dotname("idp_all_conf")) diff --git a/tools/make_metadata.py b/tools/make_metadata.py index 1eaaca0..23ea95b 100755 --- a/tools/make_metadata.py +++ b/tools/make_metadata.py @@ -1,14 +1,12 @@ #!/usr/bin/env python import argparse -import os +import os import sys from saml2.metadata import entity_descriptor from saml2.metadata import entities_descriptor from saml2.metadata import sign_entity_descriptor -from saml2.sigver import SecurityContext, CryptoBackendXmlSec1 -from saml2.sigver import get_xmlsec_cryptobackend -from saml2.sigver import get_xmlsec_binary +from saml2.sigver import security_context from saml2.validate import valid_instance from saml2.config import Config @@ -46,10 +44,7 @@ paths = [".", "/opt/local/bin"] if args.valid: # translate into hours valid_for = int(args.valid) * 24 -if args.xmlsec: - xmlsec = args.xmlsec -else: - xmlsec = get_xmlsec_binary(paths) + eds = [] for filespec in args.config: @@ -61,13 +56,12 @@ for filespec in args.config: cnf = Config().load_file(fil, metadata_construction=True) eds.append(entity_descriptor(cnf)) -if not xmlsec: - crypto = get_xmlsec_cryptobackend() -else: - crypto = CryptoBackendXmlSec1(xmlsec) - -secc = SecurityContext(crypto, key_file=args.keyfile, cert_file=args.cert, - debug=1) +conf = Config() +conf.key_file = args.keyfile +conf.cert_file = args.cert +conf.debug = 1 +conf.xmlsec_binary = args.xmlsec +secc = security_context(conf) if args.id: desc = entities_descriptor(eds, valid_for, args.name, args.id,