diff options
author | Attila Molnar <attilamolnar@hush.com> | 2014-06-10 17:37:16 +0200 |
---|---|---|
committer | Attila Molnar <attilamolnar@hush.com> | 2014-06-10 17:37:16 +0200 |
commit | ad6a02809585ac1ad805e66b8aa0113815d9a957 (patch) | |
tree | daee27037992f73baa82a2c19a9d40bbf3fa97f4 | |
parent | a63882846432fda67e6282e979ab8ad248f4b574 (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.cpp | 21 | ||||
-rw-r--r-- | src/modules/m_spanningtree/compat.cpp | 26 | ||||
-rw-r--r-- | src/modules/m_spanningtree/main.cpp | 1 |
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(); } |