public static void RegisterClient(Client client) { Logger.DebugFormat("RegisterConnection: {0}", client.ConnectionId); ConnectedClients[client.ConnectionId] = client; if (client.ServerType == ServerTypes.World) WorldClients[client.ConnectionId] = client; }
private void PacketHandler_0x02_CreateA(Client client, ClientPacket packet) { var name = packet.ReadString8(); var password = packet.ReadString8(); var email = packet.ReadString8(); // This string will contain a client-ready message if the provided password // isn't valid. byte passwordErr = 0x0; if (Game.World.PlayerExists(name)) { client.LoginMessage("That name is unavailable.", 3); } else if (name.Length < 4 || name.Length > 12) { client.LoginMessage("Names must be between 4 to 12 characters long.", 3); } else if (!ValidPassword(password, out passwordErr)) { client.LoginMessage(GetPasswordError(passwordErr), 3); } else if (Regex.IsMatch(name, "^[A-Za-z]{4,12}$")) { client.NewCharacterName = name; client.NewCharacterPassword = HashPassword(password); client.LoginMessage("\0", 0); } else { client.LoginMessage("Names may only contain letters.", 3); } }
public virtual void AcceptConnection() { if (TcpListener.Pending()) { var socket = TcpListener.AcceptSocket(); var client = new Client(socket, this); client.Begin(); } }
public static void DeregisterClient(Client client) { ((IDictionary)ConnectedClients).Remove(client.ConnectionId); // Send a control message to clean up after World users; Lobby and Login handle themselves if (client.ServerType == ServerTypes.World) { ((IDictionary)WorldClients).Remove(client.ConnectionId); // This will also handle removing the user from WorldClients if necessary World.MessageQueue.Add(new HybrasylControlMessage(ControlOpcodes.CleanupUser, client.ConnectionId)); } }
private void PacketHandler_0x4B_RequestNotification(Client client, ClientPacket packet) { var x60 = new ServerPacket(0x60); x60.WriteByte(0x01); x60.WriteUInt16((ushort)Game.Notification.Length); x60.Write(Game.Notification); client.Enqueue(x60); }
// Chart for all error password-related error codes were provided by kojasou@ on // https://github.com/hybrasyl/server/pull/11. private void PacketHandler_0x26_ChangePassword(Client client, ClientPacket packet) { var name = packet.ReadString8(); var currentPass = packet.ReadString8(); // Clientside validation ensures that the same string is typed twice for the new // password, and the new password is only sent to the server once. We can assume // that they matched if 0x26 request is sent from the client. var newPass = packet.ReadString8(); // TODO: REDIS IDatabase cache = World.DatastoreConnection.GetDatabase(); var myPerson = cache.Get(name); if (myPerson == null) { client.LoginMessage(GetPasswordError(0x0E), 0x0E); Logger.DebugFormat("Password change attempt on invalid player `{0}`", name); } var player = JsonConvert.DeserializeObject(myPerson as String) as User; if (player.VerifyPassword(currentPass)) { // Check if the password is valid. byte err = 0x00; if (ValidPassword(newPass, out err)) { player.Password.Hash = HashPassword(newPass); player.Password.LastChanged = DateTime.Now; player.Password.LastChangedFrom = ((IPEndPoint) client.Socket.RemoteEndPoint).Address.ToString(); player.Save(); // Let the user know the good news. client.LoginMessage("Your password has been changed successfully.", 0x0); Logger.InfoFormat("Password successfully changed for `{0}`", name); } else { client.LoginMessage(GetPasswordError(err), err); Logger.ErrorFormat("Invalid new password proposed during password change attempt for `{0}`", name); } } // The current password is incorrect. Don't allow any changes to happen. else { client.LoginMessage(GetPasswordError(0x0F), 0x0F); Logger.ErrorFormat("Invalid current password during password change attempt for `{0}`", name); } }
private void PacketHandler_0x10_ClientJoin(Client client, ClientPacket packet) { var seed = packet.ReadByte(); var keyLength = packet.ReadByte(); var key = packet.Read(keyLength); var name = packet.ReadString8(); var id = packet.ReadUInt32(); var redirect = ExpectedConnections[id]; if (redirect.Matches(name, key, seed)) { ((IDictionary)ExpectedConnections).Remove(id); client.EncryptionKey = key; client.EncryptionSeed = seed; if (redirect.Source is Lobby) { var x60 = new ServerPacket(0x60); x60.WriteByte(0x00); x60.WriteUInt32(Game.NotificationCrc); client.Enqueue(x60); } } }
private void PacketHandler_0x04_CreateB(Client client, ClientPacket packet) { if (string.IsNullOrEmpty(client.NewCharacterName) || string.IsNullOrEmpty(client.NewCharacterPassword)) return; var hairStyle = packet.ReadByte(); var sex = packet.ReadByte(); var hairColor = packet.ReadByte(); if (hairStyle < 1) hairStyle = 1; if (hairStyle > 17) hairStyle = 17; if (hairColor > 13) hairColor = 13; if (sex < 1) sex = 1; if (sex > 2) sex = 2; if (!Game.World.PlayerExists(client.NewCharacterName)) { var newPlayer = new User(); newPlayer.Name = client.NewCharacterName; newPlayer.Sex = (Sex) sex; newPlayer.Location.Direction = Direction.South; newPlayer.Location.MapId = 136; newPlayer.Location.X = 10; newPlayer.Location.Y = 10; newPlayer.HairColor = hairColor; newPlayer.HairStyle = hairStyle; newPlayer.Class = Class.Peasant; newPlayer.Level = 1; newPlayer.Experience = 1; newPlayer.Level = 1; newPlayer.Experience = 0; newPlayer.AbilityExp = 0; newPlayer.Gold = 0; newPlayer.Ability = 0; newPlayer.Hp = 50; newPlayer.Mp = 50; newPlayer.BaseHp = 50; newPlayer.BaseMp = 50; newPlayer.BaseStr = 3; newPlayer.BaseInt = 3; newPlayer.BaseWis = 3; newPlayer.BaseCon = 3; newPlayer.BaseDex = 3; newPlayer.Login.CreatedTime = DateTime.Now; newPlayer.Password.Hash = client.NewCharacterPassword; newPlayer.Password.LastChanged = DateTime.Now; newPlayer.Password.LastChangedFrom = ((IPEndPoint) client.Socket.RemoteEndPoint).Address.ToString(); IDatabase cache = World.DatastoreConnection.GetDatabase(); var myPerson = JsonConvert.SerializeObject(newPlayer); cache.Set(String.Format("{0}:{1}", User.DatastorePrefix, newPlayer.Name), myPerson); // Logger.ErrorFormat("Error saving new player!"); // Logger.ErrorFormat(e.ToString()); // client.LoginMessage("Unknown error. Contact [email protected]", 3); // } client.LoginMessage("\0", 0); } }
private void PacketHandler_0x03_Login(Client client, ClientPacket packet) { var name = packet.ReadString8(); var password = packet.ReadString8(); Logger.DebugFormat("cid {0}: Login request for {1}", client.ConnectionId, name); User loginUser; if (!World.TryGetUser(name, out loginUser)) { client.LoginMessage("That character does not exist", 3); Logger.InfoFormat("cid {0}: attempt to login as nonexistent character {1}", client.ConnectionId, name); } else if (loginUser.VerifyPassword(password)) { Logger.DebugFormat("cid {0}: password verified for {1}", client.ConnectionId, name); if (Game.World.ActiveUsersByName.ContainsKey(name)) { Logger.InfoFormat("cid {0}: {1} logging on again, disconnecting previous connection", client.ConnectionId, name); World.MessageQueue.Add(new HybrasylControlMessage(ControlOpcodes.LogoffUser, name)); } Logger.DebugFormat("cid {0} ({1}): logging in", client.ConnectionId, name); client.LoginMessage("\0", 0); client.SendMessage("Welcome to Hybrasyl!", 3); Logger.DebugFormat("cid {0} ({1}): sending redirect to world", client.ConnectionId, name); var redirect = new Redirect(client, this, Game.World, name, client.EncryptionSeed, client.EncryptionKey); Logger.InfoFormat("cid {0} ({1}): login successful, redirecting to world server", client.ConnectionId, name); client.Redirect(redirect); loginUser.Login.LastLogin = DateTime.Now; loginUser.Login.LastLoginFrom = ((IPEndPoint) client.Socket.RemoteEndPoint).Address.ToString(); loginUser.Save(); } else { Logger.WarnFormat("cid {0} ({1}): password incorrect", client.ConnectionId, name); client.LoginMessage("Incorrect password", 3); loginUser.Login.LastLoginFailure = DateTime.Now; loginUser.Login.LoginFailureCount++; loginUser.Save(); } }
private void ProcessSlashCommands(Client client, ClientPacket packet) { }
public void Encrypt(Client client) { var length = Data.Length - 3; var rand = new Random(); var bRand = (ushort)(rand.Next() % 65277 + 256); var sRand = (byte)(rand.Next() % 155 + 100); var key = (UseDefaultKey) ? client.EncryptionKey : client.GenerateKey(bRand, sRand); for (var i = 0; i < length; i++) { Data[i] ^= key[i % key.Length]; Data[i] ^= SaltTable[client.EncryptionSeed][(i / key.Length) % SaltTable[client.EncryptionSeed].Length]; if ((i / key.Length) % SaltTable[client.EncryptionSeed].Length != Ordinal) { Data[i] ^= SaltTable[client.EncryptionSeed][Ordinal]; } } Data[length] = (byte)(bRand % 256 ^ 0x74); Data[length + 1] = (byte)(sRand ^ 0x24); Data[length + 2] = (byte)((bRand >> 8) % 256 ^ 0x64); }
// Chart for all error password-related error codes were provided by kojasou@ on // https://github.com/hybrasyl/server/pull/11. private void PacketHandler_0x26_ChangePassword(Client client, ClientPacket packet) { var name = packet.ReadString8(); var currentPass = packet.ReadString8(); // Clientside validation ensures that the same string is typed twice for the new // password, and the new password is only sent to the server once. We can assume // that they matched if 0x26 request is sent from the client. var newPass = packet.ReadString8(); using (var ctx = new hybrasylEntities(Constants.ConnectionString)) { var player = ctx.players.Where(p => p.name == name).SingleOrDefault(); // Check that `name` exists. If not, return a message indicating that to the user. if (player == null) { client.LoginMessage(GetPasswordError(0x0E), 0x0E); Logger.DebugFormat("Password change attempt on invalid player `{0}`", name); } // If the player does exist, validate the current and new passwords before updating. else { // Check that the current password is correct and the new password is different // than the current password. if (VerifyPassword(currentPass, player)) { // Check if the password is valid. byte err = 0x00; if (ValidPassword(newPass, out err)) { player.password_hash = HashPassword(newPass); ctx.SaveChanges(); // Let the user know the good news. client.LoginMessage("Your password has been changed successfully.", 0x0); Logger.InfoFormat("Password successfully changed for `{0}`", name); } else { client.LoginMessage(GetPasswordError(err), err); Logger.ErrorFormat("Invalid new password proposed during password change attempt for `{0}`", name); } } // The current password is incorrect. Don't allow any changes to happen. else { client.LoginMessage(GetPasswordError(0x0F), 0x0F); Logger.ErrorFormat("Invalid current password during password change attempt for `{0}`", name); } } } }
private void PacketHandler_0x04_CreateB(Client client, ClientPacket packet) { if (string.IsNullOrEmpty(client.NewCharacterName) || string.IsNullOrEmpty(client.NewCharacterPassword)) return; var hairStyle = packet.ReadByte(); var sex = packet.ReadByte(); var hairColor = packet.ReadByte(); if (hairStyle < 1) hairStyle = 1; if (hairStyle > 17) hairStyle = 17; if (hairColor > 13) hairColor = 13; if (sex < 1) sex = 1; if (sex > 2) sex = 2; if (!Game.World.PlayerExists(client.NewCharacterName)) { using (var ctx = new hybrasylEntities(Constants.ConnectionString)) { player newplayer = new player { name = client.NewCharacterName, password_hash = client.NewCharacterPassword, sex = (Sex) sex, hairstyle = hairStyle, haircolor = hairColor, map_id = 136, map_x = 10, map_y = 10, direction = 1, class_type = 0, level = 1, exp = 0, ab = 0, gold = 0, ab_exp = 0, max_hp = 50, max_mp = 50, cur_hp = 50, cur_mp = 35, str = 3, @int = 3, wis = 3, con = 3, dex = 3, inventory = "[]", equipment = "[]", created_at = DateTime.Now }; try { ctx.players.Add(newplayer); ctx.SaveChanges(); } catch (Exception e) { Logger.ErrorFormat("Error saving new player!"); Logger.ErrorFormat(e.ToString()); client.LoginMessage("Unknown error. Contact [email protected]", 3); } client.LoginMessage("\0", 0); } } }
private void PacketHandler_0x03_Login(Client client, ClientPacket packet) { var name = packet.ReadString8(); var password = packet.ReadString8(); Logger.DebugFormat("cid {0}: Login request for {1}", client.ConnectionId, name); using (var ctx = new hybrasylEntities(Constants.ConnectionString)) { var result = ctx.players.Where(player => player.name == name).SingleOrDefault(); if (result == null) { client.LoginMessage("That character does not exist", 3); Logger.InfoFormat("cid {0}: attempt to login as nonexistent character {1}", client.ConnectionId, name); } else { if (VerifyPassword(password, result)) { Logger.DebugFormat("cid {0}: password verified for {1}", client.ConnectionId, name); if (Game.World.ActiveUsersByName.ContainsKey(name)) { Logger.InfoFormat("cid {0}: {1} logging on again, disconnecting previous connection", client.ConnectionId, name); World.MessageQueue.Add(new HybrasylControlMessage(ControlOpcodes.LogoffUser, name)); } Logger.DebugFormat("cid {0} ({1}): logging in", client.ConnectionId, name); client.LoginMessage("\0", 0); client.SendMessage("Welcome to Hybrasyl!", 3); Logger.DebugFormat("cid {0} ({1}): sending redirect to world", client.ConnectionId, name); var redirect = new Redirect(client, this, Game.World, name, client.EncryptionSeed, client.EncryptionKey); Logger.InfoFormat("cid {0} ({1}): login successful, redirecting to world server", client.ConnectionId, name); client.Redirect(redirect); } else { Logger.WarnFormat("cid {0} ({1}): password incorrect", client.ConnectionId, name); client.LoginMessage("Incorrect password", 3); } } } }
private void PacketHandler_0x68_RequestHomepage(Client client, ClientPacket packet) { var x03 = new ServerPacket(0x66); x03.WriteByte(0x03); x03.WriteString8("http://www.hybrasyl.com"); client.Enqueue(x03); }
public Redirect(Client client, Server source, Server destination, string name, byte seed, byte[] key) { Id = id++; Client = client; Source = source; Destination = destination; Name = name; EncryptionSeed = seed; EncryptionKey = key; }
public void Decrypt(Client client) { var length = Data.Length - 3; var bRand = (ushort)((Data[length + 2] << 8 | Data[length]) ^ 0x7470); var sRand = (byte)(Data[length + 1] ^ 0x23); var key = (UseDefaultKey) ? client.EncryptionKey : client.GenerateKey(bRand, sRand); for (var i = 0; i < length; i++) { Data[i] ^= key[i % key.Length]; Data[i] ^= SaltTable[client.EncryptionSeed][(i / key.Length) % SaltTable[client.EncryptionSeed].Length]; if ((i / key.Length) % SaltTable[client.EncryptionSeed].Length != Ordinal) { Data[i] ^= SaltTable[client.EncryptionSeed][Ordinal]; } } }