3 # ATTENTION: Yes, this can be used as a backdoor, but only for an
4 # adversary with access to you *physical* serial port, which means
5 # that you are screwed any way.
7 from subprocess
import Popen
, PIPE
9 from json
import dumps
, loads
10 from pwd
import getpwnam
11 from os
import setgid
, setuid
, environ
15 def mk_switch_user_fn(uid
, gid
):
21 def run_cmd_as_user(cmd
, user
):
23 pwd_user
= getpwnam(user
)
24 switch_user_fn
= mk_switch_user_fn(pwd_user
.pw_uid
,
28 env
['USERNAME'] = user
29 env
['HOME'] = pwd_user
.pw_dir
30 env
['MAIL'] = "/var/mail/" + user
31 env
['PWD'] = env
['HOME']
32 env
['DISPLAY'] = ':0.0'
34 env
['XAUTHORITY'] = glob("/var/run/gdm3/auth-for-amnesia-*/database")[0]
38 return Popen(cmd
, stdout
=PIPE
, stderr
=PIPE
, shell
=True, env
=env
, cwd
=cwd
,
39 preexec_fn
=switch_user_fn
)
43 port
= serial
.Serial(port
= dev
, baudrate
= 4000000)
47 line
= port
.readline()
48 except Exception as e
:
49 # port must be opened wrong, so we restart everything and pray
55 cmd_type
, user
, cmd
= loads(line
)
56 except Exception as e
:
57 # We had a parse/pack error, so we just send a \0 as an ACK,
58 # releasing the client from blocking.
62 p
= run_cmd_as_user(cmd
, user
)
63 if cmd_type
== "spawn":
64 returncode
, stdout
, stderr
= 0, "", ""
66 stdout
, stderr
= p
.communicate()
67 returncode
= p
.returncode
68 port
.write(dumps([returncode
, stdout
, stderr
]) + "\0")
70 if __name__
== "__main__":