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

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

* Working version for mapped certificates *

ndgSessionClient.py:

  • renamed dict to argDict to avoid clash with existing arg var.
  • added code for handling ext attCert list and trusted host list files.
  • Changed so that --connect and --req-autho can be specified together so that a connect call is

concatenated with a call to request authorisation.

attAuthorityIOtest.py: unit tests for AttAuthorityIO classes.
attCertTest.py: unit tests for AttCert?.

AttAuthorityIO.py:

attAuthority_services_server.py: update and fixes to GetTrustedHostInfo? WS stub.

AttAuthority?.py:

AttCert?.py: !! important fix - added nonzero method so that test on AttCert? instance
yields True e.g. if attCert: ...

Session.py:

  • SessionMgr?.readProperties - only strip white space from XML data if it's string type -

elementtree sets content to None if an empty tag is present in the XML it's reading.

CredWallet?.py: changes to WS calls - use AttAuthorityIO classes - AuthorisationReq/?
AuthorisationResp? + TrustedHostInfoReq/TrustedHostInfoResp?.

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