diff --git a/include/Network/network.h b/include/Network/network.h index a4d2b84..5a0bf60 100644 --- a/include/Network/network.h +++ b/include/Network/network.h @@ -5,24 +5,28 @@ #include void NetReset(); extern bool Dev; +extern int ping; void CoreNetwork(); extern int ClientID; extern bool ModLoaded; -extern long long ping; extern bool Terminate; extern int DEFAULT_PORT; +extern uint64_t UDPSock; +extern uint64_t TCPSock; extern bool TCPTerminate; extern std::string MStatus; extern std::string UlStatus; extern std::string PublicKey; extern std::string ListOfMods; -void UDPSend(std::string Data); int KillSocket(uint64_t Dead); +void UDPSend(std::string Data); void GameSend(std::string Data); void SendLarge(std::string Data); -void TCPSend(const std::string&Data); +std::string TCPRcv(uint64_t Sock); std::string GetAddr(const std::string&IP); void ServerParser(const std::string& Data); +std::string Login(const std::string& fields); +void TCPSend(const std::string&Data,uint64_t Sock); void TCPClientMain(const std::string& IP,int Port); void UDPClientMain(const std::string& IP,int Port); void TCPGameServer(const std::string& IP, int Port); diff --git a/include/Security/Init.h b/include/Security/Init.h index c336c4d..b364ef1 100644 --- a/include/Security/Init.h +++ b/include/Security/Init.h @@ -8,4 +8,4 @@ void InitGame(const std::string& Dir,const std::string&Current); std::string CheckVer(const std::string &path); std::string GetGameDir(); void LegitimacyCheck(); -void CheckLocalKey(); +void CheckLocalKey(); \ No newline at end of file diff --git a/src/Network/Core.cpp b/src/Network/Core.cpp index 6a2dff4..6060943 100644 --- a/src/Network/Core.cpp +++ b/src/Network/Core.cpp @@ -2,6 +2,7 @@ /// Created by Anonymous275 on 7/20/2020 /// #include "Network/network.h" +#include "Security/Init.h" #include "Security/Enc.h" #include "Curl/http.h" #include @@ -22,7 +23,8 @@ std::string UlStatus; std::string MStatus; bool once = false; bool ModLoaded; -long long ping = -1; +bool LoginAuth = false; +int ping = -1; void StartSync(const std::string &Data){ std::string IP = GetAddr(Data.substr(1,Data.find(':')-1)); @@ -33,6 +35,7 @@ void StartSync(const std::string &Data){ Terminate = true; return; } + CheckLocalKey(); UlStatus = Sec("UlLoading..."); TCPTerminate = false; Terminate = false; @@ -101,6 +104,13 @@ void Parse(std::string Data,SOCKET CSocket){ case 'Z': Data = "Z" + GetVer(); break; + case 'N': + if (SubCode == 'c'){ + Data = "N{\"Auth\":"+std::to_string(LoginAuth)+"}"; + }else{ + Data = "N" + Login(Data.substr(Data.find(':') + 1)); + } + break; default: Data.clear(); break; diff --git a/src/Network/GlobalHandler.cpp b/src/Network/GlobalHandler.cpp index 47cbd40..f025ff0 100644 --- a/src/Network/GlobalHandler.cpp +++ b/src/Network/GlobalHandler.cpp @@ -15,8 +15,6 @@ std::chrono::time_point PingStart,PingEnd; bool GConnected = false; bool CServer = true; -extern SOCKET UDPSock; -extern SOCKET TCPSock; SOCKET CSocket = -1; SOCKET GSocket = -1; @@ -78,7 +76,7 @@ void ServerSend(std::string Data, bool Rel){ if(C == 'W' || C == 'Y' || C == 'V' || C == 'E')Rel = true; if(Ack || Rel){ if(Ack || DLen > 1000)SendLarge(Data); - else TCPSend(Data); + else TCPSend(Data,TCPSock); }else UDPSend(Data); if (DLen > 1000) { @@ -177,11 +175,11 @@ void ParserAsync(const std::string& Data){ case 'p': PingEnd = std::chrono::high_resolution_clock::now(); if(PingStart > PingEnd)ping = 0; - else ping = std::chrono::duration_cast(PingEnd-PingStart).count(); + else ping = int(std::chrono::duration_cast(PingEnd-PingStart).count()); return; case 'M': MStatus = Data; - UlStatus = Sec("Uldone"); + UlStatus = "Uldone"; return; default: break; @@ -197,7 +195,7 @@ void NetMain(const std::string& IP, int Port){ UDPClientMain(IP,Port); CServer = true; Terminate = true; - info(Sec("Connection Terminated!")); + info("Connection Terminated!"); } void TCPGameServer(const std::string& IP, int Port){ GSocket = SetupListener(); diff --git a/src/Network/Resources.cpp b/src/Network/Resources.cpp index d81a2d4..84bd546 100644 --- a/src/Network/Resources.cpp +++ b/src/Network/Resources.cpp @@ -1,16 +1,15 @@ /// /// Created by Anonymous275 on 4/11/2020 /// -#include "Discord/discord_info.h" + #include "Network/network.h" +#include "Security/Init.h" #include "Security/Enc.h" #include #include #include "Startup.h" -#include #include "Logger.h" #include -#include #include #include #include @@ -18,8 +17,6 @@ #include #include - - namespace fs = std::experimental::filesystem; std::string ListOfMods; std::vector Split(const std::string& String,const std::string& delimiter){ @@ -35,48 +32,6 @@ std::vector Split(const std::string& String,const std::string& deli return Val; } -void STCPSendRaw(SOCKET socket,const std::vector& Data){ - if(socket == -1){ - Terminate = true; - return; - } - int BytesSent = send(socket, Data.data(), int(Data.size()), 0); - if (BytesSent == 0){ - debug(Sec("(TCP) Connection closing...")); - Terminate = true; - return; - } - else if (BytesSent < 0) { - debug(Sec("(TCP) send failed with error: ") + std::to_string(WSAGetLastError())); - KillSocket(socket); - Terminate = true; - return; - } - std::this_thread::sleep_for(std::chrono::milliseconds(200)); -} -void STCPSend(SOCKET socket,const std::string&Data){ - STCPSendRaw(socket,std::vector(Data.begin(),Data.end())); -} -std::pair STCPRecv(SOCKET socket){ - char buf[64000]; - int len = 64000; - ZeroMemory(buf, len); - int BytesRcv = recv(socket, buf, len,0); - if (BytesRcv == 0){ - info(Sec("(TCP) Connection closing...")); - Terminate = true; - return std::make_pair((char*)"",0); - }else if (BytesRcv < 0) { - info(Sec("(TCP) recv failed with error: ") + std::to_string(WSAGetLastError())); - KillSocket(socket); - Terminate = true; - return std::make_pair((char*)"",0); - } - char* Ret = new char[BytesRcv]; - memcpy_s(Ret,BytesRcv,buf,BytesRcv); - ZeroMemory(buf, len); - return std::make_pair(Ret,BytesRcv); -} void CheckForDir(){ struct stat info{}; if(stat( Sec("Resources"), &info) != 0){ @@ -90,104 +45,54 @@ void WaitForConfirm(){ ModLoaded = false; } -int N,E; -void Parse(const std::string& msg){ - std::stringstream ss(msg); - std::string t; - while (std::getline(ss, t, 'g')) { - if(t.find_first_not_of(Sec("0123456789abcdef")) != std::string::npos)return; - if(N == 0){ - N = std::stoi(t, nullptr, 16); - }else if(E == 0){ - E = std::stoi(t, nullptr, 16); - }else return; - } -} -std::string GenerateM(RSA*key){ - std::stringstream stream; - stream << std::hex << key->n << "g" << key->e << "g" << RSA_E(Sec("IDC"),key->e,key->n); - return stream.str(); + +void Abord(){ + Terminate = true; + TCPTerminate = true; + info("Terminated!"); } -void Check(SOCKET TCPSock,std::shared_ptr ok){ - size_t accum = 0; - while (!*ok) { - std::this_thread::sleep_for(std::chrono::milliseconds(100)); - accum += 100; - if (accum >= 5000) { - error(Sec("Identification timed out (Check accum)")); - KillSocket(TCPSock); - return; - } - } -} -std::vector PrependSize(const std::string& str) { - uint32_t Size = htonl(uint32_t(str.size()) + 1); - std::vector result; - // +1 for \0, +4 for the size - result.resize(str.size() + 1 + 4); - memcpy(result.data(), &Size, 4); - memcpy(result.data() + 4, str.data(), str.size() + 1); - return result; -} -std::string HandShake(SOCKET Sock,RSA*LKey){ - std::shared_ptr ok = std::make_shared(false); - std::thread Timeout(Check,Sock,ok); - Timeout.detach(); - N = 0;E = 0; - auto Res = STCPRecv(Sock); - std::string msg(Res.first,Res.second); - Parse(msg); - if(N != 0 && E != 0) { - STCPSendRaw(Sock,PrependSize(GenerateM(LKey))); - Res = STCPRecv(Sock); - msg = std::string(Res.first,Res.second); - if(RSA_D(msg,LKey->d,LKey->n) != "HC"){ - Terminate = true; - } - }else Terminate = true; - *ok = true; +std::string Auth(SOCKET Sock){ + TCPSend("VC" + GetVer(),Sock); - if(Terminate){ - TCPTerminate = true; - UlStatus = Sec("UlDisconnected: full or outdated server"); - info(Sec("Terminated!")); + auto Res = TCPRcv(Sock); + + if(Res.empty() || Res[0] == 'E'){ + Abord(); return ""; } - msg = RSA_E("NR" + GetDName() + ":" + GetDID(),E,N); - if(!msg.empty()) { - STCPSendRaw(Sock, PrependSize(msg)); - STCPSendRaw(Sock, PrependSize(RSA_E("VC" + GetVer(),E,N))); - Res = STCPRecv(Sock); - msg = Res.first; - } - if(N == 0 || E == 0 || msg.size() < 2 || msg.substr(0,2) != "WS"){ + TCPSend(PublicKey,Sock); + if(Terminate)return ""; - Terminate = true; - TCPTerminate = true; - UlStatus = Sec("UlDisconnected: full or outdated server"); - info(Sec("Terminated!")); + Res = TCPRcv(Sock); + if(Res.empty() || Res[0] == 'E' || Res != "WS"){ + Abord(); return ""; } - STCPSend(Sock,Sec("SR")); - Res = STCPRecv(Sock); - if(strlen(Res.first) == 0 || std::string(Res.first) == "-"){ - info(Sec("Didn't Receive any mods...")); + + TCPSend("SR",Sock); + if(Terminate)return ""; + + Res = TCPRcv(Sock); + + if(Res[0] == 'E'){ + Abord(); + return ""; + } + + if(Res.empty() || Res == "-"){ + info("Didn't Receive any mods..."); ListOfMods = "-"; - STCPSend(Sock,Sec("Done")); - info(Sec("Done!")); + TCPSend("Done",Sock); + info("Done!"); return ""; } - return Res.first; + return Res; } void SyncResources(SOCKET Sock){ - RSA*LKey = GenKey(); - - std::string Ret = HandShake(Sock,LKey); - delete LKey; - + std::string Ret = Auth(Sock); if(Ret.empty())return; info(Sec("Checking Resources...")); @@ -239,26 +144,21 @@ void SyncResources(SOCKET Sock){ } CheckForDir(); do { - STCPSend(Sock, "f" + *FN); + TCPSend("f" + *FN,Sock); int Recv = 0,Size = std::stoi(*FS); char*File = new char[Size]; ZeroMemory(File,Size); do { - auto Pair = STCPRecv(Sock); - char* Data = Pair.first; - size_t BytesRcv = Pair.second; - if (strcmp(Data, Sec("Cannot Open")) == 0 || Terminate){ - if(BytesRcv != 0)delete[] Data; - break; - } - memcpy_s(File+Recv,BytesRcv,Data,BytesRcv); + auto Data = TCPRcv(Sock); + size_t BytesRcv = Data.size(); + if (Data == "Cannot Open" || Terminate)break; + memcpy_s(File+Recv,BytesRcv,&Data[0],BytesRcv); Recv += int(BytesRcv); float per = float(Recv)/std::stof(*FS) * 100; std::string Percent = std::to_string(truncf(per * 10) / 10); UlStatus = Sec("UlDownloading Resource: (") + std::to_string(Pos) + "/" + std::to_string(Amount) + "): " + a.substr(a.find_last_of('/')) + " (" + Percent.substr(0, Percent.find('.') + 2) + "%)"; - delete[] Data; } while (Recv != Size && Recv < Size && !Terminate); if(Terminate)break; UlStatus = Sec("UlLoading Resource: (") + std::to_string(Pos) + "/" + std::to_string(Amount) + @@ -278,10 +178,10 @@ void SyncResources(SOCKET Sock){ FSizes.clear(); a.clear(); if(!Terminate){ - STCPSend(Sock,Sec("Done")); - info(Sec("Done!")); + TCPSend("Done",Sock); + info("Done!"); }else{ - UlStatus = Sec("Ulstart"); - info(Sec("Connection Terminated!")); + UlStatus = "Ulstart"; + info("Connection Terminated!"); } } \ No newline at end of file diff --git a/src/Network/VehicleData.cpp b/src/Network/VehicleData.cpp index 7cf39ad..6aba019 100644 --- a/src/Network/VehicleData.cpp +++ b/src/Network/VehicleData.cpp @@ -29,7 +29,7 @@ void SendLarge(std::string Data){ std::string CMP(Comp(Data)); Data = "ABG:" + CMP; } - TCPSend(Data); + TCPSend(Data,TCPSock); } void UDPParser(std::string Packet){ @@ -61,7 +61,7 @@ void UDPClientMain(const std::string& IP,int Port){ inet_pton(AF_INET, IP.c_str(), &ToServer->sin_addr); UDPSock = socket(AF_INET, SOCK_DGRAM, 0); - TCPSend(Sec("P")); + TCPSend("P",TCPSock); UDPSend(Sec("p")); while(!Terminate)UDPRcv(); KillSocket(UDPSock); diff --git a/src/Network/VehicleEvent.cpp b/src/Network/VehicleEvent.cpp index 1756e32..ebe34b4 100644 --- a/src/Network/VehicleEvent.cpp +++ b/src/Network/VehicleEvent.cpp @@ -14,26 +14,28 @@ SOCKET TCPSock = -1; bool CheckBytes(int32_t Bytes){ if (Bytes == 0){ - debug(Sec("(TCP) Connection closing... CheckBytes(16)")); + debug("(TCP) Connection closing... CheckBytes(16)"); Terminate = true; return false; }else if (Bytes < 0) { - debug(Sec("(TCP CB) recv failed with error: ") + std::to_string(WSAGetLastError())); + debug("(TCP CB) recv failed with error: " + std::to_string(WSAGetLastError())); KillSocket(TCPSock); Terminate = true; return false; } return true; } -void TCPSend(const std::string&Data){ - if(TCPSock == -1){ +void UpdateUl(const std::string& R){ + UlStatus = "UlDisconnected: " + R; +} + +void TCPSend(const std::string&Data,uint64_t Sock){ + if(Sock == -1){ Terminate = true; + UpdateUl("Invalid Socket"); return; } - // Size is BIG-ENDIAN! - //auto Size = htonl(int32_t(Data.size())); - ///TODO int32_t Size,Sent,Temp; std::string Send(4,0); Size = int32_t(Data.size()); @@ -44,46 +46,63 @@ void TCPSend(const std::string&Data){ Size += 4; do{ if (size_t(Sent) >= Send.size()) { - error(Sec("string OOB in ") + std::string(__func__)); + error("string OOB in " + std::string(__func__)); + UpdateUl("TCP Send OOB"); + return; + } + Temp = send(Sock, &Send[Sent], Size - Sent, 0); + if(!CheckBytes(Temp)){ + UpdateUl("Socket Closed"); return; } - Temp = send(TCPSock, &Send[Sent], Size - Sent, 0); - if(!CheckBytes(Temp))return; Sent += Temp; }while(Sent < Size); } -void TCPRcv(){ - if(TCPSock == -1){ +std::string TCPRcv(SOCKET Sock){ + if(Sock == -1){ Terminate = true; - return; + UpdateUl("Invalid Socket"); + return ""; } int32_t Header,BytesRcv = 0,Temp; std::vector Data(sizeof(Header)); do{ - Temp = recv(TCPSock,&Data[BytesRcv],4-BytesRcv,0); - if(!CheckBytes(Temp))return; + Temp = recv(Sock,&Data[BytesRcv],4-BytesRcv,0); + if(!CheckBytes(Temp)){ + UpdateUl("Socket Closed"); + return ""; + } BytesRcv += Temp; }while(BytesRcv < 4); memcpy(&Header,&Data[0],sizeof(Header)); - if(!CheckBytes(BytesRcv))return; + if(!CheckBytes(BytesRcv)){ + UpdateUl("Socket Closed"); + return ""; + } Data.resize(Header); BytesRcv = 0; do{ - Temp = recv(TCPSock,&Data[BytesRcv],Header-BytesRcv,0); - if(!CheckBytes(Temp))return; + Temp = recv(Sock,&Data[BytesRcv],Header-BytesRcv,0); + if(!CheckBytes(Temp)){ + UpdateUl("Socket Closed"); + return ""; + } BytesRcv += Temp; }while(BytesRcv < Header); std::string Ret(Data.data(),Header); + if (Ret.substr(0, 4) == "ABG:") { Ret = DeComp(Ret.substr(4)); } + #ifdef DEBUG //debug("Parsing from server -> " + std::to_string(Ret.size())); #endif - ServerParser(Ret); + if(Ret[0] == 'E')UpdateUl(Ret.substr(1)); + return Ret; } @@ -115,7 +134,9 @@ void TCPClientMain(const std::string& IP,int Port){ getsockname(TCPSock, (SOCKADDR *)&ServerAddr, (int *)sizeof(ServerAddr)); SyncResources(TCPSock); - while(!Terminate)TCPRcv(); + while(!Terminate){ + ServerParser(TCPRcv(TCPSock)); + } GameSend(Sec("T")); ////Game Send Terminate if(KillSocket(TCPSock) != 0) diff --git a/src/Security/Login.cpp b/src/Security/Login.cpp index 109e039..ce1495c 100644 --- a/src/Security/Login.cpp +++ b/src/Security/Login.cpp @@ -8,14 +8,9 @@ #include #include "Json.h" - -//check file if not present flag for login to the core network -//to then get user and pass -//if present use to contact the backend to refresh and get a public key for servers -//public keys are one time use for a random server - using namespace std::filesystem; std::string PublicKey; +extern bool LoginAuth; void UpdateKey(const char* newKey){ if(newKey){ @@ -29,17 +24,39 @@ void UpdateKey(const char* newKey){ } } -void AskUser(){ - //Flag Core Network Update to have a login screen -} - /// "username":"value","password":"value" /// "Guest":"Name" /// "pk":"private_key" -void QueryKey(){ - /*std::string Buffer = PostHTTP("https://auth.beammp.com/pkToUser", R"({"key":")"+PublicKey+"\"}"); - std::cout << Buffer << std::endl;*/ +std::string Login(const std::string& fields){ + info("Attempting to authenticate..."); + std::string Buffer = PostHTTP("https://auth.beammp.com/userlogin", fields); + json::Document d; + d.Parse(Buffer.c_str()); + if(Buffer == "-1"){ + fatal("Failed to communicate with the auth system!"); + } + if (Buffer.find('{') == -1 || d.HasParseError()) { + fatal("Invalid answer from authentication servers, please try again later!"); + } + if(!d["success"].IsNull() && d["success"].GetBool()){ + LoginAuth = true; + if(!d["private_key"].IsNull()){ + UpdateKey(d["private_key"].GetString()); + } + if(!d["public_key"].IsNull()){ + PublicKey = d["public_key"].GetString(); + } + } + if(!d["message"].IsNull()){ + d.RemoveMember("private_key"); + d.RemoveMember("public_key"); + rapidjson::StringBuffer buffer; + rapidjson::Writer writer(buffer); + d.Accept(writer); + return buffer.GetString(); + } + return "{\"success\":false}"; } void CheckLocalKey(){ @@ -52,28 +69,21 @@ void CheckLocalKey(){ Key.close(); Buffer = PostHTTP("https://auth.beammp.com/userlogin", R"({"pk":")"+Buffer+"\"}"); json::Document d; - std::cout << Buffer << std::endl; d.Parse(Buffer.c_str()); if (Buffer == "-1" || Buffer.find('{') == -1 || d.HasParseError()) { fatal("Invalid answer from authentication servers, please try again later!"); } if(d["success"].GetBool()){ + LoginAuth = true; UpdateKey(d["private_key"].GetString()); PublicKey = d["public_key"].GetString(); - QueryKey(); }else{ - std::cout << "Well..... re-login" << std::endl; - std::cout << Buffer << std::endl; - //send it all to the game + info("Auto-Authentication unsuccessful please re-login!"); + UpdateKey(nullptr); } }else{ warn("Could not open saved key!"); UpdateKey(nullptr); - AskUser(); } - }else{ - UpdateKey(nullptr); - AskUser(); - } - system("pause"); + }else UpdateKey(nullptr); } diff --git a/src/Startup.cpp b/src/Startup.cpp index f3e2f0f..616ac09 100644 --- a/src/Startup.cpp +++ b/src/Startup.cpp @@ -16,13 +16,13 @@ extern int TraceBack; bool Dev = false; namespace fs = std::experimental::filesystem; std::string GetEN(){ - return std::string(Sec("BeamMP-Launcher.exe")); + return "BeamMP-Launcher.exe"; } std::string GetVer(){ - return std::string(Sec("1.70")); + return "1.71"; } std::string GetPatch(){ - return std::string(Sec(".3")); + return ""; } void ReLaunch(int argc,char*args[]){ std::string Arg;