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

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

Give more info about time expiry in AttCert?.isValidTime error message.

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