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