source: TI12-security/trunk/ndg_saml/ndg/saml/saml2/core.py @ 6786

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/ndg_saml/ndg/saml/saml2/core.py@6786
Revision 6786, 101.4 KB checked in by pjkersha, 9 years ago (diff)

Minor fixes including type checking for DecisionType?.eq input.

Line 
1"""SAML 2.0 core module
2
3Implementation of SAML 2.0 for NDG Security
4
5NERC DataGrid Project
6
7This implementation is adapted from the Java OpenSAML implementation.  The
8copyright and licence information are included here:
9
10Copyright [2005] [University Corporation for Advanced Internet Development, Inc.]
11
12Licensed under the Apache License, Version 2.0 (the "License");
13you may not use this file except in compliance with the License.
14You may obtain a copy of the License at
15
16http://www.apache.org/licenses/LICENSE-2.0
17
18Unless required by applicable law or agreed to in writing, software
19distributed under the License is distributed on an "AS IS" BASIS,
20WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21See the License for the specific language governing permissions and
22limitations under the License.
23"""
24__author__ = "P J Kershaw"
25__date__ = "11/08/09"
26__copyright__ = "(C) 2009 Science and Technology Facilities Council"
27__contact__ = "Philip.Kershaw@stfc.ac.uk"
28__license__ = "BSD - see LICENSE file in top-level directory"
29__contact__ = "Philip.Kershaw@stfc.ac.uk"
30__revision__ = "$Id: $"
31from datetime import datetime
32from urlparse import urlsplit, urlunsplit
33import urllib
34
35from ndg.saml.common import SAMLObject, SAMLVersion
36from ndg.saml.common.xml import SAMLConstants, QName
37from ndg.saml.utils import TypedList
38
39
40class Attribute(SAMLObject):
41    '''SAML 2.0 Core Attribute.'''
42   
43    # Local name of the Attribute element.
44    DEFAULT_ELEMENT_LOCAL_NAME = "Attribute"
45
46    # Default element name.
47    DEFAULT_ELEMENT_NAME = QName(SAMLConstants.SAML20_NS, 
48                                 DEFAULT_ELEMENT_LOCAL_NAME,
49                                 SAMLConstants.SAML20_PREFIX)
50
51    # Local name of the XSI type.
52    TYPE_LOCAL_NAME = "AttributeType"
53
54    # QName of the XSI type.
55    TYPE_NAME = QName(SAMLConstants.SAML20_NS, 
56                      TYPE_LOCAL_NAME,
57                      SAMLConstants.SAML20_PREFIX)
58
59    # Name of the Name attribute.
60    NAME_ATTRIB_NAME = "Name"
61
62    # Name for the NameFormat attribute.
63    NAME_FORMAT_ATTRIB_NAME = "NameFormat"
64
65    # Name of the FriendlyName attribute.
66    FRIENDLY_NAME_ATTRIB_NAME = "FriendlyName"
67
68    # Unspecified attribute format ID.
69    UNSPECIFIED = "urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified"
70
71    # URI reference attribute format ID.
72    URI_REFERENCE = "urn:oasis:names:tc:SAML:2.0:attrname-format:uri"
73
74    # Basic attribute format ID.
75    BASIC = "urn:oasis:names:tc:SAML:2.0:attrname-format:basic"
76
77    __slots__ = (
78        '__name',
79        '__nameFormat',
80        '__friendlyName',
81        '__attributeValues'
82    )
83   
84    def __init__(self, **kw):
85        """Initialise Attribute Class attributes"""
86        super(Attribute, self).__init__(**kw)
87       
88        self.__name = None
89        self.__nameFormat = None
90        self.__friendlyName = None
91        self.__attributeValues = []
92
93    def __getstate__(self):
94        '''Enable pickling'''
95        _dict = super(Attribute, self).__getstate__()
96        for attrName in Attribute.__slots__:
97            # Ugly hack to allow for derived classes setting private member
98            # variables
99            if attrName.startswith('__'):
100                attrName = "_Attribute" + attrName
101               
102            _dict[attrName] = getattr(self, attrName)
103           
104        return _dict
105   
106    def _get_name(self):
107        return self.__name
108   
109    def _set_name(self, name):
110        if not isinstance(name, basestring):
111            raise TypeError("Expecting basestring type for name, got %r"% 
112                            type(name))
113       
114        self.__name = name
115       
116    name = property(fget=_get_name,
117                    fset=_set_name,
118                    doc="name of this attribute")
119   
120    def _get_nameFormat(self):
121        return self.__nameFormat
122   
123    def _set_nameFormat(self, nameFormat):
124        if not isinstance(nameFormat, basestring):
125            raise TypeError("Expecting basestring type for nameFormat, got %r"
126                            % type(nameFormat))
127           
128        self.__nameFormat = nameFormat
129       
130    nameFormat = property(fget=_get_nameFormat,
131                          fset=_set_nameFormat,
132                          doc="Get the name format of this attribute.")
133   
134    def _get_friendlyName(self):
135        return self.__friendlyName
136   
137    def _set_friendlyName(self, friendlyName):
138        if not isinstance(friendlyName, basestring):
139            raise TypeError("Expecting basestring type for friendlyName, got "
140                            "%r" % type(friendlyName))
141           
142        self.__friendlyName = friendlyName
143       
144    friendlyName = property(fget=_get_friendlyName,
145                            fset=_set_friendlyName,
146                            doc="the friendly name of this attribute.")
147   
148    def _get_attributeValues(self):
149        return self.__attributeValues
150   
151    def _set_attributeValues(self, attributeValues):
152        if not isinstance(attributeValues, (list, tuple)):
153            raise TypeError("Expecting basestring type for attributeValues, "
154                            "got %r" % type(attributeValues))
155           
156        self.__attributeValues = attributeValues
157       
158    attributeValues = property(fget=_get_attributeValues,
159                               fset=_set_attributeValues,
160                               doc="the list of attribute values for this "
161                               "attribute.")
162
163
164class Statement(SAMLObject):
165    '''SAML 2.0 Core Statement.  Abstract base class which all statement
166    types must implement.'''
167    __slots__ = ()
168   
169    # Element local name
170    DEFAULT_ELEMENT_LOCAL_NAME = "Statement"
171
172    # Default element name
173    DEFAULT_ELEMENT_NAME = QName(SAMLConstants.SAML20_NS, 
174                                 DEFAULT_ELEMENT_LOCAL_NAME,
175                                 SAMLConstants.SAML20_PREFIX)
176
177    # Local name of the XSI type
178    TYPE_LOCAL_NAME = "StatementAbstractType"
179
180    # QName of the XSI type
181    TYPE_NAME = QName(SAMLConstants.SAML20_NS, 
182                      TYPE_LOCAL_NAME,
183                      SAMLConstants.SAML20_PREFIX)
184   
185           
186class AttributeStatement(Statement):
187    '''SAML 2.0 Core AttributeStatement'''
188   
189    # Element local name
190    DEFAULT_ELEMENT_LOCAL_NAME = "AttributeStatement"
191   
192    # Default element name.
193    DEFAULT_ELEMENT_NAME = QName(SAMLConstants.SAML20_NS, 
194                                 DEFAULT_ELEMENT_LOCAL_NAME, 
195                                 SAMLConstants.SAML20_PREFIX)
196   
197    # Local name of the XSI type.
198    TYPE_LOCAL_NAME = "AttributeStatementType" 
199       
200    # QName of the XSI type.
201    TYPE_NAME = QName(SAMLConstants.SAML20_NS, 
202                      TYPE_LOCAL_NAME, 
203                      SAMLConstants.SAML20_PREFIX)
204   
205    __slots__ = ('__attributes', '__encryptedAttributes')
206   
207    def __init__(self, **kw):
208        super(AttributeStatement, self).__init__(**kw)
209       
210        self.__attributes = TypedList(Attribute)
211        self.__encryptedAttributes = TypedList(Attribute)
212
213    def __getstate__(self):
214        '''Enable pickling'''
215        _dict = super(AttributeStatement, self).__getstate__()
216        for attrName in AttributeStatement.__slots__:
217            # Ugly hack to allow for derived classes setting private member
218            # variables
219            if attrName.startswith('__'):
220                attrName = "_AttributeStatement" + attrName
221               
222            _dict[attrName] = getattr(self, attrName)
223           
224        return _dict
225
226    def _get_attributes(self):
227        '''@return: the attributes expressed in this statement
228        '''
229        return self.__attributes
230
231    attributes = property(fget=_get_attributes)
232   
233    def _get_encryptedAttributes(self):
234       '''@return: the encrypted attribtues expressed in this statement
235       '''
236       return self.__encryptedAttributes
237   
238    encryptedAttributes = property(fget=_get_encryptedAttributes)
239
240
241class AuthnStatement(Statement):
242    '''SAML 2.0 Core AuthnStatement.  Currently implemented in abstract form
243    only
244    '''
245
246    # Element local name
247    DEFAULT_ELEMENT_LOCAL_NAME = "AuthnStatement"
248
249    # Default element name
250    DEFAULT_ELEMENT_NAME = QName(SAMLConstants.SAML20_NS, 
251                                 DEFAULT_ELEMENT_LOCAL_NAME,
252                                 SAMLConstants.SAML20_PREFIX)
253
254    # Local name of the XSI type
255    TYPE_LOCAL_NAME = "AuthnStatementType"
256
257    # QName of the XSI type
258    TYPE_NAME = QName(SAMLConstants.SAML20_NS, 
259                      TYPE_LOCAL_NAME,
260                      SAMLConstants.SAML20_PREFIX)
261
262    # AuthnInstant attribute name
263    AUTHN_INSTANT_ATTRIB_NAME = "AuthnInstant"
264
265    # SessionIndex attribute name
266    SESSION_INDEX_ATTRIB_NAME = "SessionIndex"
267
268    # SessionNoOnOrAfter attribute name
269    SESSION_NOT_ON_OR_AFTER_ATTRIB_NAME = "SessionNotOnOrAfter"
270   
271    __slots__ = ()
272   
273    def _getAuthnInstant(self):
274        '''Gets the time when the authentication took place.
275       
276        @return: the time when the authentication took place
277        '''
278        raise NotImplementedError()
279
280    def _setAuthnInstant(self, value):
281        '''Sets the time when the authentication took place.
282       
283        @param value: the time when the authentication took place
284        '''
285        raise NotImplementedError()
286
287    def _getSessionIndex(self):
288        '''Get the session index between the principal and the authenticating
289        authority.
290       
291        @return: the session index between the principal and the authenticating
292        authority
293        '''
294        raise NotImplementedError()
295
296    def _setSessionIndex(self, value):
297        '''Sets the session index between the principal and the authenticating
298        authority.
299       
300        @param value: the session index between the principal and the
301        authenticating authority
302        '''
303        raise NotImplementedError()
304
305    def _getSessionNotOnOrAfter(self):
306        '''Get the time when the session between the principal and the SAML
307        authority ends.
308       
309        @return: the time when the session between the principal and the SAML
310        authority ends
311        '''
312        raise NotImplementedError()
313
314    def _setSessionNotOnOrAfter(self, value):
315        '''Set the time when the session between the principal and the SAML
316        authority ends.
317       
318        @param value: the time when the session between the
319        principal and the SAML authority ends
320        '''
321        raise NotImplementedError()
322
323    def _getSubjectLocality(self):
324        '''Get the DNS domain and IP address of the system where the principal
325        was authenticated.
326       
327        @return: the DNS domain and IP address of the system where the principal
328        was authenticated
329        '''
330        raise NotImplementedError()
331
332    def _setSubjectLocality(self, value):
333        '''Set the DNS domain and IP address of the system where the principal
334        was authenticated.
335       
336        @param value: the DNS domain and IP address of the system where
337        the principal was authenticated
338        '''
339        raise NotImplementedError()
340
341    def _getAuthnContext(self):
342        '''Gets the context used to authenticate the subject.
343       
344        @return: the context used to authenticate the subject
345        '''
346        raise NotImplementedError()
347
348    def _setAuthnContext(self, value):
349        '''Sets the context used to authenticate the subject.
350       
351        @param value: the context used to authenticate the subject
352        '''
353        raise NotImplementedError()
354
355
356class DecisionType(object):
357    """Define decision types for the authorisation decisions"""
358   
359    # "Permit" decision type
360    PERMIT_STR = "Permit"
361   
362    # "Deny" decision type
363    DENY_STR = "Deny"
364   
365    # "Indeterminate" decision type
366    INDETERMINATE_STR = "Indeterminate"
367       
368    TYPES = (PERMIT_STR, DENY_STR, INDETERMINATE_STR)
369   
370    __slots__ = ('__value',)
371   
372    def __init__(self, decisionType):
373        self.__value = None
374        self.value = decisionType
375
376    def __getstate__(self):
377        '''Enable pickling'''
378        _dict = {}
379        for attrName in DecisionType.__slots__:
380            # Ugly hack to allow for derived classes setting private member
381            # variables
382            if attrName.startswith('__'):
383                attrName = "_DecisionType" + attrName
384               
385            _dict[attrName] = getattr(self, attrName)
386           
387        return _dict
388 
389    def __setstate__(self, attrDict):
390        '''Enable pickling'''
391        for attrName, val in attrDict.items():
392            setattr(self, attrName, val)
393           
394    def _setValue(self, value):
395        if isinstance(value, DecisionType):
396            # Cast to string
397            value = str(value)
398           
399        elif not isinstance(value, basestring):
400            raise TypeError('Expecting string or DecisionType instance for '
401                            '"value" attribute; got %r instead' % type(value))
402           
403        if value not in self.__class__.TYPES:
404            raise AttributeError('Permissable decision types are %r; got '
405                                 '%r instead' % (DecisionType.TYPES, value))
406        self.__value = value
407       
408    def _getValue(self):
409        return self.__value
410   
411    value = property(fget=_getValue, fset=_setValue, doc="Decision value")
412   
413    def __str__(self):
414        return self.__value
415
416    def __eq__(self, decision):
417        if isinstance(decision, DecisionType):
418            # Cast to string
419            value = decision.value
420           
421        elif isinstance(decision, basestring):
422            value = decision
423           
424        else:
425            raise TypeError('Expecting string or DecisionType instance for '
426                            'input decision value; got %r instead' % 
427                            type(value))
428           
429        if value not in self.__class__.TYPES:
430            raise AttributeError('Permissable decision types are %r; got '
431                                 '%r instead' % (DecisionType.TYPES, value))
432           
433        return self.__value == value
434
435
436class PermitDecisionType(DecisionType):
437    """Permit authorisation Decision"""
438    __slots__ = ()
439
440    def __init__(self):
441        super(PermitDecisionType, self).__init__(DecisionType.PERMIT_STR)
442       
443    def _setValue(self): 
444        raise AttributeError("can't set attribute")
445
446
447class DenyDecisionType(DecisionType):
448    """Deny authorisation Decision"""
449    __slots__ = ()
450   
451    def __init__(self):
452        super(DenyDecisionType, self).__init__(DecisionType.DENY_STR)
453       
454    def _setValue(self, value): 
455        raise AttributeError("can't set attribute")
456
457
458class IndeterminateDecisionType(DecisionType):
459    """Indeterminate authorisation Decision"""
460    __slots__ = ()
461   
462    def __init__(self):
463        super(IndeterminateDecisionType, self).__init__(
464                                            DecisionType.INDETERMINATE_STR)
465       
466    def _setValue(self, value): 
467        raise AttributeError("can't set attribute")
468
469# Add instances of each for convenience
470DecisionType.PERMIT = PermitDecisionType()
471DecisionType.DENY = DenyDecisionType()
472DecisionType.INDETERMINATE = IndeterminateDecisionType()
473
474
475class AuthzDecisionStatement(Statement):
476    '''SAML 2.0 Core AuthzDecisionStatement.  Currently implemented in abstract
477    form only'''
478   
479    # Element local name
480    DEFAULT_ELEMENT_LOCAL_NAME = "AuthzDecisionStatement"
481
482    # Default element name
483    DEFAULT_ELEMENT_NAME = QName(SAMLConstants.SAML20_NS, 
484                                 DEFAULT_ELEMENT_LOCAL_NAME,
485                                 SAMLConstants.SAML20_PREFIX)
486
487    # Local name of the XSI type
488    TYPE_LOCAL_NAME = "AuthzDecisionStatementType"
489
490    # QName of the XSI type
491    TYPE_NAME = QName(SAMLConstants.SAML20_NS, 
492                      TYPE_LOCAL_NAME,
493                      SAMLConstants.SAML20_PREFIX)
494
495    # Resource attribute name
496    RESOURCE_ATTRIB_NAME = "Resource"
497
498    # Decision attribute name
499    DECISION_ATTRIB_NAME = "Decision"
500   
501    __slots__ = (
502        '__resource', 
503        '__decision', 
504        '__actions', 
505        '__evidence',
506        '__normalizeResource',
507        '__safeNormalizationChars')
508   
509    def __init__(self, 
510                 normalizeResource=True, 
511                 safeNormalizationChars='/%',
512                 **kw):
513        '''Create new authorisation decision statement
514        '''
515        super(AuthzDecisionStatement, self).__init__(**kw)
516
517        # Resource attribute value.
518        self.__resource = None 
519       
520        self.__decision = DecisionType.INDETERMINATE   
521        self.__actions = TypedList(Action)
522        self.__evidence = None
523       
524        # Tuning for normalization of resource URIs in property set method
525        self.normalizeResource = normalizeResource
526        self.safeNormalizationChars = safeNormalizationChars
527
528    def __getstate__(self):
529        '''Enable pickling'''
530        _dict = super(AuthzDecisionStatement, self).__getstate__()
531        for attrName in AuthzDecisionStatement.__slots__:
532            # Ugly hack to allow for derived classes setting private member
533            # variables
534            if attrName.startswith('__'):
535                attrName = "_AuthzDecisionStatement" + attrName
536               
537            _dict[attrName] = getattr(self, attrName)
538           
539        return _dict
540   
541    def _getNormalizeResource(self):
542        return self.__normalizeResource
543
544    def _setNormalizeResource(self, value):
545        if not isinstance(value, bool):
546            raise TypeError('Expecting bool type for "normalizeResource" '
547                            'attribute; got %r instead' % type(value))
548           
549        self.__normalizeResource = value
550
551    normalizeResource = property(_getNormalizeResource, 
552                                 _setNormalizeResource, 
553                                 doc="Flag to normalize new resource value "
554                                     "assigned to the \"resource\" property.  "
555                                     "The setting only applies for URIs "
556                                     'beginning with "http://" or "https://"')
557
558    def _getSafeNormalizationChars(self):
559        return self.__safeNormalizationChars
560
561    def _setSafeNormalizationChars(self, value):
562        if not isinstance(value, basestring):
563            raise TypeError('Expecting string type for "normalizeResource" '
564                            'attribute; got %r instead' % type(value))
565           
566        self.__safeNormalizationChars = value
567
568    safeNormalizationChars = property(_getSafeNormalizationChars, 
569                                      _setSafeNormalizationChars, 
570                                      doc="String containing a list of "
571                                          "characters that should not be "
572                                          "converted when Normalizing the "
573                                          "resource URI.  These are passed to "
574                                          "urllib.quote when the resource "
575                                          "property is set.  The default "
576                                          "characters are '/%'")
577
578    def _getResource(self):
579        '''Gets the Resource attrib value of this query.
580
581        @return: the Resource attrib value of this query'''
582        return self.__resource
583   
584    def _setResource(self, value):
585        '''Sets the Resource attrib value of this query normalizing the path
586        component, removing spurious port numbers (80 for HTTP and 443 for
587        HTTPS) and converting the host component to lower case.
588       
589        @param value: the new Resource attrib value of this query'''
590        if not isinstance(value, basestring):
591            raise TypeError('Expecting string type for "resource" attribute; '
592                            'got %r instead' % type(value))
593       
594        if (self.normalizeResource and 
595            value.startswith('http://') or value.startswith('https://')):
596            # Normalise the path, set the host name to lower case and remove
597            # port redundant numbers 80 and 443
598            splitResult = urlsplit(value)
599            uriComponents = list(splitResult)
600           
601            # hostname attribute is lowercase
602            uriComponents[1] = splitResult.hostname
603           
604            if splitResult.port is not None:
605                isHttpWithStdPort = (splitResult.port == 80 and 
606                                     splitResult.scheme == 'http')
607               
608                isHttpsWithStdPort = (splitResult.port == 443 and
609                                      splitResult.scheme == 'https')
610               
611                if not isHttpWithStdPort and not isHttpsWithStdPort:
612                    uriComponents[1] += ":%d" % splitResult.port
613           
614            uriComponents[2] = urllib.quote(splitResult.path, 
615                                            self.safeNormalizationChars)
616           
617            self.__resource = urlunsplit(uriComponents)
618        else:
619            self.__resource = value
620   
621    resource = property(fget=_getResource, fset=_setResource,
622                        doc="Resource for which authorisation was requested")
623
624    def _getDecision(self):
625        '''
626        Gets the decision of the authorization request.
627       
628        @return: the decision of the authorization request
629        '''
630        return self.__decision
631
632    def _setDecision(self, value):
633        '''
634        Sets the decision of the authorization request.
635       
636        @param value: the decision of the authorization request
637        '''
638        if not isinstance(value, DecisionType):
639            raise TypeError('Expecting %r type for "decision" attribute; '
640                            'got %r instead' % (DecisionType, type(value)))
641        self.__decision = value
642
643    decision = property(_getDecision, _setDecision, 
644                        doc="Authorization decision as a DecisionType instance")
645   
646    @property
647    def actions(self):
648        '''The actions for which authorisation is requested
649       
650        @return: the Actions of this statement'''
651        return self.__actions
652   
653    def _getEvidence(self):
654        '''Gets the Evidence of this statement.
655
656        @return: the Evidence of this statement'''
657        return self.__evidence
658
659    def _setEvidence(self, value):
660        '''Sets the Evidence of this query.
661        @param newEvidence: the new Evidence of this statement''' 
662        if not isinstance(value, Evidence):
663            raise TypeError('Expecting Evidence type for "evidence" '
664                            'attribute; got %r' % type(value))
665
666        self.__evidence = value 
667
668    evidence = property(fget=_getEvidence, fset=_setEvidence, 
669                        doc="A set of assertions which the Authority may use "
670                            "to base its authorisation decision on")
671   
672    def getOrderedChildren(self):
673        children = []
674
675        superChildren = super(AuthzDecisionStatement, self).getOrderedChildren()
676        if superChildren:
677            children.extend(superChildren)
678
679        children.extend(self.__actions)
680       
681        if self.__evidence is not None:
682            children.extend(self.__evidence)
683
684        if len(children) == 0:
685            return None
686
687        return tuple(children)
688       
689
690class Subject(SAMLObject):
691    '''Concrete implementation of @link org.opensaml.saml2.core.Subject.'''
692   
693    # Element local name.
694    DEFAULT_ELEMENT_LOCAL_NAME = "Subject"
695
696    # Default element name.
697    DEFAULT_ELEMENT_NAME = QName(SAMLConstants.SAML20_NS, 
698                                 DEFAULT_ELEMENT_LOCAL_NAME,
699                                 SAMLConstants.SAML20_PREFIX)
700
701    # Local name of the XSI type.
702    TYPE_LOCAL_NAME = "SubjectType"
703
704    # QName of the XSI type.
705    TYPE_NAME = QName(SAMLConstants.SAML20_NS, 
706                      TYPE_LOCAL_NAME,
707                      SAMLConstants.SAML20_PREFIX)
708    __slots__ = (
709        '__baseID',
710        '__nameID',
711        '__encryptedID',
712        '__subjectConfirmations'
713    )
714   
715    def __init__(self, **kw):
716        super(Subject, self).__init__(**kw)
717       
718        # BaseID child element.
719        self.__baseID = None
720   
721        # NameID child element.
722        self.__nameID = None
723   
724        # EncryptedID child element.
725        self.__encryptedID = None
726   
727        # Subject Confirmations of the Subject.
728        self.__subjectConfirmations = []
729
730    def __getstate__(self):
731        '''Enable pickling'''
732        _dict = super(Subject, self).__getstate__()
733        for attrName in Subject.__slots__:
734            # Ugly hack to allow for derived classes setting private member
735            # variables
736            if attrName.startswith('__'):
737                attrName = "_Subject" + attrName
738               
739            _dict[attrName] = getattr(self, attrName)
740           
741        return _dict
742   
743    def _getBaseID(self): 
744        return self.__baseID
745
746    def _setBaseID(self, value):
747        if not isinstance(value, basestring):
748            raise TypeError("Expecting %r type for \"baseID\" got %r" %
749                            (basestring, value.__class__))
750        self.__baseID = value
751
752    baseID = property(fget=_getBaseID, 
753                      fset=_setBaseID, 
754                      doc="Base identifier")
755     
756    def _getNameID(self):
757        return self.__nameID
758   
759    def _setNameID(self, value):
760        if not isinstance(value, NameID):
761            raise TypeError("Expecting %r type for \"nameID\" got %r" %
762                            (NameID, type(value)))
763        self.__nameID = value
764
765    nameID = property(fget=_getNameID, 
766                      fset=_setNameID, 
767                      doc="Name identifier")
768   
769    def _getEncryptedID(self):
770        return self.__encryptedID
771   
772    def _setEncryptedID(self, value): 
773        self.__encryptedID = value
774
775    encryptedID = property(fget=_getEncryptedID, 
776                           fset=_setEncryptedID, 
777                           doc="EncryptedID's Docstring")
778   
779    def _getSubjectConfirmations(self): 
780        return self.__subjectConfirmations
781
782    subjectConfirmations = property(fget=_getSubjectConfirmations, 
783                                    doc="Subject Confirmations")   
784   
785    def getOrderedChildren(self): 
786        children = []
787
788        if self.baseID is not None:
789            children.append(self.baseID)
790       
791        if self.nameID is not None: 
792            children.append(self.nameID)
793       
794        if self.encryptedID is not None: 
795            children.append(self.encryptedID)
796       
797        children += self.subjectConfirmations
798
799        return tuple(children)
800
801
802class AbstractNameIDType(SAMLObject):
803    '''Abstract implementation of NameIDType'''
804
805    # SPNameQualifier attribute name.
806    SP_NAME_QUALIFIER_ATTRIB_NAME = "SPNameQualifier"
807
808    # Format attribute name.
809    FORMAT_ATTRIB_NAME = "Format"
810
811    # SPProviderID attribute name.
812    SPPROVIDED_ID_ATTRIB_NAME = "SPProvidedID"
813
814    # URI for unspecified name format.
815    UNSPECIFIED = "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
816
817    # URI for email name format.
818    EMAIL = "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
819
820    # URI for X509 subject name format.
821    X509_SUBJECT = "urn:oasis:names:tc:SAML:1.1:nameid-format:x509SubjectName"
822
823    # URI for windows domain qualified name name format.
824    WIN_DOMAIN_QUALIFIED = \
825        "urn:oasis:names:tc:SAML:1.1:nameid-format:WindowsDomainQualifiedName"
826
827    # URI for kerberos name format.
828    KERBEROS = "urn:oasis:names:tc:SAML:2.0:nameid-format:kerberos"
829
830    # URI for SAML entity name format.
831    ENTITY = "urn:oasis:names:tc:SAML:2.0:nameid-format:entity"
832
833    # URI for persistent name format.
834    PERSISTENT = "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"
835
836    # URI for transient name format.
837    TRANSIENT = "urn:oasis:names:tc:SAML:2.0:nameid-format:transient"
838
839    # Special URI used by NameIDPolicy to indicate a NameID should be encrypted
840    ENCRYPTED = "urn:oasis:names:tc:SAML:2.0:nameid-format:encrypted"
841   
842    __slots__ = (
843        '__name',
844        '__nameQualifier',
845        '__spNameQualifier',
846        '__format',
847        '__spProvidedID',
848        '__value'
849    )
850   
851    def __init__(self, **kw): 
852        '''@param namespaceURI: the namespace the element is in
853        @param elementLocalName: the local name of the XML element this Object
854        represents
855        @param namespacePrefix: the prefix for the given namespace
856        '''
857        super(AbstractNameIDType, self).__init__(**kw)
858   
859        # Name of the Name ID.
860        self.__name = None
861       
862        # Name Qualifier of the Name ID.
863        self.__nameQualifier = None
864   
865        # SP Name Qualifier of the Name ID.
866        self.__spNameQualifier = None
867   
868        # Format of the Name ID.
869        self.__format = None
870   
871        # SP ProvidedID of the NameID.
872        self.__spProvidedID = None
873
874        self.__value = None
875
876    def __getstate__(self):
877        '''Enable pickling'''
878        _dict = super(AbstractNameIDType, self).__getstate__()
879        for attrName in AbstractNameIDType.__slots__:
880            # Ugly hack to allow for derived classes setting private member
881            # variables
882            if attrName.startswith('__'):
883                attrName = "_AbstractNameIDType" + attrName
884               
885            _dict[attrName] = getattr(self, attrName)
886           
887        return _dict
888             
889    def _getValue(self):
890        return self.__value
891       
892    def _setValue(self, value):
893        if not isinstance(value, basestring):
894            raise TypeError("\"value\" must be a basestring derived type, "
895                            "got %r" % value.__class__)
896           
897        self.__value = value
898
899    value = property(fget=_getValue, fset=_setValue, doc="string value") 
900   
901    def _getNameQualifier(self): 
902        return self.__nameQualifier
903   
904    def _setNameQualifier(self, value): 
905        self.__nameQualifier = value
906
907    nameQualifier = property(fget=_getNameQualifier, 
908                             fset=_setNameQualifier, 
909                             doc="Name qualifier")   
910
911    def _getSPNameQualifier(self): 
912        return self.__spNameQualifier
913   
914    def _setSPNameQualifier(self, value): 
915        self.__spNameQualifier = value
916
917    spNameQualifier = property(fget=_getSPNameQualifier, 
918                               fset=_setSPNameQualifier, 
919                               doc="SP Name qualifier")   
920   
921    def _getFormat(self):
922        return self.__format
923       
924    def _setFormat(self, format):
925        if not isinstance(format, basestring):
926            raise TypeError("\"format\" must be a basestring derived type, "
927                            "got %r" % format.__class__)
928           
929        self.__format = format
930
931    format = property(fget=_getFormat, fset=_setFormat, doc="Name format") 
932   
933    def _getSPProvidedID(self): 
934        return self.__spProvidedID
935   
936    def _setSPProvidedID(self, value): 
937        self.__spProvidedID = value
938
939    spProvidedID = property(fget=_getSPProvidedID, fset=_setSPProvidedID, 
940                            doc="SP Provided Identifier") 
941   
942    def getOrderedChildren(self): 
943        raise NotImplementedError()
944
945   
946class Issuer(AbstractNameIDType):
947    """SAML 2.0 Core Issuer type"""
948   
949    # Element local name.
950    DEFAULT_ELEMENT_LOCAL_NAME = "Issuer"
951
952    # Default element name.
953    DEFAULT_ELEMENT_NAME = QName(SAMLConstants.SAML20_NS, 
954                                 DEFAULT_ELEMENT_LOCAL_NAME,
955                                 SAMLConstants.SAML20_PREFIX)
956
957    # Local name of the XSI type.
958    TYPE_LOCAL_NAME = "IssuerType"
959
960    # QName of the XSI type.
961    TYPE_NAME = QName(SAMLConstants.SAML20_NS, 
962                      TYPE_LOCAL_NAME,
963                      SAMLConstants.SAML20_PREFIX) 
964   
965    __slots__ = ()
966
967     
968class NameID(AbstractNameIDType):
969    '''SAML 2.0 Core NameID'''
970    # Element local name.
971    DEFAULT_ELEMENT_LOCAL_NAME = "NameID"
972
973    # Default element name.
974    DEFAULT_ELEMENT_NAME = QName(SAMLConstants.SAML20_NS, 
975                                 DEFAULT_ELEMENT_LOCAL_NAME,
976                                 SAMLConstants.SAML20_PREFIX)
977
978    # Local name of the XSI type.
979    TYPE_LOCAL_NAME = "NameIDType"
980
981    # QName of the XSI type.
982    TYPE_NAME = QName(SAMLConstants.SAML20_NS, 
983                      TYPE_LOCAL_NAME,
984                      SAMLConstants.SAML20_PREFIX)
985   
986    __slots__ = ()
987   
988
989class Conditions(SAMLObject): 
990    '''SAML 2.0 Core Conditions.'''
991   
992    # Element local name.
993    DEFAULT_ELEMENT_LOCAL_NAME = "Conditions"
994
995    # Default element name.
996    DEFAULT_ELEMENT_NAME = QName(SAMLConstants.SAML20_NS, 
997                                 DEFAULT_ELEMENT_LOCAL_NAME,
998                                 SAMLConstants.SAML20_PREFIX)
999
1000    # Local name of the XSI type.
1001    TYPE_LOCAL_NAME = "ConditionsType"
1002
1003    # QName of the XSI type.
1004    TYPE_NAME = QName(SAMLConstants.SAML20_NS, 
1005                      TYPE_LOCAL_NAME,
1006                      SAMLConstants.SAML20_PREFIX)
1007
1008    # NotBefore attribute name.
1009    NOT_BEFORE_ATTRIB_NAME = "NotBefore"
1010
1011    # NotOnOrAfter attribute name.
1012    NOT_ON_OR_AFTER_ATTRIB_NAME = "NotOnOrAfter"
1013
1014    __slots__ = (
1015        '__conditions',
1016        '__notBefore',
1017        '__notOnOrAfter'
1018    )
1019   
1020    def __init__(self, **kw):
1021        super(Conditions, self).__init__(**kw)
1022       
1023        # A Condition.
1024        self.__conditions = []
1025   
1026        # Not Before conditions.
1027        self.__notBefore = None
1028   
1029        # Not On Or After conditions.
1030        self.__notOnOrAfter = None
1031
1032    def __getstate__(self):
1033        '''Enable pickling'''
1034        _dict = super(Conditions, self).__getstate__()
1035        for attrName in Conditions.__slots__:
1036            # Ugly hack to allow for derived classes setting private member
1037            # variables
1038            if attrName.startswith('__'):
1039                attrName = "_Conditions" + attrName
1040               
1041            _dict[attrName] = getattr(self, attrName)
1042           
1043        return _dict
1044   
1045    def _getNotBefore(self):
1046        '''Get the date/time before which the assertion is invalid.
1047       
1048        @return: the date/time before which the assertion is invalid'''
1049        return self.__notBefore
1050   
1051    def _setNotBefore(self, value):
1052        '''Sets the date/time before which the assertion is invalid.
1053       
1054        @param value: the date/time before which the assertion is invalid
1055        '''
1056        if not isinstance(value, datetime):
1057            raise TypeError('Expecting "datetime" type for "notBefore", '
1058                            'got %r' % type(value))
1059        self.__notBefore = value
1060
1061    def _getNotOnOrAfter(self):
1062        '''Gets the date/time on, or after, which the assertion is invalid.
1063       
1064        @return: the date/time on, or after, which the assertion is invalid'
1065        '''
1066        return self.__notOnOrAfter
1067   
1068    def _setNotOnOrAfter(self, value):
1069        '''Sets the date/time on, or after, which the assertion is invalid.
1070       
1071        @param value: the date/time on, or after, which the assertion
1072        is invalid
1073        '''
1074        if not isinstance(value, datetime):
1075            raise TypeError('Expecting "datetime" type for "notOnOrAfter", '
1076                            'got %r' % type(value))
1077        self.__notOnOrAfter = value 
1078
1079    notBefore = property(_getNotBefore, _setNotBefore, 
1080                         doc="Not before time restriction")
1081
1082    notOnOrAfter = property(_getNotOnOrAfter, _setNotOnOrAfter, 
1083                            doc="Not on or after time restriction")
1084
1085    @property
1086    def conditions(self):
1087        '''All the conditions on the assertion.
1088       
1089        @return: all the conditions on the assertion
1090        '''
1091        return self.__conditions
1092   
1093    def _getAudienceRestrictions(self):
1094        '''Gets the audience restriction conditions for the assertion.
1095       
1096        @return: the audience restriction conditions for the assertion
1097        '''
1098        raise NotImplementedError()
1099
1100    def _getOneTimeUse(self):
1101        '''Gets the OneTimeUse condition for the assertion.
1102       
1103        @return: the OneTimeUse condition for the assertion
1104        '''
1105        raise NotImplementedError()
1106
1107    def _getProxyRestriction(self):   
1108        '''Gets the ProxyRestriction condition for the assertion.
1109       
1110        @return: the ProxyRestriction condition for the assertion
1111        '''
1112        raise NotImplementedError()
1113   
1114   
1115class Advice(SAMLObject):
1116    '''SAML 2.0 Core Advice.
1117    '''
1118
1119    # Element local name
1120    DEFAULT_ELEMENT_LOCAL_NAME = "Advice"
1121
1122    # Default element name.
1123    DEFAULT_ELEMENT_NAME = QName(SAMLConstants.SAML20_NS, 
1124                                 DEFAULT_ELEMENT_LOCAL_NAME,
1125                                 SAMLConstants.SAML20_PREFIX)
1126
1127    # Local name of the XSI type
1128    TYPE_LOCAL_NAME = "AdviceType"
1129
1130    # QName of the XSI type
1131    TYPE_NAME = QName(SAMLConstants.SAML20_NS, 
1132                      TYPE_LOCAL_NAME,
1133                      SAMLConstants.SAML20_PREFIX)
1134
1135    __slots__ = ()
1136   
1137    def _getChildren(self, typeOrName=None):
1138        '''
1139        Gets the list of all child elements attached to this advice.
1140       
1141        @return: the list of all child elements attached to this advice
1142        '''
1143        raise NotImplementedError()
1144
1145    def _getAssertionIDReferences(self):
1146        '''Gets the list of AssertionID references used as advice.
1147       
1148        @return: the list of AssertionID references used as advice
1149        '''
1150        raise NotImplementedError()
1151
1152    def _getAssertionURIReferences(self):
1153        '''Gets the list of AssertionURI references used as advice.
1154       
1155        @return: the list of AssertionURI references used as advice
1156        '''
1157        raise NotImplementedError()
1158   
1159    def _getAssertions(self):
1160        '''Gets the list of Assertions used as advice.
1161       
1162        @return: the list of Assertions used as advice
1163        '''
1164        raise NotImplementedError()
1165   
1166    def _getEncryptedAssertions(self):
1167        '''Gets the list of EncryptedAssertions used as advice.
1168       
1169        @return: the list of EncryptedAssertions used as advice
1170        '''
1171        raise NotImplementedError()
1172       
1173
1174class Assertion(SAMLObject):
1175    """SAML 2.0 Attribute Assertion for use with NERC DataGrid   
1176    """   
1177    # Element local name.
1178    DEFAULT_ELEMENT_LOCAL_NAME = "Assertion"
1179
1180    # Default element name.
1181    DEFAULT_ELEMENT_NAME = QName(SAMLConstants.SAML20_NS, 
1182                                 DEFAULT_ELEMENT_LOCAL_NAME,
1183                                 SAMLConstants.SAML20_PREFIX)
1184
1185    # Local name of the XSI type.
1186    TYPE_LOCAL_NAME = "AssertionType"
1187
1188    # QName of the XSI type.
1189    TYPE_NAME = QName(SAMLConstants.SAML20_NS, TYPE_LOCAL_NAME,
1190                      SAMLConstants.SAML20_PREFIX)
1191
1192    # Version attribute name.
1193    VERSION_ATTRIB_NAME = "Version"
1194
1195    # IssueInstant attribute name.
1196    ISSUE_INSTANT_ATTRIB_NAME = "IssueInstant"
1197
1198    # ID attribute name.
1199    ID_ATTRIB_NAME = "ID"
1200
1201    __slots__ = (
1202        '__version',
1203        '__issueInstant',
1204        '__id',
1205        '__issuer',
1206        '__subject',
1207        '__conditions',
1208        '__advice',
1209        '__statements',
1210        '__authnStatements',
1211        '__authzDecisionStatements',
1212        '__attributeStatements'
1213    )
1214   
1215    def __init__(self):
1216        # Base class initialisation
1217        super(Assertion, self).__init__()
1218       
1219        self.__version = None
1220        self.__issueInstant = None
1221        self.__id = None
1222        self.__issuer = None
1223        self.__subject = None
1224       
1225        self.__conditions = None
1226        self.__advice = None
1227        self.__statements = TypedList(Statement)
1228       
1229        # TODO: Implement AuthnStatement and AuthzDecisionStatement classes
1230        self.__authnStatements = []
1231        self.__authzDecisionStatements = TypedList(AuthzDecisionStatement)
1232        self.__attributeStatements = TypedList(AttributeStatement)
1233
1234    def __getstate__(self):
1235        '''Enable pickling'''
1236        _dict = super(Assertion, self).__getstate__()
1237        for attrName in Assertion.__slots__:
1238            # Ugly hack to allow for derived classes setting private member
1239            # variables
1240            if attrName.startswith('__'):
1241                attrName = "_Assertion" + attrName
1242               
1243            _dict[attrName] = getattr(self, attrName)
1244           
1245        return _dict   
1246                 
1247    def _get_version(self):
1248        '''@return: the SAML Version of this assertion.
1249        '''
1250        return self.__version
1251   
1252    def _set_version(self, version):
1253        '''@param version: the SAML Version of this assertion
1254        '''
1255        if not isinstance(version, SAMLVersion):
1256            raise TypeError("Expecting SAMLVersion type got: %r" % 
1257                            version.__class__)
1258       
1259        self.__version = version
1260       
1261    version = property(fget=_get_version,
1262                       fset=_set_version,
1263                       doc="SAML Version of the assertion")
1264
1265    def _get_issueInstant(self):
1266        '''Gets the issue instance of this assertion.
1267       
1268        @return: the issue instance of this assertion'''
1269        return self.__issueInstant
1270   
1271    def _set_issueInstant(self, issueInstant):
1272        '''Sets the issue instance of this assertion.
1273       
1274        @param issueInstant: the issue instance of this assertion
1275        '''
1276        if not isinstance(issueInstant, datetime):
1277            raise TypeError('Expecting "datetime" type for "issueInstant", '
1278                            'got %r' % issueInstant.__class__)
1279           
1280        self.__issueInstant = issueInstant
1281       
1282    issueInstant = property(fget=_get_issueInstant, 
1283                            fset=_set_issueInstant,
1284                            doc="Issue instant of the assertion")
1285
1286    def _get_id(self):
1287        '''Sets the ID of this assertion.
1288       
1289        @return: the ID of this assertion
1290        '''
1291        return self.__id
1292   
1293    def _set_id(self, _id):
1294        '''Sets the ID of this assertion.
1295       
1296        @param _id: the ID of this assertion
1297        '''
1298        if not isinstance(_id, basestring):
1299            raise TypeError('Expecting basestring derived type for "id", got '
1300                            '%r' % _id.__class__)
1301        self.__id = _id
1302       
1303    id = property(fget=_get_id, fset=_set_id, doc="ID of assertion")
1304   
1305    def _set_issuer(self, issuer):
1306        """Set issuer"""
1307        if not isinstance(issuer, Issuer):
1308            raise TypeError("issuer must be %r, got %r" % (Issuer, 
1309                                                           type(issuer)))
1310        self.__issuer = issuer
1311   
1312    def _get_issuer(self):
1313        """Get the issuer name """
1314        return self.__issuer
1315
1316    issuer = property(fget=_get_issuer, 
1317                      fset=_set_issuer,
1318                      doc="Issuer of assertion")
1319   
1320    def _set_subject(self, subject):
1321        """Set subject string."""
1322        if not isinstance(subject, Subject):
1323            raise TypeError("subject must be %r, got %r" % (Subject, 
1324                                                            type(subject)))
1325
1326        self.__subject = subject
1327   
1328    def _get_subject(self):
1329        """Get subject string."""
1330        return self.__subject
1331
1332    subject = property(fget=_get_subject,
1333                       fset=_set_subject, 
1334                       doc="Attribute Assertion subject")
1335   
1336    def _get_conditions(self):
1337        """Get conditions string."""
1338        return self.__conditions
1339   
1340    def _set_conditions(self, value):
1341        """Get conditions string."""
1342        if not isinstance(value, Conditions):
1343            raise TypeError("Conditions must be %r, got %r" % (Conditions, 
1344                                                               type(value)))
1345
1346        self.__conditions = value
1347
1348    conditions = property(fget=_get_conditions,
1349                          fset=_set_conditions,
1350                          doc="Attribute Assertion conditions")
1351   
1352    def _set_advice(self, advice):
1353        """Set advice string."""
1354        if not isinstance(advice, basestring):
1355            raise TypeError("advice must be a string")
1356
1357        self.__advice = advice
1358   
1359    def _get_advice(self):
1360        """Get advice string."""
1361        return self.__advice
1362
1363    advice = property(fget=_get_advice,
1364                      fset=_set_advice, 
1365                      doc="Attribute Assertion advice")
1366   
1367    @property
1368    def statements(self):
1369        """Attribute Assertion statements"""
1370        return self.__statements
1371   
1372    @property
1373    def authnStatements(self):
1374        """Attribute Assertion authentication"""
1375        return self.__authnStatements
1376   
1377    @property
1378    def authzDecisionStatements(self):
1379        """Attribute Assertion authorisation decision statements"""
1380        return self.__authzDecisionStatements
1381   
1382    @property
1383    def attributeStatements(self):
1384        """Attribute Assertion attribute statements"""
1385        return self.__attributeStatements
1386   
1387
1388class AttributeValue(SAMLObject):
1389    """Base class for Attribute Value type"""
1390   
1391    # Element name, no namespace
1392    DEFAULT_ELEMENT_LOCAL_NAME = "AttributeValue"
1393
1394    # Default element name
1395    DEFAULT_ELEMENT_NAME = QName(SAMLConstants.SAML20_NS, 
1396                                 DEFAULT_ELEMENT_LOCAL_NAME,
1397                                 SAMLConstants.SAML20_PREFIX)
1398    __slots__ = ()
1399
1400
1401class XSStringAttributeValue(AttributeValue):
1402    """XML XS:String Attribute Value type"""
1403   
1404    # Local name of the XSI type
1405    TYPE_LOCAL_NAME = "string"
1406       
1407    # QName of the XSI type
1408    TYPE_NAME = QName(SAMLConstants.XSD_NS, 
1409                      TYPE_LOCAL_NAME, 
1410                      SAMLConstants.XSD_PREFIX)
1411   
1412    DEFAULT_FORMAT = "%s#%s" % (SAMLConstants.XSD_NS, TYPE_LOCAL_NAME)
1413 
1414    __slots__ = ('__value',)
1415   
1416    def __init__(self, **kw):
1417        super(XSStringAttributeValue, self).__init__(**kw)
1418        self.__value = None
1419
1420    def __getstate__(self):
1421        '''Enable pickling'''
1422        _dict = super(XSStringAttributeValue, self).__getstate__()
1423        for attrName in XSStringAttributeValue.__slots__:
1424            # Ugly hack to allow for derived classes setting private member
1425            # variables
1426            if attrName.startswith('__'):
1427                attrName = "_XSStringAttributeValue" + attrName
1428               
1429            _dict[attrName] = getattr(self, attrName)
1430           
1431        return _dict
1432           
1433    def _getValue(self):
1434        return self.__value
1435       
1436    def _setValue(self, value):
1437        if not isinstance(value, basestring):
1438            raise TypeError("Input must be a basestring derived type, got %r" %
1439                            value.__class__)
1440           
1441        self.__value = value
1442
1443    value = property(fget=_getValue, fset=_setValue, doc="string value") 
1444
1445
1446class StatusDetail(SAMLObject):
1447    '''Implementation of SAML 2.0 StatusDetail'''
1448   
1449    # Local Name of StatusDetail.
1450    DEFAULT_ELEMENT_LOCAL_NAME = "StatusDetail"
1451
1452    # Default element name.
1453    DEFAULT_ELEMENT_NAME = QName(SAMLConstants.SAML20P_NS, 
1454                                 DEFAULT_ELEMENT_LOCAL_NAME,
1455                                 SAMLConstants.SAML20P_PREFIX)
1456
1457    # Local name of the XSI type.
1458    TYPE_LOCAL_NAME = "StatusDetailType"
1459
1460    # QName of the XSI type.
1461    TYPE_NAME = QName(SAMLConstants.SAML20P_NS, 
1462                      TYPE_LOCAL_NAME,
1463                      SAMLConstants.SAML20P_PREFIX)
1464   
1465    __slots__ = ('__unknownChildren', )
1466   
1467    def __init__(self, **kw):
1468        super(StatusDetail, self).__init__(**kw)
1469       
1470        # child "any" elements.
1471        self.__unknownChildren = TypedList(SAMLObject)         
1472
1473    def __getstate__(self):
1474        '''Enable pickling'''
1475        _dict = super(StatusDetail, self).__getstate__()
1476        for attrName in StatusDetail.__slots__:
1477            # Ugly hack to allow for derived classes setting private member
1478            # variables
1479            if attrName.startswith('__'):
1480                attrName = "_StatusDetail" + attrName
1481               
1482            _dict[attrName] = getattr(self, attrName)
1483           
1484        return _dict
1485   
1486    def getUnknownXMLTypes(self, qname=None): 
1487        if qname is not None:
1488            if not isinstance(qname, QName):
1489                raise TypeError("\"qname\" must be a %r derived type, "
1490                                "got %r" % (QName, type(qname)))
1491               
1492            children = []
1493            for child in self.__unknownChildren:
1494                childQName = getattr(child, "qname", None)
1495                if childQName is not None:
1496                    if childQName.namespaceURI == qname.namespaceURI or \
1497                       childQName.localPart == qname.localPart:
1498                        children.append(child)
1499                       
1500            return children
1501        else:
1502            return self.__unknownChildren
1503   
1504    unknownChildren = property(fget=getUnknownXMLTypes,
1505                               doc="Child objects of Status Detail - may be "
1506                                   "any type")
1507   
1508
1509class StatusMessage(SAMLObject):
1510    '''Implementation of SAML 2.0 Status Message'''
1511
1512    DEFAULT_ELEMENT_LOCAL_NAME = "StatusMessage"
1513    DEFAULT_ELEMENT_NAME = QName(SAMLConstants.SAML20P_NS, 
1514                                 DEFAULT_ELEMENT_LOCAL_NAME,
1515                                 SAMLConstants.SAML20P_PREFIX)
1516   
1517    __slots__ = ('__value', )
1518   
1519    def __init__(self, **kw):
1520        super(StatusMessage, self).__init__(**kw)
1521       
1522        # Value attribute URI.
1523        self.__value = None       
1524
1525    def __getstate__(self):
1526        '''Enable pickling'''
1527        _dict = super(StatusMessage, self).__getstate__()
1528        for attrName in StatusMessage.__slots__:
1529            # Ugly hack to allow for derived classes setting private member
1530            # variables
1531            if attrName.startswith('__'):
1532                attrName = "_StatusMessage" + attrName
1533               
1534            _dict[attrName] = getattr(self, attrName)
1535           
1536        return _dict
1537   
1538    def _getValue(self):
1539        return self.__value
1540       
1541    def _setValue(self, value):
1542        if not isinstance(value, basestring):
1543            raise TypeError("\"value\" must be a basestring derived type, "
1544                            "got %r" % type(value))
1545           
1546        self.__value = value
1547
1548    value = property(fget=_getValue, fset=_setValue, doc="Status message value")
1549
1550
1551class StatusCode(SAMLObject):
1552    '''Implementation of SAML 2.0 StatusCode.'''
1553   
1554    # Local Name of StatusCode.
1555    DEFAULT_ELEMENT_LOCAL_NAME = "StatusCode"
1556
1557    # Default element name.
1558    DEFAULT_ELEMENT_NAME = QName(SAMLConstants.SAML20P_NS, 
1559                                 DEFAULT_ELEMENT_LOCAL_NAME,
1560                                 SAMLConstants.SAML20P_PREFIX)
1561
1562    # Local name of the XSI type.
1563    TYPE_LOCAL_NAME = "StatusCodeType"
1564
1565    # QName of the XSI type.
1566    TYPE_NAME = QName(SAMLConstants.SAML20P_NS, 
1567                      TYPE_LOCAL_NAME,
1568                      SAMLConstants.SAML20P_PREFIX)
1569
1570    # Local Name of the Value attribute.
1571    VALUE_ATTRIB_NAME = "Value"
1572
1573    # URI for Success status code.
1574    SUCCESS_URI = "urn:oasis:names:tc:SAML:2.0:status:Success"
1575
1576    # URI for Requester status code.
1577    REQUESTER_URI = "urn:oasis:names:tc:SAML:2.0:status:Requester"
1578
1579    # URI for Responder status code.
1580    RESPONDER_URI = "urn:oasis:names:tc:SAML:2.0:status:Responder"
1581
1582    # URI for VersionMismatch status code.
1583    VERSION_MISMATCH_URI = "urn:oasis:names:tc:SAML:2.0:status:VersionMismatch"
1584
1585    # URI for AuthnFailed status code.
1586    AUTHN_FAILED_URI = "urn:oasis:names:tc:SAML:2.0:status:AuthnFailed"
1587
1588    # URI for InvalidAttrNameOrValue status code.
1589    INVALID_ATTR_NAME_VALUE_URI = \
1590                "urn:oasis:names:tc:SAML:2.0:status:InvalidAttrNameOrValue"
1591
1592    # URI for InvalidNameIDPolicy status code.
1593    INVALID_NAMEID_POLICY_URI = \
1594                "urn:oasis:names:tc:SAML:2.0:status:InvalidNameIDPolicy"
1595
1596    # URI for NoAuthnContext status code.
1597    NO_AUTHN_CONTEXT_URI = "urn:oasis:names:tc:SAML:2.0:status:NoAuthnContext"
1598
1599    # URI for NoAvailableIDP status code.
1600    NO_AVAILABLE_IDP_URI = "urn:oasis:names:tc:SAML:2.0:status:NoAvailableIDP"
1601
1602    # URI for NoPassive status code.
1603    NO_PASSIVE_URI = "urn:oasis:names:tc:SAML:2.0:status:NoPassive"
1604
1605    # URI for NoSupportedIDP status code.
1606    NO_SUPPORTED_IDP_URI = "urn:oasis:names:tc:SAML:2.0:status:NoSupportedIDP"
1607
1608    # URI for PartialLogout status code.
1609    PARTIAL_LOGOUT_URI = "urn:oasis:names:tc:SAML:2.0:status:PartialLogout"
1610
1611    # URI for ProxyCountExceeded status code.
1612    PROXY_COUNT_EXCEEDED_URI = \
1613                "urn:oasis:names:tc:SAML:2.0:status:ProxyCountExceeded"
1614
1615    # URI for RequestDenied status code.
1616    REQUEST_DENIED_URI = "urn:oasis:names:tc:SAML:2.0:status:RequestDenied"
1617
1618    # URI for RequestUnsupported status code.
1619    REQUEST_UNSUPPORTED_URI = \
1620                "urn:oasis:names:tc:SAML:2.0:status:RequestUnsupported"
1621
1622    # URI for RequestVersionDeprecated status code.
1623    REQUEST_VERSION_DEPRECATED_URI = \
1624                "urn:oasis:names:tc:SAML:2.0:status:RequestVersionDeprecated"
1625
1626    # URI for RequestVersionTooHigh status code.
1627    REQUEST_VERSION_TOO_HIGH_URI = \
1628                "urn:oasis:names:tc:SAML:2.0:status:RequestVersionTooHigh"
1629   
1630    # URI for RequestVersionTooLow status code.
1631    REQUEST_VERSION_TOO_LOW_URI = \
1632                "urn:oasis:names:tc:SAML:2.0:status:RequestVersionTooLow"
1633
1634    # URI for ResourceNotRecognized status code.
1635    RESOURCE_NOT_RECOGNIZED_URI = \
1636                "urn:oasis:names:tc:SAML:2.0:status:ResourceNotRecognized"
1637
1638    # URI for TooManyResponses status code.
1639    TOO_MANY_RESPONSES = "urn:oasis:names:tc:SAML:2.0:status:TooManyResponses"
1640
1641    # URI for UnknownAttrProfile status code.
1642    UNKNOWN_ATTR_PROFILE_URI = \
1643                "urn:oasis:names:tc:SAML:2.0:status:UnknownAttrProfile"
1644
1645    # URI for UnknownPrincipal status code.
1646    UNKNOWN_PRINCIPAL_URI = \
1647                "urn:oasis:names:tc:SAML:2.0:status:UnknownPrincipal"
1648
1649    # URI for UnsupportedBinding status code.
1650    UNSUPPORTED_BINDING_URI = \
1651                "urn:oasis:names:tc:SAML:2.0:status:UnsupportedBinding"
1652
1653    __slots__ = ('__value', '__childStatusCode',)
1654   
1655    def __init__(self, **kw):
1656        super(StatusCode, self).__init__(**kw)
1657       
1658        # Value attribute URI.
1659        self.__value = None
1660   
1661        # Nested secondary StatusCode child element.
1662        self.__childStatusCode = None
1663
1664    def __getstate__(self):
1665        '''Enable pickling'''
1666        _dict = super(StatusCode, self).__getstate__()
1667        for attrName in StatusCode.__slots__:
1668            # Ugly hack to allow for derived classes setting private member
1669            # variables
1670            if attrName.startswith('__'):
1671                attrName = "_StatusCode" + attrName
1672               
1673            _dict[attrName] = getattr(self, attrName)
1674           
1675        return _dict
1676   
1677    def _getStatusCode(self): 
1678        return self.__childStatusCode
1679   
1680    def _setStatusCode(self, value):
1681        if not isinstance(value, StatusCode):
1682            raise TypeError('Child "statusCode" must be a %r derived type, '
1683                            "got %r" % (StatusCode, type(value)))
1684           
1685        self.__childStatusCode = value
1686
1687    value = property(fget=_getStatusCode, 
1688                     fset=_setStatusCode, 
1689                     doc="Child Status code")
1690             
1691    def _getValue(self):
1692        return self.__value
1693       
1694    def _setValue(self, value):
1695        if not isinstance(value, basestring):
1696            raise TypeError("\"value\" must be a basestring derived type, "
1697                            "got %r" % value.__class__)
1698           
1699        self.__value = value
1700
1701    value = property(fget=_getValue, fset=_setValue, doc="Status code value")
1702       
1703
1704class Status(SAMLObject): 
1705    '''SAML 2.0 Core Status'''
1706   
1707    # Local Name of Status.
1708    DEFAULT_ELEMENT_LOCAL_NAME = "Status"
1709
1710    # Default element name.
1711    DEFAULT_ELEMENT_NAME = QName(SAMLConstants.SAML20P_NS, 
1712                                 DEFAULT_ELEMENT_LOCAL_NAME,
1713                                 SAMLConstants.SAML20P_PREFIX)
1714
1715    # Local name of the XSI type.
1716    TYPE_LOCAL_NAME = "StatusType"
1717
1718    # QName of the XSI type.
1719    TYPE_NAME = QName(SAMLConstants.SAML20P_NS, 
1720                      TYPE_LOCAL_NAME,
1721                      SAMLConstants.SAML20P_PREFIX)
1722
1723    __slots__ = ('__statusCode', '__statusMessage', '__statusDetail', )
1724   
1725    def __init__(self, **kw):
1726        super(Status, self).__init__(**kw)
1727       
1728        # StatusCode element.
1729        self.__statusCode = None
1730   
1731        # StatusMessage element.
1732        self.__statusMessage = None
1733   
1734        # StatusDetail element.
1735        self.__statusDetail = None
1736       
1737    def __getstate__(self):
1738        '''Enable pickling'''
1739        _dict = super(Status, self).__getstate__()
1740        for attrName in Status.__slots__:
1741            # Ugly hack to allow for derived classes setting private member
1742            # variables
1743            if attrName.startswith('__'):
1744                attrName = "_Status" + attrName
1745               
1746            _dict[attrName] = getattr(self, attrName)
1747           
1748        return _dict
1749   
1750    def _getStatusCode(self):
1751        '''
1752        Gets the Code of this Status.
1753       
1754        @return: Status StatusCode
1755        '''
1756        return self.__statusCode
1757
1758    def _setStatusCode(self, value):
1759        '''
1760        Sets the Code of this Status.
1761       
1762        @param value: the Code of this Status
1763        '''
1764        if not isinstance(value, StatusCode):
1765            raise TypeError('"statusCode" must be a %r derived type, '
1766                            "got %r" % (StatusCode, type(value)))
1767           
1768        self.__statusCode = value
1769       
1770    statusCode = property(fget=_getStatusCode,
1771                          fset=_setStatusCode,
1772                          doc="status code object")
1773   
1774    def _getStatusMessage(self):
1775        '''
1776        Gets the Message of this Status.
1777       
1778        @return: Status StatusMessage
1779        '''
1780        return self.__statusMessage
1781
1782    def _setStatusMessage(self, value):
1783        '''
1784        Sets the Message of this Status.
1785       
1786        @param value: the Message of this Status
1787        '''
1788        if not isinstance(value, StatusMessage):
1789            raise TypeError('"statusMessage" must be a %r derived type, '
1790                            "got %r" % (StatusMessage, type(value)))
1791           
1792        self.__statusMessage = value
1793       
1794    statusMessage = property(fget=_getStatusMessage,
1795                             fset=_setStatusMessage,
1796                             doc="status message")
1797
1798    def _getStatusDetail(self):
1799        '''
1800        Gets the Detail of this Status.
1801       
1802        @return: Status StatusDetail
1803        '''
1804        return self.__statusDetail
1805   
1806    def _setStatusDetail(self, value):
1807        '''
1808        Sets the Detail of this Status.
1809       
1810        @param value: the Detail of this Status
1811        '''
1812        self.__statusDetail = value
1813       
1814    statusDetail = property(fget=_getStatusDetail,
1815                            fset=_setStatusDetail,
1816                            doc="status message")
1817
1818
1819class Action(SAMLObject): 
1820    '''SAML 2.0 Core Action'''
1821   
1822    # Element local name.
1823    DEFAULT_ELEMENT_LOCAL_NAME = "Action"
1824
1825    # Default element name.
1826    DEFAULT_ELEMENT_NAME = QName(SAMLConstants.SAML20_NS, 
1827                                 DEFAULT_ELEMENT_LOCAL_NAME,
1828                                 SAMLConstants.SAML20_PREFIX)
1829
1830    # Local name of the XSI type.
1831    TYPE_LOCAL_NAME = "ActionType"
1832
1833    # QName of the XSI type
1834    TYPE_NAME = QName(SAMLConstants.SAML20_NS, 
1835                      TYPE_LOCAL_NAME,
1836                      SAMLConstants.SAML20_PREFIX)
1837
1838    # Name of the Namespace attribute.
1839    NAMESPACE_ATTRIB_NAME = "Namespace"
1840
1841    # Read/Write/Execute/Delete/Control action namespace.
1842    RWEDC_NS_URI = "urn:oasis:names:tc:SAML:1.0:action:rwedc"
1843
1844    # Read/Write/Execute/Delete/Control negation action namespace.
1845    RWEDC_NEGATION_NS_URI = "urn:oasis:names:tc:SAML:1.0:action:rwedc-negation"
1846
1847    # Get/Head/Put/Post action namespace.
1848    GHPP_NS_URI = "urn:oasis:names:tc:SAML:1.0:action:ghpp"
1849
1850    # UNIX file permission action namespace.
1851    UNIX_NS_URI = "urn:oasis:names:tc:SAML:1.0:action:unix"
1852
1853    ACTION_NS_IDENTIFIERS = (
1854        RWEDC_NS_URI,
1855        RWEDC_NEGATION_NS_URI,   
1856        GHPP_NS_URI,
1857        UNIX_NS_URI       
1858    )
1859   
1860    # Read action.
1861    READ_ACTION = "Read"
1862
1863    # Write action.
1864    WRITE_ACTION = "Write"
1865
1866    # Execute action.
1867    EXECUTE_ACTION = "Execute"
1868
1869    # Delete action.
1870    DELETE_ACTION = "Delete"
1871
1872    # Control action.
1873    CONTROL_ACTION = "Control"
1874
1875    # Negated Read action.
1876    NEG_READ_ACTION = "~Read"
1877
1878    # Negated Write action.
1879    NEG_WRITE_ACTION = "~Write"
1880
1881    # Negated Execute action.
1882    NEG_EXECUTE_ACTION = "~Execute"
1883
1884    # Negated Delete action.
1885    NEG_DELETE_ACTION = "~Delete"
1886
1887    # Negated Control action.
1888    NEG_CONTROL_ACTION = "~Control"
1889
1890    # HTTP GET action.
1891    HTTP_GET_ACTION = "GET"
1892
1893    # HTTP HEAD action.
1894    HTTP_HEAD_ACTION = "HEAD"
1895
1896    # HTTP PUT action.
1897    HTTP_PUT_ACTION = "PUT"
1898
1899    # HTTP POST action.
1900    HTTP_POST_ACTION = "POST"
1901   
1902    ACTION_TYPES = {
1903        RWEDC_NS_URI: (READ_ACTION, WRITE_ACTION, EXECUTE_ACTION, DELETE_ACTION,
1904                       CONTROL_ACTION),
1905        RWEDC_NEGATION_NS_URI: (READ_ACTION, WRITE_ACTION, EXECUTE_ACTION, 
1906                                DELETE_ACTION, CONTROL_ACTION, NEG_READ_ACTION, 
1907                                NEG_WRITE_ACTION, NEG_EXECUTE_ACTION, 
1908                                NEG_CONTROL_ACTION),   
1909        GHPP_NS_URI: (HTTP_GET_ACTION, HTTP_HEAD_ACTION, HTTP_PUT_ACTION,
1910                      HTTP_POST_ACTION),
1911                     
1912        # This namespace uses octal bitmask for file permissions
1913        UNIX_NS_URI: ()   
1914    }
1915   
1916    __slots__ = ('__namespace', '__value', '__actionTypes')
1917   
1918    def __init__(self, **kw):
1919        '''Create an authorization action type
1920        '''
1921        super(Action, self).__init__(**kw)
1922
1923        # URI of the Namespace of this action.  Default to read/write/negation
1924        # type - 2.7.4.2 SAML 2 Core Spec. 15 March 2005
1925        self.__namespace = Action.RWEDC_NEGATION_NS_URI
1926
1927        # Action value
1928        self.__value = None       
1929   
1930        self.__actionTypes = Action.ACTION_TYPES
1931       
1932    def __getstate__(self):
1933        '''Enable pickling'''
1934        _dict = super(Action, self).__getstate__()
1935        for attrName in Action.__slots__:
1936            # Ugly hack to allow for derived classes setting private member
1937            # variables
1938            if attrName.startswith('__'):
1939                attrName = "_Action" + attrName
1940               
1941            _dict[attrName] = getattr(self, attrName)
1942           
1943        return _dict
1944   
1945    def _getActionTypes(self):
1946        return self.__actionTypes
1947
1948    def _setActionTypes(self, value):
1949        if not isinstance(value, dict):
1950            raise TypeError('Expecting list or tuple type for "actionTypes" '
1951                            'attribute; got %r' % type(value))
1952           
1953        for k, v in value.items():
1954            if not isinstance(v, (tuple, type(None))):
1955                raise TypeError('Expecting None or tuple type for '
1956                                '"actionTypes" dictionary values; got %r for '
1957                                '%r key' % (type(value), k))
1958        self.__actionTypes = value
1959
1960    actionTypes = property(_getActionTypes, 
1961                           _setActionTypes, 
1962                           doc="Restrict vocabulary of action types")
1963       
1964    def _getNamespace(self):
1965        '''
1966        gets the namespace scope of the specified value.
1967       
1968        @return: the namespace scope of the specified value
1969        '''
1970        return self.__namespace
1971
1972    def _setNamespace(self, value):
1973        '''Sets the namespace scope of the specified value.
1974       
1975        @param value: the namespace scope of the specified value
1976        '''
1977        if not isinstance(value, basestring):
1978            raise TypeError('Expecting string type for "namespace" '
1979                            'attribute; got %r' % type(value))
1980           
1981        if value not in self.__actionTypes.keys():
1982            raise AttributeError('"namespace" action type %r not recognised. '
1983                                 'It must be one of these action types: %r' % 
1984                                 self.__actionTypes.keys())
1985           
1986        self.__namespace = value
1987
1988    namespace = property(_getNamespace, _setNamespace, doc="Action Namespace")
1989
1990    def _getValue(self):
1991        '''gets the URI of the action to be performed.
1992       
1993        @return: the URI of the action to be performed
1994        '''
1995        return self.__value
1996
1997    def _setValue(self, value):
1998        '''Sets the URI of the action to be performed.
1999       
2000        @param value: the URI of the value to be performed
2001        '''
2002        # int and oct allow for UNIX file permissions action type
2003        if not isinstance(value, (basestring, int)):
2004            raise TypeError('Expecting string or int type for "action" '
2005                            'attribute; got %r' % type(value))
2006           
2007        # Default to read/write/negation type - 2.7.4.2 SAML 2 Core Spec.
2008        # 15 March 2005
2009        allowedActions = self.__actionTypes.get(self.__namespace,
2010                                                Action.RWEDC_NEGATION_NS_URI)
2011       
2012        # Only apply restriction for action type that has a restricted
2013        # vocabulary - UNIX type is missed out of this because its an octal
2014        # mask
2015        if len(allowedActions) > 0 and value not in allowedActions:
2016            raise AttributeError('%r action not recognised; known actions for '
2017                                 'the %r namespace identifier are: %r.  ' 
2018                                 'If this is not as expected make sure to set '
2019                                 'the "namespace" attribute to an alternative '
2020                                 'value first or override completely by '
2021                                 'explicitly setting the "allowTypes" '
2022                                 'attribute' % 
2023                                 (value, self.__namespace, allowedActions))
2024        self.__value = value
2025
2026    value = property(_getValue, _setValue, doc="Action string")
2027       
2028
2029class RequestAbstractType(SAMLObject): 
2030    '''SAML 2.0 Core RequestAbstractType'''
2031   
2032    # Local name of the XSI type.
2033    TYPE_LOCAL_NAME = "RequestAbstractType"
2034
2035    # QName of the XSI type.
2036    TYPE_NAME = QName(SAMLConstants.SAML20P_NS, 
2037                      TYPE_LOCAL_NAME,
2038                      SAMLConstants.SAML20P_PREFIX)
2039
2040    # ID attribute name.
2041    ID_ATTRIB_NAME = "ID"
2042
2043    # Version attribute name.
2044    VERSION_ATTRIB_NAME = "Version"
2045
2046    # IssueInstant attribute name.
2047    ISSUE_INSTANT_ATTRIB_NAME = "IssueInstant"
2048
2049    # Destination attribute name.
2050    DESTINATION_ATTRIB_NAME = "Destination"
2051
2052    # Consent attribute name.
2053    CONSENT_ATTRIB_NAME = "Consent"
2054
2055    # Unspecified consent URI.
2056    UNSPECIFIED_CONSENT = "urn:oasis:names:tc:SAML:2.0:consent:unspecified"
2057
2058    # Obtained consent URI.
2059    OBTAINED_CONSENT = "urn:oasis:names:tc:SAML:2.0:consent:obtained"
2060
2061    # Prior consent URI.
2062    PRIOR_CONSENT = "urn:oasis:names:tc:SAML:2.0:consent:prior"
2063
2064    # Implicit consent URI.
2065    IMPLICIT_CONSENT = "urn:oasis:names:tc:SAML:2.0:consent:implicit"
2066
2067    # Explicit consent URI.
2068    EXPLICIT_CONSENT = "urn:oasis:names:tc:SAML:2.0:consent:explicit"
2069
2070    # Unavailable consent URI.
2071    UNAVAILABLE_CONSENT = "urn:oasis:names:tc:SAML:2.0:consent:unavailable"
2072
2073    # Inapplicable consent URI.
2074    INAPPLICABLE_CONSENT = "urn:oasis:names:tc:SAML:2.0:consent:inapplicable"
2075     
2076    __slots__ = (
2077        '__version',
2078        '__id',
2079        '__issueInstant',
2080        '__destination',
2081        '__consent',
2082        '__issuer',
2083        '__extensions'
2084    )
2085   
2086    def __init__(self, **kw):
2087        '''Request abstract type
2088        @type kw: dict
2089        @param kw: see SAMLObject.__init__
2090        '''
2091        super(RequestAbstractType, self).__init__(**kw)
2092       
2093        # SAML Version of the request.
2094        self.__version = None
2095   
2096        # Unique identifier of the request.
2097        self.__id = None
2098   
2099        # Date/time request was issued.
2100        self.__issueInstant = None
2101   
2102        # URI of the request destination.
2103        self.__destination = None
2104   
2105        # URI of the SAML user consent type.
2106        self.__consent = None
2107   
2108        # URI of the SAML user consent type.
2109        self.__issuer = None
2110   
2111        # Extensions child element.
2112        self.__extensions = None
2113
2114    def __getstate__(self):
2115        '''Enable pickling'''
2116        _dict = super(RequestAbstractType, self).__getstate__()
2117        for attrName in RequestAbstractType.__slots__:
2118            # Ugly hack to allow for derived classes setting private member
2119            # variables
2120            if attrName.startswith('__'):
2121                attrName = "_RequestAbstractType" + attrName
2122               
2123            _dict[attrName] = getattr(self, attrName)
2124           
2125        return _dict
2126   
2127    def _get_version(self):
2128        '''@return: the SAML Version of this assertion.
2129        '''
2130        return self.__version
2131   
2132    def _set_version(self, version):
2133        '''@param version: the SAML Version of this assertion
2134        '''
2135        if not isinstance(version, SAMLVersion):
2136            raise TypeError("Expecting SAMLVersion type got: %r" % 
2137                            version.__class__)
2138       
2139        self.__version = version
2140       
2141    version = property(fget=_get_version,
2142                       fset=_set_version,
2143                       doc="SAML Version of the assertion")
2144
2145    def _get_issueInstant(self):
2146        '''Gets the date/time the request was issued
2147       
2148        @return: the issue instance of this request'''
2149        return self.__issueInstant
2150   
2151    def _set_issueInstant(self, value):
2152        '''Sets the date/time the request was issued
2153       
2154        @param value: the issue instance of this request
2155        '''
2156        if not isinstance(value, datetime):
2157            raise TypeError('Expecting "datetime" type for "issueInstant", '
2158                            'got %r' % type(value))
2159           
2160        self.__issueInstant = value
2161       
2162    issueInstant = property(fget=_get_issueInstant, 
2163                            fset=_set_issueInstant,
2164                            doc="Issue instant of the request") 
2165
2166    def _get_id(self):
2167        '''Sets the unique identifier for this request.
2168       
2169        @return: the ID of this request
2170        '''
2171        return self.__id
2172   
2173    def _set_id(self, value):
2174        '''Sets the unique identifier for this request
2175       
2176        @param value: the ID of this assertion
2177        '''
2178        if not isinstance(value, basestring):
2179            raise TypeError('Expecting basestring derived type for "id", got '
2180                            '%r' % type(value))
2181        self.__id = value
2182       
2183    id = property(fget=_get_id, fset=_set_id, doc="ID of request")
2184
2185    def _get_destination(self):
2186        '''Gets the URI of the destination of the request.
2187       
2188        @return: the URI of the destination of the request
2189        '''
2190        return self.__destination
2191   
2192    def _set_destination(self, value):
2193        '''Sets the URI of the destination of the request.
2194       
2195        @param value: the URI of the destination of the request'''
2196        if not isinstance(value, basestring):
2197            raise TypeError('Expecting basestring derived type for '
2198                            '"destination", got %r' % type(value))
2199        self.__destination = value
2200       
2201    destination = property(fget=_get_destination, 
2202                           fset=_set_destination,
2203                           doc="Destination of request")
2204     
2205    def _get_consent(self):
2206        '''Gets the consent obtained from the principal for sending this
2207        request.
2208       
2209        @return: the consent obtained from the principal for sending this
2210        request
2211        '''
2212        return self.__consent
2213       
2214    def _set_consent(self, value):
2215        '''Sets the consent obtained from the principal for sending this
2216        request.
2217       
2218        @param value: the new consent obtained from the principal for
2219        sending this request
2220        ''' 
2221        if not isinstance(value, basestring):
2222            raise TypeError('Expecting basestring derived type for "consent", '
2223                            'got %r' % type(value))
2224        self.__consent = value
2225             
2226    consent = property(fget=_get_consent, 
2227                       fset=_set_consent,
2228                       doc="Consent for request")
2229   
2230    def _set_issuer(self, issuer):
2231        """Set issuer of request"""
2232        if not isinstance(issuer, Issuer):
2233            raise TypeError('"issuer" must be a %r, got %r' % (Issuer, 
2234                                                               type(issuer)))
2235       
2236        self.__issuer = issuer
2237   
2238    def _get_issuer(self):
2239        """Get the issuer name """
2240        return self.__issuer
2241
2242    issuer = property(fget=_get_issuer, 
2243                      fset=_set_issuer,
2244                      doc="Issuer of request")
2245 
2246    def _get_extensions(self):
2247        '''Gets the Extensions of this request.
2248       
2249        @return: the Status of this request
2250        '''
2251        return self.__extensions
2252     
2253    def _set_extensions(self, value):
2254        '''Sets the Extensions of this request.
2255       
2256        @param value: the Extensions of this request
2257        '''
2258        self.__extensions = value
2259       
2260    extensions = property(fget=_get_extensions, 
2261                          fset=_set_extensions,
2262                          doc="Request extensions")
2263
2264
2265class SubjectQuery(RequestAbstractType):
2266    """SAML 2.0 Core Subject Query type"""
2267   
2268    DEFAULT_ELEMENT_LOCAL_NAME = 'SubjectQuery'
2269   
2270    __slots__ = ('__subject', )
2271   
2272    def __init__(self):
2273        super(SubjectQuery, self).__init__()
2274        self.__subject = None
2275
2276    def __getstate__(self):
2277        '''Enable pickling'''
2278        _dict = super(SubjectQuery, self).__getstate__()
2279        for attrName in SubjectQuery.__slots__:
2280            # Ugly hack to allow for derived classes setting private member
2281            # variables
2282            if attrName.startswith('__'):
2283                attrName = "_SubjectQuery" + attrName
2284               
2285            _dict[attrName] = getattr(self, attrName)
2286           
2287        return _dict
2288           
2289    def _getSubject(self):
2290        '''Gets the Subject of this request.
2291       
2292        @return: the Subject of this request'''   
2293        return self.__subject
2294   
2295    def _setSubject(self, value):
2296        '''Sets the Subject of this request.
2297       
2298        @param value: the Subject of this request'''
2299        if not isinstance(value, Subject):
2300            raise TypeError('Setting "subject", got %r, expecting %r' %
2301                            (Subject, type(value)))
2302           
2303        self.__subject = value
2304       
2305    subject = property(fget=_getSubject, fset=_setSubject, doc="Query subject")
2306   
2307   
2308class AttributeQuery(SubjectQuery):
2309    '''SAML 2.0 AttributeQuery'''
2310   
2311    # Element local name.
2312    DEFAULT_ELEMENT_LOCAL_NAME = "AttributeQuery"
2313
2314    # Default element name.
2315    DEFAULT_ELEMENT_NAME = QName(SAMLConstants.SAML20P_NS, 
2316                                 DEFAULT_ELEMENT_LOCAL_NAME,
2317                                 SAMLConstants.SAML20P_PREFIX)
2318
2319    # Local name of the XSI type.
2320    TYPE_LOCAL_NAME = "AttributeQueryType"
2321
2322    # QName of the XSI type.
2323    TYPE_NAME = QName(SAMLConstants.SAML20P_NS, 
2324                      TYPE_LOCAL_NAME,
2325                      SAMLConstants.SAML20P_PREFIX)
2326
2327    __slots__ = ('__attributes',)
2328   
2329    def __init__(self):
2330        super(AttributeQuery, self).__init__()
2331        self.__attributes = TypedList(Attribute)
2332
2333    def __getstate__(self):
2334        '''Enable pickling'''
2335        _dict = super(AttributeQuery, self).__getstate__()
2336        for attrName in AttributeQuery.__slots__:
2337            # Ugly hack to allow for derived classes setting private member
2338            # variables
2339            if attrName.startswith('__'):
2340                attrName = "_AttributeQuery" + attrName
2341               
2342            _dict[attrName] = getattr(self, attrName)
2343           
2344        return _dict
2345 
2346    def _getAttributes(self):
2347        '''Gets the Attributes of this query.
2348       
2349        @return: the list of Attributes of this query'''
2350        return self.__attributes
2351
2352    def _setAttributes(self, value):
2353        self.__attributes = value
2354
2355    attributes = property(fget=_getAttributes, 
2356                          fset=_setAttributes, 
2357                          doc="Attributes")
2358
2359
2360class Evidentiary(SAMLObject):
2361    """Base class for types set in an evidence object"""
2362    __slots__ = ()
2363
2364
2365class AssertionURIRef(Evidentiary):
2366    '''SAML 2.0 Core AssertionURIRef'''
2367    __slots__ = ('__assertionURI',)
2368   
2369    # Element local name
2370    DEFAULT_ELEMENT_LOCAL_NAME = "AssertionURIRef"
2371
2372    # Default element name
2373    DEFAULT_ELEMENT_NAME = QName(SAMLConstants.SAML20_NS, 
2374                                 DEFAULT_ELEMENT_LOCAL_NAME,
2375                                 SAMLConstants.SAML20_PREFIX)
2376   
2377    def __init__(self):
2378        '''Create assertion URI reference'''
2379        super(AssertionURIRef, self).__init__()
2380       
2381        # URI of the Assertion
2382        self.__assertionURI = None   
2383
2384    def __getstate__(self):
2385        '''Enable pickling'''
2386        _dict = super(AssertionURIRef, self).__getstate__()
2387        for attrName in AssertionURIRef.__slots__:
2388            # Ugly hack to allow for derived classes setting private member
2389            # variables
2390            if attrName.startswith('__'):
2391                attrName = "_AssertionURIRef" + attrName
2392               
2393            _dict[attrName] = getattr(self, attrName)
2394           
2395        return _dict
2396   
2397    def _getAssertionURI(self):
2398        return self.__assertionURI
2399
2400    def _setAssertionURI(self, value):
2401        if not isinstance(value, basestring):
2402            raise TypeError('Expecting string type for "assertionID" '
2403                            'attribute; got %r' % type(value))
2404        self.__assertionURI = value
2405
2406    def getOrderedChildren(self):
2407        return None
2408
2409    assertionURI = property(_getAssertionURI, _setAssertionURI, 
2410                            doc="Assertion URI")
2411   
2412   
2413class AssertionIDRef(Evidentiary):
2414    '''SAML 2.0 Core AssertionIDRef.'''
2415
2416    # Element local name.
2417    DEFAULT_ELEMENT_LOCAL_NAME = "AssertionIDRef"
2418
2419    # Default element name.
2420    DEFAULT_ELEMENT_NAME = QName(SAMLConstants.SAML20_NS, 
2421                                 DEFAULT_ELEMENT_LOCAL_NAME,
2422                                 SAMLConstants.SAML20_PREFIX)
2423   
2424    __slots__ = ("_AssertionID",)
2425   
2426    def __init__(self, namespaceURI, elementLocalName, namespacePrefix):
2427        '''
2428        @param namespaceURI: the namespace the element is in
2429        @param elementLocalName: the local name of the XML element this Object
2430        represents
2431        @param namespacePrefix: the prefix for the given namespace
2432        '''
2433        super(AssertionIDRef, self).__init__(namespaceURI, 
2434                                             elementLocalName, 
2435                                             namespacePrefix)
2436        self.__assertionID = None
2437
2438    def __getstate__(self):
2439        '''Enable pickling'''
2440        _dict = super(AssertionIDRef, self).__getstate__()
2441        for attrName in AssertionIDRef.__slots__:
2442            # Ugly hack to allow for derived classes setting private member
2443            # variables
2444            if attrName.startswith('__'):
2445                attrName = "_AssertionIDRef" + attrName
2446               
2447            _dict[attrName] = getattr(self, attrName)
2448           
2449        return _dict
2450       
2451    def _getAssertionID(self):
2452        '''Gets the ID of the assertion this references.
2453       
2454        @return: the ID of the assertion this references'''
2455        return self.__assertionID
2456       
2457    def _setAssertionID(self, value):
2458        '''Sets the ID of the assertion this references.
2459       
2460        @param value: the ID of the assertion this references'''
2461        if not isinstance(value, basestring):
2462            raise TypeError('Expecting string type for "assertionID" '
2463                            'attribute; got %r' % type(value))
2464        self.__assertionID = value
2465
2466    def getOrderedChildren(self):
2467        return None
2468
2469    assertionID = property(_getAssertionID, _setAssertionID, 
2470                           doc="Assertion ID")
2471       
2472   
2473class EncryptedElementType(SAMLObject):
2474    '''SAML 2.0 Core EncryptedElementType'''
2475   
2476    # Local name of the XSI type.
2477    TYPE_LOCAL_NAME = "EncryptedElementType"
2478       
2479    # QName of the XSI type.
2480    TYPE_NAME = QName(SAMLConstants.SAML20_NS, 
2481                      TYPE_LOCAL_NAME, 
2482                      SAMLConstants.SAML20_PREFIX)
2483   
2484    __slots__ = ()
2485   
2486    def _getEncryptedData(self):
2487        '''Get the EncryptedData child element.
2488       
2489        @return the EncryptedData child element'''
2490        raise NotImplementedError()
2491   
2492    def _setEncryptedData(self, value):
2493        '''Set the EncryptedData child element.
2494       
2495        @param newEncryptedData the new EncryptedData child element'''
2496        raise NotImplementedError()
2497   
2498    def _getEncryptedKeys(self):
2499        '''A list of EncryptedKey child elements.
2500       
2501        @return a list of EncryptedKey child elements'''
2502        raise NotImplementedError()
2503   
2504   
2505class EncryptedAssertion(EncryptedElementType, Evidentiary):
2506    '''SAML 2.0 Core EncryptedAssertion.'''
2507   
2508    # Element local name.
2509    DEFAULT_ELEMENT_LOCAL_NAME = "EncryptedAssertion"
2510
2511    # Default element name.
2512    DEFAULT_ELEMENT_NAME = QName(SAMLConstants.SAML20_NS, 
2513                                 DEFAULT_ELEMENT_LOCAL_NAME,
2514                                 SAMLConstants.SAML20_PREFIX) 
2515    __slots__ = ()
2516     
2517   
2518class Evidence(SAMLObject):
2519    '''SAML 2.0 Core Evidence.'''
2520   
2521    # Element local name.
2522    DEFAULT_ELEMENT_LOCAL_NAME = "Evidence"
2523   
2524    # Default element name.
2525    DEFAULT_ELEMENT_NAME = QName(SAMLConstants.SAML20_NS, 
2526                                 DEFAULT_ELEMENT_LOCAL_NAME, 
2527                                 SAMLConstants.SAML20_PREFIX)
2528   
2529    # Local name of the XSI type.
2530    TYPE_LOCAL_NAME = "EvidenceType" 
2531       
2532    # QName of the XSI type.
2533    TYPE_NAME = QName(SAMLConstants.SAML20_NS, 
2534                      TYPE_LOCAL_NAME, 
2535                      SAMLConstants.SAML20_PREFIX)
2536
2537    __slots__ = ('__values',)
2538   
2539    def __init__(self, **kw):
2540        '''Create an authorization evidence type
2541        '''
2542        super(Evidence, self).__init__(**kw)
2543
2544        # Assertion of the Evidence.
2545        self.__values = TypedList(Evidentiary) 
2546
2547    def __getstate__(self):
2548        '''Enable pickling'''
2549        _dict = super(Evidence, self).__getstate__()
2550        for attrName in Evidence.__slots__:
2551            # Ugly hack to allow for derived classes setting private member
2552            # variables
2553            if attrName.startswith('__'):
2554                attrName = "_Evidence" + attrName
2555               
2556            _dict[attrName] = getattr(self, attrName)
2557           
2558        return _dict   
2559         
2560    @property
2561    def assertionIDReferences(self):
2562        '''Gets the list of AssertionID references used as evidence.
2563   
2564        @return: the list of AssertionID references used as evidence'''
2565        return [i for i in self.__values
2566                if (getattr(i, "DEFAULT_ELEMENT_NAME") == 
2567                    AssertionIDRef.DEFAULT_ELEMENT_NAME)]
2568   
2569    @property
2570    def assertionURIReferences(self):
2571        '''Gets the list of AssertionURI references used as evidence.
2572       
2573        @return: the list of AssertionURI references used as evidence'''
2574        return [i for i in self.__values
2575                if (getattr(i, "DEFAULT_ELEMENT_NAME") == 
2576                    AssertionURIRef.DEFAULT_ELEMENT_NAME)]
2577   
2578    @property
2579    def assertions(self):
2580        '''Gets the list of Assertions used as evidence.
2581       
2582        @return: the list of Assertions used as evidence'''
2583        return [i for i in self.__values
2584                if (getattr(i, "DEFAULT_ELEMENT_NAME") == 
2585                    Assertion.DEFAULT_ELEMENT_NAME)]
2586   
2587    @property
2588    def encryptedAssertions(self):
2589        '''Gets the list of EncryptedAssertions used as evidence.
2590       
2591        @return: the list of EncryptedAssertions used as evidence'''
2592        return [i for i in self.__values
2593                if (getattr(i, "DEFAULT_ELEMENT_NAME") == 
2594                    EncryptedAssertion.DEFAULT_ELEMENT_NAME)]   
2595
2596    @property
2597    def values(self):
2598        '''Gets the list of all elements used as evidence.
2599       
2600        @return: the list of Evidentiary objects used as evidence'''
2601        return self.__values
2602   
2603    def getOrderedChildren(self):
2604        children = []
2605
2606        if len(self.__values) == 0:
2607            return None
2608
2609        children.extend(self.__values)
2610
2611        return tuple(children)
2612   
2613
2614class AuthzDecisionQuery(SubjectQuery):
2615    '''SAML 2.0 AuthzDecisionQuery.'''
2616
2617    # Element local name.
2618    DEFAULT_ELEMENT_LOCAL_NAME = "AuthzDecisionQuery"
2619
2620    # Default element name.
2621    DEFAULT_ELEMENT_NAME = QName(SAMLConstants.SAML20P_NS, 
2622                                 DEFAULT_ELEMENT_LOCAL_NAME,
2623                                 SAMLConstants.SAML20P_PREFIX)
2624
2625    # Local name of the XSI type.
2626    TYPE_LOCAL_NAME = "AuthzDecisionQueryType"
2627
2628    # QName of the XSI type.
2629    TYPE_NAME = QName(SAMLConstants.SAML20P_NS, 
2630                      TYPE_LOCAL_NAME,
2631                      SAMLConstants.SAML20P_PREFIX)
2632
2633    # Resource attribute name.
2634    RESOURCE_ATTRIB_NAME = "Resource"
2635   
2636    __slots__ = (
2637       '__resource',
2638       '__evidence',
2639       '__actions',
2640       '__normalizeResource',
2641       '__safeNormalizationChars'
2642    )
2643   
2644    def __init__(self, normalizeResource=True, safeNormalizationChars='/%'):
2645        '''Create new authorisation decision query
2646        '''
2647        super(AuthzDecisionQuery, self).__init__()
2648
2649        # Resource attribute value.
2650        self.__resource = None
2651   
2652        # Evidence child element.
2653        self.__evidence = None
2654   
2655        # Action child elements.
2656        self.__actions = TypedList(Action)   
2657       
2658        # Tuning for normalization of resource URIs in property set method
2659        self.normalizeResource = normalizeResource
2660        self.safeNormalizationChars = safeNormalizationChars
2661
2662    def __getstate__(self):
2663        '''Enable pickling'''
2664        _dict = super(AuthzDecisionQuery, self).__getstate__()
2665        for attrName in AuthzDecisionQuery.__slots__:
2666            # Ugly hack to allow for derived classes setting private member
2667            # variables
2668            if attrName.startswith('__'):
2669                attrName = "_AuthzDecisionQuery" + attrName
2670               
2671            _dict[attrName] = getattr(self, attrName)
2672           
2673        return _dict
2674   
2675    def _getNormalizeResource(self):
2676        return self.__normalizeResource
2677
2678    def _setNormalizeResource(self, value):
2679        if not isinstance(value, bool):
2680            raise TypeError('Expecting bool type for "normalizeResource" '
2681                            'attribute; got %r instead' % type(value))
2682           
2683        self.__normalizeResource = value
2684
2685    normalizeResource = property(_getNormalizeResource, 
2686                                 _setNormalizeResource, 
2687                                 doc="Flag to normalize new resource value "
2688                                     "assigned to the \"resource\" property.  "
2689                                     "The setting only applies for URIs "
2690                                     'beginning with "http://" or "https://"')
2691
2692    def _getSafeNormalizationChars(self):
2693        return self.__safeNormalizationChars
2694
2695    def _setSafeNormalizationChars(self, value):
2696        if not isinstance(value, basestring):
2697            raise TypeError('Expecting string type for "normalizeResource" '
2698                            'attribute; got %r instead' % type(value))
2699           
2700        self.__safeNormalizationChars = value
2701
2702    safeNormalizationChars = property(_getSafeNormalizationChars, 
2703                                      _setSafeNormalizationChars, 
2704                                      doc="String containing a list of "
2705                                          "characters that should not be "
2706                                          "converted when Normalizing the "
2707                                          "resource URI.  These are passed to "
2708                                          "urllib.quote when the resource "
2709                                          "property is set.  The default "
2710                                          "characters are '/%'")
2711
2712    def _getResource(self):
2713        '''Gets the Resource attrib value of this query.
2714
2715        @return: the Resource attrib value of this query'''
2716        return self.__resource
2717   
2718    def _setResource(self, value):
2719        '''Sets the Resource attrib value of this query normalizing the path
2720        component, removing spurious port numbers (80 for HTTP and 443 for
2721        HTTPS) and converting the host component to lower case.
2722       
2723        @param value: the new Resource attrib value of this query'''
2724        if not isinstance(value, basestring):
2725            raise TypeError('Expecting string type for "resource" attribute; '
2726                            'got %r instead' % type(value))
2727       
2728        if (self.normalizeResource and 
2729            value.startswith('http://') or value.startswith('https://')):
2730            # Normalise the path, set the host name to lower case and remove
2731            # port redundant numbers 80 and 443
2732            splitResult = urlsplit(value)
2733            uriComponents = list(splitResult)
2734           
2735            # hostname attribute is lowercase
2736            uriComponents[1] = splitResult.hostname
2737           
2738            if splitResult.port is not None:
2739                isHttpWithStdPort = (splitResult.port == 80 and 
2740                                     splitResult.scheme == 'http')
2741               
2742                isHttpsWithStdPort = (splitResult.port == 443 and
2743                                      splitResult.scheme == 'https')
2744               
2745                if not isHttpWithStdPort and not isHttpsWithStdPort:
2746                    uriComponents[1] += ":%d" % splitResult.port
2747           
2748            uriComponents[2] = urllib.quote(splitResult.path, 
2749                                            self.safeNormalizationChars)
2750           
2751            self.__resource = urlunsplit(uriComponents)
2752        else:
2753            self.__resource = value
2754   
2755    resource = property(fget=_getResource, fset=_setResource,
2756                        doc="Resource for which authorisation is requested")
2757   
2758    @property
2759    def actions(self):
2760        '''The actions for which authorisation is requested
2761       
2762        @return: the Actions of this query'''
2763        return self.__actions
2764   
2765    def _getEvidence(self):
2766        '''Gets the Evidence of this query.
2767
2768        @return: the Evidence of this query'''
2769        return self.__evidence
2770
2771    def _setEvidence(self, value):
2772        '''Sets the Evidence of this query.
2773        @param newEvidence: the new Evidence of this query''' 
2774        if not isinstance(value, Evidence):
2775            raise TypeError('Expecting Evidence type for "evidence" '
2776                            'attribute; got %r' % type(value))
2777
2778        self.__evidence = value 
2779
2780    evidence = property(fget=_getEvidence, fset=_setEvidence, 
2781                        doc="A set of assertions which the Authority may use "
2782                            "to base its authorisation decision on")
2783   
2784    def getOrderedChildren(self):
2785        children = []
2786
2787        superChildren = super(AuthzDecisionQuery, self).getOrderedChildren()
2788        if superChildren:
2789            children.extend(superChildren)
2790
2791        children.extend(self.__actions)
2792       
2793        if self.__evidence is not None:
2794            children.extend(self.__evidence)
2795
2796        if len(children) == 0:
2797            return None
2798
2799        return tuple(children)
2800
2801
2802class StatusResponseType(SAMLObject):
2803    '''SAML 2.0 Core Status Response Type
2804    '''
2805
2806    # Local name of the XSI type.
2807    TYPE_LOCAL_NAME = "StatusResponseType"
2808
2809    # QName of the XSI type.
2810    TYPE_NAME = QName(SAMLConstants.SAML20P_NS, 
2811                      TYPE_LOCAL_NAME,
2812                      SAMLConstants.SAML20P_PREFIX)
2813
2814    # ID attribute name
2815    ID_ATTRIB_NAME = "ID"
2816
2817    # InResponseTo attribute name
2818    IN_RESPONSE_TO_ATTRIB_NAME = "InResponseTo"
2819
2820    # Version attribute name
2821    VERSION_ATTRIB_NAME = "Version"
2822
2823    # IssueInstant attribute name
2824    ISSUE_INSTANT_ATTRIB_NAME = "IssueInstant"
2825
2826    # Destination attribute name
2827    DESTINATION_ATTRIB_NAME = "Destination"
2828
2829    # Consent attribute name.
2830    CONSENT_ATTRIB_NAME = "Consent"
2831
2832    # Unspecified consent URI
2833    UNSPECIFIED_CONSENT = "urn:oasis:names:tc:SAML:2.0:consent:unspecified"
2834
2835    # Obtained consent URI
2836    OBTAINED_CONSENT = "urn:oasis:names:tc:SAML:2.0:consent:obtained"
2837
2838    # Prior consent URI
2839    PRIOR_CONSENT = "urn:oasis:names:tc:SAML:2.0:consent:prior"
2840
2841    # Implicit consent URI
2842    IMPLICIT_CONSENT = "urn:oasis:names:tc:SAML:2.0:consent:implicit"
2843
2844    # Explicit consent URI
2845    EXPLICIT_CONSENT = "urn:oasis:names:tc:SAML:2.0:consent:explicit"
2846
2847    # Unavailable consent URI
2848    UNAVAILABLE_CONSENT = "urn:oasis:names:tc:SAML:2.0:consent:unavailable"
2849
2850    # Inapplicable consent URI
2851    INAPPLICABLE_CONSENT = "urn:oasis:names:tc:SAML:2.0:consent:inapplicable"
2852
2853    __slots__ = (   
2854        '__version',
2855        '__id',
2856        '__inResponseTo',
2857        '__issueInstant',
2858        '__destination',
2859        '__consent',
2860        '__issuer',
2861        '__status',
2862        '__extensions'               
2863    )
2864   
2865    def __init__(self, **kw):
2866        super(StatusResponseType, self).__init__(**kw)
2867       
2868        self.__version = SAMLVersion(SAMLVersion.VERSION_20)
2869        self.__id = None
2870        self.__inResponseTo = None
2871        self.__issueInstant = None
2872        self.__destination = None
2873        self.__consent = None
2874        self.__issuer = None
2875        self.__status = None
2876        self.__extensions = None
2877
2878    def __getstate__(self):
2879        '''Enable pickling'''
2880        _dict = super(StatusResponseType, self).__getstate__()
2881        for attrName in StatusResponseType.__slots__:
2882            # Ugly hack to allow for derived classes setting private member
2883            # variables
2884            if attrName.startswith('__'):
2885                attrName = "_StatusResponseType" + attrName
2886               
2887            _dict[attrName] = getattr(self, attrName)
2888           
2889        return _dict
2890   
2891    def _get_version(self):
2892        '''@return: the SAML Version of this response.
2893        '''
2894        return self.__version
2895   
2896    def _set_version(self, version):
2897        '''@param version: the SAML Version of this response
2898        '''
2899        if not isinstance(version, SAMLVersion):
2900            raise TypeError("Expecting SAMLVersion type got: %r" % 
2901                            version.__class__)
2902       
2903        self.__version = version
2904       
2905    version = property(fget=_get_version,
2906                       fset=_set_version,
2907                       doc="SAML Version of the response")
2908
2909    def _get_id(self):
2910        '''Sets the ID of this response.
2911       
2912        @return: the ID of this response
2913        '''
2914        return self.__id
2915   
2916    def _set_id(self, value):
2917        '''Sets the ID of this response.
2918       
2919        @param value: the ID of this response
2920        '''
2921        if not isinstance(value, basestring):
2922            raise TypeError('Expecting basestring derived type for "id", got '
2923                            '%r' % type(value))
2924        self.__id = value
2925       
2926    id = property(fget=_get_id, fset=_set_id, doc="ID of response")
2927
2928    def _getInResponseTo(self):
2929        '''Get the unique request identifier for which this is a response
2930       
2931        @return: the unique identifier of the originating
2932        request
2933        '''
2934        return self.__inResponseTo
2935   
2936    def _setInResponseTo(self, value):
2937        '''Set the unique request identifier for which this is a response
2938       
2939        @param value: the unique identifier of the originating
2940        request
2941        '''
2942        if not isinstance(value, basestring):
2943            raise TypeError('Expecting basestring derived type for '
2944                            '"inResponseTo", got %r' % type(value))
2945        self.__inResponseTo = value
2946       
2947    inResponseTo = property(fget=_getInResponseTo, 
2948                            fset=_setInResponseTo,
2949                            doc="unique request identifier for which this is "
2950                                "a response")
2951
2952    def _get_issueInstant(self):
2953        '''Gets the issue instance of this response.
2954       
2955        @return: the issue instance of this response'''
2956        return self.__issueInstant
2957   
2958    def _set_issueInstant(self, issueInstant):
2959        '''Sets the issue instance of this response.
2960       
2961        @param newIssueInstance: the issue instance of this response
2962        '''
2963        if not isinstance(issueInstant, datetime):
2964            raise TypeError('Expecting "datetime" type for "issueInstant", '
2965                            'got %r' % issueInstant.__class__)
2966           
2967        self.__issueInstant = issueInstant
2968       
2969    issueInstant = property(fget=_get_issueInstant, 
2970                            fset=_set_issueInstant,
2971                            doc="Issue instant of the response")
2972
2973    def _get_destination(self):
2974        '''Gets the URI of the destination of the response.
2975       
2976        @return: the URI of the destination of the response
2977        '''
2978        return self.__destination
2979   
2980    def _set_destination(self, value):
2981        '''Sets the URI of the destination of the response.
2982       
2983        @param value: the URI of the destination of the response'''
2984        if not isinstance(value, basestring):
2985            raise TypeError('Expecting basestring derived type for '
2986                            '"destination", got %r' % type(value))
2987        self.__destination = value
2988       
2989    destination = property(fget=_get_destination, 
2990                           fset=_set_destination,
2991                           doc="Destination of response")
2992     
2993    def _get_consent(self):
2994        '''Gets the consent obtained from the principal for sending this
2995        response.
2996       
2997        @return: the consent obtained from the principal for sending this
2998        response
2999        '''
3000        return self.__consent
3001       
3002    def _set_consent(self, value):
3003        '''Sets the consent obtained from the principal for sending this
3004        response.
3005       
3006        @param value: the new consent obtained from the principal for
3007        sending this response
3008        ''' 
3009        if not isinstance(value, basestring):
3010            raise TypeError('Expecting basestring derived type for "consent", '
3011                            'got %r' % type(value))
3012        self.__consent = value
3013             
3014    consent = property(fget=_get_consent, 
3015                       fset=_set_consent,
3016                       doc="Consent for response")
3017   
3018    def _set_issuer(self, issuer):
3019        """Set issuer of response"""
3020        if not isinstance(issuer, Issuer):
3021            raise TypeError('"issuer" must be a %r, got %r' % (Issuer,
3022                                                               type(issuer)))
3023        self.__issuer = issuer
3024   
3025    def _get_issuer(self):
3026        """Get the issuer name """
3027        return self.__issuer
3028
3029    issuer = property(fget=_get_issuer, 
3030                      fset=_set_issuer,
3031                      doc="Issuer of response")
3032   
3033    def _getStatus(self):
3034        '''Gets the Status of this response.
3035       
3036        @return: the Status of this response
3037        '''
3038        return self.__status
3039
3040    def _setStatus(self, value):
3041        '''Sets the Status of this response.
3042       
3043        @param newStatus: the Status of this response
3044        '''
3045        if not isinstance(value, Status):
3046            raise TypeError('"status" must be a %r, got %r' % (Status,
3047                                                               type(value)))
3048        self.__status = value
3049       
3050    status = property(fget=_getStatus, fset=_setStatus, doc="Response status")   
3051       
3052    def _get_extensions(self):
3053        '''Gets the Extensions of this response.
3054       
3055        @return: the Status of this response
3056        '''
3057        return self.__extensions
3058     
3059    def _set_extensions(self, value):
3060        '''Sets the Extensions of this response.
3061       
3062        @param value: the Extensions of this response
3063        '''
3064        if not isinstance(value, (list, tuple)):
3065            raise TypeError('Expecting list or tuple for "extensions", got %r'
3066                            % type(value))
3067        self.__extensions = value
3068       
3069    extensions = property(fget=_get_extensions, 
3070                          fset=_set_extensions,
3071                          doc="Response extensions")   
3072
3073
3074class Response(StatusResponseType):
3075    '''SAML2 Core Response'''
3076   
3077    # Element local name.
3078    DEFAULT_ELEMENT_LOCAL_NAME = "Response"
3079   
3080    # Default element name.
3081    DEFAULT_ELEMENT_NAME = QName(SAMLConstants.SAML20P_NS, 
3082                                 DEFAULT_ELEMENT_LOCAL_NAME, 
3083                                 SAMLConstants.SAML20P_PREFIX)
3084   
3085    # Local name of the XSI type.
3086    TYPE_LOCAL_NAME = "ResponseType"
3087       
3088    # QName of the XSI type.
3089    TYPE_NAME = QName(SAMLConstants.SAML20P_NS, 
3090                      TYPE_LOCAL_NAME, 
3091                      SAMLConstants.SAML20P_PREFIX)
3092   
3093    __slots__ = ('__indexedChildren',)
3094   
3095    def __init__(self, **kw):
3096        '''''' 
3097        super(Response, self).__init__(**kw)
3098       
3099        # Assertion child elements
3100        self.__indexedChildren = []
3101
3102    def __getstate__(self):
3103        '''Enable pickling'''
3104        _dict = super(Response, self).__getstate__()
3105        for attrName in Response.__slots__:
3106            # Ugly hack to allow for derived classes setting private member
3107            # variables
3108            if attrName.startswith('__'):
3109                attrName = "_Response" + attrName
3110               
3111            _dict[attrName] = getattr(self, attrName)
3112           
3113        return _dict
3114       
3115    @property
3116    def assertions(self): 
3117        "Assertions contained in this response"
3118        return self.__indexedChildren
Note: See TracBrowser for help on using the repository browser.