//Login. private static async Task LoginStartHandler(byte[] data, MemoryStream stream, MinecraftClientConnection connection) { Logger.LogMessage("Login Start"); //Grab username. connection.connectingUsername = await ReadStringAsync(stream); if (connection.config.OfflineMode) { connection.WriteString(GetKickMessage(await AuthenticationManager.GenerateToken(connection.connectingUsername, true))); connection.Flush(0); connection.client.Close(); return; } //Generate encryption data needed for connection. connection.encryptionState = new FakeServerEncryptionState(); connection.encryptionState.GenerateKeyPair(); var keyTokenPair = connection.encryptionState.GeneratePublicKeyAndToken(); connection.randomToken = keyTokenPair.randomToken; //Server ID (useless) connection.WriteString(""); //Public Key. connection.WriteVarInt(keyTokenPair.publicKey.Length); connection.Write(keyTokenPair.publicKey); //Token. connection.WriteVarInt(keyTokenPair.randomToken.Length); connection.Write(keyTokenPair.randomToken); connection.Flush(1); }
//Status. private static async Task StatusRequestHandler(byte[] data, MemoryStream stream, MinecraftClientConnection connection) { Logger.LogMessage("Status Request"); connection.WriteString(serverStatusResponse); connection.Flush(0); }
private static async Task ServerAuthRequestHandler(byte[] data, MemoryStream stream, MinecraftClientConnection connection) { Logger.LogMessage("Server Auth Request"); //Read secret. int secretLength = await ReadVarIntAsync(stream); byte[] secret = new byte[secretLength]; ReadBytesAsync(stream, secret).Wait(); //Verify token. int encryptedTokenLength = await ReadVarIntAsync(stream); byte[] encryptedToken = new byte[encryptedTokenLength]; ReadBytesAsync(stream, encryptedToken).Wait(); //Decrypt shared key from secret. connection.sharedKey = connection.encryptionState.Decrypt(secret); //Decrypt the token. byte[] token = connection.encryptionState.Decrypt(encryptedToken); if (!token.SequenceEqual(connection.randomToken)) { //Failed to verify token. //Close connection. connection.isRunning = false; return; } //Get the ID of the server the client joined, from the public key. string serverID = MinecraftShaDigest(connection.sharedKey.Concat(connection.encryptionState.publicKey).ToArray()); //Verify the player has joined the server they say they have, using Mojang's auth. FiguraAuthServer.JoinedResponse hasJoinedResponse = await FiguraAuthServer.HasJoined(connection.connectingUsername, serverID); if (hasJoinedResponse == null) { //Player hasn't actually joined this server, auth failed, close connection. connection.isRunning = false; return; } //Auth success!!! Logger.LogMessage("Auth Complete for user " + connection.connectingUsername); //Turn on encryption connection.enableEncryption = true; //Respond with JWT in kick message. connection.WriteString(GetKickMessage(await AuthenticationManager.GenerateToken(connection.connectingUsername, false))); connection.Flush(0); connection.client.Close(); }