Commit f528bb98 authored by Steven McDonald's avatar Steven McDonald

Add --no-sudo-pythonpath option

This provides a way to avoid setting PYTHONPATH when invoking the
privileged part of sshuttle with sudo. This is useful if running
sshuttle as a PEX archive, as Telepresence does, as it enables
sshuttle's sudo access to be securely locked down.

PEX archives will extract themselves into the invoking user's home
directory, which means that the invoking user has full control over
the code in them. This makes restricting sudo access with
PYTHONPATH set completely pointless in this scenario -- an attacker
could put any code into ~/.pex and gain full root access anyway.

On the other hand, if sshuttle is a PEX archive, the privileged
invocation will simply extract itself into /root/.pex anyway, so
there is no need to set PYTHONPATH in this case.
parent 561b648e
......@@ -183,7 +183,7 @@ class MultiListener:
class FirewallClient:
def __init__(self, method_name):
def __init__(self, method_name, sudo_pythonpath):
# Default to sudo unless on OpenBSD in which case use built in `doas`
elevbin = 'sudo'
......@@ -198,10 +198,12 @@ class FirewallClient:
['--firewall'])
if ssyslog._p:
argvbase += ['--syslog']
elev_prefix = [part % {'eb': elevbin, 'pp': python_path}
elev_prefix = [part % {'eb': elevbin}
for part in ['%(eb)s', '-p',
'[local %(eb)s] Password: ',
'/usr/bin/env', 'PYTHONPATH=%(pp)s']]
'[local %(eb)s] Password: ']]
if sudo_pythonpath:
elev_prefix += ['/usr/bin/env',
'PYTHONPATH=%s' % python_path]
argv_tries = [elev_prefix + argvbase, argvbase]
# we can't use stdin/stdout=subprocess.PIPE here, as we normally would,
......@@ -550,7 +552,7 @@ def main(listenip_v6, listenip_v4,
ssh_cmd, remotename, python, latency_control, dns, nslist,
method_name, seed_hosts, auto_hosts, auto_nets,
subnets_include, subnets_exclude, daemon, to_nameserver, pidfile,
user):
user, sudo_pythonpath):
if daemon:
try:
......@@ -560,7 +562,7 @@ def main(listenip_v6, listenip_v4,
return 5
debug1('Starting sshuttle proxy.\n')
fw = FirewallClient(method_name)
fw = FirewallClient(method_name, sudo_pythonpath)
# Get family specific subnet lists
if dns:
......
......@@ -76,7 +76,8 @@ def main():
opt.daemon,
opt.to_ns,
opt.pidfile,
opt.user)
opt.user,
opt.sudo_pythonpath)
if return_code == 0:
log('Normal exit code, exiting...')
......
......@@ -310,3 +310,11 @@ parser.add_argument(
(internal use only)
"""
)
parser.add_argument(
"--no-sudo-pythonpath",
action="store_false",
dest="sudo_pythonpath",
help="""
do not set PYTHONPATH when invoking sudo
"""
)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment