Add files via upload

This commit is contained in:
Harold Finch
2023-04-10 07:20:22 +02:00
committed by GitHub
parent 65875d8fef
commit 82d4ef7fa9
100 changed files with 20541 additions and 0 deletions

View File

View File

@@ -0,0 +1,416 @@
import web
from controllers.utils import api_render
from libs import iredutils
from libs.iredapd import greylist as lib_greylist
import settings
if settings.backend == 'ldap':
from libs.ldaplib import decorators
else:
from libs.sqllib import decorators
def convert_greylist_setting_to_api_json(greylist_setting=None):
"""Return dict with simplified information as API result."""
if not greylist_setting:
greylist_setting = {}
_status = greylist_setting.get('active', 'inherit')
status = 'inherit'
if _status == 1:
status = 'enabled'
elif _status == 0:
status = 'disabled'
return api_render((True, {'status': status}))
class APIAllSettings:
@decorators.api_require_global_admin
def GET(self):
"""Get all existing greylisting settings.
curl -X GET -i -b cookie.txt https://<server>/api/greylisting/all
"""
s = lib_greylist.get_all_greylist_settings()
_all_settings = {}
for i in s:
_sender = str(i.sender).lower()
_account = str(i.account).lower()
_active = int(i.active)
_setting = {'sender': _sender,
'account': _account}
if _active == 1:
_setting['status'] = 'enabled'
else:
_setting['status'] = 'disabled'
if _account in _all_settings:
_all_settings[_account] += [_setting]
else:
_all_settings[_account] = [_setting]
return api_render((True, _all_settings))
class APIGlobalSetting:
@decorators.api_require_global_admin
def GET(self):
"""Get global greylisting setting.
curl -X GET -i -b cookie.txt https://<server>/api/greylisting/global
"""
s = lib_greylist.get_greylist_setting(account='@.')
# If no greylisting setting, mark it as explicitly disabled.
if not s:
s = {'active': 0}
return convert_greylist_setting_to_api_json(s)
@decorators.api_require_global_admin
def POST(self):
"""Set global greylisting setting.
curl -X POST -i -b cookie.txt -d "status=enable" https://<server>/api/greylisting/global
Required parameters:
@status -- Explicitly enable or disable greylisting globally.
Possible values: enable, disable.
"""
form = web.input(_unicode=False)
enable = True
if form.get('status') == 'disable':
enable = False
qr = lib_greylist.enable_disable_greylist_setting(account='@.', enable=enable)
return api_render(qr)
class APIDomainSetting:
@decorators.api_require_domain_access
def GET(self, domain):
"""Get per-domain greylisting setting.
curl -X GET -i -b cookie.txt https://<server>/api/greylisting/<domain>
"""
domain = str(domain).lower()
s = lib_greylist.get_greylist_setting(account='@' + domain)
return convert_greylist_setting_to_api_json(s)
@decorators.api_require_domain_access
def POST(self, domain):
"""Set per-domain greylisting setting.
curl -X POST -i -b cookie.txt -d "status=enable" https://<server>/api/greylisting/<domain>
Required parameters:
@status -- Explicitly enable or disable greylisting globally.
Possible values: enable, disable.
"""
form = web.input(_unicode=False)
domain = str(domain).lower()
status = form.get('status', 'inherit').lower()
if status in ['enable', 'disable']:
enable = (status == 'enable')
qr = lib_greylist.enable_disable_greylist_setting(account='@' + domain, enable=enable)
else:
# Remove setting
qr = lib_greylist.delete_greylist_setting(account='@' + domain)
return api_render(qr)
class APIUserSetting:
@decorators.api_require_domain_access
def GET(self, mail):
"""Get per-user greylisting setting.
curl -X GET -i -b cookie.txt https://<server>/api/greylisting/<mail>
"""
mail = str(mail).lower()
s = lib_greylist.get_greylist_setting(account=mail)
return convert_greylist_setting_to_api_json(s)
@decorators.api_require_domain_access
def POST(self, mail):
"""Set per-user greylisting setting.
curl -X POST -i -b cookie.txt -d "status=enable" https://<server>/api/greylisting/<mail>
Required parameters:
@status -- Explicitly enable or disable greylisting globally.
Possible values: enable, disable.
"""
form = web.input(_unicode=False)
status = form.get('status', 'inherit').lower()
mail = str(mail).lower()
if status in ['enable', 'disable']:
enable = (status == 'enable')
qr = lib_greylist.enable_disable_greylist_setting(account=mail, enable=enable)
else:
# Remove setting
qr = lib_greylist.delete_greylist_setting(account=mail)
return api_render(qr)
def _get_account_whitelists(account):
account = str(account).lower()
if not (iredutils.is_domain(account)
or iredutils.is_email(account)
or account == '@.'):
return False, 'INVALID_ACCOUNT'
if iredutils.is_domain(account):
account = '@' + account
wl = lib_greylist.get_greylist_whitelists(account=account, address_only=True)
_result = {'whitelists': wl}
if account == '@.':
wl_domains = lib_greylist.get_greylist_whitelist_domains()
_result['whitelist_domains'] = wl_domains
return True, _result
def _update_account_whitelists(account, form):
account = str(account).lower()
if not (iredutils.is_domain(account)
or iredutils.is_email(account)
or account == '@.'):
return False, 'INVALID_ACCOUNT'
if iredutils.is_domain(account):
account = '@' + account
if 'senders' in form:
# Reset whitelisted senders
_senders = form.get('senders', '').strip().split(',')
_senders = [str(i).lower()
for i in _senders
if iredutils.is_valid_wblist_address(i)]
_senders = list(set(_senders))
qr = lib_greylist.reset_greylist_whitelists(account=account,
whitelists=_senders)
if not qr[0]:
return qr
else:
# Add new whitelist senders
_new = []
if 'addSenders' in form:
_new = form.get('addSenders', '').strip().split(',')
# Remove existing ones
_removed = []
if 'removeSenders' in form:
_removed = form.get('removeSenders', '').strip().split(',')
qr = lib_greylist.update_greylist_whitelists(account=account,
new=_new,
removed=_removed)
if not qr[0]:
return qr
return True,
class APIGlobalWhitelists:
@decorators.api_require_global_admin
def GET(self):
"""Get globally whitelisted senders for greylisting service.
curl -X GET -i -b cookie.txt https://<server>/api/greylisting/global/whitelists
"""
qr = _get_account_whitelists(account='@.')
return api_render(qr)
@decorators.api_require_global_admin
def POST(self):
"""Set global greylisting setting.
curl -X POST -i -b cookie.txt -d "var=value&var2=value2" https://<server>/api/greylisting/global/whitelists
Optional parameters:
@senders - Reset whitelisted senders for global greylisting
service to given senders. Multiple addresses must
be separated by comma. Conflicts with parameter
`addSenders` and `removeSenders`.
@addSenders - Whitelist new senders for greylisting service
globally. Multiple addresses must be separated by
comma. Conflicts with parameter `senders`.
@removeSenders - Remove existing whitelisted senders for
greylisting service globally. Multiple
addresses must be separated by comma.
Conflicts with parameter `senders`.
"""
form = web.input(_unicode=False)
qr = _update_account_whitelists(account='@.', form=form)
if not qr[0]:
return api_render(qr)
return api_render(True)
class APIGlobalWhitelist:
"""Handle single whitelist."""
@decorators.api_require_global_admin
def PUT(self, ip):
"""
Whitelist given IP address globally.
curl -X PUT -i -b cookie.txt https://<server>/api/greylisting/global/whitelist/<ip>
"""
qr = lib_greylist.update_greylist_whitelists(account='@.', new=[ip], removed=None)
return api_render(qr)
class APIDomainWhitelists:
@decorators.api_require_domain_access
def GET(self, domain):
"""Get whitelisted senders for greylisting service for given domain.
curl -X GET -i -b cookie.txt https://<server>/api/greylisting/<domain>/whitelists
"""
qr = _get_account_whitelists(account=domain)
return api_render(qr)
@decorators.api_require_domain_access
def POST(self, domain):
"""Set global greylisting setting.
curl -X POST -i -b cookie.txt -d "var=value&var2=value2" https://<server>/api/greylisting/<domain>/whitelists
Optional parameters:
@senders - Reset whitelisted senders
@addSenders - Whitelist new senders for greylisting service
@removeSenders - Remove existing whitelisted senders
"""
form = web.input(_unicode=False)
qr = _update_account_whitelists(account=domain, form=form)
if not qr[0]:
return api_render(qr)
return api_render(True)
class APIUserWhitelists:
@decorators.api_require_domain_access
def GET(self, mail):
"""Get whitelisted senders for greylisting service for given user.
curl -X GET -i -b cookie.txt https://<server>/api/greylisting/<mail>/whitelists
"""
qr = _get_account_whitelists(account=mail)
return api_render(qr)
@decorators.api_require_domain_access
def POST(self, mail):
"""Set global greylisting setting.
curl -X POST -i -b cookie.txt -d "var=value&var2=value2" https://<server>/api/greylisting/<mail>/whitelists
Optional parameters:
@senders - Reset whitelisted senders
@addSenders - Whitelist new senders for greylisting service
@removeSenders - Remove existing whitelisted senders
"""
form = web.input(_unicode=False)
qr = _update_account_whitelists(account=mail, form=form)
if not qr[0]:
return api_render(qr)
return api_render(True)
def _update_whitelist_spf_domains(form):
if 'domains' in form:
# Reset
_domains = form.get('domains', '').strip().split(',')
_domains = [str(i).lower()
for i in _domains
if iredutils.is_domain(i)]
_domains = list(set(_domains))
qr = lib_greylist.reset_greylist_whitelist_domains(domains=_domains)
if not qr[0]:
return qr
else:
# Add new
_new = []
if 'addDomains' in form:
_new = form.get('addDomains', '').strip().split(',')
# Remove existing ones
_removed = []
if 'removeDomains' in form:
_removed = form.get('removeDomains', '').strip().split(',')
qr = lib_greylist.update_greylist_whitelist_domains(new=_new, removed=_removed)
if not qr[0]:
return qr
return True,
class APIWhitelistSPFDomain:
@decorators.api_require_global_admin
def GET(self):
"""Get whitelisted sender domains (for SPF query) for greylisting service.
curl -X GET -i -b cookie.txt https://<server>/api/greylisting/whitelist_spf_domains
"""
domains = lib_greylist.get_greylist_whitelist_domains()
return api_render((True, {'domains': domains}))
@decorators.api_require_global_admin
def POST(self):
"""Manage whitelisted sender domains (for SPF query) for greylisting service.
curl -X POST -i -b cookie.txt -d "var=value&var2=value2" https://<server>/api/greylisting/whitelist_spf_domains
Optional parameters:
@domains - Reset sender domains
@addDomains - Add new sender domains
@removeDomains - Remove existing sender domains
Note: given sender domain names are not used directly while checking
whitelisting, instead, there's a cron job to query SPF and MX
DNS records of given sender domains, then whitelist the IP
addresses/networks listed in DNS records. Multiple domains must
be separated by comma.
"""
form = web.input(_unicode=False)
qr = _update_whitelist_spf_domains(form)
return api_render(qr)

View File

@@ -0,0 +1,118 @@
import web
from controllers.utils import api_render
from libs import form_utils
from libs.iredapd import throttle as iredapd_throttle
import settings
if settings.backend == 'ldap':
from libs.ldaplib import decorators
else:
from libs.sqllib import decorators
# TODO able to specify quota unit for msg_size and max_quota. e.g. 10MB, 2GB.
# Build form from API POST data and submit the throttle setting
def _add_throttle(form, account, kind):
form['enable_' + kind + '_throttling'] = 'on'
if 'period' in form:
form[kind + '_period'] = form.pop('period')
else:
return False, 'MISS_PERIOD'
_has_rule = False
for i in ['msg_size', 'max_quota', 'max_msgs']:
if i in form:
_has_rule = True
# radio/checkboxes are toggled
form[kind + '_' + i] = 'on'
# value
form['custom_' + kind + '_' + i] = form.pop(i)
if not _has_rule:
return False, 'MISS_THROTTLE_SETTING'
ts = form_utils.get_throttle_setting(form, account=account, inout_type=kind)
qr = iredapd_throttle.add_throttle(account=account, setting=ts, inout_type=kind)
return qr
class APIGlobalThrottle:
@decorators.require_global_admin
def GET(self, kind):
"""Get global inbound and outbound throttle settings.
curl -X GET -i -b cookie.txt https://<server>/api/throttle/global/inbound
curl -X GET -i -b cookie.txt https://<server>/api/throttle/global/outbound
"""
ts = iredapd_throttle.get_throttle_setting(account='@.', inout_type=kind)
return api_render({'_success': True, 'setting': ts})
@decorators.require_global_admin
def POST(self, kind):
"""Set global throttle settings.
curl -X POST -i -b cookie.txt -d "var=value1&var2=value2&..." https://<server>/api/throttle/global/inbound
curl -X POST -i -b cookie.txt -d "var=value1&var2=value2&..." https://<server>/api/throttle/global/outbound
Required POST parameters:
@period - Period of time (in seconds)
@msg_size - Max size of single email
@max_msgs - Number of max inbound emails
@max_quota - Cumulative size of all inbound emails
Note: at least one of msg_size, max_msgs, max_quota is required.
"""
form = web.input(_unicode=False)
qr = _add_throttle(form, account='@.', kind=kind)
return api_render(qr)
class APIDomainThrottle:
@decorators.api_require_domain_access
def GET(self, domain, kind):
"""Set per-domain throttle settings.
curl -X GET -i -b cookie.txt -d "var=value1&var2=value2&..." https://<server>/api/throttle/<domain>/inbound
curl -X GET -i -b cookie.txt -d "var=value1&var2=value2&..." https://<server>/api/throttle/<domain>/outbound
"""
ts = iredapd_throttle.get_throttle_setting(account='@' + domain, inout_type=kind)
return api_render({'_success': True, 'setting': ts})
@decorators.api_require_domain_access
def POST(self, domain, kind):
"""Set per-domain throttle settings.
curl -X POST -i -b cookie.txt -d "var=value1&var2=value2&..." https://<server>/api/throttle/<domain>/inbound
curl -X POST -i -b cookie.txt -d "var=value1&var2=value2&..." https://<server>/api/throttle/<domain>/outbound
"""
form = web.input(_unicode=False)
qr = _add_throttle(form, account='@' + domain, kind=kind)
return api_render(qr)
class APIUserThrottle:
@decorators.api_require_domain_access
def GET(self, mail, kind):
"""Set per-user throttle settings.
curl -X GET -i -b cookie.txt -d "var=value1&var2=value2&..." https://<server>/api/throttle/<mail>/inbound
curl -X GET -i -b cookie.txt -d "var=value1&var2=value2&..." https://<server>/api/throttle/<mail>/outbound
"""
ts = iredapd_throttle.get_throttle_setting(account=mail, inout_type=kind)
return api_render({'_success': True, 'setting': ts})
@decorators.api_require_domain_access
def POST(self, mail, kind):
"""Set per-user throttle settings.
curl -X POST -i -b cookie.txt -d "var=value1&var2=value2&..." https://<server>/api/throttle/<mail>/inbound
curl -X POST -i -b cookie.txt -d "var=value1&var2=value2&..." https://<server>/api/throttle/<mail>/outbound
"""
form = web.input(_unicode=False)
qr = _add_throttle(form, account=mail, kind=kind)
return api_render(qr)

View File

@@ -0,0 +1,55 @@
# Author: Zhang Huangbin <zhb@iredmail.org>
import web
from libs.iredapd import greylist as iredapd_greylist
import settings
if settings.backend == 'ldap':
from libs.ldaplib import decorators
else:
from libs.sqllib import decorators
class DefaultGreylisting:
@decorators.require_global_admin
def GET(self):
gl_setting = iredapd_greylist.get_greylist_setting(account='@.')
gl_whitelists = iredapd_greylist.get_greylist_whitelists(account='@.')
gl_whitelist_domains = iredapd_greylist.get_greylist_whitelist_domains()
# Get greylisting tracking data
(_status, _result) = iredapd_greylist.get_tracking_data(account='@.')
if not _status:
raise web.seeother('/domains?msg=%s' % web.urlquote(_result))
else:
tracking_records = _result
return web.render('iredapd/greylisting_global.html',
gl_setting=gl_setting,
gl_whitelists=gl_whitelists,
gl_whitelist_domains=gl_whitelist_domains,
parent_setting={},
tracking_records=tracking_records,
msg=web.input().get('msg'))
@decorators.require_global_admin
def POST(self):
form = web.input()
qr = iredapd_greylist.update_greylist_settings_from_form(account='@.', form=form)
if qr[0]:
raise web.seeother('/system/greylisting?msg=GL_UPDATED')
else:
raise web.seeother('/system/greylisting?msg=%s' % web.urlquote(qr[1]))
class GreylistingRawTrackingData:
@decorators.require_domain_access
def GET(self, domain):
(_status, _result) = iredapd_greylist.get_domain_tracking_data(domain=domain)
if not _status:
raise web.seeother('/domains?msg=%s' % web.urlquote(_result))
return web.render('iredapd/greylisting_tracking_records.html',
domain=domain,
tracking_records=_result)

217
controllers/iredapd/log.py Normal file
View File

@@ -0,0 +1,217 @@
# Author: Zhang Huangbin <zhb@iredmail.org>
from typing import List
import web
import settings
from libs.iredapd import log as iredapd_log, wblist_senderscore
from libs.iredapd import greylist as lib_greylist
if settings.backend == 'ldap':
from libs.ldaplib import decorators
else:
from libs.sqllib import decorators
session = web.config.get('_session')
def _filter_whitelisted_senderscore_ips(rows=None) -> List:
# Get IP addresses of rejected sessions due to senderscore.
whitelisted_ips = []
try:
_rejected_ips = [
row.client_address
for row in rows
if row.action == 'REJECT'
and row.reason.startswith('Server IP address has bad reputation')
]
if _rejected_ips:
_qr = wblist_senderscore.filter_whitelisted_ips(ips=_rejected_ips)
if _qr[0]:
whitelisted_ips = _qr[1]
except:
pass
return whitelisted_ips
def _filter_whitelisted_greylisting_ips(rows=None):
# Get IP addresses of rejected sessions due to greylisting.
whitelisted_ips = []
if not rows:
return whitelisted_ips
try:
_rejected_ips = [
row.client_address
for row in rows
if row.action == '451'
and row.reason == '4.7.1 Intentional policy rejection, please try again later'
]
if _rejected_ips:
_qr = lib_greylist.filter_whitelisted_ips(ips=_rejected_ips)
if _qr[0]:
whitelisted_ips = _qr[1]
except:
pass
return whitelisted_ips
class SMTPSessions:
@decorators.require_admin_login
def GET(self, page=1, outbound_only=False, rejected_only=False):
"""Display log of SMTP rejections."""
page = int(page)
if page < 1:
page = 1
qr = iredapd_log.get_log_smtp_sessions(
outbound_only=outbound_only,
rejected_only=rejected_only,
offset=settings.PAGE_SIZE_LIMIT * (page - 1),
limit=settings.PAGE_SIZE_LIMIT,
)
total = qr['total']
rows = qr['rows']
if outbound_only:
tmpl = 'smtp_outbound_sessions.html'
else:
tmpl = 'smtp_sessions.html'
num_insecure_outbound = 0
insecure_outbound_usernames = []
query_insecure_outbound_hours = settings.IREDAPD_QUERY_INSECURE_OUTBOUND_IN_HOURS
if outbound_only:
# Count insecure outbound connections.
_qr = iredapd_log.get_smtp_insecure_outbound(hours=query_insecure_outbound_hours)
if _qr[0]:
num_insecure_outbound = _qr[1]['total']
insecure_outbound_usernames = _qr[1]['usernames']
# Get IP addresses of rejected sessions due to senderscore.
whitelisted_senderscore_ips = []
if session.get('is_global_admin') and total > 0:
whitelisted_senderscore_ips = _filter_whitelisted_senderscore_ips(rows=rows)
# Get IP addresses of rejected sessions due to greylisting.
whitelisted_greylisting_ips = []
if session.get('is_global_admin') and total > 0:
whitelisted_greylisting_ips = _filter_whitelisted_greylisting_ips(rows=rows)
return web.render('iredapd/activities/' + tmpl,
total=total,
rows=rows,
current_page=page,
rejected_only=rejected_only,
whitelisted_senderscore_ips=whitelisted_senderscore_ips,
whitelisted_greylisting_ips=whitelisted_greylisting_ips,
query_insecure_outbound_hours=query_insecure_outbound_hours,
num_insecure_outbound=num_insecure_outbound,
insecure_outbound_usernames=insecure_outbound_usernames,
msg=web.input().get('msg'))
class SMTPSessionsPerAccount:
@decorators.require_admin_login
def GET(self, account_type, account, page=1, outbound_only=False):
"""Display log of SMTP authentications."""
account_type = account_type.lower()
account = account.lower()
page = int(page)
if page < 1:
page = 1
domains = []
sasl_usernames = []
senders = []
recipients = []
client_addresses = []
encryption_protocols = []
# Make sure admin has privilege to manage this domain.
if account_type == 'sasl_username':
sasl_usernames = [account]
elif account_type == 'sender':
senders = [account]
elif account_type == 'recipient':
recipients = [account]
elif account_type == 'domain':
domains = [account]
elif account_type == 'client_address':
client_addresses = [account]
elif account_type == 'encryption_protocol':
encryption_protocols = [account]
qr = iredapd_log.get_log_smtp_sessions(
domains=domains,
sasl_usernames=sasl_usernames,
senders=senders,
recipients=recipients,
encryption_protocols=encryption_protocols,
client_addresses=client_addresses,
outbound_only=outbound_only,
offset=settings.PAGE_SIZE_LIMIT * (page - 1),
limit=settings.PAGE_SIZE_LIMIT,
)
total = qr['total'] or 0
rows = qr['rows']
if outbound_only:
tmpl = 'smtp_outbound_sessions.html'
else:
tmpl = 'smtp_sessions.html'
# Get IP addresses of rejected sessions due to senderscore.
whitelisted_senderscore_ips = []
if session.get('is_global_admin') and total > 0:
whitelisted_senderscore_ips = _filter_whitelisted_senderscore_ips(rows=rows)
# Get IP addresses of rejected sessions due to greylisting.
whitelisted_greylisting_ips = []
if session.get('is_global_admin') and total > 0:
whitelisted_greylisting_ips = _filter_whitelisted_greylisting_ips(rows=rows)
return web.render(
'iredapd/activities/' + tmpl,
account_type=account_type,
account=account,
total=total,
rows=rows,
whitelisted_senderscore_ips=whitelisted_senderscore_ips,
whitelisted_greylisting_ips=whitelisted_greylisting_ips,
current_page=page,
msg=web.input().get('msg'),
)
class SMTPSessionsRejected:
@decorators.require_admin_login
def GET(self, page=1):
c = SMTPSessions()
return c.GET(page=page, rejected_only=True)
class SMTPSessionsOutbound:
@decorators.require_admin_login
def GET(self, page=1):
c = SMTPSessions()
return c.GET(page=page, outbound_only=True)
class SMTPSessionsOutboundPerAccount:
@decorators.require_admin_login
def GET(self, account_type, account, page=1):
c = SMTPSessionsPerAccount()
return c.GET(account_type=account_type,
account=account,
page=page,
outbound_only=True)

View File

@@ -0,0 +1,14 @@
from controllers import decorators
from controllers.utils import api_render
from libs.iredapd import wblist_senderscore
class WhitelistIPForSenderScore:
@decorators.require_global_admin
def PUT(self, ip):
"""Whitelist given IP address for senderscore.
curl -X PUT -i -b cookie.txt -d "ip=x.x.x.x" https://<server>/api/wblist/senderscore/whitelist/<ip>
"""
qr = wblist_senderscore.whitelist_ips(ips=[ip])
return api_render(qr)

View File

@@ -0,0 +1,45 @@
# Author: Zhang Huangbin <zhb@iredmail.org>
import web
import settings
from libs import form_utils
from libs.iredapd import throttle as iredapd_throttle
if settings.backend == 'ldap':
from libs.ldaplib import decorators
else:
from libs.sqllib import decorators
# server-wide throttle setting.
class GlobalThrottle:
@decorators.require_global_admin
def GET(self):
inbound_setting = iredapd_throttle.get_throttle_setting(account='@.', inout_type='inbound')
outbound_setting = iredapd_throttle.get_throttle_setting(account='@.', inout_type='outbound')
return web.render('iredapd/throttle_global.html',
inbound_setting=inbound_setting,
outbound_setting=outbound_setting,
msg=web.input().get('msg'))
@decorators.require_global_admin
def POST(self):
form = web.input(_unicode=False)
t_account = '@.'
inbound_setting = form_utils.get_throttle_setting(form, account=t_account, inout_type='inbound')
outbound_setting = form_utils.get_throttle_setting(form, account=t_account, inout_type='outbound')
iredapd_throttle.add_throttle(account=t_account,
setting=inbound_setting,
inout_type='inbound')
iredapd_throttle.add_throttle(account=t_account,
setting=outbound_setting,
inout_type='outbound')
raise web.seeother('/system/throttle?msg=UPDATED')

View File

@@ -0,0 +1,69 @@
# Author: Zhang Huangbin <zhb@iredmail.org>
import settings
from libs.regxes import email as e, domain as d, ip
# fmt: off
urls = [
# Throttling
'/system/throttle', 'controllers.iredapd.throttle.GlobalThrottle',
# Greylisting
'/system/greylisting', 'controllers.iredapd.greylist.DefaultGreylisting',
# Greylisting tracking data
'/system/greylisting/tracking/domain/(%s)' % d, 'controllers.iredapd.greylist.GreylistingRawTrackingData',
# White/blacklist based on rDNS
'/system/wblist/rdns', 'controllers.iredapd.wblist_rdns.WBListRDNS',
#
# Activities
#
'/activities/smtp/sessions', 'controllers.iredapd.log.SMTPSessions',
r'/activities/smtp/sessions/page/(\d+)', 'controllers.iredapd.log.SMTPSessions',
'/activities/smtp/sessions/(sasl_username|sender|recipient)/(%s)' % e, 'controllers.iredapd.log.SMTPSessionsPerAccount',
r'/activities/smtp/sessions/(sasl_username|sender|recipient)/(%s)/page/(\d+)' % e, 'controllers.iredapd.log.SMTPSessionsPerAccount',
'/activities/smtp/sessions/(domain)/(%s)' % d, 'controllers.iredapd.log.SMTPSessionsPerAccount',
r'/activities/smtp/sessions/(domain)/(%s)/page/(\d+)' % d, 'controllers.iredapd.log.SMTPSessionsPerAccount',
'/activities/smtp/sessions/(client_address)/(%s)' % ip, 'controllers.iredapd.log.SMTPSessionsPerAccount',
r'/activities/smtp/sessions/(client_address)/(%s)/page/(\d+)' % ip, 'controllers.iredapd.log.SMTPSessionsPerAccount',
r'/activities/smtp/sessions/(encryption_protocol)/([0-9a-zA-Z\.]+)', 'controllers.iredapd.log.SMTPSessionsPerAccount',
r'/activities/smtp/sessions/(encryption_protocol)/([0-9a-zA-Z\.]+)/page/(\d+)', 'controllers.iredapd.log.SMTPSessionsPerAccount',
'/activities/smtp/sessions/rejected', 'controllers.iredapd.log.SMTPSessionsRejected',
r'/activities/smtp/sessions/rejected/page/(\d+)', 'controllers.iredapd.log.SMTPSessionsRejected',
# SMTP Authentications
'/activities/smtp/sessions/outbound', 'controllers.iredapd.log.SMTPSessionsOutbound',
r'/activities/smtp/sessions/outbound/page/(\d+)', 'controllers.iredapd.log.SMTPSessionsOutbound',
'/activities/smtp/sessions/outbound/(sasl_username|sender|recipient)/(%s)' % e, 'controllers.iredapd.log.SMTPSessionsOutboundPerAccount',
r'/activities/smtp/sessions/outbound/(sasl_username|sender|recipient)/(%s)/page/(\d+)' % e, 'controllers.iredapd.log.SMTPSessionsOutboundPerAccount',
'/activities/smtp/sessions/outbound/(domain)/(%s)' % d, 'controllers.iredapd.log.SMTPSessionsOutboundPerAccount',
r'/activities/smtp/sessions/outbound/(domain)/(%s)/page/(\d+)' % d, 'controllers.iredapd.log.SMTPSessionsOutboundPerAccount',
'/activities/smtp/sessions/outbound/(client_address)/(%s)' % ip, 'controllers.iredapd.log.SMTPSessionsOutboundPerAccount',
r'/activities/smtp/sessions/outbound/(client_address)/(%s)/page/(\d+)' % ip, 'controllers.iredapd.log.SMTPSessionsOutboundPerAccount',
r'/activities/smtp/sessions/outbound/(encryption_protocol)/([0-9a-zA-Z\.]+)', 'controllers.iredapd.log.SMTPSessionsOutboundPerAccount',
r'/activities/smtp/sessions/outbound/(encryption_protocol)/([0-9a-zA-Z\.]+)/page/(\d+)', 'controllers.iredapd.log.SMTPSessionsOutboundPerAccount',
# API interfaces used by web ui.
'/api/wblist/senderscore/whitelist/(%s)$' % ip, 'controllers.iredapd.senderscore.WhitelistIPForSenderScore',
'/api/greylisting/global/whitelist/(%s)$' % ip, 'controllers.iredapd.api_greylist.APIGlobalWhitelist',
]
# API Interfaces
if settings.ENABLE_RESTFUL_API:
urls += [
# Throttling
'/api/throttle/global/(inbound|outbound)', 'controllers.iredapd.api_throttle.APIGlobalThrottle',
'/api/throttle/(%s)/(inbound|outbound)' % d, 'controllers.iredapd.api_throttle.APIDomainThrottle',
'/api/throttle/(%s)/(inbound|outbound)' % e, 'controllers.iredapd.api_throttle.APIUserThrottle',
# Greylisting
'/api/greylisting/all', 'controllers.iredapd.api_greylist.APIAllSettings',
'/api/greylisting/global', 'controllers.iredapd.api_greylist.APIGlobalSetting',
'/api/greylisting/(%s)' % d, 'controllers.iredapd.api_greylist.APIDomainSetting',
'/api/greylisting/(%s)' % e, 'controllers.iredapd.api_greylist.APIUserSetting',
'/api/greylisting/global/whitelists', 'controllers.iredapd.api_greylist.APIGlobalWhitelists',
'/api/greylisting/(%s)/whitelists' % d, 'controllers.iredapd.api_greylist.APIDomainWhitelists',
'/api/greylisting/(%s)/whitelists' % e, 'controllers.iredapd.api_greylist.APIUserWhitelists',
'/api/greylisting/whitelist_spf_domains', 'controllers.iredapd.api_greylist.APIWhitelistSPFDomain',
]
# fmt: on

View File

@@ -0,0 +1,79 @@
import web
from controllers import decorators
from libs.iredutils import is_valid_wblist_rdns_domain
from libs.iredapd import wblist_rdns, wblist_senderscore
class WBListRDNS:
@decorators.require_global_admin
def GET(self):
# Get wblist records
(_status, _result) = wblist_rdns.get_wblist_rdns()
if not _status:
raise web.seeother('/domains?msg=%s' % web.urlquote(_result))
whitelists = _result['whitelists']
blacklists = _result['blacklists']
return web.render('iredapd/wblist/rdns.html',
whitelists=whitelists,
blacklists=blacklists,
msg=web.input().get('msg'))
@decorators.require_global_admin
def POST(self):
form = web.input()
whitelists = [str(i).lower()
for i in form.get('whitelists', '').splitlines()
if is_valid_wblist_rdns_domain(i)]
whitelists = list(set(whitelists))
blacklists = [str(i).lower()
for i in form.get('blacklists', '').splitlines()
if is_valid_wblist_rdns_domain(i)]
blacklists = list(set(blacklists))
(_status, _result) = wblist_rdns.reset_wblist_rdns(whitelists=whitelists, blacklists=blacklists)
if _status:
raise web.seeother('/system/wblist/rdns?msg=UPDATED')
else:
raise web.seeother('/system/wblist/rdns?msg=%s' % web.urlquote(_result))
class WBListSenderScore:
@decorators.require_global_admin
def GET(self):
# Get wblist records
(_status, _result) = wblist_senderscore.get_whitelists()
if not _status:
raise web.seeother('/domains?msg=%s' % web.urlquote(_result))
total = _result['total']
ips = _result['ips']
return web.render('iredapd/wblist/senderscore.html',
total=total,
ips=ips,
msg=web.input().get('msg'))
@decorators.require_global_admin
def POST(self):
form = web.input()
whitelists = [str(i).lower()
for i in form.get('whitelists', '').splitlines()
if is_valid_wblist_rdns_domain(i)]
whitelists = list(set(whitelists))
blacklists = [str(i).lower()
for i in form.get('blacklists', '').splitlines()
if is_valid_wblist_rdns_domain(i)]
blacklists = list(set(blacklists))
(_status, _result) = wblist_rdns.reset_wblist_rdns(whitelists=whitelists, blacklists=blacklists)
if _status:
raise web.seeother('/system/wblist/senderscore?msg=UPDATED')
else:
raise web.seeother('/system/wblist/senderscore?msg=%s' % web.urlquote(_result))