try not use socket share

This commit is contained in:
nom3ad 2022-11-06 14:03:54 +05:30 committed by Brian May
parent 2f88fc93cf
commit 3f34e27a2c
2 changed files with 40 additions and 21 deletions

View File

@ -223,13 +223,13 @@ class FirewallClient:
argv_tries.append(argvbase) argv_tries.append(argvbase)
else: else:
if sys.platform == 'win32': if sys.platform == 'win32':
argv_tries.append(argvbase)
# runas_path = which("runas") # runas_path = which("runas")
# if runas_path: # if runas_path:
# argv_tries.append([runas_path , '/noprofile', '/user:Administrator', 'python']) # argv_tries.append([runas_path , '/noprofile', '/user:Administrator', 'python'])
# XXX:attempt to elevate privilege using 'runas' in windows seems not working. # XXX: Attempt to elevate privilege using 'runas' in windows seems not working.
# This is due to underlying ShellExecute() Windows api does not allow child process to inherit stdio. # Because underlying ShellExecute() Windows api does not allow child process to inherit stdio.
# TODO(nom3ad): try to implement another way to achieve this. # TODO(nom3ad): Try to implement another way to achieve this.
raise Fatal("Privilege elevation for Windows is not yet implemented. Please run from an administrator shell")
else: else:
# Linux typically uses sudo; OpenBSD uses doas. However, some # Linux typically uses sudo; OpenBSD uses doas. However, some
# Linux distributions are starting to use doas. # Linux distributions are starting to use doas.
@ -294,22 +294,32 @@ class FirewallClient:
return s2.makefile('rwb') return s2.makefile('rwb')
else: else:
(s1, s2) = socket.socketpair() # In windows, if client/firewall processes is running as admin user, stdio can be used for communication.
pstdout = None # But if firewall process is run with elevated mode, access to stdio is lost.
# So we have to use a socketpair (as in unix).
# But socket need to be "shared" to child process as it can't be directly set as stdio in Windows
can_use_stdio = is_admin_user()
pstdout = ssubprocess.PIPE if can_use_stdio else None
pstdin = ssubprocess.PIPE pstdin = ssubprocess.PIPE
preexec_fn = None preexec_fn = None
penv = os.environ.copy() penv = os.environ.copy()
penv['PYTHONPATH'] = os.path.dirname(os.path.dirname(__file__)) penv['PYTHONPATH'] = os.path.dirname(os.path.dirname(__file__))
def get_pfile(): def get_pfile():
import base64 if can_use_stdio:
socket_share_data = s1.share(self.p.pid) import io
s1.close() self.p.stdin.write(b'STDIO:\n')
socket_share_data_b64 = base64.b64encode(socket_share_data) self.p.stdin.flush()
self.p.stdin.write(socket_share_data_b64 + b'\n') return io.BufferedRWPair(self.p.stdout, self.p.stdin, 1)
self.p.stdin.flush() else:
return s2.makefile('rwb') import base64
(s1, s2) = socket.socketpair()
socket_share_data = s1.share(self.p.pid)
s1.close()
socket_share_data_b64 = base64.b64encode(socket_share_data)
self.p.stdin.write(b'SOCKETSHARE:' + socket_share_data_b64 + b'\n')
self.p.stdin.flush()
return s2.makefile('rwb')
try: try:
debug1("Starting firewall manager with command: %r" % argv) debug1("Starting firewall manager with command: %r" % argv)
self.p = ssubprocess.Popen(argv, stdout=pstdout, stdin=pstdin, env=penv, self.p = ssubprocess.Popen(argv, stdout=pstdout, stdin=pstdin, env=penv,

View File

@ -121,13 +121,22 @@ def _setup_daemon_windows():
signal.signal(signal.SIGTERM, firewall_exit) signal.signal(signal.SIGTERM, firewall_exit)
signal.signal(signal.SIGINT, firewall_exit) signal.signal(signal.SIGINT, firewall_exit)
socket_share_data_b64 = sys.stdin.readline()
# debug3(f'FROM_SHARE ${socket_share_data_b64=}') socket_share_data_prefix = 'SOCKETSHARE:'
socket_share_data = base64.b64decode(socket_share_data_b64) line = sys.stdin.readline().strip()
sock = socket.fromshare(socket_share_data) if line.startswith('SOCKETSHARE:'):
sys.stdin = io.TextIOWrapper(sock.makefile('rb', buffering=0)) debug3('Using shared socket for communicating with sshuttle client process')
sys.stdout = io.TextIOWrapper(sock.makefile('wb', buffering=0), write_through=True) socket_share_data_b64 = line[len(socket_share_data_prefix):]
sock.close() socket_share_data = base64.b64decode(socket_share_data_b64)
sock = socket.fromshare(socket_share_data)
sys.stdin = io.TextIOWrapper(sock.makefile('rb', buffering=0))
sys.stdout = io.TextIOWrapper(sock.makefile('wb', buffering=0), write_through=True)
sock.close()
elif line.startswith("STDIO:"):
debug3('Using inherited stdio for communicating with sshuttle client process')
else:
raise Fatal("Unexpected stdin: " + line)
return sys.stdin, sys.stdout return sys.stdin, sys.stdout