Changeset 5357
- Timestamp:
- 05/06/09 12:36:59 (12 years ago)
- Location:
- TI12-security/trunk/python
- Files:
-
- 3 added
- 26 edited
Legend:
- Unmodified
- Added
- Removed
-
TI12-security/trunk/python/Makefile
r4750 r5357 6 6 # Make all eggs 7 7 # 8 # @copyright: (C) 2007 CCLRC & NERC8 # @copyright: (C) 2007 STFC 9 9 # 10 10 # @license: This software may be distributed under the terms of the Q Public -
TI12-security/trunk/python/MyProxyClient/documentation/Makefile
r4654 r5357 7 7 # 8 8 9 # @copyright: (C) 2008 CCLRC & NERC9 # @copyright: (C) 2008 STFC 10 10 # 11 11 # @license: This software may be distributed under the terms of the Q Public -
TI12-security/trunk/python/Tests/etreewss/client/Makefile
r4024 r5357 7 7 # server side code 8 8 # 9 # @copyright (C) 2007 CCLRC & NERC9 # @copyright (C) 2007 STFC 10 10 # 11 11 # @license This software may be distributed under the terms of the Q Public -
TI12-security/trunk/python/Tests/etreewss/server/Makefile
r4024 r5357 7 7 # server side code 8 8 # 9 # @copyright (C) 2007 CCLRC & NERC9 # @copyright (C) 2007 STFC 10 10 # 11 11 # @license This software may be distributed under the terms of the Q Public -
TI12-security/trunk/python/ndg.security.common/ndg/security/common/authz/msi.py
r5355 r5357 554 554 555 555 # Iterate through matching targets checking for user access 556 knownAttributeAuthorityURIs = []557 556 request.subject[Subject.ROLES_NS] = [] 558 557 permitForAllTargets = [Response.DECISION_PERMIT]*numMatchingTargets … … 565 564 # Make call to the Policy Information Point to pull user 566 565 # attributes applicable to this resource 567 if matchingTarget.attributeAuthorityURI not in \ 568 knownAttributeAuthorityURIs: 566 attributeQuery = PIPAttributeQuery() 567 attributeQuery[PIPAttributeQuery.SUBJECT_NS] = request.subject 568 569 attributeQuery[PIPAttributeQuery.ATTRIBUTEAUTHORITY_NS] = \ 570 matchingTarget.attributeAuthorityURI 571 572 # Exit from function returning indeterminate status if a 573 # problem occurs here 574 try: 575 attributeResponse=self.pip.attributeQuery(attributeQuery) 569 576 570 attributeQuery = PIPAttributeQuery() 571 attributeQuery[PIPAttributeQuery.SUBJECT_NS] = request.subject 577 except SubjectRetrievalError, e: 578 # i.e. a defined exception within the scope of this 579 # module 580 log.exception(e) 581 return Response(Response.DECISION_INDETERMINATE, 582 message=str(e)) 572 583 573 attributeQuery[PIPAttributeQuery.ATTRIBUTEAUTHORITY_NS] = \ 574 matchingTarget.attributeAuthorityURI 575 576 # Exit from function returning indeterminate status if a 577 # problem occurs here 578 try: 579 attributeResponse=self.pip.attributeQuery(attributeQuery) 580 581 except SubjectRetrievalError, e: 582 # i.e. a defined exception within the scope of this 583 # module 584 log.exception(e) 585 return Response(Response.DECISION_INDETERMINATE, 586 message=str(e)) 587 588 except Exception, e: 589 log.exception(e) 590 return Response(Response.DECISION_INDETERMINATE, 591 message="An internal error occurred") 592 593 knownAttributeAuthorityURIs.append( 594 matchingTarget.attributeAuthorityURI) 595 596 # Accumulate attributes retrieved from multiple attribute 597 # authorities 598 request.subject[Subject.ROLES_NS] += attributeResponse[ 599 Subject.ROLES_NS] 584 except Exception, e: 585 log.exception(e) 586 return Response(Response.DECISION_INDETERMINATE, 587 message="An internal error occurred") 588 589 # Accumulate attributes retrieved from multiple attribute 590 # authorities 591 request.subject[Subject.ROLES_NS] += attributeResponse[ 592 Subject.ROLES_NS] 600 593 601 594 # Match the subject's attributes against the target -
TI12-security/trunk/python/ndg.security.common/ndg/security/common/wssecurity/__init__.py
r5067 r5357 23 23 CaseSensitiveConfigParser 24 24 25 class WSSecurityConfigError(Exception): 25 class WSSecurityError(Exception): 26 """For WS-Security generic exceptions not covered by other exception 27 classes in this module""" 28 def __init__(self, errorMessage): 29 log.warning(errorMessage) 30 super(WSSecurityError, self).__init__(errorMessage) 31 32 class WSSecurityConfigError(WSSecurityError): 26 33 """Configuration error with WS-Security setting or settings""" 27 34 … … 46 53 caCertFilePathList=[], 47 54 addTimestamp=True, 55 timestampMustBeSet=False, 56 createdElemMustBeSet=True, 57 expiresElemMustBeSet=True, 48 58 applySignatureConfirmation=False, 49 59 refC14nInclNS=[], -
TI12-security/trunk/python/ndg.security.common/ndg/security/common/wssecurity/signaturehandler/__init__.py
r5280 r5357 26 26 27 27 # Enable settings from a config file 28 from ndg.security.common.wssecurity import WSSecurityConfig 28 from ndg.security.common.wssecurity import WSSecurityConfig, WSSecurityError 29 29 30 30 from ndg.security.common.X509 import X509Cert, X509CertParse, X509CertRead, \ … … 35 35 log = logging.getLogger(__name__) 36 36 37 38 class _ENCRYPTION(ENCRYPTION):39 '''Derived from ENCRYPTION class to add in extra 'tripledes-cbc' - is this40 any different to 'des-cbc'? ENCRYPTION class implies that it is the same41 because it's assigned to 'BLOCK_3DES' ??'''42 BLOCK_TRIPLEDES = "http://www.w3.org/2001/04/xmlenc#tripledes-cbc"43 37 44 38 class _WSU(WSU): … … 57 51 58 52 59 class WSSecurityError(Exception):60 """For WS-Security generic exceptions not covered by other exception61 classes in this module"""62 def __init__(self, errorMessage):63 log.warning(errorMessage)64 super(WSSecurityError, self).__init__(errorMessage)65 66 53 class InvalidCertChain(WSSecurityError): 67 54 """Raised from SignatureHandler.verify if the certificate submitted to … … 75 62 """Raised from SignatureHandler._verifyTimestamp if there is a problem with 76 63 the created or expiry times in an input message Timestamp""" 64 65 class MessageExpired(TimestampError): 66 """Raised from SignatureHandler._verifyTimestamp if the timestamp of 67 the message being processed is before the current time. Can be caught in 68 order to set a wsu:MessageExpired fault code""" 77 69 78 70 class InvalidSignature(WSSecurityError): … … 271 263 self.caCertFilePathList = self.cfg['caCertFilePathList'] 272 264 265 # Configure signature generation t oadd/omit a timestamp 273 266 self.addTimestamp = self.cfg['addTimestamp'] 267 268 # Configure timestamp checking in Signature verification handler 269 self.timestampMustBeSet = self.cfg['timestampMustBeSet'] 270 self.createdElemMustBeSet = self.cfg['createdElemMustBeSet'] 271 self.expiresElemMustBeSet = self.cfg['expiresElemMustBeSet'] 274 272 275 273 # set default value, if none specified in config file … … 691 689 doc="List of CA cert. files used for verification") 692 690 691 692 def _setBool(self, val): 693 """Convert input string, float or int to bool type 694 695 @type val: int, float or basestring 696 @param val: input value to be converted 697 @rtype: bool 698 @return: input value converted to bool type 699 """ 700 701 if isinstance(val, bool): 702 return val 703 704 elif isinstance(val, basestring): 705 val = val.lower() 706 if val not in ("true", "false"): 707 raise ValueError("String conversion failed for input: %r"%val) 708 709 return val == "true" 710 711 elif isinstance(val, (int, float)): 712 return bool(val) 713 else: 714 raise TypeError("Invalid type for bool conversion: %r" % 715 val.__class__) 716 717 def _get_timestampMustBeSet(self): 718 return getattr(self, "_timestampMustBeSet", False) 719 720 def _set_timestampMustBeSet(self, val): 721 self._timestampMustBeSet = self._setBool(val) 722 723 timestampMustBeSet = property(fset=_set_timestampMustBeSet, 724 fget=_get_timestampMustBeSet, 725 doc="Set to True to raise an exception if a " 726 "message to be verified doesn't have a " 727 "timestamp element. Set to False to " 728 "log a warning message and continue " 729 "processing") 730 731 def _get_createdElemMustBeSet(self): 732 return getattr(self, "_createdElemMustBeSet", False) 733 734 def _set_createdElemMustBeSet(self, val): 735 self._createdElemMustBeSet = self._setBool(val) 736 737 createdElemMustBeSet = property(fset=_set_createdElemMustBeSet, 738 fget=_get_createdElemMustBeSet, 739 doc="Set to True to raise an exception if " 740 "a message to be verified doesn't " 741 "have <wsu:Created/> element with its " 742 "timestamp element. Set to False to " 743 "log a warning message and continue " 744 "processing") 745 746 def _get_expiresElemMustBeSet(self): 747 return getattr(self, "_expiresElemMustBeSet", False) 748 749 def _set_expiresElemMustBeSet(self, val): 750 self._expiresElemMustBeSet = self._setBool(val) 751 752 expiresElemMustBeSet = property(fset=_set_expiresElemMustBeSet, 753 fget=_get_expiresElemMustBeSet, 754 doc="Set to True to raise an exception if " 755 "a message to be verified doesn't " 756 "have <wsu:Expires/> element with its " 757 "timestamp element. Set to False to " 758 "log a warning message and continue " 759 "processing") 760 761 -
TI12-security/trunk/python/ndg.security.common/ndg/security/common/wssecurity/signaturehandler/dom.py
r5063 r5357 1 1 """ DOM based WS-Security digital signature handler 2 2 3 NERC Data 3 NERC DataGrid Project 4 4 """ 5 5 __author__ = "C Byrom" … … 18 18 import base64 19 19 20 # Conditional import as this is required for the encryption21 # handler22 try:23 # For shared key encryption24 from Crypto.Cipher import AES, DES325 except:26 from warnings import warn27 warn('Crypto.Cipher not available: EncryptionHandler disabled!',28 RuntimeWarning)29 class AES:30 MODE_ECB = None31 MODE_CBC = None32 33 class DES3:34 MODE_CBC = None35 36 20 import os 37 21 … … 68 52 import logging 69 53 log = logging.getLogger(__name__) 70 71 from ndg.security.common.wssecurity.signaturehandler import _ENCRYPTION, \ 72 _WSU, OASIS, BaseSignatureHandler, WSSecurityError, NoSignatureFound, \ 73 InvalidSignature, TimestampError, VerifyError, SignatureError 74 75 # Enable settings from a config file 76 from ndg.security.common.wssecurity import WSSecurityConfig 54 from ndg.security.common.wssecurity import WSSecurityError 55 from ndg.security.common.wssecurity.signaturehandler import _WSU, OASIS, \ 56 BaseSignatureHandler, NoSignatureFound, InvalidSignature, TimestampError, \ 57 MessageExpired, VerifyError, SignatureError 77 58 78 59 from ndg.security.common.X509 import X509Cert, X509CertParse, X509CertRead, \ 79 60 X509Stack, X509StackParseFromDER 61 62 63 # Helper functions 64 def getElements(node, nameList): 65 '''DOM Helper function for getting child elements from a given node''' 66 # Avoid sub-string matches 67 nameList = isinstance(nameList, basestring) and [nameList] or nameList 68 return [n for n in node.childNodes if str(n.localName) in nameList] 69 70 71 def getChildNodes(node, nodeList=None): 72 if nodeList is None: 73 nodeList = [node] 74 return _getChildNodes(node, nodeList) 75 76 def _getChildNodes(node, nodeList): 77 78 if node.attributes is not None: 79 nodeList += node.attributes.values() 80 nodeList += node.childNodes 81 for childNode in node.childNodes: 82 _getChildNodes(childNode, nodeList) 83 return nodeList 84 80 85 81 86 class SignatureHandler(BaseSignatureHandler): … … 141 146 142 147 143 def _verifyTimeStamp(self, parsedSOAP, ctxt, timestampMustBeSet=False): 148 def _verifyTimeStamp(self, 149 parsedSOAP, 150 ctxt, 151 timestampMustBeSet=False, 152 createdElemMustBeSet=True, 153 expiresElemMustBeSet=True): 144 154 """Call from verify to check timestamp if found. 145 155 … … 150 160 sender 151 161 @type ctxt: 152 @param ctxt: XPath context object""" 162 @param ctxt: XPath context object 163 @type timestampMustBeSet: bool 164 @param timestampMustBeSet: if set to True, raise an exception if no 165 timestamp element is found 166 @type createdElemMustBeSet: bool 167 @param createdElemMustBeSet: if True. raise an exception if no 168 <wsu:Created/> element is present 169 @param expiresElemMustBeSet: if True. raise an exception if no 170 <wsu:Expires/> element is present 171 """ 153 172 154 173 # TODO: do we need to be more rigorous in terms of handling the … … 159 178 contextNode=parsedSOAP.dom, 160 179 context=ctxt)[0] 161 except :180 except IndexError: 162 181 msg = "Verifying message - No timestamp element found" 163 182 if timestampMustBeSet: … … 172 191 createdNode = timestampNode.getElementsByTagName("wsu:Created") 173 192 if createdNode is None: 174 raise TimestampError("Verifying message - No Created timestamp " 175 "sub-element found") 176 177 # Workaround for fractions of second 178 try: 179 createdDateTime, createdSecFraction = \ 193 msg = ("Verifying message: no <wsu:Created/> timestamp " 194 "sub-element found") 195 if createdElemMustBeSet: 196 raise TimestampError(msg) 197 else: 198 log.warning(msg) 199 else: 200 # Workaround for fractions of second 201 try: 202 createdDateTime, createdSecFraction = \ 180 203 createdNode[0].childNodes[0].nodeValue.split('.') 181 dtCreated = _strptime(createdDateTime, '%Y-%m-%dT%H:%M:%S')182 createdSeconds = float("0." + createdSecFraction.replace('Z',''))183 dtCreated += timedelta(seconds=createdSeconds)184 185 except ValueError, e:186 raise TimestampError("Failed to parse timestamp Created element:"187 "%s" % e)188 189 if dtCreated >= dtNow:190 raise TimestampError("Timestamp created time %s is equal to or"191 "after the current time %s" % \192 (dtCreated, dtNow))204 dtCreated = _strptime(createdDateTime, '%Y-%m-%dT%H:%M:%S') 205 createdSeconds = float("0."+createdSecFraction.replace('Z','')) 206 dtCreated += timedelta(seconds=createdSeconds) 207 208 except ValueError, e: 209 raise TimestampError("Failed to parse timestamp Created " 210 "element: %s" % e) 211 212 if dtCreated >= dtNow: 213 raise TimestampError("Timestamp created time %s is equal to " 214 "or after the current time %s" % 215 (dtCreated, dtNow)) 193 216 194 217 expiresNode = timestampNode.getElementsByTagName("wsu:Expires") 195 218 if expiresNode is None: 196 log.warning("Verifying message - No Expires element found in " 197 "Timestamp") 198 return 199 200 try: 201 expiresDateTime, expiresSecFraction = \ 219 msg = ("Verifying message: no <wsu:Expires/> element found in " 220 "Timestamp") 221 if expiresElemMustBeSet: 222 raise TimestampError(msg) 223 else: 224 log.warning(msg) 225 else: 226 try: 227 expiresDateTime, expiresSecFraction = \ 202 228 expiresNode[0].childNodes[0].nodeValue.split('.') 203 dtExpiry = _strptime(expiresDateTime, '%Y-%m-%dT%H:%M:%S')204 expirySeconds = float("0." +expiresSecFraction.replace('Z', ''))205 dtExpiry += timedelta(seconds=expirySeconds)206 207 except ValueError, e:208 raise TimestampError("Failed to parse timestamp Expires element:"209 "%s" % e)210 211 if dtExpiry < dtNow:212 raise TimestampError("Timestamp expiry time %s is before the"213 "current time %s - i.e. the message has "214 "expired." %(dtExpiry, dtNow))229 dtExpiry = _strptime(expiresDateTime, '%Y-%m-%dT%H:%M:%S') 230 expirySeconds = float("0."+expiresSecFraction.replace('Z', '')) 231 dtExpiry += timedelta(seconds=expirySeconds) 232 233 except ValueError, e: 234 raise TimestampError("Failed to parse timestamp Expires " 235 "element: %s" % e) 236 237 if dtExpiry < dtNow: 238 raise MessageExpired("Message has expired: timestamp expiry " 239 "time %s is before the current time %s." % 240 (dtExpiry, dtNow)) 215 241 216 242 … … 723 749 caX509Stack=self._caX509Stack) 724 750 725 self._verifyTimeStamp(parsedSOAP, ctxt) 751 self._verifyTimeStamp(parsedSOAP, 752 ctxt, 753 timestampMustBeSet=self.timestampMustBeSet, 754 createdElemMustBeSet=self.createdElemMustBeSet, 755 expiresElemMustBeSet=self.expiresElemMustBeSet) 756 726 757 log.info("Signature OK") 727 728 729 class EncryptionError(WSSecurityError):730 """Flags an error in the encryption process"""731 732 class DecryptionError(WSSecurityError):733 """Raised from EncryptionHandler.decrypt if an error occurs with the734 decryption process"""735 736 737 class EncryptionHandler(object):738 """Encrypt/Decrypt SOAP messages using WS-Security"""739 740 # Map namespace URIs to Crypto algorithm module and mode741 cryptoAlg = \742 {743 _ENCRYPTION.WRAP_AES256: {'module': AES,744 'mode': AES.MODE_ECB,745 'blockSize': 16},746 747 # CBC (Cipher Block Chaining) modes748 _ENCRYPTION.BLOCK_AES256: {'module': AES,749 'mode': AES.MODE_CBC,750 'blockSize': 16},751 752 _ENCRYPTION.BLOCK_TRIPLEDES: {'module': DES3,753 'mode': DES3.MODE_CBC,754 'blockSize': 8}755 }756 757 758 def __init__(self,759 signingCertFilePath=None,760 signingPriKeyFilePath=None,761 signingPriKeyPwd=None,762 chkSecurityTokRef=False,763 encrNS=_ENCRYPTION.BLOCK_AES256):764 765 self.__signingCertFilePath = signingCertFilePath766 self.__signingPriKeyFilePath = signingPriKeyFilePath767 self.__signingPriKeyPwd = signingPriKeyPwd768 769 self.__chkSecurityTokRef = chkSecurityTokRef770 771 # Algorithm for shared key encryption772 try:773 self.__encrAlg = self.cryptoAlg[encrNS]774 775 except KeyError:776 raise EncryptionError, \777 'Input encryption algorithm namespace "%s" is not supported' % encrNS778 779 self.__encrNS = encrNS780 781 782 def encrypt(self, soapWriter):783 """Encrypt an outbound SOAP message784 785 Use Key Wrapping - message is encrypted using a shared key which786 itself is encrypted with the public key provided by the X.509 cert.787 signingCertFilePath"""788 789 # Use X.509 Cert to encrypt790 x509Cert = X509.load_cert(self.__signingCertFilePath)791 792 soapWriter.dom.setNamespaceAttribute('wsse', OASIS.WSSE)793 soapWriter.dom.setNamespaceAttribute('xenc', _ENCRYPTION.BASE)794 soapWriter.dom.setNamespaceAttribute('ds', DSIG.BASE)795 796 # TODO: Put in a check to make sure <wsse:security> isn't already797 # present in header798 wsseElem = soapWriter._header.createAppendElement(OASIS.WSSE,799 'Security')800 wsseElem.node.setAttribute('SOAP-ENV:mustUnderstand', "1")801 802 encrKeyElem = wsseElem.createAppendElement(_ENCRYPTION.BASE,803 'EncryptedKey')804 805 # Encryption method used to encrypt the shared key806 keyEncrMethodElem = encrKeyElem.createAppendElement(_ENCRYPTION.BASE,807 'EncryptionMethod')808 809 keyEncrMethodElem.node.setAttribute('Algorithm',810 _ENCRYPTION.KT_RSA_1_5)811 812 813 # Key Info814 KeyInfoElem = encrKeyElem.createAppendElement(DSIG.BASE, 'KeyInfo')815 816 secTokRefElem = KeyInfoElem.createAppendElement(OASIS.WSSE,817 'SecurityTokenReference')818 819 x509IssSerialElem = secTokRefElem.createAppendElement(DSIG.BASE,820 'X509IssuerSerial')821 822 823 x509IssNameElem = x509IssSerialElem.createAppendElement(DSIG.BASE,824 'X509IssuerName')825 x509IssNameElem.createAppendTextNode(x509Cert.get_issuer().as_text())826 827 828 x509IssSerialNumElem = x509IssSerialElem.createAppendElement(829 DSIG.BASE,830 'X509IssuerSerialNumber')831 832 x509IssSerialNumElem.createAppendTextNode(833 str(x509Cert.get_serial_number()))834 835 # References to what has been encrypted836 encrKeyCiphDataElem = encrKeyElem.createAppendElement(837 _ENCRYPTION.BASE,838 'CipherData')839 840 encrKeyCiphValElem = encrKeyCiphDataElem.createAppendElement(841 _ENCRYPTION.BASE,842 'CipherValue')843 844 # References to what has been encrypted845 refListElem = encrKeyElem.createAppendElement(_ENCRYPTION.BASE,846 'ReferenceList')847 848 dataRefElem = refListElem.createAppendElement(_ENCRYPTION.BASE,849 'DataReference')850 dataRefElem.node.setAttribute('URI', "#encrypted")851 852 853 # Add Encrypted data to SOAP body854 encrDataElem = soapWriter.body.createAppendElement(_ENCRYPTION.BASE,855 'EncryptedData')856 encrDataElem.node.setAttribute('Id', 'encrypted')857 encrDataElem.node.setAttribute('Type', _ENCRYPTION.BASE)858 859 # Encryption method used to encrypt the target data860 dataEncrMethodElem = encrDataElem.createAppendElement(861 _ENCRYPTION.BASE,862 'EncryptionMethod')863 864 dataEncrMethodElem.node.setAttribute('Algorithm', self.__encrNS)865 866 # Cipher data867 ciphDataElem = encrDataElem.createAppendElement(_ENCRYPTION.BASE,868 'CipherData')869 870 ciphValueElem = ciphDataElem.createAppendElement(_ENCRYPTION.BASE,871 'CipherValue')872 873 874 # Get elements from SOAP body for encryption875 dataElem = soapWriter.body.node.childNodes[0]876 data = dataElem.toxml()877 878 # Pad data to nearest multiple of encryption algorithm's block size879 modData = len(data) % self.__encrAlg['blockSize']880 nPad = modData and self.__encrAlg['blockSize'] - modData or 0881 882 # PAd with random junk but ...883 data += os.urandom(nPad-1)884 885 # Last byte should be number of padding bytes886 # (http://www.w3.org/TR/xmlenc-core/#sec-Alg-Block)887 data += chr(nPad)888 889 # Generate shared key and input vector - for testing use hard-coded890 # values to allow later comparison891 sharedKey = os.urandom(self.__encrAlg['blockSize'])892 iv = os.urandom(self.__encrAlg['blockSize'])893 894 alg = self.__encrAlg['module'].new(sharedKey,895 self.__encrAlg['mode'],896 iv)897 898 # Encrypt required elements - prepend input vector899 encryptedData = alg.encrypt(iv + data)900 dataCiphValue = base64.encodestring(encryptedData).strip()901 902 ciphValueElem.createAppendTextNode(dataCiphValue)903 904 905 # ! Delete unencrypted message body elements !906 soapWriter.body.node.removeChild(dataElem)907 908 909 # Use X.509 cert public key to encrypt the shared key - Extract key910 # from the cert911 rsaPubKey = x509Cert.get_pubkey().get_rsa()912 913 # Encrypt the shared key914 encryptedSharedKey = rsaPubKey.public_encrypt(sharedKey,915 RSA.pkcs1_padding)916 917 encrKeyCiphVal = base64.encodestring(encryptedSharedKey).strip()918 919 # Add the encrypted shared key to the EncryptedKey section in the SOAP920 # header921 encrKeyCiphValElem.createAppendTextNode(encrKeyCiphVal)922 923 # print soapWriter.dom.node.toprettyxml()924 # import pdb;pdb.set_trace()925 926 927 def decrypt(self, parsedSOAP):928 """Decrypt an inbound SOAP message"""929 930 processorNss = \931 {932 'xenc': _ENCRYPTION.BASE,933 'ds': DSIG.BASE,934 'wsu': _WSU.UTILITY,935 'wsse': OASIS.WSSE,936 'soapenv':"http://schemas.xmlsoap.org/soap/envelope/"937 }938 ctxt = Context(parsedSOAP.dom, processorNss=processorNss)939 940 refListNodes = xpath.Evaluate('//xenc:ReferenceList',941 contextNode=parsedSOAP.dom,942 context=ctxt)943 if len(refListNodes) > 1:944 raise DecryptionError, 'Expecting a single ReferenceList element'945 946 try:947 refListNode = refListNodes[0]948 except:949 # Message wasn't encrypted - is this OK or is a check needed for950 # encryption info in SOAP body - enveloped form?951 return952 953 954 # Check for wrapped key encryption955 encrKeyNodes = xpath.Evaluate('//xenc:EncryptedKey',956 contextNode=parsedSOAP.dom,957 context=ctxt)958 if len(encrKeyNodes) > 1:959 raise DecryptionError, 'This implementation can only handle ' + \960 'single EncryptedKey element'961 962 try:963 encrKeyNode = encrKeyNodes[0]964 except:965 # Shared key encryption used - leave out for the moment966 raise DecryptionError, 'This implementation can only handle ' + \967 'wrapped key encryption'968 969 970 # Check encryption method971 keyEncrMethodNode = getElements(encrKeyNode, 'EncryptionMethod')[0]972 keyAlgorithm = keyEncrMethodNode.getAttributeNode("Algorithm").value973 if keyAlgorithm != _ENCRYPTION.KT_RSA_1_5:974 raise DecryptionError, \975 'Encryption algorithm for wrapped key is "%s", expecting "%s"' % \976 (keyAlgorithm, _ENCRYPTION.KT_RSA_1_5)977 978 979 if self.__chkSecurityTokRef and self.__signingCertFilePath:980 981 # Check input cert. against SecurityTokenReference982 securityTokRefXPath = '/ds:KeyInfo/wsse:SecurityTokenReference'983 securityTokRefNode = xpath.Evaluate(securityTokRefXPath,984 contextNode=encrKeyNode,985 context=ctxt)986 # TODO: Look for ds:X509* elements to check against X.509 cert987 # input988 989 990 # Look for cipher data for wrapped key991 keyCiphDataNode = getElements(encrKeyNode, 'CipherData')[0]992 keyCiphValNode = getElements(keyCiphDataNode, 'CipherValue')[0]993 994 keyCiphVal = str(keyCiphValNode.childNodes[0].nodeValue)995 encryptedKey = base64.decodestring(keyCiphVal)996 997 # Read RSA Private key in order to decrypt wrapped key998 priKeyFile = BIO.File(open(self.__signingPriKeyFilePath))999 pwdCallback = lambda *ar, **kw: self.__signingPriKeyPwd1000 priKey = RSA.load_key_bio(priKeyFile, callback=pwdCallback)1001 1002 sharedKey = priKey.private_decrypt(encryptedKey, RSA.pkcs1_padding)1003 1004 1005 # Check list of data elements that have been encrypted1006 for dataRefNode in refListNode.childNodes:1007 1008 # Get the URI for the reference1009 dataRefURI = dataRefNode.getAttributeNode('URI').value1010 if dataRefURI[0] != "#":1011 raise VerifyError, \1012 "Expecting # identifier for DataReference URI \"%s\"" % \1013 dataRefURI1014 1015 # XPath reference - need to check for wsu namespace qualified?1016 #encrNodeXPath = '//*[@wsu:Id="%s"]' % dataRefURI[1:]1017 encrNodeXPath = '//*[@Id="%s"]' % dataRefURI[1:]1018 encrNode = xpath.Evaluate(encrNodeXPath,1019 contextNode=parsedSOAP.dom,1020 context=ctxt)[0]1021 1022 dataEncrMethodNode = getElements(encrNode, 'EncryptionMethod')[0]1023 dataAlgorithm = \1024 dataEncrMethodNode.getAttributeNode("Algorithm").value1025 try:1026 # Match algorithm name to Crypto module1027 CryptoAlg = self.cryptoAlg[dataAlgorithm]1028 1029 except KeyError:1030 raise DecryptionError, \1031 'Encryption algorithm for data is "%s", supported algorithms are:\n "%s"' % \1032 (keyAlgorithm, "\n".join(self.cryptoAlg.keys()))1033 1034 # Get Data1035 dataCiphDataNode = getElements(encrNode, 'CipherData')[0]1036 dataCiphValNode = getElements(dataCiphDataNode, 'CipherValue')[0]1037 1038 dataCiphVal = str(dataCiphValNode.childNodes[0].nodeValue)1039 encryptedData = base64.decodestring(dataCiphVal)1040 1041 alg = CryptoAlg['module'].new(sharedKey, CryptoAlg['mode'])1042 decryptedData = alg.decrypt(encryptedData)1043 1044 # Strip prefix - assume is block size1045 decryptedData = decryptedData[CryptoAlg['blockSize']:]1046 1047 # Strip any padding suffix - Last byte should be number of padding1048 # bytes1049 # (http://www.w3.org/TR/xmlenc-core/#sec-Alg-Block)1050 lastChar = decryptedData[-1]1051 nPad = ord(lastChar)1052 1053 # Sanity check - there may be no padding at all - the last byte1054 # being the end of the encrypted XML?1055 #1056 # TODO: are there better sanity checks than this?!1057 if nPad < CryptoAlg['blockSize'] and nPad > 0 and \1058 lastChar != '\n' and lastChar != '>':1059 1060 # Follow http://www.w3.org/TR/xmlenc-core/#sec-Alg-Block -1061 # last byte gives number of padding bytes1062 decryptedData = decryptedData[:-nPad]1063 1064 1065 # Parse the encrypted data - inherit from Reader as a fudge to1066 # enable relevant namespaces to be added prior to parse1067 processorNss.update({'xsi': SCHEMA.XSI3, 'ns1': 'urn:ZSI:examples'})1068 class _Reader(Reader):1069 def initState(self, ownerDoc=None):1070 Reader.initState(self, ownerDoc=ownerDoc)1071 self._namespaces.update(processorNss)1072 1073 rdr = _Reader()1074 dataNode = rdr.fromString(decryptedData, ownerDoc=parsedSOAP.dom)1075 1076 # Add decrypted element to parent and remove encrypted one1077 parentNode = encrNode._get_parentNode()1078 parentNode.appendChild(dataNode)1079 parentNode.removeChild(encrNode)1080 1081 from xml.dom.ext import ReleaseNode1082 ReleaseNode(encrNode)1083 1084 # Ensure body_root attribute is up to date in case it was1085 # previously encrypted1086 parsedSOAP.body_root = parsedSOAP.body.childNodes[0]1087 #print decryptedData1088 #import pdb;pdb.set_trace()1089 1090 1091 1092 def getElements(node, nameList):1093 '''DOM Helper function for getting child elements from a given node'''1094 # Avoid sub-string matches1095 nameList = isinstance(nameList, basestring) and [nameList] or nameList1096 return [n for n in node.childNodes if str(n.localName) in nameList]1097 1098 1099 def getChildNodes(node, nodeList=None):1100 if nodeList is None:1101 nodeList = [node]1102 return _getChildNodes(node, nodeList)1103 1104 def _getChildNodes(node, nodeList):1105 1106 if node.attributes is not None:1107 nodeList += node.attributes.values()1108 nodeList += node.childNodes1109 for childNode in node.childNodes:1110 _getChildNodes(childNode, nodeList)1111 return nodeList -
TI12-security/trunk/python/ndg.security.common/ndg/security/common/wssecurity/signaturehandler/etree.py
r5063 r5357 1 1 """WS-Security digital signature handler for ElementTree XML package 2 2 3 NERC Data 3 NERC DataGrid Project 4 4 """ 5 5 __author__ = "P J Kershaw" … … 8 8 __license__ = "BSD - see LICENSE file in top-level directory" 9 9 __contact__ = "Philip.Kershaw@stfc.ac.uk" 10 __revision__ = '$Id: $' 11 10 __revision__ = '$Id$' 11 import base64 12 import os 12 13 import re 13 14 … … 15 16 from sha import sha 16 17 from M2Crypto import X509, BIO, RSA 17 import base64 18 from StringIO import StringIO 19 20 from ZSI.wstools.Namespaces import DSIG, SOAP 18 21 19 22 from elementtree import ElementTree, ElementC14N 20 from StringIO import StringIO21 22 # Conditional import as this is required for the encryption23 # handler24 try:25 # For shared key encryption26 from Crypto.Cipher import AES, DES327 except:28 from warnings import warn29 warn('Crypto.Cipher not available: EncryptionHandler disabled!',30 RuntimeWarning)31 class AES:32 MODE_ECB = None33 MODE_CBC = None34 35 class DES3:36 MODE_CBC = None37 38 import os39 40 import ZSI41 from ZSI.wstools.Namespaces import DSIG, WSA200403, \42 SOAP, SCHEMA # last included for xsi43 44 from ZSI.TC import ElementDeclaration,TypeDefinition45 from ZSI.generate.pyclass import pyclass_type46 47 from ZSI.wstools.Utility import DOMException48 from ZSI.wstools.Utility import NamespaceError, MessageInterface, ElementProxy49 50 # Canonicalization51 from ZSI.wstools.c14n import Canonicalize52 53 from xml.dom import Node54 from xml.xpath.Context import Context55 from xml import xpath56 57 # Enable settings from a config file58 from ndg.security.common.wssecurity import WSSecurityConfig59 60 from ndg.security.common.wssecurity.signaturehandler import _WSU, OASIS, \61 BaseSignatureHandler62 23 63 24 # Check SoapWriter.dom attribute is ElementTreeProxy type 64 25 from ndg.security.common.zsi.elementtreeproxy import ElementTreeProxy 26 27 from ndg.security.common.wssecurity import WSSecurityError 28 from ndg.security.common.wssecurity.signaturehandler import _WSU, OASIS, \ 29 BaseSignatureHandler, NoSignatureFound, \ 30 InvalidSignature, TimestampError, MessageExpired, VerifyError, \ 31 SignatureError 32 65 33 66 34 from ndg.security.common.X509 import X509Cert, X509CertParse, X509CertRead, \ … … 93 61 } 94 62 95 96 63 97 64 def _applySignatureConfirmation(self, wsseElem): … … 138 105 ''' 139 106 # Nb. wsu ns declaration is in the SOAP header elem 140 timestampElem =ElementTree.Element("{%s}%s"%(_WSU.UTILITY,'Timestamp'))107 timestampElem=ElementTree.Element("{%s}%s"%(_WSU.UTILITY,'Timestamp')) 141 108 wsseElem.append(timestampElem) 142 109 … … 159 126 160 127 161 def _verifyTimeStamp(self, parsedSOAP, timestampMustBeSet=False): 128 def _verifyTimeStamp(self, 129 parsedSOAP, 130 timestampMustBeSet=False, 131 createdElemMustBeSet=True, 132 expiresElemMustBeSet=True): 162 133 """Call from verify to check timestamp if found. 163 134 … … 168 139 sender 169 140 @type timestampMustBeSet: bool 170 @param timestampMustBeSet: set to True to raise an exception if no 171 timestamp element is present in the message to be checked""" 172 141 @type timestampMustBeSet: bool 142 @param timestampMustBeSet: if set to True, raise an exception if no 143 timestamp element is found 144 @type createdElemMustBeSet: bool 145 @param createdElemMustBeSet: if True. raise an exception if no 146 <wsu:Created/> element is present 147 @param expiresElemMustBeSet: if True. raise an exception if no 148 <wsu:Expires/> element is present 149 """ 173 150 timestampElems = self._soapEnvElem.findall('.//wsu:Timestamp', 174 151 namespaces=self._processorNSs) … … 193 170 namespaces=self._processorNSs) 194 171 if createdElem is None: 195 raise TimestampError("No 'Created' element found in timestamp") 196 197 # Workaround for fractions of second with datetime module 198 try: 199 createdDateTime,strCreatedSecFraction = createdElem.text.split('.') 200 strCreatedSecFraction = strCreatedSecFraction.split('Z')[0] 201 createdExp = -int(len(strCreatedSecFraction)) 202 createdSecFraction = int(strCreatedSecFraction) * 10 ** createdExp 203 204 except ValueError, e: 205 raise ValueError("Parsing timestamp Created element: %s" % e) 206 207 208 dtCreated = _strptime(createdDateTime, '%Y-%m-%dT%H:%M:%S') 209 dtCreated += timedelta(seconds=createdSecFraction) 210 if dtCreated >= dtNow: 211 raise TimestampError(\ 212 "Timestamp created time %s is equal to or after the current time %s" %\ 213 (dtCreated, dtNow)) 172 "No <wsu:Created/> element found in timestamp" 173 if createdElemMustBeSet: 174 raise TimestampError(msg) 175 else: 176 log.warning(msg) 177 else: 178 # Workaround for fractions of second with datetime module 179 try: 180 createdDateTime, strCreatedSecFraction = \ 181 createdElem.text.split('.') 182 strCreatedSecFraction = strCreatedSecFraction.split('Z')[0] 183 createdExp = -int(len(strCreatedSecFraction)) 184 createdSecFraction = int(strCreatedSecFraction) *10**createdExp 185 186 except ValueError, e: 187 raise ValueError("Parsing timestamp Created element: %s" % e) 188 189 190 dtCreated = _strptime(createdDateTime, '%Y-%m-%dT%H:%M:%S') 191 dtCreated += timedelta(seconds=createdSecFraction) 192 if dtCreated >= dtNow: 193 raise TimestampError("Timestamp created time %s is equal to " 194 "or after the current time %s" % 195 (dtCreated, dtNow)) 214 196 215 197 expiresElem = timestampElem.find("wsu:Expires", 216 198 namespaces=self._processorNSs) 217 199 if expiresElem is None: 218 raise TimestampError("Verifying message - No Expires element " 219 "found in Timestamp") 220 221 try: 222 expiryDateTime, strExpirySecFraction = expiresElem.text.split('.') 223 strExpirySecFraction = strExpirySecFraction.split('Z')[0] 224 expiryExp = -int(len(strExpirySecFraction)) 225 expirySecFraction = int(strExpirySecFraction) * 10 ** expiryExp 226 except ValueError, e: 227 raise ValueError("Parsing timestamp Expires element: %s" % e) 228 229 dtExpiry = _strptime(expiryDateTime, '%Y-%m-%dT%H:%M:%S') 230 dtExpiry += timedelta(seconds=expirySecFraction) 231 if dtExpiry < dtNow: 232 raise TimestampError(\ 233 "Timestamp expiry time %s is before the current time %s" % \ 234 (dtCreated, dtNow)) 235 236 log.debug("Verified timestamp") 237 238 239 #_________________________________________________________________________ 200 msg = "No <wsu:Expires/> element found in Timestamp" 201 if expiresElemMustBeSet: 202 raise TimestampError(msg) 203 else: 204 log.warning(msg) 205 else: 206 try: 207 expiryDateTime, strExpirySecFraction = \ 208 expiresElem.text.split('.') 209 strExpirySecFraction = strExpirySecFraction.split('Z')[0] 210 expiryExp = -int(len(strExpirySecFraction)) 211 expirySecFraction = int(strExpirySecFraction) * 10 ** expiryExp 212 213 except ValueError, e: 214 raise ValueError("Parsing timestamp Expires element: %s" % e) 215 216 dtExpiry = _strptime(expiryDateTime, '%Y-%m-%dT%H:%M:%S') 217 dtExpiry += timedelta(seconds=expirySecFraction) 218 if dtExpiry < dtNow: 219 raise MessageExpired("Message has expired: timestamp expiry " 220 "time %s is before the current time %s" % 221 (dtCreated, dtNow)) 222 223 log.debug("Completed timestamp verification") 224 225 240 226 def sign(self, soapWriter): 241 227 '''Sign the message body and binary security token of a SOAP message … … 697 683 log.debug("Verified certificate chain of trust") 698 684 699 self._verifyTimeStamp(parsedSOAP) 685 self._verifyTimeStamp(parsedSOAP, 686 timestampMustBeSet=self.timestampMustBeSet, 687 createdElemMustBeSet=self.createdElemMustBeSet, 688 expiresElemMustBeSet=self.expiresElemMustBeSet) 700 689 701 690 log.info("Signature OK") -
TI12-security/trunk/python/ndg.security.common/ndg/security/common/wssecurity/signaturehandler/foursuite.py
r5063 r5357 35 35 from Ft.Xml.Domlette import CanonicalPrint 36 36 37 from ndg.security.common.wssecurity.signaturehandler import _ENCRYPTION, \ 38 _WSU, OASIS, BaseSignatureHandler, WSSecurityError, NoSignatureFound, \ 39 InvalidSignature, TimestampError, VerifyError, SignatureError 40 41 # Enable settings from a config file 42 from ndg.security.common.wssecurity import WSSecurityConfig 37 from ndg.security.common.wssecurity import WSSecurityError 38 from ndg.security.common.wssecurity.signaturehandler import _WSU, OASIS, \ 39 BaseSignatureHandler, NoSignatureFound, InvalidSignature, TimestampError, \ 40 MessageExpired, VerifyError, SignatureError 43 41 44 42 from ndg.security.common.X509 import X509Cert, X509CertParse, X509CertRead, \ … … 116 114 117 115 118 def _verifyTimeStamp(self, parsedSOAP, timestampMustBeSet=False): 119 """Call from verify to check timestamp if found. 120 121 TODO: refactor input args - maybe these should by object attributes 116 def _verifyTimeStamp(self, 117 parsedSOAP, 118 processorNss, 119 timestampMustBeSet=False, 120 createdElemMustBeSet=True, 121 expiresElemMustBeSet=True): 122 """Call from verify to check timestamp if found. The WS-Security 1.1 123 specification allows elements to be optional. Hence, the bool flags 124 enable their configuration. The default behaviour is, send a warning 125 if a timestamp is not found but if a timestamp is present raise 126 an exception if the created or the expired elements are missing. 122 127 123 128 @type parsedSOAP: ZSI.parse.ParsedSoap 124 129 @param parsedSOAP: object contain parsed SOAP message received from 125 130 sender 126 @type ctxt: 127 @param ctxt: XPath context object""" 128 129 # TODO: do we need to be more rigorous in terms of handling the 130 # situation where no timestamp is found? 131 131 @type processorNss: dict 132 @param processorNss: namespaces to be used in XPath query to locate 133 timestamp. 134 @type timestampMustBeSet: bool 135 @param timestampMustBeSet: if set to True, raise an exception if no 136 timestamp element is found 137 @type createdElemMustBeSet: bool 138 @param createdElemMustBeSet: if True. raise an exception if no 139 <wsu:Created/> element is present 140 @param expiresElemMustBeSet: if True. raise an exception if no 141 <wsu:Expires/> element is present 142 """ 143 132 144 try: 133 timestamp Node= parsedSOAP.dom.xpath('//wsu:Timestamp',145 timestampElem = parsedSOAP.dom.xpath('//wsu:Timestamp', 134 146 explicitNss=processorNss)[0] 135 except: 147 except IndexError: 148 # Catch TypeError raised from attempt to reference element 0 of 149 # None type 136 150 msg = "Verifying message - No timestamp element found" 137 151 if timestampMustBeSet: … … 144 158 dtNow = datetime.utcnow() 145 159 146 createdNode = timestampNode.getElementsByTagName("wsu:Created") 147 if createdNode is None: 148 raise TimestampError("Verifying message - No Created timestamp " 149 "sub-element found") 150 151 # Workaround for fractions of second 152 try: 153 createdDateTime, createdSecFraction = \ 154 createdNode[0].childNodes[0].nodeValue.split('.') 155 dtCreated = _strptime(createdDateTime, '%Y-%m-%dT%H:%M:%S') 156 createdSeconds = float("0." + createdSecFraction.replace('Z', '')) 157 dtCreated += timedelta(seconds=createdSeconds) 158 159 except ValueError, e: 160 raise TimestampError("Failed to parse timestamp Created element: " 161 "%s" % e) 162 163 if dtCreated >= dtNow: 164 raise TimestampError("Timestamp created time %s is equal to or " 165 "after the current time %s" % \ 166 (dtCreated, dtNow)) 167 168 expiresNode = timestampNode.getElementsByTagName("wsu:Expires") 169 if expiresNode is None: 170 log.warning("Verifying message - No Expires element found in " 171 "Timestamp") 172 return 173 174 try: 175 expiresDateTime, expiresSecFraction = \ 176 expiresNode[0].childNodes[0].nodeValue.split('.') 177 dtExpiry = _strptime(expiresDateTime, '%Y-%m-%dT%H:%M:%S') 178 expirySeconds = float("0." + expiresSecFraction.replace('Z', '')) 179 dtExpiry += timedelta(seconds=expirySeconds) 180 181 except ValueError, e: 182 raise TimestampError("Failed to parse timestamp Expires element: " 183 "%s" % e) 184 185 if dtExpiry < dtNow: 186 raise TimestampError("Timestamp expiry time %s is before the " 187 "current time %s - i.e. the message has " 188 "expired." % (dtExpiry, dtNow)) 160 createdElem = getElements(timestampElem, "Created") 161 if len(createdElem) == 0: 162 msg = ("Verifying message: no <wsu:Created/> timestamp " 163 "sub-element found") 164 if createdElemMustBeSet: 165 raise TimestampError(msg) 166 else: 167 log.warning(msg) 168 else: 169 # Workaround for fractions of second 170 try: 171 createdDateTime, createdSecFraction = \ 172 createdElem[0].childNodes[0].nodeValue.split('.') 173 dtCreated = _strptime(createdDateTime, '%Y-%m-%dT%H:%M:%S') 174 createdSeconds = float("0."+createdSecFraction.replace('Z','')) 175 dtCreated += timedelta(seconds=createdSeconds) 176 177 except ValueError, e: 178 raise TimestampError("Failed to parse timestamp Created " 179 "element: %s" % e) 180 181 if dtCreated >= dtNow: 182 raise TimestampError("Timestamp created time %s is equal to " 183 "or after the current time %s" % 184 (dtCreated, dtNow)) 185 186 expiresElem = getElements(timestampElem, "Expires") 187 if len(expiresElem) == 0: 188 msg = ("Verifying message: no <wsu:Expires/> element found in " 189 "Timestamp") 190 if expiresElemMustBeSet: 191 raise TimeStampError(msg) 192 else: 193 log.warning(warning) 194 else: 195 try: 196 expiresDateTime, expiresSecFraction = \ 197 expiresElem[0].childNodes[0].nodeValue.split('.') 198 dtExpiry = _strptime(expiresDateTime, '%Y-%m-%dT%H:%M:%S') 199 expirySeconds = float("0."+expiresSecFraction.replace('Z', '')) 200 dtExpiry += timedelta(seconds=expirySeconds) 201 202 except ValueError, e: 203 raise TimestampError("Failed to parse timestamp Expires " 204 "element: %s" % e) 205 206 if dtExpiry < dtNow: 207 raise MessageExpired("Message has expired: timestamp expiry " 208 "time %s is before the current time %s." % 209 (dtExpiry, dtNow)) 189 210 190 211 … … 324 345 # Add Reference to body so that it can be included in the signature 325 346 soapWriter.body.setAttributeNS(_WSU.UTILITY, 'Id', "body") 326 # soapWriter.body.setAttributeNS('xmlns:wsu', _WSU.UTILITY)327 328 # Serialize and re-parse prior to reference generation - calculating329 # canonicalization based on soapWriter.dom.node seems to give an330 # error: the order of wsu:Id attribute is not correct331 # try:332 # docNode = Reader().fromString(str(soapWriter))333 # except Exception, e:334 # raise SignatureError("Error parsing SOAP message for signing: %s"%335 # e)336 337 347 338 348 refElems = soapWriter.body.evaluate('//*[@wsu:Id]', … … 354 364 # Canonicalize reference 355 365 inclusiveNsKWs = self.createUnsupressedPrefixKW(self.refC14nKw) 356 # refSubsetList = getChildNodes(refElem)357 # refC14n = Canonicalize(docNode,358 # None,359 # subset=refSubsetList,360 # **inclusiveNsKWs)361 366 refC14n = refElem.canonicalize(algorithm=refC14nAlg, 362 367 **inclusiveNsKWs) … … 404 409 # 405 410 # Canonicalize the signedInfo node 406 # docNode = Reader().fromString(str(soapWriter))407 # ctxt = Context(docNode, processorNss=processorNss)408 # signedInfoElem = xpath.Evaluate('//ds:SignedInfo',409 # contextNode=docNode,410 # context=ctxt)[0]411 #412 # signedInfoSubsetList = getChildNodes(signedInfoElem)413 414 411 signedInfoInclusiveNsKWs = self.createUnsupressedPrefixKW( 415 412 self.signedInfoC14nKw) 416 # c14nSignedInfo = Canonicalize(docNode,417 # None,418 # subset=signedInfoSubsetList,419 # **inclusiveNSKWs)420 413 try: 421 414 signedInfoElem = soapWriter.body.evaluate('//ds:SignedInfo', … … 691 684 caX509Stack=self._caX509Stack) 692 685 693 self._verifyTimeStamp(parsedSOAP) 686 self._verifyTimeStamp(parsedSOAP, 687 processorNss, 688 timestampMustBeSet=self.timestampMustBeSet, 689 createdElemMustBeSet=self.createdElemMustBeSet, 690 expiresElemMustBeSet=self.expiresElemMustBeSet) 694 691 log.info("Signature OK") -
TI12-security/trunk/python/ndg.security.common/ndg/security/common/zsi/attributeauthority/Makefile
r4361 r5357 7 7 # server side code 8 8 # 9 # @copyright (C) 2008 CCLRC & NERC9 # @copyright (C) 2008 STFC 10 10 # 11 11 # @license This software may be distributed under the terms of the Q Public -
TI12-security/trunk/python/ndg.security.common/ndg/security/common/zsi/sessionmanager/Makefile
r4361 r5357 7 7 # server side code 8 8 # 9 # @copyright (C) 2007 CCLRC & NERC9 # @copyright (C) 2007 STFC 10 10 # 11 11 # @license This software may be distributed under the terms of the Q Public -
TI12-security/trunk/python/ndg.security.server/ndg/security/server/share/Makefile
r4752 r5357 6 6 # Generate SysV init scripts from ndg-aa template 7 7 # 8 # @copyright (C) 2007 CCLRC & NERC8 # @copyright (C) 2007 STFC 9 9 # 10 10 # @license This software may be distributed under the terms of the Q Public -
TI12-security/trunk/python/ndg.security.server/ndg/security/server/wsgi/authz.py
r5355 r5357 137 137 policyCfg = PEPFilter._filterKeywords(local_conf, 'policy.') 138 138 self.policyFilePath = policyCfg['filePath'] 139 self.policy = Policy.Parse(policyCfg['filePath'])139 policy = Policy.Parse(policyCfg['filePath']) 140 140 141 141 # Initialise the Policy Information Point to None. This object is 142 142 # created and set later. See AuthorizationMiddleware. 143 self.pdp = PDP( self.policy, None)143 self.pdp = PDP(policy, None) 144 144 145 145 self.sessionKey = local_conf.get('sessionKey', … … 250 250 path 251 251 """ 252 matchingTargets = [target for target in self.p olicy.targets252 matchingTargets = [target for target in self.pdp.policy.targets 253 253 if target.regEx.match(resourceURI) is not None] 254 254 return matchingTargets … … 302 302 303 303 return filteredConf 304 305 def _getPDP(self): 306 if self._pdp is None: 307 raise TypeError("PDP object has not been initialised") 308 return self._pdp 309 310 def _setPDP(self, pdp): 311 if not isinstance(pdp, (PDP, None.__class__)): 312 raise TypeError("Expecting %s or None type for pdp; got %r" % 313 (PDP.__class__.__name__, pdp)) 314 self._pdp = pdp 315 316 pdp = property(fget=_getPDP, 317 fset=_setPDP, 318 doc="Policy Decision Point object makes access control " 319 "decisions on behalf of the PEP") 304 320 305 321 … … 409 425 attrCert = credential.get('attCert') 410 426 if attrCert is not None: 411 log.debug("PIPMiddleware._getAttributeCertificate: existing"412 " Attribute Certificate cached in Credential Wallet for"413 " user session [%s]",427 log.debug("PIPMiddleware._getAttributeCertificate: retrieved " 428 "existing Attribute Certificate cached in Credential " 429 "Wallet for user session [%s]", 414 430 self.session['username']) 415 431 … … 474 490 pepInterceptFunc = pepFilter.multiHandlerInterceptFactory() 475 491 492 # Slot in the Policy Information Point in the WSGI stack at this point 493 # so that it can take a copy of the beaker session object from environ 494 # ahead of the PDP make a request to it for an Attribute Certificate 495 # retrieval 476 496 pipApp = PIPMiddleware(pepFilter, 477 497 global_conf, … … 480 500 pepFilter.pdp.pip = pipApp 481 501 482 # app = MultiHandler(pepFilter)483 502 app = MultiHandler(pipApp) 484 503 -
TI12-security/trunk/python/ndg.security.server/ndg/security/server/wsgi/ssl.py
r5343 r5357 263 263 # Check certificate Distinguished Name via 264 264 # ClientCertVerificationInterface object 265 return self._ clientCertVerify(x509Cert)266 265 return self._verifyClientCert(x509Cert) 266 -
TI12-security/trunk/python/ndg.security.server/ndg/security/server/zsi/attributeauthority/Makefile
r4386 r5357 7 7 # server side code 8 8 # 9 # @copyright (C) 2007 CCLRC & NERC9 # @copyright (C) 2007 STFC 10 10 # 11 11 # @license This software may be distributed under the terms of the Q Public -
TI12-security/trunk/python/ndg.security.server/ndg/security/server/zsi/sessionmanager/Makefile
r4386 r5357 7 7 # server side code 8 8 # 9 # @copyright (C) 2007 CCLRC & NERC9 # @copyright (C) 2007 STFC 10 10 # 11 11 # @license This software may be distributed under the terms of the Q Public -
TI12-security/trunk/python/ndg.security.server/ndg/security/server/zsi/twisted/attributeauthority/Makefile
r4390 r5357 7 7 # server side code 8 8 # 9 # @copyright (C) 2007 CCLRC & NERC9 # @copyright (C) 2007 STFC 10 10 # 11 11 # @license This software may be distributed under the terms of the Q Public -
TI12-security/trunk/python/ndg.security.server/ndg/security/server/zsi/twisted/sessionmanager/Makefile
r4390 r5357 7 7 # server side code 8 8 # 9 # @copyright (C) 2007 CCLRC & NERC9 # @copyright (C) 2007 STFC 10 10 # 11 11 # @license This software may be distributed under the terms of the Q Public -
TI12-security/trunk/python/ndg.security.test/ndg/security/test/config/sessionmanager/userx509certauthn.py
r5154 r5357 45 45 ''' 46 46 47 # Check password by executing a trial load of the private key 47 # Check password by executing a trial load of the private key - Nb. 48 # unicode is not supported 48 49 try: 49 50 RSA.load_key_string(self.userPriKey, 50 callback=lambda *ar, **kw: passphrase)51 callback=lambda *ar, **kw: str(passphrase)) 51 52 except RSA.RSAError, e: 52 53 raise AuthNServiceInvalidCredentials(e) -
TI12-security/trunk/python/ndg.security.test/ndg/security/test/unit/attCert/ac.xml
r5290 r5357 9 9 <userId>/O=NDG/OU=BADC/CN=pjkershaw</userId> 10 10 <validity> 11 <notBefore>2009 0 5 14 11 18 00</notBefore>12 <notAfter>2009 0 5 14 19 18 00</notAfter>11 <notBefore>2009 06 05 08 04 29</notBefore> 12 <notAfter>2009 06 05 16 04 29</notAfter> 13 13 </validity> 14 14 <attributes> … … 27 27 <provenance>original</provenance> 28 28 </acInfo> 29 <ds:Signature><ds:SignedInfo><ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"><ec:InclusiveNamespaces PrefixList="ds"></ec:InclusiveNamespaces></ds:CanonicalizationMethod><ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"></ds:SignatureMethod><ds:Reference URI=""><ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"></ds:Transform><ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"><ec:InclusiveNamespaces PrefixList="xmlns"></ec:InclusiveNamespaces></ds:Transform></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></ds:DigestMethod><ds:DigestValue> sPx/VQ+W/6ImQpzpVyqNN4SRi94=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>lvYk1Pjb7lDkkkZBrF8PhlT5krZWReU1l6X1vjDUPPkthV2ASVwj3NHCLJIFwrp3PCD8TLUERbhN30 7MBO/IhQ9AM2qHZDScc+QxJ1iCdXgIGiV5Bb98Gyex3ZxBE+Kj7HlD2NCwzLswKUTEHfdstMlWWI 31 FuDlalmEJ2pyGdyi+DaA7b1g2rUxapJneqvH94SNQCaS7RqiThy5JyI/u43cMeZXgxCeGzDUZmWo 32 UQb4jbLe+oQn7PhYV15jf3MwksLqfiLYO9iyjKZhfXQpn+mOW5dY3+00NTb5v6wup+f3l7uGNHkU 33 U+AfrdIAp52UPM15kWd9aYjQQgdwDegzAz/mBA==</ds:SignatureValue><ds:KeyInfo><ds:X509Data><ds:X509Certificate>MIICazCCAdSgAwIBAgICAQEwDQYJKoZIhvcNAQEEBQAwLzEMMAoGA1UEChMDTkRH29 <ds:Signature><ds:SignedInfo><ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"><ec:InclusiveNamespaces PrefixList="ds"></ec:InclusiveNamespaces></ds:CanonicalizationMethod><ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"></ds:SignatureMethod><ds:Reference URI=""><ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"></ds:Transform><ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"><ec:InclusiveNamespaces PrefixList="xmlns"></ec:InclusiveNamespaces></ds:Transform></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></ds:DigestMethod><ds:DigestValue>7rpCVUcm4cDwkpIzPBthqpqj38Q=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>FPniax9JlVxqLYlj9b0aEYbPFMyTvz8ok0Ci3tU+s0GV5HIiA0c7eXj9sU1JVy5jxyYYMtzcU9V6 30 eszrVX4TL7Twk9GL3xCWk+7VttUAAT3AAdtYisjD2O6wCHl6H/K/orV5EKERb+raB4v6ji++wOi1 31 WJFjtV/QTz8Ld/kaQFdJV2cl3DFlO3XvL+TkBMayrjI4UXuwZk+AlhYtvDUKrcSL36JNpJBIhvgu 32 RLgdwgDwdQKoLkg/tNhYNaqDiAs6N2F17jhYzisfLmwZfTs8vefT9nrvz0lTbpEB1/geiAl9nWdB 33 zKGTsPpYlOG9wdEL6BBhAD2RsDSr4pb+ng1tjA==</ds:SignatureValue><ds:KeyInfo><ds:X509Data><ds:X509Certificate>MIICazCCAdSgAwIBAgICAQEwDQYJKoZIhvcNAQEEBQAwLzEMMAoGA1UEChMDTkRH 34 34 MQ0wCwYDVQQLEwRCQURDMRAwDgYDVQQDEwdUZXN0IENBMB4XDTA4MTIxNjE1MTE0 35 35 OFoXDTEzMTIxNTE1MTE0OFowLDEMMAoGA1UEChMDTkRHMQ0wCwYDVQQLEwRCQURD -
TI12-security/trunk/python/ndg.security.test/ndg/security/test/unit/wsgi/ssl/test_ssl.py
r5343 r5357 19 19 from paste.deploy import loadapp 20 20 from ndg.security.test.unit import BaseTestCase 21 from ndg.security.common.X509 import X509Cert 21 22 22 23 class TestSSLClientAuthNMiddleware(BaseTestCase): … … 51 52 52 53 53 class SSLClientAuthNTestCase( unittest.TestCase):54 class SSLClientAuthNTestCase(BaseTestCase): 54 55 55 56 def __init__(self, *args, **kwargs): … … 58 59 self.app = paste.fixture.TestApp(wsgiapp) 59 60 60 unittest.TestCase.__init__(self, *args, **kwargs)61 BaseTestCase.__init__(self, *args, **kwargs) 61 62 62 63 … … 73 74 74 75 def test03ClientCertSet(self): 75 thisDir = os.dirname(__file__) 76 sslClientCertFilePath = os.path.join(BaseTestCase.configDirEnvVarName, 77 'pki', 78 'test.crt') 79 sslClientCert = str(X509.Read(sslClientCertFilePath)) 76 thisDir = os.path.dirname(__file__) 77 sslClientCertFilePath = os.path.join( 78 os.environ[BaseTestCase.configDirEnvVarName], 79 'pki', 80 'test.crt') 81 sslClientCert = X509Cert.Read(sslClientCertFilePath).toString() 80 82 extra_environ = {'HTTPS':'1', 'SSL_CLIENT_CERT': sslClientCert} 81 83 response = self.app.get('/secured/uri', -
TI12-security/trunk/python/ndg.security.test/ndg/security/test/unit/wssecurity/dom/client/Makefile
r3108 r5357 7 7 # server side code 8 8 # 9 # @copyright (C) 2007 CCLRC & NERC9 # @copyright (C) 2007 STFC 10 10 # 11 11 # @license This software may be distributed under the terms of the Q Public -
TI12-security/trunk/python/ndg.security.test/ndg/security/test/unit/wssecurity/dom/server/Makefile
r3123 r5357 7 7 # server side code 8 8 # 9 # @copyright (C) 2007 CCLRC & NERC9 # @copyright (C) 2007 STFC 10 10 # 11 11 # @license This software may be distributed under the terms of the Q Public -
TI12-security/trunk/python/ndg.security.test/ndg/security/test/unit/wssecurity/foursuite/client/Makefile
r5053 r5357 7 7 # server side code 8 8 # 9 # @copyright (C) 2007 CCLRC & NERC9 # @copyright (C) 2007 STFC 10 10 # 11 11 # @license This software may be distributed under the terms of the Q Public -
TI12-security/trunk/python/ndg.security.test/ndg/security/test/unit/wssecurity/foursuite/server/Makefile
r5053 r5357 7 7 # server side code 8 8 # 9 # @copyright (C) 2007 CCLRC & NERC9 # @copyright (C) 2007 STFC 10 10 # 11 11 # @license This software may be distributed under the terms of the Q Public
Note: See TracChangeset
for help on using the changeset viewer.