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)
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')