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
luchonacho
  • 793
  • 2
  • 11
  • 28
user1876484
  • 315
  • 3
  • 12

3 Answers3

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.

mikem
  • 806
  • 3
  • 8
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.

telcoM
  • 87,318
  • 3
  • 112
  • 232
  • Thank you! For some reason [gksu](https://packages.debian.org/stretch/gksu) is no longer available in Debian 10. Do you know why? Is there any other alternative for Gnome on Debian10? – user1876484 Sep 17 '20 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? – user1876484 Sep 17 '20 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! – user1876484 Sep 20 '20 at 19:15
  • FYI: Wayland used by default in Debian 10 Gnome. – user1876484 Sep 20 '20 at 19:18
  • I have updated my question to include the `env` output. Maybe this will help. – user1876484 Sep 24 '20 at 07:42
  • It did work with "Gnome on Xorg"!!! Thank you! What didn't work was the access to the microphone and the webcam. How can it be granted to the `daddy` user? – user1876484 Jan 01 '21 at 09:55
  • You might want to add the `daddy` user to groups `audio`, `video` and/or `plugdev` - those will grant the group members access to audio devices, video devices and hot-plugged USB (and other) devices respectively, even when not logged in locally. (Normally a locally logged-in user gets permission to use them for the time of the session only. Remote users won't get that permission.) That is probably the simplest way to solve this part of the problem. – telcoM Jan 01 '21 at 12:30
  • Thank you! This indeed solved the issue with microphone/webcam. The last thing that left is [blocking zoom from launching browser](https://unix.stackexchange.com/q/627071/44880). – user1876484 Jan 12 '21 at 13:17
  • I now try to use the same sudo way to provide `trans` (translate-shell) to `kiddy` (which is actually a CLI program, no X). Command within bash is `sudo -u guest trans en:he -no-bidi -speak -player mpg123 $1`. The translation works fine, but playing audio of pronunciation via mpg123 player doesn't. I get "Voice output isn't available for English". As `daddy` I run that same program and audio works fine. I added `daddy` user to `audio`, `video`, `plugdev` and some other groups... What do I miss? Thank you! – user1876484 Aug 20 '22 at 21:17
  • I also added passwordles `mpg123` for `kiddy` but it didn't help... I suppose there is an issue in this [line](https://github.com/soimort/translate-shell/blob/30384b82b3f039be23c8b6d121cf21375655d36d/include/Translate.awk#L254). – user1876484 Aug 20 '22 at 21:47
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.

intgr
  • 227
  • 2
  • 7