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