jdarwood007 commited on 2019-12-08 12:17:24
Showing 2 changed files, with 260 additions and 8 deletions.
... | ... |
@@ -242,6 +242,7 @@ class SFS |
242 | 242 |
'', |
243 | 243 |
array('check', 'sfs_emailcheck'), |
244 | 244 |
array('check', 'sfs_ipcheck'), |
245 |
+ array('check', 'sfs_ipcheck_autoban'), |
|
245 | 246 |
array('check', 'sfs_usernamecheck'), |
246 | 247 |
'', |
247 | 248 |
array('select', 'sfs_region', $this->sfsServerMapping('config')), |
... | ... |
@@ -285,6 +286,10 @@ class SFS |
285 | 286 |
$this->unloadDefaults(); |
286 | 287 |
checkSession(); |
287 | 288 |
|
289 |
+ // If we are automatically banning IPs, make sure we have a ban group. |
|
290 |
+ if (isset($_POST['sfs_ipcheck_autoban']) || empty($modSettings['sfs_ipcheck_autoban_group'])) |
|
291 |
+ $this->createBanGroup(true); |
|
292 |
+ |
|
288 | 293 |
saveDBSettings($config_vars); |
289 | 294 |
|
290 | 295 |
writeLog(); |
... | ... |
@@ -692,8 +697,12 @@ class SFS |
692 | 697 |
// This tells us what it matched on exactly. |
693 | 698 |
if (strpos($row['result'], ',') !== false) |
694 | 699 |
{ |
695 |
- list($resultType, $resultMatch) = explode(',', $row['result']); |
|
696 |
- $entries[$row['id_sfs']]['result'] = 'Matched on ' . $resultType . ' [' . $resultMatch . ']'; |
|
700 |
+ list($resultType, $resultMatch, $extra) = explode(',', $row['result'] . ',,,'); |
|
701 |
+ $entries[$row['id_sfs']]['result'] = sprintf($txt['sfs_log_matched_on'], $resultType, $resultMatch); |
|
702 |
+ |
|
703 |
+ // If this was a IP ban, note it. |
|
704 |
+ if ($resultType == 'ip' && !empty($extra)) |
|
705 |
+ $entries[$row['id_sfs']]['result'] .= ' ' . $txt['sfs_log_auto_banned']; |
|
697 | 706 |
} |
698 | 707 |
else |
699 | 708 |
$entries[$row['id_sfs']]['result'] = $row['result']; |
... | ... |
@@ -1061,11 +1070,16 @@ class SFS |
1061 | 1070 |
{ |
1062 | 1071 |
foreach ($response['ip'] as $check) |
1063 | 1072 |
{ |
1064 |
- // !!! TODO: Frequency 255 is a blacklist, maybe add them to a generic ban list? |
|
1073 |
+ // They appeared! Block this. |
|
1065 | 1074 |
if (!empty($check['appears'])) |
1066 | 1075 |
{ |
1076 |
+ // Ban them because they are black listed? |
|
1077 |
+ $autoBlackListResult = '0'; |
|
1078 |
+ if (!empty($modSettings['sfs_ipcheck_autoban']) && !empty($check['frequency']) && $check['frequency'] == 255) |
|
1079 |
+ $autoBlackListResult = $this->BanNewIP($check['value']); |
|
1080 |
+ |
|
1067 | 1081 |
$this->logBlockedStats('ip', $check); |
1068 |
- $requestBlocked = 'ip,' . $smcFunc['htmlspecialchars']($check['value']); |
|
1082 |
+ $requestBlocked = 'ip,' . $smcFunc['htmlspecialchars']($check['value']) . ',' . ($autoBlackListResult ? 1 : 0); |
|
1069 | 1083 |
break; |
1070 | 1084 |
} |
1071 | 1085 |
} |
... | ... |
@@ -1108,7 +1122,7 @@ class SFS |
1108 | 1122 |
$this->logAllStats('all', $checks, $requestBlocked); |
1109 | 1123 |
|
1110 | 1124 |
// At this point, we have checked everything, do what needs to be done for our good person. |
1111 |
- if (!$requestBlocked) |
|
1125 |
+ if (empty($requestBlocked)) |
|
1112 | 1126 |
return true; |
1113 | 1127 |
|
1114 | 1128 |
// You are a bad spammer, don't tell them what was blocked. |
... | ... |
@@ -1220,7 +1234,7 @@ class SFS |
1220 | 1234 |
$user_info['ip'], |
1221 | 1235 |
$user_info['ip2'], |
1222 | 1236 |
json_encode($checks), |
1223 |
- $requestBlocked, |
|
1237 |
+ $DebugMessage, |
|
1224 | 1238 |
), |
1225 | 1239 |
array('id_sfs', 'id_type') |
1226 | 1240 |
); |
... | ... |
@@ -1251,8 +1265,7 @@ class SFS |
1251 | 1265 |
{ |
1252 | 1266 |
$data = @json_decode($requestData, true); |
1253 | 1267 |
|
1254 |
- // We got a error, return nothing. |
|
1255 |
- // !!! TODO: Log this? |
|
1268 |
+ // We got a error, return nothing. Don't log this, not worth it. |
|
1256 | 1269 |
if (json_last_error() !== JSON_ERROR_NONE) |
1257 | 1270 |
return array(); |
1258 | 1271 |
return $data; |
... | ... |
@@ -1553,6 +1566,237 @@ class SFS |
1553 | 1566 |
'type' => $this->search_params['type'], |
1554 | 1567 |
'label' => $searchTypes[$this->search_params_type]['label'], |
1555 | 1568 |
); |
1569 |
+ } |
|
1570 |
+ |
|
1571 |
+ /** |
|
1572 |
+ * Create a Ban Group if needed to handle automatic IP bans. |
|
1573 |
+ * We attempt to use the known ban function to create bans, otherwise we just fall back to a standard insert. |
|
1574 |
+ * |
|
1575 |
+ * @internal |
|
1576 |
+ * @CalledIn SMF 2.0, SMF 2.1 |
|
1577 |
+ * @version 1.1 |
|
1578 |
+ * @since 1.0 |
|
1579 |
+ * @return bool True upon success, false otherwise. |
|
1580 |
+ */ |
|
1581 |
+ private function createBanGroup(bool $noChecks = false): bool |
|
1582 |
+ { |
|
1583 |
+ global $smcFunc, $modSettings, $sourcedir, $txt; |
|
1584 |
+ |
|
1585 |
+ // Is this disabled? Don't do it. |
|
1586 |
+ if (empty($noChecks) && empty($modSettings['sfs_ipcheck_autoban'])) |
|
1587 |
+ return false; |
|
1588 |
+ |
|
1589 |
+ // Maybe just got unlinked, if we can find the matching name, relink it. |
|
1590 |
+ $request = $smcFunc['db_query']('', ' |
|
1591 |
+ SELECT id_ban_group |
|
1592 |
+ FROM {db_prefix}ban_groups |
|
1593 |
+ WHERE name = {string:new_ban_name}' . ' |
|
1594 |
+ LIMIT 1', |
|
1595 |
+ array( |
|
1596 |
+ 'new_ban_name' => $txt['sfs_ban_group_name'], |
|
1597 |
+ ) |
|
1598 |
+ ); |
|
1599 |
+ if ($smcFunc['db_num_rows']($request) == 1) |
|
1600 |
+ { |
|
1601 |
+ $ban_data = $smcFunc['db_fetch_assoc']($result); |
|
1602 |
+ $smcFunc['db_free_result']($request); |
|
1603 |
+ |
|
1604 |
+ if (!empty($ban_data['id_ban_group'])) |
|
1605 |
+ { |
|
1606 |
+ updateSettings(array('sfs_ipcheck_autoban_group' => $ban_data['id_ban_group'])); |
|
1607 |
+ return true; |
|
1608 |
+ } |
|
1609 |
+ } |
|
1610 |
+ $smcFunc['db_free_result']($request); |
|
1611 |
+ |
|
1612 |
+ require_once($sourcedir . '/ManageBans.php'); |
|
1613 |
+ |
|
1614 |
+ // Ban Information, this follows the format from the function. |
|
1615 |
+ $ban_info = array( |
|
1616 |
+ 'name' => $txt['sfs_ban_group_name'], |
|
1617 |
+ 'cannot' => array( |
|
1618 |
+ 'access' => 1, |
|
1619 |
+ 'register' => 1, |
|
1620 |
+ 'post' => 1, |
|
1621 |
+ 'login' => 1, |
|
1622 |
+ ), |
|
1623 |
+ 'db_expiration' => 'NULL', |
|
1624 |
+ 'reason' => $txt['sfs_ban_group_reason'], |
|
1625 |
+ 'notes' => $txt['sfs_ban_group_notes'] |
|
1626 |
+ ); |
|
1627 |
+ |
|
1628 |
+ // If we can shortcut this.. |
|
1629 |
+ $ban_group_id = 0; |
|
1630 |
+ if (function_exists('insertBanGroup')) |
|
1631 |
+ $ban_group_id = insertBanGroup($ban_info); |
|
1632 |
+ |
|
1633 |
+ // Fall back. |
|
1634 |
+ if (is_array($ban_group_id) || empty($ban_group_id)) |
|
1635 |
+ { |
|
1636 |
+ $smcFunc['db_insert']('', |
|
1637 |
+ '{db_prefix}ban_groups', |
|
1638 |
+ array( |
|
1639 |
+ 'name' => 'string-20', 'ban_time' => 'int', 'expire_time' => 'raw', 'cannot_access' => 'int', 'cannot_register' => 'int', |
|
1640 |
+ 'cannot_post' => 'int', 'cannot_login' => 'int', 'reason' => 'string-255', 'notes' => 'string-65534', |
|
1641 |
+ ), |
|
1642 |
+ array( |
|
1643 |
+ $ban_info['name'], time(), $ban_info['db_expiration'], $ban_info['cannot']['access'], $ban_info['cannot']['register'], |
|
1644 |
+ $ban_info['cannot']['post'], $ban_info['cannot']['login'], $ban_info['reason'], $ban_info['notes'], |
|
1645 |
+ ), |
|
1646 |
+ array('id_ban_group'), |
|
1647 |
+ 1 |
|
1648 |
+ ); |
|
1649 |
+ $ban_group_id = $smcFunc['db_insert_id']('{db_prefix}ban_groups', 'id_ban_group'); |
|
1650 |
+ } |
|
1651 |
+ |
|
1652 |
+ // Didn't work? Try again later. |
|
1653 |
+ if (empty($ban_group_id)) |
|
1654 |
+ return false; |
|
1655 |
+ |
|
1656 |
+ updateSettings(array('sfs_ipcheck_autoban_group' => $ban_group_id)); |
|
1657 |
+ return true; |
|
1658 |
+ } |
|
1659 |
+ |
|
1660 |
+ /** |
|
1661 |
+ * They have triggered a automatic IP ban, lets do it. |
|
1662 |
+ * In newer versions we attempt to use more of the APIs, but fall back as needed. |
|
1663 |
+ * |
|
1664 |
+ * @param string $ip_address The IP address of the spammer. |
|
1665 |
+ * |
|
1666 |
+ * @internal |
|
1667 |
+ * @CalledIn SMF 2.0, SMF 2.1 |
|
1668 |
+ * @version 1.1 |
|
1669 |
+ * @since 1.0 |
|
1670 |
+ * @return bool True upon success, false otherwise. |
|
1671 |
+ */ |
|
1672 |
+ private function BanNewIP(string $ip_address): bool |
|
1673 |
+ { |
|
1674 |
+ global $smcFunc, $modSettings, $sourcedir; |
|
1675 |
+ |
|
1676 |
+ // Is this disabled? Don't do it. |
|
1677 |
+ if (empty($modSettings['sfs_ipcheck_autoban'])) |
|
1678 |
+ return false; |
|
1679 |
+ |
|
1680 |
+ // Did we loose our Ban Group? Try to fix this. |
|
1681 |
+ if (empty($modSettings['sfs_ipcheck_autoban_group'])) |
|
1682 |
+ $this->createBanGroup(); |
|
1683 |
+ |
|
1684 |
+ // Still no Ban Group? Bail out. |
|
1685 |
+ if (empty($modSettings['sfs_ipcheck_autoban_group'])) |
|
1686 |
+ return false; |
|
1687 |
+ |
|
1688 |
+ require_once($sourcedir . '/ManageBans.php'); |
|
1689 |
+ |
|
1690 |
+ // If we have it, use the standard function. |
|
1691 |
+ if (function_exists('insertBanGroup')) |
|
1692 |
+ { |
|
1693 |
+ // We don't call checkExistingTriggerIP as it induces a fatal error. |
|
1694 |
+ $request = $smcFunc['db_query']('', ' |
|
1695 |
+ SELECT bg.id_ban_group, bg.name |
|
1696 |
+ FROM {db_prefix}ban_groups AS bg |
|
1697 |
+ INNER JOIN {db_prefix}ban_items AS bi ON |
|
1698 |
+ (bi.id_ban_group = bg.id_ban_group) |
|
1699 |
+ AND ip_low = {inet:ip_low} AND ip_high = {inet:ip_high} |
|
1700 |
+ LIMIT 1', |
|
1701 |
+ array( |
|
1702 |
+ 'ip_low' => $ip_address, |
|
1703 |
+ 'ip_high' => $ip_address, |
|
1704 |
+ ) |
|
1705 |
+ ); |
|
1706 |
+ // Alredy exists, bail out. |
|
1707 |
+ if ($smcFunc['db_num_rows']($request) != 0) |
|
1708 |
+ { |
|
1709 |
+ $smcFunc['db_free_result']($request); |
|
1710 |
+ return false; |
|
1711 |
+ } |
|
1712 |
+ |
|
1713 |
+ // The trigger info. |
|
1714 |
+ $triggers = array( |
|
1715 |
+ array( |
|
1716 |
+ 'ip_low' => $ip_address, |
|
1717 |
+ 'ip_high' => $ip_address, |
|
1718 |
+ ) |
|
1719 |
+ ); |
|
1720 |
+ |
|
1721 |
+ // Add it. |
|
1722 |
+ addTriggers($modSettings['sfs_ipcheck_autoban_group'], $triggers); |
|
1723 |
+ } |
|
1724 |
+ // Go old school. |
|
1725 |
+ else |
|
1726 |
+ { |
|
1727 |
+ $ip_parts = ip2range($ip_address); |
|
1728 |
+ |
|
1729 |
+ // Not valid? Get out. |
|
1730 |
+ if (count($ip_parts) != 4) |
|
1731 |
+ return false; |
|
1732 |
+ |
|
1733 |
+ // We don't call checkExistingTriggerIP as it induces a fatal error. |
|
1734 |
+ $request = $smcFunc['db_query']('', ' |
|
1735 |
+ SELECT bg.id_ban_group, bg.name |
|
1736 |
+ FROM {db_prefix}ban_groups AS bg |
|
1737 |
+ INNER JOIN {db_prefix}ban_items AS bi ON |
|
1738 |
+ (bi.id_ban_group = bg.id_ban_group) |
|
1739 |
+ AND ip_low1 = {int:ip_low1} AND ip_high1 = {int:ip_high1} |
|
1740 |
+ AND ip_low2 = {int:ip_low2} AND ip_high2 = {int:ip_high2} |
|
1741 |
+ AND ip_low3 = {int:ip_low3} AND ip_high3 = {int:ip_high3} |
|
1742 |
+ AND ip_low4 = {int:ip_low4} AND ip_high4 = {int:ip_high4} |
|
1743 |
+ LIMIT 1', |
|
1744 |
+ array( |
|
1745 |
+ 'ip_low1' => $ip_parts[0]['low'], |
|
1746 |
+ 'ip_high1' => $ip_parts[0]['high'], |
|
1747 |
+ 'ip_low2' => $ip_parts[1]['low'], |
|
1748 |
+ 'ip_high2' => $ip_parts[1]['high'], |
|
1749 |
+ 'ip_low3' => $ip_parts[2]['low'], |
|
1750 |
+ 'ip_high3' => $ip_parts[2]['high'], |
|
1751 |
+ 'ip_low4' => $ip_parts[3]['low'], |
|
1752 |
+ 'ip_high4' => $ip_parts[3]['high'], |
|
1753 |
+ ) |
|
1754 |
+ ); |
|
1755 |
+ // Alredy exists, bail out. |
|
1756 |
+ if ($smcFunc['db_num_rows']($request) != 0) |
|
1757 |
+ { |
|
1758 |
+ $smcFunc['db_free_result']($request); |
|
1759 |
+ return false; |
|
1760 |
+ } |
|
1761 |
+ |
|
1762 |
+ $ban_triggers[] = array( |
|
1763 |
+ $modSettings['sfs_ipcheck_autoban_group'], |
|
1764 |
+ $ip_parts[0]['low'], |
|
1765 |
+ $ip_parts[0]['high'], |
|
1766 |
+ $ip_parts[1]['low'], |
|
1767 |
+ $ip_parts[1]['high'], |
|
1768 |
+ $ip_parts[2]['low'], |
|
1769 |
+ $ip_parts[2]['high'], |
|
1770 |
+ $ip_parts[3]['low'], |
|
1771 |
+ $ip_parts[3]['high'], |
|
1772 |
+ '', |
|
1773 |
+ '', |
|
1774 |
+ 0, |
|
1775 |
+ ); |
|
1776 |
+ |
|
1777 |
+ $smcFunc['db_insert']('', |
|
1778 |
+ '{db_prefix}ban_items', |
|
1779 |
+ array( |
|
1780 |
+ 'id_ban_group' => 'int', 'ip_low1' => 'int', 'ip_high1' => 'int', 'ip_low2' => 'int', 'ip_high2' => 'int', |
|
1781 |
+ 'ip_low3' => 'int', 'ip_high3' => 'int', 'ip_low4' => 'int', 'ip_high4' => 'int', 'hostname' => 'string-255', |
|
1782 |
+ 'email_address' => 'string-255', 'id_member' => 'int', |
|
1783 |
+ ), |
|
1784 |
+ $ban_triggers, |
|
1785 |
+ array('id_ban') |
|
1786 |
+ ); |
|
1787 |
+ } |
|
1556 | 1788 |
|
1789 |
+ // Log this. The log will show from the user/guest and ip of spammer. |
|
1790 |
+ logAction('ban', array( |
|
1791 |
+ 'ip_range' => $ip_address, |
|
1792 |
+ 'new' => 1, |
|
1793 |
+ 'source' => 'sfs' |
|
1794 |
+ )); |
|
1795 |
+ |
|
1796 |
+ // Let things know we need updated ban data. |
|
1797 |
+ updateSettings(array('banLastUpdated' => time())); |
|
1798 |
+ updateBanMembers(); |
|
1799 |
+ |
|
1800 |
+ return true; |
|
1557 | 1801 |
} |
1558 | 1802 |
} |
1559 | 1803 |
\ No newline at end of file |
... | ... |
@@ -11,6 +11,7 @@ $txt['sfs_general_title'] = 'General Configuration'; |
11 | 11 |
$txt['sfs_enabled'] = 'Enable Stop Forum Spam?'; |
12 | 12 |
$txt['sfs_log_debug'] = 'Enable Logging of all SFS requests (Debugging Only)?'; |
13 | 13 |
$txt['sfs_ipcheck'] = 'Check IP Address?'; |
14 |
+$txt['sfs_ipcheck_autoban'] = 'Automatically ban IPs that are blacklisted?'; |
|
14 | 15 |
$txt['sfs_usernamecheck'] = 'Check Username?'; |
15 | 16 |
$txt['sfs_emailcheck'] = 'Check Email? (Recommended)'; |
16 | 17 |
|
... | ... |
@@ -77,3 +78,10 @@ $txt['sfs_log_types_0'] = 'Debug'; |
77 | 78 |
$txt['sfs_log_types_1'] = 'Username'; |
78 | 79 |
$txt['sfs_log_types_2'] = 'Email'; |
79 | 80 |
$txt['sfs_log_types_3'] = 'IP Address'; |
81 |
+$txt['sfs_log_matched_on'] = 'Matched on %1$s [%2$s]'; |
|
82 |
+$txt['sfs_log_auto_banned'] = 'Banned'; |
|
83 |
+ |
|
84 |
+// The ban group info. |
|
85 |
+$txt['sfs_ban_group_name'] = 'SFS Automatic IP Bans'; |
|
86 |
+$txt['sfs_ban_group_reason'] = 'Your IP has triggered the automatic ban for poor reputation and has been blacklisted'; |
|
87 |
+$txt['sfs_ban_group_notes'] = 'This Group is automatically created by the Stop Forum Spam Customization and automatically will add IPs that are blacklisted to this group'; |
|
80 | 88 |
\ No newline at end of file |
81 | 89 |