7feb755a34551099b56f3630a207f1db879b3558
[shibboleth/sp.git] / shib / ShibConfig.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 /* ShibConfig.cpp - Shibboleth runtime configuration
18
19    Scott Cantor
20    6/4/02
21
22    $History:$
23 */
24
25 #define SHIB_INSTANTIATE
26 #include "internal.h"
27
28 #include <ctime>
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <openssl/err.h>
32 #include <xmltooling/util/Threads.h>
33
34 using namespace saml;
35 using namespace shibboleth;
36 using namespace xmltooling;
37 using namespace log4cpp;
38 using namespace std;
39
40
41 namespace {
42     ShibConfig g_config;
43     vector<Mutex*> g_openssl_locks;
44 #ifdef HAVE_GOOD_STL
45     map<xmltooling::xstring,const IAttributeFactory*> attrMap;
46 #else
47     map<XMLCh*,const IAttributeFactory*> attrMap;
48 #endif
49 }
50
51 extern "C" SAMLAttribute* ShibAttributeFactory(DOMElement* e)
52 {
53     // First check for an explicit factory.
54 #ifdef HAVE_GOOD_STL
55     map<xmltooling::xstring,const IAttributeFactory*>::const_iterator i=attrMap.find(e->getAttributeNS(NULL,L(AttributeName)));
56 #else
57     const XMLCh* aname=e->getAttributeNS(NULL,L(AttributeName));
58     map<XMLCh*,const IAttributeFactory*>::const_iterator i;
59     for (i=attrMap.begin(); i!=attrMap.end(); i++)
60         if (!XMLString::compareString(aname,i->first))
61             break;
62 #endif
63     if (i!=attrMap.end())
64         return i->second->build(e);
65
66     // Now check for a Scope attribute to ensure proper value handling whenever possible.
67     DOMElement* n=saml::XML::getFirstChildElement(e,saml::XML::SAML_NS,L(AttributeValue));
68     if (n && n->hasAttributeNS(NULL,ScopedAttribute::Scope))
69         return new ScopedAttribute(e);
70         
71     // Just use the default class.
72     return new SAMLAttribute(e);
73 }
74
75 void ShibConfig::regAttributeMapping(const XMLCh* name, const IAttributeFactory* factory)
76 {
77     if (name && factory) {
78 #ifdef HAVE_GOOD_STL
79         attrMap[name]=factory;
80 #else
81         attrMap.insert(make_pair(XMLString::replicate(name),factory));
82 #endif
83     }
84 }
85
86 void ShibConfig::unregAttributeMapping(const XMLCh* name)
87 {
88     if (name) {
89 #ifdef HAVE_GOOD_STL
90         attrMap.erase(name);
91 #else
92         for (map<XMLCh*,const IAttributeFactory*>::iterator i=attrMap.begin(); i!=attrMap.end(); i++) {
93             if (!XMLString::compareString(name,i->first)) {
94                 XMLCh* temp=i->first;
95                 XMLString::release(&temp);
96                 attrMap.erase(i);
97                 break;
98             }
99         }
100 #endif
101     }
102 }
103
104 void ShibConfig::clearAttributeMappings()
105 {
106 #ifndef HAVE_GOOD_STL
107     for (map<XMLCh*,const IAttributeFactory*>::iterator i=attrMap.begin(); i!=attrMap.end(); i++) {
108         XMLCh* temp=i->first;
109         XMLString::release(&temp);
110     }
111 #endif
112     attrMap.clear();
113 }
114
115 extern "C" void openssl_locking_callback(int mode,int n,const char *file,int line)
116 {
117     if (mode & CRYPTO_LOCK)
118         g_openssl_locks[n]->lock();
119     else
120         g_openssl_locks[n]->unlock();
121 }
122
123 #ifndef WIN32
124 extern "C" unsigned long openssl_thread_id(void)
125 {
126     return (unsigned long)(pthread_self());
127 }
128 #endif
129
130 bool ShibConfig::init()
131 {
132     // Set up OpenSSL locking.
133         for (int i=0; i<CRYPTO_num_locks(); i++)
134         g_openssl_locks.push_back(Mutex::create());
135         CRYPTO_set_locking_callback(openssl_locking_callback);
136 #ifndef WIN32
137     CRYPTO_set_id_callback(openssl_thread_id);
138 #endif
139
140     SAMLAttribute::setFactory(&ShibAttributeFactory);
141     return true;
142 }
143
144 void ShibConfig::term()
145 {
146     SAMLAttribute::setFactory(NULL);
147     clearAttributeMappings();
148    
149     CRYPTO_set_locking_callback(NULL);
150     for (vector<Mutex*>::iterator j=g_openssl_locks.begin(); j!=g_openssl_locks.end(); j++)
151         delete (*j);
152     g_openssl_locks.clear();
153 }
154
155 ShibConfig& ShibConfig::getConfig()
156 {
157     return g_config;
158 }