IP ban record.
예제 #1
0
        public static IPBanInfo Load(string[] fields)
        {
            IPBanInfo info = new IPBanInfo();

            if (fields == null)
            {
                throw new ArgumentNullException("fields");
            }
            if (fields.Length != 8)
            {
                throw new ArgumentException("Unexpected field count", "fields");
            }

            info.Address  = IPAddress.Parse(fields[0]);
            info.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);
        }
예제 #2
0
        internal static IPBanInfo LoadFormat1([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 = FlatfilePlayerDBProvider.Unescape(fields[1])
            };

            FlatfilePlayerDBProvider.ToDateTimeLegacy(fields[2], out info.BanDate);
            if (fields[3].Length > 0)
            {
                info.BanReason = FlatfilePlayerDBProvider.Unescape(fields[3]);
            }
            if (fields[4].Length > 0)
            {
                info.PlayerName = FlatfilePlayerDBProvider.Unescape(fields[4]);
            }

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

            return(info);
        }
예제 #3
0
        static bool RaiseRemovingIPBanEvent([NotNull] IPBanInfo info)
        {
            var e = new IPBanCancelableEventArgs(info);

            RemovingIPBanEvent.Raise(e);
            return(!e.Cancel);
        }
예제 #4
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 ) {
         CheckIfLoaded();
         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);
     }
 }
예제 #5
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 = PlayerDB.Unescape(fields[1])
            };

            DateTimeUtil.TryParseDateTime(fields[2], ref info.BanDate);
            if (fields[3].Length > 0)
            {
                info.BanReason = PlayerDB.Unescape(fields[3]);
            }
            if (fields[4].Length > 0)
            {
                info.PlayerName = PlayerDB.Unescape(fields[4]);
            }

            Int32.TryParse(fields[5], out info.Attempts);
            info.LastAttemptName = PlayerDB.Unescape(fields[6]);
            if (info.LastAttemptName.Length == 0)
            {
                info.LastAttemptName = null;
            }
            DateTimeUtil.TryParseDateTime(fields[7], ref info.LastAttemptDate);

            return(info);
        }
예제 #6
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 ) {
         CheckIfLoaded();
         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);
         }
     }
 }
예제 #7
0
 internal void Load()
 {
     if (File.Exists(FileName))
     {
         using (StreamReader reader = File.OpenText(FileName)) {
             reader.ReadLine(); // header
             while (!reader.EndOfStream)
             {
                 string[] fields = reader.ReadLine().Split(',');
                 if (fields.Length == IPBanInfo.fieldCount)
                 {
                     try {
                         IPBanInfo ban = new IPBanInfo(fields);
                         bans.Add(ban.address.ToString(), ban);
                     } catch (FormatException ex) {
                         world.log.Log("IPBanList.Load: Could not parse a record: {0}", LogType.Error, ex.Message);
                     } catch (IOException ex) {
                         world.log.Log("IPBanList.Load: Error while trying to read from file: {0}", LogType.Error, ex.Message);
                     }
                 }
             }
         }
         world.log.Log("IPBanList.Load: Done loading IP ban list ({0} records).", LogType.Debug, bans.Count);
     }
     else
     {
         world.log.Log("IPBanList.Load: No IP ban file found.", LogType.Warning);
     }
 }
예제 #8
0
        static void RaiseRemovedIPBanEvent(IPBanInfo info)
        {
            var h = RemovedIPBan;

            if (h != null)
            {
                h(null, new IPBanEventArgs(info));
            }
        }
예제 #9
0
파일: IPBanList.cs 프로젝트: fragmer/fCraft
 public bool Add( IPBanInfo ban ) {
     lock( locker ) {
         if( !bans.ContainsKey( ban.address.ToString() ) ) {
             bans.Add( ban.address.ToString(), ban );
             Save();
             return true;
         } else {
             return false;
         }
     }
 }
예제 #10
0
        static bool RaiseRemovingIPBanEvent(IPBanInfo info)
        {
            var h = RemovingIPBan;

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

            h(null, e);
            return(e.Cancel);
        }
예제 #11
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));
            }
        }
예제 #12
0
 public bool Add(IPBanInfo ban)
 {
     lock ( locker ) {
         if (!bans.ContainsKey(ban.address.ToString()))
         {
             bans.Add(ban.address.ToString(), ban);
             Save();
             return(true);
         }
         else
         {
             return(false);
         }
     }
 }
예제 #13
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 IPBanCancelableEventArgs(info);

            h(null, e);
            return(e.Cancel);
        }
예제 #14
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 = PlayerDB.UnescapeOldFormat(fields[1])
            };

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

            info.Attempts        = Int32.Parse(fields[5]);
            info.LastAttemptName = PlayerDB.UnescapeOldFormat(fields[6]);
            if (info.LastAttemptName.Length == 0)
            {
                info.LastAttemptName = null;
            }
            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);
        }
예제 #15
0
 /// <summary> Adds a new IP Ban. </summary>
 /// <param name="ban"> Ban information </param>
 /// <returns> True if ban was added, false if it was already on the list </returns>
 public static bool Add(IPBanInfo ban)
 {
     if (ban == null)
     {
         throw new ArgumentNullException("ban");
     }
     lock ( BanListLock ) {
         if (Bans.ContainsKey(ban.Address.ToString()))
         {
             return(false);
         }
         if (RaiseAddingIPBanEvent(ban))
         {
             return(false);
         }
         Bans.Add(ban.Address.ToString(), ban);
         RaiseAddedIPBanEvent(ban);
         Save();
         return(true);
     }
 }
예제 #16
0
파일: IPBanInfo.cs 프로젝트: fragmer/fCraft
        internal static IPBanInfo LoadFormat1( [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].ToDateTimeLegacy( 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].ToDateTimeLegacy( ref info.LastAttemptDate );

            return info;
        }
예제 #17
0
파일: IPBanList.cs 프로젝트: fragmer/fCraft
 internal void Load() {
     if( File.Exists( FileName ) ) {
         using( StreamReader reader = File.OpenText( FileName ) ) {
             reader.ReadLine(); // header
             while( !reader.EndOfStream ) {
                 string[] fields = reader.ReadLine().Split( ',' );
                 if( fields.Length == IPBanInfo.fieldCount ) {
                     try {
                         IPBanInfo ban = new IPBanInfo( fields );
                         bans.Add( ban.address.ToString(), ban );
                     } catch( FormatException ex ) {
                         world.log.Log( "IPBanList.Load: Could not parse a record: {0}", LogType.Error, ex.Message );
                     } catch( IOException ex ) {
                         world.log.Log( "IPBanList.Load: Error while trying to read from file: {0}", LogType.Error, ex.Message );
                     }
                 }
             }
         }
         world.log.Log( "IPBanList.Load: Done loading IP ban list ({0} records).", LogType.Debug, bans.Count );
     } else {
         world.log.Log( "IPBanList.Load: No IP ban file found.", LogType.Warning );
     }
 }
예제 #18
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>
        /// <exception cref="ArgumentNullException"> targetAddress or player is null. </exception>
        /// <exception cref="PlayerOpException"> Permission or configuration issues arise, or if everyone has already been banned. </exception>
        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;

            lock ( BanListLock ) {
                CheckIfLoaded();
                // 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}", targetAddress, player.ClassyName);
                            var cant = Server.Players.Cant(Permission.ViewPlayerIPs);
                            cant.Message("&WAn IP was banned by {0}", 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)
            {
                string kickReason;
                if (reason != null)
                {
                    kickReason = String.Format("Banned by {0}: {1}", player.Name, reason);
                }
                else
                {
                    kickReason = String.Format("Banned by {0}", player.Name);
                }
                for (int i = 0; i < targetsOnline.Length; i++)
                {
                    if (targetsOnline[i].Info.BanStatus != BanStatus.IPBanExempt)
                    {
                        targetsOnline[i].Kick(kickReason, LeaveReason.BanAll);
                    }
                }
            }
        }
예제 #19
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>
        /// <exception cref="ArgumentNullException"> targetAddress or player is null. </exception>
        /// <exception cref="PlayerOpException"> Permission or configuration issues arise, or if IP is already banned. </exception>
        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");
            }

            lock ( BanListLock ) {
                CheckIfLoaded();
                // 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}", targetAddress, player.ClassyName);
                        var cant = Server.Players.Cant(Permission.ViewPlayerIPs);
                        cant.Message("&WAn IP was banned by {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);
                }
            }
        }
예제 #20
0
파일: IPBanList.cs 프로젝트: fragmer/fCraft
 static bool RaiseRemovingIPBanEvent( IPBanInfo info ) {
     var h = RemovingIPBan;
     if( h == null ) return false;
     var e = new IPBanCancellableEventArgs( info );
     h( null, e );
     return e.Cancel;
 }
예제 #21
0
        internal static void Load()
        {
            lock ( BanListLock ) {
                if (IsLoaded)
                {
                    throw new InvalidOperationException("IPBanList is already loaded!");
                }
                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.");
                            IsLoaded = true;
                            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.");
                }
                IsLoaded = true;
            }
        }
예제 #22
0
파일: IPBanList.cs 프로젝트: fragmer/fCraft
 static void RaiseRemovedIPBanEvent( IPBanInfo info ) {
     var h = RemovedIPBan;
     if( h != null ) h( null, new IPBanEventArgs( info ) );
 }
예제 #23
0
파일: IPBanInfo.cs 프로젝트: fragmer/fCraft
        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 = PlayerDB.UnescapeOldFormat( fields[1] )
            };

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

            info.Attempts = Int32.Parse( fields[5] );
            info.LastAttemptName = PlayerDB.UnescapeOldFormat( fields[6] );
            if( info.LastAttemptName.Length == 0 ) info.LastAttemptName = null;
            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;
        }
예제 #24
0
파일: IPBanList.cs 프로젝트: fragmer/fCraft
 /// <summary> Adds a new IP Ban. </summary>
 /// <param name="ban"> Ban information </param>
 /// <returns> True if ban was added, false if it was already on the list </returns>
 public static bool Add( IPBanInfo ban ) {
     if( ban == null ) throw new ArgumentNullException( "ban" );
     lock( BanListLock ) {
         if( Bans.ContainsKey( ban.Address.ToString() ) ) return false;
         if( RaiseAddingIPBanEvent( ban ) ) return false;
         Bans.Add( ban.Address.ToString(), ban );
         RaiseAddedIPBanEvent( ban );
         Save();
         return true;
     }
 }
예제 #25
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}", targetAddress, player.ClassyName );
                    var cant = Server.Players.Cant( Permission.ViewPlayerIPs );
                    cant.Message( "&WAn IP was banned by {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 );
            }
        }
예제 #26
0
        // login logic
        void LoginSequence()
        {
            byte opcode = reader.ReadByte();

            if (opcode != (byte)InputCodes.Handshake)
            {
                world.log.Log("Session.LoginSequence: Unexpected opcode in the first packet: {0}.", LogType.Error, opcode);
                KickNow("Unexpected handshake message - possible protocol mismatch!");
                return;
            }

            // check protocol version
            int clientProtocolVersion = reader.ReadByte();

            if (clientProtocolVersion != Config.ProtocolVersion)
            {
                world.log.Log("Session.LoginSequence: Wrong protocol version: {0}.", LogType.Error, clientProtocolVersion);
                KickNow("Incompatible protocol version!");
                return;
            }

            // check name for nonstandard characters
            string playerName       = ReadString();
            string verificationCode = ReadString();

            reader.ReadByte(); // unused

            if (!Player.IsValidName(playerName))
            {
                world.log.Log("Session.LoginSequence: Unacceptible player name: {0} ({1})", LogType.SuspiciousActivity, playerName, GetIP().ToString());
                KickNow("Invalid characters in player name!");
                return;
            }

            // check if player is banned
            player = new Player(world, playerName, this, world.map.spawn);
            if (player.info.banned)
            {
                player.info.ProcessFailedLogin(player);
                world.log.Log("Banned player {0} tried to log in.", LogType.SuspiciousActivity, player.name);
                world.SendToAll(PacketWriter.MakeMessage(Color.Sys + "Banned player " + player.name + " tried to log in."), player);
                KickNow("You were banned by " + player.info.bannedBy + " " + DateTime.Now.Subtract(player.info.banDate).Days + " days ago.");
                return;
            }

            // check if player's IP is banned
            IPBanInfo IPBanInfo = world.bans.Get(GetIP());

            if (IPBanInfo != null)
            {
                player.info.ProcessFailedLogin(player);
                IPBanInfo.ProcessAttempt(player);
                world.log.Log("{0} tried to log in from a banned IP.", LogType.SuspiciousActivity, player.name);
                world.SendToAll(PacketWriter.MakeMessage(Color.Sys + player.name + " tried to log in from a banned IP."), null);
                KickNow("Your IP was banned by " + IPBanInfo.bannedBy + " " + DateTime.Now.Subtract(IPBanInfo.banDate).Days + " days ago.");
                return;
            }

            // verify name
            if (!world.server.VerifyName(player.name, verificationCode))
            {
                string standardMessage = String.Format("Session.LoginSequence: Could not verify player name for {0} ({1}).",
                                                       player.name, GetIP());
                if (player.info.timesVisited == 1 || player.info.lastIP.ToString() != GetIP().ToString())
                {
                    switch (world.config.GetString("VerifyNames"))
                    {
                    case "Always":
                    case "Balanced":
                        player.info.ProcessFailedLogin(player);
                        world.log.Log("{0} IP did not match. Player was kicked.", LogType.SuspiciousActivity, standardMessage);
                        KickNow("Could not verify player name!");
                        return;

                    case "Never":
                        world.log.Log("{0} IP did not match. Player was allowed in anyway because VerifyNames is set to Never.",
                                      LogType.SuspiciousActivity,
                                      standardMessage);
                        Send(PacketWriter.MakeMessage(Color.Red + "Your name could not be verified."));
                        world.SendToAll(PacketWriter.MakeMessage(Color.Red + "Name and IP of " + player.name + " could not be verified!"), player);
                        break;
                    }
                }
                else
                {
                    switch (world.config.GetString("VerifyNames"))
                    {
                    case "Always":
                        player.info.ProcessFailedLogin(player);
                        world.log.Log("{0} IP matched previous records for that name. " +
                                      "Player was kicked anyway because VerifyNames is set to Always.", LogType.SuspiciousActivity,
                                      standardMessage);
                        KickNow("Could not verify player name!");
                        return;

                    case "Balanced":
                    case "Never":
                        world.log.Log("{0} IP matched previous records for that name. Player was allowed in.", LogType.SuspiciousActivity,
                                      standardMessage);
                        Send(PacketWriter.MakeMessage(Color.Red + "Your name could not be verified."));
                        if (world.config.GetBool("AnnounceUnverifiedNames"))
                        {
                            world.SendToAll(PacketWriter.MakeMessage(Color.Red + "Name of " + player.name +
                                                                     " could not be verified, but IP matches."), player);
                        }
                        break;
                    }
                }
            }

            // check if another player with the same name is on
            Player potentialClone = world.FindPlayer(player.name);

            if (potentialClone != null)
            {
                player.info.ProcessFailedLogin(player);
                world.log.Log("Session.LoginSequence: Player {0} tried to log in from two computers at once.", LogType.SuspiciousActivity, player.name);
                potentialClone.Message("Warning: someone just attempted to log in using your name.");
                KickNow("Already connected form elsewhere!");
                return;
            }

            potentialClone = world.FindPlayer(GetIP());
            if (potentialClone != null)
            {
                player.info.ProcessFailedLogin(player);
                world.log.Log("Session.LoginSequence: Player {0} tried to log in from same IP ({1}) as {2}.", LogType.SuspiciousActivity,
                              player.name, GetIP().ToString(), potentialClone.name);
                potentialClone.Message("Warning: someone just attempted to log in using your IP.");
                KickNow("Only one connection per IP allowed!");
                return;
            }

            // Register player for future block updates
            if (!world.RegisterPlayer(player))
            {
                KickNow("Sorry, server is full.");
                return;
            }

            player.info.ProcessLogin(player);

            // Player is now authenticated. Send server info.
            writer.Write(PacketWriter.MakeHandshake(world, player));

            // Start sending over the level copy
            writer.WriteLevelBegin();
            byte[] buffer    = new byte[1024];
            int    bytesSent = 0;

            // Fetch compressed map copy
            byte[] blockData;
            using (MemoryStream stream = new MemoryStream()) {
                world.map.GetCompressedCopy(stream, true);
                blockData = stream.ToArray();
            }
            world.log.Log("Session.LoginSequence: Sending compressed level copy ({0} bytes) to {1}.", LogType.Debug,
                          blockData.Length, player.name);

            while (bytesSent < blockData.Length)
            {
                int chunkSize = blockData.Length - bytesSent;
                if (chunkSize > 1024)
                {
                    chunkSize = 1024;
                }
                Array.Copy(blockData, bytesSent, buffer, 0, chunkSize);
                byte progress = (byte)(100 * bytesSent / blockData.Length);

                // write in chunks of 1024 bytes or less
                writer.WriteLevelChunk(buffer, chunkSize, progress);
                bytesSent += chunkSize;
            }

            // Done sending over level copy
            writer.Write(PacketWriter.MakeLevelEnd(world.map));

            // Send playerlist and add player himself
            writer.WriteAddEntity(255, player.name, player.pos);
            world.SendPlayerList(player);

            // Reveal newcommer to existing players
            world.log.Log("{0} ({1}) has joined the server.", LogType.UserActivity, player.name, player.info.playerClass.name);
            world.SendToAll(PacketWriter.MakeAddEntity(player, player.pos), player);
            world.SendToAll(PacketWriter.MakeMessage(Color.Sys + player.name + " (" + player.info.playerClass.color +
                                                     player.info.playerClass.name + Color.Sys + ") has joined the server."),
                            player);

            // Welcome message
            if (player.info.timesVisited > 1)
            {
                player.Message("Welcome back to " + world.config.GetString("ServerName"));
            }
            else
            {
                player.Message("Welcome to " + world.config.GetString("ServerName"));
            }

            player.Message("Your player class is " + player.info.playerClass.color + player.info.playerClass.name + Color.Sys +
                           ". Type /help for details.");

            if (world.config.GetBool("LowLatencyMode"))
            {
                client.NoDelay = true;
            }

            // Done.
            world.log.Log("Session.LoginSequence: {0} is now ready.", LogType.Debug,
                          player.name);
            GC.Collect();
        }
예제 #27
0
        // Shows ban information.
        //     When used without arguments, shows players's own ban stats.
        //     An optional argument allows to look at other people's ban stats.
        void BanInfo(Player player, Command cmd)
        {
            string    name = cmd.Next();
            IPAddress address;

            if (name == null)
            {
                name = player.name;
            }
            else if (!player.Can(Permissions.ViewOthersInfo))
            {
                world.NoAccessMessage(player);
            }
            else if (IPAddress.TryParse(name, out address))
            {
                IPBanInfo info = world.bans.Get(address);
                if (info != null)
                {
                    player.Message(String.Format("{0} was banned by {1} on {2:dd MMM yyyy}.",
                                                 info.address,
                                                 info.bannedBy,
                                                 info.banDate));
                    if (info.playerName != null)
                    {
                        player.Message("  IP ban was banned by association with " + info.playerName);
                    }
                    if (info.attempts > 0)
                    {
                        player.Message("  There have been " + info.attempts + " attempts to log in, most recently");
                        player.Message(String.Format("  on {0:dd MMM yyyy} by {1}.",
                                                     info.lastAttemptDate,
                                                     info.lastAttemptName));
                    }
                    if (info.banReason != "")
                    {
                        player.Message("  Memo: " + info.banReason);
                    }
                }
                else
                {
                    player.Message(address.ToString() + " is currently NOT banned.");
                }
            }
            else
            {
                PlayerInfo info;
                if (!world.db.FindPlayerInfo(name, out info))
                {
                    world.ManyPlayersMessage(player, name);
                }
                else if (info != null)
                {
                    if (info.banned)
                    {
                        player.Message("Player " + info.name + " is currently " + Color.Red + "banned.");
                    }
                    else
                    {
                        player.Message("Player " + info.name + " is currently NOT banned.");
                    }
                    if (info.bannedBy != "-")
                    {
                        player.Message(String.Format("  Last banned by {0} on {1:dd MMM yyyy}.",
                                                     info.bannedBy,
                                                     info.banDate));
                        if (info.banReason != "")
                        {
                            player.Message("  Ban memo: " + info.banReason);
                        }
                    }
                    if (info.unbannedBy != "-")
                    {
                        player.Message(String.Format("  Unbanned by {0} on {1:dd MMM yyyy}.",
                                                     info.unbannedBy,
                                                     info.unbanDate));
                        if (info.unbanReason != "")
                        {
                            player.Message("  Unban memo: " + info.unbanReason);
                        }
                    }
                    if (info.banDate != DateTime.MinValue)
                    {
                        TimeSpan banDuration;
                        if (info.banned)
                        {
                            banDuration = DateTime.Now.Subtract(info.banDate);
                        }
                        else
                        {
                            banDuration = info.unbanDate.Subtract(info.banDate);
                        }
                        player.Message(String.Format("  Last ban duration: {0} days and {1:F1} hours.",
                                                     (int)banDuration.TotalDays,
                                                     banDuration.TotalHours));
                    }
                }
                else
                {
                    world.NoPlayerMessage(player, name);
                }
            }
        }
예제 #28
0
        internal static void Load()
        {
            if (File.Exists(Paths.IPBanListFileName))
            {
                string headerText;
                using (StreamReader reader = File.OpenText(Paths.IPBanListFileName)) {
                    headerText = reader.ReadLine(); // header
                    if (headerText == null)
                    {
                        Logger.Log("IPBanList.Load: IP ban file is empty.", LogType.Warning);
                    }

                    int version = ParseHeader(headerText);

                    while (!reader.EndOfStream)
                    {
                        string[] fields = reader.ReadLine().Split(',');
                        if (fields.Length == IPBanInfo.FieldCount)
                        {
                            try {
                                IPBanInfo ban;
                                if (version == 0)
                                {
                                    ban = IPBanInfo.LoadOldFormat(fields, true);
                                }
                                else
                                {
                                    ban = IPBanInfo.Load(fields);
                                }

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

                    if (version == 0)
                    {
                        Logger.Log("IPBanList.Load: Attempting to recover IP bans...", LogType.SystemActivity);
                        int oldBanCount = Bans.Count;
                        PlayerDB.RecoverIPBans();
                        Logger.Log("IPBanList.Load: {0} IP bans recovered.", LogType.SystemActivity, Bans.Count - oldBanCount);
                    }
                }

                Logger.Log("IPBanList.Load: Done loading IP ban list ({0} records).", LogType.Debug, Bans.Count);
            }
            else
            {
                Logger.Log("IPBanList.Load: No IP ban file found.", LogType.Warning);
            }
            IsLoaded = true;
        }
예제 #29
0
        /// <summary> Bans given player and their IP address.
        /// All players from IP are kicked. Throws PlayerOpException on problems. </summary>
        /// <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>
        /// <exception cref="fCraft.PlayerOpException" />
        public void BanIP( [NotNull] Player player, [CanBeNull] string reason, bool announce, bool raiseEvents ) {
            if( player == null ) throw new ArgumentNullException( "player" );
            if( reason != null && reason.Trim().Length == 0 ) reason = null;
            lock( actionLock ) {
                if( !player.Can( Permission.Ban, Permission.BanIP ) ) {
                    PlayerOpException.ThrowPermissionMissing( player, this, "IP-ban", Permission.Ban, Permission.BanIP );
                }

                IPAddress address = LastIP;

                // Check if player is trying to ban self
                if( player.Info == this || address.Equals( player.IP ) && !player.IsSuper ) {
                    PlayerOpException.ThrowCannotTargetSelf( player, this, "IP-ban" );
                }

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

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

                // Check existing ban statuses
                bool needNameBan = !IsBanned;
                bool needIPBan = !IPBanList.Contains( address );
                if( !needIPBan && !needNameBan ) {
                    string msg, colorMsg;
                    if( player.Can( Permission.ViewPlayerIPs ) ) {
                        msg = String.Format( "Given player ({0}) and their IP address ({1}) are both already banned.",
                                             Name, address );
                        colorMsg = String.Format( "&SGiven player ({0}&S) and their IP address ({1}) are both already banned.",
                                                  ClassyName, address );
                    } else {
                        msg = String.Format( "Given player ({0}) and their IP address are both already banned.",
                                             Name );
                        colorMsg = String.Format( "&SGiven player ({0}&S) and their IP address are both already banned.",
                                                  ClassyName );
                    }
                    throw new PlayerOpException( player, this, PlayerOpExceptionCode.NoActionNeeded, msg, colorMsg );
                }

                // Check if target is IPBan-exempt
                bool targetIsExempt = (BanStatus == BanStatus.IPBanExempt);
                if( !needIPBan && targetIsExempt ) {
                    string msg = String.Format( "Given player ({0}) is exempt from IP bans. Remove the exemption and retry.",
                                                Name );
                    string colorMsg = String.Format( "&SGiven player ({0}&S) is exempt from IP bans. Remove the exemption and retry.",
                                                     ClassyName );
                    throw new PlayerOpException( player, this, PlayerOpExceptionCode.TargetIsExempt, msg, colorMsg );
                }

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

                // Ban the name
                if( needNameBan ) {
                    Ban( player, reason, announce, raiseEvents );
                }

                // Ban the IP
                if( needIPBan ) {
                    IPBanInfo banInfo = new IPBanInfo( address, Name, player.Name, reason );
                    if( IPBanList.Add( banInfo, raiseEvents ) ) {
                        Logger.Log( LogType.UserActivity,
                                    "{0} banned {1} (BanIP {2}). Reason: {3}",
                                    player.Name, address, Name, reason ?? "" );

                        // Announce ban on the server
                        if( announce ) {
                            var can = Server.Players.Can( Permission.ViewPlayerIPs );
                            can.Message( "&WPlayer {0}&W was IP-banned ({1}) by {2}",
                                         ClassyName, address, player.ClassyName );
                            var cant = Server.Players.Cant( Permission.ViewPlayerIPs );
                            cant.Message( "&WPlayer {0}&W was IP-banned by {1}",
                                          ClassyName, player.ClassyName );
                            if( ConfigKey.AnnounceKickAndBanReasons.Enabled() && reason != null ) {
                                Server.Message( "&WBanIP reason: {0}", reason );
                            }
                        }
                    } else {
                        // IP is already banned
                        string msg, colorMsg;
                        if( player.Can( Permission.ViewPlayerIPs ) ) {
                            msg = String.Format( "IP of player {0} ({1}) is already banned.",
                                                 Name, address );
                            colorMsg = String.Format( "&SIP of player {0}&S ({1}) is already banned.",
                                                      Name, address );
                        } else {
                            msg = String.Format( "IP of player {0} is already banned.",
                                                 Name );
                            colorMsg = String.Format( "&SIP of player {0}&S is already banned.",
                                                      ClassyName );
                        }
                        throw new PlayerOpException( player, null, PlayerOpExceptionCode.NoActionNeeded, msg, colorMsg );
                    }
                }
                
                // 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( address ) ) {
                    if( other.Info.BanStatus != BanStatus.IPBanExempt ) {
                        other.Kick( kickReason, LeaveReason.BanIP ); // TODO: check side effects of not using DoKick
                    }
                }
            }
        }
예제 #30
0
        public static void PrintPlayerInfo(Player player, PlayerInfo info)
        {
            Player target = Server.FindPlayerExact(info.Name);

            // hide online status when hidden
            if (target != null && !player.CanSee(target))
            {
                target = null;
            }

            if (info.LastIP.Equals(IPAddress.None))
            {
                player.Message("About {0}&S: Never seen before.", info.GetClassyName());
            }
            else
            {
                if (target != null)
                {
                    if (target.IsHidden)
                    {
                        if (player.Can(Permission.ViewPlayerIPs))
                        {
                            player.Message("About {0}&S: HIDDEN. Online from {1}",
                                           info.GetClassyName(),
                                           info.LastIP);
                        }
                        else
                        {
                            player.Message("About {0}&S: HIDDEN.",
                                           info.GetClassyName());
                        }
                    }
                    else
                    {
                        if (player.Can(Permission.ViewPlayerIPs))
                        {
                            player.Message("About {0}&S: Online now from {1}",
                                           info.GetClassyName(),
                                           info.LastIP);
                        }
                        else
                        {
                            player.Message("About {0}&S: Online now.",
                                           info.GetClassyName());
                        }
                    }
                }
                else
                {
                    if (player.Can(Permission.ViewPlayerIPs))
                    {
                        player.Message("About {0}&S: Last seen {1} ago from {2}",
                                       info.GetClassyName(),
                                       info.TimeSinceLastSeen.ToMiniString(),
                                       info.LastIP);
                    }
                    else
                    {
                        player.Message("About {0}&S: Last seen {1} ago.",
                                       info.GetClassyName(),
                                       info.TimeSinceLastSeen.ToMiniString());
                    }
                }
                // Show login information
                player.Message("  Logged in {0} time(s) since {1:d MMM yyyy}.",
                               info.TimesVisited,
                               info.FirstLoginDate);
            }


            // Show ban information
            IPBanInfo ipBan = IPBanList.Get(info.LastIP);

            if (ipBan != null && info.Banned)
            {
                player.Message("  Both name and IP are {0}BANNED&S. See &H/baninfo", Color.Red);
            }
            else if (ipBan != null)
            {
                player.Message("  IP is {0}BANNED&S (but nick isn't). See &H/baninfo", Color.Red);
            }
            else if (info.Banned)
            {
                player.Message("  Nick is {0}BANNED&S (but IP isn't). See &H/baninfo", Color.Red);
            }


            if (info.LastIP.ToString() != IPAddress.None.ToString())
            {
                // Show alts
                List <PlayerInfo> altNames = new List <PlayerInfo>();
                int bannedAltCount         = 0;
                foreach (PlayerInfo playerFromSameIP in PlayerDB.FindPlayers(info.LastIP, 25))
                {
                    if (playerFromSameIP != info)
                    {
                        altNames.Add(playerFromSameIP);
                        if (playerFromSameIP.Banned)
                        {
                            bannedAltCount++;
                        }
                    }
                }

                if (altNames.Count > 0)
                {
                    if (bannedAltCount > 0)
                    {
                        player.Message("  {0} accounts ({1} banned) share this IP: {2}",
                                       altNames.Count,
                                       bannedAltCount,
                                       altNames.ToArray().JoinToClassyString());
                    }
                    else
                    {
                        player.Message("  {0} accounts share this IP: {1}",
                                       altNames.Count,
                                       altNames.ToArray().JoinToClassyString());
                    }
                }
            }


            // Stats
            if (info.BlocksDrawn > 500000000)
            {
                player.Message("  Built {0} and deleted {1} blocks, drew {2}M blocks, wrote {3} messages.",
                               info.BlocksBuilt,
                               info.BlocksDeleted,
                               info.BlocksDrawn / 1000000,
                               info.LinesWritten);
            }
            else if (info.BlocksDrawn > 500000)
            {
                player.Message("  Built {0} and deleted {1} blocks, drew {2}K blocks, wrote {3} messages.",
                               info.BlocksBuilt,
                               info.BlocksDeleted,
                               info.BlocksDrawn / 1000,
                               info.LinesWritten);
            }
            else if (info.BlocksDrawn > 0)
            {
                player.Message("  Built {0} and deleted {1} blocks, drew {2} blocks, wrote {3} messages.",
                               info.BlocksBuilt,
                               info.BlocksDeleted,
                               info.BlocksDrawn,
                               info.LinesWritten);
            }
            else
            {
                player.Message("  Built {0} and deleted {1} blocks, wrote {2} messages.",
                               info.BlocksBuilt,
                               info.BlocksDeleted,
                               info.LinesWritten);
            }


            // More stats
            if (info.TimesBannedOthers > 0 || info.TimesKickedOthers > 0)
            {
                player.Message("  Kicked {0} and banned {1} players.", info.TimesKickedOthers, info.TimesBannedOthers);
            }

            if (info.TimesKicked > 0)
            {
                if (info.LastKickDate != DateTime.MinValue)
                {
                    player.Message("  Got kicked {0} times. Last kick {1} ago by {2}",
                                   info.TimesKicked,
                                   info.TimeSinceLastKick.ToMiniString(),
                                   info.LastKickBy);
                    if (info.LastKickReason.Length > 0)
                    {
                        player.Message("  Last kick reason: {0}", info.LastKickReason);
                    }
                }
                else
                {
                    player.Message("  Got kicked {0} times", info.TimesKicked);
                }
            }


            // Promotion/demotion
            if (!String.IsNullOrEmpty(info.RankChangedBy))
            {
                if (info.PreviousRank == null)
                {
                    player.Message("  Promoted to {0}&S by {1} {2} ago.",
                                   info.Rank.GetClassyName(),
                                   info.RankChangedBy,
                                   info.TimeSinceRankChange.ToMiniString());
                }
                else if (info.PreviousRank < info.Rank)
                {
                    player.Message("  Promoted from {0}&S to {1}&S by {2} {3} ago.",
                                   info.PreviousRank.GetClassyName(),
                                   info.Rank.GetClassyName(),
                                   info.RankChangedBy,
                                   info.TimeSinceRankChange.ToMiniString());
                    if (!string.IsNullOrEmpty(info.RankChangeReason))
                    {
                        player.Message("  Promotion reason: {0}", info.RankChangeReason);
                    }
                }
                else
                {
                    player.Message("  Demoted from {0}&S to {1}&S by {2} {3} ago.",
                                   info.PreviousRank.GetClassyName(),
                                   info.Rank.GetClassyName(),
                                   info.RankChangedBy,
                                   info.TimeSinceRankChange.ToMiniString());
                    if (info.RankChangeReason.Length > 0)
                    {
                        player.Message("  Demotion reason: {0}", info.RankChangeReason);
                    }
                }
            }
            else
            {
                player.Message("  Rank is {0}&S (default).",
                               info.Rank.GetClassyName());
            }

            if (info.LastIP.ToString() != IPAddress.None.ToString())
            {
                // Time on the server
                TimeSpan totalTime = info.TotalTime;
                if (target != null)
                {
                    totalTime = totalTime.Add(info.TimeSinceLastLogin);
                }
                player.Message("  Spent a total of {0:F1} hours ({1:F1} minutes) here.",
                               totalTime.TotalHours,
                               totalTime.TotalMinutes);
            }
        }
예제 #31
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}", targetAddress, player.ClassyName );
                        var cant = Server.Players.Cant( Permission.ViewPlayerIPs );
                        cant.Message( "&WAn IP was banned by {0}", 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 ) {
                string kickReason;
                if( reason != null ) {
                    kickReason = String.Format( "Banned by {0}: {1}", player.Name, reason );
                } else {
                    kickReason = String.Format( "Banned by {0}", player.Name );
                }
                for( int i = 0; i < targetsOnline.Length; i++ ) {
                    targetsOnline[i].Kick( kickReason, LeaveReason.BanAll );
                }
            }
        }
예제 #32
0
        internal static void BanInfo(Player player, Command cmd)
        {
            string    name = cmd.Next();
            IPAddress address;

            if (name == null)
            {
                name = player.Name;
            }
            else if (!player.Can(Permission.ViewOthersInfo))
            {
                player.NoAccessMessage(Permission.ViewOthersInfo);
                return;
            }

            if (Server.IsIP(name) && IPAddress.TryParse(name, out address))
            {
                IPBanInfo info = IPBanList.Get(address);
                if (info != null)
                {
                    player.Message("{0} was banned by {1} on {2:dd MMM yyyy}.",
                                   info.Address,
                                   info.BannedBy,
                                   info.BanDate);
                    if (!String.IsNullOrEmpty(info.PlayerName))
                    {
                        player.Message("  IP ban was banned by association with {0}",
                                       info.PlayerName);
                    }
                    if (info.Attempts > 0)
                    {
                        player.Message("  There have been {0} attempts to log in, most recently", info.Attempts);
                        player.Message("  on {0:dd MMM yyyy} by {1}.",
                                       info.LastAttemptDate,
                                       info.LastAttemptName);
                    }
                    if (info.BanReason.Length > 0)
                    {
                        player.Message("  Ban reason: {0}", info.BanReason);
                    }
                }
                else
                {
                    player.Message("{0} is currently NOT banned.", address);
                }
            }
            else
            {
                PlayerInfo info;
                if (!PlayerDB.FindPlayerInfo(name, out info))
                {
                    player.Message("More than one player found matching \"{0}\"", name);
                }
                else if (info != null)
                {
                    if (info.Banned)
                    {
                        player.Message("Player {0}&S is &WBANNED", info.GetClassyName());
                    }
                    else
                    {
                        player.Message("Player {0}&S is NOT banned.", info.GetClassyName());
                    }
                    if (!String.IsNullOrEmpty(info.BannedBy))
                    {
                        player.Message("  Last ban by {0} on {1:dd MMM yyyy} ({2} ago).",
                                       info.BannedBy,
                                       info.BanDate,
                                       info.TimeSinceBan.ToMiniString());
                        if (info.BanReason.Length > 0)
                        {
                            player.Message("  Last ban reason: {0}", info.BanReason);
                        }
                    }
                    if (!String.IsNullOrEmpty(info.UnbannedBy))
                    {
                        player.Message("  Unbanned by {0} on {1:dd MMM yyyy} ({2} ago).",
                                       info.UnbannedBy,
                                       info.UnbanDate,
                                       info.TimeSinceUnban.ToMiniString());
                        if (info.UnbanReason.Length > 0)
                        {
                            player.Message("  Last unban reason: {0}", info.UnbanReason);
                        }
                    }
                    if (info.BanDate != DateTime.MinValue)
                    {
                        TimeSpan banDuration;
                        if (info.Banned)
                        {
                            banDuration = info.TimeSinceBan;
                        }
                        else
                        {
                            banDuration = info.UnbanDate.Subtract(info.BanDate);
                        }
                        player.Message("  Last ban duration: {0} days and {1:F1} hours.",
                                       (int)banDuration.TotalDays,
                                       banDuration.TotalHours);
                    }
                }
                else
                {
                    player.NoPlayerMessage(name);
                }
            }
        }