From e5cd84730129ec3cabb2e75ebbb43ccf177c3ec6 Mon Sep 17 00:00:00 2001 From: prozacx Date: Fri, 17 Mar 2006 07:02:16 +0000 Subject: [PATCH] IMAP Authentication Module git-svn-id: https://znc.svn.sourceforge.net/svnroot/znc/trunk@698 726aef4b-f618-498e-8847-2d620e286838 --- modules/imapauth.cpp | 132 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 modules/imapauth.cpp diff --git a/modules/imapauth.cpp b/modules/imapauth.cpp new file mode 100644 index 00000000..507ef04b --- /dev/null +++ b/modules/imapauth.cpp @@ -0,0 +1,132 @@ +#include "main.h" +#include "User.h" +#include "Nick.h" +#include "Modules.h" +#include "Chan.h" +#include "znc.h" +#include "HTTPSock.h" +#include "Server.h" +#include + +using std::map; + +class CIMAPAuthMod; + +class CIMAPSock : public CSocket { +public: + CIMAPSock(CIMAPAuthMod* pModule, CSmartPtr Auth) + : CSocket((CModule*) pModule, "IMAPMod"), m_spAuth(Auth) { + m_pIMAPMod = pModule; + m_bSentReply = false; + m_bSentLogin = false; + EnableReadLine(); + } + + virtual ~CIMAPSock() { + if (!m_bSentReply) { + m_spAuth->RefuseLogin("IMAP server is down, please try again later"); + } + } + + virtual void ReadLine(const CString& sLine); +private: +protected: + CIMAPAuthMod* m_pIMAPMod; + bool m_bSentLogin; + bool m_bSentReply; + CSmartPtr m_spAuth; +}; + + +class CIMAPAuthMod : public CGlobalModule { +public: + GLOBALMODCONSTRUCTOR(CIMAPAuthMod) { + m_Cache.SetTTL(60000); + m_uPort = 143; + m_bSSL = false; + } + + virtual ~CIMAPAuthMod() {} + + virtual bool OnBoot() { + return true; + } + + virtual bool OnLoad(const CString& sArgs) { + m_sServer = sArgs.Token(0); + + if (m_sServer.empty()) { + return false; + } + + CString sPort = sArgs.Token(1); + + if (sPort.Left(1) == "+") { + m_bSSL = true; + sPort.LeftChomp(); + } + + unsigned short uPort = sPort.ToUShort(); + + if (uPort) { + m_uPort = uPort; + } + + return true; + } + + virtual EModRet OnLoginAttempt(CSmartPtr Auth) { + CUser* pUser = CZNC::Get().FindUser(Auth->GetUsername()); + + if (pUser && m_Cache.HasItem(CString(Auth->GetUsername() + ":" + Auth->GetPassword()).MD5())) { + DEBUG_ONLY(cerr << "+++ Found in cache" << endl); + Auth->AcceptLogin(*pUser); + return HALT; + } + + CIMAPSock* pSock = new CIMAPSock(this, Auth); + pSock->Connect(m_sServer, m_uPort, m_bSSL, 20); + + return HALT; + } + + virtual void OnModCommand(const CString& sLine) { + ListSockets(); + } + + void CacheLogin(const CString& sLogin) { + m_Cache.AddItem(sLogin); + } +private: + // Settings + CString m_sServer; + unsigned short m_uPort; + bool m_bSSL; + // !Settings + + TCacheMap m_Cache; +}; + +void CIMAPSock::ReadLine(const CString& sLine) { + if (!m_bSentLogin) { + m_bSentLogin = true; + + Write("AUTH LOGIN " + m_spAuth->GetUsername() + " " + m_spAuth->GetPassword() + "\r\n"); + } else { + CUser* pUser = CZNC::Get().FindUser(m_spAuth->GetUsername()); + + if (pUser && sLine.Left(7).CaseCmp("AUTH OK") == 0) { + m_spAuth->AcceptLogin(*pUser); + m_pIMAPMod->CacheLogin(CString(m_spAuth->GetUsername() + ":" + m_spAuth->GetPassword()).MD5()); // Use MD5 so passes don't sit in memory in plain text + DEBUG_ONLY(cerr << "+++ Successful IMAP lookup" << endl); + } else { + m_spAuth->RefuseLogin("Invalid Password"); + DEBUG_ONLY(cerr << "--- FAILED IMAP lookup" << endl); + } + + m_bSentReply = true; + Close(); + } +} + +GLOBALMODULEDEFS(CIMAPAuthMod, "Allow users to authenticate via imap");