Revamped binding classes with security policy layer.
[shibboleth/cpp-opensaml.git] / saml / saml1 / core / impl / ProtocolsImpl.cpp
1 /*
2  *  Copyright 2001-2006 Internet2
3  * 
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /**
18  * ProtocolsImpl.cpp
19  * 
20  * Implementation classes for SAML 1.x Protocols schema
21  */
22
23 #include "internal.h"
24 #include "exceptions.h"
25 #include "saml1/core/Assertions.h"
26 #include "saml1/core/Protocols.h"
27
28 #include <xmltooling/AbstractComplexElement.h>
29 #include <xmltooling/AbstractElementProxy.h>
30 #include <xmltooling/AbstractSimpleElement.h>
31 #include <xmltooling/impl/AnyElement.h>
32 #include <xmltooling/io/AbstractXMLObjectMarshaller.h>
33 #include <xmltooling/io/AbstractXMLObjectUnmarshaller.h>
34 #include <xmltooling/util/XMLHelper.h>
35
36 #include <ctime>
37 #include <xercesc/util/XMLUniDefs.hpp>
38
39 using namespace opensaml::saml1p;
40 using namespace opensaml::saml1;
41 using namespace opensaml;
42 using namespace xmlsignature;
43 using namespace xmltooling;
44 using namespace std;
45 using xmlconstants::XMLSIG_NS;
46 using xmlconstants::XML_ONE;
47 using samlconstants::SAML1P_NS;
48 using samlconstants::SAML1_NS;
49 using samlconstants::SAML1P_PREFIX;
50
51 #if defined (_MSC_VER)
52     #pragma warning( push )
53     #pragma warning( disable : 4250 4251 )
54 #endif
55
56 namespace opensaml {
57     namespace saml1p {
58     
59         DECL_XMLOBJECTIMPL_SIMPLE(SAML_DLLLOCAL,AssertionArtifact);
60         DECL_XMLOBJECTIMPL_SIMPLE(SAML_DLLLOCAL,StatusMessage);
61
62         class SAML_DLLLOCAL RespondWithImpl : public virtual RespondWith,
63             public AbstractSimpleElement,
64             public AbstractDOMCachingXMLObject,
65             public AbstractXMLObjectMarshaller,
66             public AbstractXMLObjectUnmarshaller
67         {
68             QName* m_qname;
69         public:
70             virtual ~RespondWithImpl() {
71                 delete m_qname;
72             }
73     
74             RespondWithImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType)
75                 : AbstractXMLObject(nsURI, localName, prefix, schemaType), m_qname(NULL) {
76             }
77                 
78             RespondWithImpl(const RespondWithImpl& src)
79                     : AbstractXMLObject(src), AbstractSimpleElement(src), AbstractDOMCachingXMLObject(src), m_qname(NULL) {
80                 setQName(src.getQName());
81             }
82             
83             QName* getQName() const {
84                 return m_qname;
85             }
86             
87             void setQName(const QName* qname) {
88                 m_qname=prepareForAssignment(m_qname,qname);
89                 if (m_qname) {
90                     auto_ptr_XMLCh temp(m_qname->toString().c_str());
91                     setTextContent(temp.get());
92                 }
93                 else
94                     setTextContent(NULL);
95             }
96             
97             IMPL_XMLOBJECT_CLONE(RespondWith);
98         };
99
100         class SAML_DLLLOCAL SubjectQueryImpl : public virtual SubjectQuery,
101             public AbstractComplexElement,
102             public AbstractDOMCachingXMLObject,
103             public AbstractXMLObjectMarshaller,
104             public AbstractXMLObjectUnmarshaller
105         {
106             void init() {
107                 m_Subject=NULL;
108                 m_children.push_back(NULL);
109                 m_pos_Subject=m_children.begin();
110             }
111         protected:
112             SubjectQueryImpl() {
113                 init();
114             }
115         public:
116             virtual ~SubjectQueryImpl() {}
117     
118             SubjectQueryImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType)
119                 : AbstractXMLObject(nsURI, localName, prefix, schemaType) {
120                 init();
121             }
122                 
123             SubjectQueryImpl(const SubjectQueryImpl& src)
124                     : AbstractXMLObject(src), AbstractComplexElement(src), AbstractDOMCachingXMLObject(src) {
125                 init();
126                 if (src.getSubject())
127                     setSubject(src.getSubject()->cloneSubject());
128             }
129             
130             IMPL_TYPED_CHILD(Subject);
131     
132         protected:
133             void processChildElement(XMLObject* childXMLObject, const DOMElement* root) {
134                 PROC_TYPED_CHILD(Subject,SAML1_NS,true);
135                 AbstractXMLObjectUnmarshaller::processChildElement(childXMLObject,root);
136             }
137         };
138
139         class SAML_DLLLOCAL AuthenticationQueryImpl : public virtual AuthenticationQuery, public SubjectQueryImpl
140         {
141             void init() {
142                 m_AuthenticationMethod=NULL;
143             }
144         public:
145             virtual ~AuthenticationQueryImpl() {
146                 XMLString::release(&m_AuthenticationMethod);
147             }
148     
149             AuthenticationQueryImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType)
150                 : AbstractXMLObject(nsURI, localName, prefix, schemaType) {
151                 init();
152             }
153                 
154             AuthenticationQueryImpl(const AuthenticationQueryImpl& src) : AbstractXMLObject(src), SubjectQueryImpl(src) {
155                 init();
156                 setAuthenticationMethod(src.getAuthenticationMethod());
157             }
158             
159             IMPL_XMLOBJECT_CLONE(AuthenticationQuery);
160             SubjectQuery* cloneSubjectQuery() const {
161                 return cloneAuthenticationQuery();
162             }
163             Query* cloneQuery() const {
164                 return cloneAuthenticationQuery();
165             }
166             IMPL_STRING_ATTRIB(AuthenticationMethod);
167     
168         protected:
169             void marshallAttributes(DOMElement* domElement) const {
170                 MARSHALL_STRING_ATTRIB(AuthenticationMethod,AUTHENTICATIONMETHOD,NULL);
171                 SubjectQueryImpl::marshallAttributes(domElement);
172             }
173     
174             void processAttribute(const DOMAttr* attribute) {
175                 PROC_STRING_ATTRIB(AuthenticationMethod,AUTHENTICATIONMETHOD,NULL);
176                 SubjectQueryImpl::processAttribute(attribute);
177             }
178         };
179
180         class SAML_DLLLOCAL AttributeQueryImpl : public virtual AttributeQuery, public SubjectQueryImpl
181         {
182             void init() {
183                 m_Resource=NULL;
184             }
185         public:
186             virtual ~AttributeQueryImpl() {
187                 XMLString::release(&m_Resource);
188             }
189     
190             AttributeQueryImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType)
191                 : AbstractXMLObject(nsURI, localName, prefix, schemaType) {
192                 init();
193             }
194                 
195             AttributeQueryImpl(const AttributeQueryImpl& src) : AbstractXMLObject(src), SubjectQueryImpl(src) {
196                 init();
197                 setResource(src.getResource());
198                 VectorOf(AttributeDesignator) v=getAttributeDesignators();
199                 for (vector<AttributeDesignator*>::const_iterator i=src.m_AttributeDesignators.begin(); i!=src.m_AttributeDesignators.end(); i++) {
200                     if (*i) {
201                         v.push_back((*i)->cloneAttributeDesignator());
202                     }
203                 }
204             }
205             
206             IMPL_XMLOBJECT_CLONE(AttributeQuery);
207             SubjectQuery* cloneSubjectQuery() const {
208                 return cloneAttributeQuery();
209             }
210             Query* cloneQuery() const {
211                 return cloneAttributeQuery();
212             }
213             IMPL_STRING_ATTRIB(Resource);
214             IMPL_TYPED_CHILDREN(AttributeDesignator,m_children.end());
215     
216         protected:
217             void marshallAttributes(DOMElement* domElement) const {
218                 MARSHALL_STRING_ATTRIB(Resource,RESOURCE,NULL);
219                 SubjectQueryImpl::marshallAttributes(domElement);
220             }
221     
222             void processChildElement(XMLObject* childXMLObject, const DOMElement* root) {
223                 PROC_TYPED_CHILDREN(AttributeDesignator,SAML1_NS,true);
224                 SubjectQueryImpl::processChildElement(childXMLObject,root);
225             }
226     
227             void processAttribute(const DOMAttr* attribute) {
228                 PROC_STRING_ATTRIB(Resource,RESOURCE,NULL);
229                 SubjectQueryImpl::processAttribute(attribute);
230             }
231         };
232
233         class SAML_DLLLOCAL AuthorizationDecisionQueryImpl : public virtual AuthorizationDecisionQuery, public SubjectQueryImpl
234         {
235             void init() {
236                 m_Resource=NULL;
237                 m_Evidence=NULL;
238                 m_children.push_back(NULL);
239                 m_pos_Evidence=m_pos_Subject;
240                 ++m_pos_Evidence;
241             }
242         public:
243             virtual ~AuthorizationDecisionQueryImpl() {
244                 XMLString::release(&m_Resource);
245             }
246     
247             AuthorizationDecisionQueryImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType)
248                 : AbstractXMLObject(nsURI, localName, prefix, schemaType) {
249                 init();
250             }
251                 
252             AuthorizationDecisionQueryImpl(const AuthorizationDecisionQueryImpl& src) : AbstractXMLObject(src), SubjectQueryImpl(src) {
253                 init();
254                 setResource(src.getResource());
255                 if (src.getEvidence())
256                     setEvidence(src.getEvidence()->cloneEvidence());
257                 VectorOf(Action) v=getActions();
258                 for (vector<Action*>::const_iterator i=src.m_Actions.begin(); i!=src.m_Actions.end(); i++) {
259                     if (*i) {
260                         v.push_back((*i)->cloneAction());
261                     }
262                 }
263             }
264             
265             IMPL_XMLOBJECT_CLONE(AuthorizationDecisionQuery);
266             SubjectQuery* cloneSubjectQuery() const {
267                 return cloneAuthorizationDecisionQuery();
268             }
269             Query* cloneQuery() const {
270                 return cloneAuthorizationDecisionQuery();
271             }
272             IMPL_STRING_ATTRIB(Resource);
273             IMPL_TYPED_CHILD(Evidence);
274             IMPL_TYPED_CHILDREN(Action, m_pos_Evidence);
275     
276         protected:
277             void marshallAttributes(DOMElement* domElement) const {
278                 MARSHALL_STRING_ATTRIB(Resource,RESOURCE,NULL);
279                 SubjectQueryImpl::marshallAttributes(domElement);
280             }
281     
282             void processChildElement(XMLObject* childXMLObject, const DOMElement* root) {
283                 PROC_TYPED_CHILD(Evidence,SAML1_NS,false);
284                 PROC_TYPED_CHILDREN(Action,SAML1_NS,false);
285                 SubjectQueryImpl::processChildElement(childXMLObject,root);
286             }
287     
288             void processAttribute(const DOMAttr* attribute) {
289                 PROC_STRING_ATTRIB(Resource,RESOURCE,NULL);
290                 SubjectQueryImpl::processAttribute(attribute);
291             }
292         };
293
294         class SAML_DLLLOCAL RequestAbstractTypeImpl : public virtual RequestAbstractType,
295             public AbstractComplexElement,
296             public AbstractDOMCachingXMLObject,
297             public AbstractXMLObjectMarshaller,
298             public AbstractXMLObjectUnmarshaller
299         {
300             void init() {
301                 m_MinorVersion=NULL;
302                 m_RequestID=NULL;
303                 m_IssueInstant=NULL;
304                 m_children.push_back(NULL);
305                 m_Signature=NULL;
306                 m_pos_Signature=m_children.begin();
307             }
308         protected:
309             RequestAbstractTypeImpl() {
310                 init();
311             }
312         public:
313             virtual ~RequestAbstractTypeImpl() {
314                 XMLString::release(&m_MinorVersion);
315                 XMLString::release(&m_RequestID);
316                 delete m_IssueInstant;
317             }
318     
319             RequestAbstractTypeImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType)
320                 : AbstractXMLObject(nsURI, localName, prefix, schemaType) {
321                 init();
322             }
323                 
324             RequestAbstractTypeImpl(const RequestAbstractTypeImpl& src)
325                     : AbstractXMLObject(src), AbstractComplexElement(src), AbstractDOMCachingXMLObject(src) {
326                 init();
327                 setMinorVersion(src.m_MinorVersion);
328                 setRequestID(src.getRequestID());
329                 setIssueInstant(src.getIssueInstant());
330                 if (src.getSignature())
331                     setSignature(src.getSignature()->cloneSignature());
332                 VectorOf(RespondWith) v=getRespondWiths();
333                 for (vector<RespondWith*>::const_iterator i=src.m_RespondWiths.begin(); i!=src.m_RespondWiths.end(); i++) {
334                     if (*i) {
335                         v.push_back((*i)->cloneRespondWith());
336                     }
337                 }
338             }
339             
340             //IMPL_TYPED_CHILD(Signature);
341             // Need customized setter.
342         protected:
343             Signature* m_Signature;
344             list<XMLObject*>::iterator m_pos_Signature;
345         public:
346             Signature* getSignature() const {
347                 return m_Signature;
348             }
349             
350             void setSignature(Signature* sig) {
351                 prepareForAssignment(m_Signature,sig);
352                 *m_pos_Signature=m_Signature=sig;
353                 // Sync content reference back up.
354                 if (m_Signature)
355                     m_Signature->setContentReference(new opensaml::ContentReference(*this));
356             }
357
358             IMPL_INTEGER_ATTRIB(MinorVersion);
359             IMPL_STRING_ATTRIB(RequestID);    // have to special-case getXMLID
360             const XMLCh* getXMLID() const {
361                 pair<bool,int> v = getMinorVersion();
362                 return (!v.first || v.second > 0) ? m_RequestID : NULL;
363             }
364             const XMLCh* getID() const {
365                 return getRequestID();
366             }
367             IMPL_DATETIME_ATTRIB(IssueInstant,0);
368             IMPL_TYPED_CHILDREN(RespondWith,m_pos_Signature);
369     
370         protected:
371             void marshallAttributes(DOMElement* domElement) const {
372                 static const XMLCh MAJORVERSION[] = UNICODE_LITERAL_12(M,a,j,o,r,V,e,r,s,i,o,n);
373                 domElement->setAttributeNS(NULL,MAJORVERSION,XML_ONE);
374                 if (!m_MinorVersion)
375                     const_cast<RequestAbstractTypeImpl*>(this)->m_MinorVersion=XMLString::replicate(XML_ONE);
376                 MARSHALL_INTEGER_ATTRIB(MinorVersion,MINORVERSION,NULL);
377                 if (!m_RequestID)
378                     const_cast<RequestAbstractTypeImpl*>(this)->m_RequestID=SAMLConfig::getConfig().generateIdentifier();
379                 MARSHALL_ID_ATTRIB(RequestID,REQUESTID,NULL);
380                 if (!m_IssueInstant) {
381                     const_cast<RequestAbstractTypeImpl*>(this)->m_IssueInstantEpoch=time(NULL);
382                     const_cast<RequestAbstractTypeImpl*>(this)->m_IssueInstant=new DateTime(m_IssueInstantEpoch);
383                 }
384                 MARSHALL_DATETIME_ATTRIB(IssueInstant,ISSUEINSTANT,NULL);
385             }
386
387             void processChildElement(XMLObject* childXMLObject, const DOMElement* root) {
388                 PROC_TYPED_CHILDREN(RespondWith,SAML1P_NS,false);
389                 PROC_TYPED_CHILD(Signature,XMLSIG_NS,false);
390                 AbstractXMLObjectUnmarshaller::processChildElement(childXMLObject,root);
391             }
392
393             void processAttribute(const DOMAttr* attribute) {
394                 static const XMLCh MAJORVERSION[] = UNICODE_LITERAL_12(M,a,j,o,r,V,e,r,s,i,o,n);
395                 if (XMLHelper::isNodeNamed(attribute,NULL,MAJORVERSION)) {
396                     if (!XMLString::equals(attribute->getValue(),XML_ONE))
397                         throw UnmarshallingException("Request has invalid major version.");
398                 }
399                 PROC_INTEGER_ATTRIB(MinorVersion,MINORVERSION,NULL);
400                 PROC_ID_ATTRIB(RequestID,REQUESTID,NULL);
401                 PROC_DATETIME_ATTRIB(IssueInstant,ISSUEINSTANT,NULL);
402             }
403         };
404
405         class SAML_DLLLOCAL RequestImpl : public virtual Request, public RequestAbstractTypeImpl
406         {
407             void init() {
408                 m_children.push_back(NULL);
409                 m_Query=NULL;
410                 m_pos_Query=m_pos_Signature;
411                 ++m_pos_Query;
412             }
413         public:
414             virtual ~RequestImpl() {}
415     
416             RequestImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType)
417                 : AbstractXMLObject(nsURI, localName, prefix, schemaType) {
418                 init();
419             }
420                 
421             RequestImpl(const RequestImpl& src) : AbstractXMLObject(src), RequestAbstractTypeImpl(src) {
422                 init();
423                 if (src.getQuery())
424                     setQuery(src.getQuery()->cloneQuery());
425                 VectorOf(AssertionIDReference) v=getAssertionIDReferences();
426                 for (vector<AssertionIDReference*>::const_iterator i=src.m_AssertionIDReferences.begin(); i!=src.m_AssertionIDReferences.end(); i++) {
427                     if (*i) {
428                         v.push_back((*i)->cloneAssertionIDReference());
429                     }
430                 }
431                 VectorOf(AssertionArtifact) v2=getAssertionArtifacts();
432                 for (vector<AssertionArtifact*>::const_iterator i=src.m_AssertionArtifacts.begin(); i!=src.m_AssertionArtifacts.end(); i++) {
433                     if (*i) {
434                         v2.push_back((*i)->cloneAssertionArtifact());
435                     }
436                 }
437             }
438             
439             IMPL_XMLOBJECT_CLONE(Request);
440             RequestAbstractType* cloneRequestAbstractType() const {
441                 return cloneRequest();
442             }
443             IMPL_TYPED_CHILD(Query);
444             
445             SubjectQuery* getSubjectQuery() const {
446                 return dynamic_cast<SubjectQuery*>(getQuery());
447             }
448             AuthenticationQuery* getAuthenticationQuery() const {
449                 return dynamic_cast<AuthenticationQuery*>(getQuery());
450             }
451             AttributeQuery* getAttributeQuery() const {
452                 return dynamic_cast<AttributeQuery*>(getQuery());
453             }
454             AuthorizationDecisionQuery* getAuthorizationDecisionQuery() const {
455                 return dynamic_cast<AuthorizationDecisionQuery*>(getQuery());
456             }
457
458             void setSubjectQuery(SubjectQuery* q) {
459                 setQuery(q);
460             }
461             void setAuthenticationQuery(AuthenticationQuery* q) {
462                 setQuery(q);
463             }
464             void setAttributeQuery(AttributeQuery* q) {
465                 setQuery(q);
466             }
467             void setAuthorizationDecisionQuery(AuthorizationDecisionQuery* q) {
468                 setQuery(q);
469             }
470             
471             IMPL_TYPED_CHILDREN(AssertionIDReference, m_children.end());
472             IMPL_TYPED_CHILDREN(AssertionArtifact, m_children.end());
473     
474         protected:
475             void processChildElement(XMLObject* childXMLObject, const DOMElement* root) {
476                 PROC_TYPED_CHILD(Query,SAML1P_NS,true);
477                 PROC_TYPED_CHILDREN(AssertionIDReference,SAML1_NS,false);
478                 PROC_TYPED_CHILDREN(AssertionArtifact,SAML1P_NS,false);
479                 RequestAbstractTypeImpl::processChildElement(childXMLObject,root);
480             }
481         };
482
483         class SAML_DLLLOCAL StatusCodeImpl : public virtual StatusCode,
484             public AbstractComplexElement,
485             public AbstractDOMCachingXMLObject,
486             public AbstractXMLObjectMarshaller,
487             public AbstractXMLObjectUnmarshaller
488         {
489             void init() {
490                 m_Value=NULL;
491                 m_children.push_back(NULL);
492                 m_StatusCode=NULL;
493                 m_pos_StatusCode=m_children.begin();
494             }
495         public:
496             virtual ~StatusCodeImpl() {
497                 delete m_Value;
498             }
499     
500             StatusCodeImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType)
501                 : AbstractXMLObject(nsURI, localName, prefix, schemaType) {
502                 init();
503             }
504                 
505             StatusCodeImpl(const StatusCodeImpl& src)
506                     : AbstractXMLObject(src), AbstractComplexElement(src), AbstractDOMCachingXMLObject(src) {
507                 init();
508                 setValue(src.getValue());
509                 if (src.getStatusCode())
510                     setStatusCode(src.getStatusCode()->cloneStatusCode());
511             }
512             
513             IMPL_XMLOBJECT_CLONE(StatusCode);
514             IMPL_XMLOBJECT_ATTRIB(Value,QName);
515             IMPL_TYPED_CHILD(StatusCode);
516     
517         protected:
518             void marshallAttributes(DOMElement* domElement) const {
519                 MARSHALL_QNAME_ATTRIB(Value,VALUE,NULL);
520             }
521
522             void processChildElement(XMLObject* childXMLObject, const DOMElement* root) {
523                 PROC_TYPED_CHILD(StatusCode,SAML1P_NS,true);
524                 AbstractXMLObjectUnmarshaller::processChildElement(childXMLObject,root);
525             }
526
527             void processAttribute(const DOMAttr* attribute) {
528                 PROC_QNAME_ATTRIB(Value,VALUE,NULL);
529             }
530         };
531
532         class SAML_DLLLOCAL StatusDetailImpl : public virtual StatusDetail,
533             public AbstractComplexElement,
534             public AbstractDOMCachingXMLObject,
535             public AbstractXMLObjectMarshaller,
536             public AbstractXMLObjectUnmarshaller
537         {
538         public:
539             virtual ~StatusDetailImpl() {}
540     
541             StatusDetailImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType)
542                 : AbstractXMLObject(nsURI, localName, prefix, schemaType) {
543             }
544                 
545             StatusDetailImpl(const StatusDetailImpl& src)
546                     : AbstractXMLObject(src), AbstractComplexElement(src), AbstractDOMCachingXMLObject(src) {
547                 VectorOf(XMLObject) v=getDetails();
548                 for (vector<XMLObject*>::const_iterator i=src.m_Details.begin(); i!=src.m_Details.end(); i++) {
549                     if (*i) {
550                         v.push_back((*i)->clone());
551                     }
552                 }
553             }
554             
555             IMPL_XMLOBJECT_CLONE(StatusDetail);
556             IMPL_XMLOBJECT_CHILDREN(Detail,m_children.end());
557     
558         protected:
559             void processChildElement(XMLObject* childXMLObject, const DOMElement* root) {
560                 getDetails().push_back(childXMLObject);
561             }
562         };
563
564         class SAML_DLLLOCAL StatusImpl : public virtual Status,
565             public AbstractComplexElement,
566             public AbstractDOMCachingXMLObject,
567             public AbstractXMLObjectMarshaller,
568             public AbstractXMLObjectUnmarshaller
569         {
570             void init() {
571                 m_children.push_back(NULL);
572                 m_children.push_back(NULL);
573                 m_children.push_back(NULL);
574                 m_StatusCode=NULL;
575                 m_pos_StatusCode=m_children.begin();
576                 m_StatusMessage=NULL;
577                 m_pos_StatusMessage=m_pos_StatusCode;
578                 ++m_pos_StatusMessage;
579                 m_StatusDetail=NULL;
580                 m_pos_StatusDetail=m_pos_StatusMessage;
581                 ++m_pos_StatusDetail;
582             }
583         public:
584             virtual ~StatusImpl() {}
585     
586             StatusImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType)
587                 : AbstractXMLObject(nsURI, localName, prefix, schemaType) {
588                 init();
589             }
590                 
591             StatusImpl(const StatusImpl& src)
592                     : AbstractXMLObject(src), AbstractComplexElement(src), AbstractDOMCachingXMLObject(src) {
593                 init();
594                 if (src.getStatusCode())
595                     setStatusCode(src.getStatusCode()->cloneStatusCode());
596                 if (src.getStatusMessage())
597                     setStatusMessage(src.getStatusMessage()->cloneStatusMessage());
598                 if (src.getStatusDetail())
599                     setStatusDetail(src.getStatusDetail()->cloneStatusDetail());
600             }
601             
602             IMPL_XMLOBJECT_CLONE(Status);
603             IMPL_TYPED_CHILD(StatusCode);
604             IMPL_TYPED_CHILD(StatusMessage);
605             IMPL_TYPED_CHILD(StatusDetail);
606     
607         protected:
608             void processChildElement(XMLObject* childXMLObject, const DOMElement* root) {
609                 PROC_TYPED_CHILD(StatusCode,SAML1P_NS,false);
610                 PROC_TYPED_CHILD(StatusMessage,SAML1P_NS,false);
611                 PROC_TYPED_CHILD(StatusDetail,SAML1P_NS,false);
612                 AbstractXMLObjectUnmarshaller::processChildElement(childXMLObject,root);
613             }
614         };
615
616         class SAML_DLLLOCAL ResponseAbstractTypeImpl : public virtual ResponseAbstractType,
617             public AbstractComplexElement,
618             public AbstractDOMCachingXMLObject,
619             public AbstractXMLObjectMarshaller,
620             public AbstractXMLObjectUnmarshaller
621         {
622             void init() {
623                 m_MinorVersion=NULL;
624                 m_ResponseID=NULL;
625                 m_InResponseTo=NULL;
626                 m_IssueInstant=NULL;
627                 m_Recipient=NULL;
628                 m_children.push_back(NULL);
629                 m_Signature=NULL;
630                 m_pos_Signature=m_children.begin();
631             }
632         protected:
633             ResponseAbstractTypeImpl() {
634                 init();
635             }
636         public:
637             virtual ~ResponseAbstractTypeImpl() {
638                 XMLString::release(&m_MinorVersion);
639                 XMLString::release(&m_ResponseID);
640                 XMLString::release(&m_InResponseTo);
641                 XMLString::release(&m_Recipient);
642                 delete m_IssueInstant;
643             }
644     
645             ResponseAbstractTypeImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType)
646                 : AbstractXMLObject(nsURI, localName, prefix, schemaType) {
647                 init();
648             }
649                 
650             ResponseAbstractTypeImpl(const ResponseAbstractTypeImpl& src)
651                     : AbstractXMLObject(src), AbstractComplexElement(src), AbstractDOMCachingXMLObject(src) {
652                 init();
653                 setMinorVersion(src.m_MinorVersion);
654                 setResponseID(src.getResponseID());
655                 setInResponseTo(src.getInResponseTo());
656                 setIssueInstant(src.getIssueInstant());
657                 setRecipient(src.getRecipient());
658                 if (src.getSignature())
659                     setSignature(src.getSignature()->cloneSignature());
660             }
661
662             //IMPL_TYPED_CHILD(Signature);
663             // Need customized setter.
664         protected:
665             Signature* m_Signature;
666             list<XMLObject*>::iterator m_pos_Signature;
667         public:
668             Signature* getSignature() const {
669                 return m_Signature;
670             }
671             
672             void setSignature(Signature* sig) {
673                 prepareForAssignment(m_Signature,sig);
674                 *m_pos_Signature=m_Signature=sig;
675                 // Sync content reference back up.
676                 if (m_Signature)
677                     m_Signature->setContentReference(new opensaml::ContentReference(*this));
678             }
679
680             IMPL_INTEGER_ATTRIB(MinorVersion);
681             IMPL_STRING_ATTRIB(ResponseID);    // have to special-case getXMLID
682             const XMLCh* getXMLID() const {
683                 pair<bool,int> v = getMinorVersion();
684                 return (!v.first || v.second > 0) ? m_ResponseID : NULL;
685             }
686             const XMLCh* getID() const {
687                 return getResponseID();
688             }
689             IMPL_STRING_ATTRIB(InResponseTo);
690             IMPL_DATETIME_ATTRIB(IssueInstant,0);
691             IMPL_STRING_ATTRIB(Recipient);
692     
693         protected:
694             void marshallAttributes(DOMElement* domElement) const {
695                 static const XMLCh MAJORVERSION[] = UNICODE_LITERAL_12(M,a,j,o,r,V,e,r,s,i,o,n);
696                 domElement->setAttributeNS(NULL,MAJORVERSION,XML_ONE);
697                 if (!m_MinorVersion)
698                     const_cast<ResponseAbstractTypeImpl*>(this)->m_MinorVersion=XMLString::replicate(XML_ONE);
699                 MARSHALL_INTEGER_ATTRIB(MinorVersion,MINORVERSION,NULL);
700                 if (!m_ResponseID)
701                     const_cast<ResponseAbstractTypeImpl*>(this)->m_ResponseID=SAMLConfig::getConfig().generateIdentifier();
702                 MARSHALL_ID_ATTRIB(ResponseID,RESPONSEID,NULL);
703                 MARSHALL_STRING_ATTRIB(InResponseTo,INRESPONSETO,NULL);
704                 if (!m_IssueInstant) {
705                     const_cast<ResponseAbstractTypeImpl*>(this)->m_IssueInstantEpoch=time(NULL);
706                     const_cast<ResponseAbstractTypeImpl*>(this)->m_IssueInstant=new DateTime(m_IssueInstantEpoch);
707                 }
708                 MARSHALL_DATETIME_ATTRIB(IssueInstant,ISSUEINSTANT,NULL);
709                 MARSHALL_STRING_ATTRIB(Recipient,RECIPIENT,NULL);
710             }
711
712             void processChildElement(XMLObject* childXMLObject, const DOMElement* root) {
713                 PROC_TYPED_CHILD(Signature,XMLSIG_NS,false);
714                 AbstractXMLObjectUnmarshaller::processChildElement(childXMLObject,root);
715             }
716
717             void processAttribute(const DOMAttr* attribute) {
718                 static const XMLCh MAJORVERSION[] = UNICODE_LITERAL_12(M,a,j,o,r,V,e,r,s,i,o,n);
719                 if (XMLHelper::isNodeNamed(attribute,NULL,MAJORVERSION)) {
720                     if (!XMLString::equals(attribute->getValue(),XML_ONE))
721                         throw UnmarshallingException("Response has invalid major version.");
722                 }
723                 PROC_INTEGER_ATTRIB(MinorVersion,MINORVERSION,NULL);
724                 PROC_ID_ATTRIB(ResponseID,RESPONSEID,NULL);
725                 PROC_STRING_ATTRIB(InResponseTo,INRESPONSETO,NULL);
726                 PROC_DATETIME_ATTRIB(IssueInstant,ISSUEINSTANT,NULL);
727                 PROC_STRING_ATTRIB(Recipient,RECIPIENT,NULL);
728             }
729         };
730
731         class SAML_DLLLOCAL ResponseImpl : public virtual Response, public ResponseAbstractTypeImpl
732         {
733             void init() {
734                 m_children.push_back(NULL);
735                 m_Status=NULL;
736                 m_pos_Status=m_pos_Signature;
737                 ++m_pos_Status;
738             }
739         public:
740             virtual ~ResponseImpl() {}
741     
742             ResponseImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const QName* schemaType)
743                 : AbstractXMLObject(nsURI, localName, prefix, schemaType) {
744                 init();
745             }
746                 
747             ResponseImpl(const ResponseImpl& src) : AbstractXMLObject(src), ResponseAbstractTypeImpl(src) {
748                 init();
749                 if (src.getStatus())
750                     setStatus(src.getStatus()->cloneStatus());
751                 VectorOf(Assertion) v=getAssertions();
752                 for (vector<Assertion*>::const_iterator i=src.m_Assertions.begin(); i!=src.m_Assertions.end(); i++) {
753                     if (*i) {
754                         v.push_back((*i)->cloneAssertion());
755                     }
756                 }
757             }
758             
759             IMPL_XMLOBJECT_CLONE(Response);
760             ResponseAbstractType* cloneResponseAbstractType() const {
761                 return cloneResponse();
762             }
763             IMPL_TYPED_CHILD(Status);
764             IMPL_TYPED_CHILDREN(Assertion, m_children.end());
765     
766         protected:
767             void processChildElement(XMLObject* childXMLObject, const DOMElement* root) {
768                 PROC_TYPED_CHILD(Status,SAML1P_NS,false);
769                 PROC_TYPED_CHILDREN(Assertion,SAML1_NS,true);
770                 ResponseAbstractTypeImpl::processChildElement(childXMLObject,root);
771             }
772         };
773
774     };
775 };
776
777 #if defined (_MSC_VER)
778     #pragma warning( pop )
779 #endif
780
781 // Builder Implementations
782
783 IMPL_XMLOBJECTBUILDER(AssertionArtifact);
784 IMPL_XMLOBJECTBUILDER(AttributeQuery);
785 IMPL_XMLOBJECTBUILDER(AuthenticationQuery);
786 IMPL_XMLOBJECTBUILDER(AuthorizationDecisionQuery);
787 IMPL_XMLOBJECTBUILDER(Request);
788 IMPL_XMLOBJECTBUILDER(RespondWith);
789 IMPL_XMLOBJECTBUILDER(Response);
790 IMPL_XMLOBJECTBUILDER(Status);
791 IMPL_XMLOBJECTBUILDER(StatusCode);
792 IMPL_XMLOBJECTBUILDER(StatusDetail);
793 IMPL_XMLOBJECTBUILDER(StatusMessage);
794
795 // Unicode literals
796 const XMLCh RequestAbstractType::LOCAL_NAME[] =             {chNull};
797 const XMLCh RequestAbstractType::TYPE_NAME[] =              UNICODE_LITERAL_19(R,e,q,u,e,s,t,A,b,s,t,r,a,c,t,T,y,p,e);
798 const XMLCh RequestAbstractType::MINORVERSION_ATTRIB_NAME[] =   UNICODE_LITERAL_12(M,i,n,o,r,V,e,r,s,i,o,n);
799 const XMLCh RequestAbstractType::REQUESTID_ATTRIB_NAME[] =      UNICODE_LITERAL_9(R,e,q,u,e,s,t,I,D);
800 const XMLCh RequestAbstractType::ISSUEINSTANT_ATTRIB_NAME[] =   UNICODE_LITERAL_12(I,s,s,u,e,I,n,s,t,a,n,t);
801 const XMLCh ResponseAbstractType::LOCAL_NAME[] =            {chNull};
802 const XMLCh ResponseAbstractType::TYPE_NAME[] =             UNICODE_LITERAL_20(R,e,s,p,o,n,s,e,A,b,s,t,r,a,c,t,T,y,p,e);
803 const XMLCh ResponseAbstractType::MINORVERSION_ATTRIB_NAME[] =  UNICODE_LITERAL_12(M,i,n,o,r,V,e,r,s,i,o,n);
804 const XMLCh ResponseAbstractType::RESPONSEID_ATTRIB_NAME[] =    UNICODE_LITERAL_10(R,e,s,p,o,n,s,e,I,D);
805 const XMLCh ResponseAbstractType::ISSUEINSTANT_ATTRIB_NAME[] =  UNICODE_LITERAL_12(I,s,s,u,e,I,n,s,t,a,n,t);
806 const XMLCh ResponseAbstractType::INRESPONSETO_ATTRIB_NAME[] =  UNICODE_LITERAL_12(I,n,R,e,s,p,o,n,s,e,T,o);
807 const XMLCh ResponseAbstractType::RECIPIENT_ATTRIB_NAME[] =     UNICODE_LITERAL_9(R,e,c,i,p,i,e,n,t);
808 const XMLCh AssertionArtifact::LOCAL_NAME[] =               UNICODE_LITERAL_17(A,s,s,e,r,t,i,o,n,A,r,t,i,f,a,c,t);
809 const XMLCh AttributeQuery::LOCAL_NAME[] =                  UNICODE_LITERAL_14(A,t,t,r,i,b,u,t,e,Q,u,e,r,y);
810 const XMLCh AttributeQuery::TYPE_NAME[] =                   UNICODE_LITERAL_18(A,t,t,r,i,b,u,t,e,Q,u,e,r,y,T,y,p,e);
811 const XMLCh AttributeQuery::RESOURCE_ATTRIB_NAME[] =        UNICODE_LITERAL_8(R,e,s,o,u,r,c,e);
812 const XMLCh AuthenticationQuery::LOCAL_NAME[] =             UNICODE_LITERAL_19(A,u,t,h,e,n,t,i,c,a,t,i,o,n,Q,u,e,r,y);
813 const XMLCh AuthenticationQuery::TYPE_NAME[] =              UNICODE_LITERAL_23(A,u,t,h,e,n,t,i,c,a,t,i,o,n,Q,u,e,r,y,T,y,p,e);
814 const XMLCh AuthenticationQuery::AUTHENTICATIONMETHOD_ATTRIB_NAME[] =   UNICODE_LITERAL_20(A,u,t,h,e,n,t,i,c,a,t,i,o,n,M,e,t,h,o,d);
815 const XMLCh AuthorizationDecisionQuery::LOCAL_NAME[] =      UNICODE_LITERAL_26(A,u,t,h,o,r,i,z,a,t,i,o,n,D,e,c,i,s,i,o,n,Q,u,e,r,y);
816 const XMLCh AuthorizationDecisionQuery::TYPE_NAME[] =       UNICODE_LITERAL_30(A,u,t,h,o,r,i,z,a,t,i,o,n,D,e,c,i,s,i,o,n,Q,u,e,r,y,T,y,p,e);
817 const XMLCh AuthorizationDecisionQuery::RESOURCE_ATTRIB_NAME[] =        UNICODE_LITERAL_8(R,e,s,o,u,r,c,e);
818 const XMLCh Query::LOCAL_NAME[] =                           UNICODE_LITERAL_5(Q,u,e,r,y);
819 const XMLCh Request::LOCAL_NAME[] =                         UNICODE_LITERAL_7(R,e,q,u,e,s,t);
820 const XMLCh Request::TYPE_NAME[] =                          UNICODE_LITERAL_11(R,e,q,u,e,s,t,T,y,p,e);
821 const XMLCh RespondWith::LOCAL_NAME[] =                     UNICODE_LITERAL_11(R,e,s,p,o,n,d,W,i,t,h);
822 const XMLCh Response::LOCAL_NAME[] =                        UNICODE_LITERAL_8(R,e,s,p,o,n,s,e);
823 const XMLCh Response::TYPE_NAME[] =                         UNICODE_LITERAL_12(R,e,s,p,o,n,s,e,T,y,p,e);
824 const XMLCh Status::LOCAL_NAME[] =                          UNICODE_LITERAL_6(S,t,a,t,u,s);
825 const XMLCh Status::TYPE_NAME[] =                           UNICODE_LITERAL_10(S,t,a,t,u,s,T,y,p,e);
826 const XMLCh StatusCode::LOCAL_NAME[] =                      UNICODE_LITERAL_10(S,t,a,t,u,s,C,o,d,e);
827 const XMLCh StatusCode::TYPE_NAME[] =                       UNICODE_LITERAL_14(S,t,a,t,u,s,C,o,d,e,T,y,p,e);
828 const XMLCh StatusCode::VALUE_ATTRIB_NAME[] =               UNICODE_LITERAL_5(V,a,l,u,e);
829 const XMLCh StatusDetail::LOCAL_NAME[] =                    UNICODE_LITERAL_12(S,t,a,t,u,s,D,e,t,a,i,l);
830 const XMLCh StatusDetail::TYPE_NAME[] =                     UNICODE_LITERAL_16(S,t,a,t,u,s,D,e,t,a,i,l,T,y,p,e);
831 const XMLCh StatusMessage::LOCAL_NAME[] =                   UNICODE_LITERAL_13(S,t,a,t,u,s,M,e,s,s,a,g,e);
832 const XMLCh SubjectQuery::LOCAL_NAME[] =                    UNICODE_LITERAL_12(S,u,b,j,e,c,t,Q,u,e,r,y);
833
834 #define XCH(ch) chLatin_##ch
835 #define XNUM(d) chDigit_##d
836
837 const XMLCh _SUCCESS[] =                                    UNICODE_LITERAL_7(S,u,c,c,e,s,s);
838 const XMLCh _REQUESTER[] =                                  UNICODE_LITERAL_9(R,e,q,u,e,s,t,e,r);
839 const XMLCh _RESPONDER[] =                                  UNICODE_LITERAL_9(R,e,s,p,o,n,d,e,r);
840 const XMLCh _VERSIONMISMATCH[] =                            UNICODE_LITERAL_15(V,e,r,s,i,o,n,M,i,s,m,a,t,c,h);
841  
842 QName StatusCode::SUCCESS(SAML1P_NS,_SUCCESS,SAML1P_PREFIX);
843 QName StatusCode::REQUESTER(SAML1P_NS,_REQUESTER,SAML1P_PREFIX);
844 QName StatusCode::RESPONDER(SAML1P_NS,_RESPONDER,SAML1P_PREFIX);
845 QName StatusCode::VERSIONMISMATCH(SAML1P_NS,_VERSIONMISMATCH,SAML1P_PREFIX);