diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/modules/m_spanningtree/treesocket.h | 4 | ||||
-rw-r--r-- | src/modules/m_spanningtree/treesocket1.cpp | 33 | ||||
-rw-r--r-- | src/modules/m_spanningtree/treesocket2.cpp | 22 | ||||
-rw-r--r-- | src/modules/m_spanningtree/utils.cpp | 1 | ||||
-rw-r--r-- | src/modules/m_spanningtree/utils.h | 8 |
5 files changed, 59 insertions, 9 deletions
diff --git a/src/modules/m_spanningtree/treesocket.h b/src/modules/m_spanningtree/treesocket.h index db19f76ac..ff06f0926 100644 --- a/src/modules/m_spanningtree/treesocket.h +++ b/src/modules/m_spanningtree/treesocket.h @@ -138,6 +138,10 @@ class TreeSocket : public InspSocket */ void SetTheirChallenge(const std::string &c); + /** Compare two passwords based on authentication scheme + */ + bool ComparePass(const std::string &ours, const std::string &theirs); + /** Return the module which we are hooking to for I/O encapsulation */ Module* GetHook(); diff --git a/src/modules/m_spanningtree/treesocket1.cpp b/src/modules/m_spanningtree/treesocket1.cpp index 836fc3477..0c8e39f3b 100644 --- a/src/modules/m_spanningtree/treesocket1.cpp +++ b/src/modules/m_spanningtree/treesocket1.cpp @@ -101,7 +101,6 @@ const std::string& TreeSocket::GetOurChallenge() void TreeSocket::SetOurChallenge(const std::string &c) { - Instance->Log(DEBUG,"SetOurChallenge: "+c); this->ourchallenge = c; } @@ -112,7 +111,6 @@ const std::string& TreeSocket::GetTheirChallenge() void TreeSocket::SetTheirChallenge(const std::string &c) { - Instance->Log(DEBUG,"SetTheirChallenge: "+c); this->theirchallenge = c; } @@ -125,9 +123,17 @@ std::string TreeSocket::MakePass(const std::string &password, const std::string * HMAC challenge/response. */ Module* sha256 = Instance->FindModule("m_sha256.so"); - if (sha256 && !challenge.empty()) + if (Utils->ChallengeResponse && sha256 && !challenge.empty()) { - /* sha256( (pass xor 0x5c) + sha256((pass xor 0x36) + m) ) */ + /* XXX: This is how HMAC is supposed to be done: + * + * sha256( (pass xor 0x5c) + sha256((pass xor 0x36) + m) ) + * + * Note that we are encoding the hex hash, not the binary + * output of the hash which is slightly different to standard. + * + * Don't ask me why its always 0x5c and 0x36... it just is. + */ std::string hmac1, hmac2; for (size_t n = 0; n < password.length(); n++) @@ -296,8 +302,15 @@ void TreeSocket::SendCapabilities() #ifdef SUPPORT_IP6LINKS ip6support = 1; #endif - this->SetOurChallenge(RandString(20)); - this->WriteLine("CAPAB CAPABILITIES :NICKMAX="+ConvToStr(NICKMAX)+" HALFOP="+ConvToStr(this->Instance->Config->AllowHalfop)+" CHANMAX="+ConvToStr(CHANMAX)+" MAXMODES="+ConvToStr(MAXMODES)+" IDENTMAX="+ConvToStr(IDENTMAX)+" MAXQUIT="+ConvToStr(MAXQUIT)+" MAXTOPIC="+ConvToStr(MAXTOPIC)+" MAXKICK="+ConvToStr(MAXKICK)+" MAXGECOS="+ConvToStr(MAXGECOS)+" MAXAWAY="+ConvToStr(MAXAWAY)+" IP6NATIVE="+ConvToStr(ip6)+" IP6SUPPORT="+ConvToStr(ip6support)+" PROTOCOL="+ConvToStr(ProtocolVersion)+" CHALLENGE="+this->GetOurChallenge()); + std::string extra; + /* Do we have sha256 available? If so, we send a challenge */ + if (Utils->ChallengeResponse && (Instance->FindModule("m_sha256.so"))) + { + this->SetOurChallenge(RandString(20)); + extra = " CHALLENGE=" + this->GetOurChallenge(); + } + + this->WriteLine("CAPAB CAPABILITIES :NICKMAX="+ConvToStr(NICKMAX)+" HALFOP="+ConvToStr(this->Instance->Config->AllowHalfop)+" CHANMAX="+ConvToStr(CHANMAX)+" MAXMODES="+ConvToStr(MAXMODES)+" IDENTMAX="+ConvToStr(IDENTMAX)+" MAXQUIT="+ConvToStr(MAXQUIT)+" MAXTOPIC="+ConvToStr(MAXTOPIC)+" MAXKICK="+ConvToStr(MAXKICK)+" MAXGECOS="+ConvToStr(MAXGECOS)+" MAXAWAY="+ConvToStr(MAXAWAY)+" IP6NATIVE="+ConvToStr(ip6)+" IP6SUPPORT="+ConvToStr(ip6support)+" PROTOCOL="+ConvToStr(ProtocolVersion)+extra); this->WriteLine("CAPAB END"); } @@ -408,7 +421,7 @@ bool TreeSocket::Capab(const std::deque<std::string> ¶ms) /* Challenge response, store their challenge for our password */ std::map<std::string,std::string>::iterator n = this->CapKeys.find("CHALLENGE"); - if (n != this->CapKeys.end()) + if (Utils->ChallengeResponse && (n != this->CapKeys.end()) && (Instance->FindModule("m_sha256.so"))) { /* Challenge-response is on now */ this->SetTheirChallenge(n->second); @@ -417,6 +430,12 @@ bool TreeSocket::Capab(const std::deque<std::string> ¶ms) this->WriteLine(std::string("SERVER ")+this->Instance->Config->ServerName+" "+this->MakePass(OutboundPass, this->GetTheirChallenge())+" 0 :"+this->Instance->Config->ServerDesc); } } + else + { + /* They didnt specify a challenge or we don't have m_sha256.so, we use plaintext */ + if (this->LinkState == CONNECTING) + this->WriteLine(std::string("SERVER ")+this->Instance->Config->ServerName+" "+OutboundPass+" 0 :"+this->Instance->Config->ServerDesc); + } if (reason.length()) { diff --git a/src/modules/m_spanningtree/treesocket2.cpp b/src/modules/m_spanningtree/treesocket2.cpp index 5f8cafb53..6c0418a0b 100644 --- a/src/modules/m_spanningtree/treesocket2.cpp +++ b/src/modules/m_spanningtree/treesocket2.cpp @@ -814,6 +814,24 @@ bool TreeSocket::RemoteServer(const std::string &prefix, std::deque<std::string> return true; } +bool TreeSocket::ComparePass(const std::string &ours, const std::string &theirs) +{ + if ((!strncmp(ours.c_str(), "HMAC-SHA256:", 12)) || (!strncmp(theirs.c_str(), "HMAC-SHA256:", 12))) + { + /* One or both of us specified hmac sha256, but we don't have sha256 module loaded! + * We can't allow this password as valid. + */ + if (!Instance->FindModule("m_sha256.so") || !Utils->ChallengeResponse) + return false; + else + /* Straight string compare of hashes */ + return ours == theirs; + } + else + /* Straight string compare of plaintext */ + return ours == theirs; +} + bool TreeSocket::Outbound_Reply_Server(std::deque<std::string> ¶ms) { if (params.size() < 4) @@ -833,7 +851,7 @@ bool TreeSocket::Outbound_Reply_Server(std::deque<std::string> ¶ms) std::string description = params[3]; for (std::vector<Link>::iterator x = Utils->LinkBlocks.begin(); x < Utils->LinkBlocks.end(); x++) { - if ((x->Name == servername) && (this->MakePass(x->RecvPass,this->GetOurChallenge()) == password)) + if ((x->Name == servername) && (ComparePass(this->MakePass(x->RecvPass,this->GetOurChallenge()),password))) { TreeServer* CheckDupe = Utils->FindServer(sname); if (CheckDupe) @@ -882,7 +900,7 @@ bool TreeSocket::Inbound_Server(std::deque<std::string> ¶ms) std::string description = params[3]; for (std::vector<Link>::iterator x = Utils->LinkBlocks.begin(); x < Utils->LinkBlocks.end(); x++) { - if ((x->Name == servername) && (this->MakePass(x->RecvPass,this->GetOurChallenge()) == password)) + if ((x->Name == servername) && (ComparePass(this->MakePass(x->RecvPass,this->GetOurChallenge()),password))) { TreeServer* CheckDupe = Utils->FindServer(sname); if (CheckDupe) diff --git a/src/modules/m_spanningtree/utils.cpp b/src/modules/m_spanningtree/utils.cpp index 5788b61f9..671fad7c3 100644 --- a/src/modules/m_spanningtree/utils.cpp +++ b/src/modules/m_spanningtree/utils.cpp @@ -442,6 +442,7 @@ void SpanningTreeUtilities::ReadConfiguration(bool rebind) AnnounceTSChange = Conf->ReadFlag("options","announcets",0); EnableTimeSync = Conf->ReadFlag("timesync","enable",0); MasterTime = Conf->ReadFlag("timesync", "master", 0); + ChallengeResponse = !Conf->ReadFlag("options", "disablehmac", 0); LinkBlocks.clear(); ValidIPs.clear(); for (int j =0; j < Conf->Enumerate("link"); j++) diff --git a/src/modules/m_spanningtree/utils.h b/src/modules/m_spanningtree/utils.h index 291d7010d..70ce1eb13 100644 --- a/src/modules/m_spanningtree/utils.h +++ b/src/modules/m_spanningtree/utils.h @@ -98,6 +98,14 @@ class SpanningTreeUtilities */ std::vector<std::string> hooknames; + /** True (default) if we are to use challenge-response HMAC + * to authenticate passwords. + * + * NOTE: This defaults to on, but should be turned off if + * you are linking to an older version of inspircd. + */ + bool ChallengeResponse; + /** Initialise utility class */ SpanningTreeUtilities(InspIRCd* Instance, ModuleSpanningTree* Creator); |