summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/inspircd.conf.example13
-rw-r--r--src/modules/m_spanningtree/treesocket.h4
-rw-r--r--src/modules/m_spanningtree/treesocket1.cpp33
-rw-r--r--src/modules/m_spanningtree/treesocket2.cpp22
-rw-r--r--src/modules/m_spanningtree/utils.cpp1
-rw-r--r--src/modules/m_spanningtree/utils.h8
6 files changed, 72 insertions, 9 deletions
diff --git a/docs/inspircd.conf.example b/docs/inspircd.conf.example
index aee35722e..b26ee7ef2 100644
--- a/docs/inspircd.conf.example
+++ b/docs/inspircd.conf.example
@@ -822,6 +822,18 @@
# invites annother user. If you consider this to be #
# unnecessary noise, explicitly set this to no. #
# #
+# disablehmac - If you are linking your InspIRCd to older versions #
+# then you can specify this option and set it to #
+# yes. 1.1.6 and above support HMAC and challenge- #
+# response for password authentication. These can #
+# greatly enhance security of your server to server #
+# connections when you are not using SSL (as is the #
+# case with a lot of larger networks). Linking to #
+# older versions of InspIRCd should not *usually* be #
+# a problem, but if you have problems with HMAC #
+# authentication, this option can be used to turn it #
+# off. #
+# #
<options prefixquit="Quit: "
loglevel="default"
@@ -846,6 +858,7 @@
cyclehosts="yes"
ircumsgprefix="no"
announcets="yes"
+ disablehmac="no"
hostintopic="yes"
allowhalfop="yes">
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> &params)
/* 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> &params)
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> &params)
{
if (params.size() < 4)
@@ -833,7 +851,7 @@ bool TreeSocket::Outbound_Reply_Server(std::deque<std::string> &params)
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> &params)
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);