Przeglądaj źródła

do not require an account to play

Kolja Strohm 2 lat temu
rodzic
commit
aa84d01aec
3 zmienionych plików z 129 dodań i 52 usunięć
  1. 67 0
      FactoryCraft/Game.cpp
  2. 6 0
      FactoryCraft/Game.h
  3. 56 52
      FactoryCraft/Server.cpp

+ 67 - 0
FactoryCraft/Game.cpp

@@ -11,6 +11,15 @@
 
 using namespace Framework;
 
+char* randomKey(int& len)
+{
+	len = 1024 + (int)(((double)rand() / RAND_MAX - 0.5) * 512);
+	char* key = new char[len];
+	for (int i = 0; i < len; i++)
+		key[i] = (char)((((double)rand() / RAND_MAX) * 254) + 1);
+	return key;
+}
+
 GameClient::GameClient(Player* zPlayer, FCKlient* client)
 	: Thread(),
 	zPlayer(zPlayer),
@@ -543,6 +552,64 @@ bool Game::requestWorldUpdate(WorldUpdate* update)
 	return 1;
 }
 
+bool Game::checkPlayer(Framework::Text name, Framework::Text secret)
+{
+	Datei pFile;
+	pFile.setDatei(path + "/player/" + name + ".key");
+	if (!pFile.existiert())
+	{
+		if (!secret.getLength())
+			return 1;
+		else
+		{
+			std::cout << "player " << name.getText() << " tryed to connect with an invalid secret.\n";
+			return 0;
+		}
+	}
+	pFile.open(Datei::Style::lesen);
+	char* buffer = new char[(int)pFile.getSize()];
+	pFile.lese(buffer, (int)pFile.getSize());
+	bool eq = 1;
+	int sLen = secret.getLength();
+	for (int i = 0; i < pFile.getSize(); i++) // !!SECURITY!! runtime should not be dependent on the position of the first unequal character in the secret
+		eq &= buffer[i] == (sLen > i ? secret[i] : ~buffer[i]);
+	delete[] buffer;
+	pFile.close();
+	if (!eq)
+	{
+		std::cout << "player " << name.getText() << " tryed to connect with an invalid secret.\n";
+	}
+	return eq;
+}
+
+bool Game::existsPlayer(Framework::Text name)
+{
+	Datei pFile;
+	pFile.setDatei(path + "/player/" + name + ".key");
+	return pFile.existiert();
+}
+
+Framework::Text Game::createPlayer(Framework::Text name)
+{
+	Datei pFile;
+	pFile.setDatei(path + "/player/" + name + ".key");
+	if (!pFile.existiert())
+	{
+		pFile.erstellen();
+		int keyLen;
+		char* key = randomKey(keyLen);
+		pFile.open(Datei::Style::schreiben);
+		pFile.schreibe(key, keyLen);
+		pFile.close();
+		Text res = "";
+		for (int i = 0; i < keyLen; i++)
+			res.append(key[i]);
+		delete[] key;
+		return res;
+	}
+	return "";
+}
+
 GameClient* Game::addPlayer(FCKlient* client, Framework::Text name)
 {
 	cs.lock();

+ 6 - 0
FactoryCraft/Game.h

@@ -19,6 +19,8 @@
 
 class FCKlient;
 
+char* randomKey(int& len);
+
 class GameClient : public Framework::Thread
 {
 private:
@@ -90,6 +92,7 @@ private:
 	void thread() override;
 
 	Game(Framework::Text name, Framework::Text worldsDir);
+	
 public:
 	~Game();
 	void initialize();
@@ -99,6 +102,9 @@ public:
 	void broadcastMessage(NetworkMessage* response);
 	void sendMessage(NetworkMessage* response, Entity* zTargetPlayer);
 	bool requestWorldUpdate(WorldUpdate* update);
+	bool checkPlayer(Framework::Text name, Framework::Text secret);
+	bool existsPlayer(Framework::Text name);
+	Framework::Text createPlayer(Framework::Text name);
 	GameClient* addPlayer(FCKlient* client, Framework::Text name);
 	bool doesChunkExist(int x, int y, int dimension);
 	bool isChunkLoaded(int x, int y, int dimension) const;

+ 56 - 52
FactoryCraft/Server.cpp

@@ -167,15 +167,6 @@ int FactoryCraftServer::getUnencryptedPort() const
 	return server->getPort();
 }
 
-char* randomKey(int& len)
-{
-	len = 1024 + (int)(((double)rand() / RAND_MAX - 0.5) * 512);
-	char* key = new char[len];
-	for (int i = 0; i < len; i++)
-		key[i] = (char)(((double)rand() / RAND_MAX) * 256);
-	return key;
-}
-
 // Inhalt der LSKlient aus LoginServer.h
 // Konstruktor
 FCKlient::FCKlient(SSLSKlient* klient, FactoryCraftServer* ls)
@@ -278,51 +269,39 @@ void FCKlient::thread()
 			{
 			case 1: // Klient identifikation
 			{
-				int accountId = 0;
-				klient->getNachricht((char*)&accountId, 4);
-				unsigned char secretLength = 0;
-				klient->getNachricht((char*)&secretLength, 1);
-				char* secret = new char[secretLength + 1];
-				klient->getNachricht(secret, (int)secretLength);
-				secret[secretLength] = 0;
-				Text data = "{\"account_id\":";
-				data += accountId;
-				data += ", \"secret\": \"";
-				data += secret;
-				data += "\"}";
-				bool ok = false;
-				HTTP::Answer* answer = HTTP::PostRequest("/game_client/api/verify_client.php", "koljastrohm-games.com", data, "application/json", 443, true).execute();
-				if (answer->getStatusCode() == 200)
+				char len;
+				klient->getNachricht(&len, 1);
+				char* name = new char[len + 1];
+				klient->getNachricht(name, len);
+				name[(int)len] = 0;
+				unsigned short sLen;
+				klient->getNachricht((char*)&sLen, 2);
+				char* secret = new char[sLen + 1];
+				klient->getNachricht(secret, sLen);
+				secret[sLen] = 0;
+				if (!Game::INSTANCE->checkPlayer(name, secret))
 				{
-					JSON::JSONObject obj(answer->getData());
-					if (obj.hasValue("verified"))
-					{
-						JSON::JSONValue* value = obj.getValue("verified");
-						if (value->getType() == JSON::JSONType::BOOLEAN)
-						{
-							if (((JSON::JSONBool*)value)->getBool())
-							{
-								this->accountId = accountId;
-								if (zGameClient)
-								{
-									zGameClient->logout();
-									zGameClient = (GameClient*)zGameClient->release();
-								}
-								klient->sende("\1", 1);
-								klient->sende((char*)&authKeyLen, 4);
-								klient->sende(authKey, authKeyLen);
-								int port = ls->getUnencryptedPort();
-								klient->sende((char*)&port, 4);
-								ok = true;
-							}
-						}
-						value->release();
-					}
-				}
-				answer->release();
-				delete[]secret;
-				if (!ok)
 					klient->sende("\0", 1);
+					delete[] name;
+					delete[] secret;
+					break;
+				}
+				if (!Game::INSTANCE->existsPlayer(name))
+				{
+					Text secret = Game::INSTANCE->createPlayer(name);
+					klient->sende("\2", 1);
+					short len = (short)secret.getLength();
+					klient->sende((char*)&len, 2);
+					klient->sende(secret.getText(), len);
+				}
+				else
+				{
+					klient->sende("\1", 1);
+				}
+				klient->sende((char*)&authKeyLen, 4);
+				klient->sende(authKey, authKeyLen);
+				delete[] name;
+				delete[] secret;
 				break;
 			}
 			case 2: // Verbindungsende
@@ -334,6 +313,30 @@ void FCKlient::thread()
 				}
 				klient->sende("\1", 1);
 				break;
+			case 3: // ping
+				klient->sende("\1", 1);
+				break;
+			case 4: // check player name valid
+			{
+				klient->sende("\1", 1);
+				char len;
+				klient->getNachricht(&len, 1);
+				char* name = new char[len + 1];
+				klient->getNachricht(name, len);
+				name[(int)len] = 0;
+				short sLen;
+				klient->getNachricht((char*)&sLen, 2);
+				char* secret = new char[sLen + 1];
+				klient->getNachricht(secret, sLen);
+				secret[sLen] = 0;
+				char res = 0;
+				if (Game::INSTANCE->checkPlayer(name, secret))
+					res = 1;
+				klient->sende(&res, 1);
+				delete[] name;
+				delete[] secret;
+				break;
+			}
 			default:
 				br = 1;
 				break;
@@ -371,4 +374,5 @@ bool FCKlient::matchAuthKey(char* key, int len) const
 			return 0;
 	}
 	return 1;
+	an account to play
 }