summaryrefslogtreecommitdiff
path: root/src/modules/m_spanningtree
diff options
context:
space:
mode:
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;
}