Ubuntu – Switching between two opened X sessions without reauthenticating

lightdmswitch-userxorg

Need: quick switch between pairs of users.

On a system there is a pair of user accounts that are somehow equivalent.

More concretely, for a given pair:

  • Both account are regular Unix accounts, they just happened to be used by the same physical user (person).
  • The same person has nearly always two graphical X sessions opened, one for each user account, but only needs to see one at a time on the screen.
  • These are completely separate accounts with different mail configurations, browser histories, files, with different levels of security.
  • Nothing is shared between the accounts, there would be no point in mixing those accounts on same X session (even a copy-paste between those would be useless).
  • Yet the user needs to switch between them many times a day.
  • It is easy to put a button that calls dm-tool switch-to-user but practically the user then has to re-authenticate on every switch and that is a productivity loss.

The need is to allow quick switch between the two graphical X sessions (e.g. at the click on a button on a panel) without having to reauthenticate.

System info and security implication (relaxing local security should be okay)

  • System is Xubuntu 16.04 Xenial.
  • X seats, login, locking, switching is done by lightdm out-of-the-box.

I am aware that relaxing security between pair of users while keeping other operations secure is more complicated than the usual lock-and-switch approach. Fortunately, in our case it's okay if some local security is lost since the machine is in controlled premises. For example, if a solution to the need causes some scenario that would normally automatically lock session (like suspend+resume) to no longer lock, for this pair of users, or even every user on the system, it may be acceptable.

Still, it's good if the user can manually lock the session.

Also, remote security must be preserved (for example SSH access to those accounts must not be affected by a solution to this problem).

Search before you post

Approach 1: use lightdm tools but adjust somehow

Basically, use dm-tool switch-to-user *username* and arrange for the user's session to not get locked.

Worked in 12.04

In Ubuntu 12.04 we disabled light-locker to prevent session locking, plus set an icon on each user's desktop that ran this command:

dbus-send --system --type=method_call --print-reply --dest=org.freedesktop.DisplayManager $XDG_SEAT_PATH org.freedesktop.DisplayManager.Seat.SwitchToUser string:$CALLEDUSERNAME string:somesessionname

This worked: session switched to the user mentioned as $CALLEDUSERNAME.

Fails in 16.04

This is unsatisfactory on 16.04: it switches to a greeter with $CALLEDUSERNAME pre-selected but authentication is still needed. So, basically the result is the same as dm-tool switch-to-user *username*. I haven't checked fully but probably it's just going exactly the same code paths as what dm-tool causes.

More search

Looked for hints in Bug #1205384 “Lock can be circumvented by switching to console” : Bugs : lxsession package : Ubuntu, nothing concretely working.

I've looked at dm-tool source code at http://archive.ubuntu.com/ubuntu/pool/main/l/lightdm/lightdm_1.18.1-0ubuntu1.tar.gz (from link on Ubuntu – Details of package lightdm in xenial).

Principle looks like this:

  • dm-tool executable calls dbus to send message to lightdm.
  • lightdm receives dbus event in handle_seat_call(), calls seat_switch_to_user()
  • seat_switch_to_user() calls g_signal_connect (session, SESSION_SIGNAL_AUTHENTICATION_COMPLETE, G_CALLBACK (switch_authentication_complete_cb), seat); to register callback switch_authentication_complete_cb().
  • seat_switch_to_user() then calls session_start() which apparently creates a whole new X session to get authentication (not sure about the details, perhaps runs session_child_run() which calls PAM)
  • switch_authentication_complete_cb() then switches to existing session or create new one

Next step

Can we somehow instruct PAM to just allow without prompting in this case, but without that change disturbing any other case? Ideally PAM behavior would change only in the switch-user case, not in the login case or the unlock case. Maybe the extra X session would still be started but not waiting for the user to type a password.

Approach 2: just figure out the VT number and use chvt

  • Get at any time which VT corresponds to target user (perhaps because at login time, a script would read XDG_SEAT_PATH to get seat number, join with Xorg command line which tells the corresponding vt number and write the result into a conventional place).
  • When needing to switch to user, get the vt number and use chvt. Probably some sudo config will be needed.

  • Advantage: simpler, no mess with lightdm, PAM or whatever, not even an explicit dependency on lightdm so might work elsewhere.

  • Drawback: hackish way to figure out the join between user and VT number?

Conclusion, retell question

  • Any comment about the first approach (via dm-tool, PAM adjust)?
  • Any comment about the second approach (via chvt)?

Thank you for your attention.

Best Answer

Summary: done, usable, current solution is acceptable only in a cooperative multi-user environment, can be improved.

I wrote a usable-proof-of-concept patch to lightdm that does the job.

It does what we need here!

See below for installation instructions.

Prerequisites

  • A system with at least two user accounts and users willing to allow quick switch between graphical sessions without retyping passwords.
  • Each user can use any desktop environment that fully uses lightdm, including using light-locker for session locking. Unity and XFCE should work.

Tested with XFCE.

How to use, how to see the changes

Try this before performing the changes:

  • have user A open a graphical session
  • have user B open another graphical session

Now from any of the two session you can do :

    dm-tool switch-to-user userA

or

    dm-tool switch-to-user userB

Effect of the changes

Without the change you will see a login prompt requiring to type a password.

With the change you will see an immediate switch without login prompt.

Here the switch is really quick. Much quicker than in Ubuntu 12.04 and even without flickering in some cases.

Practical use

For maximum benefit, I recommend to create a launcher icon somewhere in a dock/panel/wharf (whatever it is called in your particular desktop environment) that when clicked runs:

    dm-tool switch-to-user name-of-other-user

SECURITY WARNING

Applying the commands below replaces system's lightdm packages with modified versions that allow switching between any two users currently being logged in a graphical session. This weakens system security, for example user A logs in graphically, locks session, walks away, user B logs in. User B can unlock user A session and switch to it any time it is opened. And the other way round (swap A and B).

The changes cannot be applied without administrator access (sudo is assumed, especially for package install).

It works fine for us, but still, note that lightdm is an important package and this might break it or introduce other subtle bugs. Breaking it will break ability to use graphical login sessions for all users. You are fully responsible for the use of the commands below. You have been warned.

Permanence warning

Changes are near-permanent. They stay after rebooting. To revert them, install (using aptitude, synaptic or whatever) the regular lightdm* packages which will replace the changed ones.

Notice that any time Ubuntu updates lightdm packages, and the updates are installed, they will revert the changes. Administrator can apply them again.

Possible refinement (restore security)

This proof-of-concept could be refined by a clever use of e.g. Unix groups. lightdm would only allow the switch if current and target users are listed in any group with a conventional filename, like lightdm-quickswitch-anystringfoo. Such a change (possible along with others) could be eventually merged into some official solution.

Commands

I suggest to login on a text console (press Ctrl-Alt-F1 and login) to do the steps below. This allows to restart lightdm without losing the current shell.

Copy-paste the commands below in a bash shell and it will adjust lightdm to perform the changes.

(
set -euxv

echo Making sure system has necessary packages.

echo Installing packages will be done only once but might be long as it may fetch around 40Mbytes of data from the Internet.
sudo apt-get --assume-yes install devscripts

echo Enabling source packages in apt.
sudo sed -i '/^#\sdeb-src /s/^# *//' "/etc/apt/sources.list"
sudo apt-get update
sudo apt-get --assume-yes --no-install-recommends build-dep lightdm

THETEMPDIR=$( mktemp -d )
cd $THETEMPDIR

echo Getting package source

apt-get source lightdm
cd */

pwd

if [ -d .pc ]
then
quilt push -a || echo "Quilt returned an error code, we ignore it because we saw it was sometimes irrelevant."
quilt new allow_switch_between_logged_users_without_authentication
quilt add src/seat.c
fi

patch -p0 <<EOF
--- src/seat.c  2016-07-29 05:19:45.000000000 +0200
+++ src/seat.c  2016-08-15 19:37:11.693364683 +0200
@@ -1578,6 +1578,20 @@

     l_debug (seat, "Switching to user %s", username);

+    if (session)
+    {
+   l_debug (seat, "WIP quick switch: found inactive existing user session, switching to it: %s. For details, see https://askubuntu.com/questions/811953/switching-between-two-opened-x-sessions-without-reauthenticating", username);
+
+   session_unlock (session);
+   seat_set_active_session (seat, session);
+
+   l_debug (seat, "WIP quick switch to user complete: %s.  For details, see https://askubuntu.com/questions/811953/switching-between-two-opened-x-sessions-without-reauthenticating", username);
+   return TRUE;
+    }
+
+    l_debug (seat, "WIP quick switch: no session for user, switching to greeter: %s. For details, see https://askubuntu.com/questions/811953/switching-between-two-opened-x-sessions-without-reauthenticating", username);
+
+
     /* Attempt to authenticate them */
     session = create_user_session (seat, username, FALSE);
     g_signal_connect (session, SESSION_SIGNAL_AUTHENTICATION_COMPLETE, G_CALLBACK (switch_authentication_complete_cb), seat);
EOF

if [ -d .pc ]
then
quilt refresh
ls -al debian/patches/allow_switch_between_logged_users_without_authentication
cat debian/patches/allow_switch_between_logged_users_without_authentication
fi

echo Building modified packages.

dch -lquickswitch "Allow dm-tool switch-to-user username to switch without authentication if user session is already opened.  WARNING: this negates local security. For details, see https://askubuntu.com/questions/811953/switching-between-two-opened-x-sessions-without-reauthenticating"
head debian/changelog
time dpkg-buildpackage -rfakeroot -uc -b

echo Installing modified packages.

cd ..
PACKAGESTOINSTALL=$( for DEBNAME in *.deb ; do PACKAGENAME="$( echo "$DEBNAME" | cut -f 1 -d _ )" ; if dpkg -l $PACKAGENAME | grep -q ^ii ; then echo $DEBNAME ; fi ; done ) ; sudo dpkg --install ${PACKAGESTOINSTALL}
dpkg -l '*lightdm*'
)

Notice that the command below will close immediately all graphical sessions without a chance to save data, so all users should close applications properly and save needed data first.

If packages did install well, the change can be activated immediately with :

    sudo service lightdm restart

or by rebooting.

Feedback

Does it work for you? Can you think of a variant? Feedback welcome.