Skip to content

Commit

Permalink
Validate ionice and nice parameters
Browse files Browse the repository at this point in the history
  • Loading branch information
Safihre committed Jun 21, 2020
1 parent db13ae5 commit 73d3f7b
Show file tree
Hide file tree
Showing 5 changed files with 142 additions and 27 deletions.
1 change: 1 addition & 0 deletions interfaces/Config/templates/config_switches.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
</div>
<form action="saveSwitches" method="post" name="fullform" class="fullform" autocomplete="off">
<input type="hidden" id="apikey" name="apikey" value="$apikey" />
<input type="hidden" id="ajax" name="ajax" value="1" />
<div class="section advanced-settings">
<div class="col2">
<h3>$T('swtag-server') <a href="$helpuri$help_uri#toc1" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a></h3>
Expand Down
29 changes: 14 additions & 15 deletions sabnzbd/cfg.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,30 +21,29 @@
import re

import sabnzbd
from sabnzbd.constants import (
DEF_HOST,
DEF_PORT,
DEF_STDINTF,
DEF_ADMIN_DIR,
DEF_DOWNLOAD_DIR,
DEF_NZBBACK_DIR,
DEF_SCANRATE,
DEF_COMPLETE_DIR,
)

from sabnzbd.config import (
OptionBool,
OptionNumber,
OptionPassword,
OptionDir,
OptionStr,
OptionList,
no_nonsense,
validate_octal,
validate_safedir,
all_lowercase,
create_api_key,
validate_notempty,
clean_nice_ionice_parameters,
)
from sabnzbd.constants import (
DEF_HOST,
DEF_PORT,
DEF_STDINTF,
DEF_ADMIN_DIR,
DEF_DOWNLOAD_DIR,
DEF_NZBBACK_DIR,
DEF_SCANRATE,
DEF_COMPLETE_DIR,
)

##############################################################################
Expand Down Expand Up @@ -156,11 +155,11 @@ def validate_server(value):
ssl_ciphers = OptionStr("misc", "ssl_ciphers", "") # Now per-server setting
enable_recursive = OptionBool("misc", "enable_recursive", True)
flat_unpack = OptionBool("misc", "flat_unpack", False)
par_option = OptionStr("misc", "par_option", "", validation=no_nonsense)
par_option = OptionStr("misc", "par_option", "")
pre_check = OptionBool("misc", "pre_check", False)
nice = OptionStr("misc", "nice", "", validation=no_nonsense)
nice = OptionStr("misc", "nice", "", validation=clean_nice_ionice_parameters)
win_process_prio = OptionNumber("misc", "win_process_prio", 3)
ionice = OptionStr("misc", "ionice", "", validation=no_nonsense)
ionice = OptionStr("misc", "ionice", "", validation=clean_nice_ionice_parameters)
fail_hopeless_jobs = OptionBool("misc", "fail_hopeless_jobs", True)
fast_fail = OptionBool("misc", "fast_fail", True)
autodisconnect = OptionBool("misc", "auto_disconnect", True)
Expand Down
44 changes: 34 additions & 10 deletions sabnzbd/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,21 @@
"""
sabnzbd.config - Configuration Support
"""

import argparse
import logging
import os
import re
import logging
import threading
import shutil
import threading
import uuid
from urllib.parse import urlparse

import configobj

import sabnzbd.misc
from sabnzbd.filesystem import clip_path, real_path, create_real_path, renamer, remove_file, is_writable
from sabnzbd.constants import CONFIG_VERSION, NORMAL_PRIORITY, DEFAULT_PRIORITY, MAX_WIN_DFOLDER
import configobj
from sabnzbd.decorators import synchronized
from sabnzbd.filesystem import clip_path, real_path, create_real_path, renamer, remove_file, is_writable

CONFIG_LOCK = threading.Lock()
SAVE_CONFIG_LOCK = threading.Lock()
Expand Down Expand Up @@ -1008,6 +1010,13 @@ def get_filename():
__PW_PREFIX = "!!!encoded!!!"


class ErrorCatchingArgumentParser(argparse.ArgumentParser):
def error(self, status=0, message=None):
# Need to override so it doesn't raise SystemExit
if status:
raise ValueError


def encode_password(pw):
""" Encode password in hexadecimal if needed """
enc = False
Expand Down Expand Up @@ -1041,11 +1050,26 @@ def decode_password(pw, name):
return pw


def no_nonsense(value):
""" Strip and Filter out None and 'None' from strings """
value = str(value).strip()
if value.lower() == "none":
value = ""
def clean_nice_ionice_parameters(value):
""" Verify that the passed parameters are not exploits """
if value:
parser = ErrorCatchingArgumentParser()

# Nice parameters
parser.add_argument("-n", "--adjustment", type=int)

# Ionice parameters, not supporting -p
parser.add_argument("--classdata", type=int)
parser.add_argument("-c", "--class", type=int)
parser.add_argument("-t", "--ignore", action="store_true")

try:
parser.parse_args(value.split())
except ValueError:
# Also log at start-up if invalid parameter was set in the ini
msg = "%s: %s" % (T("Incorrect parameter"), value)
logging.error(msg)
return msg, None
return None, value


Expand Down
7 changes: 5 additions & 2 deletions sabnzbd/interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -1311,15 +1311,18 @@ def saveSwitches(self, **kwargs):
value = value.lower().replace(".", "")
msg = item.set(value)
if msg:
return badParameterResponse(msg)
return badParameterResponse(msg, kwargs.get("ajax"))

cleanup_list = kwargs.get("cleanup_list")
if cleanup_list and sabnzbd.WIN32:
cleanup_list = cleanup_list.lower()
cfg.cleanup_list.set(cleanup_list)

config.save_config()
raise Raiser(self.__root)
if kwargs.get("ajax"):
return sabnzbd.api.report("json")
else:
raise Raiser(self.__root)


##############################################################################
Expand Down
88 changes: 88 additions & 0 deletions tests/test_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
#!/usr/bin/python3 -OO
# Copyright 2007-2020 The SABnzbd-Team <team@sabnzbd.org>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

"""
tests.test_config - Testing functions in config.py
"""

import sabnzbd.config as config


class TestValidators:
def test_clean_nice_ionice_parameters_allowed(self):
""" Allowed nice and ionice parameters
https://linux.die.net/man/1/nice
https://linux.die.net/man/1/ionice
"""

def assert_allowed(inp_value):
""" Helper function to check for block """
msg, value = config.clean_nice_ionice_parameters(inp_value)
assert msg is None
assert value == inp_value

# nice
assert_allowed("-n1")
assert_allowed("-n-11")
assert_allowed("-n 3")
assert_allowed("-n -4")
assert_allowed("--adjustment=11")
assert_allowed("--adjustment=-7")
assert_allowed("--adjustment 20")
assert_allowed("--adjustment -8")

# ionice
assert_allowed("-c1")
assert_allowed("-c-11")
assert_allowed("-c 3")
assert_allowed("-c -4")
assert_allowed("--classdata=1")
assert_allowed("--classdata=-11")
assert_allowed("--classdata 3")
assert_allowed("--classdata -4")
assert_allowed("-t")
assert_allowed("--ignore")
assert_allowed("-c 11 -n 12 -t")
assert_allowed("-c 11 --classdata=12 --ignore")
assert_allowed("--ignore -n9 --class=7")
assert_allowed("-t -n9 -c7")

def test_clean_nice_ionice_parameters_blocked(self):
""" Should all be blocked """

def assert_blocked(inp_value):
""" Helper function to check for block """
msg, value = config.clean_nice_ionice_parameters(inp_value)
assert msg
assert msg.startswith("Incorrect parameter")
assert value is None

assert_blocked("-ca")
assert_blocked("-t11")
assert_blocked("-p 11")
assert_blocked("123")
assert_blocked("/bin/sh /tmp/test.sh")
assert_blocked("'/evil.sh' 11")
assert_blocked("; 11")
assert_blocked("python evil.py")
assert_blocked("-n5 /bin/echo 666")
assert_blocked("4 && test.sh")
assert_blocked("-t | bla.py")
assert_blocked("5 || now")
assert_blocked("echo 'how;now;brown;cow'")
assert_blocked("-c'echo'")
assert_blocked("--classdata=;/bin/echo")

0 comments on commit 73d3f7b

Please sign in to comment.