commit 769209065dde6365070dff9ccce54e627fecd1ee from: the xhr date: Mon Sep 07 17:05:02 2020 UTC Sync with latest changes form upstream (not written by me) commit - ee81442939ec433b2fe2b792a04e94f854c2a68b commit + 769209065dde6365070dff9ccce54e627fecd1ee blob - b68e39f16415bfa312bfa044d585da806992c2e4 blob + 38640772dcae729cc22b3892bffe69c49e2e79c9 --- xodo.sh +++ xodo.sh @@ -1,95 +1,146 @@ #!/bin/sh -set -e - main() { - if [[ "$1" == "" ]]; then + if [ -z "$1" ]; then echo "Missing arguments" >&2 display_usage >&2 return 1 - elif [[ "$1" == "-h" ]] || [[ "$1" == "--help" ]]; then + elif [ "$1" = "-h" ] || [ "$1" = "--help" ]; then display_usage - elif [[ "$1" == "--setup" ]]; then + elif [ "$1" = "--setup" ]; then shift - setup $@ + setup "$@" else - execute $@ + execute "$@" fi } execute() { - command=`which -- $1` - basename=`basename $command` - asuser=$USER-$basename + command="" + asuser="" - shift + while [ -n "$1" ]; do + if [ "$1" = "--as" ]; then + if [ -z "$2" ]; then + echo "--as user not specified" >&2 + display_usage >&2 + return 1 + elif [ -n "$asuser" ]; then + echo "--as user specified twice" >&2 + display_usage >&2 + return 1 + fi - if [[ "$1" == "--as" ]]; then - if [[ "$2" == "" ]]; then - echo "--as user not specified" >&2 - display_usage >&2 - return 1 + asuser="$2" + shift + shift + elif [ -z "$command" ]; then + command="$1" + shift + elif [ "$1" = "--" ]; then + shift + break + else + break fi + done - asuser=$2 - elif [[ "$1" != "" ]]; then - echo "Invalid argument: $1" >&2 - display_usage + if [ -z "$command" ]; then + echo "Command not specified" >&2 return 1 fi - userinfo=`userinfo $asuser` - otherhome=`echo "$userinfo" | grep ^dir | sed s/^dir//` - authfile=$otherhome/.Xauthority + cmdfullpath="`which -- $command`" + if [ -z "$cmdfullpath" ]; then + echo "Command not found: $command" >&2 + return 1 + fi + if [ -z "$asuser" ]; then + basename="`basename $cmdfullpath`" + asuser="$USER-$basename" + fi + + otherhome="`grep ^$asuser: /etc/passwd | head -n1 | cut -d: -f6`" + if [ -z "$otherhome" ]; then + echo "Could not find home of $asuser" >&2 + return 1 + fi + + authfile="$otherhome/.Xauthority" + + set -e touch $authfile xauth -f $authfile generate $DISPLAY . trusted chgrp $asuser $authfile chmod g+r $authfile cd $otherhome - exec doas -u $asuser $command + + # Closes IO handlers to avoid tty manipulation + # See: https://github.com/garotosopa/xodo/issues/1 + + XAUTHORITY="$authfile" exec perl -e " + use strict; + use warnings; + use POSIX qw(setsid uname); + my (\$sysname) = uname(); + close STDIN; close STDOUT; close STDERR; + fork and exit; + setsid; + if (\$sysname eq \"OpenBSD\") { + exec 'doas', '-u', \$ARGV[0], \$ARGV[1], @ARGV[2 .. @ARGV-1]; + } else { + exec 'sudo', '-u', \$ARGV[0], \$ARGV[1], (defined \$ARGV[2] ? @ARGV[2 .. @ARGV-1] : ()); + } + " -- "$asuser" "$cmdfullpath" "$@" } setup() { - if [[ "$1" == "" ]]; then + if [ -z "$1" ]; then echo "Command not specified" >&2 display_usage >&2 return 1 fi - command=`which -- $1` - basename=`basename $command` + command="`which -- $1`" + if [ -z "$command" ]; then + echo "Command not found: $command" >&2 + return 1 + fi + + basename="`basename $command`" + shift - while [[ "$1" != "" ]]; do - if [[ "$1" == "--as" ]]; then - if [[ "$2" == "" ]]; then + while [ -n "$1" ]; do + if [ "$1" = "--as" ]; then + if [ -z "$2" ]; then echo "--as user not specified" >&2 display_usage >&2 return 1 - elif [[ "$asuser" != "" ]]; then + elif [ -n "$asuser" ]; then echo "--as user specified twice" >&2 display_usage >&2 return 1 fi - asuser=$2 + asuser="$2" shift shift - elif [[ "$1" == "--for" ]]; then - if [[ "$2" == "" ]]; then + elif [ "$1" = "--for" ]; then + if [ -z "$2" ]; then echo "--for user not specified" >&2 display_usage >&2 return 1 - elif [[ "$foruser" != "" ]]; then + elif [ -n "$foruser" ]; then echo "--for user specified twice" >&2 display_usage >&2 return 1 fi - foruser=$2 + foruser="$2" shift shift else @@ -99,18 +150,87 @@ setup() { fi done - asuser=${asuser-$USER-$basename} - foruser=${foruser-$USER} + foruser="${foruser-$USER}" + asuser="${asuser-$foruser-$basename}" - echo "Setup $command as $asuser for $foruser" >&2 - echo "Not implemented yet" >&2 - return 1 + case "`uname`" in + Linux) + setup_function=setup_linux + priv_file=/etc/sudoers.d/xodo + ;; + OpenBSD) + setup_function=setup_openbsd + priv_file=/etc/doas.conf + ;; + *) + echo "Unsupported platform: `uname`" >&2 + return 1 + ;; + esac + + echo "The following steps will be executed:" + echo " - add user $asuser if it doesn't exist;" + echo " - make $asuser's home readable and writable by its group;" + echo " - add group $asuser to user $foruser;" + echo " - add an entry to $priv_file" + echo " allowing existing user $foruser" + echo " to execute $command" + echo " as new user $asuser with no password." + + echo -n "Proceed? [y/n] " + read proceed + if [ "$proceed" != "y" ] && [ "$proceed" != "Y" ]; then + echo "Aborted." + return 1 + fi + + set -e + + $setup_function "$command" "$asuser" "$foruser" + + echo "Done." + echo "If user $foruser is logged in, it must log out and in again before using xodo as $asuser, so that it gets added to the new group." } +setup_linux() { + command="$1" + asuser="$2" + foruser="$3" + + if [ -z "`grep "^$asuser:" /etc/passwd`" ]; then + useradd --create-home --skel /dev/null --user-group --key UMASK=002 "$asuser" + fi + + usermod -aG "$asuser" "$foruser" + echo "$foruser ALL = ($asuser) NOPASSWD: $command" >> /etc/sudoers.d/xodo +} + +setup_openbsd() { + command="$1" + asuser="$2" + foruser="$3" + + if [ -z "`grep "^$asuser:" /etc/passwd`" ]; then + useradd -m -k "" "$asuser" + fi + + usermod -G "$asuser" "$foruser" + + otherhome="`grep "^$asuser:" /etc/passwd | head -n1 | cut -d: -f6`" + if [ -z "$otherhome" ]; then + echo "Could not find home of $asuser" >&2 + return 1 + fi + + chmod g+rwX "$otherhome" + + echo "\npermit nopass setenv { DISPLAY HOME=$otherhome USER=$asuser } $foruser as $asuser cmd $command" >> /etc/doas.conf +} + display_usage() { - echo "usage: xodo [--as ]" + echo "usage: xodo [--as ] [--] [args...]" echo " xodo --setup [--as ] [--for ]" echo " xodo --help" } -main $@ +main "$@"