ftp -o - https://jcs.org/move_in | sh -
1#!/bin/sh -e
2#
3# xsudo
4# Run an X11 command via sudo (most likely as an unprivileged user) with
5# temporary, untrusted xauth forwarding and rc-file copying
6#
7# Copyright (c) 2017 joshua stein <jcs@jcs.org>
8#
9# Permission to use, copy, modify, and distribute this software for any
10# purpose with or without fee is hereby granted, provided that the above
11# copyright notice and this permission notice appear in all copies.
12#
13# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20#
21
22#
23# Example setup:
24# groupadd _firefox
25# usermod -G _firefox $USER
26# useradd -g _firefox -m _firefox
27# chmod 770 ~_firefox
28# cp -r ~/.mozilla ~_firefox/
29# chown -R _firefox:_firefox ~_firefox/.mozilla
30#
31# Add to sudoers:
32# %wheel ALL=(_firefox) NOPASSWD: /usr/local/bin/firefox
33#
34# Example usage:
35# xsudo -u _firefox /usr/local/bin/firefox
36#
37# By default, ~/.fonts.conf and ~/.config/gtk-3.0 are copied into the
38# unprivileged user's home directory before running. Additional
39# files/directories can be specified with multiple -f flags.
40#
41# X11 connections are untrusted by default, but some programs (like firefox)
42# run much slower in this mode for some reason. Passing -t will mark these
43# temporary connections as trusted (see Xsecurity(7)).
44#
45
46usage() {
47 echo "usage: `basename $0` [-f file to copy] [-t] -u username command"
48 exit 1
49}
50
51UNPRIV_USER=
52CMD=
53TRUSTED="untrusted"
54RC_FILES=".fonts.conf .config/gtk-3.0/"
55
56while getopts "f:tu:" o; do
57 case "$o" in
58 f)
59 RC_FILES="${RC_FILES} ${OPTARG}"
60 ;;
61 t)
62 TRUSTED="trusted"
63 ;;
64 u)
65 UNPRIV_USER="$OPTARG"
66 ;;
67 *)
68 usage
69 ;;
70 esac
71done
72shift $((OPTIND-1))
73
74if [ X"${1}" = X"" ]; then
75 usage
76fi
77
78CMD=$*
79
80# validate unprivileged user
81if [ X"$UNPRIV_USER" = X"" ]; then
82 usage
83fi
84PLINE="getent passwd ${UNPRIV_USER}"
85if [ X"`${PLINE}`" = X"" ]; then
86 echo "user \"${UNPRIV_USER}\" does not exist" > /dev/stderr
87 usage
88fi
89UNPRIV_HOME=`${PLINE} | awk '{ FS=":" }{ print $6 }'`
90if [ X"${UNPRIV_HOME}" = X"" -o ! -d $UNPRIV_HOME ]; then
91 echo "home of ${UNPRIV_USER} (${UNPRIV_HOME}) does not exist" > /dev/stderr
92 exit 1
93fi
94
95# validate unprivileged user's home directory permissions, which must
96# allow us to write to it, but noone else to read from it
97UNPRIV_HOME_P=`ls -l ${UNPRIV_HOME} | awk '{ print $1 }'`
98if [ X"$UNPRIV_HOME_P" = X"drwxrwx---" ]; then
99 echo "permissions on ${UNPRIV_HOME} must be 0770, are ${UNPRIV_HOME_P}"
100 exit 1
101fi
102
103# generate temporary untrusted authorization
104if [ -f $UNPRIV_HOME/.Xauthority ]; then
105 rm -f $UNPRIV_HOME/.Xauthority
106fi
107touch $UNPRIV_HOME/.Xauthority
108xauth -f $UNPRIV_HOME/.Xauthority generate $DISPLAY . $TRUSTED
109chmod 660 $UNPRIV_HOME/.Xauthority
110
111# copy files into the untrusted user's home
112(cd ~; tar -chf - $RC_FILES) | (cd $UNPRIV_HOME; tar xf -)
113for f in $RC_FILES; do
114 chgrp -R $UNPRIV_USER $UNPRIV_HOME/$f
115 chmod -R g=u $UNPRIV_HOME/$f
116done
117
118# run the actual command
119cd $UNPRIV_HOME
120sudo -u $UNPRIV_USER -H $CMD
121
122# remove auth
123rm -f $UNPRIV_HOME/.Xauthority