summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAttila Molnar <attilamolnar@hush.com>2014-06-10 17:37:16 +0200
committerAttila Molnar <attilamolnar@hush.com>2014-06-10 17:37:16 +0200
commitad6a02809585ac1ad805e66b8aa0113815d9a957 (patch)
treedaee27037992f73baa82a2c19a9d40bbf3fa97f4
parenta63882846432fda67e6282e979ab8ad248f4b574 (diff)
Add channel TS to server-to-server INVITE to detect and drop unauthorized invites
The syntax of the server-to-server INVITE command changes from :<source> INVITE <target> <channel> [<expire>] to :<source> INVITE <target> <channel> <chants> [<expire>]
-rw-r--r--src/coremods/core_channel/cmd_invite.cpp21
-rw-r--r--src/modules/m_spanningtree/compat.cpp26
-rw-r--r--src/modules/m_spanningtree/main.cpp1
3 files changed, 44 insertions, 4 deletions
diff --git a/src/coremods/core_channel/cmd_invite.cpp b/src/coremods/core_channel/cmd_invite.cpp
index 3260d7862..ea4692d04 100644
--- a/src/coremods/core_channel/cmd_invite.cpp
+++ b/src/coremods/core_channel/cmd_invite.cpp
@@ -36,7 +36,7 @@ CmdResult CommandInvite::Handle (const std::vector<std::string>& parameters, Use
{
ModResult MOD_RESULT;
- if (parameters.size() == 2 || parameters.size() == 3)
+ if (parameters.size() >= 2)
{
User* u;
if (IS_LOCAL(user))
@@ -46,12 +46,12 @@ CmdResult CommandInvite::Handle (const std::vector<std::string>& parameters, Use
Channel* c = ServerInstance->FindChan(parameters[1]);
time_t timeout = 0;
- if (parameters.size() == 3)
+ if (parameters.size() >= 3)
{
if (IS_LOCAL(user))
timeout = ServerInstance->Time() + InspIRCd::Duration(parameters[2]);
- else
- timeout = ConvToInt(parameters[2]);
+ else if (parameters.size() > 3)
+ timeout = ConvToInt(parameters[3]);
}
if ((!c) || (!u) || (u->registered != REG_ALL))
@@ -60,6 +60,19 @@ CmdResult CommandInvite::Handle (const std::vector<std::string>& parameters, Use
return CMD_FAILURE;
}
+ // Verify channel timestamp if the INVITE is coming from a remote server
+ if (!IS_LOCAL(user))
+ {
+ // Remote INVITE commands must carry a channel timestamp
+ if (parameters.size() < 3)
+ return CMD_INVALID;
+
+ // Drop the invite if our channel TS is lower
+ time_t RemoteTS = ConvToInt(parameters[2]);
+ if (c->age < RemoteTS)
+ return CMD_FAILURE;
+ }
+
if ((IS_LOCAL(user)) && (!c->HasUser(user)))
{
user->WriteNumeric(ERR_NOTONCHANNEL, "%s :You're not on that channel!", c->name.c_str());
diff --git a/src/modules/m_spanningtree/compat.cpp b/src/modules/m_spanningtree/compat.cpp
index 98b6826e2..ca9fbfa6a 100644
--- a/src/modules/m_spanningtree/compat.cpp
+++ b/src/modules/m_spanningtree/compat.cpp
@@ -169,6 +169,25 @@ void TreeSocket::WriteLine(const std::string& original_line)
line.erase(colon, 1);
}
}
+ else if (command == "INVITE")
+ {
+ // :22D INVITE 22DAAAAAN #chan TS ExpirationTime
+ // A B C D E
+ if (b == std::string::npos)
+ return;
+
+ std::string::size_type c = line.find(' ', b + 1);
+ if (c == std::string::npos)
+ return;
+
+ std::string::size_type d = line.find(' ', c + 1);
+ if (d == std::string::npos)
+ return;
+
+ std::string::size_type e = line.find(' ', d + 1);
+ // If there is no expiration time then everything will be erased from 'd'
+ line.erase(d, e-d);
+ }
}
ServerInstance->Logs->Log(MODNAME, LOG_RAWIO, "S[%d] O %s", this->GetFd(), line.c_str());
this->WriteData(line);
@@ -297,6 +316,13 @@ bool TreeSocket::PreProcessOldProtocolMessage(User*& who, std::string& cmd, std:
{
return false;
}
+ else if (cmd == "INVITE")
+ {
+ // :20D INVITE 22DAAABBB #chan
+ // :20D INVITE 22DAAABBB #chan 123456789
+ // Insert channel timestamp after the channel name; the 3rd parameter, if there, is the invite expiration time
+ return InsertCurrentChannelTS(params, 1, 2);
+ }
return true; // Passthru
}
diff --git a/src/modules/m_spanningtree/main.cpp b/src/modules/m_spanningtree/main.cpp
index 0dc680ca0..46f46e0e0 100644
--- a/src/modules/m_spanningtree/main.cpp
+++ b/src/modules/m_spanningtree/main.cpp
@@ -415,6 +415,7 @@ void ModuleSpanningTree::OnUserInvite(User* source,User* dest,Channel* channel,
CmdBuilder params(source, "INVITE");
params.push_back(dest->uuid);
params.push_back(channel->name);
+ params.push_int(channel->age);
params.push_back(ConvToStr(expiry));
params.Broadcast();
}