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