https://issues.shibboleth.net/jira/browse/SSPCPP-199
[shibboleth/cpp-sp.git] / shibsp / SPConfig.cpp
1
2 /*
3  *  Copyright 2001-2009 Internet2
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 /**
19  * SPConfig.cpp
20  *
21  * Library configuration
22  */
23
24 #include "internal.h"
25
26 #if defined(XMLTOOLING_LOG4SHIB)
27 # ifndef SHIBSP_LOG4SHIB
28 #  error "Logging library mismatch (XMLTooling is using log4shib)."
29 # endif
30 #elif defined(XMLTOOLING_LOG4CPP)
31 # ifndef SHIBSP_LOG4CPP
32 #  error "Logging library mismatch (XMLTooling is using log4cpp)."
33 # endif
34 #else
35 # error "No supported logging library."
36 #endif
37
38 #include "AccessControl.h"
39 #include "exceptions.h"
40 #include "RequestMapper.h"
41 #include "ServiceProvider.h"
42 #include "SessionCache.h"
43 #include "SPConfig.h"
44 #include "attribute/Attribute.h"
45 #include "handler/SessionInitiator.h"
46 #include "remoting/ListenerService.h"
47
48 #ifndef SHIBSP_LITE
49 # include "attribute/AttributeDecoder.h"
50 # include "attribute/filtering/AttributeFilter.h"
51 # include "attribute/filtering/MatchFunctor.h"
52 # include "attribute/resolver/AttributeExtractor.h"
53 # include "attribute/resolver/AttributeResolver.h"
54 # include "binding/ArtifactResolver.h"
55 # include "metadata/MetadataExt.h"
56 # include "security/PKIXTrustEngine.h"
57 # include <saml/SAMLConfig.h>
58 #else
59 # include <xmltooling/XMLToolingConfig.h>
60 #endif
61
62 #include <ctime>
63 #include <xercesc/util/XMLUniDefs.hpp>
64 #include <xmltooling/util/NDC.h>
65 #include <xmltooling/util/PathResolver.h>
66 #include <xmltooling/util/TemplateEngine.h>
67 #include <xmltooling/util/XMLHelper.h>
68
69 using namespace shibsp;
70 using namespace opensaml;
71 using namespace xmltooling;
72 using namespace std;
73
74 DECL_XMLTOOLING_EXCEPTION_FACTORY(AttributeException,shibsp);
75 DECL_XMLTOOLING_EXCEPTION_FACTORY(AttributeExtractionException,shibsp);
76 DECL_XMLTOOLING_EXCEPTION_FACTORY(AttributeFilteringException,shibsp);
77 DECL_XMLTOOLING_EXCEPTION_FACTORY(AttributeResolutionException,shibsp);
78 DECL_XMLTOOLING_EXCEPTION_FACTORY(ConfigurationException,shibsp);
79 DECL_XMLTOOLING_EXCEPTION_FACTORY(ListenerException,shibsp);
80
81 #ifdef SHIBSP_LITE
82 DECL_XMLTOOLING_EXCEPTION_FACTORY(BindingException,opensaml);
83 DECL_XMLTOOLING_EXCEPTION_FACTORY(SecurityPolicyException,opensaml);
84 DECL_XMLTOOLING_EXCEPTION_FACTORY(ProfileException,opensaml);
85 DECL_XMLTOOLING_EXCEPTION_FACTORY(FatalProfileException,opensaml);
86 DECL_XMLTOOLING_EXCEPTION_FACTORY(RetryableProfileException,opensaml);
87 DECL_XMLTOOLING_EXCEPTION_FACTORY(MetadataException,opensaml::saml2md);
88 #endif
89
90 namespace shibsp {
91    SPConfig g_config;
92 }
93
94 SPConfig& SPConfig::getConfig()
95 {
96     return g_config;
97 }
98
99 void SPConfig::setServiceProvider(ServiceProvider* serviceProvider)
100 {
101     delete m_serviceProvider;
102     m_serviceProvider = serviceProvider;
103 }
104
105 bool SPConfig::init(const char* catalog_path, const char* inst_prefix)
106 {
107 #ifdef _DEBUG
108     NDC ndc("init");
109 #endif
110     if (!inst_prefix)
111         inst_prefix = getenv("SHIBSP_PREFIX");
112     if (!inst_prefix)
113         inst_prefix = SHIBSP_PREFIX;
114     std::string inst_prefix2;
115     while (*inst_prefix) {
116         inst_prefix2.push_back((*inst_prefix=='\\') ? ('/') : (*inst_prefix));
117         ++inst_prefix;
118     }
119
120     const char* loglevel=getenv("SHIBSP_LOGGING");
121     if (!loglevel)
122         loglevel = SHIBSP_LOGGING;
123     std::string ll(loglevel);
124     PathResolver localpr;
125     localpr.setDefaultPrefix(inst_prefix2.c_str());
126     inst_prefix = getenv("SHIBSP_CFGDIR");
127     if (!inst_prefix)
128         inst_prefix = SHIBSP_CFGDIR;
129     localpr.setCfgDir(inst_prefix);
130     XMLToolingConfig::getConfig().log_config(localpr.resolve(ll, PathResolver::XMLTOOLING_CFG_FILE, PACKAGE_NAME).c_str());
131
132     Category& log=Category::getInstance(SHIBSP_LOGCAT".Config");
133     log.debug("%s library initialization started", PACKAGE_STRING);
134
135     if (!catalog_path)
136         catalog_path = getenv("SHIBSP_SCHEMAS");
137     if (!catalog_path)
138         catalog_path = SHIBSP_SCHEMAS;
139     XMLToolingConfig::getConfig().catalog_path = catalog_path;
140
141 #ifndef SHIBSP_LITE
142     if (!SAMLConfig::getConfig().init()) {
143         log.fatal("failed to initialize OpenSAML library");
144         return false;
145     }
146 #else
147     if (!XMLToolingConfig::getConfig().init()) {
148         log.fatal("failed to initialize XMLTooling library");
149         return false;
150     }
151 #endif
152     PathResolver* pr = XMLToolingConfig::getConfig().getPathResolver();
153     pr->setDefaultPackageName(PACKAGE_NAME);
154     pr->setDefaultPrefix(inst_prefix2.c_str());
155     pr->setCfgDir(inst_prefix);
156     inst_prefix = getenv("SHIBSP_LIBDIR");
157     if (!inst_prefix)
158         inst_prefix = SHIBSP_LIBDIR;
159     pr->setLibDir(inst_prefix);
160     inst_prefix = getenv("SHIBSP_LOGDIR");
161     if (!inst_prefix)
162         inst_prefix = SHIBSP_LOGDIR;
163     pr->setLogDir(inst_prefix);
164     inst_prefix = getenv("SHIBSP_RUNDIR");
165     if (!inst_prefix)
166         inst_prefix = SHIBSP_RUNDIR;
167     pr->setRunDir(inst_prefix);
168     inst_prefix = getenv("SHIBSP_XMLDIR");
169     if (!inst_prefix)
170         inst_prefix = SHIBSP_XMLDIR;
171     pr->setXMLDir(inst_prefix);
172
173     XMLToolingConfig::getConfig().setTemplateEngine(new TemplateEngine());
174     XMLToolingConfig::getConfig().getTemplateEngine()->setTagPrefix("shibmlp");
175
176     REGISTER_XMLTOOLING_EXCEPTION_FACTORY(AttributeException,shibsp);
177     REGISTER_XMLTOOLING_EXCEPTION_FACTORY(AttributeExtractionException,shibsp);
178     REGISTER_XMLTOOLING_EXCEPTION_FACTORY(AttributeFilteringException,shibsp);
179     REGISTER_XMLTOOLING_EXCEPTION_FACTORY(AttributeResolutionException,shibsp);
180     REGISTER_XMLTOOLING_EXCEPTION_FACTORY(ConfigurationException,shibsp);
181     REGISTER_XMLTOOLING_EXCEPTION_FACTORY(ListenerException,shibsp);
182
183 #ifdef SHIBSP_LITE
184     REGISTER_XMLTOOLING_EXCEPTION_FACTORY(BindingException,opensaml);
185     REGISTER_XMLTOOLING_EXCEPTION_FACTORY(SecurityPolicyException,opensaml);
186     REGISTER_XMLTOOLING_EXCEPTION_FACTORY(ProfileException,opensaml);
187     REGISTER_XMLTOOLING_EXCEPTION_FACTORY(FatalProfileException,opensaml);
188     REGISTER_XMLTOOLING_EXCEPTION_FACTORY(RetryableProfileException,opensaml);
189     REGISTER_XMLTOOLING_EXCEPTION_FACTORY(MetadataException,opensaml::saml2md);
190 #endif
191
192 #ifndef SHIBSP_LITE
193     if (isEnabled(Metadata))
194         registerMetadataExtClasses();
195     if (isEnabled(Trust))
196         registerPKIXTrustEngine();
197 #endif
198
199     registerAttributeFactories();
200     registerHandlers();
201     registerSessionInitiators();
202     registerServiceProviders();
203
204 #ifndef SHIBSP_LITE
205     if (isEnabled(AttributeResolution)) {
206         registerAttributeExtractors();
207         registerAttributeDecoders();
208         registerAttributeResolvers();
209         registerAttributeFilters();
210         registerMatchFunctors();
211     }
212 #endif
213
214     if (isEnabled(Listener))
215         registerListenerServices();
216
217     if (isEnabled(RequestMapping)) {
218         registerAccessControls();
219         registerRequestMappers();
220     }
221
222     if (isEnabled(Caching))
223         registerSessionCaches();
224
225 #ifndef SHIBSP_LITE
226     if (isEnabled(OutOfProcess))
227         m_artifactResolver = new ArtifactResolver();
228 #endif
229     srand(static_cast<unsigned int>(std::time(NULL)));
230
231     log.info("%s library initialization complete", PACKAGE_STRING);
232     return true;
233 }
234
235 void SPConfig::term()
236 {
237 #ifdef _DEBUG
238     NDC ndc("term");
239 #endif
240     Category& log=Category::getInstance(SHIBSP_LOGCAT".Config");
241     log.info("%s library shutting down", PACKAGE_STRING);
242
243     setServiceProvider(NULL);
244     if (m_configDoc)
245         m_configDoc->release();
246     m_configDoc = NULL;
247 #ifndef SHIBSP_LITE
248     setArtifactResolver(NULL);
249 #endif
250
251     ArtifactResolutionServiceManager.deregisterFactories();
252     AssertionConsumerServiceManager.deregisterFactories();
253     LogoutInitiatorManager.deregisterFactories();
254     ManageNameIDServiceManager.deregisterFactories();
255     SessionInitiatorManager.deregisterFactories();
256     SingleLogoutServiceManager.deregisterFactories();
257     HandlerManager.deregisterFactories();
258     ServiceProviderManager.deregisterFactories();
259     Attribute::deregisterFactories();
260
261 #ifndef SHIBSP_LITE
262     if (isEnabled(AttributeResolution)) {
263         MatchFunctorManager.deregisterFactories();
264         AttributeFilterManager.deregisterFactories();
265         AttributeDecoderManager.deregisterFactories();
266         AttributeExtractorManager.deregisterFactories();
267         AttributeResolverManager.deregisterFactories();
268     }
269 #endif
270
271     if (isEnabled(Listener))
272         ListenerServiceManager.deregisterFactories();
273
274     if (isEnabled(RequestMapping)) {
275         AccessControlManager.deregisterFactories();
276         RequestMapperManager.deregisterFactories();
277     }
278
279     if (isEnabled(Caching))
280         SessionCacheManager.deregisterFactories();
281
282 #ifndef SHIBSP_LITE
283     SAMLConfig::getConfig().term();
284 #else
285     XMLToolingConfig::getConfig().term();
286 #endif
287     log.info("%s library shutdown complete", PACKAGE_STRING);
288 }
289
290 bool SPConfig::instantiate(const char* config, bool rethrow)
291 {
292 #ifdef _DEBUG
293     NDC ndc("instantiate");
294 #endif
295     if (!config)
296         config = getenv("SHIBSP_CONFIG");
297     if (!config)
298         config = SHIBSP_CONFIG;
299     try {
300         xercesc::DOMDocument* dummydoc;
301         if (*config == '"' || *config == '\'') {
302             throw ConfigurationException("The value of SHIBSP_CONFIG started with a quote.");
303         }
304         else if (*config != '<') {
305
306             // Mock up some XML.
307             string resolved(config);
308             stringstream snippet;
309             snippet
310                 << "<Dummy path='"
311                 << XMLToolingConfig::getConfig().getPathResolver()->resolve(resolved, PathResolver::XMLTOOLING_CFG_FILE)
312                 << "' validate='1'/>";
313             dummydoc = XMLToolingConfig::getConfig().getParser().parse(snippet);
314             XercesJanitor<xercesc::DOMDocument> docjanitor(dummydoc);
315             setServiceProvider(ServiceProviderManager.newPlugin(XML_SERVICE_PROVIDER, dummydoc->getDocumentElement()));
316             if (m_configDoc)
317                 m_configDoc->release();
318             m_configDoc = docjanitor.release();
319         }
320         else {
321             stringstream snippet(config);
322             dummydoc = XMLToolingConfig::getConfig().getParser().parse(snippet);
323             XercesJanitor<xercesc::DOMDocument> docjanitor(dummydoc);
324             static const XMLCh _type[] = UNICODE_LITERAL_4(t,y,p,e);
325             auto_ptr_char type(dummydoc->getDocumentElement()->getAttributeNS(NULL,_type));
326             if (type.get() && *type.get())
327                 setServiceProvider(ServiceProviderManager.newPlugin(type.get(), dummydoc->getDocumentElement()));
328             else
329                 throw ConfigurationException("The supplied XML bootstrapping configuration did not include a type attribute.");
330             if (m_configDoc)
331                 m_configDoc->release();
332             m_configDoc = docjanitor.release();
333         }
334
335         getServiceProvider()->init();
336         return true;
337     }
338     catch (exception& ex) {
339         if (rethrow)
340             throw;
341         Category::getInstance(SHIBSP_LOGCAT".Config").fatal("caught exception while loading configuration: %s", ex.what());
342     }
343     return false;
344 }