summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDirk Mueller <dirk@dmllr.de>2013-06-11 18:25:20 +0200
committerDirk Mueller <dirk@dmllr.de>2013-07-03 11:26:03 +0200
commitf9d1a59bb826e1d5b928bc5301dc5fa40f6adc63 (patch)
treee4a8d72035d2a5a73ca46bb6ab98ae6cfe3d4558
parent085dd69acdd5c8c216271dc8890c4107363190fb (diff)
downloadoslo-f9d1a59bb826e1d5b928bc5301dc5fa40f6adc63.zip
oslo-f9d1a59bb826e1d5b928bc5301dc5fa40f6adc63.tar.gz
oslo-f9d1a59bb826e1d5b928bc5301dc5fa40f6adc63.tar.xz
Handle empty arglists in Filters
The various filters either asserted or incorrectly assumed that an empty arglist matched the filter. Add testcases to avoid regressions. Change-Id: If90fbad3d54749ecc645071675402ea2613870a2
-rw-r--r--openstack/common/rootwrap/filters.py17
-rw-r--r--tests/unit/test_rootwrap.py39
2 files changed, 46 insertions, 10 deletions
diff --git a/openstack/common/rootwrap/filters.py b/openstack/common/rootwrap/filters.py
index b40fdfd..660434a 100644
--- a/openstack/common/rootwrap/filters.py
+++ b/openstack/common/rootwrap/filters.py
@@ -47,7 +47,7 @@ class CommandFilter(object):
def match(self, userargs):
"""Only check that the first argument (command) matches exec_path."""
- return os.path.basename(self.exec_path) == userargs[0]
+ return userargs and os.path.basename(self.exec_path) == userargs[0]
def get_command(self, userargs, exec_dirs=[]):
"""Returns command to execute (with sudo -u if run_as != root)."""
@@ -67,7 +67,7 @@ class RegExpFilter(CommandFilter):
def match(self, userargs):
# Early skip if command or number of args don't match
- if (len(self.args) != len(userargs)):
+ if (not userargs or len(self.args) != len(userargs)):
# DENY: argument numbers don't match
return False
# Compare each arg (anchoring pattern explicitly at end of string)
@@ -101,6 +101,9 @@ class PathFilter(CommandFilter):
"""
def match(self, userargs):
+ if not userargs or len(userargs) < 2:
+ return False
+
command, arguments = userargs[0], userargs[1:]
equal_args_num = len(self.args) == len(arguments)
@@ -178,7 +181,7 @@ class KillFilter(CommandFilter):
super(KillFilter, self).__init__("/bin/kill", *args)
def match(self, userargs):
- if userargs[0] != "kill":
+ if not userargs or userargs[0] != "kill":
return False
args = list(userargs)
if len(args) == 3:
@@ -229,13 +232,7 @@ class ReadFileFilter(CommandFilter):
super(ReadFileFilter, self).__init__("/bin/cat", "root", *args)
def match(self, userargs):
- if userargs[0] != 'cat':
- return False
- if userargs[1] != self.file_path:
- return False
- if len(userargs) != 2:
- return False
- return True
+ return (userargs == ['cat', self.file_path])
class IpFilter(CommandFilter):
diff --git a/tests/unit/test_rootwrap.py b/tests/unit/test_rootwrap.py
index 6e1e6e6..a649660 100644
--- a/tests/unit/test_rootwrap.py
+++ b/tests/unit/test_rootwrap.py
@@ -40,6 +40,32 @@ class RootwrapTestCase(utils.BaseTestCase):
filters.CommandFilter("/bin/cat", "root") # Keep this one last
]
+ def test_CommandFilter(self):
+ f = filters.CommandFilter("sleep", 'root', '10')
+ self.assertFalse(f.match(["sleep2"]))
+
+ # verify that any arguments are accepted
+ self.assertTrue(f.match(["sleep"]))
+ self.assertTrue(f.match(["sleep", "anything"]))
+ self.assertTrue(f.match(["sleep", "10"]))
+ f = filters.CommandFilter("sleep", 'root')
+ self.assertTrue(f.match(["sleep", "10"]))
+
+ def test_empty_commandfilter(self):
+ f = filters.CommandFilter("sleep", "root")
+ self.assertFalse(f.match([]))
+ self.assertFalse(f.match(None))
+
+ def test_empty_regexpfilter(self):
+ f = filters.RegExpFilter("sleep", "root", "sleep")
+ self.assertFalse(f.match([]))
+ self.assertFalse(f.match(None))
+
+ def test_empty_invalid_regexpfilter(self):
+ f = filters.RegExpFilter("sleep", "root")
+ self.assertFalse(f.match(["anything"]))
+ self.assertFalse(f.match([]))
+
def test_RegExpFilter_match(self):
usercmd = ["ls", "/root"]
filtermatch = wrapper.match_filter(self.filters, usercmd)
@@ -195,6 +221,9 @@ class RootwrapTestCase(utils.BaseTestCase):
# Providing something that is not a pid should be False
usercmd = ['kill', 'notapid']
self.assertFalse(f.match(usercmd))
+ # no arguments should also be fine
+ self.assertFalse(f.match([]))
+ self.assertFalse(f.match(None))
def test_KillFilter_deleted_exe(self):
"""Makes sure deleted exe's are killed correctly."""
@@ -289,6 +318,12 @@ class RootwrapTestCase(utils.BaseTestCase):
self.assertRaises(wrapper.NoFilterMatched,
wrapper.match_filter, filter_list, args)
+ def test_ReadFileFilter_empty_args(self):
+ goodfn = '/good/file.name'
+ f = filters.ReadFileFilter(goodfn)
+ self.assertFalse(f.match([]))
+ self.assertFalse(f.match(None))
+
def test_exec_dirs_search(self):
# This test supposes you have /bin/cat or /usr/bin/cat locally
f = filters.CommandFilter("cat", "root")
@@ -387,6 +422,10 @@ class PathFilterTestCase(utils.BaseTestCase):
self.SYMLINK_OUTSIDE_DIR = os.path.join(tmpdir.path, gen_name())
os.symlink(os.path.join('/tmp', 'some_file'), self.SYMLINK_OUTSIDE_DIR)
+ def test_empty_args(self):
+ self.assertFalse(self.f.match([]))
+ self.assertFalse(self.f.match(None))
+
def test_argument_pass_constraint(self):
f = filters.PathFilter('/bin/chown', 'root', 'pass', 'pass')