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