aboutsummaryrefslogtreecommitdiff
path: root/src/modules/m_spanningtree
diff options
context:
space:
mode:
authorGravatar danieldg2010-01-15 19:46:01 +0000
committerGravatar danieldg2010-01-15 19:46:01 +0000
commit33318dd6fbc2fa38ccf16ca90a95666f28d860b3 (patch)
tree286968ccc2195b8c68f57e47ff431381014e6515 /src/modules/m_spanningtree
parentAllow regex engine to be omitted in configuration to use automatic binding (diff)
Add CAPAB CHANMODES, CAPAB USERMODES to verify matching of modes by name, not just by letter
git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@12262 e03df62e-2008-0410-955e-edbf42e46eb7
Diffstat (limited to 'src/modules/m_spanningtree')
-rw-r--r--src/modules/m_spanningtree/capab.cpp130
-rw-r--r--src/modules/m_spanningtree/hmac.cpp18
-rw-r--r--src/modules/m_spanningtree/netburst.cpp4
-rw-r--r--src/modules/m_spanningtree/treesocket.h27
-rw-r--r--src/modules/m_spanningtree/treesocket1.cpp18
5 files changed, 134 insertions, 63 deletions
diff --git a/src/modules/m_spanningtree/capab.cpp b/src/modules/m_spanningtree/capab.cpp
index de97b6c70..e5d63ab22 100644
--- a/src/modules/m_spanningtree/capab.cpp
+++ b/src/modules/m_spanningtree/capab.cpp
@@ -49,15 +49,33 @@ std::string TreeSocket::MyModules(int filter)
return capabilities;
}
+static std::string BuildModeList(ModeType type)
+{
+ std::string line;
+ for(char c='A'; c <= 'z'; c++)
+ {
+ ModeHandler* mh = ServerInstance->Modes->FindMode(c, type);
+ if (mh)
+ {
+ if (!line.empty())
+ line.push_back(',');
+ line.append(mh->name);
+ line.push_back('=');
+ line.push_back(c);
+ }
+ }
+ return line;
+}
+
void TreeSocket::SendCapabilities(int phase)
{
- if (capab_phase >= phase)
+ if (capab->capab_phase >= phase)
return;
- if (capab_phase < 1 && phase >= 1)
+ if (capab->capab_phase < 1 && phase >= 1)
WriteLine("CAPAB START " + ConvToStr(ProtocolVersion));
- capab_phase = phase;
+ capab->capab_phase = phase;
if (phase < 2)
return;
@@ -99,6 +117,13 @@ void TreeSocket::SendCapabilities(int phase)
if (line != "CAPAB MODSUPPORT ")
this->WriteLine(line);
+ line = "CAPAB CHANMODES " + BuildModeList(MODETYPE_CHANNEL);
+ if (line != "CAPAB CHANMODES ")
+ this->WriteLine(line);
+
+ line = "CAPAB USERMODES " + BuildModeList(MODETYPE_USER);
+ if (line != "CAPAB USERMODES ")
+ this->WriteLine(line);
int ip6 = 0;
#ifdef IPV6
@@ -173,9 +198,9 @@ bool TreeSocket::Capab(const parameterlist &params)
}
if (params[0] == "START")
{
- ModuleList.clear();
- OptModuleList.clear();
- CapKeys.clear();
+ capab->ModuleList.clear();
+ capab->OptModuleList.clear();
+ capab->CapKeys.clear();
if (params.size() > 1)
proto_version = atoi(params[1].c_str());
SendCapabilities(2);
@@ -184,10 +209,10 @@ bool TreeSocket::Capab(const parameterlist &params)
{
std::string reason;
/* Compare ModuleList and check CapKeys */
- if ((this->ModuleList != this->MyModules(VF_COMMON)) && (this->ModuleList.length()))
+ if ((this->capab->ModuleList != this->MyModules(VF_COMMON)) && (this->capab->ModuleList.length()))
{
- std::string diffIneed = ListDifference(this->ModuleList, this->MyModules(VF_COMMON));
- std::string diffUneed = ListDifference(this->MyModules(VF_COMMON), this->ModuleList);
+ std::string diffIneed = ListDifference(this->capab->ModuleList, this->MyModules(VF_COMMON));
+ std::string diffUneed = ListDifference(this->MyModules(VF_COMMON), this->capab->ModuleList);
if (diffIneed.length() == 0 && diffUneed.length() == 0)
{
reason = "Module list in CAPAB is not alphabetically ordered, cannot compare lists.";
@@ -203,10 +228,10 @@ bool TreeSocket::Capab(const parameterlist &params)
this->SendError("CAPAB negotiation failed: "+reason);
return false;
}
- if (this->OptModuleList != this->MyModules(VF_OPTCOMMON) && this->OptModuleList.length())
+ if (this->capab->OptModuleList != this->MyModules(VF_OPTCOMMON) && this->capab->OptModuleList.length())
{
- std::string diffIneed = ListDifference(this->OptModuleList, this->MyModules(VF_OPTCOMMON));
- std::string diffUneed = ListDifference(this->MyModules(VF_OPTCOMMON), this->OptModuleList);
+ std::string diffIneed = ListDifference(this->capab->OptModuleList, this->MyModules(VF_OPTCOMMON));
+ std::string diffUneed = ListDifference(this->MyModules(VF_OPTCOMMON), this->capab->OptModuleList);
if (diffIneed.length() == 0 && diffUneed.length() == 0)
{
reason = "Optional Module list in CAPAB is not alphabetically ordered, cannot compare lists.";
@@ -230,13 +255,13 @@ bool TreeSocket::Capab(const parameterlist &params)
}
}
- if (this->CapKeys.find("PROTOCOL") == this->CapKeys.end())
+ if (this->capab->CapKeys.find("PROTOCOL") == this->capab->CapKeys.end())
{
reason = "Protocol version not specified";
}
else
{
- proto_version = atoi(CapKeys.find("PROTOCOL")->second.c_str());
+ proto_version = atoi(capab->CapKeys.find("PROTOCOL")->second.c_str());
if (proto_version < MinCompatProtocol)
{
reason = "Server is using protocol version " + ConvToStr(proto_version) +
@@ -245,26 +270,57 @@ bool TreeSocket::Capab(const parameterlist &params)
}
}
- if(this->CapKeys.find("PREFIX") != this->CapKeys.end() && this->CapKeys.find("PREFIX")->second != ServerInstance->Modes->BuildPrefixes())
+ if(this->capab->CapKeys.find("PREFIX") != this->capab->CapKeys.end() && this->capab->CapKeys.find("PREFIX")->second != ServerInstance->Modes->BuildPrefixes())
reason = "One or more of the prefixes on the remote server are invalid on this server.";
- if(this->CapKeys.find("CHANMODES") != this->CapKeys.end() && this->CapKeys.find("CHANMODES")->second != ServerInstance->Modes->GiveModeList(MASK_CHANNEL))
- reason = "One or more of the channel modes on the remote server are invalid on this server.";
-
- if(this->CapKeys.find("USERMODES") != this->CapKeys.end() && this->CapKeys.find("USERMODES")->second != ServerInstance->Modes->GiveModeList(MASK_USER))
- reason = "One or more of the user modes on the remote server are invalid on this server.";
+ if (!capab->ChanModes.empty())
+ {
+ if (capab->ChanModes != BuildModeList(MODETYPE_CHANNEL))
+ {
+ std::string diffIneed = ListDifference(capab->ChanModes, BuildModeList(MODETYPE_CHANNEL));
+ std::string diffUneed = ListDifference(BuildModeList(MODETYPE_CHANNEL), capab->ChanModes);
+ reason = "Channel modes not matched on these servers.";
+ if (diffIneed.length())
+ reason += " Not loaded here:" + diffIneed;
+ if (diffUneed.length())
+ reason += " Not loaded there:" + diffUneed;
+ }
+ }
+ else if (this->capab->CapKeys.find("CHANMODES") != this->capab->CapKeys.end())
+ {
+ if (this->capab->CapKeys.find("CHANMODES")->second != ServerInstance->Modes->GiveModeList(MASK_CHANNEL))
+ reason = "One or more of the channel modes on the remote server are invalid on this server.";
+ }
+ if (!capab->UserModes.empty())
+ {
+ if (capab->UserModes != BuildModeList(MODETYPE_USER))
+ {
+ std::string diffIneed = ListDifference(capab->UserModes, BuildModeList(MODETYPE_USER));
+ std::string diffUneed = ListDifference(BuildModeList(MODETYPE_USER), capab->UserModes);
+ reason = "User modes not matched on these servers.";
+ if (diffIneed.length())
+ reason += " Not loaded here:" + diffIneed;
+ if (diffUneed.length())
+ reason += " Not loaded there:" + diffUneed;
+ }
+ }
+ else if (this->capab->CapKeys.find("USERMODES") != this->capab->CapKeys.end())
+ {
+ if (this->capab->CapKeys.find("USERMODES")->second != ServerInstance->Modes->GiveModeList(MASK_USER))
+ reason = "One or more of the user modes on the remote server are invalid on this server.";
+ }
/* Challenge response, store their challenge for our password */
- std::map<std::string,std::string>::iterator n = this->CapKeys.find("CHALLENGE");
- if (Utils->ChallengeResponse && (n != this->CapKeys.end()) && (ServerInstance->Modules->Find("m_sha256.so")))
+ std::map<std::string,std::string>::iterator n = this->capab->CapKeys.find("CHALLENGE");
+ if (Utils->ChallengeResponse && (n != this->capab->CapKeys.end()) && (ServerInstance->Modules->Find("m_sha256.so")))
{
/* Challenge-response is on now */
this->SetTheirChallenge(n->second);
if (!this->GetTheirChallenge().empty() && (this->LinkState == CONNECTING))
{
this->SendCapabilities(2);
- this->WriteLine(std::string("SERVER ")+ServerInstance->Config->ServerName+" "+this->MakePass(OutboundPass, this->GetTheirChallenge())+" 0 "+
+ this->WriteLine(std::string("SERVER ")+ServerInstance->Config->ServerName+" "+this->MakePass(capab->OutboundPass, this->GetTheirChallenge())+" 0 "+
ServerInstance->Config->GetSID()+" :"+ServerInstance->Config->ServerDesc);
}
}
@@ -274,7 +330,7 @@ bool TreeSocket::Capab(const parameterlist &params)
if (this->LinkState == CONNECTING)
{
this->SendCapabilities(2);
- this->WriteLine(std::string("SERVER ")+ServerInstance->Config->ServerName+" "+OutboundPass+" 0 "+ServerInstance->Config->GetSID()+" :"+ServerInstance->Config->ServerDesc);
+ this->WriteLine(std::string("SERVER ")+ServerInstance->Config->ServerName+" "+capab->OutboundPass+" 0 "+ServerInstance->Config->GetSID()+" :"+ServerInstance->Config->ServerDesc);
}
}
@@ -286,28 +342,36 @@ bool TreeSocket::Capab(const parameterlist &params)
}
else if ((params[0] == "MODULES") && (params.size() == 2))
{
- if (!this->ModuleList.length())
+ if (!this->capab->ModuleList.length())
{
- this->ModuleList.append(params[1]);
+ this->capab->ModuleList.append(params[1]);
}
else
{
- this->ModuleList.append(",");
- this->ModuleList.append(params[1]);
+ this->capab->ModuleList.append(",");
+ this->capab->ModuleList.append(params[1]);
}
}
else if ((params[0] == "MODSUPPORT") && (params.size() == 2))
{
- if (!this->OptModuleList.length())
+ if (!this->capab->OptModuleList.length())
{
- this->OptModuleList.append(params[1]);
+ this->capab->OptModuleList.append(params[1]);
}
else
{
- this->OptModuleList.append(",");
- this->OptModuleList.append(params[1]);
+ this->capab->OptModuleList.append(",");
+ this->capab->OptModuleList.append(params[1]);
}
}
+ else if ((params[0] == "CHANMODES") && (params.size() == 2))
+ {
+ capab->ChanModes = params[1];
+ }
+ else if ((params[0] == "USERMODES") && (params.size() == 2))
+ {
+ capab->UserModes = params[1];
+ }
else if ((params[0] == "CAPABILITIES") && (params.size() == 2))
{
irc::tokenstream capabs(params[1]);
@@ -321,7 +385,7 @@ bool TreeSocket::Capab(const parameterlist &params)
{
std::string var = item.substr(0, equals);
std::string value = item.substr(equals+1, item.length());
- CapKeys[var] = value;
+ capab->CapKeys[var] = value;
}
}
}
diff --git a/src/modules/m_spanningtree/hmac.cpp b/src/modules/m_spanningtree/hmac.cpp
index 573dada4f..172883f3f 100644
--- a/src/modules/m_spanningtree/hmac.cpp
+++ b/src/modules/m_spanningtree/hmac.cpp
@@ -29,22 +29,22 @@
const std::string& TreeSocket::GetOurChallenge()
{
- return this->ourchallenge;
+ return capab->ourchallenge;
}
void TreeSocket::SetOurChallenge(const std::string &c)
{
- this->ourchallenge = c;
+ capab->ourchallenge = c;
}
const std::string& TreeSocket::GetTheirChallenge()
{
- return this->theirchallenge;
+ return capab->theirchallenge;
}
void TreeSocket::SetTheirChallenge(const std::string &c)
{
- this->theirchallenge = c;
+ capab->theirchallenge = c;
}
std::string TreeSocket::MakePass(const std::string &password, const std::string &challenge)
@@ -130,8 +130,8 @@ std::string TreeSocket::RandString(unsigned int ilength)
bool TreeSocket::ComparePass(const Link& link, const std::string &theirs)
{
- this->auth_fingerprint = !link.Fingerprint.empty();
- this->auth_challenge = !ourchallenge.empty() && !theirchallenge.empty();
+ capab->auth_fingerprint = !link.Fingerprint.empty();
+ capab->auth_challenge = !capab->ourchallenge.empty() && !capab->theirchallenge.empty();
std::string fp;
if (GetIOHook())
@@ -143,9 +143,9 @@ bool TreeSocket::ComparePass(const Link& link, const std::string &theirs)
}
}
- if (auth_challenge)
+ if (capab->auth_challenge)
{
- std::string our_hmac = MakePass(link.RecvPass, ourchallenge);
+ std::string our_hmac = MakePass(link.RecvPass, capab->ourchallenge);
/* Straight string compare of hashes */
if (our_hmac != theirs)
@@ -158,7 +158,7 @@ bool TreeSocket::ComparePass(const Link& link, const std::string &theirs)
return false;
}
- if (auth_fingerprint)
+ if (capab->auth_fingerprint)
{
/* Require fingerprint to exist and match */
if (link.Fingerprint != fp)
diff --git a/src/modules/m_spanningtree/netburst.cpp b/src/modules/m_spanningtree/netburst.cpp
index ca87b09f9..0e2ae2bf8 100644
--- a/src/modules/m_spanningtree/netburst.cpp
+++ b/src/modules/m_spanningtree/netburst.cpp
@@ -34,8 +34,8 @@ void TreeSocket::DoBurst(TreeServer* s)
std::string endburst = ":" + ServerInstance->Config->GetSID() + " ENDBURST";
ServerInstance->SNO->WriteToSnoMask('l',"Bursting to \2%s\2 (Authentication: %s%s).",
name.c_str(),
- this->auth_fingerprint ? "SSL Fingerprint and " : "",
- this->auth_challenge ? "challenge-response" : "plaintext password");
+ capab->auth_fingerprint ? "SSL Fingerprint and " : "",
+ capab->auth_challenge ? "challenge-response" : "plaintext password");
this->CleanNegotiationInfo();
this->WriteLine(burst);
/* send our version string */
diff --git a/src/modules/m_spanningtree/treesocket.h b/src/modules/m_spanningtree/treesocket.h
index 773a6cd13..7bbaba050 100644
--- a/src/modules/m_spanningtree/treesocket.h
+++ b/src/modules/m_spanningtree/treesocket.h
@@ -54,6 +54,21 @@
*/
enum ServerState { CONNECTING, WAIT_AUTH_1, WAIT_AUTH_2, CONNECTED };
+struct CapabData
+{
+ std::string ModuleList; /* Required module list of other server from CAPAB */
+ std::string OptModuleList; /* Optional module list of other server from CAPAB */
+ std::string ChanModes;
+ std::string UserModes;
+ std::map<std::string,std::string> CapKeys; /* CAPAB keys from other server */
+ std::string ourchallenge; /* Challenge sent for challenge/response */
+ std::string theirchallenge; /* Challenge recv for challenge/response */
+ std::string OutboundPass; /* Outbound password */
+ int capab_phase; /* Have sent CAPAB already */
+ bool auth_fingerprint; /* Did we auth using SSL fingerprint */
+ bool auth_challenge; /* Did we auth using challenge/response */
+};
+
/** Every SERVER connection inbound or outbound is represented by
* an object of type TreeSocket.
* TreeSockets, being inherited from BufferedSocket, can be tied into
@@ -73,20 +88,12 @@ class TreeSocket : public BufferedSocket
std::string InboundServerName; /* Server name sent to us by other side */
std::string InboundDescription; /* Server description (GECOS) sent to us by the other side */
std::string InboundSID; /* Server ID sent to us by the other side */
+ std::string IP;
+ CapabData* capab;
int num_lost_users; /* Users lost in split */
int num_lost_servers; /* Servers lost in split */
time_t NextPing; /* Time when we are due to ping this server */
bool LastPingWasGood; /* Responded to last ping we sent? */
- std::string IP;
- std::string ModuleList; /* Required module list of other server from CAPAB */
- std::string OptModuleList; /* Optional module list of other server from CAPAB */
- std::map<std::string,std::string> CapKeys; /* CAPAB keys from other server */
- std::string ourchallenge; /* Challenge sent for challenge/response */
- std::string theirchallenge; /* Challenge recv for challenge/response */
- std::string OutboundPass; /* Outbound password */
- int capab_phase; /* Have sent CAPAB already */
- bool auth_fingerprint; /* Did we auth using SSL fingerprint */
- bool auth_challenge; /* Did we auth using challenge/response */
int proto_version; /* Remote protocol version */
public:
reference<Autoconnect> myautoconnect; /* Autoconnect used to cause this connection, if any */
diff --git a/src/modules/m_spanningtree/treesocket1.cpp b/src/modules/m_spanningtree/treesocket1.cpp
index c96bf3bc9..71cca66c4 100644
--- a/src/modules/m_spanningtree/treesocket1.cpp
+++ b/src/modules/m_spanningtree/treesocket1.cpp
@@ -35,7 +35,8 @@ TreeSocket::TreeSocket(SpanningTreeUtilities* Util, const std::string& shost, in
{
age = ServerInstance->Time();
myhost = ServerName;
- capab_phase = 0;
+ capab = new CapabData;
+ capab->capab_phase = 0;
proto_version = 0;
LinkState = CONNECTING;
if (!hook.empty())
@@ -60,10 +61,11 @@ TreeSocket::TreeSocket(SpanningTreeUtilities* Util, const std::string& shost, in
TreeSocket::TreeSocket(SpanningTreeUtilities* Util, int newfd, ListenSocket* via, irc::sockets::sockaddrs* client, irc::sockets::sockaddrs* server)
: BufferedSocket(newfd), Utils(Util)
{
+ capab = new CapabData;
IP = client->addr();
age = ServerInstance->Time();
LinkState = WAIT_AUTH_1;
- capab_phase = 0;
+ capab->capab_phase = 0;
proto_version = 0;
myhost = "inbound from " + IP;
@@ -82,12 +84,8 @@ ServerState TreeSocket::GetLinkState()
void TreeSocket::CleanNegotiationInfo()
{
- ModuleList.clear();
- OptModuleList.clear();
- CapKeys.clear();
- ourchallenge.clear();
- theirchallenge.clear();
- OutboundPass.clear();
+ delete capab;
+ capab = NULL;
}
CullResult TreeSocket::cull()
@@ -100,6 +98,8 @@ CullResult TreeSocket::cull()
TreeSocket::~TreeSocket()
{
+ if (capab)
+ delete capab;
}
/** When an outbound connection finishes connecting, we receive
@@ -119,7 +119,7 @@ void TreeSocket::OnConnected()
if (x->Name == this->myhost)
{
ServerInstance->SNO->WriteGlobalSno('l', "Connection to \2%s\2[%s] started.", myhost.c_str(), (x->HiddenFromStats ? "<hidden>" : this->IP.c_str()));
- this->OutboundPass = x->SendPass;
+ capab->OutboundPass = x->SendPass;
this->SendCapabilities(1);
return;
}