2
# Copyright 2012-2013 Canonical Ltd.
4
# This program is free software: you can redistribute it and/or modify
5
# it under the terms of the GNU General Public License version 3,
6
# as published by the Free Software Foundation.
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
# GNU General Public License for more details.
13
# You should have received a copy of the GNU General Public License
14
# along with this program. If not, see <http://www.gnu.org/licenses/>.
21
from StringIO import StringIO
23
from io import StringIO
25
import tests.unit.support
30
class FrontendTestCase(unittest.TestCase):
32
ufw.common.do_checks = False
34
for d in ["/sbin", "/bin",
35
"/usr/sbin", "/usr/bin",
36
"/usr/local/sbin", "/usr/local/bin"]:
37
if os.path.exists(os.path.join(d, "iptables")):
40
self.assertTrue(iptables_dir != "")
41
ufw.common.iptables_dir = iptables_dir
43
# This needs to be before we set ufw.util.msg_output since
44
# ufw.util.warn() is called in backend.py:init()
45
self.ui = ufw.frontend.UFWFrontend(dryrun=True)
47
# Capture stdout from msg() and write_to_file() so we can examine it
48
self.saved_msg_output = ufw.util.msg_output
49
self.msg_output = StringIO()
50
ufw.util.msg_output = self.msg_output
55
ufw.util.msg_output = self.saved_msg_output
56
self.msg_output.close()
57
self.msg_output = None
61
def test_parse_command(self):
62
'''Test parse_command()'''
63
# test_parser.py will handle command combinations exhaustively, let's
64
# just use a representative set here
72
'default allow incoming',
73
'default deny outgoing',
91
'insert 1 limit 22/tcp',
94
'allow to any port 23 proto tcp',
95
'deny from 192.168.0.1 to 192.168.0.2',
98
'deny from any port 53 proto udp',
99
'limit in on eth0 to 192.168.0.1 port 22 from 10.0.0.0/24 port 1024:65535 proto tcp',
101
'--dry-run allow 22/tcp',
102
'--dry-run app list',
110
ufw.frontend.parse_command(['ufw'] + c.split())
112
def test_parse_command_bad(self):
113
'''Test parse_command_bad'''
115
('llow 12345', ValueError),
116
('allo 12345', ValueError),
117
('allow', ValueError),
119
# for ufw.util.error() on python3
120
ufw.util.msg_output = self.saved_msg_output
121
for (c, expected) in data:
122
tests.unit.support.check_for_exception(self, expected,
123
ufw.frontend.parse_command, ['ufw'] + c.split())
125
def test___init__(self):
126
'''Test __init__()'''
127
tests.unit.support.check_for_exception(self, ufw.common.UFWError,
128
ufw.frontend.UFWFrontend, True, 'nonexistent')
130
def test_get_command_help(self):
131
'''Test get_command_help()'''
132
s = ufw.frontend.get_command_help()
152
'app update PROFILE',
156
self.assertTrue(search in s, "Could not find '%s' in:\n%s" % \
159
def test_continue_under_ssh(self):
160
'''Test continue_under_ssh()'''
161
self.ui.continue_under_ssh()
163
def test_do_action(self):
164
'''Test do_action()'''
173
'default allow incoming',
174
'default deny outgoing',
186
'insert 1 limit 22/tcp',
189
'allow to any port 23 proto tcp',
190
'deny from 192.168.0.1 to 192.168.0.2',
192
'allow to fe80::/16',
193
'deny from any port 53 proto udp',
194
'limit in on eth0 to 192.168.0.1 port 22 from 10.0.0.0/24 port 1024:65535 proto tcp',
199
'allow to 192.168.0.1 app WWW',
200
'delete allow to 192.168.0.1 app WWW',
201
'allow to fe80::/16 app WWW',
202
'delete allow to fe80::/16 app WWW',
203
'allow from fe80::/16 app WWW',
204
'delete allow from fe80::/16 app WWW',
205
'allow from fe80::/16 app CIFS',
206
'delete allow from fe80::/16 app CifS',
211
for dryrun in [True, False]:
212
ufw.util.msg_output = self.saved_msg_output
213
ui = ufw.frontend.UFWFrontend(dryrun=dryrun)
214
ufw.util.msg_output = self.msg_output
216
if not dryrun and c not in ['allow', 'deny', 'limit',
217
'reject', 'delete', 'insert']:
220
pr = ufw.frontend.parse_command(['ufw'] + c.split())
221
if 'rule' in pr.data:
222
res = ui.do_action(pr.action,
227
res = ui.do_action(pr.action, "", "", force=True)
229
print("%s failed:" % c)
231
self.assertTrue(res != "", "Output is empty for '%s'" % c)
233
out = self.msg_output.getvalue()
234
if cmd in ['allow', 'deny', 'limit', 'reject', 'delete',
236
for search in ['*filter', 'COMMIT']:
237
self.assertTrue(search in out, \
238
"Could not find '%s' in:\n%s" % \
241
search = "running ufw-init"
242
self.assertTrue(search in out, \
243
"Could not find '%s' in:\n%s" % \
246
print ("TODO: verify output of rules in do_action()")
248
def test_do_action_remove_bad_appname(self):
249
'''Test do_action() remove bad appname'''
250
c = 'delete allow to any app &^%$'
251
pr = ufw.frontend.parse_command(['ufw'] + c.split())
252
tests.unit.support.check_for_exception(self, ufw.common.UFWError,
253
self.ui.do_action, pr.action, pr.data['rule'],
254
pr.data['iptype'], True)
256
def test_do_application_action(self):
257
'''Test do_application_action()'''
265
'app update --add-new CIFS',
269
pr = ufw.frontend.parse_command(['ufw'] + c.split())
270
if 'type' in pr.data and pr.data['type'] == 'app':
271
res = self.ui.do_application_action(pr.action,
274
res = self.ui.do_action(pr.action, "", "", force=True)
276
print("%s failed:" % c)
279
if c.startswith("app update"):
280
self.assertTrue(res == "", "Output is not empty for '%s'" % c)
281
elif c.startswith('app list'):
282
for search in ['Available applications', 'AIM', 'WWW']:
283
self.assertTrue(search in res, \
284
"Could not find '%s' in:\n%s" % \
286
elif c.startswith('app info'):
287
for search in ['Title: Web Server', '80/tcp']:
288
self.assertTrue(search in res, \
289
"Could not find '%s' in:\n%s" % \
291
elif c.startswith('app default'):
293
search = "Default application policy changed to '%s'" % p
294
self.assertTrue(search in res, \
295
"Could not find '%s' in:\n%s" % (search, res))
297
self.assertTrue(res != "", "Output is empty for '%s'" % c)
299
pr = ufw.frontend.parse_command(['ufw', 'app', 'update', '--add-new', 'all'])
300
tests.unit.support.check_for_exception(self, ufw.common.UFWError,
301
self.ui.do_application_action, pr.action, pr.data['name'])
303
def test_get_show_raw(self):
304
'''Test get_show_raw()'''
305
res = self.ui.get_show_raw()
306
search = "> Checking"
307
self.assertTrue(search in res, \
308
"Could not find '%s' in:\n%s" % (search, res))
310
def test_get_show_listening(self):
311
'''Test get_show_listening()'''
312
res = self.ui.get_show_listening()
313
for search in ['tcp', 'udp']:
314
# self.assertTrue(search in res, \
315
# "Could not find '%s' in:\n%s" % (search, res))
316
if search not in res:
317
print("(TODO: fake-netstat) Could not find '%s' in:\n%s" % (search, res))
319
def test_get_show_added(self):
320
'''Test get_show_added()'''
321
res = self.ui.get_show_added()
323
self.assertTrue(search in res, \
324
"Could not find '%s' in:\n%s" % (search, res))
327
pr = ufw.frontend.parse_command(['ufw'] + c.split())
328
self.ui.do_action(pr.action, pr.data['rule'], pr.data['iptype'],
330
res = self.ui.get_show_added()
332
self.assertTrue(search in res, \
333
"Could not find '%s' in:\n%s" % (search, res))
335
def test_application_add(self):
336
'''Test application_add()'''
337
for i in ['accept', 'drop', 'reject']:
338
self.ui.backend.defaults['default_application_policy'] = i
339
res = self.ui.application_add('WWW')
340
for search in ['Rules updated', 'Rules updated (v6)']:
341
self.assertTrue(search in res, \
342
"Could not find '%s' in:\n%s" % (search, res))
343
self.ui.backend.defaults['default_application_policy'] = 'bad'
344
tests.unit.support.check_for_exception(self, ufw.common.UFWError,
345
self.ui.application_add, 'WWW')
346
self.ui.backend.defaults['default_application_policy'] = 'skip'
349
def test_main(): # used by runner.py
350
tests.unit.support.run_unittest(
354
if __name__ == "__main__": # used when standalone