mirror of
https://github.com/mail-in-a-box/mailinabox.git
synced 2025-04-03 00:07:05 +00:00
163 lines
4.7 KiB
Python
163 lines
4.7 KiB
Python
#####
|
|
##### This file is part of Mail-in-a-Box-LDAP which is released under the
|
|
##### terms of the GNU Affero General Public License as published by the
|
|
##### Free Software Foundation, either version 3 of the License, or (at
|
|
##### your option) any later version. See file LICENSE or go to
|
|
##### https://github.com/downtownallday/mailinabox-ldap for full license
|
|
##### details.
|
|
#####
|
|
|
|
import logging
|
|
from .Timeseries import Timeseries
|
|
from .exceptions import InvalidArgsError
|
|
from .top import select_top
|
|
|
|
log = logging.getLogger(__name__)
|
|
|
|
with open(__file__.replace('.py','.1.sql')) as fp:
|
|
select_1 = fp.read()
|
|
|
|
with open(__file__.replace('.py','.2.sql')) as fp:
|
|
select_2 = fp.read()
|
|
|
|
with open(__file__.replace('.py','.3.sql')) as fp:
|
|
select_3 = fp.read()
|
|
|
|
with open(__file__.replace('.py','.4.sql')) as fp:
|
|
select_4 = fp.read()
|
|
|
|
with open(__file__.replace('.py','.5.sql')) as fp:
|
|
select_5 = fp.read()
|
|
|
|
with open(__file__.replace('.py','.6.sql')) as fp:
|
|
select_6 = fp.read()
|
|
|
|
with open(__file__.replace('.py','.7.sql')) as fp:
|
|
select_7 = fp.read()
|
|
|
|
|
|
def flagged_connections(conn, args):
|
|
try:
|
|
ts = Timeseries(
|
|
"Failed login attempts and suspected scanners over time",
|
|
args['start'],
|
|
args['end'],
|
|
args['binsize']
|
|
)
|
|
except KeyError:
|
|
raise InvalidArgsError()
|
|
|
|
c = conn.cursor()
|
|
|
|
# pie chart for "connections by disposition"
|
|
connections_by_disposition = []
|
|
for row in c.execute(select_7, {'start_date':ts.start, 'end_date':ts.end}):
|
|
connections_by_disposition.append({
|
|
'name': row[0],
|
|
'value': row[1]
|
|
})
|
|
|
|
# timeseries = failed logins count
|
|
s_failed_login = ts.add_series('failed_login_attempt', 'failed login attempts')
|
|
sql = select_1.format(timefmt=ts.timefmt)
|
|
for row in c.execute(sql, {
|
|
'start_date': ts.start,
|
|
'end_date': ts.end,
|
|
'start_unixepoch': ts.start_unixepoch,
|
|
'binsize': ts.binsize
|
|
}):
|
|
idx = ts.insert_date(row['bin'])
|
|
s_failed_login['values'][idx] = row['count']
|
|
|
|
# timeseries = suspected scanners count
|
|
s_scanner = ts.add_series('suspected_scanner', 'connections by suspected scanners')
|
|
sql = select_2.format(timefmt=ts.timefmt)
|
|
for row in c.execute(sql, {
|
|
'start_date': ts.start,
|
|
'end_date': ts.end,
|
|
'start_unixepoch': ts.start_unixepoch,
|
|
'binsize': ts.binsize
|
|
}):
|
|
idx = ts.insert_date(row['bin'])
|
|
s_scanner['values'][idx] = row['count']
|
|
|
|
|
|
# pie chart for "disposition=='reject' grouped by failure_category"
|
|
reject_by_failure_category = []
|
|
for row in c.execute(select_3, {
|
|
'start_date': ts.start,
|
|
'end_date': ts.end
|
|
}):
|
|
reject_by_failure_category.append({
|
|
'name': row[0],
|
|
'value': row[1]
|
|
})
|
|
|
|
# top 10 servers rejected by category
|
|
top_hosts_rejected = select_top(
|
|
c,
|
|
select_4,
|
|
ts.start,
|
|
ts.end,
|
|
"Top servers rejected by category",
|
|
[ 'remote_host', 'category', 'count' ],
|
|
[ 'text/hostname', 'text/plain', 'number/plain' ]
|
|
)
|
|
|
|
# insecure inbound connections - no limit
|
|
insecure_inbound = select_top(
|
|
c,
|
|
select_5,
|
|
ts.start,
|
|
ts.end,
|
|
"Insecure inbound connections (no use of STARTTLS)",
|
|
[
|
|
'service',
|
|
'sasl_username',
|
|
'envelope_from',
|
|
'rcpt_to',
|
|
'count'
|
|
],
|
|
[
|
|
'text/plain', # service
|
|
'text/plain', # sasl_username
|
|
'text/email', # envelope_from
|
|
{ 'type':'text/email', 'label':'Recipient' }, # rcpt_to
|
|
'number/plain', # count
|
|
]
|
|
)
|
|
|
|
# insecure outbound connections - no limit
|
|
insecure_outbound = select_top(
|
|
c,
|
|
select_6,
|
|
ts.start,
|
|
ts.end,
|
|
"Insecure outbound connections (low grade encryption)",
|
|
[
|
|
'service',
|
|
'sasl_username',
|
|
'envelope_from',
|
|
'rcpt_to',
|
|
'count'
|
|
],
|
|
[
|
|
'text/plain', # service
|
|
'text/plain', # sasl_username
|
|
'text/email', # envelope_from
|
|
{ 'type':'text/email', 'label':'Recipient' }, # rcpt_to
|
|
'number/plain', # count
|
|
]
|
|
)
|
|
|
|
|
|
|
|
return {
|
|
'connections_by_disposition': connections_by_disposition,
|
|
'flagged': ts.asDict(),
|
|
'reject_by_failure_category': reject_by_failure_category,
|
|
'top_hosts_rejected': top_hosts_rejected,
|
|
'insecure_inbound': insecure_inbound,
|
|
'insecure_outbound': insecure_outbound,
|
|
}
|