Exemple #1
0
 /// <summary> Removes a given IP address from the ban list (if present). </summary>
 /// <param name="address"> Address to unban. </param>
 /// <param name="raiseEvents"> Whether to raise RemovingIPBan and RemovedIPBan events. </param>
 /// <returns> True if IP was unbanned.
 /// False if it was not banned in the first place, or if it was cancelled by an event. </returns>
 public static bool Remove([NotNull] IPAddress address, bool raiseEvents)
 {
     if (address == null)
     {
         throw new ArgumentNullException("address");
     }
     lock ( BanListLock ) {
         if (!Bans.ContainsKey(address.ToString()))
         {
             return(false);
         }
         IPBanInfo info = Bans[address.ToString()];
         if (raiseEvents)
         {
             if (RaiseRemovingIPBanEvent(info))
             {
                 return(false);
             }
         }
         if (Bans.Remove(address.ToString()))
         {
             if (raiseEvents)
             {
                 RaiseRemovedIPBanEvent(info);
             }
             Save();
             return(true);
         }
         else
         {
             return(false);
         }
     }
 }
Exemple #2
0
        internal static IPBanInfo LoadFormat2([NotNull] string[] fields)
        {
            if (fields == null)
            {
                throw new ArgumentNullException("fields");
            }
            if (fields.Length != 8)
            {
                throw new ArgumentException("Unexpected field count", "fields");
            }
            IPBanInfo info = new IPBanInfo {
                Address  = IPAddress.Parse(fields[0]),
                BannedBy = PlayerInfo.Unescape(fields[1])
            };

            fields[2].ToDateTime(ref info.BanDate);
            if (fields[3].Length > 0)
            {
                info.BanReason = PlayerInfo.Unescape(fields[3]);
            }
            if (fields[4].Length > 0)
            {
                info.PlayerName = PlayerInfo.Unescape(fields[4]);
            }

            Int32.TryParse(fields[5], out info.Attempts);
            info.LastAttemptName = PlayerInfo.Unescape(fields[6]);
            fields[7].ToDateTime(ref info.LastAttemptDate);

            return(info);
        }
Exemple #3
0
 /// <summary> Adds a new IP Ban. </summary>
 /// <param name="ban"> Ban information </param>
 /// <param name="raiseEvent"> Whether AddingIPBan and AddedIPBan events should be raised. </param>
 /// <returns> True if ban was added, false if it was already on the list </returns>
 public static bool Add([NotNull] IPBanInfo ban, bool raiseEvent)
 {
     if (ban == null)
     {
         throw new ArgumentNullException("ban");
     }
     lock ( BanListLock ) {
         if (Bans.ContainsKey(ban.Address.ToString()))
         {
             return(false);
         }
         if (raiseEvent)
         {
             if (RaiseAddingIPBanEvent(ban))
             {
                 return(false);
             }
             Bans.Add(ban.Address.ToString(), ban);
             RaiseAddedIPBanEvent(ban);
         }
         else
         {
             Bans.Add(ban.Address.ToString(), ban);
         }
         Save();
         return(true);
     }
 }
Exemple #4
0
        static void RaiseRemovedIPBanEvent([NotNull] IPBanInfo info)
        {
            if (info == null)
            {
                throw new ArgumentNullException("info");
            }
            var h = RemovedIPBan;

            if (h != null)
            {
                h(null, new IPBanEventArgs(info));
            }
        }
Exemple #5
0
        static bool RaiseRemovingIPBanEvent([NotNull] IPBanInfo info)
        {
            if (info == null)
            {
                throw new ArgumentNullException("info");
            }
            var h = RemovingIPBan;

            if (h == null)
            {
                return(false);
            }
            var e = new IPBanCancellableEventArgs(info);

            h(null, e);
            return(e.Cancel);
        }
Exemple #6
0
        internal static IPBanInfo LoadFormat0([NotNull] string[] fields, bool convertDatesToUtc)
        {
            if (fields == null)
            {
                throw new ArgumentNullException("fields");
            }
            if (fields.Length != 8)
            {
                throw new ArgumentException("Unexpected field count", "fields");
            }
            IPBanInfo info = new IPBanInfo {
                Address  = IPAddress.Parse(fields[0]),
                BannedBy = PlayerInfo.UnescapeOldFormat(fields[1])
            };

            DateTimeUtil.TryParseLocalDate(fields[2], out info.BanDate);
            info.BanReason = PlayerInfo.UnescapeOldFormat(fields[3]);
            if (fields[4].Length > 1)
            {
                info.PlayerName = PlayerInfo.UnescapeOldFormat(fields[4]);
            }

            info.Attempts        = Int32.Parse(fields[5]);
            info.LastAttemptName = PlayerInfo.UnescapeOldFormat(fields[6]);
            DateTimeUtil.TryParseLocalDate(fields[7], out info.LastAttemptDate);

            if (convertDatesToUtc)
            {
                if (info.BanDate != DateTime.MinValue)
                {
                    info.BanDate = info.BanDate.ToUniversalTime();
                }
                if (info.LastAttemptDate != DateTime.MinValue)
                {
                    info.LastAttemptDate = info.LastAttemptDate.ToUniversalTime();
                }
            }

            return(info);
        }
Exemple #7
0
        /// <summary> Bans given IP address and all accounts on that IP. All players from IP are kicked.
        /// Throws PlayerOpException on problems. </summary>
        /// <param name="targetAddress"> IP address that is being banned. </param>
        /// <param name="player"> Player who is banning. </param>
        /// <param name="reason"> Reason for ban. May be empty, if permitted by server configuration. </param>
        /// <param name="announce"> Whether ban should be publicly announced on the server. </param>
        /// <param name="raiseEvents"> Whether AddingIPBan, AddedIPBan, BanChanging, and BanChanged events should be raised. </param>
        public static void BanAll([NotNull] this IPAddress targetAddress, [NotNull] Player player, [CanBeNull] string reason,
                                  bool announce, bool raiseEvents)
        {
            if (targetAddress == null)
            {
                throw new ArgumentNullException("targetAddress");
            }
            if (player == null)
            {
                throw new ArgumentNullException("player");
            }
            if (reason != null && reason.Trim().Length == 0)
            {
                reason = null;
            }

            if (!player.Can(Permission.Ban, Permission.BanIP, Permission.BanAll))
            {
                PlayerOpException.ThrowPermissionMissing(player, null, "ban-all",
                                                         Permission.Ban, Permission.BanIP, Permission.BanAll);
            }

            // Check if player is trying to ban self
            if (targetAddress.Equals(player.IP) && !player.IsSuper())
            {
                PlayerOpException.ThrowCannotTargetSelf(player, null, "ban-all");
            }

            // Check if a non-bannable address was given (0.0.0.0 or 255.255.255.255)
            if (targetAddress.Equals(IPAddress.None) || targetAddress.Equals(IPAddress.Any))
            {
                PlayerOpException.ThrowInvalidIP(player, null, targetAddress);
            }

            // Check if any high-ranked players use this address
            PlayerInfo[] allPlayersOnIP        = PlayerDB.FindPlayers(targetAddress);
            PlayerInfo   infoWhomPlayerCantBan = allPlayersOnIP.FirstOrDefault(info => !player.Can(Permission.Ban, info.Rank));

            if (infoWhomPlayerCantBan != null)
            {
                PlayerOpException.ThrowPermissionLimitIP(player, infoWhomPlayerCantBan, targetAddress);
            }

            PlayerOpException.CheckBanReason(reason, player, null, false);
            bool somethingGotBanned = false;

            // Ban the IP
            if (!Contains(targetAddress))
            {
                IPBanInfo banInfo = new IPBanInfo(targetAddress, null, player.Name, reason);
                if (Add(banInfo, raiseEvents))
                {
                    Logger.Log(LogType.UserActivity,
                               "{0} banned {1} (BanAll {1}). Reason: {2}",
                               player.Name, targetAddress, reason ?? "");

                    // Announce ban on the server
                    if (announce)
                    {
                        var can = Server.Players.Can(Permission.ViewPlayerIPs);
                        can.Message("&W{0} was banned by {1}", MessageType.Announcement, targetAddress, player.ClassyName);
                        var cant = Server.Players.Cant(Permission.ViewPlayerIPs);
                        cant.Message("&WAn IP was banned by {0}", MessageType.Announcement, player.ClassyName);
                    }
                    somethingGotBanned = true;
                }
            }

            // Ban individual players
            foreach (PlayerInfo targetAlt in allPlayersOnIP)
            {
                if (targetAlt.BanStatus != BanStatus.NotBanned)
                {
                    continue;
                }

                // Raise PlayerInfo.BanChanging event
                PlayerInfoBanChangingEventArgs e = new PlayerInfoBanChangingEventArgs(targetAlt, player, false, reason, announce);
                if (raiseEvents)
                {
                    PlayerInfo.RaiseBanChangingEvent(e);
                    if (e.Cancel)
                    {
                        continue;
                    }
                    reason = e.Reason;
                }

                // Do the ban
                if (targetAlt.ProcessBan(player, player.Name, reason))
                {
                    if (raiseEvents)
                    {
                        PlayerInfo.RaiseBanChangedEvent(e);
                    }

                    // Log and announce ban
                    Logger.Log(LogType.UserActivity,
                               "{0} banned {1} (BanAll {2}). Reason: {3}",
                               player.Name, targetAlt.Name, targetAddress, reason ?? "");
                    if (announce)
                    {
                        Server.Message("&WPlayer {0}&W was banned by {1}&W (BanAll)",
                                       targetAlt.ClassyName, player.ClassyName);
                    }
                    somethingGotBanned = true;
                }
            }

            // If no one ended up getting banned, quit here
            if (!somethingGotBanned)
            {
                PlayerOpException.ThrowNoOneToBan(player, null, targetAddress);
            }

            // Announce BanAll reason towards the end of all bans
            if (announce && ConfigKey.AnnounceKickAndBanReasons.Enabled() && reason != null)
            {
                Server.Message("&WBanAll reason: {0}", reason);
            }

            // Kick all players from IP
            Player[] targetsOnline = Server.Players.FromIP(targetAddress).ToArray();
            if (targetsOnline.Length <= 0)
            {
                return;
            }
            var kickReason = reason != null ? $"Banned by {player.Name}: {reason}" : $"Banned by {player.Name}";

            foreach (var t in targetsOnline)
            {
                t.Kick(kickReason, LeaveReason.BanAll);
            }
        }
Exemple #8
0
        /// <summary> Bans given IP address. All players from IP are kicked. If an associated PlayerInfo is known,
        /// use a different overload of this method instead. Throws PlayerOpException on problems. </summary>
        /// <param name="targetAddress"> IP address that is being banned. </param>
        /// <param name="player"> Player who is banning. </param>
        /// <param name="reason"> Reason for ban. May be empty, if permitted by server configuration. </param>
        /// <param name="announce"> Whether ban should be publicly announced on the server. </param>
        /// <param name="raiseEvents"> Whether AddingIPBan and AddedIPBan events should be raised. </param>
        public static void BanIP([NotNull] this IPAddress targetAddress, [NotNull] Player player, [CanBeNull] string reason,
                                 bool announce, bool raiseEvents)
        {
            if (targetAddress == null)
            {
                throw new ArgumentNullException("targetAddress");
            }
            if (player == null)
            {
                throw new ArgumentNullException("player");
            }
            if (reason != null && reason.Trim().Length == 0)
            {
                reason = null;
            }

            // Check if player can ban IPs in general
            if (!player.Can(Permission.Ban, Permission.BanIP))
            {
                PlayerOpException.ThrowPermissionMissing(player, null, "IP-ban", Permission.Ban, Permission.BanIP);
            }

            // Check if a non-bannable address was given (0.0.0.0 or 255.255.255.255)
            if (targetAddress.Equals(IPAddress.None) || targetAddress.Equals(IPAddress.Any))
            {
                PlayerOpException.ThrowInvalidIP(player, null, targetAddress);
            }

            // Check if player is trying to ban self
            if (targetAddress.Equals(player.IP) && !player.IsSuper())
            {
                PlayerOpException.ThrowCannotTargetSelf(player, null, "IP-ban");
            }

            // Check if target is already banned
            IPBanInfo existingBan = Get(targetAddress);

            if (existingBan != null)
            {
                string msg;
                if (player.Can(Permission.ViewPlayerIPs))
                {
                    msg = String.Format("IP address {0} is already banned.", targetAddress);
                }
                else
                {
                    msg = String.Format("Given IP address is already banned.");
                }
                string colorMsg = "&S" + msg;
                throw new PlayerOpException(player, null, PlayerOpExceptionCode.NoActionNeeded, msg, colorMsg);
            }

            // Check if any high-ranked players use this address
            PlayerInfo infoWhomPlayerCantBan = PlayerDB.FindPlayers(targetAddress)
                                               .FirstOrDefault(info => !player.Can(Permission.Ban, info.Rank));

            if (infoWhomPlayerCantBan != null)
            {
                PlayerOpException.ThrowPermissionLimitIP(player, infoWhomPlayerCantBan, targetAddress);
            }

            PlayerOpException.CheckBanReason(reason, player, null, false);

            // Actually ban
            IPBanInfo banInfo = new IPBanInfo(targetAddress, null, player.Name, reason);
            bool      result  = Add(banInfo, raiseEvents);

            if (result)
            {
                Logger.Log(LogType.UserActivity,
                           "{0} banned {1} (BanIP {1}). Reason: {2}",
                           player.Name, targetAddress, reason ?? "");
                if (announce)
                {
                    // Announce ban on the server
                    var can = Server.Players.Can(Permission.ViewPlayerIPs);
                    can.Message("&W{0} was banned by {1}", 0, targetAddress, player.ClassyName);
                    var cant = Server.Players.Cant(Permission.ViewPlayerIPs);
                    cant.Message("&WAn IP was banned by {0}", 0, player.ClassyName);
                    if (ConfigKey.AnnounceKickAndBanReasons.Enabled() && reason != null)
                    {
                        Server.Message("&WBanIP reason: {0}", reason);
                    }
                }

                // Kick all players connected from address
                string kickReason;
                if (reason != null)
                {
                    kickReason = String.Format("IP-Banned by {0}: {1}", player.Name, reason);
                }
                else
                {
                    kickReason = String.Format("IP-Banned by {0}", player.Name);
                }
                foreach (Player other in Server.Players.FromIP(targetAddress))
                {
                    if (other.Info.BanStatus != BanStatus.IPBanExempt)
                    {
                        other.Kick(kickReason, LeaveReason.BanIP);   // TODO: check side effects of not using DoKick
                    }
                }
            }
            else
            {
                // address is already banned
                string msg;
                if (player.Can(Permission.ViewPlayerIPs))
                {
                    msg = String.Format("{0} is already banned.", targetAddress);
                }
                else
                {
                    msg = "Given IP address is already banned.";
                }
                string colorMsg = "&S" + msg;
                throw new PlayerOpException(player, null, PlayerOpExceptionCode.NoActionNeeded, msg, colorMsg);
            }
        }
Exemple #9
0
        internal static void Load()
        {
            if (File.Exists(Paths.IPBanListFileName))
            {
                using (StreamReader reader = File.OpenText(Paths.IPBanListFileName)) {
                    string headerText = reader.ReadLine();
                    if (headerText == null)
                    {
                        Logger.Log(LogType.Warning, "IPBanList.Load: IP ban file is empty.");
                        return;
                    }

                    int version = ParseHeader(headerText);
                    if (version > FormatVersion)
                    {
                        Logger.Log(LogType.Warning,
                                   "IPBanList.Load: Attempting to load unsupported IPBanList format ({0}). Errors may occur.",
                                   version);
                    }
                    else if (version < FormatVersion)
                    {
                        Logger.Log(LogType.Warning,
                                   "IPBanList.Load: Converting IPBanList to a newer format (version {0} to {1}).",
                                   version, FormatVersion);
                    }

                    while (!reader.EndOfStream)
                    {
                        string line = reader.ReadLine();
                        if (line == null)
                        {
                            break;
                        }
                        string[] fields = line.Split(',');
                        if (fields.Length == IPBanInfo.FieldCount)
                        {
                            try {
                                IPBanInfo ban;
                                switch (version)
                                {
                                case 0:
                                    ban = IPBanInfo.LoadFormat0(fields, true);
                                    break;

                                case 1:
                                    ban = IPBanInfo.LoadFormat1(fields);
                                    break;

                                case 2:
                                    ban = IPBanInfo.LoadFormat2(fields);
                                    break;

                                default:
                                    return;
                                }

                                if (ban.Address.Equals(IPAddress.Any) || ban.Address.Equals(IPAddress.None))
                                {
                                    Logger.Log(LogType.Warning,
                                               "IPBanList.Load: Invalid IP address skipped.");
                                }
                                else
                                {
                                    Bans.Add(ban.Address.ToString(), ban);
                                }
                            } catch (IOException ex) {
                                Logger.Log(LogType.Error,
                                           "IPBanList.Load: Error while trying to read from file: {0}", ex.Message);
                            } catch (Exception ex) {
                                Logger.Log(LogType.Error,
                                           "IPBanList.Load: Could not parse a record: {0}", ex.Message);
                            }
                        }
                        else
                        {
                            Logger.Log(LogType.Error,
                                       "IPBanList.Load: Corrupt record skipped ({0} fields instead of {1}): {2}",
                                       fields.Length, IPBanInfo.FieldCount, String.Join(",", fields));
                        }
                    }
                }

                Logger.Log(LogType.Debug,
                           "IPBanList.Load: Done loading IP ban list ({0} records).", Bans.Count);
            }
            else
            {
                Logger.Log(LogType.Warning,
                           "IPBanList.Load: No IP ban file found. Ignore this message if this is your first time running GemsCraft.");
            }
            IsLoaded = true;
        }