google / xsecurelock

X11 screen lock utility with security in mind
Apache License 2.0
863 stars 65 forks source link

About XSecureLock

XSecureLock is an X11 screen lock utility designed with the primary goal of security.

Screen lock utilities are widespread. However, in the past they often had security issues regarding authentication bypass (a crashing screen locker would unlock the screen), information disclosure (notifications may appear on top of the screen saver), or sometimes even worse.

In XSecureLock, security is achieved using a modular design to avoid the usual pitfalls of screen locking utility design on X11. Details are available in the Security Design section.

Requirements

The following packages need to be installed; their names depend on your Linux distribution of choice, but will be similar:

Installation

NOTE: In these instructions, please replace SERVICE-NAME by the name of an appropriate and existing file in /etc/pam.d. If xscreensaver is installed, xscreensaver should always be a good choice; otherwise, on Debian and Ubuntu, common-auth would work. This will be used as default and can be overridden with XSECURELOCK_PAM_SERVICE.

Configuring a broken or missing SERVICE-NAME will render unlocking the screen impossible! If this should happen to you, switch to another terminal (Ctrl-Alt-F1), log in there, and run: killall xsecurelock to force unlocking of the screen.

git clone https://github.com/google/xsecurelock.git
cd xsecurelock
sh autogen.sh
./configure --with-pam-service-name=SERVICE-NAME
make
sudo make install

Special notes for FreeBSD and NetBSD

First of all, on BSD systems, /usr/local is owned by the ports system, so unless you are creating a port, it is recommended to install to a separate location by specifying something like --prefix=/opt/xsecurelock in the ./configure call. You can then run XSecureLock as /opt/xsecurelock/bin/xsecurelock.

Also, in order to authenticate with PAM on FreeBSD and NetBSD, you must be root so you can read the shadow password database. The authproto_pam binary can be made to acquire these required privileges like this:

chmod +s /opt/xsecurelock/libexec/xsecurelock/authproto_pam

Special notes for OpenBSD

First of all, on BSD systems, /usr/local is owned by the ports system, so unless you are creating a port, it is recommended to install to a separate location by specifying something like --prefix=/opt/xsecurelock in the ./configure call. You can then run XSecureLock as /opt/xsecurelock/bin/xsecurelock.

Also, in order to authenticate with PAM on OpenBSD, you must be in the auth group so you can run a setuid helper called login_passwd that can read the shadow password database. The authproto_pam binary can be made to acquire these required privileges like this:

chgrp auth /opt/xsecurelock/libexec/xsecurelock/authproto_pam
chmod g+s /opt/xsecurelock/libexec/xsecurelock/authproto_pam

Note that this adds substantially less attack surface than adding your own user to the auth group, as the login_passwd binary can try out passwords of any user, while authproto_pam is restricted to trying your own user.

Setup

Pick one of the authentication modules and one of the screen saver modules.

Tell your desktop environment to run XSecureLock by using a command line such as one of the following:

xsecurelock
env XSECURELOCK_SAVER=saver_xscreensaver xsecurelock
env XSECURELOCK_SAVER=saver_mplayer XSECURELOCK_DISCARD_FIRST_KEYPRESS=0 xsecurelock
env XSECURELOCK_FONT=`xlsfonts | grep '\<iso10646-1\>' | shuf | head -n 1` xsecurelock

Just kidding about the last one :)

IMPORTANT: Make sure your desktop environment does not launch any other locker, be it via autostart file or its own configuration, as multiple screen lockers may interfere with each other. You have been warned!

Authentication on resume from suspend/hibernate

To have the authentication process start up without a keypress when the system exits suspend/hibernate, arrange for the system to send the SIGUSR2 signal to the XSecureLock process.

For example, you can copy the following script to the file /usr/lib/systemd/system-sleep/xsecurelock:

#!/bin/bash
if [[ "$1" = "post" ]] ; then
  pkill -x -USR2 xsecurelock
fi
exit 0

Don't forget to mark the script executable.

Automatic Locking

To automatically lock the screen after some time of inactivity, use xss-lock as follows:

xset s 300 5
xss-lock -n /usr/lib/xsecurelock/dimmer -l -- xsecurelock

The option -l is critical as it makes sure not to allow machine suspend before the screen saver is active - otherwise previous screen content may show up for a short time after wakeup!

NOTE: When using xss-lock, it's recommended to not launch xsecurelock directly for manual locking, but to manually lock using xset s activate. This ensures that xss-lock knows about the locking state and won't try again, which would spam the X11 error log.

WARNING: Never rely on automatic locking for security, for the following reasons:

Automatic locking should merely be seen as a fallback for the case of the user forgetting to lock explicitly, and not as a security feature. If you really want to use this as a security feature, make sure to kill the session whenever attempts to lock fail (in which case xsecurelock will return a non-zero exit status).

Alternatives

xautolock

xautolock can be used instead of xss-lock as long as you do not care for suspend events (like on laptops):

xautolock -time 10 -notify 5 -notifier '/usr/lib/xsecurelock/until_nonidle /usr/lib/xsecurelock/dimmer' -locker xsecurelock

Possible other tools

Ideally, an environment integrating xsecurelock should provide the following facilities:

  1. Wait for one of the following events:
    1. When idle for a sufficient amount of time:
      1. Run dimmer.
      2. When no longer idle while dimmed, kill dimmer and go back to the start.
      3. When dimmer exits, run xsecurelock and wait for it.
    2. When locking was requested, run xsecurelock and wait for it.
    3. When suspending, run xsecurelock while passing along XSS_SLEEP_LOCK_FD and wait for it.
  2. Repeat.

This is, of course precisely what xss-lock does, and - apart from the suspend handling - what xautolock does.

As an alternative, we also support this way of integrating:

  1. Wait for one of the following events:
    1. When idle for a sufficient amount of time:
      1. Run until_nonidle dimmer || exec xsecurelock and wait for it.
      2. Reset your idle timer (optional when your idle timer is either the X11 Screen Saver extension's idle timer or the X Synchronization extension's "IDLETIME" timer, as this command can never exit without those being reset).
    2. When locking was requested, run xsecurelock and wait for it.
    3. When suspending, run xsecurelock while passing along XSS_SLEEP_LOCK_FD and wait for it.
  2. Repeat.

NOTE: When using until_nonidle with other dimming tools than the included dimmer, please set XSECURELOCK_DIM_TIME_MS and XSECURELOCK_WAIT_TIME_MS to match the time your dimming tool takes for dimming, and how long you want to wait in dimmed state before locking.

Options

Options to XSecureLock can be passed by environment variables:

Additionally, command line arguments following a "--" argument will be executed via execvp once locking is successful; this can be used to notify a calling process of successful locking.

Authentication Modules

The following authentication modules are included:

Writing Your Own Module

The authentication module is a separate executable, whose name must start with auth_ and be installed together with the included auth_ modules (default location: /usr/local/libexec/xsecurelock/helpers).

Authentication Protocol Modules

The following authentication protocol ("authproto") modules are included:

Writing Your Own Module

The authentication protocol module is a separate executable, whose name must start with authproto_ and be installed together with the included authproto_ modules (default location: /usr/local/libexec/xsecurelock/helpers).

Screen Saver Modules

The following screen saver modules are included:

Writing Your Own Module

The screen saver module is a separate executable, whose name must start with saver_ and be installed together with the included auth_ modules (default location: /usr/local/libexec/xsecurelock/helpers).

Security Design

In order to achieve maximum possible security against screen lock bypass exploits, the following measures are taken:

Known Security Issues

Most these issues are inherent with X11 and can only really be fixed by migrating to an alternative such as Wayland; some of the issues (in particular the gamepad input issue) will probably persist even with Wayland.

Forcing Grabs

As a workaround to the issue of another window already holding a grab, we offer an XSECURELOCK_FORCE_GRAB option.

This adds a last measure attempt to force grabbing by iterating through all subwindows of the root window, unmapping them (which closes down their grabs), then taking the grab and mapping them again.

This has the following known issues:

Known Compatibility Issues

License

The code is released under the Apache 2.0 license. See the LICENSE file for more details.

This project is not an official Google project. It is not supported by Google and Google specifically disclaims all warranties as to its quality, merchantability, or fitness for a particular purpose.