Saturday, February 25, 2017

Lock remote deskop over ssh

I had a seemingly simple problem, connect over SSH to remote computer and lock the screen. Simple Google search for "gnome lock screen" yielded a plenty of results all of which revolving about using command gnome-screensaver-command -l.  First of, the package gnome-screensaver isn't installed by default on Fedora, meaning it isn't used there. Then, after installing it I got the following error message:
** Message: Failed to get session bus: Error spawning command line 'dbus-launch --autolaunch=062fabbac04041679f56c8db8593c352 --binary-syntax --close-stderr': Child process exited with code 1
Ok, turns out that session DBus is inaccessible and that gnome-screensaver-command just sends a message over DBus. Using d-feet it was easy to find out object, interface and method to use to lock the screen, but how to access DBus was a bit harder. The easy part was to find out that the key is in environment variable DBUS_SESSION_BUS_ADDRESS which has to point to a DBus daemon socket. But harder was to find where this socket is by looking into usual places on the file system. Finally, turned out that the easiest was to look at the environment of an existing process and get value from there, i.e.:
$ cat /proc/`pidof gnome-shell`/environ | \
              tr '\0' '\n' | grep DBUS_SESSION_BUS_ADDRESS
DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-dl1GC6PYCt,guid=33abd4a9e6bb3dee9262121d5819bdf1
tr command is necessary because entries in the environment are separated by NULL character (i.e. they are strings in C), so we are changing them into new line. Finally, grep just takes out the entry we are interested in. BTW, sorry for the useless cat use, but it is leftover as I constructed the command. :)

When you have properly set environment variable to access DBus, it is easy to invoke method Lock() that locks the screen, i.e.:
dbus-send --print-reply --session \
          --type=method_call --reply-timeout=3000 \
          --dest='org.gnome.ScreenSaver' \
          /org/gnome/ScreenSaver \
          org.gnome.ScreenSaver.Lock
and that will lock the screen. What's left to do is just to glue everything into a script:
#!/bin/bash
PID=`pidof gnome-shell`
DBUS_SESSION_BUS_ADDRESS=$(tr '\0' '\n' < /proc/${PID}/environ | grep "DBUS_SESSION_BUS_ADDRESS" | cut -d "=" -f 2-) \
dbus-send --print-reply --session --type=method_call --reply-timeout=3000 --dest='org.gnome.ScreenSaver' /org/gnome/ScreenSaver org.gnome.ScreenSaver.Lock
Just copy that into a file, make it executable and try it. It should work every time. :)

No comments:

About Me

scientist, consultant, security specialist, networking guy, system administrator, philosopher ;)