diff --git a/src/saml2/attributemaps/saml_uri.py b/src/saml2/attributemaps/saml_uri.py index 23cdceb..fd5d51c 100644 --- a/src/saml2/attributemaps/saml_uri.py +++ b/src/saml2/attributemaps/saml_uri.py @@ -1,6 +1,6 @@ EDUCOURSE_OID = 'urn:oid:1.3.6.1.4.1.5923.1.6.1.' EDUPERSON_OID = 'urn:oid:1.3.6.1.4.1.5923.1.1.1.' -LDAPGVAT_OID = 'urn:oid:1.2.40.0.10.2.1.1.' # ldap.gv.at definitions as specified in http://www.ref.gv.at/AG-IZ-PVP2-Version-2-1-0-2.2754.0.html +LDAPGVAT_OID = 'urn:oid:1.2.40.0.10.2.1.1.' # ldap.gv.at definitions as specified in http://www.ref.gv.at/AG-IZ-PVP2-Version-2-1-0-2.2754.0.html UCL_DIR_PILOT = 'urn:oid:0.9.2342.19200300.100.1.' X500ATTR_OID = 'urn:oid:2.5.4.' LDAPGVAT_UCL_DIR_PILOT = UCL_DIR_PILOT diff --git a/src/saml2/httputil.py b/src/saml2/httputil.py index c67c9fe..2304f36 100644 --- a/src/saml2/httputil.py +++ b/src/saml2/httputil.py @@ -142,6 +142,20 @@ class BadGateway(Response): _status = "502 Bad Gateway" +class HttpParameters(): + """GET or POST signature parameters for Redirect or POST-SimpleSign bindings + because they are not contained in XML unlike the POST binding + """ + signature = None + sigalg = None + # Relaystate and SAML message are stored elsewhere + def __init__(self, dict): + try: + self.signature = dict["Signature"][0] + self.sigalg = dict["SigAlg"][0] + except KeyError: + pass + def extract(environ, empty=False, err=False): """Extracts strings in form data and returns a dict. diff --git a/src/saml2/saml.py b/src/saml2/saml.py index d24a37c..a85bfd0 100644 --- a/src/saml2/saml.py +++ b/src/saml2/saml.py @@ -36,7 +36,14 @@ NAMEID_FORMAT_TRANSIENT = ( "urn:oasis:names:tc:SAML:2.0:nameid-format:transient") NAMEID_FORMAT_ENTITY = ( "urn:oasis:names:tc:SAML:2.0:nameid-format:entity") - +NAMEID_FORMATS_SAML2 = ( + ('NAMEID_FORMAT_EMAILADDRESS', NAMEID_FORMAT_EMAILADDRESS), + ('NAMEID_FORMAT_ENCRYPTED', NAMEID_FORMAT_ENCRYPTED), + ('NAMEID_FORMAT_ENTITY', NAMEID_FORMAT_ENTITY), + ('NAMEID_FORMAT_PERSISTENT', NAMEID_FORMAT_PERSISTENT), + ('NAMEID_FORMAT_TRANSIENT', NAMEID_FORMAT_TRANSIENT), + ('NAMEID_FORMAT_UNSPECIFIED', NAMEID_FORMAT_UNSPECIFIED), +) PROFILE_ATTRIBUTE_BASIC = ( "urn:oasis:names:tc:SAML:2.0:profiles:attribute:basic") @@ -48,7 +55,11 @@ NAME_FORMAT_UNSPECIFIED = ( "urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified") NAME_FORMAT_URI = "urn:oasis:names:tc:SAML:2.0:attrname-format:uri" NAME_FORMAT_BASIC = "urn:oasis:names:tc:SAML:2.0:attrname-format:basic" - +NAME_FORMATS_SAML2 = ( + ('NAME_FORMAT_BASIC', NAME_FORMAT_BASIC), + ('NAME_FORMAT_URI', NAME_FORMAT_URI), + ('NAME_FORMAT_UNSPECIFIED', NAME_FORMAT_UNSPECIFIED), +) DECISION_TYPE_PERMIT = "Permit" DECISION_TYPE_DENY = "Deny" DECISION_TYPE_INDETERMINATE = "Indeterminate" diff --git a/src/saml2/sigver.py b/src/saml2/sigver.py index 2d02923..c32136a 100644 --- a/src/saml2/sigver.py +++ b/src/saml2/sigver.py @@ -42,26 +42,30 @@ from saml2.time_util import str_to_time from tempfile import NamedTemporaryFile from subprocess import Popen, PIPE + +from xmldsig import digest_default +from xmldsig import sig_default +from xmldsig import SIG_RSA_SHA1 +from xmldsig import SIG_RSA_SHA224 +from xmldsig import SIG_RSA_SHA256 +from xmldsig import SIG_RSA_SHA384 +from xmldsig import SIG_RSA_SHA512 from xmlenc import EncryptionMethod from xmlenc import EncryptedKey from xmlenc import CipherData from xmlenc import CipherValue from xmlenc import EncryptedData +from Crypto.Hash import SHA +from Crypto.Hash import SHA224 from Crypto.Hash import SHA256 from Crypto.Hash import SHA384 from Crypto.Hash import SHA512 -from Crypto.Hash import SHA logger = logging.getLogger(__name__) SIG = "{%s#}%s" % (ds.NAMESPACE, "Signature") -RSA_SHA1 = "http://www.w3.org/2000/09/xmldsig#rsa-sha1" -RSA_SHA256 = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" -RSA_SHA384 = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha384" -RSA_SHA512 = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha512" - RSA_1_5 = "http://www.w3.org/2001/04/xmlenc#rsa-1_5" TRIPLE_DES_CBC = "http://www.w3.org/2001/04/xmlenc#tripledes-cbc" XMLTAG = "" @@ -595,10 +599,11 @@ class RSASigner(Signer): SIGNER_ALGS = { - RSA_SHA1: RSASigner(SHA), - RSA_SHA256: RSASigner(SHA256), - RSA_SHA384: RSASigner(SHA384), - RSA_SHA512: RSASigner(SHA512), + SIG_RSA_SHA1: RSASigner(SHA), + SIG_RSA_SHA224: RSASigner(SHA224), + SIG_RSA_SHA256: RSASigner(SHA256), + SIG_RSA_SHA384: RSASigner(SHA384), + SIG_RSA_SHA512: RSASigner(SHA512), } REQ_ORDER = ["SAMLRequest", "RelayState", "SigAlg"] @@ -619,7 +624,7 @@ def verify_redirect_signature(saml_msg, cert): except KeyError: raise Unsupported("Signature algorithm: %s" % saml_msg["SigAlg"]) else: - if saml_msg["SigAlg"][0] == RSA_SHA1: + if saml_msg["SigAlg"][0] == SIG_RSA_SHA1: if "SAMLRequest" in saml_msg: _order = REQ_ORDER elif "SAMLResponse" in saml_msg: @@ -1682,7 +1687,8 @@ class SecurityContext(object): # =========================================================================== -def pre_signature_part(ident, public_key=None, identifier=None): +def pre_signature_part(ident, public_key=None, identifier=None, + digest_alg=None, sign_alg=None): """ 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 @@ -1695,13 +1701,17 @@ def pre_signature_part(ident, public_key=None, identifier=None): :return: A preset signature part """ - signature_method = ds.SignatureMethod(algorithm=ds.SIG_RSA_SHA1) + if not digest_alg: + digest_alg=ds.digest_default + if not sign_alg: + sign_alg=ds.sig_default + signature_method = ds.SignatureMethod(algorithm=sign_alg) canonicalization_method = ds.CanonicalizationMethod( algorithm=ds.ALG_EXC_C14N) trans0 = ds.Transform(algorithm=ds.TRANSFORM_ENVELOPED) trans1 = ds.Transform(algorithm=ds.ALG_EXC_C14N) transforms = ds.Transforms(transform=[trans0, trans1]) - digest_method = ds.DigestMethod(algorithm=ds.DIGEST_SHA1) + digest_method = ds.DigestMethod(algorithm=digest_alg) reference = ds.Reference(uri="#%s" % ident, digest_value=ds.DigestValue(), transforms=transforms, digest_method=digest_method) diff --git a/src/xmldsig/__init__.py b/src/xmldsig/__init__.py index a184912..c21da29 100644 --- a/src/xmldsig/__init__.py +++ b/src/xmldsig/__init__.py @@ -10,20 +10,59 @@ from saml2 import SamlBase NAMESPACE = 'http://www.w3.org/2000/09/xmldsig#' ENCODING_BASE64 = 'http://www.w3.org/2000/09/xmldsig#base64' + +# digest and signature algorithms (not implemented = commented out) +DIGEST_MD5 = 'http://www.w3.org/2001/04/xmldsig-more#md5' # test framework only! DIGEST_SHA1 = 'http://www.w3.org/2000/09/xmldsig#sha1' -ALG_EXC_C14N = 'http://www.w3.org/2001/10/xml-exc-c14n#' -SIG_DSA_SHA1 = 'http://www.w3.org/2000/09/xmldsig#dsa-sha1' +DIGEST_SHA224 = 'http://www.w3.org/2001/04/xmldsig-more#sha224' +DIGEST_SHA256 = 'http://www.w3.org/2001/04/xmlenc#sha256' +DIGEST_SHA384 = 'http://www.w3.org/2001/04/xmldsig-more#sha384' +DIGEST_SHA512 = 'http://www.w3.org/2001/04/xmlenc#sha512' +DIGEST_RIPEMD160 = 'http://www.w3.org/2001/04/xmlenc#ripemd160' +digest_default = DIGEST_SHA1 +DIGEST_ALLOWED_ALG = (('DIGEST_SHA1', DIGEST_SHA1), + ('DIGEST_SHA224', DIGEST_SHA224), + ('DIGEST_SHA256', DIGEST_SHA256), + ('DIGEST_SHA384', DIGEST_SHA384), + ('DIGEST_SHA512', DIGEST_SHA512), + ('DIGEST_RIPEMD160', DIGEST_RIPEMD160)) +DIGEST_AVAIL_ALG = DIGEST_ALLOWED_ALG + (('DIGEST_MD5', DIGEST_MD5), ) + +#SIG_DSA_SHA1 = 'http,//www.w3.org/2000/09/xmldsig#dsa-sha1' +#SIG_DSA_SHA256 = 'http://www.w3.org/2009/xmldsig11#dsa-sha256' +#SIG_ECDSA_SHA1 = 'http://www.w3.org/2001/04/xmldsig-more#ECDSA_sha1' +#SIG_ECDSA_SHA224 = 'http://www.w3.org/2001/04/xmldsig-more#ECDSA_sha224' +#SIG_ECDSA_SHA256 = 'http://www.w3.org/2001/04/xmldsig-more#ECDSA_sha256' +#SIG_ECDSA_SHA384 = 'http://www.w3.org/2001/04/xmldsig-more#ECDSA_sha384' +#SIG_ECDSA_SHA512 = 'http://www.w3.org/2001/04/xmldsig-more#ECDSA_sha512' +SIG_RSA_MD5 = 'http://www.w3.org/2001/04/xmldsig-more#rsa-md5' # test framework SIG_RSA_SHA1 = 'http://www.w3.org/2000/09/xmldsig#rsa-sha1' +SIG_RSA_SHA224 = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha224' +SIG_RSA_SHA256 = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256' +SIG_RSA_SHA384 = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha384' +SIG_RSA_SHA512 = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha512' +#SIG_RSA_RIPEMD160 = 'http://www.w3.org/2001/04/xmldsig-more#rsa-ripemd160' +sig_default = SIG_RSA_SHA1 +SIG_ALLOWED_ALG = (('SIG_RSA_SHA1', SIG_RSA_SHA1), + ('SIG_RSA_SHA224', SIG_RSA_SHA224), + ('SIG_RSA_SHA256', SIG_RSA_SHA256), + ('SIG_RSA_SHA384', SIG_RSA_SHA384), + ('SIG_RSA_SHA512', SIG_RSA_SHA512)) +SIG_AVAIL_ALG = SIG_ALLOWED_ALG + (('SIG_RSA_MD5', SIG_RSA_MD5), ) + MAC_SHA1 = 'http://www.w3.org/2000/09/xmldsig#hmac-sha1' C14N = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315' C14N_WITH_C = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments' +ALG_EXC_C14N = 'http://www.w3.org/2001/10/xml-exc-c14n#' TRANSFORM_XSLT = 'http://www.w3.org/TR/1999/REC-xslt-19991116' TRANSFORM_XPATH = 'http://www.w3.org/TR/1999/REC-xpath-19991116' TRANSFORM_ENVELOPED = 'http://www.w3.org/2000/09/xmldsig#enveloped-signature' + + class CryptoBinary_(SamlBase): """The http://www.w3.org/2000/09/xmldsig#:CryptoBinary element """