It helps to actually RETURN the object....
[shibboleth/sp.git] / shib-target / shib-config.cpp
1 /*
2  * shib-config.cpp -- ShibTarget initialization and finalization routines
3  *
4  * Created By:  Derek Atkins <derek@ihtfp.com>
5  *
6  * $Id$
7  */
8
9 #include "shib-target.h"
10
11 #include <log4cpp/PropertyConfigurator.hh>
12 #include <log4cpp/Category.hh>
13
14 using namespace saml;
15 using namespace shibboleth;
16 using namespace shibtarget;
17 using namespace std;
18
19 #ifndef SHIBTARGET_INIFILE
20 #define SHIBTARGET_INIFILE "/etc/shibboleth.ini"
21 #endif
22
23 class STConfig : public ShibTargetConfig
24 {
25 public:
26   STConfig(const char* app_name, const char* inifile);
27   ~STConfig();
28   void shutdown();
29   ShibINI& getINI() { return *ini; }
30
31   void ref();
32 private:
33   SAMLConfig& samlConf;
34   ShibConfig& shibConf;
35   ShibINI* ini;
36   int refcount;
37 };
38
39 namespace {
40   STConfig * g_Config = NULL;
41 }
42
43 CCache* shibtarget::g_shibTargetCCache = NULL;
44
45 /****************************************************************************/
46 // External Interface
47
48
49 ShibTargetConfig& ShibTargetConfig::init(const char* app_name, const char* inifile)
50 {
51   if (!app_name)
52     throw runtime_error ("No Application name");
53
54   if (g_Config) {
55     g_Config->ref();
56     return *g_Config;
57   }
58
59   g_Config = new STConfig(app_name, inifile);
60   return *g_Config;
61 }
62
63
64
65 /****************************************************************************/
66 // Mapper
67
68 class DummyMapper : public IOriginSiteMapper
69 {
70 public:
71     DummyMapper();
72     ~DummyMapper();
73     virtual Iterator<xstring> getHandleServiceNames(const XMLCh* originSite) { return Iterator<xstring>(m_hsnames); }
74     virtual Key* getHandleServiceKey(const XMLCh* handleService) { return NULL; }
75     virtual Iterator<xstring> getSecurityDomains(const XMLCh* originSite);
76     virtual Iterator<X509Certificate*> getTrustedRoots() { return Iterator<X509Certificate*>(); }
77
78 private:
79     typedef map<xstring,vector<xstring>*> domains_t;
80     domains_t m_domains;
81     vector<xstring> m_hsnames;
82 };
83
84 DummyMapper::DummyMapper()
85 {
86     auto_ptr<XMLCh> buf(XMLString::transcode("wayf.internet2.edu"));
87     m_hsnames.push_back(buf.get());
88 }
89
90 Iterator<xstring> DummyMapper::getSecurityDomains(const XMLCh* originSite)
91 {
92     domains_t::iterator i=m_domains.find(originSite);
93     if (i==m_domains.end())
94     {
95         vector<xstring>* pv=new vector<xstring>();
96         pv->push_back(originSite);
97         pair<domains_t::iterator,bool> p=m_domains.insert(domains_t::value_type(originSite,pv));
98         i=p.first;
99     }
100     return Iterator<xstring>(*(i->second));
101 }
102
103 DummyMapper::~DummyMapper()
104 {
105     for (domains_t::iterator i=m_domains.begin(); i!=m_domains.end(); i++)
106         delete i->second;
107 }
108
109
110
111
112 /****************************************************************************/
113 // STConfig
114
115 STConfig::STConfig(const char* app_name, const char* inifile)
116   :  samlConf(SAMLConfig::getConfig()), shibConf(ShibConfig::getConfig())
117 {
118   ini = new ShibINI((inifile ? inifile : SHIBTARGET_INIFILE));
119
120   string app = app_name;
121   string tag;
122
123   // Initialize Log4cpp
124   if (ini->get_tag (app, SHIBTARGET_TAG_LOGGER, true, &tag)) {
125     cerr << "Trying to load logger configuration: " << tag << "\n";
126     try {
127       log4cpp::PropertyConfigurator::configure(tag);
128     } catch (log4cpp::ConfigureFailure& e) {
129       cerr << "Error reading configuration: " << e.what() << "\n";
130     }
131   } else {
132     log4cpp::Category& category = log4cpp::Category::getRoot();
133     category.setPriority(log4cpp::Priority::DEBUG);
134     cerr << "No logger configuration found\n";
135   }
136
137   log4cpp::Category& log = log4cpp::Category::getInstance("shibtarget.STConfig");
138
139   // Init SAML
140   if (ini->get_tag (app, SHIBTARGET_TAG_SCHEMAS, true, &tag))
141     samlConf.schema_dir = tag;
142   if (ini->get_tag (app, SHIBTARGET_TAG_CERTFILE, true, &tag))
143     samlConf.ssl_certfile = tag;
144   if (ini->get_tag (app, SHIBTARGET_TAG_KEYFILE, true, &tag))
145     samlConf.ssl_keyfile = tag;
146   if (ini->get_tag (app, SHIBTARGET_TAG_KEYPASS, true, &tag))
147     samlConf.ssl_keypass = tag;
148   if (ini->get_tag (app, SHIBTARGET_TAG_CALIST, true, &tag))
149     samlConf.ssl_calist = tag;
150
151   if (!samlConf.init()) {
152     log.error ("Failed to initialize SAML Library");
153     throw runtime_error ("Failed to initialize SAML Library");
154   } else
155     log.debug ("SAML Initialized");
156
157   // Init Shib
158   if (! ini->get_tag (app, SHIBTARGET_TAG_SITES, true, &tag)) {
159     log.crit("No Sites File found in configuration");
160     throw runtime_error ("No Sites File found in configuration");
161   }
162
163   shibConf.origin_mapper = new XMLOriginSiteMapper(tag.c_str(),
164                                                    Iterator<X509Certificate*>());
165   
166   if (!shibConf.init()) {
167     log.error ("Failed to initialize Shib library");
168     throw runtime_error ("Failed to initialize Shib Library");
169   } else
170     log.debug ("Shib Initialized");
171
172   // Initialize the SHAR Cache
173   if (!strcmp (app_name, SHIBTARGET_SHAR))
174     g_shibTargetCCache = CCache::getInstance();  
175
176   // Load any extensions
177   string ext = "extensions";
178   if (ini->exists(ext)) {
179     saml::NDC ndc("load extensions");
180     ShibINI::Iterator* iter = ini->tag_iterator(ext);
181
182     for (const string* str = iter->begin(); str; str = iter->next()) {
183       string file = ini->get(ext, *str);
184       try
185       {
186         samlConf.saml_register_extension(file.c_str());
187         log.debug("%s: loading %s", str->c_str(), file.c_str());
188       }
189       catch (SAMLException& e)
190       {
191         log.error("%s: %s", str->c_str(), e.what());
192       }
193     }
194     delete iter;
195   }
196
197   ref();
198   log.debug("finished");
199 }
200
201 STConfig::~STConfig()
202 {
203   if (ini) delete ini;
204   
205   if (g_shibTargetCCache)
206     delete g_shibTargetCCache;
207
208   delete shibConf.origin_mapper;
209   shibConf.term();
210   samlConf.term();
211 }
212
213 void STConfig::ref()
214 {
215   refcount++;
216 }
217
218 void STConfig::shutdown()
219 {
220   refcount--;
221   if (!refcount) {
222     delete g_Config;
223     g_Config = NULL;
224   }
225 }