Implement automatic unlocking though a systemd service
- Dominant language
- Go
- Stars
- 1k
- Forks
- 111
- Avg merge
- 2d 19h
- Merged PRs (30d)
- 3
Description
Right now, both automatic unlocking of directories and rewrapping of the user's login protector are done though the [PAM module](https://wiki.archlinux.org/index.php/PAM) `pam_fscrypt.so`. Specifically the following [PAM _types_](http://www.linux-pam.org/Linux-PAM-html/sag-configuration-file.html) do the following things:
- `session`
- tracks of the number of open sessions for that user
- automatically unlocks user encrypted directories
- automatically locks user encrypted directories (on the last logout)
- `auth` forwards the `AUTHTOK` object as part of the PAM data (if necessary)
- `password` rewarps the login protector (if necessary)
The basic plan is to keep the `auth` and `password` types in the pam modules (with modifications), while doing all the stuff we do in `session` in `fscrypt@.service`.
@ebiggers, @tyhicks: I'd love your feedback on the basic idea (and if it would improve things).
@fancytenseletters, @Minecrell, @sebadoom: This should (hopefully) fix some of the bugs you've reported.
## Justification
Bugs #66, #77, #93, #196 (#57 and #34 are also related) seem to be bugs around what order certain operations run in. Ideally, we want all of our setup to happen _before_ any user task starts. Similarly, all our teardown should occur _after_ all user tasks complete. To do this well, we need to integrate with the OS's init service. This is because the init service:
- knows when the first session of a user begins
- knows when the last session ends
- allows us to run fscrypt commands at specific points to prevent things from breaking
eCryptfs has been running into issues with systemd and automatic mounting via PAM modules. See: [Arch Bug](https://bugs.archlinux.org/task/55943), [Debian Bug](https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=765854), [Ubuntu Bug](https://bugs.launchpad.net/ecryptfs/+bug/1734290), [systemd Bug](https://bugs.freedesktop.org/show_bug.cgi?id=72759). `pam_mount.so`, which can do similar stuff for device encryption, has [also](https://wiki.archlinux.org/index.php/Talk:Pam_mount#automatic_unmounting_and_systemd) had [issues](https://bugzilla.redhat.com/show_bug.cgi?id=1086822).
## Details
This change would require changing or adding three things.
- Remove functionality from `pam_fscrypt.so`
- Remove `session` hooks, keyring linking code, caches code, etc..
- For `auth`, if the user has a login protector, use the passphrase to unlock the login protector, and store it in the root user keyring (with type `user`). We could also prompt the user here to enter their old login password if things have gotten out of sync.
- For `password`, if we find a login protector, use the passphrase hashes of `AUTHTOK` and `OLDAUTHTOK` to update the login protector to update the login protector
- Add new commands to fscrypt that must be run as root:
- `fscrypt system start --unlock=[none|login] [--link-to-root]`
- `--unlock` adds policies to the user's keyring
- `login` gets the login protector key from the root user keyring and uses it to unlock the corresponding policies
- `--link-root-keyring` makes sure the user keyring is linked into the root user keyring
- `fscrypt system stop --lock=[none|login|all] [--drop-caches] [--unlink-from-root]`
- `--lock` removes policies from the user's keyring:
- `login` removes just those protected by the login passphrase
- `all` removes all policies in the user's keyring
- `--drop-caches` calls [`DropFilesystemCache`](https://github.com/google/fscrypt/blob/7442ff1144c91ba9810b66fa843baf8c1953107f/security/cache.go#L29-L49) after all keys are removed
- `--unlink-from-root` removes the user keyring from the root user keyring
- Add a [systemd service](https://www.freedesktop.org/software/systemd/man/systemd.service.html) to trigger the appropriate commands. For example:
```ini
[Unit]
Description=Unlock fscrypt directories with login credentials
Before=user@%i.service
[Service]
Type=oneshot
RemainAfterExit=yes
Slice=user-%i.slice
RemainAfterExit=yes
StandardOutput=jouranal
StandardError=syslog
SyslogIdentifier=fscrypt
ExecStart=/usr/bin/env fscrypt system start %i --unlock=login --link-to-root
ExecStop=/usr/bin/env fscrypt system stop %i --lock=all --drop-caches --unlink-from-root
[Install]
WantedBy=user@%i.service
```
## Benefits
- _Way_ less PAM code to maintain
- No more tracking the number of open user sessions
- No locking/unlocking of directories
- No keyrings or caching related code
- Could replace how we currently [check the user password](https://github.com/google/fscrypt/blob/4879df9a6063886865b94c270660838060acbc20/pam/login.go#L82-L113) eliminating our [custom conversation function](https://github.com/google/fscrypt/blob/7442ff1144c91ba9810b66fa843baf8c1953107f/pam/pam.c#L31-L80)
- Keeps the Pluggable _Authentication_ Module focused on authentication related stuff.
- More stability
- Should load before a lot of login jobs, preventing bugs with SDDM/GDM
- Better setup to handle user session failures (right now we just never trigger cleanup)
- Will eliminate issues with user processes keeping files open ([mentioned here](https://github.com/google/fscrypt/issues/66#issuecomment-333694848)).
- Allows for more complex configuration than the PAM config files
- Allows behavior in #60 to be easily configurable
- No ties to systemd in particular. Any init service can call `fscrypt system [start|stop] `.
Contributor guide
Assessment
This issue has not been assessed yet.