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