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