Subversion Repositories configs

Rev

Rev 34 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
34 - 1
# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: t -*-
2
# vi: set ft=python sts=4 ts=4 sw=4 noet :
3
 
4
# This file is part of Fail2Ban.
5
#
6
# Fail2Ban is free software; you can redistribute it and/or modify
7
# it under the terms of the GNU General Public License as published by
8
# the Free Software Foundation; either version 2 of the License, or
9
# (at your option) any later version.
10
#
11
# Fail2Ban is distributed in the hope that it will be useful,
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
# GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License
17
# along with Fail2Ban; if not, write to the Free Software
18
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19
 
20
import socket
21
import smtplib
22
from email.mime.text import MIMEText
23
from email.utils import formatdate, formataddr
24
 
25
from fail2ban.server.actions import ActionBase, CallingMap
26
 
27
messages = {}
28
messages['start'] = \
29
"""Hi,
30
 
31
The jail %(jailname)s has been started successfully.
32
 
33
Regards,
34
Fail2Ban"""
35
 
36
messages['stop'] = \
37
"""Hi,
38
 
39
The jail %(jailname)s has been stopped.
40
 
41
Regards,
42
Fail2Ban"""
43
 
44
messages['ban'] = {}
45
messages['ban']['head'] = \
46
"""Hi,
47
 
48
The IP %(ip)s has just been banned for %(bantime)i seconds
49
by Fail2Ban after %(failures)i attempts against %(jailname)s.
50
"""
51
messages['ban']['tail'] = \
52
"""
53
Regards,
54
Fail2Ban"""
55
messages['ban']['matches'] = \
56
"""
57
Matches for this ban:
58
%(matches)s
59
"""
60
messages['ban']['ipmatches'] = \
61
"""
62
Matches for %(ip)s:
63
%(ipmatches)s
64
"""
65
messages['ban']['ipjailmatches'] = \
66
"""
67
Matches for %(ip)s for jail %(jailname)s:
68
%(ipjailmatches)s
69
"""
70
 
39 - 71
 
34 - 72
class SMTPAction(ActionBase):
73
	"""Fail2Ban action which sends emails to inform on jail starting,
74
	stopping and bans.
75
	"""
76
 
77
	def __init__(
78
		self, jail, name, host="localhost", user=None, password=None,
79
		sendername="Fail2Ban", sender="fail2ban", dest="root", matches=None):
80
		"""Initialise action.
81
 
82
		Parameters
83
		----------
84
		jail : Jail
85
			The jail which the action belongs to.
86
		name : str
87
			Named assigned to the action.
88
		host : str, optional
89
			SMTP host, of host:port format. Default host "localhost" and
90
			port "25"
91
		user : str, optional
92
			Username used for authentication with SMTP server.
93
		password : str, optional
94
			Password used for authentication with SMTP server.
95
		sendername : str, optional
96
			Name to use for from address in email. Default "Fail2Ban".
97
		sender : str, optional
98
			Email address to use for from address in email.
99
			Default "fail2ban".
100
		dest : str, optional
101
			Email addresses of intended recipient(s) in comma space ", "
102
			delimited format. Default "root".
103
		matches : str, optional
104
			Type of matches to be included from ban in email. Can be one
105
			of "matches", "ipmatches" or "ipjailmatches". Default None
106
			(see man jail.conf.5).
107
		"""
108
 
109
		super(SMTPAction, self).__init__(jail, name)
110
 
111
		self.host = host
112
		#TODO: self.ssl = ssl
113
 
114
		self.user = user
115
		self.password =password
116
 
117
		self.fromname = sendername
118
		self.fromaddr = sender
119
		self.toaddr = dest
120
 
121
		self.matches = matches
122
 
123
		self.message_values = CallingMap(
124
			jailname = self._jail.name,
125
			hostname = socket.gethostname,
126
			bantime = self._jail.actions.getBanTime,
127
			)
128
 
129
	def _sendMessage(self, subject, text):
130
		"""Sends message based on arguments and instance's properties.
131
 
132
		Parameters
133
		----------
134
		subject : str
135
			Subject of the email.
136
		text : str
137
			Body of the email.
138
 
139
		Raises
140
		------
141
		SMTPConnectionError
142
			Error on connecting to host.
143
		SMTPAuthenticationError
144
			Error authenticating with SMTP server.
145
		SMTPException
146
			See Python `smtplib` for full list of other possible
147
			exceptions.
148
		"""
149
		msg = MIMEText(text)
150
		msg['Subject'] = subject
151
		msg['From'] = formataddr((self.fromname, self.fromaddr))
152
		msg['To'] = self.toaddr
153
		msg['Date'] = formatdate()
154
 
155
		smtp = smtplib.SMTP()
156
		try:
157
			self._logSys.debug("Connected to SMTP '%s', response: %i: %s",
158
				self.host, *smtp.connect(self.host))
159
			if self.user and self.password:
160
				smtp.login(self.user, self.password)
161
			failed_recipients = smtp.sendmail(
162
				self.fromaddr, self.toaddr.split(", "), msg.as_string())
163
		except smtplib.SMTPConnectError:
164
			self._logSys.error("Error connecting to host '%s'", self.host)
165
			raise
166
		except smtplib.SMTPAuthenticationError:
167
			self._logSys.error(
168
				"Failed to authenticate with host '%s' user '%s'",
169
				self.host, self.user)
170
			raise
171
		except smtplib.SMTPException:
172
			self._logSys.error(
173
				"Error sending mail to host '%s' from '%s' to '%s'",
174
				self.host, self.fromaddr, self.toaddr)
175
			raise
176
		else:
177
			if failed_recipients:
178
				self._logSys.warning(
179
					"Email to '%s' failed to following recipients: %r",
180
					self.toaddr, failed_recipients)
181
			self._logSys.debug("Email '%s' successfully sent", subject)
182
		finally:
183
			try:
184
				self._logSys.debug("Disconnected from '%s', response %i: %s",
185
					self.host, *smtp.quit())
186
			except smtplib.SMTPServerDisconnected:
187
				pass # Not connected
188
 
189
	def start(self):
190
		"""Sends email to recipients informing that the jail has started.
191
		"""
192
		self._sendMessage(
193
			"[Fail2Ban] %(jailname)s: started on %(hostname)s" %
194
				self.message_values,
195
			messages['start'] % self.message_values)
196
 
197
	def stop(self):
198
		"""Sends email to recipients informing that the jail has stopped.
199
		"""
200
		self._sendMessage(
201
			"[Fail2Ban] %(jailname)s: stopped on %(hostname)s" %
202
				self.message_values,
203
			messages['stop'] % self.message_values)
204
 
205
	def ban(self, aInfo):
206
		"""Sends email to recipients informing that ban has occurred.
207
 
208
		Parameters
209
		----------
210
		aInfo : dict
211
			Dictionary which includes information in relation to
212
			the ban.
213
		"""
214
		aInfo.update(self.message_values)
215
		message = "".join([
216
			messages['ban']['head'],
217
			messages['ban'].get(self.matches, ""),
218
			messages['ban']['tail']
219
			])
220
		self._sendMessage(
221
			"[Fail2Ban] %(jailname)s: banned %(ip)s from %(hostname)s" %
222
				aInfo,
223
			message % aInfo)
224
 
225
Action = SMTPAction