From 2a4940f23e1c31a68f46eb921b03b3d508f24d61 Mon Sep 17 00:00:00 2001 From: Kyle Fuller Date: Fri, 30 Mar 2012 21:52:35 +0100 Subject: [PATCH] saslauth: Cleanup module, don't refuse logins if we can't provide them --- modules/saslauth.cpp | 100 ++++++++++++++++++++++++------------------- 1 file changed, 56 insertions(+), 44 deletions(-) diff --git a/modules/saslauth.cpp b/modules/saslauth.cpp index 32b30a1c..5815e70d 100644 --- a/modules/saslauth.cpp +++ b/modules/saslauth.cpp @@ -20,29 +20,28 @@ public: MODCONSTRUCTOR(CSASLAuthMod) { m_Cache.SetTTL(60000/*ms*/); } - virtual ~CSASLAuthMod() {} - virtual bool OnBoot() { - return true; + virtual ~CSASLAuthMod() { + sasl_done(); } virtual bool OnLoad(const CString& sArgs, CString& sMessage) { - VCString vsChans; + VCString vsArgs; VCString::const_iterator it; - sArgs.Split(" ", vsChans, false); + sArgs.Split(" ", vsArgs, false); - for (it = vsChans.begin(); it != vsChans.end(); ++it) { - if (it->StrCmp("saslauthd") || it->StrCmp("auxprop")) { - method += *it + " "; - } - else { + for (it = vsArgs.begin(); it != vsArgs.end(); ++it) { + if (it->Equals("saslauthd") || it->Equals("auxprop")) { + m_sMethod += *it + " "; + } else { CUtils::PrintError("Ignoring invalid SASL pwcheck method: " + *it); sMessage = "Ignored invalid SASL pwcheck method"; } } - method.TrimRight(); - if (method.empty()) { + m_sMethod.TrimRight(); + + if (m_sMethod.empty()) { sMessage = "Need a pwcheck method as argument (saslauthd, auxprop)"; return false; } @@ -52,60 +51,73 @@ public: return false; } + m_cbs[0].id = SASL_CB_GETOPT; + m_cbs[0].proc = reinterpret_cast(CSASLAuthMod::getopt); + m_cbs[0].context = this; + m_cbs[1].id = SASL_CB_LIST_END; + m_cbs[1].proc = NULL; + m_cbs[1].context = NULL; + return true; } virtual EModRet OnLoginAttempt(CSmartPtr Auth) { - CString const user(Auth->GetUsername()); - CString const pass(Auth->GetPassword()); - CUser* pUser(CZNC::Get().FindUser(user)); - sasl_conn_t *sasl_conn(0); + const CString& sUsername = Auth->GetUsername(); + const CString& sPassword = Auth->GetPassword(); + CUser *pUser(CZNC::Get().FindUser(sUsername)); + sasl_conn_t *sasl_conn(NULL); - if (!pUser) { // @todo Will want to do some sort of && !m_bAllowCreate in the future - Auth->RefuseLogin("Invalid User - Halting SASL Authentication"); + if (!pUser) { + /* @todo Will want to do some sort of && + * !m_bAllowCreate in the future */ + return CONTINUE; + } + + const CString sCacheKey(CString(sUsername + ":" + sPassword).MD5()); + if (m_Cache.HasItem(sCacheKey)) { + DEBUG("saslauth: Found [" + sUsername + "] in cache"); + + Auth->AcceptLogin(*pUser); return HALT; } - CString const key(CString(user + ":" + pass).MD5()); - if (m_Cache.HasItem(key)) { + if (sasl_server_new("znc", NULL, NULL, NULL, NULL, m_cbs, 0, &sasl_conn) == SASL_OK && + sasl_checkpass(sasl_conn, sUsername.c_str(), sUsername.size(), sPassword.c_str(), sPassword.size()) == SASL_OK) { + m_Cache.AddItem(sCacheKey); + + DEBUG("saslauth: Successful SASL authentication [" + sUsername + "]"); + sasl_dispose(&sasl_conn); + Auth->AcceptLogin(*pUser); - DEBUG("+++ Found in cache"); - } - else if (sasl_server_new("znc", NULL, NULL, NULL, NULL, cbs, 0, &sasl_conn) == SASL_OK && - sasl_checkpass(sasl_conn, user.c_str(), user.size(), pass.c_str(), pass.size()) == SASL_OK) { - Auth->AcceptLogin(*pUser); - m_Cache.AddItem(key); - DEBUG("+++ Successful SASL password check"); - } - else { - Auth->RefuseLogin("SASL Authentication failed"); - DEBUG("--- FAILED SASL password check"); + return HALT; } sasl_dispose(&sasl_conn); - return HALT; + + return CONTINUE; } -private: + const CString& GetMethod() const { return m_sMethod; } + +protected: TCacheMap m_Cache; - static sasl_callback_t cbs[]; - static CString method; + sasl_callback_t m_cbs[2]; + CString m_sMethod; - static int getopt(void *context, const char *plugin_name, const char *option, const char **result, unsigned *len) { - if (!method.empty() && strcmp(option, "pwcheck_method") == 0) { - *result = method.c_str(); + static int getopt(void *context, const char *plugin_name, + const char *option, const char **result, unsigned *len) { + if (CString(option).Equals("pwcheck_method")) { + *result = ((CSASLAuthMod*)context)->GetMethod().c_str(); return SASL_OK; } + return SASL_CONTINUE; } }; -sasl_callback_t CSASLAuthMod::cbs[] = { - { SASL_CB_GETOPT, reinterpret_cast(CSASLAuthMod::getopt), NULL }, - { SASL_CB_LIST_END, NULL, NULL } -}; - -CString CSASLAuthMod::method; +template<> void TModInfo(CModInfo& Info) { + Info.SetWikiPage("saslauth"); +} GLOBALMODULEDEFS(CSASLAuthMod, "Allow users to authenticate via SASL password verification method")