Changeset 1964
- Timestamp:
- 08/01/07 09:21:13 (14 years ago)
- Location:
- TI12-security/trunk/python/ndg.security.common/ndg/security/common
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
TI12-security/trunk/python/ndg.security.common/ndg/security/common/AttCert.py
r1642 r1964 1 """NDG Attribute Certificate (Auth entication -or Access- Token)1 """NDG Attribute Certificate (Authorisation -or Access- Token) 2 2 3 3 NERC Data Grid Project 4 4 5 P J Kershaw 05/04/056 7 Copyright (C) 2006 CCLRC & NERC8 9 This software may be distributed under the terms of the Q Public License, 10 version 1.0 or later."""5 @author P J Kershaw 05/04/05 6 7 @copyright (C) 2006 CCLRC & NERC 8 9 @license This software may be distributed under the terms of the Q Public 10 License, version 1.0 or later.""" 11 11 12 12 reposID = '$Id$' … … 20 20 21 21 # Time module for use with validity times 22 from time import strftime 23 from time import strptime 24 from datetime import datetime 25 from datetime import timedelta 22 from time import strftime, strptime 23 from datetime import datetime, timedelta 26 24 27 25 # XML signature module based on xmlsec and libxml2 28 from XMLSec Doc import *26 from XMLSec import XMLSecDoc 29 27 30 28 from X509 import X500DN … … 32 30 33 31 34 class AttCertError(Exception): 35 32 class AttCertError(Exception): 36 33 """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 34 35 36 #_____________________________________________________________________________ 37 class _MetaAttCert(type): 38 """Enable AttCert to have read only class variables e.g. 39 40 print AttCert.mappedProvenance is allowed but, 41 42 AttCert.mappedProvenance = None 43 44 ... raises - AttributeError: can't set attribute""" 45 46 #_________________________________________________________________________ 47 def __getVersion(cls): 48 '''Version of THIS format for the certificate''' 49 return '1.0' 50 51 version = property(fget=__getVersion, 52 doc="Version of the certificate format") 53 54 #_________________________________________________________________________ 55 def __getMappedProvenance(cls): 56 '''Text for mapped provenance setting of certificate''' 57 return 'mapped' 58 59 mappedProvenance = property(fget=__getMappedProvenance, 60 doc="Text constant indicating cert has mapped roles from another") 61 62 #_________________________________________________________________________ 63 def __getOriginalProvenance(cls): 64 '''Text for original provenance setting of certificate''' 65 return 'original' 66 67 origProvenance = property(fget=__getOriginalProvenance, 68 doc="Text constant indicating cert has original and not mapped roles") 69 70 71 #_____________________________________________________________________________ 45 72 class AttCert(dict, XMLSecDoc): 46 47 """NDG Attribute Certificate (Authentication or Access Token).""" 48 49 # Attribute Certificate file version 50 __version = "1.0" 73 """NDG Attribute Certificate (Authorisation or Access Token).""" 74 75 __metaclass__ = _MetaAttCert 51 76 52 77 # Provenance of certificate may be original or mapped from another 53 78 # certificate 54 mappedProvenance = 'mapped'55 origProvenance = 'original'56 79 __provenance = (origProvenance, mappedProvenance) 57 80 58 81 59 # Nb. pass XMLSecDoc keyword arguments in xmlSecDocKeys dictionary 60 def __init__(self, filePath=None, lifeTime=-1, **xmlSecDocKeys): 61 82 #_________________________________________________________________________ 83 def __init__(self, lifeTime=28800, **xmlSecDocKw): 62 84 """Initialisation - Attribute Certificate file path may be specified. 63 85 Also, holder and issuer details and signing authority key and 64 certificate.""" 86 certificate. 87 88 @param lifeTime: set the lifetime for the certificate in seconds. 89 Defaults to 8 hours. 90 @param **xmlSecDocKw: see XMLSec.XMLSec class for an explanation. 91 Keywords include, filePath for the cert. for reading/writing and 92 cert./private key settings for digital signature and verification.""" 65 93 66 94 # Base class initialisation 67 95 dict.__init__(self) 68 XMLSecDoc.__init__(self, **xmlSecDocKeys) 69 70 71 if filePath is not None: 72 if not isinstance(filePath, basestring): 73 raise AttCertError("Input file path must be a valid string") 74 75 self.filePath = filePath 76 96 XMLSecDoc.__init__(self, **xmlSecDocKw) 77 97 78 98 # Data dictionary version of xml … … 82 102 self.__dat = { 83 103 84 "version": AttCert. __version,104 "version": AttCert.version, 85 105 "holder": '', 86 106 "issuer": '', … … 97 117 98 118 99 # Check for input certificate life time interval - if not set default 100 # to one day 101 if lifeTime is -1: 102 self.__lifeTime = 28800 # 8 hours 103 else: 104 self.__lifeTime = lifeTime 119 # Certificate life time interval in seconds 120 self.__lifeTime = lifeTime 105 121 106 122 self.__dtNotBefore = None 107 123 self.__dtNotAfter = None 108 124 109 125 126 #_________________________________________________________________________ 110 127 def __repr__(self): 111 128 """Override default behaviour to return internal dictionary content""" … … 113 130 114 131 132 #_________________________________________________________________________ 115 133 def __delitem__(self, key): 116 134 "Attribute Certificate keys cannot be removed" 117 135 118 raise AttCertError('Keys cannot be deleted from ' + \ 119 self.__class__.__name__) 120 121 136 raise AttCertError, 'Keys cannot be deleted from ' + \ 137 self.__class__.__name__ 138 139 140 #_________________________________________________________________________ 122 141 def __getitem__(self, key): 123 142 self.__class__.__name__ + """ behaves as data dictionary of Attribute … … 148 167 else: 149 168 # key not recognised as a short or long name version 150 raise AttCertError('Key "%s" not recognised for %s' % \ 151 (key, self.__class__.__name__)) 152 153 169 raise AttCertError, 'Key "%s" not recognised for %s' % \ 170 (key, self.__class__.__name__) 171 172 173 #_________________________________________________________________________ 154 174 def __setitem__(self, key, item): 155 175 self.__class__.__name__ + """ behaves as data dictionary of Attribute … … 165 185 # key recognised - check if setting provenance 166 186 if key is "provenance" and not self.isValidProvenance(item): 167 raise AttCertError ("Provenance must be set to \"" + \168 "\" or \"".join(AttCert.__provenance) + "\"" )187 raise AttCertError, "Provenance must be set to \"" + \ 188 "\" or \"".join(AttCert.__provenance) + "\"" 169 189 170 190 self.__dat[key] = item … … 177 197 178 198 elif self.__dat['validity'].has_key(key): 179 180 199 # Prevent setting of notBefore/notAfter - restrict to method 181 200 # setValidityTime 182 raise AttCertError(\ 183 "Use setValidityTime method to set notBefore/notAfter times") 184 201 raise AttCertError, \ 202 "Use setValidityTime method to set notBefore/notAfter times" 185 203 else: 186 204 # key not recognised as a short or long name version 187 raise AttCertError('Key "%s" not recognised for %s' % \ 188 (key, self.__class__.__name__)) 189 190 205 raise AttCertError, 'Key "%s" not recognised for %s' % \ 206 (key, self.__class__.__name__) 207 208 209 #_________________________________________________________________________ 191 210 def __eq__(self, attCert): 192 211 """Return true if all elements are the same""" … … 199 218 200 219 220 #_________________________________________________________________________ 201 221 def __nonzero__(self): 202 222 """Ensure if <attCertInstance> test yields True""" … … 204 224 205 225 226 #_________________________________________________________________________ 206 227 def clear(self): 207 raise AttCertError("Data cannot be cleared from " + \ 208 self.__class__.__name__) 209 210 228 raise AttCertError, "Data cannot be cleared from " + \ 229 self.__class__.__name__ 230 231 232 #_________________________________________________________________________ 211 233 def copy(self): 212 234 … … 215 237 216 238 239 #_________________________________________________________________________ 217 240 def keys(self): 218 241 return self.__dat.keys() 219 242 243 #_________________________________________________________________________ 220 244 def items(self): 221 245 return self.__dat.items() 222 246 247 #_________________________________________________________________________ 223 248 def values(self): 224 249 return self.__dat.values() 225 250 251 #_________________________________________________________________________ 226 252 def has_key(self, key): 227 253 return self.__dat.has_key(key) 228 254 229 255 # 'in' operator 256 #_________________________________________________________________________ 230 257 def __contains__(self, key): 231 258 return key in self.__dat 232 233 234 def getExptdVersion(self):235 """Return the Attribute Certificate XML expected version."""236 return AttCert.__version237 259 238 260 … … 243 265 # __setitem__ and __getitem__ standard dictionary methods 244 266 # 267 #_________________________________________________________________________ 245 268 def setVersion(self, version): 246 269 """Set the version number to be written to file.""" 247 270 self.__dat['version'] = version 248 271 272 #_________________________________________________________________________ 249 273 def getVersion(self): 250 274 """Get version number as set in file.""" 251 275 return self.__dat['version'] 252 276 277 #_________________________________________________________________________ 253 278 def setHolder(self, holder): 254 279 """Set holder's Distinguished Name string.""" 255 280 self.__dat['holder'] = holder 256 281 282 #_________________________________________________________________________ 257 283 def getHolder(self): 258 284 """Get holder's Distinguished Name string.""" 259 285 return self.__dat['holder'] 260 286 287 #_________________________________________________________________________ 261 288 def getHolderDN(self): 262 289 """Get the holder's Distinguished Name as an X500DN instance""" 263 290 return self.__holderDN 264 291 292 #_________________________________________________________________________ 265 293 def setIssuer(self, issuer): 266 294 """Set issuer's Distinguished Name.""" 267 295 self.__dat['issuer'] = issuer 268 296 297 #_________________________________________________________________________ 269 298 def getIssuer(self): 270 299 """Get the issuer's Distinguished Name string""" 271 300 return self.__dat['issuer'] 272 301 302 #_________________________________________________________________________ 273 303 def getIssuerDN(self): 274 304 """Get the issuer's Distinguished Name as an X500DN instance""" 275 305 return self.__issuerDN 276 306 307 #_________________________________________________________________________ 277 308 def setIssuerName(self, issuerName): 278 309 """Set the name of the issuer""" 279 310 self.__dat['issuerName'] = issuerName 280 311 312 #_________________________________________________________________________ 281 313 def getIssuerName(self): 282 """ Getthe name of the issuer"""314 """@return the name of the issuer""" 283 315 return self.__dat['issuerName'] 284 316 317 #_________________________________________________________________________ 285 318 def setIssuerSerialNumber(self, serialNumber): 286 """ Setthe issuer serial number"""319 """@param serialNumber: the issuer serial number""" 287 320 self.__dat['issuerSerialNumber'] = serialNumber 288 321 322 #_________________________________________________________________________ 289 323 def getIssuerSerialNumber(self): 290 """ Getthe issuer serial number"""324 """@return the issuer serial number""" 291 325 return self.__dat['issuerSerialNumber'] 292 326 … … 295 329 # setValidityTime instead. 296 330 331 #_________________________________________________________________________ 297 332 def getValidityNotBefore(self, asDatetime=False): 298 333 """Get the validity Not Before date/time string 299 334 300 Set asDatetime to True to return as a datetime type 301 Nb. time may not have been set - if so it will be set to None""" 335 @param asDatetime: boolean to True to return as a datetime type 336 Nb. time may not have been set - if so it will be set to None 337 338 @return the not before time as string or datetime type - see above""" 302 339 if asDatetime is True: 303 340 return self.__dtNotBefore … … 306 343 307 344 345 #_________________________________________________________________________ 308 346 def getValidityNotAfter(self, asDatetime=False): 309 347 """Get the validity Not After date/time string 310 348 311 Set asDatetime to True to return as a datetime type 312 Nb. time may not have been set - if so it will be set to None""" 349 @param asDatetime: boolean set to True to return as a datetime type 350 Nb. time may not have been set - if so it will be set to None 351 352 @return the not after time as string or datetime type - see above""" 313 353 if asDatetime is True: 314 354 return self.__dtNotAfter … … 317 357 318 358 359 #_________________________________________________________________________ 319 360 def getRoleSet(self): 320 """ Getthe roleSet as a list of role dictionaries."""361 """@return the roleSet as a list of role dictionaries.""" 321 362 return self.__dat['attributes']['roleSet'] 322 363 323 364 365 #_________________________________________________________________________ 324 366 def getRoles(self): 325 """Return roles as a list""" 367 """Return roles as a list 368 369 @return list of roles contained in the certificate""" 370 326 371 try: 327 372 return [i.values()[0].values()[0] \ … … 331 376 332 377 378 #_________________________________________________________________________ 333 379 def setProvenance(self, provenance): 334 """Set the provenance for the certificate: 'original' or 'mapped'.""" 380 """Set the provenance for the certificate: 'original' or 'mapped'. 381 382 @param provenance: string provenance setting""" 335 383 336 384 if not self.isValidProvenance(provenance): 337 raise AttCertError ("Provenance must be set to \"" + \338 "\" or \"".join(AttCert.__provenance) + "\"" )385 raise AttCertError, "Provenance must be set to \"" + \ 386 "\" or \"".join(AttCert.__provenance) + "\"" 339 387 340 388 self.__dat['provenance'] = provenance 341 389 342 390 391 #_________________________________________________________________________ 343 392 def getProvenance(self): 344 """Get the provenance for the certificate.""" 393 """Get the provenance for the certificate. 394 395 @return provenance of certificate mapped or original""" 345 396 return self.__dat['provenance'] 346 397 347 398 399 #_________________________________________________________________________ 348 400 def isValidProvenance(self, provenance=None): 349 401 """Check provenance is set correctly - to 'original'/'mapped'. … … 351 403 If no provenance argument is provided, test against the setting in 352 404 the current instance. 405 406 @param provenance: by default the current provenance setting is 407 checked i.e. self.__dat['provenance']. Set this keyword to override 408 and check against an alternate provenance setting. 409 @return True if certificate has a valid provenance setting 353 410 """ 354 411 … … 359 416 360 417 418 #_________________________________________________________________________ 361 419 def isOriginal(self): 362 """Check for original provenance.""" 420 """Check for original provenance. 421 @return True if certificate has original roles""" 363 422 return self.__dat['provenance'] == self.__class__.origProvenance 364 423 365 424 425 #_________________________________________________________________________ 366 426 def isMapped(self): 367 """Check for mapped provenance.""" 427 """Check for mapped provenance. 428 @return True if certificate contain roles mapped from another""" 368 429 return self.__dat['provenance'] == self.__class__.mappedProvenance 369 430 370 431 432 #_________________________________________________________________________ 371 433 def addRoles(self, roleName): 372 """Add new roles to the roleSet in attributes.""" 434 """Add new roles to the roleSet in attributes. 435 436 @param roleName: role name or list of role names to add to certificate 437 """ 373 438 374 439 if isinstance(roleName, basestring): … … 379 444 380 445 446 #_________________________________________________________________________ 381 447 def parse(self, xmlTxt, rtnRootElem=False): 382 383 448 """Parse an Attribute Certificate content contained in string input 384 449 385 xmlTxt: Attribute Certificate XML content as string""" 450 @param xmlTxt: Attribute Certificate XML content as string 451 @param rtnRootElem: boolean set to True to return the ElementTree 452 root element 453 @return root element if rtnRootElem keyword is set to True""" 386 454 387 455 rootElem = ElementTree.XML(xmlTxt) … … 391 459 392 460 393 # Call base class parser method to initialise libxml2objects for461 # Call base class parser method to initialise DOM objects for 394 462 # signature validation 395 463 try: … … 397 465 398 466 except Exception, e: 399 raise AttCertError ("Attribute Certificate: %s" % e)467 raise AttCertError, "Attribute Certificate: %s" % e 400 468 401 469 if rtnRootElem: … … 403 471 404 472 405 def read(self, filePath=None):406 407 """Read Attribute Certificate408 409 filePath: file to be read, if omitted __filePath member variable is410 473 #_________________________________________________________________________ 474 def read(self, filePath=None, **xmlSecDocKw): 475 """Read an Attribute Certificate from file 476 477 @param filePath: file to be read, if omitted XMLSecDoc.__filePath 478 member variable is used instead""" 411 479 412 480 if filePath: 413 if not isinstance(filePath, basestring):414 raise AttCertError("Input file path must be a string.")415 416 481 self.filePath = filePath 417 else:418 filePath = self.filePath419 420 482 421 483 try: 422 tree = ElementTree.parse( filePath)484 tree = ElementTree.parse(self.filePath) 423 485 rootElem = tree.getroot() 424 486 except Exception, e: 425 raise AttCertError ("Attribute Certificate: %s" % e)487 raise AttCertError, "Attribute Certificate: %s" % e 426 488 427 489 # Call generic ElementTree parser 428 490 self.__parse(rootElem) 429 430 491 431 492 # Call base class read method to initialise libxml2 objects for 432 493 # signature validation 433 494 try: 434 XMLSecDoc.read(self )495 XMLSecDoc.read(self, **xmlSecDocKw) 435 496 436 497 except Exception, e: 437 raise AttCertError("Attribute Certificate: %s" % e) 438 439 440 441 498 raise AttCertError, "Attribute Certificate: %s" % e 499 500 501 #_________________________________________________________________________ 442 502 def __parse(self, rootElem): 443 444 503 """Private XML parsing method accepts a ElementTree.Element type 445 504 as input 446 505 447 rootElem:ElementTree.Element type506 @param rootElem: root element of doc - ElementTree.Element type 448 507 """ 449 508 … … 452 511 453 512 if not acInfoElem: 454 raise AttCertError ("<acInfo> tag not found in \"%s\"" % \455 self.filePath )513 raise AttCertError, "<acInfo> tag not found in \"%s\"" % \ 514 self.filePath 456 515 457 516 458 517 # Copy all acInfo tags into dictionary 459 518 for elem in acInfoElem: 460 461 if not self.__dat.has_key(elem.tag): 462 raise AttCertError(self.filePath + "\": <" + \ 463 elem.tag + "> not recognised.") 519 if elem.tag not in self.__dat: 520 raise AttCertError, '%s: "<%s>" not recognised.' % \ 521 (self.filePath, elem.tag) 464 522 465 523 # Make sure not to copy validity and attributes tags - handle … … 473 531 474 532 except X500DNError, x500dnErr: 475 raise AttCertError ("Issuer DN: %s" % x500dnErr)533 raise AttCertError, "Issuer DN: %s" % x500dnErr 476 534 477 535 … … 480 538 481 539 except X500DNError, x500dnErr: 482 raise AttCertError ("Holder DN: %s" % x500dnErr)540 raise AttCertError, "Holder DN: %s" % x500dnErr 483 541 484 542 … … 488 546 489 547 if self.__dat['validity']['notBefore'] is None: 490 raise AttCertError ("<notBefore> tag not found in \"%s\"" % \491 self.filePath )548 raise AttCertError, "<notBefore> tag not found in \"%s\"" % \ 549 self.filePath 492 550 493 551 # Update datetime object equivalent … … 500 558 501 559 if self.__dat['validity']['notAfter'] is None: 502 raise AttCertError("<notAfter> tag not found in \"%s\"" % 503 self.filePath) 504 560 raise AttCertError, '<notAfter> tag not found in "%s"' % \ 561 self.filePath 505 562 506 563 # Update datetime object equivalent … … 508 565 self.__dat['validity']['notAfter']) 509 566 510 511 567 # set up role list 512 568 roleElem = acInfoElem.findall("attributes/roleSet/role/name") 513 569 if roleElem is None: 514 raise AttCertError ("<role> tag not found in \"%s\"" % \515 self.filePath )570 raise AttCertError, "<role> tag not found in \"%s\"" % \ 571 self.filePath 516 572 517 573 self.__dat['attributes']['roleSet'] = \ … … 520 576 521 577 if not self.isValidVersion(): 522 raise AttCertError ('Attribute Certificate version is ' + \578 raise AttCertError, 'Attribute Certificate version is ' + \ 523 579 self.__dat['version'] + ' but version ' + \ 524 AttCert.__version + ' expected') 525 526 527 528 580 AttCert.version + ' expected' 581 582 583 #_________________________________________________________________________ 529 584 def createXML(self): 530 531 585 """Create XML for Attribute Token from current data settings and 532 586 return as a string. The XML created is MINUS the digital signature. 533 To obtain the signed version, run the sign method and pass the attCert 534 object reference into str() 535 536 Implementation of virtual method defined in XMLSecDoc base class""" 587 To obtain the signed version, run the applyEnvelopedSignature method 588 (inherited from XMLSecDoc) and pass the attCert object reference into 589 str() 590 591 @return xmlTxt: formatted XML for certificate as a string""" 537 592 538 593 # Nb. … … 543 598 # Check for valid provenance 544 599 if not self.isValidProvenance(): 545 raise AttCertError ("Provenance must be set to \"" + \546 "\" or \"".join(AttCert.__provenance) + "\"" )600 raise AttCertError, "Provenance must be set to \"" + \ 601 "\" or \"".join(AttCert.__provenance) + "\"" 547 602 548 603 549 604 # Create string of all XML content 550 xmlTxt = \ 551 """<attributeCertificate> 605 xmlTxt = """<attributeCertificate> 552 606 <acInfo> 553 607 <version>""" + self.__dat['version'] + """</version> … … 565 619 <attributes> 566 620 <roleSet> 567 """ +\568 "".join(["""<role>621 """ + "".join([\ 622 """ <role> 569 623 <name>""" + i['role']['name'] + """</name> 570 624 </role> 571 """ for i in self.__dat['attributes']['roleSet']]) + \625 """ for i in self.__dat['attributes']['roleSet']]) + \ 572 626 """</roleSet> 573 627 </attributes> … … 576 630 </attributeCertificate>""" 577 631 578 579 632 # Return XML file content as a string 580 633 return xmlTxt 581 634 582 635 583 584 636 #_________________________________________________________________________ 585 637 def setValidityTime(self, 586 638 dtNotBefore=None, … … 588 640 lifeTime=None, 589 641 notBeforeOffset=None): 590 591 642 """Set the notBefore and notAfter times which determine the window for 592 which the Attribute Certificate is valid 643 which the Attribute Certificate is valid. These times are set as 644 datetime types and also the correct string format settings are made 645 ready for output. 593 646 594 647 Nb. use UTC time. lifeTime and notBeforeOffset are in seconds 648 649 @param dtNotBefore: not before time as datetime type. If omitted, 650 it defaults to the current time 651 652 @param dtNotAfter: not after time as datetime type. Defaults to 653 self.__dtNotBefore + self.__lifetime. If dtNotAfter is set it will 654 reset self.__lifetime to self.__dtNotAfter - self.dtNotBefore 655 656 @param lifetime: lifetime for certificate in seconds i.e. not after 657 time - not before time. If dtNotAfter is set then this keyword will 658 be ignored. 659 660 @param notBeforeOffset: skew the not before time by some offset. This 661 is useful in cases where system clocks are not correctly synchronized 662 between different hosts. Set a negative value to skew the offset 663 backward in time. 595 664 """ 596 665 597 666 if dtNotBefore is not None: 598 667 if not isinstance(dtNotBefore, datetime): 599 raise AttCertError (\600 "Input not before time must be datetime type" )668 raise AttCertError, \ 669 "Input not before time must be datetime type" 601 670 602 671 self.__dtNotBefore = dtNotBefore … … 610 679 611 680 612 613 681 if dtNotAfter is not None: 614 682 if not isinstance(dtNotAfter, datetime): 615 raise AttCertError (\616 "Input not after time must be datetime type" )683 raise AttCertError, \ 684 "Input not after time must be datetime type" 617 685 618 686 # Use input Not After time to calculate a new lifetime setting 619 687 dtDeltaLifeTime = dtNotAfter - self.__dtNotBefore 620 688 if dtDeltaLifeTime < timedelta(0): 621 raise AttCertError ("Input Not After time is invalid %s" % \622 str(dtNotAfter) )689 raise AttCertError, "Input Not After time is invalid %s" % \ 690 str(dtNotAfter) 623 691 624 692 self.__lifeTime = dtDeltaLifeTime.days*86400 + \ … … 637 705 dtDeltaLifeTime = timedelta(seconds=self.__lifeTime) 638 706 except Exception, e: 639 raise AttCertError ("Invalid Certificate lifetime set %.3f" %\640 self.__lifeTime )707 raise AttCertError, "Invalid Certificate lifetime set %.3f" %\ 708 self.__lifeTime 641 709 642 710 # Add certificate lifetime to calculate not after time … … 653 721 654 722 723 #_________________________________________________________________________ 655 724 def datetime2timeStr(self, dtVal): 656 657 """Convert a datetime object to a notBefore/notAfter time string""" 725 """Convert a datetime object to a notBefore/notAfter time string 726 727 @param dtVal: input datetime 728 @return datetime converted into correct string format for AttCert""" 658 729 659 730 if not isinstance(dtVal, datetime): 660 raise AttCertError (\661 "Invalid datetime object for conversion to string" )731 raise AttCertError, \ 732 "Invalid datetime object for conversion to string" 662 733 663 734 # Convert from 1-12 to 0-11 month format used in XML file … … 675 746 676 747 748 #_________________________________________________________________________ 677 749 def timeStr2datetime(self, sTime): 678 679 """Convert a notBefore/notAfter time string to a datetime object""" 680 681 # Convert from 0-11 to 1-12 month format used by datetime() 750 """Convert a notBefore/notAfter time string to a datetime object 751 752 @param sTime: time in string format as used by AttCert 753 @return datetime type equivalent of string input""" 754 682 755 try: 683 #lTime = [int(i) for i in sTime.split()]684 756 lTime = strptime(sTime, "%Y %m %d %H %M %S") 685 686 # Use 1-12 format 687 # P J Kershaw 09/05/05 688 #lTime[1] += 1 689 690 return datetime(lTime[0], lTime[1], lTime[2], 691 lTime[3], lTime[4], lTime[5]) 757 return datetime(*lTime[0:6]) 758 692 759 except Exception, e: 693 raise AttCertError(\ 694 "Error converting time string into datetime object: %s" % e) 695 696 697 698 760 raise AttCertError, \ 761 "Error converting time string into datetime object: %s" % e 762 763 764 765 766 #_________________________________________________________________________ 699 767 def isValidTime(self, dtNow=None, raiseExcep=False): 700 768 """Check Attribute Certificate for expiry. Set raiseExcep to True 701 769 to raise an exception with a message indicating the nature of the 702 time error""" 770 time error 771 772 @param dtNow: the time to test against in datetime format. This time 773 must be within the range of the not before and not after times in 774 order for the certificate to be valid. Defaults to the current 775 system time 776 777 @param raiseExcep: boolean set to True to raise an exception if the 778 time is invalid. Defaults to False in which case no exception is 779 raised if the time is invalid, instead False is returned 780 781 @return boolean True if time is valid, False if invalid. Also see 782 raiseExcep keyword above.""" 703 783 704 784 if not isinstance(self.__dtNotBefore, datetime): 705 raise AttCertError ("Not Before datetime is not set")785 raise AttCertError, "Not Before datetime is not set" 706 786 707 787 if not isinstance(self.__dtNotAfter, datetime): 708 raise AttCertError ("Not After datetime is not set")788 raise AttCertError, "Not After datetime is not set" 709 789 710 790 if dtNow is None: … … 735 815 else: 736 816 return dtNow > self.__dtNotBefore and dtNow < self.__dtNotAfter 737 738 739 740 817 818 819 #_________________________________________________________________________ 741 820 def isValidVersion(self): 742 743 """Check Attribute Certificate XML file version""" 744 return self.__dat['version'] == AttCert.__version 745 746 747 748 821 """Check Attribute Certificate XML file version 822 823 @return boolean True if certificate version matches the expected one, 824 False otherwise. 825 """ 826 return self.__dat['version'] == AttCert.version 827 828 829 #_________________________________________________________________________ 749 830 def isValid(self, 750 831 raiseExcep=False, … … 753 834 chkProvenance=True, 754 835 chkSig=True, 755 **xmlSecDocKeys): 756 836 **xmlSecDocKw): 757 837 """Check Attribute Certificate is valid: 758 838 … … 762 842 - Signature is valid. 763 843 764 chkTime: set to True to do time validity check (default 765 is True) 766 767 chkVersion: set to True to Attribute Certificate file 768 version (default is True) 769 770 chkProvenance: set to True to check provenance value is valid 771 (default is True) 772 773 chkSig: set to True to check digital signature - for 774 this certFilePathList must contain the root 775 certificate of the X.509 certificate used to 776 sign the AttCert. Alternatively, 777 certFilePathList can be set via __init__ 778 (default chkSig value is True) 844 @param chkTime: set to True to do time validity check (default is 845 True) 846 847 @param chkVersion: set to True to Attribute Certificate file 848 version (default is True) 849 850 @param chkProvenanceset to True to check provenance value is valid 851 (default is True) 852 853 @param chkSig: set to True to check digital signature - for 854 this certFilePathList must contain the root certificate of the X.509 855 certificate used to sign the AttCert. Alternatively, certFilePathList 856 can be set via __init__ (default chkSig value is True) 779 857 780 raiseExcep: set to true to raise an exception if invalid 781 instead of returning False. Default is to set 782 this flag to False. 783 784 Also accepts keyword arguments corresponding to XMLSecDoc.isValidSig: 785 786 xmlTxt: string buffer containing the text from the XML 787 file to be checked. If omitted, the 788 filePath argument is used instead. 789 790 filePath: file path to XML file to be checked. This 791 argument is used if no xmlTxt was provided. 792 If filePath itself is omitted the file set 793 by self.__filePath is read instead. 794 795 certFilePathList: list of files paths must contain certificate 796 of trusted authority used to validate the 797 signature. If set, it is copied into 798 self.__certFilePathList. If omitted 799 self.__certFilePathList is used unchanged. 858 @param raiseExcep: set to true to raise an exception if invalid 859 instead of returning False. Default is to set this flag to False. 860 861 @param **xmlSecDocKw: Also accepts keyword arguments corresponding to 862 XMLSecDoc.verifyEnvelopedSignature(). 863 864 @return boolean True if certificate is valid, False otherwise. Also 865 see explanation for raiseExcep keyword. 800 866 """ 801 867 … … 805 871 return False 806 872 807 808 873 if chkVersion and not self.isValidVersion(): 809 874 if raiseExcep: 810 raise AttCertError ('Attribute Certificate version is ' + \875 raise AttCertError, 'Attribute Certificate version is ' + \ 811 876 self.__dat['version'] + ' but version ' + \ 812 AttCert.__version + ' expected') 813 877 AttCert.version + ' expected' 814 878 return False 815 816 879 817 880 if chkProvenance and not self.isValidProvenance(): 818 881 if raiseExcep: 819 raise AttCertError (\882 raise AttCertError, \ 820 883 "Attribute Certificate Provenance must be set to \"" + \ 821 "\" or \"".join(AttCert.__provenance) + "\"") 822 884 "\" or \"".join(AttCert.__provenance) + "\"" 823 885 return False 824 825 886 826 887 # Handle exception from XMLSecDocc.isValidSig() regardless of 827 888 # raiseExcep flag setting 828 try: 829 if chkSig and not self.isValidSig(**xmlSecDocKeys): 830 if raiseExcep: 831 raise AttCertError(\ 832 "Attribute Certificate signature is invalid") 889 if chkSig: 890 try: 891 self.verifyEnvelopedSignature(**xmlSecDocKw) 892 893 except InvalidSignature, e: 894 if raiseExcep: 895 raise AttCertError, \ 896 "Attribute Certificate signature:" + str(e) 897 else: 898 return False 833 899 834 return False835 836 except Exception, e:837 raise AttCertError(str(e))838 839 840 900 # All tests passed 841 901 return True 842 902 843 903 844 845 904 #_____________________________________________________________________________ 846 905 # Alternative AttCert constructors 847 #848 906 def AttCertRead(filePath): 849 907 """Create a new attribute certificate read in from a file""" … … 854 912 return attCert 855 913 856 857 858 914 #_________________________________________________________________________ 859 915 def AttCertParse(attCertTxt): 860 916 """Create a new attribute certificate from string of file content""" -
TI12-security/trunk/python/ndg.security.common/ndg/security/common/XMLSec.py
r1962 r1964 22 22 import sys 23 23 24 # For asString() - enables XML header to be stripped if required24 # For removal of BEGIN and END CERTIFICATE markers from X.509 certs 25 25 import re 26 27 # Use to create buffer for string output for asString() method28 from cStringIO import StringIO29 26 30 27 # Include for re-parsing doc ready for canonicalization in sign method - see
Note: See TracChangeset
for help on using the changeset viewer.