2 * Copyright 2001-2005 Internet2
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 /* ShibConfig.cpp - Shibboleth runtime configuration
26 #include <sys/types.h>
29 #define SHIB_INSTANTIATE
33 #include <openssl/err.h>
36 using namespace shibboleth;
37 using namespace xmltooling;
38 using namespace log4cpp;
42 SAML_EXCEPTION_FACTORY(ResourceAccessException);
43 SAML_EXCEPTION_FACTORY(MetadataException);
44 SAML_EXCEPTION_FACTORY(CredentialException);
45 SAML_EXCEPTION_FACTORY(InvalidHandleException);
46 SAML_EXCEPTION_FACTORY(InvalidSessionException);
48 PlugManager::Factory BasicTrustFactory;
49 PlugManager::Factory ShibbolethTrustFactory;
53 vector<Mutex*> g_openssl_locks;
55 map<xstring,const IAttributeFactory*> attrMap;
57 map<XMLCh*,const IAttributeFactory*> attrMap;
61 extern "C" SAMLAttribute* ShibAttributeFactory(DOMElement* e)
63 // First check for an explicit factory.
65 map<xstring,const IAttributeFactory*>::const_iterator i=attrMap.find(e->getAttributeNS(NULL,L(AttributeName)));
67 const XMLCh* aname=e->getAttributeNS(NULL,L(AttributeName));
68 map<XMLCh*,const IAttributeFactory*>::const_iterator i;
69 for (i=attrMap.begin(); i!=attrMap.end(); i++)
70 if (!XMLString::compareString(aname,i->first))
74 return i->second->build(e);
76 // Now check for a Scope attribute to ensure proper value handling whenever possible.
77 DOMElement* n=saml::XML::getFirstChildElement(e,saml::XML::SAML_NS,L(AttributeValue));
78 if (n && n->hasAttributeNS(NULL,ScopedAttribute::Scope))
79 return new ScopedAttribute(e);
81 // Just use the default class.
82 return new SAMLAttribute(e);
85 void ShibConfig::regAttributeMapping(const XMLCh* name, const IAttributeFactory* factory)
87 if (name && factory) {
89 attrMap[name]=factory;
91 attrMap.insert(make_pair(XMLString::replicate(name),factory));
96 void ShibConfig::unregAttributeMapping(const XMLCh* name)
102 for (map<XMLCh*,const IAttributeFactory*>::iterator i=attrMap.begin(); i!=attrMap.end(); i++) {
103 if (!XMLString::compareString(name,i->first)) {
104 XMLCh* temp=i->first;
105 XMLString::release(&temp);
114 void ShibConfig::clearAttributeMappings()
116 #ifndef HAVE_GOOD_STL
117 for (map<XMLCh*,const IAttributeFactory*>::iterator i=attrMap.begin(); i!=attrMap.end(); i++) {
118 XMLCh* temp=i->first;
119 XMLString::release(&temp);
125 extern "C" void openssl_locking_callback(int mode,int n,const char *file,int line)
127 if (mode & CRYPTO_LOCK)
128 g_openssl_locks[n]->lock();
130 g_openssl_locks[n]->unlock();
134 extern "C" unsigned long openssl_thread_id(void)
136 return (unsigned long)(pthread_self());
140 bool ShibConfig::init()
142 REGISTER_EXCEPTION_FACTORY(ResourceAccessException);
143 REGISTER_EXCEPTION_FACTORY(MetadataException);
144 REGISTER_EXCEPTION_FACTORY(CredentialException);
145 REGISTER_EXCEPTION_FACTORY(InvalidHandleException);
146 REGISTER_EXCEPTION_FACTORY(InvalidSessionException);
148 // Register plugin factories (some are legacy aliases)
149 SAMLConfig& conf=SAMLConfig::getConfig();
150 conf.getPlugMgr().regFactory("edu.internet2.middleware.shibboleth.common.provider.BasicTrust",&BasicTrustFactory);
151 conf.getPlugMgr().regFactory("edu.internet2.middleware.shibboleth.common.provider.ShibbolethTrust",&ShibbolethTrustFactory);
153 // Set up OpenSSL locking.
154 for (int i=0; i<CRYPTO_num_locks(); i++)
155 g_openssl_locks.push_back(Mutex::create());
156 CRYPTO_set_locking_callback(openssl_locking_callback);
158 CRYPTO_set_id_callback(openssl_thread_id);
161 SAMLAttribute::setFactory(&ShibAttributeFactory);
165 void ShibConfig::term()
167 SAMLAttribute::setFactory(NULL);
168 clearAttributeMappings();
170 CRYPTO_set_locking_callback(NULL);
171 for (vector<Mutex*>::iterator j=g_openssl_locks.begin(); j!=g_openssl_locks.end(); j++)
173 g_openssl_locks.clear();
175 // Unregister plugin factories
176 SAMLConfig& conf=SAMLConfig::getConfig();
177 conf.getPlugMgr().unregFactory("edu.internet2.middleware.shibboleth.common.provider.BasicTrust");
178 conf.getPlugMgr().unregFactory("edu.internet2.middleware.shibboleth.common.provider.ShibbolethTrust");
181 ShibConfig& ShibConfig::getConfig()
186 void shibboleth::annotateException(SAMLException* e, const IEntityDescriptor* entity, bool rethrow)
189 auto_ptr_char id(entity->getId());
190 e->addProperty("providerId",id.get());
191 Iterator<const IRoleDescriptor*> roles=entity->getRoleDescriptors();
192 while (roles.hasNext()) {
193 const IRoleDescriptor* role=roles.next();
194 if (role->isValid()) {
195 const char* temp=role->getErrorURL();
197 e->addProperty("errorURL",temp);
203 Iterator<const IContactPerson*> i=entity->getContactPersons();
204 while (i.hasNext()) {
205 const IContactPerson* c=i.next();
206 if ((c->getType()==IContactPerson::technical || c->getType()==IContactPerson::support)) {
207 const char* fname=c->getGivenName();
208 const char* lname=c->getSurName();
209 if (fname && lname) {
210 string contact=string(fname) + ' ' + lname;
211 e->addProperty("contactName",contact.c_str());
214 e->addProperty("contactName",fname);
216 e->addProperty("contactName",lname);
217 Iterator<string> emails=c->getEmailAddresses();
218 if (emails.hasNext())
219 e->addProperty("contactEmail",emails.next().c_str());
229 void shibboleth::annotateException(saml::SAMLException* e, const IRoleDescriptor* role, bool rethrow)
232 auto_ptr_char id(role->getEntityDescriptor()->getId());
233 e->addProperty("providerId",id.get());
234 const char* temp=role->getErrorURL();
235 if (role->getErrorURL())
236 e->addProperty("errorURL",role->getErrorURL());
238 Iterator<const IContactPerson*> i=role->getContactPersons();
239 while (i.hasNext()) {
240 const IContactPerson* c=i.next();
241 if ((c->getType()==IContactPerson::technical || c->getType()==IContactPerson::support)) {
242 const char* fname=c->getGivenName();
243 const char* lname=c->getSurName();
244 if (fname && lname) {
245 string contact=string(fname) + ' ' + lname;
246 e->addProperty("contactName",contact.c_str());
249 e->addProperty("contactName",fname);
251 e->addProperty("contactName",lname);
252 Iterator<string> emails=c->getEmailAddresses();
253 if (emails.hasNext())
254 e->addProperty("contactEmail",emails.next().c_str());