diff --git a/modules/modpython/functions.in b/modules/modpython/functions.in index b662507f..366c6307 100644 --- a/modules/modpython/functions.in +++ b/modules/modpython/functions.in @@ -115,6 +115,7 @@ void OnClientCapRequest(CClient* pClient, const CString& sCap, bool bState) void OnClientGetSASLMechanisms(SCString& ssMechanisms) EModRet OnClientSASLServerInitialChallenge(const CString& sMechanism, CString& sResponse) EModRet OnClientSASLAuthenticate(const CString& sMechanism, const CString& sMessage) +void OnClientSASLAborted() EModRet OnModuleLoading(const CString& sModName, const CString& sArgs, CModInfo::EModuleType eType, bool& bSuccess, CString& sRetMsg) EModRet OnModuleUnloading(CModule* pModule, bool& bSuccess, CString& sRetMsg) EModRet OnGetModInfo(CModInfo& ModInfo, const CString& sModule, bool& bSuccess, CString& sRetMsg) diff --git a/modules/modpython/module.h b/modules/modpython/module.h index ed701246..57a7ffbb 100644 --- a/modules/modpython/module.h +++ b/modules/modpython/module.h @@ -199,6 +199,7 @@ class ZNC_EXPORT_LIB_EXPORT CPyModule : public CModule { CString& sResponse) override; EModRet OnClientSASLAuthenticate(const CString& sMechanism, const CString& sMessage) override; + void OnClientSASLAborted() override; virtual EModRet OnModuleLoading(const CString& sModName, const CString& sArgs, CModInfo::EModuleType eType, bool& bSuccess, diff --git a/modules/modpython/znc.py b/modules/modpython/znc.py index d2a3dc49..64e429d3 100644 --- a/modules/modpython/znc.py +++ b/modules/modpython/znc.py @@ -487,6 +487,9 @@ class Module: def OnClientSASLAuthenticate(self, sMechanism, sMessage): pass + def OnClientSASLAborted(self): + pass + def OnModuleLoading(self, sModName, sArgs, eType, bSuccess, sRetMsg): pass diff --git a/test/integration/tests/scripting.cpp b/test/integration/tests/scripting.cpp index eacac7e0..516cd9c4 100644 --- a/test/integration/tests/scripting.cpp +++ b/test/integration/tests/scripting.cpp @@ -355,5 +355,54 @@ TEST_F(ZNCTest, ModpythonCommand) { client.ReadUntil(":*cmdtest!cmdtest@znc.in PRIVMSG nick :ping понг"); } +TEST_F(ZNCTest, ModpythonSaslAuth) { +#ifndef WANT_PYTHON + GTEST_SKIP() << "Modpython is disabled"; +#endif + auto znc = Run(); + znc->CanLeak(); + + InstallModule("sasltest.py", R"( + import znc + + class sasltest(znc.Module): + + module_types = [znc.CModInfo.GlobalModule] + + def OnClientGetSASLMechanisms(self, ssMechanisms): + ssMechanisms.insert("FOO") + + def OnClientSASLServerInitialChallenge(self, sMechanism, sResponse): + if sMechanism == "FOO": + sResponse.s = "Welcome" + return znc.CONTINUE + + def OnClientSASLAuthenticate(self, sMechanism, sMessage): + if sMechanism == "FOO": + user = znc.CZNC.Get().FindUser("user") + self.GetClient().AcceptSASLLogin(user) + return znc.HALT + return znc.CONTINUE + + )"); + auto ircd = ConnectIRCd(); + auto client = LoginClient(); + client.Write("znc loadmod modpython"); + client.Write("znc loadmod sasltest"); + client.ReadUntil("Loaded"); + + auto client2 = ConnectClient(); + client2.Write("CAP LS 302"); + client2.Write("NICK nick"); + client2.ReadUntil(" sasl=FOO,PLAIN "); + client2.Write("CAP REQ :sasl"); + client2.Write("AUTHENTICATE FOO"); + client2.ReadUntil("AUTHENTICATE " + QByteArrayLiteral("Welcome").toBase64()); + client2.Write("AUTHENTICATE +"); + client2.ReadUntil( + ":irc.znc.in 900 nick nick!user@127.0.0.1 user :You are now logged in " + "as user"); +} + } // namespace } // namespace znc_inttest