crypt: Modernize and add test. Fix OnNumericMessage 332 issue.
It was possible to trigger null pointer dereference during OnNumericMessage The affected versions are 1.7.0+ CVE-2026-82374
This commit is contained in:
1 parent
4b88c64c6e
commit
af5cdd0192
2 files changed
+110
-17
No files matched your search
+37
-16
@@ -248,13 +248,19 @@ class CCryptMod : public CModule {
|
|||||||
FilterOutgoing(Message);
|
FilterOutgoing(Message);
|
||||||
return CONTINUE;
|
return CONTINUE;
|
||||||
}
|
}
|
||||||
|
EModRet OnPrivTextMessage(CTextMessage& Message) override {
|
||||||
|
CNick& Nick = Message.GetNick();
|
||||||
|
CString sMessage = Message.GetText();
|
||||||
|
CString sHostmask = Nick.GetHostMask();
|
||||||
|
|
||||||
EModRet OnPrivMsg(CNick& Nick, CString& sMessage) override {
|
|
||||||
FilterIncoming(Nick.GetNick(), Nick, sMessage);
|
FilterIncoming(Nick.GetNick(), Nick, sMessage);
|
||||||
|
Message.SetText(sMessage);
|
||||||
return CONTINUE;
|
return CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
EModRet OnPrivNotice(CNick& Nick, CString& sMessage) override {
|
EModRet OnPrivNoticeMessage(CNoticeMessage& Message) override {
|
||||||
|
CNick& Nick = Message.GetNick();
|
||||||
|
CString sMessage = Message.GetText();
|
||||||
CString sCommand = sMessage.Token(0);
|
CString sCommand = sMessage.Token(0);
|
||||||
CString sOtherPubKey = sMessage.Token(1);
|
CString sOtherPubKey = sMessage.Token(1);
|
||||||
|
|
||||||
@@ -305,33 +311,42 @@ class CCryptMod : public CModule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
FilterIncoming(Nick.GetNick(), Nick, sMessage);
|
FilterIncoming(Nick.GetNick(), Nick, sMessage);
|
||||||
|
Message.SetText(sMessage);
|
||||||
return CONTINUE;
|
return CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
EModRet OnPrivAction(CNick& Nick, CString& sMessage) override {
|
EModRet OnPrivActionMessage(CActionMessage& Message) override {
|
||||||
FilterIncoming(Nick.GetNick(), Nick, sMessage);
|
CString sText = Message.GetText();
|
||||||
|
FilterIncoming(Message.GetNick().GetNick(), Message.GetNick(), sText);
|
||||||
|
Message.SetText(sText);
|
||||||
return CONTINUE;
|
return CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
EModRet OnChanMsg(CNick& Nick, CChan& Channel, CString& sMessage) override {
|
EModRet OnChanTextMessage(CTextMessage& Message) override {
|
||||||
FilterIncoming(Channel.GetName(), Nick, sMessage);
|
CString sText = Message.GetText();
|
||||||
|
FilterIncoming(Message.GetTarget(), Message.GetNick(), sText);
|
||||||
|
Message.SetText(sText);
|
||||||
return CONTINUE;
|
return CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
EModRet OnChanNotice(CNick& Nick, CChan& Channel,
|
EModRet OnChanNoticeMessage(CNoticeMessage& Message) override {
|
||||||
CString& sMessage) override {
|
CString sText = Message.GetText();
|
||||||
FilterIncoming(Channel.GetName(), Nick, sMessage);
|
FilterIncoming(Message.GetTarget(), Message.GetNick(), sText);
|
||||||
|
Message.SetText(sText);
|
||||||
return CONTINUE;
|
return CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
EModRet OnChanAction(CNick& Nick, CChan& Channel,
|
EModRet OnChanActionMessage(CActionMessage& Message) override {
|
||||||
CString& sMessage) override {
|
CString sText = Message.GetText();
|
||||||
FilterIncoming(Channel.GetName(), Nick, sMessage);
|
FilterIncoming(Message.GetTarget(), Message.GetNick(), sText);
|
||||||
|
Message.SetText(sText);
|
||||||
return CONTINUE;
|
return CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
EModRet OnTopic(CNick& Nick, CChan& Channel, CString& sMessage) override {
|
EModRet OnTopicMessage(CTopicMessage& Message) override {
|
||||||
FilterIncoming(Channel.GetName(), Nick, sMessage);
|
CString sText = Message.GetText();
|
||||||
|
FilterIncoming(Message.GetTarget(), Message.GetNick(), sText);
|
||||||
|
Message.SetText(sText);
|
||||||
return CONTINUE;
|
return CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -342,10 +357,16 @@ class CCryptMod : public CModule {
|
|||||||
|
|
||||||
CChan* pChan = GetNetwork()->FindChan(Message.GetParam(1));
|
CChan* pChan = GetNetwork()->FindChan(Message.GetParam(1));
|
||||||
if (pChan) {
|
if (pChan) {
|
||||||
CNick* Nick = pChan->FindNick(Message.GetParam(0));
|
CNick* pNick = pChan->FindNick(Message.GetParam(0));
|
||||||
CString sTopic = Message.GetParam(2);
|
CString sTopic = Message.GetParam(2);
|
||||||
|
|
||||||
FilterIncoming(pChan->GetName(), *Nick, sTopic);
|
if (pNick) {
|
||||||
|
FilterIncoming(pChan->GetName(), *pNick, sTopic);
|
||||||
|
} else {
|
||||||
|
// 332 can arrive before ZNC has this nick in the nicklist.
|
||||||
|
CNick TempNick(Message.GetParam(0));
|
||||||
|
FilterIncoming(pChan->GetName(), TempNick, sTopic);
|
||||||
|
}
|
||||||
Message.SetParam(2, sTopic);
|
Message.SetParam(2, sTopic);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -138,7 +138,11 @@ TEST_F(ZNCTest, WatchModule) {
|
|||||||
":*spaces!watch@znc.in PRIVMSG nick :<n:#znc> SOMETHING word1 word2 SOMETHING");
|
":*spaces!watch@znc.in PRIVMSG nick :<n:#znc> SOMETHING word1 word2 SOMETHING");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ZNCTest, ModuleCrypt) {
|
TEST_F(ZNCTest, CryptModule) {
|
||||||
|
#ifndef HAVE_LIBSSL
|
||||||
|
GTEST_SKIP() << "SSL is disabled";
|
||||||
|
#endif
|
||||||
|
|
||||||
QFile conf(m_dir.path() + "/configs/znc.conf");
|
QFile conf(m_dir.path() + "/configs/znc.conf");
|
||||||
ASSERT_TRUE(conf.open(QIODevice::Append | QIODevice::Text));
|
ASSERT_TRUE(conf.open(QIODevice::Append | QIODevice::Text));
|
||||||
QTextStream(&conf) << "ServerThrottle = 1\n";
|
QTextStream(&conf) << "ServerThrottle = 1\n";
|
||||||
@@ -184,6 +188,8 @@ TEST_F(ZNCTest, ModuleCrypt) {
|
|||||||
QByteArray key2("");
|
QByteArray key2("");
|
||||||
client2.ReadUntilAndGet("\002user\017: ", key2);
|
client2.ReadUntilAndGet("\002user\017: ", key2);
|
||||||
ASSERT_EQ(key1.mid(9), key2.mid(8));
|
ASSERT_EQ(key1.mid(9), key2.mid(8));
|
||||||
|
|
||||||
|
// OnPrivTextMessage
|
||||||
client1.Write("CAP REQ :echo-message");
|
client1.Write("CAP REQ :echo-message");
|
||||||
client1.Write("PRIVMSG .nick2 :Hello");
|
client1.Write("PRIVMSG .nick2 :Hello");
|
||||||
QByteArray secretmsg;
|
QByteArray secretmsg;
|
||||||
@@ -191,6 +197,72 @@ TEST_F(ZNCTest, ModuleCrypt) {
|
|||||||
ircd2.Write(":user!user@user/test " + secretmsg);
|
ircd2.Write(":user!user@user/test " + secretmsg);
|
||||||
client2.ReadUntil("Hello");
|
client2.ReadUntil("Hello");
|
||||||
client1.ReadUntil(secretmsg); // by echo-message
|
client1.ReadUntil(secretmsg); // by echo-message
|
||||||
|
|
||||||
|
client1.Write("PRIVMSG *crypt :SetNickPrefix .");
|
||||||
|
client1.ReadUntil("Setting Nick Prefix to .");
|
||||||
|
client2.Write("PRIVMSG *crypt :SetNickPrefix .");
|
||||||
|
client2.ReadUntil("Setting Nick Prefix to .");
|
||||||
|
|
||||||
|
// OnPrivNoticeMessage
|
||||||
|
client1.Write("NOTICE .nick2 :secret notice");
|
||||||
|
QByteArray noticeMsg;
|
||||||
|
ircd1.ReadUntilAndGet("NOTICE nick2 :+OK ", noticeMsg);
|
||||||
|
ircd2.Write(":user!user@user/test " + noticeMsg);
|
||||||
|
QByteArray noticeLine;
|
||||||
|
client2.ReadUntilAndGet("NOTICE nick2 :", noticeLine);
|
||||||
|
QByteArray noticemessage = noticeLine.mid(noticeLine.lastIndexOf(':') + 1);
|
||||||
|
EXPECT_EQ(noticemessage, "secret notice");
|
||||||
|
|
||||||
|
// OnUserActionMessage
|
||||||
|
client1.Write("PRIVMSG .nick2 :\001ACTION waves\001");
|
||||||
|
QByteArray actionMsg;
|
||||||
|
ircd1.ReadUntilAndGet("PRIVMSG nick2 :\001ACTION +OK ", actionMsg);
|
||||||
|
ircd2.Write(":user!user@user/test " + actionMsg);
|
||||||
|
QByteArray actionLine;
|
||||||
|
client2.ReadUntilAndGet("PRIVMSG nick2 :", actionLine);
|
||||||
|
QByteArray actionMessage = actionLine.mid(actionLine.lastIndexOf(':') + 1);
|
||||||
|
EXPECT_EQ(actionMessage, "\001ACTION waves\001");
|
||||||
|
|
||||||
|
client1.Write("JOIN #test");
|
||||||
|
client2.Write("JOIN #test");
|
||||||
|
|
||||||
|
QByteArray chanKey = "channelKey123";
|
||||||
|
client1.Write(QByteArray("PRIVMSG *crypt :SetKey #test ") + chanKey);
|
||||||
|
client1.ReadUntil(QByteArray("Set encryption key for [#test] to [") +
|
||||||
|
chanKey + "]");
|
||||||
|
client2.Write(QByteArray("PRIVMSG *crypt :SetKey #test ") + chanKey);
|
||||||
|
client2.ReadUntil(QByteArray("Set encryption key for [#test] to [") +
|
||||||
|
chanKey + "]");
|
||||||
|
|
||||||
|
// OnChanTextMessage
|
||||||
|
client1.Write("PRIVMSG #test :channel secret");
|
||||||
|
QByteArray chanMsg;
|
||||||
|
ircd1.ReadUntilAndGet("PRIVMSG #test :+OK ", chanMsg);
|
||||||
|
ircd2.Write(":user!user@user/test " + chanMsg);
|
||||||
|
client2.ReadUntil("channel secret");
|
||||||
|
|
||||||
|
// OnChanNoticeMessage
|
||||||
|
client1.Write("NOTICE #test :chan notice");
|
||||||
|
QByteArray chanNoticeMsg;
|
||||||
|
ircd1.ReadUntilAndGet("NOTICE #test :+OK ", chanNoticeMsg);
|
||||||
|
ircd2.Write(":user!user@user/test " + chanNoticeMsg);
|
||||||
|
client2.ReadUntil("chan notice");
|
||||||
|
|
||||||
|
// OnChanActionMessage
|
||||||
|
client1.Write("PRIVMSG #test :\001ACTION dances\001");
|
||||||
|
QByteArray chanActionMsg;
|
||||||
|
ircd1.ReadUntilAndGet("PRIVMSG #test :\001ACTION +OK ", chanActionMsg);
|
||||||
|
ircd2.Write(":user!user@user/test " + chanActionMsg);
|
||||||
|
client2.ReadUntil("dances");
|
||||||
|
|
||||||
|
// OnTopicMessage / OnNumericMessage
|
||||||
|
client1.Write("TOPIC #test :new chan topic");
|
||||||
|
QByteArray chanTopicEncrypted;
|
||||||
|
ircd1.ReadUntilAndGet("TOPIC #test :+OK ", chanTopicEncrypted);
|
||||||
|
chanTopicEncrypted = "+OK " + chanTopicEncrypted.mid(
|
||||||
|
chanTopicEncrypted.lastIndexOf(' ') + 1);
|
||||||
|
ircd2.Write(":ircd2 332 nick2 #test :" + chanTopicEncrypted);
|
||||||
|
client2.ReadUntil("new chan topic");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ZNCTest, AutoAttachModule) {
|
TEST_F(ZNCTest, AutoAttachModule) {
|
||||||
|
|||||||
Reference in new issue
Block a user