diff options
author | Robin Burchell <robin+git@viroteck.net> | 2012-11-29 00:14:40 +0100 |
---|---|---|
committer | Robin Burchell <robin+git@viroteck.net> | 2012-11-29 10:07:05 +0100 |
commit | 50ea2230637ddc31673cb19d41e6a6dde12487db (patch) | |
tree | 22272c2072a0f0a5c69fe77a9716c4d9d11bee63 /src/modules | |
parent | 1813369adecc1efc9812e90c40c21dc32e4965c9 (diff) |
ldapauth: RAII returned ldap message.
This ensures it is always freed, and coincidentally fixes freeing in the case of
LDAP errors.
Diffstat (limited to 'src/modules')
-rw-r--r-- | src/modules/extra/m_ldapauth.cpp | 51 |
1 files changed, 41 insertions, 10 deletions
diff --git a/src/modules/extra/m_ldapauth.cpp b/src/modules/extra/m_ldapauth.cpp index e2205ca8d..c5de59743 100644 --- a/src/modules/extra/m_ldapauth.cpp +++ b/src/modules/extra/m_ldapauth.cpp @@ -38,16 +38,16 @@ /* $ModDesc: Allow/Deny connections based upon answer from LDAP server */ /* $LinkerFlags: -lldap */ -struct LDAPString +struct RAIILDAPString { char *str; - LDAPString(char *Str) + RAIILDAPString(char *Str) : str(Str) { } - ~LDAPString() + ~RAIILDAPString() { ldap_memfree(str); } @@ -63,6 +63,35 @@ struct LDAPString } }; +struct RAIILDAPMessage +{ + RAIILDAPMessage() + { + } + + ~RAIILDAPMessage() + { + dealloc(); + } + + void dealloc() + { + ldap_msgfree(msg); + } + + operator LDAPMessage*() + { + return msg; + } + + LDAPMessage **operator &() + { + return &msg; + } + + LDAPMessage *msg; +}; + class ModuleLDAPAuth : public Module { LocalIntExt ldapAuthed; @@ -278,7 +307,7 @@ public: } } - LDAPMessage *msg, *entry; + RAIILDAPMessage msg; std::string what = (attribute + "=" + (useusername ? user->ident : user->nick)); if ((res = ldap_search_ext_s(conn, base.c_str(), searchscope, what.c_str(), NULL, 0, NULL, NULL, NULL, 0, &msg)) != LDAP_SUCCESS) { @@ -287,6 +316,11 @@ public: size_t pos = user->password.find(":"); if (pos != std::string::npos) { + // manpage says we must deallocate regardless of success or failure + // since we're about to do another query (and reset msg), first + // free the old one. + msg.dealloc(); + std::string cutpassword = user->password.substr(0, pos); res = ldap_search_ext_s(conn, base.c_str(), searchscope, cutpassword.c_str(), NULL, 0, NULL, NULL, NULL, 0, &msg); @@ -309,24 +343,23 @@ public: { if (verbose) ServerInstance->SNO->WriteToSnoMask('c', "Forbidden connection from %s (LDAP search returned more than one result: %s)", user->GetFullRealHost().c_str(), ldap_err2string(res)); - ldap_msgfree(msg); return false; } + + LDAPMessage *entry; if ((entry = ldap_first_entry(conn, msg)) == NULL) { if (verbose) ServerInstance->SNO->WriteToSnoMask('c', "Forbidden connection from %s (LDAP search returned no results: %s)", user->GetFullRealHost().c_str(), ldap_err2string(res)); - ldap_msgfree(msg); return false; } cred.bv_val = (char*)user->password.data(); cred.bv_len = user->password.length(); - LDAPString DN(ldap_get_dn(conn, entry)); + RAIILDAPString DN(ldap_get_dn(conn, entry)); if ((res = ldap_sasl_bind_s(conn, DN, LDAP_SASL_SIMPLE, &cred, NULL, NULL, NULL)) != LDAP_SUCCESS) { if (verbose) ServerInstance->SNO->WriteToSnoMask('c', "Forbidden connection from %s (%s)", user->GetFullRealHost().c_str(), ldap_err2string(res)); - ldap_msgfree(msg); return false; } @@ -355,7 +388,6 @@ public: { if (verbose) ServerInstance->SNO->WriteToSnoMask('c', "Forbidden connection from %s (Lacks required LDAP attributes)", user->GetFullRealHost().c_str()); - ldap_msgfree(msg); return false; } } @@ -383,7 +415,6 @@ public: ldapVhost.set(user, SafeReplace(vhost, dnParts)); } - ldap_msgfree(msg); ldapAuthed.set(user,1); return true; } |