Fix a crash bug with auth modules

If a module like imapauth needs some time to process a login, it's possible that
the client already disconnected by the time the lookup finished. This would then
cause a stale pointer in CAuthBase to be dereferenced.

Fix this remotely exploitable crash bug by adding a new function
CAuthBase::Invalidate(). After this was called, the CAuthBase instance doesn't
do anything at all anymore, especially not dereferencing the (possibly stale)
m_pSock pointer.

This also makes sure that one can only call AcceptLogin() or RefuseLogin() once.

Thanks to Sm0ke0ut for providing backtraces and reporting this bug.


git-svn-id: https://znc.svn.sourceforge.net/svnroot/znc/trunk@1669 726aef4b-f618-498e-8847-2d620e286838
This commit is contained in:
psychon
2009-11-28 18:53:20 +00:00
parent 13b1295119
commit b0e59f1294
3 changed files with 24 additions and 5 deletions
+16 -1
View File
@@ -49,7 +49,7 @@
CClient::~CClient() {
if (!m_spAuth.IsNull()) {
CClientAuth* pAuth = (CClientAuth*) &(*m_spAuth);
pAuth->SetClient(NULL);
pAuth->Invalidate();
}
if (m_pUser != NULL) {
m_pUser->AddBytesRead(GetBytesRead());
@@ -641,9 +641,23 @@ CString CAuthBase::GetRemoteIP() const {
return "";
}
void CAuthBase::Invalidate() {
m_pSock = NULL;
}
void CAuthBase::AcceptLogin(CUser& User) {
if (m_pSock) {
AcceptedLogin(User);
Invalidate();
}
}
void CAuthBase::RefuseLogin(const CString& sReason) {
CUser* pUser = CZNC::Get().GetUser(GetUsername());
if (!m_pSock)
return;
// If the username is valid, notify that user that someone tried to
// login. Use sReason because there are other reasons than "wrong
// password" for a login to be rejected (e.g. fail2ban).
@@ -656,6 +670,7 @@ void CAuthBase::RefuseLogin(const CString& sReason) {
CZNC::Get().GetModules().OnFailedLogin(GetUsername(), GetRemoteIP());
#endif
RefusedLogin(sReason);
Invalidate();
}
void CClient::RefuseLogin(const CString& sReason) {