mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-02-25 08:43:36 +00:00
The package license (AGPL3+) implicitly indicates the license of each file. However, it is desirable to have license headers in each file. This is the case for many prominent projects like GNU project, Mozilla etc.
134 lines
4.3 KiB
Python
134 lines
4.3 KiB
Python
#!/usr/bin/python3
|
|
# -*- mode: python; mode: auto-fill; fill-column: 80 -*-
|
|
#
|
|
# This file is part of Plinth.
|
|
#
|
|
# This program is free software: you can redistribute it and/or modify
|
|
# it 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.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU Affero General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU Affero General Public License
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
#
|
|
|
|
import os
|
|
import shlex
|
|
import subprocess
|
|
import unittest
|
|
|
|
from plinth.actions import superuser_run, run
|
|
from plinth import cfg
|
|
|
|
|
|
ROOT_DIR = os.path.split(os.path.abspath(os.path.split(__file__)[0]))[0]
|
|
cfg.actions_dir = os.path.join(ROOT_DIR, 'actions')
|
|
|
|
|
|
class TestPrivileged(unittest.TestCase):
|
|
"""Verify that privileged actions perform as expected.
|
|
|
|
See actions.py for a full description of the expectations.
|
|
|
|
Symlink to ``echo`` and ``id`` during testing.
|
|
|
|
"""
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
os.symlink("/bin/echo", "actions/echo")
|
|
os.symlink("/usr/bin/id", "actions/id")
|
|
|
|
@classmethod
|
|
def tearDownClass(cls):
|
|
os.remove("actions/echo")
|
|
os.remove("actions/id")
|
|
|
|
def notest_run_as_root(self):
|
|
"""1. Privileged actions run as root. """
|
|
# TODO: it's not allowed to call a symlink in the actions dir anymore
|
|
self.assertEqual(
|
|
"0", # user 0 is root
|
|
superuser_run("id", "-ur")[0].strip())
|
|
|
|
def test_breakout_actions_dir(self):
|
|
"""2. The actions directory can't be changed at run time.
|
|
|
|
Can't currently be tested, as the actions directory is hardcoded.
|
|
|
|
"""
|
|
pass
|
|
|
|
def test_breakout_up(self):
|
|
"""3A. Users can't call actions above the actions directory.
|
|
|
|
Tests both a relative and a literal path.
|
|
|
|
"""
|
|
options="hi"
|
|
|
|
for arg in ("../echo", "/bin/echo"):
|
|
with self.assertRaises(ValueError):
|
|
run(arg, options)
|
|
|
|
def test_breakout_down(self):
|
|
"""3B. Users can't call actions beneath the actions directory."""
|
|
action="directory/echo"
|
|
|
|
self.assertRaises(ValueError, superuser_run, action)
|
|
|
|
def test_breakout_actions(self):
|
|
"""3C. Actions can't be used to run other actions.
|
|
|
|
If multiple actions are specified, bail out.
|
|
|
|
"""
|
|
# counting is safer than actual badness.
|
|
actions = ("echo ''; echo $((1+1))",
|
|
"echo '' && echo $((1+1))",
|
|
"echo '' || echo $((1+1))")
|
|
options = ("good", "")
|
|
|
|
for action in actions:
|
|
for option in options:
|
|
with self.assertRaises(ValueError):
|
|
output = run(action, option)
|
|
# if it somewhow doesn't error, we'd better not evaluate
|
|
# the data.
|
|
self.assertFalse("2" in output[0])
|
|
|
|
def test_breakout_option_string(self):
|
|
"""3D. Option strings can't be used to run other actions.
|
|
Verify that shell control characters aren't interpreted.
|
|
"""
|
|
action = "echo"
|
|
# counting is safer than actual badness.
|
|
options = "good; echo $((1+1))"
|
|
self.assertRaises(ValueError, run, action, options)
|
|
|
|
def test_breakout_option_list(self):
|
|
"""3D. Option lists can't be used to run other actions.
|
|
Verify that only a string of options is accepted and that we can't just
|
|
tack additional shell control characters onto the list.
|
|
"""
|
|
action = "echo"
|
|
# counting is safer than actual badness.
|
|
options = ["good", ";", "echo $((1+1))"]
|
|
# we'd better not evaluate the data.
|
|
self.assertRaises(ValueError, run, action, options)
|
|
|
|
def notest_multiple_options(self):
|
|
""" 4. Multiple options can be provided as a list. """
|
|
# TODO: it's not allowed to call a symlink in the actions dir anymore
|
|
self.assertEqual(
|
|
subprocess.check_output(shlex.split("id -ur")).strip(),
|
|
run("id", ["-u" ,"-r"])[0].strip())
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|