3

I block all Internet traffic for my kids' Linux accounts using iptables. Sometimes I want to allow them to use one program or another. In such cases I enable them to run that programs as another(unlimited) user via sudoers. This time I tried to enable them to use zoom, as follows:

kiddy ALL= (daddy) NOPASSWD: /usr/bin/zoom

However running sudo -u daddy /usr/bin/zoom produces no output (also no errors), but zoom doesn't start. Running zoom from command line launches GUI client, but it obviously is unable to connect (which is expected). What's wrong here?

If I try to do the same with gnome-terminal instead of zoom by adding to the visudo following line: kiddy ALL= (daddy) NOPASSWD: /usr/bin/gnome-terminal and then running: sudo -u daddy /usr/bin/gnome-terminal I get this error:

No protocol specified
Unable to init server: Could not connect: Connection refused
# Failed to parse arguments: Cannot open display:

I face all the above once logged in into Gnome as user kiddy, however if I log into Gnome as daddy and then in terminal run su kiddy followed by sudo -u daddy gnome-terminal or sudo -u daddy zoom - everything works.

Should I add some additional variables to the sudoers file? If yes - how do I determine which variables are needed and what are their values?

Here is the output of env for a typical Debian 10 user (named guest in this case):

SHELL=/bin/bash
SESSION_MANAGER=local/debox:@/tmp/.ICE-unix/2055,unix/debox:/tmp/.ICE-unix/2055
QT_ACCESSIBILITY=1
COLORTERM=truecolor
XDG_MENU_PREFIX=gnome-
GNOME_DESKTOP_SESSION_ID=this-is-deprecated
LANGUAGE=en_IL:en
SSH_AUTH_SOCK=/run/user/1001/keyring/ssh
DESKTOP_SESSION=gnome
GTK_MODULES=gail:atk-bridge
XDG_SEAT=seat0
PWD=/home/guest
XDG_SESSION_DESKTOP=gnome
LOGNAME=guest
XDG_SESSION_TYPE=wayland
GJS_DEBUG_TOPICS=JS ERROR;JS LOG
GDM_LANG=en_IL
HOME=/home/guest
USERNAME=guest
LANG=en_IL
LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:
XDG_CURRENT_DESKTOP=GNOME
VTE_VERSION=5402
WAYLAND_DISPLAY=wayland-0
GNOME_TERMINAL_SCREEN=/org/gnome/Terminal/screen/a2088f04_0308_4c60_9882_a758f7d883b8
GJS_DEBUG_OUTPUT=stderr
XDG_SESSION_CLASS=user
TERM=xterm-256color
USER=guest
GNOME_TERMINAL_SERVICE=:1.59
DISPLAY=:0
SHLVL=1
XDG_VTNR=2
XDG_SESSION_ID=4
XDG_RUNTIME_DIR=/run/user/1001
PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
GDMSESSION=gnome
DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1001/bus
_=/usr/bin/env
2
  • 1
    you're missing the username for the -u option. Sep 9, 2020 at 21:31
  • @glennjackman: thanks, fixed. That is not the issue here though. Sep 10, 2020 at 9:30

3 Answers 3

2

Possibly it doesn't know what display to use. When you start it with sudo, it's creating a new shell. If that shell is unaware of the display, it won't be able to open a window.

To test this, try to sudo an xterm (/usr/bin/xterm) in the same way. Does it open? If not, we may be on to something here.

It may be as simple as adding VAR=DISPLAY to the sudo line. See sudo man page for specific details.

2
  • Also XAUTH and a couple of other variables that carry authentication/authorisation state Sep 9, 2020 at 20:27
  • @roaima: I did some home work and updated my question accordingly. Does it help? Sep 16, 2020 at 9:13
1

If the initial GUI session is running as user kiddy, then the session key file (either at ~/.Xauthority or in a custom location pointed to by the XAUTHORITY environment variable) is owned by that user and not readable by anyone else by default.

If you're sudoing to root, this is not a problem as root can normally read everything (unless e.g. the user's home directory is on a NFS share that is exported with root_squash option set). You can just export XAUTHORITY=/home/$SUDO_USER/.Xauthority and make sure the DISPLAY variable is preserved from the original session.

But when you use sudo -u daddy to switch onto another non-root account and want to use GUI programs, you'll need to either use GUI versions of the user switching tool (e.g. gksu for Gnome or kdesudo for KDE) which can handle this automatically, or give the second user account access to the session key (or a copy of it) yourself.

The GUI user switching tools would be the recommended way, as they can appropriately handle additional things beyond the basic GUI session access, like the environment variables required for the accessibility features and/or more elaborate character input methods, like the ones required for Chinese/Japanese/Korean character input for example.

Some distributions may also have PAM modules or other pre-configuration to make this more automatic.

But if you need to do it manually, there are three things you must do to for a basic ability to run GUI programs as an user that did not perform the GUI login:

  • the destination user must have an accessible copy of the X session key file (~/.Xauthority, or pointed to by the XAUTHORITY variable in the original session). If security is a concern, this file should be accessible only by the original and the destination user.
  • the destination user will probably need to have a XAUTHORITY variable pointing to the accessible copy of the X session key file (unless the copy is placed at ~/.Xauthority of the destination user)
  • the destination user must have the same DISPLAY variable value as the original session

Apparently gksu has been removed. To allow sudo preserve the necessary environment variables, you might write an /etc/sudoers.d/zoomforkiddy file with the following contents (it is recommended to use visudo -f /etc/sudoers.d/zoomforkiddy to create/edit it):

Defaults:kiddy env_keep += "DISPLAY XAUTHORITY"
kiddy ALL = (daddy) NOPASSWD: /usr/bin/zoom

This allows the necessary environment variables to pass through sudo, and grants kiddy passwordless access to /usr/bin/zoom only.

Then add daddy to kiddy's user group:

sudo usermod -a -G kiddy daddy

This will allow daddy to access kiddy's files if they have group access permissions set. So now kiddy will be able to copy his Xauthority file to some location that can be accessed by daddy and set permissions so that (only) daddy can access it.

Now create a script, e.g. /usr/local/bin/zoom_for_kiddy and set it executable (chmod a+rx /usr/local/bin/zoom_for_kiddy):

#!/bin/sh
if [ "$XAUTHORITY" = "" ]
then
    XAUTHORITY="$HOME/.Xauthority"
fi
if [ -f "$XAUTHORITY" ]
then
    cp "$XAUTHORITY" /tmp/zoom_for_kiddy_xauth
    trap "rm -f /tmp/zoom_for_kiddy_xauth" EXIT
    chmod 640 /tmp/zoom_for_kiddy_xauth

    export XAUTHORITY=/tmp/zoom_for_kiddy_xauth
    sudo -u daddy /usr/bin/zoom "$@"
else
    echo "ERROR: cannot find the Xauthority file" >&2
fi

This script will make a copy of kiddy's Xauthority file for daddy, set the permissions, set the XAUTHORITY environment variable to a value that's usable for daddy, and then start /usr/bin/zoom through sudo. When zoom exits, the copy of the Xauthority file will be automatically deleted as the shell executing the script exits.

Now you can adjust kiddy's desktop environment to use /usr/local/bin/zoom_for_kiddy instead of the real /usr/bin/zoom. Any command arguments will be passed through the script to the real zoom as-is.

10
  • Thank you! For some reason gksu is no longer available in Debian 10. Do you know why? Is there any other alternative for Gnome on Debian10? Sep 17, 2020 at 11:56
  • also - I, obviously, don't want to provide daddy's password to kiddy. So I must limit the (passwordless) usage of gksu to zoom only. How do I achieve this? Sep 17, 2020 at 12:16
  • Thank you very much for the detailed explanation. I've followed your instructions, but I face following issue - it seems like on Debian 10 Gnome there is no $HOME/.Xauthority - only $HOME/.ICEauthority... tried to replaced the former by the latter in the bash script, but it didn't help... running it produces no output and no zoom runs... Should there be additional changes? Maybe in the sudoers? Thank you very much! Sep 20, 2020 at 19:15
  • FYI: Wayland used by default in Debian 10 Gnome. Sep 20, 2020 at 19:18
  • I have updated my question to include the env output. Maybe this will help. Sep 24, 2020 at 7:42
0

I wrote ego (Alter Ego) for a similar use case. Using ego, you can launch programs under another local user. Besides X11 setup, it also handles Wayland and PulseAudio socket sharing: https://github.com/intgr/ego

So you would just run ego --sudo -u daddy app or ego -u daddy zoom (some applications have glitches with the --sudo mode).

If you run into problems, please open an issue on GitHub.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .