diff --git a/include/znc/HTTPSock.h b/include/znc/HTTPSock.h index 0f12c866..76d06cee 100644 --- a/include/znc/HTTPSock.h +++ b/include/znc/HTTPSock.h @@ -106,6 +106,7 @@ protected: bool m_bLoggedIn; bool m_bPost; bool m_bDone; + bool m_bBasicAuth; unsigned long m_uPostLen; CString m_sPostData; CString m_sURI; diff --git a/src/HTTPSock.cpp b/src/HTTPSock.cpp index c3533a37..133cf61d 100644 --- a/src/HTTPSock.cpp +++ b/src/HTTPSock.cpp @@ -39,6 +39,7 @@ CHTTPSock::CHTTPSock(CModule *pMod, const CString& sURIPrefix, const CString& sH m_bLoggedIn(false), m_bPost(false), m_bDone(false), + m_bBasicAuth(false), m_uPostLen(0), m_sPostData(""), m_sURI(""), @@ -136,6 +137,7 @@ void CHTTPSock::ReadLine(const CString& sData) { sLine.Token(2).Base64Decode(sUnhashed); m_sUser = sUnhashed.Token(0, false, ":"); m_sPass = sUnhashed.Token(1, true, ":"); + m_bBasicAuth = true; // Postpone authorization attempt until end of headers, because cookies should be read before that, otherwise session id will be overwritten in GetSession() } else if (sName.Equals("Content-Length:")) { m_uPostLen = sLine.Token(1).ToULong(); @@ -182,9 +184,10 @@ void CHTTPSock::ReadLine(const CString& sData) { sLine.Token(1, true).Split(",", ssEncodings, false, "", "", false, true); m_bAcceptGzip = (ssEncodings.find("gzip") != ssEncodings.end()); } else if (sLine.empty()) { - if (!m_sUser.empty() && !m_bLoggedIn) { + if (m_bBasicAuth && !m_bLoggedIn) { m_bLoggedIn = OnLogin(m_sUser, m_sPass, true); // After successful login ReadLine("") will be called again to trigger "else" block + // Failed login sends error and closes socket, so no infinite loop here } else { m_bGotHeader = true; diff --git a/src/WebModules.cpp b/src/WebModules.cpp index cb678b39..832a2e16 100644 --- a/src/WebModules.cpp +++ b/src/WebModules.cpp @@ -601,7 +601,10 @@ CWebSock::EPageReqResult CWebSock::OnPageRequestInternal(const CString& sURI, CS // know the "secret" CSRF check value. Don't do this for login since // CSRF against the login form makes no sense and the login form does a // cookies-enabled check which would break otherwise. - if (IsPost() && GetParam("_CSRF_Check") != GetCSRFCheck() && sURI != "/login") { + // Don't do this, if user authenticated using http-basic auth, because: + // 1. they obviously know the password, + // 2. it's easier to automate some tasks e.g. user creation, without need to care about cookies and csrf + if (IsPost() && !m_bBasicAuth && GetParam("_CSRF_Check") != GetCSRFCheck() && sURI != "/login") { DEBUG("Expected _CSRF_Check: " << GetCSRFCheck()); DEBUG("Actual _CSRF_Check: " << GetParam("_CSRF_Check")); PrintErrorPage(403, "Access denied", "POST requests need to send "