Add files via upload

This commit is contained in:
Harold Finch
2023-04-10 07:18:32 +02:00
committed by GitHub
parent 06ddbf431f
commit 65875d8fef
100 changed files with 84692 additions and 42 deletions

0
libs/iredapd/__init__.py Normal file
View File

535
libs/iredapd/greylist.py Normal file
View File

@@ -0,0 +1,535 @@
# Author: Zhang Huangbin <zhb@iredmail.org>
import web
from libs import iredutils
from libs.logger import logger
def get_all_greylist_settings():
"""Return all existing greylisting settings."""
gl_settings = {}
try:
qr = web.conn_iredapd.select(
'greylisting',
what='id, account, sender, active',
)
if qr:
gl_settings = list(qr)
except Exception as e:
logger.error(e)
return gl_settings
def get_greylist_setting(account=None):
"""Return greylisting setting of specified account."""
gl_setting = {}
if not account:
account = '@.'
if not iredutils.is_valid_amavisd_address(account):
return gl_setting
try:
qr = web.conn_iredapd.select(
'greylisting',
vars={'account': account},
what='id, account, sender, active',
where="""account = $account AND sender='@.'""",
limit=1,
)
if qr:
gl_setting = qr[0]
except Exception as e:
logger.error(e)
return gl_setting
def get_greylist_whitelists(account, address_only=False):
"""Return greylisting whitelists of specified account."""
if not iredutils.is_valid_amavisd_address(account):
return []
whitelists = []
try:
qr = web.conn_iredapd.select(
'greylisting_whitelists',
vars={'account': account},
what='id, sender, comment',
where='account = $account',
order='sender',
)
if qr:
whitelists = list(qr)
# Don't explore SQL structure, just export the sender addresses
if address_only and whitelists:
wl = []
for i in whitelists:
wl.append(i.sender.lower())
whitelists = wl
except Exception as e:
logger.error(e)
return whitelists
def get_greylist_whitelist_domains():
"""Return greylisting whitelist domains of specified account."""
domains = []
try:
qr = web.conn_iredapd.select(
'greylisting_whitelist_domains',
what='domain',
order='domain',
)
if qr:
for i in qr:
domains.append(str(i.domain).lower())
except Exception as e:
logger.error(e)
return domains
def delete_greylist_setting(account, senders=None):
"""Delete greylisting setting of specified account."""
if not iredutils.is_valid_amavisd_address(account):
return True
try:
if senders:
web.conn_iredapd.delete(
'greylisting',
vars={'account': account, 'senders': senders},
where="""account = $account AND sender IN $sender""",
)
else:
web.conn_iredapd.delete(
'greylisting',
vars={'account': account},
where="""account = $account""",
)
return True,
except Exception as e:
return False, repr(e)
def enable_disable_greylist_setting(account, enable=False):
"""Update (or create) greylisting setting of specified account."""
account_type = iredutils.is_valid_amavisd_address(account)
if not account_type:
return False, 'INVALID_ACCOUNT'
active = 0
if enable:
active = 1
gl_setting = {'account': account,
'priority': iredutils.IREDAPD_ACCOUNT_PRIORITIES.get(account_type, 0),
'sender': '@.',
'sender_priority': 0,
'active': active}
try:
# Delete existing record first.
web.conn_iredapd.delete(
'greylisting',
vars={'account': account, 'sender': gl_setting['sender']},
where='account = $account AND sender = $sender',
)
# Create new record
web.conn_iredapd.insert('greylisting', **gl_setting)
except Exception as e:
return False, repr(e)
return True,
def reset_greylist_whitelist_domains(domains=None):
"""Update greylisting whitelist domains for specified account.
@domains -- must be a list/tuple/set
@conn -- sql connection cursor
"""
# Delete existing records first
try:
web.conn_iredapd.delete('greylisting_whitelist_domains', where='1=1')
except Exception as e:
return False, repr(e)
# Insert new records
if domains:
values = []
for d in domains:
values += [{'domain': d}]
try:
web.conn_iredapd.multiple_insert('greylisting_whitelist_domains', values=values)
except Exception as e:
return False, repr(e)
return True, 'GL_WLD_UPDATED'
def update_greylist_whitelist_domains(new=None, removed=None):
"""Add new or remove existing whitelist SPF domains for greylisting service.
@new - must be a list/tuple/set of sender domains
@removed - must be a list/tuple/set of sender domains
@conn - sql connection cursor
"""
_new = []
if new:
_new = [str(i).lower()
for i in new
if iredutils.is_domain(i)]
_new = list(set(_new))
_removed = []
if removed:
_removed = [str(i).lower()
for i in removed
if iredutils.is_domain(i)]
_removed = list(set(_removed))
# Remove duplicates
_removed = [i for i in _removed if i not in _new]
if not (_new or _removed):
return True,
# Insert new whitelists
if _new:
for i in _new:
try:
web.conn_iredapd.insert('greylisting_whitelist_domains', domain=i)
except Exception as e:
logger.error(e)
# Remove existing ones
if _removed:
try:
web.conn_iredapd.delete(
'greylisting_whitelist_domains',
vars={'removed': _removed},
where='domain IN $removed',
)
except Exception as e:
logger.error(e)
return True,
def reset_greylist_whitelists(account, whitelists=None):
"""Reset greylisting whitelists for specified account.
If `whitelists` is empty, all existing whitelists will be removed.
@whitelists - must be a list/tuple/set of whitelist senders, or a list of
dict which maps to sql column/value pairs. e.g.
[{'account': '@.',
'sender': '192.168.1.1',
'comment': ''},
...]
"""
if not iredutils.is_valid_amavisd_address(account):
return False, 'INVALID_ACCOUNT'
# Delete existing whitelists first
try:
web.conn_iredapd.delete(
'greylisting_whitelists',
vars={'account': account},
where='account = $account',
)
except Exception as e:
return False, repr(e)
# Insert new whitelists
if whitelists:
for w in whitelists:
if isinstance(w, dict):
try:
web.conn_iredapd.insert('greylisting_whitelists', **w)
except:
pass
elif isinstance(w, str):
try:
web.conn_iredapd.insert(
'greylisting_whitelists',
account=account,
sender=w,
)
except:
pass
return True,
def update_greylist_whitelists(account, new=None, removed=None):
"""Add new or remove existing greylisting whitelists for specified account.
:param account: must be an valid iRedAPD account
:param new: must be a list/tuple/set of whitelist senders
:param removed: must be a list/tuple/set of whitelist senders
"""
if not iredutils.is_valid_amavisd_address(account):
return False, 'INVALID_ACCOUNT'
_new = []
if new:
_new = [str(i).lower()
for i in new
if iredutils.is_valid_wblist_address(i)]
_new = list(set(_new))
_removed = []
if removed:
_removed = [str(i).lower()
for i in removed
if iredutils.is_valid_wblist_address(i)]
_removed = list(set(_removed))
# Remove duplicates
_removed = [i for i in _removed if i not in _new]
if not (_new or _removed):
return True,
# Insert new whitelists
if _new:
for w in _new:
try:
web.conn_iredapd.insert(
'greylisting_whitelists',
account=account,
sender=w,
)
except:
pass
# Remove existing ones
if _removed:
try:
web.conn_iredapd.delete(
'greylisting_whitelists',
vars={'removed': removed},
where='sender IN $removed',
)
except:
pass
return True,
def update_greylist_settings_from_form(account, form):
# Enable/disable greylisting
# @inherit - inherit from global setting
# @enable - explicitly enable
# @disable - explicitly disable
_gl_value = form.get('greylisting', 'inherit')
if _gl_value == 'inherit':
# Delete greylisting setting
qr = delete_greylist_setting(account=account)
elif _gl_value == 'enable':
qr = enable_disable_greylist_setting(account=account, enable=True)
elif _gl_value == 'disable':
qr = enable_disable_greylist_setting(account=account, enable=False)
else:
return True, 'GL_UPDATED'
if qr[0] is not True:
return qr
# Update greylisting whitelist domains.
if account == '@.':
wl_domains = set()
lines = form.get('whitelist_domains', '').splitlines()
for line in lines:
if iredutils.is_domain(line):
wl_domains.add(str(line).lower())
qr = reset_greylist_whitelist_domains(domains=wl_domains)
if not qr[0]:
return qr
# Update greylisting whitelists.
whitelists = []
# Store senders to avoid duplicate
_senders = set()
lines = form.get('whitelists', '').splitlines()
for line in lines:
# Split sender and comment with '#'
wl = line.split('#', 1)
sender = ''
comment = ''
if len(wl) == 1:
sender = str(wl[0]).strip()
comment = ''
elif len(wl) == 2:
sender = str(wl[0]).strip()
comment = wl[1].strip()
# Validate sender.
if not iredutils.is_valid_wblist_address(sender):
continue
if sender not in _senders:
whitelists += [{'account': account, 'sender': sender, 'comment': comment}]
_senders.add(sender)
qr = reset_greylist_whitelists(account=account, whitelists=whitelists)
if qr[0]:
return True, 'GL_UPDATED'
else:
return qr
def delete_settings_for_removed_users(mails):
mails = [str(v).lower() for v in mails if iredutils.is_email(v)]
if not mails:
return True,
try:
# Delete settings for user
web.conn_iredapd.delete(
'greylisting',
vars={'mails': mails},
where="""account IN $mails""",
)
# Delete whitelists
web.conn_iredapd.delete(
'greylisting_whitelists',
vars={'mails': mails},
where='account IN $mails',
)
# Delete greylisting tracking
web.conn_iredapd.delete(
'greylisting_tracking',
vars={'mails': mails},
where="""recipient IN $mails""",
)
return True,
except Exception as e:
return False, repr(e)
def delete_settings_for_removed_domain(domain):
if not iredutils.is_domain(domain):
return True,
try:
# Delete settings for domain ('@domain.com')
web.conn_iredapd.delete(
'greylisting',
vars={'domain': '@' + domain},
where='account=$domain',
)
# Delete settings for all users under this domain
web.conn_iredapd.delete(
'greylisting',
vars={'domain': '%@' + domain},
where="""account LIKE $domain""",
)
# Delete whitelists
web.conn_iredapd.delete(
'greylisting_whitelists',
vars={'domain': '@' + domain},
where='account=$domain',
)
web.conn_iredapd.delete(
'greylisting_whitelists',
vars={'domain': '%@' + domain},
where='account LIKE $domain',
)
# Delete greylisting tracking
web.conn_iredapd.delete(
'greylisting_tracking',
vars={'domain': domain},
where='rcpt_domain=$domain',
)
return True,
except Exception as e:
return False, repr(e)
def get_tracking_data(account):
"""Get tracking data of given local account."""
_account_type = iredutils.is_valid_amavisd_address(account)
if not _account_type:
return True, []
try:
if _account_type == 'catchall':
# account = '@.'
qr = web.conn_iredapd.select(
'greylisting_tracking',
what='COUNT(blocked_count) AS total, sender_domain',
where='passed=0',
group='sender_domain',
order='total DESC',
)
elif _account_type == 'domain':
domain = account.lstrip('@')
qr = web.conn_iredapd.select(
'greylisting_tracking',
vars={'domain': domain},
where='sender_domain=$domain AND passed=0',
order='init_time DESC',
)
else:
return False, 'INVALID_ACCOUNT'
return True, list(qr)
except Exception as e:
return False, repr(e)
def get_domain_tracking_data(domain):
"""Get tracking data of given domain."""
domain = str(domain).lower()
return get_tracking_data(account='@' + domain)
def filter_whitelisted_ips(ips):
"""Return list of (globally) whitelisted IPs."""
ips = [i for i in ips if iredutils.is_strict_ip(i)]
if not ips:
return True, []
try:
qr = web.conn_iredapd.select(
'greylisting_whitelists',
vars={'account': '@.', 'ips': ips},
what='sender',
where='account=$account AND sender IN $ips',
order='sender',
)
whitelisted_ips = [i.sender for i in qr]
return True, whitelisted_ips
except Exception as e:
logger.error(e)
return False, repr(e)

286
libs/iredapd/log.py Normal file
View File

@@ -0,0 +1,286 @@
# Author: Zhang Huangbin <zhb@iredmail.org>
import time
import web
import settings
from libs import iredutils
from libs.logger import logger
if settings.backend == 'ldap':
from libs.ldaplib.admin import get_managed_domains
else:
from libs.sqllib.admin import get_managed_domains
session = web.config.get('_session')
def __get_managed_domains():
domains = []
kw = {'admin': session.get('username'),
'domain_name_only': True,
'conn': None}
if settings.backend != 'ldap':
kw['listed_only'] = True
qr = get_managed_domains(**kw)
if qr[0]:
domains = qr[1]
return domains
def get_num_rejected(hours=None):
"""Return amount of rejected mails in last given `hours`."""
num = 0
if not hours:
hours = 24
sql_vars = {
"action": "REJECT",
"time_num": (int(time.time()) - (hours * 3600)),
}
sql_wheres = ["action = $action AND time_num >= $time_num"]
if not session.get('is_global_admin'):
domains = __get_managed_domains()
if domains:
sql_vars['domains'] = domains
sql_wheres += ['(sender_domain IN $domains OR sasl_username IN $domains OR recipient_domain IN $domains)']
else:
return num
sql_where = ' AND '.join(sql_wheres)
try:
qr = web.conn_iredapd.select(
'smtp_sessions',
vars=sql_vars,
what="COUNT(id) AS total",
where=sql_where,
)
if qr:
num = qr[0]['total']
except Exception as e:
logger.error(e)
return num
def get_num_smtp_outbound_sessions(hours=None):
"""Return amount of smtp authentications in last given `hours`."""
num = 0
if not hours:
hours = 24
sql_vars = {
"time_num": (int(time.time()) - (hours * 3600)),
}
sql_wheres = ["sasl_username <> '' AND time_num >= $time_num"]
if not session.get('is_global_admin'):
domains = __get_managed_domains()
if domains:
sql_vars['domains'] = domains
sql_wheres += ['sasl_domain IN $domains']
else:
return num
sql_where = ' AND '.join(sql_wheres)
try:
qr = web.conn_iredapd.select(
'smtp_sessions',
vars=sql_vars,
what="COUNT(id) AS total",
where=sql_where,
)
if qr:
num = qr[0]['total']
except Exception as e:
logger.error(e)
return num
def get_log_smtp_sessions(domains=None,
sasl_usernames=None,
senders=None,
recipients=None,
client_addresses=None,
encryption_protocols=None,
outbound_only=False,
rejected_only=False,
offset=None,
limit=None):
"""Return a dict with amount of smtp rejections and list of (SQL) rows."""
result = {'total': 0, 'rows': []}
if not offset or not isinstance(offset, int):
offset = 0
if not limit or not isinstance(limit, int):
limit = settings.PAGE_SIZE_LIMIT
query_domains = []
sql_vars = {}
sql_wheres = []
sql_where = None
if domains:
query_domains = [str(i).lower() for i in domains if iredutils.is_domain(i)]
if session.get('is_global_admin'):
if query_domains:
sql_vars['domains'] = query_domains
if outbound_only:
sql_wheres += ['sasl_domain IN $domains']
else:
sql_wheres += ['(sender_domain IN $domains OR sasl_domain IN $domains OR recipient_domain IN $domains)']
else:
if outbound_only:
sql_wheres += ["sasl_username <> ''"]
else:
managed_domains = __get_managed_domains()
if not managed_domains:
return result
if domains:
query_domains = [str(i).lower() for i in domains if i in managed_domains]
if not query_domains:
return result
else:
query_domains = managed_domains
sql_vars['domains'] = query_domains
if outbound_only:
sql_wheres += ['sasl_domain in $domains']
else:
sql_wheres += ['(sender_domain IN $domains OR sasl_domain IN $domains OR recipient_domain IN $domains)']
if sasl_usernames:
sql_vars['sasl_usernames'] = [str(i).lower() for i in sasl_usernames if iredutils.is_email(i)]
sql_wheres += ['sasl_username IN $sasl_usernames']
if senders:
sql_vars['senders'] = [str(i).lower() for i in senders if iredutils.is_email(i)]
sql_wheres += ['sender IN $senders']
if recipients:
sql_vars['recipients'] = [str(i).lower() for i in recipients if iredutils.is_email(i)]
sql_wheres += ['recipient IN $recipients']
if client_addresses:
sql_vars['client_addresses'] = [i for i in client_addresses if iredutils.is_strict_ip(i)]
sql_wheres += ['client_address IN $client_addresses']
if encryption_protocols:
sql_vars['encryption_protocols'] = encryption_protocols
sql_wheres += ['encryption_protocol IN $encryption_protocols']
if rejected_only:
sql_wheres += ["action='REJECT'"]
if sql_wheres:
sql_where = ' AND '.join(sql_wheres)
try:
qr = web.conn_iredapd.select(
'smtp_sessions',
vars=sql_vars,
what='COUNT(id) AS total',
where=sql_where,
)
if qr:
result['total'] = qr[0].total
except Exception as e:
logger.error(e)
columns = [
'id', 'time', 'time_num',
'action', 'reason', 'instance',
'sasl_username', 'sender', 'recipient',
'client_address', 'encryption_protocol',
]
try:
qr = web.conn_iredapd.select(
'smtp_sessions',
vars=sql_vars,
what=','.join(columns),
where=sql_where,
order='time_num DESC',
offset=offset,
limit=limit,
)
if qr:
result['rows'] = list(qr)
except Exception as e:
logger.error(e)
return result
def get_smtp_insecure_outbound(hours=None):
"""
Return info of insecure smtp outbound sessions in last given `hours`.
(True, {'total': '<int>', 'usernames': [<mail>, <mail>, ...]})
(False, '<error>')
"""
result = {'total': 0, 'usernames': []}
if not isinstance(hours, int):
hours = 24
sql_vars = {
"time_num": (int(time.time()) - (hours * 3600)),
}
sql_wheres = ["sasl_username <> '' AND encryption_protocol = '' AND time_num >= $time_num"]
if not session.get('is_global_admin'):
domains = __get_managed_domains()
if domains:
sql_vars['domains'] = domains
sql_wheres += ['sasl_domain IN $domains']
else:
return True, result
sql_where = ' AND '.join(sql_wheres)
try:
qr = web.conn_iredapd.select(
'smtp_sessions',
vars=sql_vars,
what='sasl_username',
where=sql_where,
group='sasl_username',
)
for row in qr:
result['total'] += 1
_email = str(row['sasl_username']).lower().strip()
result['usernames'].append(_email)
result['usernames'].sort()
return True, result
except Exception as e:
logger.error(e)
return False, repr(e)

180
libs/iredapd/throttle.py Normal file
View File

@@ -0,0 +1,180 @@
# Author: Zhang Huangbin <zhb@iredmail.org>
import web
from libs import iredutils
def get_throttle_setting(account, inout_type='outbound'):
"""Get throttle setting.
@account -- a valid throttling account
@inout_type -- inbound, outbound
"""
setting = {}
if not iredutils.is_valid_amavisd_address(account):
return setting
qr = web.conn_iredapd.select(
'throttle',
vars={'account': account, 'inout_type': inout_type},
where='kind=$inout_type AND account=$account',
limit=1,
)
if qr:
setting = qr[0]
return setting
def delete_throttle_setting(account, inout_type):
if not iredutils.is_valid_amavisd_address(account):
return False, 'INVALID_ACCOUNT'
if not (inout_type in ['inbound', 'outbound']):
return False, 'INVALID_INOUT_TYPE'
if account and inout_type:
web.conn_iredapd.delete(
'throttle',
vars={'account': account, 'inout_type': inout_type},
where='account=$account AND kind=$inout_type',
)
return True,
return True,
def delete_throttle_tracking(account, inout_type):
tid = get_throttle_id(account, inout_type)
if tid:
try:
web.conn_iredapd.delete(
'throttle_tracking',
vars={'tid': tid},
where='tid=$tid',
)
except Exception as e:
return False, repr(e)
return True,
def delete_settings_for_removed_users(mails):
mails = [str(v).lower() for v in mails if iredutils.is_email(v)]
if not mails:
return True,
try:
web.conn_iredapd.delete(
'throttle',
vars={'mails': mails},
where="""account IN $mails""",
)
web.conn_iredapd.delete(
'throttle_tracking',
vars={'mails': mails},
where="""account IN $mails""",
)
return True,
except Exception as e:
return False, repr(e)
def delete_settings_for_removed_domain(domain):
if not iredutils.is_domain(domain):
return True,
try:
# Delete settings for domain ('@domain.com')
web.conn_iredapd.delete(
'throttle',
vars={'domain': '@' + domain},
where='account=$domain',
)
# Delete settings for all users under this domain
web.conn_iredapd.delete(
'throttle',
vars={'domain': '%@' + domain},
where="""account LIKE $domain""")
web.conn_iredapd.delete(
'throttle_tracking',
vars={'domain': '%@' + domain},
where="""account LIKE $domain""",
)
return True,
except Exception as e:
return False, repr(e)
def get_throttle_id(account, inout_type):
tid = None
# get `throttle.id`
qr = web.conn_iredapd.select(
'throttle',
vars={'account': account, 'inout_type': inout_type},
where='account=$account AND kind=$inout_type',
limit=1,
)
if qr:
tid = qr[0].id
return tid
def add_throttle(account,
setting,
inout_type='inbound'):
if not setting:
# Delete tracking and setting
delete_throttle_tracking(account=account, inout_type=inout_type)
delete_throttle_setting(account=account, inout_type=inout_type)
return True,
# Delete record if
# - no period. (period == 0) means disabled
# - account mismatch
# - account is '@.' (global setting) and no valid setting (all are 0)
# - account is not '@.' (not global setting) and no valid setting (all are -1)
if (not setting.get('period', 0)) \
or (account != setting.get('account')) \
or (account == '@.'
and (not setting.get('max_msgs'))
and (not setting.get('msg_size'))
and (not setting.get('max_quota'))
and (not setting.get("max_rcpts"))) \
or (account != '@.'
and setting.get("max_msgs") == -1
and setting.get("msg_size") == -1
and setting.get("max_quota") == -1
and setting.get("max_rcpts") in (None, -1)):
delete_throttle_tracking(account=account, inout_type=inout_type)
delete_throttle_setting(account=account, inout_type=inout_type)
else:
try:
# Get `throttle.id` if there's a setting.
tid = get_throttle_id(account=account, inout_type=inout_type)
if tid:
# Update existing setting
web.conn_iredapd.update(
'throttle',
vars={'tid': tid},
where='id=$tid',
**setting)
else:
# Add new throttle setting.
web.conn_iredapd.insert('throttle', **setting)
except Exception as e:
return False, repr(e)
return True,

28
libs/iredapd/utils.py Normal file
View File

@@ -0,0 +1,28 @@
# Author: Zhang Huangbin <zhb@iredmail.org>
from libs import iredutils
from libs.iredapd import throttle as iredapd_throttle
from libs.iredapd import greylist as iredapd_greylist
def delete_settings_for_removed_users(mails):
try:
iredapd_greylist.delete_settings_for_removed_users(mails=mails)
iredapd_throttle.delete_settings_for_removed_users(mails=mails)
return True,
except Exception as e:
return False, repr(e)
def delete_settings_for_removed_domains(domains):
domains = [str(d).lower() for d in domains if iredutils.is_domain(d)]
if not domains:
return True,
for d in domains:
iredapd_throttle.delete_settings_for_removed_domain(domain=d)
iredapd_greylist.delete_settings_for_removed_domain(domain=d)
return True,

View File

@@ -0,0 +1,66 @@
# Author: Zhang Huangbin <zhb@iredmail.org>
import web
def get_wblist_rdns():
"""Get wblist of rDNS."""
whitelists = []
blacklists = []
try:
qr = web.conn_iredapd.select(
'wblist_rdns',
what='rdns,wb',
order='rdns',
)
for i in qr:
_rdns = str(i.rdns).lower()
if i.wb == 'W':
whitelists.append(_rdns)
elif i.wb == 'B':
blacklists.append(_rdns)
return True, {'whitelists': whitelists, 'blacklists': blacklists}
except Exception as e:
return False, repr(e)
def reset_wblist_rdns(whitelists=None, blacklists=None):
"""Reset wblist rdns.
@whitelists -- a list/tuple/set of whitelist rdns domain names. Notes:
- if it's None, no reset.
- if it's empty list/tuple/set, all existing records will be
removed.
@blacklists -- a list/tuple/set of blacklist rdns domain names.
@conn -- sql connection cursor
"""
if whitelists and blacklists:
# Remove duplicate records
blacklists = [i for i in blacklists if i not in whitelists]
# Delete first to avoid possible duplicate records while inserting new
# records later.
for (_lists, _wb) in [(whitelists, 'W'), (blacklists, 'B')]:
if _lists is not None:
try:
# Delete all existing records first
web.conn_iredapd.delete(
'wblist_rdns',
vars={'wb': _wb},
where='WB=$wb',
)
except Exception as e:
return False, repr(e)
# Insert new records
for (_lists, _wb) in [(whitelists, 'W'), (blacklists, 'B')]:
if _lists:
for i in _lists:
try:
web.conn_iredapd.insert('wblist_rdns', rdns=i, wb=_wb)
except:
pass
return True, 'UPDATED'

View File

@@ -0,0 +1,83 @@
import web
from libs import iredutils
# `4102444799` seconds since 1970-01-01 is '2099-12-31 23:59:59'.
# It's a trick to use this time as whitelist and not cleaned by
# script `tools/cleanup_db.py`.
# It's ok to use any long epoch seconds to avoid cleanup, but we use this
# hard-coded value for easier management.
expire_epoch_seconds = 4102444799
def get_whitelists():
total = 0
ips = []
try:
qr = web.conn_iredapd.select(
"senderscore_cache",
vars={'seconds': expire_epoch_seconds},
what='COUNT(client_address) AS total',
where="time=$seconds",
)
total = qr[0].total
if total:
qr = web.conn_iredapd.select(
"senderscore_cache",
vars={'seconds': expire_epoch_seconds},
what='client_address',
where="time=$seconds",
)
ips = [i.client_address for i in qr]
return True, {'total': total, 'ips': ips}
except Exception as e:
return False, repr(e)
def filter_whitelisted_ips(ips):
# Return a list of whitelisted IP addresses of given ones.
ips = [i for i in ips if iredutils.is_strict_ip(i)]
try:
qr = web.conn_iredapd.select(
"senderscore_cache",
vars={'ips': ips, 'seconds': expire_epoch_seconds},
what='client_address',
where="client_address IN $ips AND time=$seconds",
)
ips = [i.client_address for i in qr]
return True, ips
except Exception as e:
return False, repr(e)
def whitelist_ips(ips):
# Whitelist given IP addresses.
ips = [i for i in ips if iredutils.is_strict_ip(i)]
if not ips:
return True,
# Remove existing records first.
try:
web.conn_iredapd.delete("senderscore_cache",
vars={'ips': ips},
where="client_address IN $ips")
rows = []
for ip in ips:
rows += [{'client_address': ip,
'score': 100,
'time': expire_epoch_seconds}]
# Insert whitelists.
web.conn_iredapd.multiple_insert("senderscore_cache", rows)
return True,
except Exception as e:
return False, repr(e)