diff --git a/src/saml2/saml.py b/src/saml2/saml.py index 2383b49..be57e1d 100644 --- a/src/saml2/saml.py +++ b/src/saml2/saml.py @@ -1,6 +1,7 @@ #!/usr/bin/python # # Copyright (C) 2007 SIOS Technology, Inc. +# Copyright (C) 2009 Umeå University # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/src/saml2/samlp.py b/src/saml2/samlp.py index 42452d8..55f697f 100644 --- a/src/saml2/samlp.py +++ b/src/saml2/samlp.py @@ -1,6 +1,7 @@ #!/usr/bin/python # # Copyright (C) 2007 SIOS Technology, Inc. +# Copyright (C) 2009 Umeå University # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/src/saml2/utils.py b/src/saml2/utils.py deleted file mode 100644 index 68df361..0000000 --- a/src/saml2/utils.py +++ /dev/null @@ -1,252 +0,0 @@ -#!/opt/local/bin/python -# -# Copyright (C) 2007 SIOS Technology, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Contains utility methods used with SAML-2.""" - -import saml2 -try: - import libxml2 as libxml -except ImportError: - import lxml as libxml -import xmlsec -import random -import time - -TEST = True - -# TODO: write tests for these methods - -class VerifyError(Exception): - pass - -def create_id(): - ret = "" - for _ in range(40): - ret = ret + chr(random.randint(0, 15) + ord('a')) - return ret - -def get_date_and_time(base=None): - if base is None: - base = time.time() - return time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime(base)) - -def lib_init(): - # Init libxml library - libxml.initParser() - libxml.substituteEntitiesDefault(1) - - # Init xmlsec library - if xmlsec.init() < 0: - raise(saml2.Error("Error: xmlsec initialization failed.")) - - # Check loaded library version - if xmlsec.checkVersion() != 1: - raise(saml2.Error( - "Error: loaded xmlsec library version is not compatible.\n")) - - # Init crypto library - if xmlsec.cryptoAppInit(None) < 0: - raise(saml2.Error("Error: crypto initialization failed.")) - - # Init xmlsec-crypto library - if xmlsec.cryptoInit() < 0: - raise(saml2.Error("Error: xmlsec-crypto initialization failed.")) - -def lib_shutdown(): - # Shutdown xmlsec-crypto library - xmlsec.cryptoShutdown() - - # Shutdown crypto library - xmlsec.cryptoAppShutdown() - - # Shutdown xmlsec library - xmlsec.shutdown() - - # Shutdown LibXML2 - libxml.cleanupParser() - -def verify(xml, key_file): - lib_init() - ret = verify_xml(xml, key_file) - lib_shutdown() - return ret == 0 - -# Verifies XML signature in xml string using public key from key_file. -# Returns 0 on success or a negative value if an error occurs. -def verify_xml(xml, key_file): - - doc = libxml.parseDoc(xml) - - if doc is None or doc.getRootElement() is None: - cleanup(doc) - raise saml2.Error("Error: unable to parse file \"%s\"" % xml) - - # Find start node - node = xmlsec.findNode(doc.getRootElement(), xmlsec.NodeSignature, - xmlsec.DSigNs) - - # Create signature context, we don't need keys manager in this example - dsig_ctx = xmlsec.DSigCtx() - if dsig_ctx is None: - cleanup(doc) - raise saml2.Error("Error: failed to create signature context") - - # Load public key, assuming that there is no password - if key_file.endswith(".der"): - key = xmlsec.cryptoAppKeyLoad(key_file, xmlsec.KeyDataFormatDer, - None, None, None) - else: - key = xmlsec.cryptoAppKeyLoad(key_file, xmlsec.KeyDataFormatPem, - None, None, None) - - if key is None: - cleanup(doc, dsig_ctx) - raise saml2.Error( - "Error: failed to load public key from \"%s\"" % key_file) - - dsig_ctx.signKey = key - - # Set key name to the file name, this is just an example! - if key.setName(key_file) < 0: - cleanup(doc, dsig_ctx) - raise saml2.Error( - "Error: failed to set key name for key from \"%s\"" % key_file) - - # Verify signature - if dsig_ctx.verify(node) < 0: - cleanup(doc, dsig_ctx) - raise saml2.Error("Error: signature verify") - - # Print verification result to stdout - if dsig_ctx.status == xmlsec.DSigStatusSucceeded: - ret = 0 - else: - ret = -1 - - # Success - cleanup(doc, dsig_ctx) - return ret - -def verify_xml_with_manager(mngr, xml): - assert(mngr) - assert(xml) - - doc = libxml.parseDoc(xml) - if doc is None or doc.getRootElement() is None: - cleanup(doc) - raise saml2.Error("Error: unable to parse xml") - - - # Find start node - node = xmlsec.findNode(doc.getRootElement(), - xmlsec.NodeSignature, xmlsec.DSigNs) - if node is None: - raise saml2.Error("Error: start node not found in xml doc") - elif TEST: - print "Start node: %s" % (node,) - - # Create signature context - dsig_ctx = xmlsec.DSigCtx(mngr) - if dsig_ctx is None: - cleanup(doc) - raise saml2.Error("Error: failed to create signature context") - - # Verify signature - if dsig_ctx.verify(node) < 0: - cleanup(doc, dsig_ctx) - raise saml2.Error( "Error: signature verify") - - # Print verification result to stdout - if dsig_ctx.status != xmlsec.DSigStatusSucceeded: - raise saml2.Error("Signature is INVALID") - - # Success - return cleanup(doc, dsig_ctx, 1) - -def sign(xml, key_file, cert_file=None): - lib_init() - ret = sign_xml(xml, key_file, cert_file) - lib_shutdown() - return ret - -# Signs the xml_file using private key from key_file and dynamicaly -# created enveloped signature template. -# Returns 0 on success or a negative value if an error occurs. -def sign_xml(xml, key_file, cert_file=None): - - # Load template - doc = libxml.parseDoc(xml) - - if doc is None or doc.getRootElement() is None: - cleanup(doc) - raise saml2.Error("Error: unable to parse string \"%s\"" % xml) - - node = xmlsec.findNode(doc.getRootElement(), xmlsec.NodeSignature, - xmlsec.DSigNs) - - if node is None: - cleanup(doc) - raise saml2.Error("Error: start node not found.") - - # Create signature context, we don't need keys manager in this example - dsig_ctx = xmlsec.DSigCtx() - if dsig_ctx is None: - cleanup(doc) - raise saml2.Error("Error: failed to create signature context") - - # Load private key, assuming that there is not password - key = xmlsec.cryptoAppKeyLoad(key_file, xmlsec.KeyDataFormatPem, - None, None, None) - if key is None: - cleanup(doc, dsig_ctx) - raise saml2.Error( - "Error: failed to load private pem key from \"%s\"" % key_file) - dsig_ctx.signKey = key - - if cert_file is not None: - if xmlsec.cryptoAppKeyCertLoad( - dsig_ctx.signKey, cert_file, xmlsec.KeyDataFormatPem) < 0: - cleanup(doc, dsig_ctx) - raise saml2.Error( - "Error: failed to load cert pem from \"%s\"" % cert_file) - else: - pass - - # Set key name to the file name, this is just an example! - if key.setName(key_file) < 0: - cleanup(doc, dsig_ctx) - raise saml2.Error( - "Error: failed to set key name for key from \"%s\"" % key_file) - - # Sign the template - if dsig_ctx.sign(node) < 0: - cleanup(doc, dsig_ctx) - raise saml2.Error("Error: signature failed") - - # signed document to string - ret = doc.__str__() - - # Success - cleanup(doc, dsig_ctx, 1) - - return ret - -def cleanup(doc=None, dsig_ctx=None, res=0): - if dsig_ctx is not None: - dsig_ctx.destroy() - if doc is not None: - doc.freeDoc() - return res diff --git a/src/xmldsig/__init__.py b/src/xmldsig/__init__.py index b4aaa7e..aa40bf1 100644 --- a/src/xmldsig/__init__.py +++ b/src/xmldsig/__init__.py @@ -1,6 +1,7 @@ #!/usr/bin/python # # Copyright (C) 2007 SIOS Technology, Inc. +# Copyright (C) 2009 Umeå University # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License.