Removed memory listener (for now), added deferred initialization of config.
[shibboleth/cpp-sp.git] / shib-target / shib-config.cpp
1 /*
2  *  Copyright 2001-2005 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  * shib-config.cpp -- ShibTarget initialization and finalization routines
19  *
20  * Created By:  Derek Atkins <derek@ihtfp.com>
21  *
22  * $Id$
23  */
24
25 #include "internal.h"
26
27 #include <log4cpp/OstreamAppender.hh>
28
29 using namespace std;
30 using namespace log4cpp;
31 using namespace saml;
32 using namespace shibboleth;
33 using namespace shibtarget;
34
35 namespace {
36     STConfig g_Config;
37 }
38
39 // Factories for built-in plugins we can manufacture. Actual definitions
40 // will be with the actual object implementation.
41 #ifndef WIN32
42 PlugManager::Factory UnixListenerFactory;
43 #endif
44 PlugManager::Factory TCPListenerFactory;
45 //PlugManager::Factory MemoryListenerFactory;
46 PlugManager::Factory MemoryCacheFactory;
47 PlugManager::Factory XMLRequestMapFactory;
48 PlugManager::Factory ShibSessionInitiatorFactory;
49 PlugManager::Factory SAML1POSTFactory;
50 PlugManager::Factory SAML1ArtifactFactory;
51 PlugManager::Factory ShibLogoutFactory;
52 //PlugManager::Factory htaccessFactory;
53
54 SAML_EXCEPTION_FACTORY(ListenerException);
55 SAML_EXCEPTION_FACTORY(ConfigurationException);
56
57 ShibTargetConfig& ShibTargetConfig::getConfig()
58 {
59     return g_Config;
60 }
61
62 bool STConfig::init(const char* schemadir)
63 {
64     // With new build of log4cpp, we need to establish a "default"
65     // logging appender to stderr up front.
66     const char* loglevel=getenv("SHIB_LOGGING");
67     if (!loglevel)
68         loglevel = SHIB_LOGGING;    
69     Category& root = Category::getRoot();
70     if (!strcmp(loglevel,"DEBUG"))
71         root.setPriority(Priority::DEBUG);
72     else if (!strcmp(loglevel,"INFO"))
73         root.setPriority(Priority::INFO);
74     else if (!strcmp(loglevel,"NOTICE"))
75         root.setPriority(Priority::NOTICE);
76     else if (!strcmp(loglevel,"WARN"))
77         root.setPriority(Priority::WARN);
78     else if (!strcmp(loglevel,"ERROR"))
79         root.setPriority(Priority::ERROR);
80     else if (!strcmp(loglevel,"CRIT"))
81         root.setPriority(Priority::CRIT);
82     else if (!strcmp(loglevel,"ALERT"))
83         root.setPriority(Priority::ALERT);
84     else if (!strcmp(loglevel,"EMERG"))
85         root.setPriority(Priority::EMERG);
86     else if (!strcmp(loglevel,"FATAL"))
87         root.setPriority(Priority::FATAL);
88     root.setAppender(new OstreamAppender("default",&cerr));
89  
90 #ifdef _DEBUG
91     saml::NDC ndc("init");
92 #endif
93     Category& log = Category::getInstance("shibtarget.Config");
94
95     if (!schemadir) {
96         log.fatal("XML schema directory not supplied");
97         return false;
98     }
99
100     // This will cause some extra console logging, but for now,
101     // initialize the underlying libraries.
102     SAMLConfig& samlConf=SAMLConfig::getConfig();
103     if (schemadir)
104         samlConf.schema_dir = schemadir;
105     try {
106         if (!samlConf.init()) {
107             log.fatal("Failed to initialize SAML Library");
108             return false;
109         }
110     }
111     catch (...) {
112         log.fatal("Died initializing SAML Library");
113         return false;
114     }
115     
116     ShibConfig& shibConf=ShibConfig::getConfig();
117     try { 
118         if (!shibConf.init()) {
119             log.fatal("Failed to initialize Shib library");
120             samlConf.term();
121             return false;
122         }
123     }
124     catch (...) {
125         log.fatal("Died initializing Shib library.");
126         samlConf.term();
127         return false;
128     }
129
130     // Register built-in plugin types.
131     REGISTER_EXCEPTION_FACTORY(ListenerException);
132     REGISTER_EXCEPTION_FACTORY(ConfigurationException);
133 #ifndef WIN32
134     samlConf.getPlugMgr().regFactory(shibtarget::XML::UnixListenerType,&UnixListenerFactory);
135 #endif
136     samlConf.getPlugMgr().regFactory(shibtarget::XML::TCPListenerType,&TCPListenerFactory);
137     //samlConf.getPlugMgr().regFactory(shibtarget::XML::MemoryListenerType,&MemoryListenerFactory);
138     samlConf.getPlugMgr().regFactory(shibtarget::XML::MemorySessionCacheType,&MemoryCacheFactory);
139     samlConf.getPlugMgr().regFactory(shibtarget::XML::LegacyRequestMapType,&XMLRequestMapFactory);
140     samlConf.getPlugMgr().regFactory(shibtarget::XML::XMLRequestMapType,&XMLRequestMapFactory);
141     samlConf.getPlugMgr().regFactory(shibtarget::XML::NativeRequestMapType,&XMLRequestMapFactory);
142     
143     auto_ptr_char temp1(Constants::SHIB_SESSIONINIT_PROFILE_URI);
144     samlConf.getPlugMgr().regFactory(temp1.get(),&ShibSessionInitiatorFactory);
145     auto_ptr_char temp2(SAMLBrowserProfile::BROWSER_POST);
146     samlConf.getPlugMgr().regFactory(temp2.get(),&SAML1POSTFactory);
147     auto_ptr_char temp3(SAMLBrowserProfile::BROWSER_ARTIFACT);
148     samlConf.getPlugMgr().regFactory(temp3.get(),&SAML1ArtifactFactory);
149     auto_ptr_char temp4(Constants::SHIB_LOGOUT_PROFILE_URI);
150     samlConf.getPlugMgr().regFactory(temp4.get(),&ShibLogoutFactory);
151     
152     saml::XML::registerSchema(shibtarget::XML::SHIBTARGET_NS,shibtarget::XML::SHIBTARGET_SCHEMA_ID,NULL,false);
153     saml::XML::registerSchema(shibtarget::XML::SAML2META_NS,shibtarget::XML::SAML2META_SCHEMA_ID,NULL,false);
154     saml::XML::registerSchema(shibtarget::XML::SAML2ASSERT_NS,shibtarget::XML::SAML2ASSERT_SCHEMA_ID,NULL,false);
155     saml::XML::registerSchema(shibtarget::XML::XMLENC_NS,shibtarget::XML::XMLENC_SCHEMA_ID,NULL,false);
156     
157     log.info("finished initializing");
158     return true;
159 }
160
161 bool STConfig::load(const char* config)
162 {
163 #ifdef _DEBUG
164     saml::NDC ndc("load");
165 #endif
166     Category& log = Category::getInstance("shibtarget.Config");
167
168     if (!config) {
169         log.fatal("path to configuration file not supplied");
170         shutdown();
171         return false;
172     }
173
174     try {
175         log.info("loading configuration file: %s", config);
176         static const XMLCh uri[] = { chLatin_u, chLatin_r, chLatin_i, chNull };
177         DOMImplementation* impl=DOMImplementationRegistry::getDOMImplementation(NULL);
178         DOMDocument* dummydoc=impl->createDocument();
179         DOMElement* dummy = dummydoc->createElementNS(NULL,XML::Literals::ShibbolethTargetConfig);
180         auto_ptr_XMLCh src(config);
181         dummy->setAttributeNS(NULL,uri,src.get());
182         m_ini=ShibTargetConfigFactory(dummy);
183         dummydoc->release();
184         m_ini->init();
185         
186         pair<bool,unsigned int> skew=m_ini->getUnsignedInt("clockSkew");
187         SAMLConfig::getConfig().clock_skew_secs=skew.first ? skew.second : 180;
188         
189         m_tranLog=new FixedContextCategory(SHIBTRAN_LOGCAT);
190         m_tranLog->info("opened transaction log");
191         m_tranLogLock = Mutex::create();
192     }
193     catch (SAMLException& ex) {
194         log.fatal("caught exception while loading/initializing configuration: %s",ex.what());
195         shutdown();
196         return false;
197     }
198 #ifndef _DEBUG
199     catch (...) {
200         log.fatal("caught exception while loading/initializing configuration");
201         shutdown();
202         return false;
203     }
204 #endif
205
206     log.info("finished loading configuration");
207     return true;
208 }
209
210 void STConfig::shutdown()
211 {
212 #ifdef _DEBUG
213     saml::NDC ndc("shutdown");
214 #endif
215     Category& log = Category::getInstance("shibtarget.Config");
216     log.info("shutting down the library");
217     delete m_tranLogLock;
218     m_tranLogLock = NULL;
219     //delete m_tranLog; // This is crashing for some reason, but we're shutting down anyway.
220     delete m_ini;
221     m_ini = NULL;
222     ShibConfig::getConfig().term();
223     SAMLConfig::getConfig().term();
224     log.info("library shutdown complete");
225 }