summaryrefslogtreecommitdiffstats
path: root/source/cAuthenticator.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--source/cAuthenticator.cpp548
1 files changed, 274 insertions, 274 deletions
diff --git a/source/cAuthenticator.cpp b/source/cAuthenticator.cpp
index d45eaa043..f248f4698 100644
--- a/source/cAuthenticator.cpp
+++ b/source/cAuthenticator.cpp
@@ -1,274 +1,274 @@
-
-#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
-
-#include "cAuthenticator.h"
-#include "cBlockingTCPLink.h"
-#include "cRoot.h"
-#include "cServer.h"
-
-#include "../iniFile/iniFile.h"
-
-#include <sstream>
-
-
-
-
-
-#define DEFAULT_AUTH_SERVER "session.minecraft.net"
-#define DEFAULT_AUTH_ADDRESS "/game/checkserver.jsp?user=%USERNAME%&serverId=%SERVERID%"
-#define MAX_REDIRECTS 10
-
-
-
-
-
-cAuthenticator::cAuthenticator(void) :
- super("cAuthenticator"),
- m_Server(DEFAULT_AUTH_SERVER),
- m_Address(DEFAULT_AUTH_ADDRESS),
- m_ShouldAuthenticate(true)
-{
- ReadINI();
-}
-
-
-
-
-
-cAuthenticator::~cAuthenticator()
-{
- Stop();
-}
-
-
-
-
-
-/// Read custom values from INI
-void cAuthenticator::ReadINI(void)
-{
- cIniFile IniFile("settings.ini");
- if (!IniFile.ReadFile())
- {
- return;
- }
-
- m_Server = IniFile.GetValue("Authentication", "Server");
- m_Address = IniFile.GetValue("Authentication", "Address");
- m_ShouldAuthenticate = IniFile.GetValueB("Authentication", "Authenticate", true);
- bool bSave = false;
-
- if (m_Server.length() == 0)
- {
- m_Server = DEFAULT_AUTH_SERVER;
- IniFile.SetValue("Authentication", "Server", m_Server);
- bSave = true;
- }
- if (m_Address.length() == 0)
- {
- m_Address = DEFAULT_AUTH_ADDRESS;
- IniFile.SetValue("Authentication", "Address", m_Address);
- bSave = true;
- }
-
- if (bSave)
- {
- IniFile.SetValueB("Authentication", "Authenticate", m_ShouldAuthenticate);
- IniFile.WriteFile();
- }
-}
-
-
-
-
-
-/// Queues a request for authenticating a user. If the auth fails, the user is kicked
-void cAuthenticator::Authenticate(int a_ClientID, const AString & a_UserName, const AString & a_ServerHash)
-{
- if (!m_ShouldAuthenticate)
- {
- cRoot::Get()->AuthenticateUser(a_ClientID);
- return;
- }
-
- cCSLock Lock(m_CS);
- m_Queue.push_back(cUser(a_ClientID, a_UserName, a_ServerHash));
- m_QueueNonempty.Set();
-}
-
-
-
-
-
-void cAuthenticator::Stop(void)
-{
- m_ShouldTerminate = true;
- m_QueueNonempty.Set();
- Wait();
-}
-
-
-
-
-
-void cAuthenticator::Execute(void)
-{
- for (;;)
- {
- cCSLock Lock(m_CS);
- while (!m_ShouldTerminate && (m_Queue.size() == 0))
- {
- cCSUnlock Unlock(Lock);
- m_QueueNonempty.Wait();
- }
- if (m_ShouldTerminate)
- {
- return;
- }
- ASSERT(!m_Queue.empty());
-
- int ClientID = m_Queue.front().mClientID;
- AString UserName = m_Queue.front().mName;
- AString ActualAddress = m_Address;
- ReplaceString(ActualAddress, "%USERNAME%", UserName);
- ReplaceString(ActualAddress, "%SERVERID%", cRoot::Get()->GetServer()->GetServerID());
- m_Queue.pop_front();
- Lock.Unlock();
-
- if (!AuthFromAddress(m_Server, ActualAddress, UserName))
- {
- cRoot::Get()->KickUser(ClientID, "Failed to authenticate account!");
- }
- else
- {
- cRoot::Get()->AuthenticateUser(ClientID);
- }
- } // for (-ever)
-}
-
-
-
-
-
-bool cAuthenticator::AuthFromAddress(const AString & a_Server, const AString & a_Address, const AString & a_UserName, int a_Level /* = 1 */)
-{
- // Returns true if the user authenticated okay, false on error; iLevel is the recursion deptht (bails out if too deep)
-
- cBlockingTCPLink Link;
- if (!Link.Connect(a_Server.c_str(), 80))
- {
- LOGERROR("cAuthenticator: cannot connect to auth server \"%s\", kicking user \"%s\"", a_Server.c_str(), a_Server.c_str());
- return false;
- }
-
- Link.SendMessage( AString( "GET " + a_Address + " HTTP/1.0\r\n\r\n" ).c_str());
- AString DataRecvd;
- Link.ReceiveData(DataRecvd);
- Link.CloseSocket();
-
- std::stringstream ss(DataRecvd);
-
- // Parse the data received:
- std::string temp;
- ss >> temp;
- bool bRedirect = false;
- bool bOK = false;
- if ((temp.compare("HTTP/1.1") == 0) || (temp.compare("HTTP/1.0") == 0))
- {
- int code;
- ss >> code;
- if (code == 302)
- {
- // redirect blabla
- LOGINFO("Need to redirect!");
- if (a_Level > MAX_REDIRECTS)
- {
- LOGERROR("cAuthenticator: received too many levels of redirection from auth server \"%s\" for user \"%s\", bailing out and kicking the user", a_Server.c_str(), a_UserName.c_str());
- return false;
- }
- bRedirect = true;
- }
- else if (code == 200)
- {
- LOGINFO("Got 200 OK :D");
- bOK = true;
- }
- }
- else
- {
- LOGERROR("cAuthenticator: cannot parse auth reply from server \"%s\" for user \"%s\", kicking the user.", a_Server.c_str(), a_UserName.c_str());
- return false;
- }
-
- if( bRedirect )
- {
- AString Location;
- // Search for "Location:"
- bool bFoundLocation = false;
- while( !bFoundLocation && ss.good() )
- {
- char c = 0;
- while( c != '\n' )
- {
- ss.get( c );
- }
- AString Name;
- ss >> Name;
- if (Name.compare("Location:") == 0)
- {
- bFoundLocation = true;
- ss >> Location;
- }
- }
- if (!bFoundLocation)
- {
- LOGERROR("cAuthenticator: received invalid redirection from auth server \"%s\" for user \"%s\", kicking user.", a_Server.c_str(), a_UserName.c_str());
- return false;
- }
-
- Location = Location.substr(strlen("http://"), std::string::npos); // Strip http://
- std::string Server = Location.substr( 0, Location.find( "/" ) ); // Only leave server address
- Location = Location.substr( Server.length(), std::string::npos);
- return AuthFromAddress(Server, Location, a_UserName, a_Level + 1);
- }
-
- if (!bOK)
- {
- LOGERROR("cAuthenticator: received an error from auth server \"%s\" for user \"%s\", kicking user.", a_Server.c_str(), a_UserName.c_str());
- return false;
- }
-
- // Header says OK, so receive the rest.
- // Go past header, double \n means end of headers
- char c = 0;
- while (ss.good())
- {
- while (c != '\n')
- {
- ss.get(c);
- }
- ss.get(c);
- if( c == '\n' || c == '\r' || ss.peek() == '\r' || ss.peek() == '\n' )
- break;
- }
- if (!ss.good())
- {
- LOGERROR("cAuthenticator: error while parsing response body from auth server \"%s\" for user \"%s\", kicking user.", a_Server.c_str(), a_UserName.c_str());
- return false;
- }
-
- std::string Result;
- ss >> Result;
- LOGINFO("Got result: %s", Result.c_str());
- if (Result.compare("YES") == 0)
- {
- LOGINFO("Result was \"YES\", so player is authenticated!");
- return true;
- }
- LOGINFO("Result was \"%s\", so player is NOT authenticated!", Result.c_str());
- return false;
-}
-
-
-
-
+
+#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
+
+#include "cAuthenticator.h"
+#include "cBlockingTCPLink.h"
+#include "cRoot.h"
+#include "cServer.h"
+
+#include "../iniFile/iniFile.h"
+
+#include <sstream>
+
+
+
+
+
+#define DEFAULT_AUTH_SERVER "session.minecraft.net"
+#define DEFAULT_AUTH_ADDRESS "/game/checkserver.jsp?user=%USERNAME%&serverId=%SERVERID%"
+#define MAX_REDIRECTS 10
+
+
+
+
+
+cAuthenticator::cAuthenticator(void) :
+ super("cAuthenticator"),
+ m_Server(DEFAULT_AUTH_SERVER),
+ m_Address(DEFAULT_AUTH_ADDRESS),
+ m_ShouldAuthenticate(true)
+{
+ ReadINI();
+}
+
+
+
+
+
+cAuthenticator::~cAuthenticator()
+{
+ Stop();
+}
+
+
+
+
+
+/// Read custom values from INI
+void cAuthenticator::ReadINI(void)
+{
+ cIniFile IniFile("settings.ini");
+ if (!IniFile.ReadFile())
+ {
+ return;
+ }
+
+ m_Server = IniFile.GetValue("Authentication", "Server");
+ m_Address = IniFile.GetValue("Authentication", "Address");
+ m_ShouldAuthenticate = IniFile.GetValueB("Authentication", "Authenticate", true);
+ bool bSave = false;
+
+ if (m_Server.length() == 0)
+ {
+ m_Server = DEFAULT_AUTH_SERVER;
+ IniFile.SetValue("Authentication", "Server", m_Server);
+ bSave = true;
+ }
+ if (m_Address.length() == 0)
+ {
+ m_Address = DEFAULT_AUTH_ADDRESS;
+ IniFile.SetValue("Authentication", "Address", m_Address);
+ bSave = true;
+ }
+
+ if (bSave)
+ {
+ IniFile.SetValueB("Authentication", "Authenticate", m_ShouldAuthenticate);
+ IniFile.WriteFile();
+ }
+}
+
+
+
+
+
+/// Queues a request for authenticating a user. If the auth fails, the user is kicked
+void cAuthenticator::Authenticate(int a_ClientID, const AString & a_UserName, const AString & a_ServerHash)
+{
+ if (!m_ShouldAuthenticate)
+ {
+ cRoot::Get()->AuthenticateUser(a_ClientID);
+ return;
+ }
+
+ cCSLock Lock(m_CS);
+ m_Queue.push_back(cUser(a_ClientID, a_UserName, a_ServerHash));
+ m_QueueNonempty.Set();
+}
+
+
+
+
+
+void cAuthenticator::Stop(void)
+{
+ m_ShouldTerminate = true;
+ m_QueueNonempty.Set();
+ Wait();
+}
+
+
+
+
+
+void cAuthenticator::Execute(void)
+{
+ for (;;)
+ {
+ cCSLock Lock(m_CS);
+ while (!m_ShouldTerminate && (m_Queue.size() == 0))
+ {
+ cCSUnlock Unlock(Lock);
+ m_QueueNonempty.Wait();
+ }
+ if (m_ShouldTerminate)
+ {
+ return;
+ }
+ ASSERT(!m_Queue.empty());
+
+ int ClientID = m_Queue.front().mClientID;
+ AString UserName = m_Queue.front().mName;
+ AString ActualAddress = m_Address;
+ ReplaceString(ActualAddress, "%USERNAME%", UserName);
+ ReplaceString(ActualAddress, "%SERVERID%", cRoot::Get()->GetServer()->GetServerID());
+ m_Queue.pop_front();
+ Lock.Unlock();
+
+ if (!AuthFromAddress(m_Server, ActualAddress, UserName))
+ {
+ cRoot::Get()->KickUser(ClientID, "Failed to authenticate account!");
+ }
+ else
+ {
+ cRoot::Get()->AuthenticateUser(ClientID);
+ }
+ } // for (-ever)
+}
+
+
+
+
+
+bool cAuthenticator::AuthFromAddress(const AString & a_Server, const AString & a_Address, const AString & a_UserName, int a_Level /* = 1 */)
+{
+ // Returns true if the user authenticated okay, false on error; iLevel is the recursion deptht (bails out if too deep)
+
+ cBlockingTCPLink Link;
+ if (!Link.Connect(a_Server.c_str(), 80))
+ {
+ LOGERROR("cAuthenticator: cannot connect to auth server \"%s\", kicking user \"%s\"", a_Server.c_str(), a_Server.c_str());
+ return false;
+ }
+
+ Link.SendMessage( AString( "GET " + a_Address + " HTTP/1.0\r\n\r\n" ).c_str());
+ AString DataRecvd;
+ Link.ReceiveData(DataRecvd);
+ Link.CloseSocket();
+
+ std::stringstream ss(DataRecvd);
+
+ // Parse the data received:
+ std::string temp;
+ ss >> temp;
+ bool bRedirect = false;
+ bool bOK = false;
+ if ((temp.compare("HTTP/1.1") == 0) || (temp.compare("HTTP/1.0") == 0))
+ {
+ int code;
+ ss >> code;
+ if (code == 302)
+ {
+ // redirect blabla
+ LOGINFO("Need to redirect!");
+ if (a_Level > MAX_REDIRECTS)
+ {
+ LOGERROR("cAuthenticator: received too many levels of redirection from auth server \"%s\" for user \"%s\", bailing out and kicking the user", a_Server.c_str(), a_UserName.c_str());
+ return false;
+ }
+ bRedirect = true;
+ }
+ else if (code == 200)
+ {
+ LOGINFO("Got 200 OK :D");
+ bOK = true;
+ }
+ }
+ else
+ {
+ LOGERROR("cAuthenticator: cannot parse auth reply from server \"%s\" for user \"%s\", kicking the user.", a_Server.c_str(), a_UserName.c_str());
+ return false;
+ }
+
+ if( bRedirect )
+ {
+ AString Location;
+ // Search for "Location:"
+ bool bFoundLocation = false;
+ while( !bFoundLocation && ss.good() )
+ {
+ char c = 0;
+ while( c != '\n' )
+ {
+ ss.get( c );
+ }
+ AString Name;
+ ss >> Name;
+ if (Name.compare("Location:") == 0)
+ {
+ bFoundLocation = true;
+ ss >> Location;
+ }
+ }
+ if (!bFoundLocation)
+ {
+ LOGERROR("cAuthenticator: received invalid redirection from auth server \"%s\" for user \"%s\", kicking user.", a_Server.c_str(), a_UserName.c_str());
+ return false;
+ }
+
+ Location = Location.substr(strlen("http://"), std::string::npos); // Strip http://
+ std::string Server = Location.substr( 0, Location.find( "/" ) ); // Only leave server address
+ Location = Location.substr( Server.length(), std::string::npos);
+ return AuthFromAddress(Server, Location, a_UserName, a_Level + 1);
+ }
+
+ if (!bOK)
+ {
+ LOGERROR("cAuthenticator: received an error from auth server \"%s\" for user \"%s\", kicking user.", a_Server.c_str(), a_UserName.c_str());
+ return false;
+ }
+
+ // Header says OK, so receive the rest.
+ // Go past header, double \n means end of headers
+ char c = 0;
+ while (ss.good())
+ {
+ while (c != '\n')
+ {
+ ss.get(c);
+ }
+ ss.get(c);
+ if( c == '\n' || c == '\r' || ss.peek() == '\r' || ss.peek() == '\n' )
+ break;
+ }
+ if (!ss.good())
+ {
+ LOGERROR("cAuthenticator: error while parsing response body from auth server \"%s\" for user \"%s\", kicking user.", a_Server.c_str(), a_UserName.c_str());
+ return false;
+ }
+
+ std::string Result;
+ ss >> Result;
+ LOGINFO("Got result: %s", Result.c_str());
+ if (Result.compare("YES") == 0)
+ {
+ LOGINFO("Result was \"YES\", so player is authenticated!");
+ return true;
+ }
+ LOGINFO("Result was \"%s\", so player is NOT authenticated!", Result.c_str());
+ return false;
+}
+
+
+
+