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

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

Unit testing AuthzDecisionStatement? added to a Response.

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