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