commit 407159e0afba5294cb855b6db771452e9e351a39
parent dbe0ab77f9cac03173d03ec8ab94a25e3935ab2f
Author: Jan Pobrislo <ccx@webprojekty.cz>
Date: Tue, 15 Dec 2020 03:38:41 +0100
Replace user-terminal.py with more generic spawn-pty.py; use execlineb for interpreting terminal command.
Diffstat:
4 files changed, 101 insertions(+), 102 deletions(-)
diff --git a/bin/spawn-pty.py b/bin/spawn-pty.py
@@ -0,0 +1,90 @@
+#!/usr/bin/env python
+
+from __future__ import (
+ generators, division, absolute_import, with_statement, print_function
+)
+import sys
+import os
+import os.path
+import pwd
+import argparse
+import re
+
+parser = argparse.ArgumentParser(description="Runs one program inside pty and another with changed privileges with master pty as fd 0")
+parser.add_argument('term_env', help='The TERM variable used by the slave')
+parser.add_argument('exe', nargs='+', help='Execline block defining program ran on slave end, then terminal program')
+
+
+def execve(argv, env):
+ if '/' in argv[0]:
+ os.execve(argv[0], argv, env)
+ else:
+ for p in os.environ['PATH'].split(os.path.pathsep):
+ os.execve(os.path.join(p, argv[0]), argv, env)
+ raise SystemExit(1)
+
+
+def exec_terminal(uid, gid, home, terminal, term_env, slave_exe):
+ assert isinstance(uid, int)
+ assert isinstance(gid, int)
+ assert isinstance(home, str)
+ assert isinstance(terminal, (list, tuple))
+ assert all(isinstance(s, str) for s in terminal)
+ assert len(terminal)
+ assert isinstance(slave_exe, list)
+ assert all(isinstance(s, str) for s in slave_exe)
+ master, slave = os.openpty()
+ if os.fork():
+ # parent
+ os.close(slave)
+ os.dup2(master, 0)
+ os.close(master)
+ env = dict(os.environ)
+ env['PTY_FD'] = "0"
+ env['HOME'] = home
+ execve(terminal, env)
+ else:
+ # child
+ os.close(master)
+ os.dup2(slave, 0)
+ os.dup2(slave, 1)
+ os.dup2(slave, 2)
+ os.close(slave)
+ os.setsid()
+ env = dict(os.environ)
+ env['TERM'] = term_env
+ env.pop('LOGNAME', None)
+ execve(slave_exe, env)
+
+
+def main():
+ args = parser.parse_args()
+
+ argv = list(args.exe)
+ slave_argv = []
+
+ while argv:
+ a = argv.pop(0)
+ if a == '':
+ break
+ elif a[0] == ' ':
+ slave_argv.append(a[1:])
+ else:
+ sys.stderr.write("Improperly terminated block!\n")
+ return 1
+ if not argv:
+ sys.stderr.write("Terminal executable not specified.\n")
+ return 1
+
+ exec_terminal(
+ uid=uid,
+ gid=gid,
+ home=pwent.pw_dir,
+ terminal=argv,
+ slave_exe=slave_argv,
+ term_env=args.term_env,
+ )
+
+
+if __name__ == '__main__':
+ main()
diff --git a/bin/zshaskpass_lock b/bin/zshaskpass_lock
@@ -46,7 +46,7 @@ if [[ -n $X ]]; then
typeset -g plumber_fifo
plumber_fifo=/run/containers/xsession.$X.ccx/run/plumber_fifo
exec_socket=$HOME/chome/xsession.$[ ${TTY#/dev/tty} + 4 ]/exec/socket
- terminal_args=( s6-sudo $exec_socket:A urxvt -pty-fd 0 )
+ terminal_args=( s6-sudo $exec_socket:A background urxvt -pty-fd 0 )
terminal_env=rxvt-unicode # the TERM variable used
else
coproc_args+=( tail -F /run/user/ccx.logs/current )
diff --git a/sbin/logincaps b/sbin/logincaps
@@ -73,7 +73,7 @@ cap_cmd() {
}
main() {
- local line term_cmd REPLY
+ local line term_cmd term_env REPLY
while read line; do
case $line in
(o) printf >&2 "%s\n" "Would power-off."
@@ -94,10 +94,15 @@ main() {
;;
(terminal-wpa_cli *)
- term_cmd=( "${(Q@)${(z)${line#* }}}" )
- printf >&2 "%s\n" "Would launch terminal with wpa_cli."
- pretendrun /command/user-term.py -u $USER -g $USER -- "$term_cmd[1]" ' wpa_cli' '' "${(@)term_cmd[2,-1]}"
- /command/user-term.py -u $USER -g $USER -- "$term_cmd[1]" ' wpa_cli' '' "${(@)term_cmd[2,-1]}" </dev/null >&2 &!
+ term_cmd="${line#* }"
+ term_env=${term_cmd$$ *}
+ if ! [[ $term_env =~ [-.0-9a-zA-Z]* ]]; then
+ printf 'ERR: invalid TERM'
+ continue
+ fi
+ term_cmd="${term_cmd#* }"
+ cap_cmd execlineb -c "/command/spawn-pty.py -- ${(qqq)term_env} { wpa_cli } s6-setuidgid ${(qqq)USER} $term_cmd"
+ #/command/user-term.py -u $USER -g $USER -- "$term_cmd[1]" ' wpa_cli' '' "${(@)term_cmd[2,-1]}" </dev/null >&2 &!
printf 'OK\n'
;;
diff --git a/sbin/user-term.py b/sbin/user-term.py
@@ -1,96 +0,0 @@
-#!/usr/bin/env python
-
-from __future__ import (
- generators, division, absolute_import, with_statement, print_function
-)
-import sys
-import os
-import os.path
-import pwd
-import argparse
-import re
-
-parser = argparse.ArgumentParser(description="Runs one program as current user in pty and another with changed privileges with master pty fd")
-parser.add_argument('-u', '--user', required=True, help="User name or ID to run terminal as")
-parser.add_argument('-g', '--group', type=int, help="Group ID to run terminal as")
-parser.add_argument('term_env', help='The TERM variable used by the slave')
-parser.add_argument('exe', nargs='+', help='Execline block defining program ran on slave end, then terminal program')
-
-
-def exec_terminal(uid, gid, home, terminal, term_env, slave_exe):
- assert isinstance(uid, int)
- assert isinstance(gid, int)
- assert isinstance(home, str)
- assert isinstance(terminal, (list, tuple))
- assert all(isinstance(s, str) for s in terminal)
- assert len(terminal)
- assert isinstance(slave_exe, list)
- assert all(isinstance(s, str) for s in slave_exe)
- master, slave = os.openpty()
- if os.fork():
- # parent
- os.close(slave)
- os.dup2(master, 0)
- os.close(master)
- os.setgid(gid)
- os.setuid(uid)
- os.chdir(home)
- env = dict(os.environ)
- env['PTY_FD'] = "0"
- env['HOME'] = home
- if '/' in terminal[0]:
- os.execve(terminal[0], terminal, env)
- else:
- # TODO: proper search path
- os.execve('/command/exec', ['exec'] + terminal, env)
- else:
- # child
- os.close(master)
- os.dup2(slave, 0)
- os.dup2(slave, 1)
- os.dup2(slave, 2)
- os.close(slave)
- os.setsid()
- env = dict(os.environ)
- env['TERM'] = term_env
- env.pop('LOGNAME', None)
- os.execve('/command/exec', ['exec'] + slave_exe, env)
-
-
-def main():
- args = parser.parse_args()
- if re.match('[0-9]+', args.user):
- uid = int(args.user)
- pwent = pwd.getpwuid(uid)
- else:
- pwent = pwd.getpwnam(args.user)
- uid = pwent.pw_uid
- gid = pwent.pw_gid if args.group is None else int(args.group)
-
- argv = list(args.exe)
- slave_argv = []
- while argv:
- a = argv.pop(0)
- if a == '':
- break
- elif a[0] == ' ':
- slave_argv.append(a[1:])
- else:
- sys.stderr.write("Improperly terminated block!\n")
- return 1
- if not argv:
- sys.stderr.write("Terminal executable not specified.\n")
- return 1
-
- exec_terminal(
- uid=uid,
- gid=gid,
- home=pwent.pw_dir,
- terminal=argv,
- slave_exe=slave_argv,
- term_env=args.term_env,
- )
-
-
-if __name__ == '__main__':
- main()