mirror of
https://github.com/borgbackup/borg.git
synced 2025-03-15 00:21:56 +00:00
borg serve: overwrite client's --restrict-to-path with forced command's option value, fixes #544
we also make sure the client is not cheating, like giving another subcommand or his own --restrict-to-path.
This commit is contained in:
parent
824e548b9f
commit
7ea2404048
2 changed files with 37 additions and 1 deletions
|
@ -7,6 +7,7 @@ import functools
|
||||||
import inspect
|
import inspect
|
||||||
import io
|
import io
|
||||||
import os
|
import os
|
||||||
|
import shlex
|
||||||
import signal
|
import signal
|
||||||
import stat
|
import stat
|
||||||
import sys
|
import sys
|
||||||
|
@ -1332,6 +1333,20 @@ class Archiver:
|
||||||
help='hex object ID(s) to delete from the repo')
|
help='hex object ID(s) to delete from the repo')
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
|
def get_args(self, argv, cmd):
|
||||||
|
"""usually, just returns argv, except if we deal with a ssh forced command for borg serve."""
|
||||||
|
result = self.parse_args(argv[1:])
|
||||||
|
if cmd is not None and result.func == self.do_serve:
|
||||||
|
forced_result = result
|
||||||
|
argv = shlex.split(cmd)
|
||||||
|
result = self.parse_args(argv[1:])
|
||||||
|
if result.func != forced_result.func:
|
||||||
|
# someone is trying to execute a different borg subcommand, don't do that!
|
||||||
|
return forced_result
|
||||||
|
# the only thing we take from the forced "borg serve" ssh command is --restrict-to-path
|
||||||
|
result.restrict_to_paths = forced_result.restrict_to_paths
|
||||||
|
return result
|
||||||
|
|
||||||
def parse_args(self, args=None):
|
def parse_args(self, args=None):
|
||||||
# We can't use argparse for "serve" since we don't want it to show up in "Available commands"
|
# We can't use argparse for "serve" since we don't want it to show up in "Available commands"
|
||||||
if args:
|
if args:
|
||||||
|
@ -1407,7 +1422,7 @@ def main(): # pragma: no cover
|
||||||
setup_signal_handlers()
|
setup_signal_handlers()
|
||||||
archiver = Archiver()
|
archiver = Archiver()
|
||||||
msg = None
|
msg = None
|
||||||
args = archiver.parse_args(sys.argv[1:])
|
args = archiver.get_args(sys.argv, os.environ.get('SSH_ORIGINAL_COMMAND'))
|
||||||
try:
|
try:
|
||||||
exit_code = archiver.run(args)
|
exit_code = archiver.run(args)
|
||||||
except Error as e:
|
except Error as e:
|
||||||
|
|
|
@ -1129,3 +1129,24 @@ class RemoteArchiverTestCase(ArchiverTestCase):
|
||||||
@unittest.skip('only works locally')
|
@unittest.skip('only works locally')
|
||||||
def test_debug_put_get_delete_obj(self):
|
def test_debug_put_get_delete_obj(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_args():
|
||||||
|
archiver = Archiver()
|
||||||
|
# everything normal:
|
||||||
|
# first param is argv as produced by ssh forced command,
|
||||||
|
# second param is like from SSH_ORIGINAL_COMMAND env variable
|
||||||
|
args = archiver.get_args(['borg', 'serve', '--restrict-to-path=/p1', '--restrict-to-path=/p2', ],
|
||||||
|
'borg serve --info --umask=0027')
|
||||||
|
assert args.func == archiver.do_serve
|
||||||
|
assert args.restrict_to_paths == ['/p1', '/p2']
|
||||||
|
assert args.umask == 0o027
|
||||||
|
assert args.log_level == 'info'
|
||||||
|
# trying to cheat - break out of path restriction
|
||||||
|
args = archiver.get_args(['borg', 'serve', '--restrict-to-path=/p1', '--restrict-to-path=/p2', ],
|
||||||
|
'borg serve --restrict-to-path=/')
|
||||||
|
assert args.restrict_to_paths == ['/p1', '/p2']
|
||||||
|
# trying to cheat - try to execute different subcommand
|
||||||
|
args = archiver.get_args(['borg', 'serve', '--restrict-to-path=/p1', '--restrict-to-path=/p2', ],
|
||||||
|
'borg init /')
|
||||||
|
assert args.func == archiver.do_serve
|
||||||
|
|
Loading…
Add table
Reference in a new issue