1 // ANNA - Anna is Not Nothingness Anymore
3 // (c) Copyright 2005-2014 Eduardo Ramos Testillano & Francisco Ruiz Rayo
5 // http://redmine.teslayout.com/projects/anna-suite
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions
11 // * Redistributions of source code must retain the above copyright
12 // notice, this list of conditions and the following disclaimer.
13 // * Redistributions in binary form must reproduce the above
14 // copyright notice, this list of conditions and the following disclaimer
15 // in the documentation and/or other materials provided with the
17 // * Neither the name of the copyright holder nor the names of its
18 // contributors may be used to endorse or promote products derived from
19 // this software without specific prior written permission.
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 // Authors: eduardo.ramos.testillano@gmail.com
34 // cisco.tierra@gmail.com
43 #include <anna/core/tracing/Logger.hpp>
44 #include <anna/core/tracing/TraceMethod.hpp>
46 #include <anna/xml/Node.hpp>
48 #include <anna/ldap/internal/sccs.hpp>
49 #include <anna/ldap/Engine.hpp>
50 #include <anna/ldap/Session.hpp>
54 using namespace anna::ldap;
57 app::Component(getClassName()),
59 ldap::sccs::activate();
60 sigset(SIGALRM, alarmnCatcher);
63 Session* Engine::createSession(const char* url, const char* user, const char* password, const int category)
64 throw(RuntimeException) {
65 ldap::Session* result(NULL);
66 Guard guard(this, "ldap::Engine::createSession");
67 url = completeURL(url);
68 session_iterator ii = session_find(url, (user == NULL) ? "" : user);
70 if(ii == session_end()) {
71 if((result = allocateSession(category)) == NULL)
72 throw RuntimeException("ldap::Engine::allocateSession returns NULL", ANNA_FILE_LOCATION);
74 result->a_category = category;
76 result->a_externalID = -1;
78 if(user && *user != 0)
79 result->a_user = user;
81 result->a_user.clear();
83 if(password && *password != 0)
84 result->a_password = password;
86 result->a_password.clear();
88 session_key key(result->a_url, result->a_keymap = result->a_user);
89 a_sessions.insert(session_value_type(key, result));
91 string msg("ldap::Engine::createSession | ");
92 msg += result->asString();
93 msg += functions::asText(" | AutoBind: ", a_autoBind);
94 Logger::debug(msg, ANNA_FILE_LOCATION);
99 if(result->getState() == Session::State::Closed && a_autoBind == true)
105 Session* Engine::createSession(const char* url, const int id, const char* user, const char* password, const int category)
106 throw(RuntimeException) {
107 ldap::Session* result(NULL);
108 Guard guard(this, "ldap::Engine::createSession");
109 url = completeURL(url);
110 session_iterator ii = session_find(url, id);
112 if(ii == session_end()) {
113 if((result = allocateSession(category)) == NULL)
114 throw RuntimeException("ldap::Engine::allocateSession returns NULL", ANNA_FILE_LOCATION);
116 result->a_category = category;
118 result->a_externalID = id;
120 if(user && *user != 0)
121 result->a_user = user;
123 result->a_user.clear();
125 if(password && *password != 0)
126 result->a_password = password;
128 result->a_password.clear();
130 session_key key(result->a_url, result->a_keymap = anna::functions::asString(id));
131 a_sessions.insert(session_value_type(key, result));
133 string msg("ldap::Engine::createSession | ");
134 msg += result->asString();
135 msg += functions::asText(" | AutoBind: ", a_autoBind);
136 Logger::debug(msg, ANNA_FILE_LOCATION);
139 result = session(ii);
141 if((result->getUser() != user) || (result->getPassword() != password)) {
143 std::string msg = "Returned session already existed but with different credentiales regarding provided ones. Reuse could be inappropiate.";
144 Logger::warning(msg, ANNA_FILE_LOCATION);
149 if(result->getState() == Session::State::Closed && a_autoBind == true)
155 Session* Engine::findSession(const char* url, const char* user, Exception::Mode::_v emode)
156 throw(RuntimeException) {
157 Guard guard(this, "ldap::Engine::findSession");
158 url = completeURL(url);
159 session_iterator ii = session_find(url, user);
161 if(ii != session_end())
164 if(emode != Exception::Mode::Ignore) {
165 string msg("ldap::Engine::findSession | URL: ");
169 msg += " | Session not found";
170 RuntimeException ex(msg, ANNA_FILE_LOCATION);
172 if(emode == Exception::Mode::Throw)
181 Session* Engine::findSession(const char* url, const int id, Exception::Mode::_v emode)
182 throw(RuntimeException) {
183 Guard guard(this, "ldap::Engine::findSession (int)");
184 session_iterator ii = session_find(url, id);
186 if(ii != session_end())
189 if(emode != Exception::Mode::Ignore) {
190 string msg("ldap::Engine::findSession | URL: ");
192 msg += functions::asText(" | ID: ", id);
193 msg += " | Session not found";
194 RuntimeException ex(msg, ANNA_FILE_LOCATION);
196 if(emode == Exception::Mode::Throw)
205 void Engine::closeSession(Session* session)
206 throw(RuntimeException) {
211 string msg("ldap::Engine::closeSession | ");
212 msg += session->asString();
213 Logger::debug(msg, ANNA_FILE_LOCATION);
215 Guard guard(this, "ldap::Engine::closeSession");
216 session_iterator ii = session_find(session->a_url, session->a_keymap);
218 if(ii == session_end())
223 releaseSession(session);
224 } catch(RuntimeException& ex) {
228 a_sessions.erase(ii);
231 void Engine::do_stop()
233 LOGMETHOD(TraceMethod tttm("anna::ldap::Engine", "do_stop", ANNA_FILE_LOCATION));
235 for(session_iterator ii = session_begin(), maxii = session_end(); ii != maxii; ii ++)
236 session(ii)->unbind();
239 xml::Node* Engine::asXML(xml::Node* parent) const
241 parent = app::Component::asXML(parent);
242 xml::Node* result = parent->createChild("ldap.Engine");
243 const Session* session;
244 result->createAttribute("AutoBind", functions::asString(a_autoBind));
246 for(const_session_iterator ii = session_begin(), maxii = session_end(); ii != maxii; ii ++) {
247 Guard guard(session = Engine::session(ii));
248 session->asXML(result);
254 Engine::session_iterator Engine::session_find(const char* url, const int id)
256 return a_sessions.find(session_key(url, anna::functions::asString(id)));
260 int Engine::setDebugLevel(const int level)
261 throw(RuntimeException) {
263 #ifdef LDAP_OPT_DEBUG_LEVEL
264 int _level = htonl(level);
266 if(ldap_get_option(NULL, LDAP_OPT_DEBUG_LEVEL, &result) != LDAP_OPT_SUCCESS)
267 throw RuntimeException("Can not get LDAP_OPT_DEBUG_LEVEL", ANNA_FILE_LOCATION);
269 if(ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, &_level) != LDAP_OPT_SUCCESS)
270 throw RuntimeException("Can not set LDAP_OPT_DEBUG_LEVEL", ANNA_FILE_LOCATION);
272 ber_set_option(NULL, LBER_OPT_DEBUG_LEVEL, &_level);
274 Logger::error("Can not set debug level", ANNA_FILE_LOCATION);
279 const char* Engine::completeURL(const char* url)
281 static const char* protocol = "ldap://";
282 static const int protocolLen = anna_strlen(protocol);
284 if(anna_strstr(url, "://") == 0) {
287 return a_auxURL.c_str();
294 void Engine::alarmnCatcher(int)