source: TI12-security/trunk/ndg_security_saml/saml/saml2/core.py @ 6603

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

Completed pickle support for AuthzDecision?* types.

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