d765e13a1198f158f7d2e69fe2ffeaffafba5f9a
[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             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                 return m_qname;
86             }
87
88             void setQName(const xmltooling::QName* qname) {
89                 m_qname=prepareForAssignment(m_qname,qname);
90                 if (m_qname) {
91                     auto_ptr_XMLCh temp(m_qname->toString().c_str());
92                     setTextContent(temp.get());
93                 }
94                 else
95                     setTextContent(nullptr);
96             }
97
98             IMPL_XMLOBJECT_CLONE(RespondWith);
99         };
100
101         class SAML_DLLLOCAL QueryImpl : public virtual Query, public AnyElementImpl
102         {
103         public:
104             virtual ~QueryImpl() {}
105
106             QueryImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const xmltooling::QName* schemaType)
107                 : AbstractXMLObject(nsURI, localName, prefix, schemaType) {
108             }
109
110             QueryImpl(const QueryImpl& src) : AbstractXMLObject(src), AnyElementImpl(src) {}
111
112             IMPL_XMLOBJECT_CLONE(Query);
113         };
114
115         class SAML_DLLLOCAL SubjectQueryImpl : public virtual SubjectQuery,
116             public AbstractComplexElement,
117             public AbstractDOMCachingXMLObject,
118             public AbstractXMLObjectMarshaller,
119             public AbstractXMLObjectUnmarshaller
120         {
121             void init() {
122                 m_Subject=nullptr;
123                 m_children.push_back(nullptr);
124                 m_pos_Subject=m_children.begin();
125             }
126         protected:
127             SubjectQueryImpl() {
128                 init();
129             }
130         public:
131             virtual ~SubjectQueryImpl() {}
132
133             SubjectQueryImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const xmltooling::QName* schemaType)
134                 : AbstractXMLObject(nsURI, localName, prefix, schemaType) {
135                 init();
136             }
137
138             SubjectQueryImpl(const SubjectQueryImpl& src)
139                     : AbstractXMLObject(src), AbstractComplexElement(src), AbstractDOMCachingXMLObject(src) {
140                 init();
141                 if (src.getSubject())
142                     setSubject(src.getSubject()->cloneSubject());
143             }
144
145             IMPL_TYPED_CHILD(Subject);
146
147         protected:
148             void processChildElement(XMLObject* childXMLObject, const DOMElement* root) {
149                 PROC_TYPED_CHILD(Subject,SAML1_NS,true);
150                 AbstractXMLObjectUnmarshaller::processChildElement(childXMLObject,root);
151             }
152         };
153
154         class SAML_DLLLOCAL AuthenticationQueryImpl : public virtual AuthenticationQuery, public SubjectQueryImpl
155         {
156             void init() {
157                 m_AuthenticationMethod=nullptr;
158             }
159         public:
160             virtual ~AuthenticationQueryImpl() {
161                 XMLString::release(&m_AuthenticationMethod);
162             }
163
164             AuthenticationQueryImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const xmltooling::QName* schemaType)
165                 : AbstractXMLObject(nsURI, localName, prefix, schemaType) {
166                 init();
167             }
168
169             AuthenticationQueryImpl(const AuthenticationQueryImpl& src) : AbstractXMLObject(src), SubjectQueryImpl(src) {
170                 init();
171                 setAuthenticationMethod(src.getAuthenticationMethod());
172             }
173
174             IMPL_XMLOBJECT_CLONE(AuthenticationQuery);
175             SubjectQuery* cloneSubjectQuery() const {
176                 return cloneAuthenticationQuery();
177             }
178             Query* cloneQuery() const {
179                 return cloneAuthenticationQuery();
180             }
181             IMPL_STRING_ATTRIB(AuthenticationMethod);
182
183         protected:
184             void marshallAttributes(DOMElement* domElement) const {
185                 MARSHALL_STRING_ATTRIB(AuthenticationMethod,AUTHENTICATIONMETHOD,nullptr);
186                 SubjectQueryImpl::marshallAttributes(domElement);
187             }
188
189             void processAttribute(const DOMAttr* attribute) {
190                 PROC_STRING_ATTRIB(AuthenticationMethod,AUTHENTICATIONMETHOD,nullptr);
191                 SubjectQueryImpl::processAttribute(attribute);
192             }
193         };
194
195         class SAML_DLLLOCAL AttributeQueryImpl : public virtual AttributeQuery, public SubjectQueryImpl
196         {
197             void init() {
198                 m_Resource=nullptr;
199             }
200         public:
201             virtual ~AttributeQueryImpl() {
202                 XMLString::release(&m_Resource);
203             }
204
205             AttributeQueryImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const xmltooling::QName* schemaType)
206                 : AbstractXMLObject(nsURI, localName, prefix, schemaType) {
207                 init();
208             }
209
210             AttributeQueryImpl(const AttributeQueryImpl& src) : AbstractXMLObject(src), SubjectQueryImpl(src) {
211                 init();
212                 setResource(src.getResource());
213                 VectorOf(AttributeDesignator) v=getAttributeDesignators();
214                 for (vector<AttributeDesignator*>::const_iterator i=src.m_AttributeDesignators.begin(); i!=src.m_AttributeDesignators.end(); i++) {
215                     if (*i) {
216                         v.push_back((*i)->cloneAttributeDesignator());
217                     }
218                 }
219             }
220
221             IMPL_XMLOBJECT_CLONE(AttributeQuery);
222             SubjectQuery* cloneSubjectQuery() const {
223                 return cloneAttributeQuery();
224             }
225             Query* cloneQuery() const {
226                 return cloneAttributeQuery();
227             }
228             IMPL_STRING_ATTRIB(Resource);
229             IMPL_TYPED_CHILDREN(AttributeDesignator,m_children.end());
230
231         protected:
232             void marshallAttributes(DOMElement* domElement) const {
233                 MARSHALL_STRING_ATTRIB(Resource,RESOURCE,nullptr);
234                 SubjectQueryImpl::marshallAttributes(domElement);
235             }
236
237             void processChildElement(XMLObject* childXMLObject, const DOMElement* root) {
238                 PROC_TYPED_CHILDREN(AttributeDesignator,SAML1_NS,true);
239                 SubjectQueryImpl::processChildElement(childXMLObject,root);
240             }
241
242             void processAttribute(const DOMAttr* attribute) {
243                 PROC_STRING_ATTRIB(Resource,RESOURCE,nullptr);
244                 SubjectQueryImpl::processAttribute(attribute);
245             }
246         };
247
248         class SAML_DLLLOCAL AuthorizationDecisionQueryImpl : public virtual AuthorizationDecisionQuery, public SubjectQueryImpl
249         {
250             void init() {
251                 m_Resource=nullptr;
252                 m_Evidence=nullptr;
253                 m_children.push_back(nullptr);
254                 m_pos_Evidence=m_pos_Subject;
255                 ++m_pos_Evidence;
256             }
257         public:
258             virtual ~AuthorizationDecisionQueryImpl() {
259                 XMLString::release(&m_Resource);
260             }
261
262             AuthorizationDecisionQueryImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const xmltooling::QName* schemaType)
263                 : AbstractXMLObject(nsURI, localName, prefix, schemaType) {
264                 init();
265             }
266
267             AuthorizationDecisionQueryImpl(const AuthorizationDecisionQueryImpl& src) : AbstractXMLObject(src), SubjectQueryImpl(src) {
268                 init();
269                 setResource(src.getResource());
270                 if (src.getEvidence())
271                     setEvidence(src.getEvidence()->cloneEvidence());
272                 VectorOf(Action) v=getActions();
273                 for (vector<Action*>::const_iterator i=src.m_Actions.begin(); i!=src.m_Actions.end(); i++) {
274                     if (*i) {
275                         v.push_back((*i)->cloneAction());
276                     }
277                 }
278             }
279
280             IMPL_XMLOBJECT_CLONE(AuthorizationDecisionQuery);
281             SubjectQuery* cloneSubjectQuery() const {
282                 return cloneAuthorizationDecisionQuery();
283             }
284             Query* cloneQuery() const {
285                 return cloneAuthorizationDecisionQuery();
286             }
287             IMPL_STRING_ATTRIB(Resource);
288             IMPL_TYPED_CHILD(Evidence);
289             IMPL_TYPED_CHILDREN(Action, m_pos_Evidence);
290
291         protected:
292             void marshallAttributes(DOMElement* domElement) const {
293                 MARSHALL_STRING_ATTRIB(Resource,RESOURCE,nullptr);
294                 SubjectQueryImpl::marshallAttributes(domElement);
295             }
296
297             void processChildElement(XMLObject* childXMLObject, const DOMElement* root) {
298                 PROC_TYPED_CHILD(Evidence,SAML1_NS,false);
299                 PROC_TYPED_CHILDREN(Action,SAML1_NS,false);
300                 SubjectQueryImpl::processChildElement(childXMLObject,root);
301             }
302
303             void processAttribute(const DOMAttr* attribute) {
304                 PROC_STRING_ATTRIB(Resource,RESOURCE,nullptr);
305                 SubjectQueryImpl::processAttribute(attribute);
306             }
307         };
308
309         class SAML_DLLLOCAL RequestAbstractTypeImpl : public virtual RequestAbstractType,
310             public AbstractComplexElement,
311             public AbstractDOMCachingXMLObject,
312             public AbstractXMLObjectMarshaller,
313             public AbstractXMLObjectUnmarshaller
314         {
315             void init() {
316                 m_MinorVersion=nullptr;
317                 m_RequestID=nullptr;
318                 m_IssueInstant=nullptr;
319                 m_children.push_back(nullptr);
320                 m_Signature=nullptr;
321                 m_pos_Signature=m_children.begin();
322             }
323         protected:
324             RequestAbstractTypeImpl() {
325                 init();
326             }
327         public:
328             virtual ~RequestAbstractTypeImpl() {
329                 XMLString::release(&m_MinorVersion);
330                 XMLString::release(&m_RequestID);
331                 delete m_IssueInstant;
332             }
333
334             RequestAbstractTypeImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const xmltooling::QName* schemaType)
335                 : AbstractXMLObject(nsURI, localName, prefix, schemaType) {
336                 init();
337             }
338
339             RequestAbstractTypeImpl(const RequestAbstractTypeImpl& src)
340                     : AbstractXMLObject(src), AbstractComplexElement(src), AbstractDOMCachingXMLObject(src) {
341                 init();
342                 setMinorVersion(src.m_MinorVersion);
343                 setRequestID(src.getRequestID());
344                 setIssueInstant(src.getIssueInstant());
345                 if (src.getSignature())
346                     setSignature(src.getSignature()->cloneSignature());
347                 VectorOf(RespondWith) v=getRespondWiths();
348                 for (vector<RespondWith*>::const_iterator i=src.m_RespondWiths.begin(); i!=src.m_RespondWiths.end(); i++) {
349                     if (*i) {
350                         v.push_back((*i)->cloneRespondWith());
351                     }
352                 }
353             }
354
355             //IMPL_TYPED_CHILD(Signature);
356             // Need customized setter.
357         protected:
358             Signature* m_Signature;
359             list<XMLObject*>::iterator m_pos_Signature;
360         public:
361             Signature* getSignature() const {
362                 return m_Signature;
363             }
364
365             void setSignature(Signature* sig) {
366                 prepareForAssignment(m_Signature,sig);
367                 *m_pos_Signature=m_Signature=sig;
368                 // Sync content reference back up.
369                 if (m_Signature)
370                     m_Signature->setContentReference(new opensaml::ContentReference(*this));
371             }
372
373             IMPL_INTEGER_ATTRIB(MinorVersion);
374             IMPL_STRING_ATTRIB(RequestID);    // have to special-case getXMLID
375             const XMLCh* getXMLID() const {
376                 pair<bool,int> v = getMinorVersion();
377                 return (!v.first || v.second > 0) ? m_RequestID : nullptr;
378             }
379             const XMLCh* getID() const {
380                 return getRequestID();
381             }
382             void releaseDOM() const {
383                 if (getDOM())
384                     getDOM()->removeAttributeNS(nullptr, REQUESTID_ATTRIB_NAME);
385                 AbstractDOMCachingXMLObject::releaseDOM();
386             }
387             IMPL_DATETIME_ATTRIB(IssueInstant,0);
388             IMPL_TYPED_CHILDREN(RespondWith,m_pos_Signature);
389
390         protected:
391             void prepareForMarshalling() const {
392                 if (m_Signature)
393                     declareNonVisibleNamespaces();
394             }
395
396             void marshallAttributes(DOMElement* domElement) const {
397                 static const XMLCh MAJORVERSION[] = UNICODE_LITERAL_12(M,a,j,o,r,V,e,r,s,i,o,n);
398                 domElement->setAttributeNS(nullptr,MAJORVERSION,XML_ONE);
399                 if (!m_MinorVersion)
400                     const_cast<RequestAbstractTypeImpl*>(this)->m_MinorVersion=XMLString::replicate(XML_ONE);
401                 MARSHALL_INTEGER_ATTRIB(MinorVersion,MINORVERSION,nullptr);
402                 if (!m_RequestID)
403                     const_cast<RequestAbstractTypeImpl*>(this)->m_RequestID=SAMLConfig::getConfig().generateIdentifier();
404                 domElement->setAttributeNS(nullptr, REQUESTID_ATTRIB_NAME, m_RequestID);
405                 if (*m_MinorVersion!=chDigit_0) {
406 #ifdef XMLTOOLING_XERCESC_BOOLSETIDATTRIBUTE
407                     domElement->setIdAttributeNS(nullptr, REQUESTID_ATTRIB_NAME, true);
408 #else
409                     domElement->setIdAttributeNS(nullptr, REQUESTID_ATTRIB_NAME);
410 #endif
411                 }
412                 if (!m_IssueInstant) {
413                     const_cast<RequestAbstractTypeImpl*>(this)->m_IssueInstantEpoch=time(nullptr);
414                     const_cast<RequestAbstractTypeImpl*>(this)->m_IssueInstant=new DateTime(m_IssueInstantEpoch);
415                 }
416                 MARSHALL_DATETIME_ATTRIB(IssueInstant,ISSUEINSTANT,nullptr);
417             }
418
419             void processChildElement(XMLObject* childXMLObject, const DOMElement* root) {
420                 PROC_TYPED_CHILDREN(RespondWith,SAML1P_NS,false);
421                 PROC_TYPED_CHILD(Signature,XMLSIG_NS,false);
422                 AbstractXMLObjectUnmarshaller::processChildElement(childXMLObject,root);
423             }
424
425             void unmarshallAttributes(const DOMElement* domElement) {
426                 // Standard processing, but then we check IDness.
427                 AbstractXMLObjectUnmarshaller::unmarshallAttributes(domElement);
428                 if (m_RequestID && (!m_MinorVersion || *m_MinorVersion!=chDigit_0)) {
429 #ifdef XMLTOOLING_XERCESC_BOOLSETIDATTRIBUTE
430                     const_cast<DOMElement*>(domElement)->setIdAttributeNS(nullptr, REQUESTID_ATTRIB_NAME, true);
431 #else
432                     const_cast<DOMElement*>(domElement)->setIdAttributeNS(nullptr, REQUESTID_ATTRIB_NAME);
433 #endif
434                 }
435             }
436
437             void processAttribute(const DOMAttr* attribute) {
438                 static const XMLCh MAJORVERSION[] = UNICODE_LITERAL_12(M,a,j,o,r,V,e,r,s,i,o,n);
439                 if (XMLHelper::isNodeNamed(attribute,nullptr,MAJORVERSION)) {
440                     if (!XMLString::equals(attribute->getValue(),XML_ONE))
441                         throw UnmarshallingException("Request has invalid major version.");
442                 }
443                 PROC_INTEGER_ATTRIB(MinorVersion,MINORVERSION,nullptr);
444                 PROC_STRING_ATTRIB(RequestID,REQUESTID,nullptr);
445                 PROC_DATETIME_ATTRIB(IssueInstant,ISSUEINSTANT,nullptr);
446             }
447         };
448
449         class SAML_DLLLOCAL RequestImpl : public virtual Request, public RequestAbstractTypeImpl
450         {
451             void init() {
452                 m_children.push_back(nullptr);
453                 m_Query=nullptr;
454                 m_pos_Query=m_pos_Signature;
455                 ++m_pos_Query;
456             }
457         public:
458             virtual ~RequestImpl() {}
459
460             RequestImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const xmltooling::QName* schemaType)
461                 : AbstractXMLObject(nsURI, localName, prefix, schemaType) {
462                 init();
463             }
464
465             RequestImpl(const RequestImpl& src) : AbstractXMLObject(src), RequestAbstractTypeImpl(src) {
466                 init();
467                 if (src.getQuery())
468                     setQuery(src.getQuery()->cloneQuery());
469                 VectorOf(AssertionIDReference) v=getAssertionIDReferences();
470                 for (vector<AssertionIDReference*>::const_iterator i=src.m_AssertionIDReferences.begin(); i!=src.m_AssertionIDReferences.end(); i++) {
471                     if (*i) {
472                         v.push_back((*i)->cloneAssertionIDReference());
473                     }
474                 }
475                 VectorOf(AssertionArtifact) v2=getAssertionArtifacts();
476                 for (vector<AssertionArtifact*>::const_iterator i=src.m_AssertionArtifacts.begin(); i!=src.m_AssertionArtifacts.end(); i++) {
477                     if (*i) {
478                         v2.push_back((*i)->cloneAssertionArtifact());
479                     }
480                 }
481             }
482
483             IMPL_XMLOBJECT_CLONE(Request);
484             RequestAbstractType* cloneRequestAbstractType() const {
485                 return cloneRequest();
486             }
487             IMPL_TYPED_CHILD(Query);
488
489             SubjectQuery* getSubjectQuery() const {
490                 return dynamic_cast<SubjectQuery*>(getQuery());
491             }
492             AuthenticationQuery* getAuthenticationQuery() const {
493                 return dynamic_cast<AuthenticationQuery*>(getQuery());
494             }
495             AttributeQuery* getAttributeQuery() const {
496                 return dynamic_cast<AttributeQuery*>(getQuery());
497             }
498             AuthorizationDecisionQuery* getAuthorizationDecisionQuery() const {
499                 return dynamic_cast<AuthorizationDecisionQuery*>(getQuery());
500             }
501
502             void setSubjectQuery(SubjectQuery* q) {
503                 setQuery(q);
504             }
505             void setAuthenticationQuery(AuthenticationQuery* q) {
506                 setQuery(q);
507             }
508             void setAttributeQuery(AttributeQuery* q) {
509                 setQuery(q);
510             }
511             void setAuthorizationDecisionQuery(AuthorizationDecisionQuery* q) {
512                 setQuery(q);
513             }
514
515             IMPL_TYPED_CHILDREN(AssertionIDReference, m_children.end());
516             IMPL_TYPED_CHILDREN(AssertionArtifact, m_children.end());
517
518         protected:
519             void processChildElement(XMLObject* childXMLObject, const DOMElement* root) {
520                 PROC_TYPED_CHILD(Query,SAML1P_NS,true);
521                 PROC_TYPED_CHILDREN(AssertionIDReference,SAML1_NS,false);
522                 PROC_TYPED_CHILDREN(AssertionArtifact,SAML1P_NS,false);
523                 RequestAbstractTypeImpl::processChildElement(childXMLObject,root);
524             }
525         };
526
527         class SAML_DLLLOCAL StatusCodeImpl : public virtual StatusCode,
528             public AbstractComplexElement,
529             public AbstractDOMCachingXMLObject,
530             public AbstractXMLObjectMarshaller,
531             public AbstractXMLObjectUnmarshaller
532         {
533             void init() {
534                 m_Value=nullptr;
535                 m_children.push_back(nullptr);
536                 m_StatusCode=nullptr;
537                 m_pos_StatusCode=m_children.begin();
538             }
539         public:
540             virtual ~StatusCodeImpl() {
541                 delete m_Value;
542             }
543
544             StatusCodeImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const xmltooling::QName* schemaType)
545                 : AbstractXMLObject(nsURI, localName, prefix, schemaType) {
546                 init();
547             }
548
549             StatusCodeImpl(const StatusCodeImpl& src)
550                     : AbstractXMLObject(src), AbstractComplexElement(src), AbstractDOMCachingXMLObject(src) {
551                 init();
552                 setValue(src.getValue());
553                 if (src.getStatusCode())
554                     setStatusCode(src.getStatusCode()->cloneStatusCode());
555             }
556
557             IMPL_XMLOBJECT_CLONE(StatusCode);
558             IMPL_XMLOBJECT_ATTRIB(Value,xmltooling::QName);
559             IMPL_TYPED_CHILD(StatusCode);
560
561         protected:
562             void marshallAttributes(DOMElement* domElement) const {
563                 MARSHALL_QNAME_ATTRIB(Value,VALUE,nullptr);
564             }
565
566             void processChildElement(XMLObject* childXMLObject, const DOMElement* root) {
567                 PROC_TYPED_CHILD(StatusCode,SAML1P_NS,true);
568                 AbstractXMLObjectUnmarshaller::processChildElement(childXMLObject,root);
569             }
570
571             void processAttribute(const DOMAttr* attribute) {
572                 PROC_QNAME_ATTRIB(Value,VALUE,nullptr);
573             }
574         };
575
576         class SAML_DLLLOCAL StatusDetailImpl : public virtual StatusDetail,
577             public AbstractComplexElement,
578             public AbstractDOMCachingXMLObject,
579             public AbstractXMLObjectMarshaller,
580             public AbstractXMLObjectUnmarshaller
581         {
582         public:
583             virtual ~StatusDetailImpl() {}
584
585             StatusDetailImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const xmltooling::QName* schemaType)
586                 : AbstractXMLObject(nsURI, localName, prefix, schemaType) {
587             }
588
589             StatusDetailImpl(const StatusDetailImpl& src)
590                     : AbstractXMLObject(src), AbstractComplexElement(src), AbstractDOMCachingXMLObject(src) {
591                 VectorOf(XMLObject) v=getUnknownXMLObjects();
592                 for (vector<XMLObject*>::const_iterator i=src.m_UnknownXMLObjects.begin(); i!=src.m_UnknownXMLObjects.end(); ++i)
593                     v.push_back((*i)->clone());
594             }
595
596             IMPL_XMLOBJECT_CLONE(StatusDetail);
597             IMPL_XMLOBJECT_CHILDREN(UnknownXMLObject,m_children.end());
598
599         protected:
600             void processChildElement(XMLObject* childXMLObject, const DOMElement* root) {
601                 getUnknownXMLObjects().push_back(childXMLObject);
602             }
603         };
604
605         class SAML_DLLLOCAL StatusImpl : public virtual Status,
606             public AbstractComplexElement,
607             public AbstractDOMCachingXMLObject,
608             public AbstractXMLObjectMarshaller,
609             public AbstractXMLObjectUnmarshaller
610         {
611             void init() {
612                 m_children.push_back(nullptr);
613                 m_children.push_back(nullptr);
614                 m_children.push_back(nullptr);
615                 m_StatusCode=nullptr;
616                 m_pos_StatusCode=m_children.begin();
617                 m_StatusMessage=nullptr;
618                 m_pos_StatusMessage=m_pos_StatusCode;
619                 ++m_pos_StatusMessage;
620                 m_StatusDetail=nullptr;
621                 m_pos_StatusDetail=m_pos_StatusMessage;
622                 ++m_pos_StatusDetail;
623             }
624         public:
625             virtual ~StatusImpl() {}
626
627             StatusImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const xmltooling::QName* schemaType)
628                 : AbstractXMLObject(nsURI, localName, prefix, schemaType) {
629                 init();
630             }
631
632             StatusImpl(const StatusImpl& src)
633                     : AbstractXMLObject(src), AbstractComplexElement(src), AbstractDOMCachingXMLObject(src) {
634                 init();
635                 if (src.getStatusCode())
636                     setStatusCode(src.getStatusCode()->cloneStatusCode());
637                 if (src.getStatusMessage())
638                     setStatusMessage(src.getStatusMessage()->cloneStatusMessage());
639                 if (src.getStatusDetail())
640                     setStatusDetail(src.getStatusDetail()->cloneStatusDetail());
641             }
642
643             IMPL_XMLOBJECT_CLONE(Status);
644             IMPL_TYPED_CHILD(StatusCode);
645             IMPL_TYPED_CHILD(StatusMessage);
646             IMPL_TYPED_CHILD(StatusDetail);
647
648         protected:
649             void processChildElement(XMLObject* childXMLObject, const DOMElement* root) {
650                 PROC_TYPED_CHILD(StatusCode,SAML1P_NS,false);
651                 PROC_TYPED_CHILD(StatusMessage,SAML1P_NS,false);
652                 PROC_TYPED_CHILD(StatusDetail,SAML1P_NS,false);
653                 AbstractXMLObjectUnmarshaller::processChildElement(childXMLObject,root);
654             }
655         };
656
657         class SAML_DLLLOCAL ResponseAbstractTypeImpl : public virtual ResponseAbstractType,
658             public AbstractComplexElement,
659             public AbstractDOMCachingXMLObject,
660             public AbstractXMLObjectMarshaller,
661             public AbstractXMLObjectUnmarshaller
662         {
663             void init() {
664                 m_MinorVersion=nullptr;
665                 m_ResponseID=nullptr;
666                 m_InResponseTo=nullptr;
667                 m_IssueInstant=nullptr;
668                 m_Recipient=nullptr;
669                 m_children.push_back(nullptr);
670                 m_Signature=nullptr;
671                 m_pos_Signature=m_children.begin();
672             }
673         protected:
674             ResponseAbstractTypeImpl() {
675                 init();
676             }
677         public:
678             virtual ~ResponseAbstractTypeImpl() {
679                 XMLString::release(&m_MinorVersion);
680                 XMLString::release(&m_ResponseID);
681                 XMLString::release(&m_InResponseTo);
682                 XMLString::release(&m_Recipient);
683                 delete m_IssueInstant;
684             }
685
686             ResponseAbstractTypeImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const xmltooling::QName* schemaType)
687                 : AbstractXMLObject(nsURI, localName, prefix, schemaType) {
688                 init();
689             }
690
691             ResponseAbstractTypeImpl(const ResponseAbstractTypeImpl& src)
692                     : AbstractXMLObject(src), AbstractComplexElement(src), AbstractDOMCachingXMLObject(src) {
693                 init();
694                 setMinorVersion(src.m_MinorVersion);
695                 setResponseID(src.getResponseID());
696                 setInResponseTo(src.getInResponseTo());
697                 setIssueInstant(src.getIssueInstant());
698                 setRecipient(src.getRecipient());
699                 if (src.getSignature())
700                     setSignature(src.getSignature()->cloneSignature());
701             }
702
703             //IMPL_TYPED_CHILD(Signature);
704             // Need customized setter.
705         protected:
706             Signature* m_Signature;
707             list<XMLObject*>::iterator m_pos_Signature;
708         public:
709             Signature* getSignature() const {
710                 return m_Signature;
711             }
712
713             void setSignature(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             IMPL_INTEGER_ATTRIB(MinorVersion);
722             IMPL_STRING_ATTRIB(ResponseID);    // have to special-case getXMLID
723             const XMLCh* getXMLID() const {
724                 pair<bool,int> v = getMinorVersion();
725                 return (!v.first || v.second > 0) ? m_ResponseID : nullptr;
726             }
727             const XMLCh* getID() const {
728                 return getResponseID();
729             }
730             void releaseDOM() const {
731                 if (getDOM())
732                     getDOM()->removeAttributeNS(nullptr, RESPONSEID_ATTRIB_NAME);
733                 AbstractDOMCachingXMLObject::releaseDOM();
734             }
735             IMPL_STRING_ATTRIB(InResponseTo);
736             IMPL_DATETIME_ATTRIB(IssueInstant,0);
737             IMPL_STRING_ATTRIB(Recipient);
738
739         protected:
740             void prepareForMarshalling() const {
741                 if (m_Signature)
742                     declareNonVisibleNamespaces();
743             }
744
745             void marshallAttributes(DOMElement* domElement) const {
746                 static const XMLCh MAJORVERSION[] = UNICODE_LITERAL_12(M,a,j,o,r,V,e,r,s,i,o,n);
747                 domElement->setAttributeNS(nullptr,MAJORVERSION,XML_ONE);
748                 if (!m_MinorVersion)
749                     const_cast<ResponseAbstractTypeImpl*>(this)->m_MinorVersion=XMLString::replicate(XML_ONE);
750                 MARSHALL_INTEGER_ATTRIB(MinorVersion,MINORVERSION,nullptr);
751                 if (!m_ResponseID)
752                     const_cast<ResponseAbstractTypeImpl*>(this)->m_ResponseID=SAMLConfig::getConfig().generateIdentifier();
753                 domElement->setAttributeNS(nullptr, RESPONSEID_ATTRIB_NAME, m_ResponseID);
754                 if (*m_MinorVersion!=chDigit_0) {
755 #ifdef XMLTOOLING_XERCESC_BOOLSETIDATTRIBUTE
756                     domElement->setIdAttributeNS(nullptr, RESPONSEID_ATTRIB_NAME, true);
757 #else
758                     domElement->setIdAttributeNS(nullptr, RESPONSEID_ATTRIB_NAME);
759 #endif
760                 }
761                 MARSHALL_STRING_ATTRIB(InResponseTo,INRESPONSETO,nullptr);
762                 if (!m_IssueInstant) {
763                     const_cast<ResponseAbstractTypeImpl*>(this)->m_IssueInstantEpoch=time(nullptr);
764                     const_cast<ResponseAbstractTypeImpl*>(this)->m_IssueInstant=new DateTime(m_IssueInstantEpoch);
765                 }
766                 MARSHALL_DATETIME_ATTRIB(IssueInstant,ISSUEINSTANT,nullptr);
767                 MARSHALL_STRING_ATTRIB(Recipient,RECIPIENT,nullptr);
768             }
769
770             void processChildElement(XMLObject* childXMLObject, const DOMElement* root) {
771                 PROC_TYPED_CHILD(Signature,XMLSIG_NS,false);
772                 AbstractXMLObjectUnmarshaller::processChildElement(childXMLObject,root);
773             }
774
775             void unmarshallAttributes(const DOMElement* domElement) {
776                 // Standard processing, but then we check IDness.
777                 AbstractXMLObjectUnmarshaller::unmarshallAttributes(domElement);
778                 if (m_ResponseID && (!m_MinorVersion || *m_MinorVersion!=chDigit_0)) {
779 #ifdef XMLTOOLING_XERCESC_BOOLSETIDATTRIBUTE
780                     const_cast<DOMElement*>(domElement)->setIdAttributeNS(nullptr, RESPONSEID_ATTRIB_NAME, true);
781 #else
782                     const_cast<DOMElement*>(domElement)->setIdAttributeNS(nullptr, RESPONSEID_ATTRIB_NAME);
783 #endif
784                 }
785             }
786
787             void processAttribute(const DOMAttr* attribute) {
788                 static const XMLCh MAJORVERSION[] = UNICODE_LITERAL_12(M,a,j,o,r,V,e,r,s,i,o,n);
789                 if (XMLHelper::isNodeNamed(attribute,nullptr,MAJORVERSION)) {
790                     if (!XMLString::equals(attribute->getValue(),XML_ONE))
791                         throw UnmarshallingException("Response has invalid major version.");
792                 }
793                 PROC_INTEGER_ATTRIB(MinorVersion,MINORVERSION,nullptr);
794                 PROC_STRING_ATTRIB(ResponseID,RESPONSEID,nullptr);
795                 PROC_STRING_ATTRIB(InResponseTo,INRESPONSETO,nullptr);
796                 PROC_DATETIME_ATTRIB(IssueInstant,ISSUEINSTANT,nullptr);
797                 PROC_STRING_ATTRIB(Recipient,RECIPIENT,nullptr);
798             }
799         };
800
801         class SAML_DLLLOCAL ResponseImpl : public virtual Response, public ResponseAbstractTypeImpl
802         {
803             void init() {
804                 m_children.push_back(nullptr);
805                 m_Status=nullptr;
806                 m_pos_Status=m_pos_Signature;
807                 ++m_pos_Status;
808             }
809         public:
810             virtual ~ResponseImpl() {}
811
812             ResponseImpl(const XMLCh* nsURI, const XMLCh* localName, const XMLCh* prefix, const xmltooling::QName* schemaType)
813                 : AbstractXMLObject(nsURI, localName, prefix, schemaType) {
814                 init();
815             }
816
817             ResponseImpl(const ResponseImpl& src) : AbstractXMLObject(src), ResponseAbstractTypeImpl(src) {
818                 init();
819                 if (src.getStatus())
820                     setStatus(src.getStatus()->cloneStatus());
821                 VectorOf(saml1::Assertion) v=getAssertions();
822                 for (vector<saml1::Assertion*>::const_iterator i=src.m_Assertions.begin(); i!=src.m_Assertions.end(); i++) {
823                     if (*i) {
824                         v.push_back((*i)->cloneAssertion());
825                     }
826                 }
827             }
828
829             IMPL_XMLOBJECT_CLONE(Response);
830             ResponseAbstractType* cloneResponseAbstractType() const {
831                 return cloneResponse();
832             }
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);