Replace "trusted" output flag with security mech ID.
[shibboleth/cpp-opensaml.git] / samltest / binding.h
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 #include "internal.h"
18
19 #include <saml/SAMLConfig.h>
20 #include <saml/binding/MessageDecoder.h>
21 #include <saml/binding/MessageEncoder.h>
22 #include <saml/binding/URLEncoder.h>
23 #include <saml/saml2/metadata/MetadataProvider.h>
24 #include <saml/security/X509TrustEngine.h>
25
26 using namespace saml2md;
27 using namespace xmlsignature;
28
29 class SAMLBindingBaseTestCase : public MessageDecoder::HTTPRequest, public MessageEncoder::HTTPResponse
30 {
31 protected:
32     CredentialResolver* m_creds; 
33     MetadataProvider* m_metadata;
34     opensaml::X509TrustEngine* m_trust;
35     map<string,string> m_fields;
36     map<string,string> m_headers;
37     string m_method,m_url;
38
39 public:
40     void setUp() {
41         m_creds=NULL;
42         m_metadata=NULL;
43         m_trust=NULL;
44         m_fields.clear();
45         m_headers.clear();
46         m_method.erase();
47         m_url.erase();
48
49         try {
50             string config = data_path + "binding/ExampleMetadataProvider.xml";
51             ifstream in(config.c_str());
52             DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(in);
53             XercesJanitor<DOMDocument> janitor(doc);
54     
55             auto_ptr_XMLCh path("path");
56             string s = data_path + "binding/example-metadata.xml";
57             auto_ptr_XMLCh file(s.c_str());
58             doc->getDocumentElement()->setAttributeNS(NULL,path.get(),file.get());
59     
60             m_metadata = SAMLConfig::getConfig().MetadataProviderManager.newPlugin(
61                 FILESYSTEM_METADATA_PROVIDER,doc->getDocumentElement()
62                 );
63             m_metadata->init();
64
65             config = data_path + "FilesystemCredentialResolver.xml";
66             ifstream in2(config.c_str());
67             DOMDocument* doc2=XMLToolingConfig::getConfig().getParser().parse(in2);
68             XercesJanitor<DOMDocument> janitor2(doc2);
69             m_creds = XMLToolingConfig::getConfig().CredentialResolverManager.newPlugin(
70                 FILESYSTEM_CREDENTIAL_RESOLVER,doc2->getDocumentElement()
71                 );
72                 
73             m_trust = dynamic_cast<X509TrustEngine*>(
74                 SAMLConfig::getConfig().TrustEngineManager.newPlugin(EXPLICIT_KEY_SAMLTRUSTENGINE, NULL)
75                 );
76         }
77         catch (XMLToolingException& ex) {
78             TS_TRACE(ex.what());
79             tearDown();
80             throw;
81         }
82
83     }
84     
85     void tearDown() {
86         delete m_creds;
87         delete m_metadata;
88         delete m_trust;
89         m_creds=NULL;
90         m_metadata=NULL;
91         m_trust=NULL;
92         m_fields.clear();
93         m_headers.clear();
94         m_method.erase();
95         m_url.erase();
96     }
97
98     // HTTPRequest methods
99
100     const char* getMethod() const {
101         return m_method.c_str();
102     } 
103
104     const char* getRequestURL() const {
105         return m_url.c_str();
106     }
107     
108     const char* getRequestBody() const {
109         return NULL;
110     }
111     
112     const char* getQueryString() const {
113         return NULL;
114     }
115     
116     string getRemoteUser() const {
117         return "";
118     }
119
120     string getHeader(const char* name) const {
121         map<string,string>::const_iterator i=m_headers.find(name);
122         return i==m_headers.end() ? "" : i->second;
123     }
124     
125     const char* getParameter(const char* name) const {
126         map<string,string>::const_iterator i=m_fields.find(name);
127         return i==m_fields.end() ? NULL : i->second.c_str();
128     }
129
130     vector<const char*>::size_type getParameters(const char* name, vector<const char*>& values) const {
131         values.clear();
132         map<string,string>::const_iterator i=m_fields.find(name);
133         if (i!=m_fields.end())
134             values.push_back(i->second.c_str());
135         return values.size();
136     }
137     
138     // HTTPResponse methods
139     
140     void setHeader(const char* name, const char* value) {
141         m_headers[name] = value ? value : "";
142     }
143     
144     void setCookie(const char* name, const char* value) {
145         m_headers["Set-Cookie"] = string(name) + "=" + (value ? value : "");
146     }
147     
148     // The amount of error checking missing from this is incredible, but as long
149     // as the test data isn't unexpected or malformed, it should work.
150     
151     long sendRedirect(const char* url) {
152         m_method = "GET";
153         char* dup = strdup(url);
154         char* pch = strchr(dup,'?');
155         if (pch) {
156             *pch++=0;
157             char* name=pch;
158             while (name && *name) {
159                 pch=strchr(pch,'=');
160                 *pch++=0;
161                 char* value=pch;
162                 pch=strchr(pch,'&');
163                 if (pch)
164                     *pch++=0;
165                 SAMLConfig::getConfig().getURLEncoder()->decode(value);
166                 m_fields[name] = value;
167                 name = pch; 
168             }
169         }
170         m_url = dup;
171         free(dup);
172         return m_fields.size();
173     }
174     
175     string html_decode(const string& s) const {
176         string decoded;
177         const char* ch=s.c_str();
178         while (*ch) {
179             if (*ch=='&') {
180                 if (!strncmp(ch,"&lt;",4)) {
181                     decoded+='<'; ch+=4;
182                 }
183                 else if (!strncmp(ch,"&gt;",4)) {
184                     decoded+='>'; ch+=4;
185                 }
186                 else if (!strncmp(ch,"&quot;",6)) {
187                     decoded+='"'; ch+=6;
188                 }
189                 else if (*++ch=='#') {
190                     decoded+=(char)atoi(++ch);
191                     ch=strchr(ch,';')+1;
192                 }
193             }
194             else {
195                 decoded+=*ch++;
196             }
197         }
198         return decoded;
199     }
200     
201     long sendResponse(std::istream& inputStream, int status = 200, const char* contentType = "text/html") {
202         m_method="POST";
203         string page,line;
204         while (getline(inputStream,line))
205             page += line + '\n';
206             
207         const char* pch=strstr(page.c_str(),"action=\"");
208         pch+=strlen("action=\"");
209         m_url = html_decode(page.substr(pch-page.c_str(),strchr(pch,'"')-pch));
210
211         while (pch=strstr(pch,"<input type=\"hidden\" name=\"")) {
212             pch+=strlen("<input type=\"hidden\" name=\"");
213             string name = page.substr(pch-page.c_str(),strchr(pch,'"')-pch);
214             pch=strstr(pch,"value=\"");
215             pch+=strlen("value=\"");
216             m_fields[name] = html_decode(page.substr(pch-page.c_str(),strchr(pch,'"')-pch));
217         }
218         return m_fields.size();
219     }
220 };