source: TI12-security/trunk/python/NDG/AttCert.py @ 660

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/python/NDG/AttCert.py@660
Revision 660, 26.0 KB checked in by pjkersha, 14 years ago (diff)

AttAuthorityServer?.py and SessionMgrServer?.py:
Overridden SOAPRequestHandler.do_POST so that wsdl path may be set explicitly. - Overcomes
problem with port in WSDL set to Apache ProxyPass? setting (see httpd.conf).

ndgData.html, ndgUserRegistration.html:
Changed style sheet font size and improved appearance

security.py:
Fixes for inter-site SessionMgr? calls.

AttAuthority?.py, attAuthorityProperties.xml, AttCert?.py:
Modified so that AttCert?.setValidityTime can set a notBefore time of BEFORE utcnow. This has
been changed because of problems when checking validity times between machines that weren't time
synchronised.

The properties file includes a new parameter to allow an offset to made for the notBefore
'attCertNotBeforeOff'

SessionMgrIO.py:
include 'setExtAttCertList' parameter in AuthorisationReq?.

Session.py:
Fixed code for SessionMgr? WS forwarding in SessionMgr?.reqAuthorisation().

SessionClient?.py:
Fixed bug in reqAuthorisation response.
CredWallet?.py:
Fixes for inter-site authorisation tests.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1"""NDG Attribute Certificate (Authentication -or Access- Token)
2
3NERC Data Grid Project
4
5P J Kershaw 05/04/05
6
7Copyright (C) 2005 CCLRC & NERC
8
9This software may be distributed under the terms of the Q Public License,
10version 1.0 or later."""
11
12cvsID = '$Id$'
13
14import types
15import os
16import re
17
18# XML Parsing
19import cElementTree as ElementTree
20
21# Time module for use with validity times
22from time import strftime
23from time import strptime
24from datetime import datetime
25from datetime import timedelta
26
27# XML signature module based on xmlsec and libxml2
28from XMLSecDoc import *
29
30from X509 import X500DN
31from X509 import X500DNError
32
33
34class AttCertError(Exception):
35   
36    """Exception handling for NDG Attribute Certificate class."""
37   
38    def __init__(self, msg):
39        self.__msg = msg
40         
41    def __str__(self):
42        return self.__msg
43   
44
45class AttCert(dict, XMLSecDoc):
46
47    """NDG Attribute Certificate (Authentication or Access Token)."""
48
49    # Attribute Certificate file version
50    __version = "1.0"
51
52    # Provenance of certificate may be original or mapped from another
53    # certificate
54    __provenance = ('original', 'mapped')
55
56
57    # Nb. pass XMLSecDoc keyword arguments in xmlSecDocKeys dictionary
58    def __init__(self, filePath=None, lifeTime=-1, **xmlSecDocKeys):
59
60        """Initialisation - Attribute Certificate file path may be specified.
61        Also, holder and issuer details and signing authority key and
62        certificate."""
63
64        # Base class initialisation
65        dict.__init__(self)
66        XMLSecDoc.__init__(self, **xmlSecDocKeys)
67
68
69        if filePath is not None:
70            if not isinstance(filePath, basestring):
71                raise AttCertError("Input file path must be a valid string")
72           
73            self.filePath = filePath
74
75
76        # Data dictionary version of xml
77        #
78        # Nb. RoleSet is an empty list - it will be filled role dictionary
79        # items [{'role': {'name': '<Name>'}}, ... ]
80        self.__dat = {
81           
82            "version":            AttCert.__version,
83            "holder":             '',
84            "issuer":             '',
85            "issuerName":         '',
86            "issuerSerialNumber": 0,
87            "validity":           {"notBefore": '', "notAfter": ''},
88            "attributes":         {"roleSet": []},
89            "provenance":         ''
90        }
91
92        # Holder and issuer X500DN objects - instanciated in read method
93        self.__issuerDN = None
94        self.__holderDN = None
95
96
97        # Check for input certificate life time interval - if not set default
98        # to one day
99        if lifeTime is -1:
100            self.__lifeTime = 28800 # 8 hours
101        else:
102            self.__lifeTime = lifeTime
103       
104        self.__dtNotBefore = None
105        self.__dtNotAfter = None
106
107
108
109       
110    def __repr__(self):
111        """Override default behaviour to return internal dictionary content"""
112        return str(self.__dat)
113
114               
115    def __delitem__(self, key):
116
117        "Attribute Certificate keys cannot be removed"
118       
119        raise AttCertError('Keys cannot be deleted from ' + \
120                           self.__class__.__name__)
121
122
123    def __getitem__(self, key):
124
125        self.__class__.__name__ + """ behaves as data dictionary of Attribute
126        Certificate properties
127
128        Nb. also possible to apply keys belonging validity and attributes
129        sub dictionaries
130        """
131       
132        # Check input key
133        if self.__dat.has_key(key):
134
135            # key recognised
136            return self.__dat[key]               
137
138        elif self.__dat['validity'].has_key(key):
139
140            # Allow indexing via validity keys - a shorthand way of referencing
141            # for convenience
142            return self.__dat['validity'][key]
143
144        elif self.__dat['attributes'].has_key(key):
145
146            # Allow indexing via attirbutes keys - a shorthand way of
147            # referencing for convenience
148            return self.__dat['attributes'][key]
149
150        else:
151            # key not recognised as a short or long name version
152            raise AttCertError('Key "%s" not recognised for %s' % \
153                               (key, self.__class__.__name__))
154
155
156    def __setitem__(self, key, item):
157       
158        self.__class__.__name__ + """ behaves as data dictionary of Attribute
159        Certificate properties
160
161        Nb. also possible to apply keys belonging validity and attributes
162        sub dictionaries
163        """
164
165        # Check input key
166        if self.__dat.has_key(key):
167
168            # key recognised - check if setting provenance
169            if key is "provenance" and not self.isValidProvenance(item):
170                raise AttCertError("Provenance must be set to \"" + \
171                            "\" or \"".join(AttCert.__provenance) + "\"")
172           
173            self.__dat[key] = item
174
175        elif self.__dat['attributes'].has_key(key):
176
177            # Allow indexing via acInfo keys - a shorthand way of referencing
178            # for convenience
179            return self.__dat['attributes'][key]
180
181        elif self.__dat['validity'].has_key(key):
182               
183            # Prevent setting of notBefore/notAfter - restrict to method
184            # setValidityTime
185            raise AttCertError(\
186                "Use setValidityTime method to set notBefore/notAfter times")
187           
188        else:
189            # key not recognised as a short or long name version
190            raise AttCertError('Key "%s" not recognised for %s' % \
191                               (key, self.__class__.__name__))
192       
193
194    def __eq__(self, attCert):
195        """Return true if all elements are the same"""
196       
197        try:
198            return min([self.__dat[key] == attCert[key] \
199                       for key in self.__dat.keys()])
200        except:
201            return False
202       
203
204    def clear(self):
205        raise AttCertError("Data cannot be cleared from " + self.__class__.__name__)
206
207   
208    def copy(self):
209
210        import copy
211        return copy.copy(self)
212
213   
214    def keys(self):
215        return self.__dat.keys()
216
217    def items(self):
218        return self.__dat.items()
219
220    def values(self):
221        return self.__dat.values()
222
223    def has_key(self, key):
224        return self.__dat.has_key(key)
225
226    # 'in' operator
227    def __contains__(self, key):
228        return key in self.__tags
229
230
231    def getExptdVersion(self):
232        """Return the Attribute Certificate XML expected version."""
233        return AttCert.__version
234
235
236    #
237    # Get/Set methods
238    #
239    # Nb. it's also possible to access the data dictionary parameters via
240    # __setitem__ and __getitem__ standard dictionary methods
241    #
242    def setVersion(self, version):
243        """Set the version number to be written to file."""       
244        self.__dat['version'] = version
245   
246    def getVersion(self):
247        """Get version number as set in file."""
248        return self.__dat['version']
249   
250    def setHolder(self, holder):
251        """Set holder's Distinguished Name string."""
252        self.__dat['holder'] = holder
253   
254    def getHolder(self):
255        """Get holder's Distinguished Name string."""
256        return self.__dat['holder']
257
258    def getHolderDN(self):
259         """Get the holder's Distinguished Name as an X500DN instance"""
260         return self.__holderDN
261   
262    def setIssuer(self, issuer):
263        """Set issuer's Distinguished Name."""
264        self.__dat['issuer'] = issuer
265   
266    def getIssuer(self):
267        """Get the issuer's Distinguished Name string"""
268        return self.__dat['issuer']
269
270    def getIssuerDN(self):
271         """Get the issuer's Distinguished Name as an X500DN instance"""
272         return self.__issuerDN
273       
274    def setIssuerName(self, issuerName):
275        """Set the name of the issuer"""
276        self.__dat['issuerName'] = issuerName
277   
278    def getIssuerName(self):
279        """Get the name of the issuer"""
280        return self.__dat['issuerName']
281   
282    def setIssuerSerialNumber(self, serialNumber):
283        """Set the issuer serial number"""
284        self.__dat['issuerSerialNumber'] = serialNumber
285   
286    def getIssuerSerialNumber(self):
287        """Get the issuer serial number"""
288        return self.__dat['issuerSerialNumber']
289
290
291    # Nb. no setValidityNotBefore/setValidityNotAfter methods - use
292    # setValidityTime instead.
293   
294    def getValidityNotBefore(self, asDatetime=False):
295        """Get the validity Not Before date/time string
296
297        Set asDatetime to True to return as a datetime type
298        Nb. time may not have been set - if so it will be set to None"""
299        if asDatetime is True:
300            return self.__dtNotBefore
301        else:
302            return self.__dat['validity']['notBefore']
303
304
305    def getValidityNotAfter(self, asDatetime=False):
306        """Get the validity Not After date/time string
307
308        Set asDatetime to True to return as a datetime type
309        Nb. time may not have been set - if so it will be set to None"""
310        if asDatetime is True:
311            return self.__dtNotAfter
312        else:
313            return self.__dat['validity']['notAfter']
314
315   
316    def getRoleSet(self):
317        """Get the roleSet as a list of role dictionaries."""
318        return self.__dat['attributes']['roleSet']
319
320
321    def getRoles(self):
322        """Return roles as a list"""
323        try:
324            return [i.values()[0].values()[0] \
325                    for i in self.__dat['attributes']['roleSet']]
326        except:
327            return []
328
329       
330    def setProvenance(self, provenance):
331        """Set the provenance for the certificate: 'original' or 'mapped'."""
332
333        if not self.isValidProvenance(provenance):
334            raise AttCertError("Provenance must be set to \"" + \
335                               "\" or \"".join(AttCert.__provenance) + "\"")
336       
337        self.__dat['provenance'] = provenance
338
339   
340    def getProvenance(self):
341        """Get the provenance for the certificate."""
342        return self.__dat['provenance']
343   
344
345    def isValidProvenance(self, provenance=None):
346        """Check provenance is set correctly - to 'original'/'mapped'.
347
348        If no provenance argument is provided, test against the setting in
349        the current instance.
350        """
351       
352        if not provenance:
353            provenance = self.__dat['provenance']
354
355        return provenance in AttCert.__provenance
356       
357
358    def isOriginal(self):
359        """Check for original provenance."""
360        return self.__dat['provenance'] == 'original'
361
362
363    def isMapped(self):
364        """Check for mapped provenance."""
365        return self.__dat['provenance'] == 'mapped'
366
367
368    def addRoles(self, roleName):
369        """Add new roles to the roleSet in attributes."""
370
371        if isinstance(roleName, basestring):
372            roleName = [roleName]
373           
374        self.__dat['attributes']['roleSet'].extend(\
375                                [{'role': {'name': i}} for i in roleName])
376
377
378    def parse(self, xmlTxt, rtnRootElem=False):
379
380        """Parse an Attribute Certificate content contained in string input
381
382        xmlTxt:     Attribute Certificate XML content as string"""
383       
384        rootElem = ElementTree.XML(xmlTxt)
385
386        # Call generic ElementTree parser
387        self.__parse(rootElem)
388
389
390        # Call base class parser method to initialise libxml2 objects for
391        # signature validation
392        try:
393            XMLSecDoc.parse(self, xmlTxt)
394
395        except Exception, e:
396            raise AttCertError("Attribute Certificate: %s" % e)
397
398        if rtnRootElem:
399            return rootElem
400
401       
402    def read(self, filePath=None):
403
404        """Read Attribute Certificate
405
406        filePath:   file to be read, if omitted __filePath member variable is
407                    used instead"""
408
409        if filePath:
410            if not isinstance(filePath, basestring):
411                raise AttCertError("Input file path must be a string.")
412
413            self.filePath = filePath
414        else:
415            filePath = self.filePath
416
417
418        try:   
419            tree = ElementTree.parse(filePath)
420            rootElem = tree.getroot()
421        except Exception, e:
422            raise AttCertError("Attribute Certificate: %s" % e)
423       
424        # Call generic ElementTree parser
425        self.__parse(rootElem)
426
427
428        # Call base class read method to initialise libxml2 objects for
429        # signature validation
430        try:
431            XMLSecDoc.read(self)
432
433        except Exception, e:
434            raise AttCertError("Attribute Certificate: %s" % e)
435
436
437
438       
439    def __parse(self, rootElem):
440
441        """Private XML parsing method accepts a ElementTree.Element type
442        as input
443
444        rootElem:       ElementTree.Element type
445        """
446       
447        # Extract from acInfo tag
448        acInfoElem = rootElem.find("acInfo")
449       
450        if not acInfoElem:
451            raise AttCertError("<acInfo> tag not found in \"%s\"" % \
452                               self.filePath)
453
454
455        # Copy all acInfo tags into dictionary
456        for elem in acInfoElem:
457       
458            if not self.__dat.has_key(elem.tag):
459                raise AttCertError(self.filePath + "\": <" + \
460                                   elem.tag + "> not recognised.")
461
462            # Make sure not to copy validity and attributes tags - handle
463            # these separately below
464            if not elem.getchildren():
465                self.__dat[elem.tag] = elem.text
466
467        # Convert issuer and holder into X500DN instances
468        try:
469            self.__issuerDN = X500DN(dn=self.__dat['issuer'])
470
471        except X500DNError, x500dnErr:
472            raise AttCertError("Issuer DN: %s" % x500dnErr)
473
474
475        try:
476            self.__holderDN = X500DN(dn=self.__dat['holder'])
477
478        except X500DNError, x500dnErr:
479            raise AttCertError("Holder DN: %s" % x500dnErr)
480       
481                                 
482        # Extract validity and attributes subsets
483        self.__dat['validity']['notBefore'] = \
484                                rootElem.findtext("acInfo/validity/notBefore")
485       
486        if self.__dat['validity']['notBefore'] is None:
487            raise AttCertError("<notBefore> tag not found in \"%s\"" % \
488                               self.filePath)
489
490        # Update datetime object equivalent
491        self.__dtNotBefore = self.timeStr2datetime(\
492                                        self.__dat['validity']['notBefore'])
493
494       
495        self.__dat['validity']['notAfter'] = \
496                                rootElem.findtext("acInfo/validity/notAfter")
497       
498        if self.__dat['validity']['notAfter'] is None:
499            raise AttCertError("<notAfter> tag not found in \"%s\"" %
500                               self.filePath)
501
502
503        # Update datetime object equivalent
504        self.__dtNotAfter = self.timeStr2datetime(\
505                                        self.__dat['validity']['notAfter'])
506
507
508        # set up role list
509        roleElem = acInfoElem.findall("attributes/roleSet/role/name")
510        if roleElem is None:
511            raise AttCertError("<role> tag not found in \"%s\"" % \
512                               self.filePath)
513       
514        self.__dat['attributes']['roleSet'] = \
515                                [{'role': {'name': i.text}} for i in roleElem]
516                   
517       
518        if not self.isValidVersion():           
519            raise AttCertError('Attribute Certificate version is ' + \
520                               self.__dat['version'] + ' but version ' + \
521                               AttCert.__version + ' expected')
522
523
524
525
526    def createXML(self):
527
528        """Create XML for Attribute Token from current data settings and
529        return as a string.  The XML created is MINUS the digital signature.
530        To obtain the signed version, run the sign method and pass the attCert
531        object reference into str()
532
533        Implementation of virtual method defined in XMLSecDoc base class"""
534
535        # Nb.
536        # * this method is used by AttCert.read()
537        # * Signing by Attribute Authority is separate - see AttCert.sign()
538       
539
540        # Check for valid provenance
541        if not self.isValidProvenance():
542            raise AttCertError("Provenance must be set to \"" + \
543                               "\" or \"".join(AttCert.__provenance) + "\"")
544
545       
546        # Create string of all XML content       
547        xmlTxt = \
548"""<attributeCertificate>
549    <acInfo>
550        <version>""" + self.__dat['version'] + """</version>
551        <holder>""" + self.__dat['holder'] + """</holder>
552        <issuer>""" + self.__dat['issuer'] + """</issuer>
553        <issuerName>""" + self.__dat['issuerName'] + """</issuerName>
554        <issuerSerialNumber>""" + str(self.__dat['issuerSerialNumber']) +\
555            """</issuerSerialNumber>
556        <validity>
557            <notBefore>""" + self.__dat['validity']['notBefore'] + \
558            """</notBefore>
559            <notAfter>""" + self.__dat['validity']['notAfter'] + \
560            """</notAfter>
561        </validity>
562        <attributes>
563            <roleSet>
564                """ + \
565        "".join(["""<role>
566                    <name>""" + i['role']['name'] + """</name>
567                </role>
568            """ for i in self.__dat['attributes']['roleSet']]) +\
569            """</roleSet>
570        </attributes>
571        <provenance>""" + self.__dat['provenance'] + """</provenance>
572    </acInfo>
573</attributeCertificate>"""
574
575
576        # Return XML file content as a string
577        return xmlTxt
578
579
580
581
582    def setValidityTime(self,
583                        dtNotBefore=None, 
584                        dtNotAfter=None, 
585                        lifeTime=None,
586                        notBeforeOffset=None):
587
588        """Set the notBefore and notAfter times which determine the window for
589        which the Attribute Certificate is valid
590
591        Nb. use UTC time.  lifeTime and notBeforeOffset are in seconds
592        """
593
594        if dtNotBefore is not None:
595            if not isinstance(dtNotBefore, datetime):
596                raise AttCertError(\
597                                "Input not before time must be datetime type")
598           
599            self.__dtNotBefore = dtNotBefore
600           
601        else:
602            # Use current UTC +/- offset
603            self.__dtNotBefore = datetime.utcnow()
604           
605            if notBeforeOffset is not None:
606                self.__dtNotBefore += timedelta(seconds=notBeforeOffset)
607           
608
609
610        if dtNotAfter is not None:
611            if not isinstance(dtNotAfter, datetime):
612                raise AttCertError(\
613                                "Input not after time must be datetime type")
614
615            # Use input Not After time to calculate a new lifetime setting
616            dtDeltaLifeTime = dtNotAfter - self.__dtNotBefore
617            if dtDeltaLifeTime < timedelta(0):
618                raise AttCertError("Input Not After time is invalid %s" % \
619                                   str(dtNotAfter))
620
621            self.__lifeTime = dtDeltaLifeTime.days*86400 + \
622                              dtDeltaLifeTime.seconds
623
624            self.__dtNotAfter = dtNotAfter
625           
626        else:
627            # Check for input certificate life time interval
628            if lifeTime is not None:
629                self.__lifeTime = lifeTime
630               
631            try:
632                # Make a time delta object from the lifetime expressed in
633                # seconds
634                dtDeltaLifeTime = timedelta(seconds=self.__lifeTime)
635            except Exception, e:
636                raise AttCertError("Invalid Certificate lifetime set %.3f" % \
637                                   self.__lifeTime)
638           
639            # Add certificate lifetime to calculate not after time
640            self.__dtNotAfter = self.__dtNotBefore + dtDeltaLifeTime
641
642       
643        self.__dat['validity']['notBefore'] = \
644                                    self.datetime2timeStr(self.__dtNotBefore)
645       
646        self.__dat['validity']['notAfter'] = \
647                                    self.datetime2timeStr(self.__dtNotAfter)
648
649
650
651
652    def datetime2timeStr(self, dtVal):
653
654        """Convert a datetime object to a notBefore/notAfter time string"""
655
656        if not isinstance(dtVal, datetime):
657            raise AttCertError(\
658                        "Invalid datetime object for conversion to string")
659       
660        # Convert from 1-12 to 0-11 month format used in XML file
661        #lDateTime = list(dtVal.utctimetuple()[0:6])
662
663        #lDateTime[1] -= 1
664
665        # Format as a single string with no commas or brackets
666        #return ''.join(re.findall('[0-9 ]', str(lDateTime)))
667
668        # Use 1-12 format
669        # P J Kershaw 09/06/05
670        return dtVal.strftime("%Y %m %d %H %M %S")
671
672   
673
674    def timeStr2datetime(self, sTime):
675
676        """Convert a notBefore/notAfter time string to a datetime object"""
677
678        # Convert from 0-11 to 1-12 month format used by datetime()
679        try:
680            #lTime = [int(i) for i in sTime.split()]
681            lTime = strptime(sTime, "%Y %m %d %H %M %S")
682           
683            # Use 1-12 format
684            # P J Kershaw 09/05/05
685            #lTime[1] += 1
686       
687            return datetime(lTime[0], lTime[1], lTime[2],
688                            lTime[3], lTime[4], lTime[5])
689        except Exception, e:
690            raise AttCertError(\
691                "Error converting time string into datetime object: %s" % e)
692       
693
694
695
696    def isValidTime(self):
697
698        """Check Attribute Certificate for expiry"""
699
700        if not isinstance(self.__dtNotBefore, datetime):
701            raise AttCertError("Not Before datetime is not set")
702
703        if not isinstance(self.__dtNotAfter, datetime):
704            raise AttCertError("Not After datetime is not set")
705       
706        dtNow = datetime.utcnow()
707       
708        # Testing only
709        #
710        # P J Kershaw 02/03/06
711        #notBefore = self.__dtNotBefore
712        #notAfter = self.__dtNotAfter
713        #print "Valid Time? = %d" % (dtNow > notBefore and dtNow < notAfter)
714        return dtNow > self.__dtNotBefore and dtNow < self.__dtNotAfter
715
716
717       
718       
719    def isValidVersion(self):
720
721        """Check Attribute Certificate XML file version"""
722        return self.__dat['version'] == AttCert.__version
723
724
725
726
727    def isValid(self,
728                raiseExcep=False,
729                chkTime=True,
730                chkVersion=True,
731                chkProvenance=True,
732                chkSig=True,
733                **xmlSecDocKeys):
734
735        """Check Attribute Certificate is valid:
736
737        - Time validity is OK
738        - XML file version is OK
739        - valid provenance setting
740        - Signature is valid.
741
742        chkTime:                set to True to do time validity check (default
743                                is True)
744
745        chkVersion:             set to True to Attribute Certificate file
746                                version (default is True)
747
748        chkProvenance:          set to True to check provenance value is valid
749                                (default is True)
750
751        chkSig:                 set to True to check digital signature - for
752                                this certFilePathList must contain the root
753                                certificate of the X.509 certificate used to
754                                sign the AttCert.  Alternatively,
755                                certFilePathList can be set via __init__
756                                (default chkSig value is True)
757                               
758        raiseExcep:             set to true to raise an exception if invalid
759                                instead of returning False.  Default is to set
760                                this flag to False.
761
762        Also accepts keyword arguments corresponding to XMLSecDoc.isValidSig:
763       
764        xmlTxt:                 string buffer containing the text from the XML
765                                file to be checked.  If omitted, the
766                                filePath argument is used instead.
767
768        filePath:               file path to XML file to be checked.  This
769                                argument is used if no xmlTxt was provided.
770                                If filePath itself is omitted the file set
771                                by self.__filePath is read instead.
772
773        certFilePathList:       list of files paths must contain certificate of
774                                trusted authority used to validate the
775                                signature.  If set, it is copied
776                                into self.__certFilePathList.  If omitted
777                                self.__certFilePathList is used unchanged.                             
778        """
779
780        # Carry out checks in turn - Specific exception error messages are
781        # raised if flag is set
782        if chkTime and not self.isValidTime():
783            if raiseExcep:
784                raise AttCertError("Attribute Certificate time is invalid")
785           
786            return False
787
788       
789        if chkVersion and not self.isValidVersion():
790            if raiseExcep:
791                raise AttCertError('Attribute Certificate version is ' + \
792                                   self.__dat['version'] + ' but version ' + \
793                                   AttCert.__version + ' expected')
794           
795            return False
796
797
798        if chkProvenance and not self.isValidProvenance():
799            if raiseExcep:
800                raise AttCertError(\
801                    "Attribute Certificate Provenance must be set to \"" + \
802                    "\" or \"".join(AttCert.__provenance) + "\"")
803               
804            return False
805
806
807        # Handle exception from XMLSecDocc.isValidSig() regardless of
808        # raiseExcep flag setting
809        try:           
810            if chkSig and not self.isValidSig(**xmlSecDocKeys):
811                if raiseExcep:
812                    raise AttCertError(\
813                                "Attribute Certificate signature is invalid")
814               
815                return False
816       
817        except Exception, e:
818            raise AttCertError(str(e))
819       
820
821        # All tests passed
822        return True
823
824
825
826#_____________________________________________________________________________
827# Alternative AttCert constructors
828#
829def AttCertRead(filePath):
830    """Create a new attribute certificate read in from a file"""
831   
832    attCert = AttCert(filePath)
833    attCert.read()
834   
835    return attCert
836
837
838
839
840def AttCertParse(attCertTxt):
841    """Create a new attribute certificate from string of file content"""
842   
843    attCert = AttCert()
844    attCert.parse(attCertTxt)
845   
846    return attCert
Note: See TracBrowser for help on using the repository browser.