Clone macros
[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         protected:
645             void processChildElement(XMLObject* childXMLObject, const DOMElement* root) {
646                 PROC_TYPED_CHILD(StatusCode,SAML1P_NS,false);
647                 PROC_TYPED_CHILD(StatusMessage,SAML1P_NS,false);
648                 PROC_TYPED_CHILD(StatusDetail,SAML1P_NS,false);
649                 AbstractXMLObjectUnmarshaller::processChildElement(childXMLObject,root);
650             }
651         };
652
653         class SAML_DLLLOCAL ResponseAbstractTypeImpl : public virtual ResponseAbstractType,
654             public AbstractComplexElement,
655             public AbstractDOMCachingXMLObject,
656             public AbstractXMLObjectMarshaller,
657             public AbstractXMLObjectUnmarshaller
658         {
659             void init() {
660                 m_MinorVersion=nullptr;
661                 m_ResponseID=nullptr;
662                 m_InResponseTo=nullptr;
663                 m_IssueInstant=nullptr;
664                 m_Recipient=nullptr;
665                 m_children.push_back(nullptr);
666                 m_Signature=nullptr;
667                 m_pos_Signature=m_children.begin();
668             }
669
670         protected:
671             ResponseAbstractTypeImpl() {
672                 init();
673             }
674
675         public:
676             virtual ~ResponseAbstractTypeImpl() {
677                 XMLString::release(&m_MinorVersion);
678                 XMLString::release(&m_ResponseID);
679                 XMLString::release(&m_InResponseTo);
680                 XMLString::release(&m_Recipient);
681                 delete m_IssueInstant;
682             }
683
684             ResponseAbstractTypeImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const xmltooling::QName* schemaType)
685                     : AbstractXMLObject(nsURI, localName, prefix, schemaType) {
686                 init();
687             }
688
689             ResponseAbstractTypeImpl(const ResponseAbstractTypeImpl& src)
690                     : AbstractXMLObject(src), AbstractComplexElement(src), AbstractDOMCachingXMLObject(src) {
691                 init();
692             }
693
694             //IMPL_TYPED_CHILD(Signature);
695             // Need customized setter.
696         protected:
697             void _clone(const ResponseAbstractTypeImpl& src) {
698                 IMPL_CLONE_INTEGER_ATTRIB(MinorVersion);
699                 IMPL_CLONE_ATTRIB(ResponseID);
700                 IMPL_CLONE_ATTRIB(InResponseTo);
701                 IMPL_CLONE_ATTRIB(IssueInstant);
702                 IMPL_CLONE_ATTRIB(Recipient);
703                 IMPL_CLONE_TYPED_CHILD(Signature);
704             }
705
706             xmlsignature::Signature* m_Signature;
707             list<XMLObject*>::iterator m_pos_Signature;
708         public:
709             xmlsignature::Signature* getSignature() const {
710                 return m_Signature;
711             }
712
713             void setSignature(xmlsignature::Signature* sig) {
714                 prepareForAssignment(m_Signature,sig);
715                 *m_pos_Signature=m_Signature=sig;
716                 // Sync content reference back up.
717                 if (m_Signature)
718                     m_Signature->setContentReference(new opensaml::ContentReference(*this));
719             }
720
721             ResponseAbstractType* cloneResponseAbstractType() const {
722                 return dynamic_cast<ResponseAbstractType*>(clone());
723             }
724
725             IMPL_INTEGER_ATTRIB(MinorVersion);
726             IMPL_STRING_ATTRIB(ResponseID);    // have to special-case getXMLID
727             const XMLCh* getXMLID() const {
728                 pair<bool,int> v = getMinorVersion();
729                 return (!v.first || v.second > 0) ? m_ResponseID : nullptr;
730             }
731             const XMLCh* getID() const {
732                 return getResponseID();
733             }
734             void releaseDOM() const {
735                 if (getDOM())
736                     getDOM()->removeAttributeNS(nullptr, RESPONSEID_ATTRIB_NAME);
737                 AbstractDOMCachingXMLObject::releaseDOM();
738             }
739             IMPL_STRING_ATTRIB(InResponseTo);
740             IMPL_DATETIME_ATTRIB(IssueInstant,0);
741             IMPL_STRING_ATTRIB(Recipient);
742
743         protected:
744             void prepareForMarshalling() const {
745                 if (m_Signature)
746                     declareNonVisibleNamespaces();
747             }
748
749             void marshallAttributes(DOMElement* domElement) const {
750                 static const XMLCh MAJORVERSION[] = UNICODE_LITERAL_12(M,a,j,o,r,V,e,r,s,i,o,n);
751                 domElement->setAttributeNS(nullptr,MAJORVERSION,XML_ONE);
752                 if (!m_MinorVersion)
753                     const_cast<ResponseAbstractTypeImpl*>(this)->m_MinorVersion=XMLString::replicate(XML_ONE);
754                 MARSHALL_INTEGER_ATTRIB(MinorVersion,MINORVERSION,nullptr);
755                 if (!m_ResponseID)
756                     const_cast<ResponseAbstractTypeImpl*>(this)->m_ResponseID=SAMLConfig::getConfig().generateIdentifier();
757                 domElement->setAttributeNS(nullptr, RESPONSEID_ATTRIB_NAME, m_ResponseID);
758                 if (*m_MinorVersion!=chDigit_0) {
759 #ifdef XMLTOOLING_XERCESC_BOOLSETIDATTRIBUTE
760                     domElement->setIdAttributeNS(nullptr, RESPONSEID_ATTRIB_NAME, true);
761 #else
762                     domElement->setIdAttributeNS(nullptr, RESPONSEID_ATTRIB_NAME);
763 #endif
764                 }
765                 MARSHALL_STRING_ATTRIB(InResponseTo,INRESPONSETO,nullptr);
766                 if (!m_IssueInstant) {
767                     const_cast<ResponseAbstractTypeImpl*>(this)->m_IssueInstantEpoch=time(nullptr);
768                     const_cast<ResponseAbstractTypeImpl*>(this)->m_IssueInstant=new DateTime(m_IssueInstantEpoch);
769                 }
770                 MARSHALL_DATETIME_ATTRIB(IssueInstant,ISSUEINSTANT,nullptr);
771                 MARSHALL_STRING_ATTRIB(Recipient,RECIPIENT,nullptr);
772             }
773
774             void processChildElement(XMLObject* childXMLObject, const DOMElement* root) {
775                 PROC_TYPED_FOREIGN_CHILD(Signature,xmlsignature,XMLSIG_NS,false);
776                 AbstractXMLObjectUnmarshaller::processChildElement(childXMLObject,root);
777             }
778
779             void unmarshallAttributes(const DOMElement* domElement) {
780                 // Standard processing, but then we check IDness.
781                 AbstractXMLObjectUnmarshaller::unmarshallAttributes(domElement);
782                 if (m_ResponseID && (!m_MinorVersion || *m_MinorVersion!=chDigit_0)) {
783 #ifdef XMLTOOLING_XERCESC_BOOLSETIDATTRIBUTE
784                     const_cast<DOMElement*>(domElement)->setIdAttributeNS(nullptr, RESPONSEID_ATTRIB_NAME, true);
785 #else
786                     const_cast<DOMElement*>(domElement)->setIdAttributeNS(nullptr, RESPONSEID_ATTRIB_NAME);
787 #endif
788                 }
789             }
790
791             void processAttribute(const DOMAttr* attribute) {
792                 static const XMLCh MAJORVERSION[] = UNICODE_LITERAL_12(M,a,j,o,r,V,e,r,s,i,o,n);
793                 if (XMLHelper::isNodeNamed(attribute,nullptr,MAJORVERSION)) {
794                     if (!XMLString::equals(attribute->getValue(),XML_ONE))
795                         throw UnmarshallingException("Response has invalid major version.");
796                 }
797                 PROC_INTEGER_ATTRIB(MinorVersion,MINORVERSION,nullptr);
798                 PROC_STRING_ATTRIB(ResponseID,RESPONSEID,nullptr);
799                 PROC_STRING_ATTRIB(InResponseTo,INRESPONSETO,nullptr);
800                 PROC_DATETIME_ATTRIB(IssueInstant,ISSUEINSTANT,nullptr);
801                 PROC_STRING_ATTRIB(Recipient,RECIPIENT,nullptr);
802             }
803         };
804
805         class SAML_DLLLOCAL ResponseImpl : public virtual Response, public ResponseAbstractTypeImpl
806         {
807             void init() {
808                 m_children.push_back(nullptr);
809                 m_Status=nullptr;
810                 m_pos_Status=m_pos_Signature;
811                 ++m_pos_Status;
812             }
813
814         public:
815             virtual ~ResponseImpl() {}
816
817             ResponseImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const xmltooling::QName* schemaType)
818                     : AbstractXMLObject(nsURI, localName, prefix, schemaType) {
819                 init();
820             }
821
822             ResponseImpl(const ResponseImpl& src) : AbstractXMLObject(src), ResponseAbstractTypeImpl(src) {
823                 init();
824             }
825
826             void _clone(const ResponseImpl& src) {
827                 ResponseAbstractTypeImpl::_clone(src);
828                 IMPL_CLONE_TYPED_CHILD(Status);
829                 IMPL_CLONE_TYPED_FOREIGN_CHILDREN(Assertion,saml1);
830             }
831
832             IMPL_XMLOBJECT_CLONE_EX(Response);
833             IMPL_TYPED_CHILD(Status);
834             IMPL_TYPED_FOREIGN_CHILDREN(Assertion,saml1,m_children.end());
835
836         protected:
837             void processChildElement(XMLObject* childXMLObject, const DOMElement* root) {
838                 PROC_TYPED_CHILD(Status,SAML1P_NS,false);
839                 PROC_TYPED_FOREIGN_CHILDREN(Assertion,saml1,SAML1_NS,true);
840                 ResponseAbstractTypeImpl::processChildElement(childXMLObject,root);
841             }
842         };
843
844     };
845 };
846
847 #if defined (_MSC_VER)
848     #pragma warning( pop )
849 #endif
850
851 // Builder Implementations
852
853 IMPL_XMLOBJECTBUILDER(AssertionArtifact);
854 IMPL_XMLOBJECTBUILDER(AttributeQuery);
855 IMPL_XMLOBJECTBUILDER(AuthenticationQuery);
856 IMPL_XMLOBJECTBUILDER(AuthorizationDecisionQuery);
857 IMPL_XMLOBJECTBUILDER(Query);
858 IMPL_XMLOBJECTBUILDER(Request);
859 IMPL_XMLOBJECTBUILDER(RespondWith);
860 IMPL_XMLOBJECTBUILDER(Response);
861 IMPL_XMLOBJECTBUILDER(Status);
862 IMPL_XMLOBJECTBUILDER(StatusCode);
863 IMPL_XMLOBJECTBUILDER(StatusDetail);
864 IMPL_XMLOBJECTBUILDER(StatusMessage);
865
866 // Unicode literals
867 const XMLCh RequestAbstractType::LOCAL_NAME[] =             {chNull};
868 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);
869 const XMLCh RequestAbstractType::MINORVERSION_ATTRIB_NAME[] =   UNICODE_LITERAL_12(M,i,n,o,r,V,e,r,s,i,o,n);
870 const XMLCh RequestAbstractType::REQUESTID_ATTRIB_NAME[] =      UNICODE_LITERAL_9(R,e,q,u,e,s,t,I,D);
871 const XMLCh RequestAbstractType::ISSUEINSTANT_ATTRIB_NAME[] =   UNICODE_LITERAL_12(I,s,s,u,e,I,n,s,t,a,n,t);
872 const XMLCh ResponseAbstractType::LOCAL_NAME[] =            {chNull};
873 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);
874 const XMLCh ResponseAbstractType::MINORVERSION_ATTRIB_NAME[] =  UNICODE_LITERAL_12(M,i,n,o,r,V,e,r,s,i,o,n);
875 const XMLCh ResponseAbstractType::RESPONSEID_ATTRIB_NAME[] =    UNICODE_LITERAL_10(R,e,s,p,o,n,s,e,I,D);
876 const XMLCh ResponseAbstractType::ISSUEINSTANT_ATTRIB_NAME[] =  UNICODE_LITERAL_12(I,s,s,u,e,I,n,s,t,a,n,t);
877 const XMLCh ResponseAbstractType::INRESPONSETO_ATTRIB_NAME[] =  UNICODE_LITERAL_12(I,n,R,e,s,p,o,n,s,e,T,o);
878 const XMLCh ResponseAbstractType::RECIPIENT_ATTRIB_NAME[] =     UNICODE_LITERAL_9(R,e,c,i,p,i,e,n,t);
879 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);
880 const XMLCh AttributeQuery::LOCAL_NAME[] =                  UNICODE_LITERAL_14(A,t,t,r,i,b,u,t,e,Q,u,e,r,y);
881 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);
882 const XMLCh AttributeQuery::RESOURCE_ATTRIB_NAME[] =        UNICODE_LITERAL_8(R,e,s,o,u,r,c,e);
883 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);
884 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);
885 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);
886 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);
887 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);
888 const XMLCh AuthorizationDecisionQuery::RESOURCE_ATTRIB_NAME[] =        UNICODE_LITERAL_8(R,e,s,o,u,r,c,e);
889 const XMLCh Query::LOCAL_NAME[] =                           UNICODE_LITERAL_5(Q,u,e,r,y);
890 const XMLCh Request::LOCAL_NAME[] =                         UNICODE_LITERAL_7(R,e,q,u,e,s,t);
891 const XMLCh Request::TYPE_NAME[] =                          UNICODE_LITERAL_11(R,e,q,u,e,s,t,T,y,p,e);
892 const XMLCh RespondWith::LOCAL_NAME[] =                     UNICODE_LITERAL_11(R,e,s,p,o,n,d,W,i,t,h);
893 const XMLCh Response::LOCAL_NAME[] =                        UNICODE_LITERAL_8(R,e,s,p,o,n,s,e);
894 const XMLCh Response::TYPE_NAME[] =                         UNICODE_LITERAL_12(R,e,s,p,o,n,s,e,T,y,p,e);
895 const XMLCh Status::LOCAL_NAME[] =                          UNICODE_LITERAL_6(S,t,a,t,u,s);
896 const XMLCh Status::TYPE_NAME[] =                           UNICODE_LITERAL_10(S,t,a,t,u,s,T,y,p,e);
897 const XMLCh StatusCode::LOCAL_NAME[] =                      UNICODE_LITERAL_10(S,t,a,t,u,s,C,o,d,e);
898 const XMLCh StatusCode::TYPE_NAME[] =                       UNICODE_LITERAL_14(S,t,a,t,u,s,C,o,d,e,T,y,p,e);
899 const XMLCh StatusCode::VALUE_ATTRIB_NAME[] =               UNICODE_LITERAL_5(V,a,l,u,e);
900 const XMLCh StatusDetail::LOCAL_NAME[] =                    UNICODE_LITERAL_12(S,t,a,t,u,s,D,e,t,a,i,l);
901 const XMLCh StatusDetail::TYPE_NAME[] =                     UNICODE_LITERAL_16(S,t,a,t,u,s,D,e,t,a,i,l,T,y,p,e);
902 const XMLCh StatusMessage::LOCAL_NAME[] =                   UNICODE_LITERAL_13(S,t,a,t,u,s,M,e,s,s,a,g,e);
903 const XMLCh SubjectQuery::LOCAL_NAME[] =                    UNICODE_LITERAL_12(S,u,b,j,e,c,t,Q,u,e,r,y);
904
905 #define XCH(ch) chLatin_##ch
906 #define XNUM(d) chDigit_##d
907
908 const XMLCh _SUCCESS[] =                                    UNICODE_LITERAL_7(S,u,c,c,e,s,s);
909 const XMLCh _REQUESTER[] =                                  UNICODE_LITERAL_9(R,e,q,u,e,s,t,e,r);
910 const XMLCh _RESPONDER[] =                                  UNICODE_LITERAL_9(R,e,s,p,o,n,d,e,r);
911 const XMLCh _VERSIONMISMATCH[] =                            UNICODE_LITERAL_15(V,e,r,s,i,o,n,M,i,s,m,a,t,c,h);
912
913 xmltooling::QName StatusCode::SUCCESS(SAML1P_NS,_SUCCESS,SAML1P_PREFIX);
914 xmltooling::QName StatusCode::REQUESTER(SAML1P_NS,_REQUESTER,SAML1P_PREFIX);
915 xmltooling::QName StatusCode::RESPONDER(SAML1P_NS,_RESPONDER,SAML1P_PREFIX);
916 xmltooling::QName StatusCode::VERSIONMISMATCH(SAML1P_NS,_VERSIONMISMATCH,SAML1P_PREFIX);