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