X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fmodules%2Fm_spanningtree%2Ftreesocket1.cpp;h=acc6c7fe2f4cf9fa22d3a18b848f1f928cfda414;hb=715074dd10079a3ed846e8815290ba0d13cd4bd8;hp=b0a7e32053dbd79de0e34c58473f342d868524b5;hpb=8eec77bdde05b5e8503a5c19a7c40c60473e21cf;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/modules/m_spanningtree/treesocket1.cpp b/src/modules/m_spanningtree/treesocket1.cpp index b0a7e3205..acc6c7fe2 100644 --- a/src/modules/m_spanningtree/treesocket1.cpp +++ b/src/modules/m_spanningtree/treesocket1.cpp @@ -35,6 +35,7 @@ /* $ModDep: m_spanningtree/timesynctimer.h m_spanningtree/resolvers.h m_spanningtree/main.h m_spanningtree/utils.h m_spanningtree/treeserver.h m_spanningtree/link.h m_spanningtree/treesocket.h m_hash.h */ + /** Because most of the I/O gubbins are encapsulated within * InspSocket, we just call the superclass constructor for * most of the action, and append a few of our own values @@ -75,7 +76,7 @@ TreeSocket::TreeSocket(SpanningTreeUtilities* Util, InspIRCd* SI, int newfd, cha if (Hook) InspSocketHookRequest(this, (Module*)Utils->Creator, Hook).Send(); - Instance->Timers->AddTimer(new HandshakeTimer(Instance, this, &(Utils->LinkBlocks[0]), this->Utils)); + Instance->Timers->AddTimer(new HandshakeTimer(Instance, this, &(Utils->LinkBlocks[0]), this->Utils, 1)); } ServerState TreeSocket::GetLinkState() @@ -101,7 +102,6 @@ const std::string& TreeSocket::GetOurChallenge() void TreeSocket::SetOurChallenge(const std::string &c) { - Instance->Log(DEBUG,"SetOurChallenge: "+c); this->ourchallenge = c; } @@ -112,17 +112,29 @@ const std::string& TreeSocket::GetTheirChallenge() void TreeSocket::SetTheirChallenge(const std::string &c) { - Instance->Log(DEBUG,"SetTheirChallenge: "+c); this->theirchallenge = c; } std::string TreeSocket::MakePass(const std::string &password, const std::string &challenge) { - Instance->Log(DEBUG,"MakePass('"+password+"','"+challenge+"')"); + /* This is a simple (maybe a bit hacky?) HMAC algorithm, thanks to jilles for + * suggesting the use of HMAC to secure the password against various attacks. + * + * Note: If m_sha256.so is not loaded, we MUST fall back to plaintext with no + * 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++) @@ -131,20 +143,14 @@ std::string TreeSocket::MakePass(const std::string &password, const std::string hmac2 += static_cast(password[n] ^ 0x36); } - Instance->Log(DEBUG,"MakePass hmac1="+hmac1+" hmac="+hmac2); - HashResetRequest(Utils->Creator, sha256).Send(); hmac2 = HashSumRequest(Utils->Creator, sha256, hmac2).Send(); - Instance->Log(DEBUG,"MakePass hmac1="+hmac1+" hmac="+hmac2); - HashResetRequest(Utils->Creator, sha256).Send(); std::string hmac = hmac1 + hmac2 + challenge; hmac = HashSumRequest(Utils->Creator, sha256, hmac).Send(); - Instance->Log(DEBUG,"MakePass hmac="+hmac); - - return hmac; + return "HMAC-SHA256:"+ hmac; } else if (!challenge.empty() && !sha256) Instance->Log(DEFAULT,"Not authenticating to server using SHA256/HMAC because we don't have m_sha256 loaded!"); @@ -173,10 +179,9 @@ bool TreeSocket::OnConnected() InspSocketHookRequest(this, (Module*)Utils->Creator, Hook).Send(); this->Instance->SNO->WriteToSnoMask('l',"Connection to \2"+myhost+"\2["+(x->HiddenFromStats ? "" : this->GetIP())+"] using transport \2"+x->Hook+"\2"); } - else - this->SendCapabilities(); + this->OutboundPass = x->SendPass; /* found who we're supposed to be connecting to, send the neccessary gubbins. */ - Instance->Timers->AddTimer(new HandshakeTimer(Instance, this, &(*x), this->Utils)); + Instance->Timers->AddTimer(new HandshakeTimer(Instance, this, &(*x), this->Utils, 2)); return true; } } @@ -260,9 +265,25 @@ std::string TreeSocket::MyCapabilities() std::string TreeSocket::RandString(unsigned int length) { + char* randombuf = new char[length+1]; std::string out; + int fd = open("/dev/urandom", O_RDONLY, 0); + + if (fd >= 0) + { + read(fd, randombuf, length); + close(fd); + } + else + { + for (unsigned int i = 0; i < length; i++) + randombuf[i] = rand(); + } + for (unsigned int i = 0; i < length; i++) - out += static_cast((rand() % 26) + 65); + out += static_cast((randombuf[i] & 0x7F) | 0x21); + + delete[] randombuf; return out; } @@ -298,8 +319,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"); } @@ -410,10 +438,20 @@ bool TreeSocket::Capab(const std::deque ¶ms) /* Challenge response, store their challenge for our password */ std::map::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); + if (!this->GetOurChallenge().empty() && (this->LinkState == CONNECTING)) + { + 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()) @@ -1257,11 +1295,10 @@ void TreeSocket::SendUsers(TreeServer* Current) */ void TreeSocket::DoBurst(TreeServer* s) { + std::string name = s->GetName(); std::string burst = "BURST "+ConvToStr(Instance->Time(true)); std::string endburst = "ENDBURST"; - // Because by the end of the netburst, it could be gone! - std::string name = s->GetName(); - this->Instance->SNO->WriteToSnoMask('l',"Bursting to \2"+name+"\2."); + this->Instance->SNO->WriteToSnoMask('l',"Bursting to \2%s\2 (Authentication: %s).", name.c_str(), this->GetTheirChallenge().empty() ? "plaintext password" : "SHA256-HMAC challenge-response"); this->WriteLine(burst); /* send our version string */ this->WriteLine(std::string(":")+this->Instance->Config->ServerName+" VERSION :"+this->Instance->GetVersionString());