예제 #1
0
        private void InitiateVariables()
        {
            Globals.Rand         = new Random();
            Console.Title        = Globals.ProtocolName;
            ServerSettings.Debug = Config.GetProperty("debug", false);
            ServerSettings.DisplayPacketErrors = Config.GetProperty("ShowNetworkErrors", false);
#if DEBUG
            ServerSettings.Debug = true;
#endif
            ServerSettings.MaxPlayers = Config.GetProperty("MaxPlayers", 10);
            ServerSettings.Seed       = Config.GetProperty("Seed", "SharpMC");
            ServerSettings.Motd       = Config.GetProperty("motd", "A SharpMC Powered Server");

            Globals.LevelManager = new LevelManager(LoadLevel());
            Globals.LevelManager.AddLevel("nether", new NetherLevel("nether"));
            ServerSettings.OnlineMode = Config.GetProperty("Online-mode", false);
            Globals.ChatHandler       = new Synchronized <ChatHandler>(new ChatHandler());

            Globals.ServerKey = PacketCryptography.GenerateKeyPair();

            Globals.ClientManager = new ClientManager();

            Globals.ConsolePlayer = new Player(Globals.LevelManager.MainLevel)
            {
                Username = "******",
                Wrapper  = new ClientWrapper(null),
                Uuid     = Guid.NewGuid().ToString(),
                Gamemode = Gamemode.Spectator,
            };
            Globals.ConsolePlayer.Wrapper.Player = Globals.ConsolePlayer;
            Globals.ConsolePlayer.IsOperator     = true;

            Globals.MessageFactory = new MessageFactory();

            Globals.PluginManager = new PluginManager();

            Globals.ServerListener = new BasicListener();

            OperatorLoader.LoadOperators();
        }
예제 #2
0
        private void HandleLogin(int protocol)
        {
            if (Buffer != null)
            {
                var usernameRaw = Buffer.ReadString();
                var username    =
                    new string(usernameRaw.Where(c => char.IsLetter(c) || char.IsPunctuation(c) || char.IsDigit(c)).ToArray());
                //username = Regex.Replace(username, @"[^\u0000-\u007F]", string.Empty);
                var uuid = getUUID(username);

                if (!Globals.Offlinemode)
                {
                    if (Globals.EncryptionEnabled)
                    {
                        Client.PacketMode = PacketMode.Login;
                        Client.Username   = username;
                        new EncryptionRequest(Client)
                        {
                            PublicKey         = PacketCryptography.PublicKeyToAsn1(Globals.ServerKey),
                            VerificationToken = PacketCryptography.GetRandomToken()
                        }.Write();
                        return;
                    }
                    if (!Client.Player.IsAuthenticated())
                    {
                        new LoginSucces(Client)
                        {
                            Username = username, UUID = uuid
                        }.Write();
                        new Disconnect(Client)
                        {
                            Reason = "§4SharpMC\n§fAuthentication failed!"
                        }.Write();
                        return;
                    }
                }

                new LoginSucces(Client)
                {
                    Username = username, UUID = uuid
                }.Write();

                if (Encoding.UTF8.GetBytes(username).Length == 0)
                {
                    new Disconnect(Client)
                    {
                        Reason = "§4SharpMC\n§fSomething went wrong while decoding your username!"
                    }.Write();
                    return;
                }

                //Protocol check!
                if (protocol < Globals.ProtocolVersion)                 //Protocol to old?
                {
                    new Disconnect(Client)
                    {
                        Reason = "§4SharpMC\n§fYour Minecraft version is to old!\nPlease update in order to play!"
                    }
                    .Write();
                    return;
                }

                if (protocol > Globals.ProtocolVersion)                 //Protocol to new?
                {
                    new Disconnect(Client)
                    {
                        Reason =
                            "§4SharpMC\n§fThis server is not yet updated for your version of Minecraft!\nIn order to play you have to use " +
                            Globals.MCProtocolName
                    }.Write();
                    return;
                }

                Client.Player = new Player(Globals.LevelManager.MainLevel)
                {
                    Uuid     = uuid,
                    Username = username,
                    Wrapper  = Client,
                    Gamemode = Globals.LevelManager.MainLevel.DefaultGamemode
                };
                Client.PacketMode = PacketMode.Play;

                new SetCompression(Client).Write();

                new JoinGame(Client)
                {
                    Player = Client.Player
                }.Write();
                new SpawnPosition(Client).Write();
                Client.StartKeepAliveTimer();
                Client.Player.InitializePlayer();
            }
        }
예제 #3
0
        public override void Read()
        {
            if (Buffer == null)
            {
                return;
            }
            var usernameRaw = Buffer.ReadString();
            var username    =
                new string(usernameRaw.Where(c => char.IsLetter(c) || char.IsPunctuation(c) || char.IsDigit(c)).ToArray());

            var uuid = GetUuid(username);

            if (Core.Server.ServerSettings.OnlineMode)
            {
                if (Core.Server.ServerSettings.EncryptionEnabled)
                {
                    Client.PacketMode = PacketMode.Login;
                    Client.Username   = username;
                    new EncryptionRequest(Client)
                    {
                        PublicKey         = PacketCryptography.PublicKeyToAsn1(Globals.ServerKey),
                        VerificationToken = PacketCryptography.GetRandomToken()
                    }.Write();
                    return;
                }
                if (!Client.Player.IsAuthenticated())
                {
                    new Disconnect(Client)
                    {
                        Reason = new ChatText("Authentication failed!", TextColor.Reset)
                    }.Write();
                    return;
                }
            }

            if (Encoding.UTF8.GetBytes(username).Length == 0)
            {
                new Disconnect(Client)
                {
                    Reason = new ChatText("Something went wrong while decoding your username!", TextColor.Reset)
                }.Write();
                return;
            }

            //Protocol check!
            if (Client.Protocol < Globals.ProtocolVersion)             //Protocol to old?
            {
                new Disconnect(Client)
                {
                    Reason = new ChatText("Your Minecraft version is too old!\nPlease update in order to play!", TextColor.Reset)
                }
                .Write();
                return;
            }

            if (Client.Protocol > Globals.ProtocolVersion)             //Protocol to new?
            {
                new Disconnect(Client)
                {
                    Reason =
                        new ChatText("This server is not yet updated for your version of Minecraft!\nIn order to play you have to use " +
                                     Globals.OfficialProtocolName, TextColor.Reset)
                }.Write();
                return;
            }

            new LoginSucces(Client)
            {
                Username = username, Uuid = uuid
            }.Write();

            Client.Player = new Player(Globals.LevelManager.MainLevel)
            {
                Uuid     = uuid,
                Username = username,
                Wrapper  = Client,
                Gamemode = Globals.LevelManager.MainLevel.DefaultGamemode
            };
            Client.PacketMode = PacketMode.Play;

            new SetCompression(Client)
            {
                CompressionLevel = Core.Server.ServerSettings.UseCompression ? Core.Server.ServerSettings.CompressionThreshold : -1
            }.Write();

            new JoinGame(Client)
            {
                Player = Client.Player
            }.Write();
            new SpawnPosition(Client).Write();
            Client.Player.InitializePlayer();
        }
예제 #4
0
        public override void Read()
        {
            if (Buffer != null)
            {
                var length       = Buffer.ReadVarInt();
                var sharedsecret = Buffer.Read(length);

                length = Buffer.ReadVarInt();
                var verifytoken = Buffer.Read(length);

                Client.SharedKey = PacketCryptography.Decrypt(sharedsecret);

                var recv = PacketCryptography.GenerateAES((byte[])Client.SharedKey.Clone());
                var send = PacketCryptography.GenerateAES((byte[])Client.SharedKey.Clone());

                var packetToken = PacketCryptography.Decrypt(verifytoken);

                if (!packetToken.SequenceEqual(PacketCryptography.VerifyToken))
                {
                    //Wrong token! :(
                    ConsoleFunctions.WriteWarningLine("Wrong token!");
                    return;
                }

                Client.Decrypter = recv.CreateDecryptor();
                Client.Encrypter = send.CreateEncryptor();

                Client.EncryptionEnabled = true;
                Client.Player            = new Player(Globals.LevelManager.MainLevel)
                {
                    Uuid     = getUUID(Client.Username),
                    Username = Client.Username,
                    Wrapper  = Client,
                    Gamemode = Globals.LevelManager.MainLevel.DefaultGamemode
                };

                if (Client.Player.IsAuthenticated())
                {
                    new LoginSucces(Client)
                    {
                        Username = Client.Username, UUID = Client.Player.Uuid
                    }.Write();
                    Client.PacketMode = PacketMode.Play;

                    new SetCompression(Client).Write();

                    new JoinGame(Client)
                    {
                        Player = Client.Player
                    }.Write();
                    new SpawnPosition(Client).Write();
                    Client.StartKeepAliveTimer();
                    Client.Player.SendChunksFromPosition();
                }
                else
                {
                    new LoginSucces(Client)
                    {
                        Username = Client.Username, UUID = Client.Player.Uuid
                    }.Write();
                    new Disconnect(Client)
                    {
                        Reason = "Authentication failed! Try restarting your client."
                    }.Write();
                }
            }
        }
예제 #5
0
 public override void Initialize(int length, Stream stream)
 {
     base.Initialize(length, stream);
     VerifyToken = PacketCryptography.GetRandomToken();
     PublicKey   = PacketCryptography.PublicKeyToAsn1(Utils.ServerKey);
 }
예제 #6
0
        public static void Main(string[] args)
        {
            var currentDomain = AppDomain.CurrentDomain;

            currentDomain.UnhandledException += UnhandledException;

            Console.Title = Globals.ProtocolName;

            Config.ConfigFile   = "server.properties";
            Config.InitialValue = new[]
            {
                "#DO NOT REMOVE THIS LINE - SharpMC Config",
                "Port=25565",
                "MaxPlayers=10",
                "LevelType=standard",
                "WorldName=world",
                "Debug=false",
                "Seed=",
                "Motd="
            };
            Config.Check();

            Console.CancelKeyPress += delegate
            {
                ConsoleFunctions.WriteInfoLine("Shutting down...");
                Disconnect.Broadcast("§fServer shutting down...");
                ConsoleFunctions.WriteInfoLine("Disabling plugins...");
                Globals.PluginManager.DisablePlugins();
                ConsoleFunctions.WriteInfoLine("Saving chunks...");
                Globals.LevelManager.MainLevel.SaveChunks();
            };

            ConsoleFunctions.WriteInfoLine("Loading config file...");
            Globals.MaxPlayers = Config.GetProperty("MaxPlayers", 10);
            var   lvltype = Config.GetProperty("LevelType", "Experimental");
            Level lvl;

            switch (lvltype.ToLower())
            {
            case "flatland":
                lvl = new FlatLandLevel(Config.GetProperty("WorldName", "world"));
                break;

            case "standard":
                lvl = new StandardLevel(Config.GetProperty("WorldName", "world"));
                //lvl = new BetterLevel(Config.GetProperty("worldname", "world"));
                break;

            case "anvil":
                lvl = new AnvilLevel(Config.GetProperty("WorldName", "world"));
                break;

            default:
                lvl = new StandardLevel(Config.GetProperty("WorldName", "world"));
                break;
            }
            Globals.LevelManager = new LevelManager(lvl);
            Globals.LevelManager.AddLevel("nether", new NetherLevel("nether"));             //Initiate the 'nether'

            Globals.Seed = Config.GetProperty("Seed", "SharpieCraft");

            Globals.Motd = Config.GetProperty("motd", "");

            Globals.Debug = Config.GetProperty("debug", false);

            ConsoleFunctions.WriteInfoLine("Checking files...");

            if (!Directory.Exists(Globals.LevelManager.MainLevel.LvlName))
            {
                Directory.CreateDirectory(Globals.LevelManager.MainLevel.LvlName);
            }

            ConsoleFunctions.WriteInfoLine("Setting up some variables...");
            Globals.ServerKey = PacketCryptography.GenerateKeyPair();
            Globals.Rand      = new Random();
#if DEBUG
            Globals.Debug = true;
#else
            Globals.Debug = false;
#endif
            ConsoleFunctions.WriteInfoLine("Loading plugins...");
            Globals.PluginManager = new PluginManager();
            Globals.PluginManager.LoadPlugins();

            ConsoleFunctions.WriteInfoLine("Enabling plugins...");
            Globals.PluginManager.EnablePlugins(Globals.LevelManager);

            new Thread(() => new BasicListener().ListenForClients()).Start();
        }
예제 #7
0
        public async Task StartConnectionAsync()
        {
            while (!Cancellation.IsCancellationRequested && this.Tcp.Connected)
            {
                Packet packet = this.Compressed ? await this.GetNextCompressedPacketAsync() : await this.GetNextPacketAsync();

                Packet returnPacket;

                if (this.State == ClientState.Play && packet.PacketData.Length < 1)
                {
                    this.Disconnect();
                }

                switch (this.State)
                {
                case ClientState.Status:     //server ping/list
                    switch (packet.PacketId)
                    {
                    case 0x00:
                        var status = new ServerStatus(OriginServer);
                        await PacketHandler.CreateAsync(new RequestResponse(status), this.MinecraftStream);

                        break;

                    case 0x01:
                        await PacketHandler.CreateAsync(new PingPong(packet.PacketData), this.MinecraftStream);

                        this.Disconnect();
                        break;
                    }
                    break;

                case ClientState.Handshaking:
                    if (packet.PacketId == 0x00)
                    {
                        if (packet == null)
                        {
                            throw new InvalidOperationException();
                        }

                        var handshake = await PacketHandler.CreateAsync(new Handshake(packet.PacketData));

                        var nextState = handshake.NextState;

                        if (nextState != ClientState.Status && nextState != ClientState.Login)
                        {
                            this.Logger.LogDebug($"Client sent unexpected state ({(int)nextState}), forcing it to disconnect");
                            await this.DisconnectAsync(Chat.ChatMessage.Simple("you seem suspicious"));
                        }

                        this.State = nextState;
                        this.Logger.LogMessage($"Handshaking with client (protocol: {handshake.Version}, server: {handshake.ServerAddress}:{handshake.ServerPort})");
                    }
                    else
                    {
                        //Handle legacy ping stuff
                    }
                    break;

                case ClientState.Login:
                    switch (packet.PacketId)
                    {
                    default:
                        this.Logger.LogError("Client in state Login tried to send an unimplemented packet. Forcing it to disconnect.");
                        await this.DisconnectAsync(ChatMessage.Simple("Unknown Packet Id."));

                        break;

                    case 0x00:
                        var loginStart = await PacketHandler.CreateAsync(new LoginStart(packet.PacketData));

                        string username = loginStart.Username;

                        if (Config.MulitplayerDebugMode)
                        {
                            username = $"Player{new Random().Next(1, 999)}";
                            this.Logger.LogDebug($"Overriding username from {loginStart.Username} to {username}");
                        }

                        this.Logger.LogDebug($"Received login request from user {loginStart.Username}");

                        if (this.OriginServer.CheckPlayerOnline(username))
                        {
                            await this.OriginServer.Clients.FirstOrDefault(c => c.Player.Username == username).DisconnectAsync(Chat.ChatMessage.Simple("Logged in from another location"));
                        }

                        if (this.Config.OnlineMode)
                        {
                            var users = await MinecraftAPI.GetUsersAsync(new string[] { loginStart.Username });

                            var uid = users.FirstOrDefault();

                            var uuid = Guid.Parse(uid.Id);
                            this.Player = new Player(uuid, loginStart.Username, this);

                            PacketCryptography.GenerateKeyPair();

                            var pubKey = PacketCryptography.PublicKeyToAsn();

                            this.Token = PacketCryptography.GetRandomToken();

                            returnPacket = await PacketHandler.CreateAsync(new EncryptionRequest(pubKey, this.Token), this.MinecraftStream);

                            break;
                        }

                        this.Player = new Player(Guid.NewGuid(), username, this);
                        await ConnectAsync(this.Player.Uuid);

                        break;

                    case 0x01:
                        var encryptionResponse = await PacketHandler.CreateAsync(new EncryptionResponse(packet.PacketData));

                        JoinedResponse response;

                        this.SharedKey = PacketCryptography.Decrypt(encryptionResponse.SharedSecret);

                        var dec2 = PacketCryptography.Decrypt(encryptionResponse.VerifyToken);

                        var dec2Base64 = Convert.ToBase64String(dec2);

                        var tokenBase64 = Convert.ToBase64String(this.Token);

                        if (!dec2Base64.Equals(tokenBase64))
                        {
                            await this.DisconnectAsync(Chat.ChatMessage.Simple("Invalid token.."));

                            break;
                        }

                        var encodedKey = PacketCryptography.PublicKeyToAsn();

                        var serverId = PacketCryptography.MinecraftShaDigest(SharedKey.Concat(encodedKey).ToArray());

                        response = await MinecraftAPI.HasJoined(this.Player.Username, serverId);

                        if (response is null)
                        {
                            this.Logger.LogWarning($"Failed to auth {this.Player.Username}");
                            await this.DisconnectAsync(Chat.ChatMessage.Simple("Unable to authenticate.."));

                            break;
                        }
                        this.EncryptionEnabled = true;
                        this.MinecraftStream   = new AesStream(this.Tcp.GetStream(), this.SharedKey);

                        await ConnectAsync(new Guid(response.Id));

                        break;

                    case 0x02:
                        // Login Plugin Response
                        break;
                    }
                    break;

                case ClientState.Play:

                    ///this.Logger.LogDebugAsync($"Received Play packet with Packet ID 0x{packet.PacketId.ToString("X")}");

                    await PacketHandler.HandlePlayPackets(packet, this);

                    break;
                }
            }

            Logger.LogMessage($"Disconnected client");

            if (this.IsPlaying)
            {
                await this.OriginServer.Events.InvokePlayerLeave(new PlayerLeaveEventArgs(this));
            }

            this.OriginServer.Broadcast(string.Format(this.Config.LeaveMessage, this.Player.Username));

            this.Player = null;

            if (Tcp.Connected)
            {
                this.Tcp.Close();
            }
        }