Giter Site home page Giter Site logo

pam_e4crypt's Introduction

pam_e4crypt

This is a PAM module for unlocking transparently encrypted directories on ext4.

Since version 4.1, the Linux kernel supports transparent encryption in ext4. The mechanism relies on the keyrings facility of the kernel.

This module will create keys for (de)ciphering files and file-names in encrypted directories during the authentication phase. During the session setup phase, those keys are added to the session keyring, giving the user (instant) access to directories for which she previously set a "policy" matching her passphrase (e.g. using e4crypt from the e2fsprogs).

Note that the only encryption mode currently supported is aes256-xts.

Google's fscrypt has the same purpose but is not restricted to ext4's transparent encryption feature and far better maintained. Thus, fscrypt is probably better suited for production machines.

Pitfalls

Users should be aware of the following when using (or thinking about using) this module:

  • Files and directories are usually cached by the kernel for performance reasons. When using ext4 transparent encryption, decrypted content ends up in those caches and may thus (still) be visible to users with sufficient access rights (e.g. root) during or even after a session (until the caches are cleared).
  • Obviously, this module will only unlock files and directories if it will be invoked, e.g. if PAM is used for login. Thus, background services can not access encrypted files directories if the files are not unlocked (that's the whole point of this module -- duh). TL;DR: don't complain about cronjobs failing while trying to access encrypted files.
  • Changing the password used for login does (currently) not change the encryption key of affected directories. Hence, those directories will not be unlocked after a password-change.

Using this module

This module should be invoked late during the authentication phase as well as early during the session phase, after an invocation of the pam_keyinit module. The module should be marked as required for the authentication phase and either required or optional for the session phase, e.g.:

auth ...
auth        required        pam_e4crypt.so

account ...
password ...

session     required        pam_keyinit.so
session     required        pam_e4crypt.so
session ...

During the authentication phase, keys are generated from the user password. Hence, the module should be invoked late, at a point where the password is available.

During the session phase, the generated keys are added to the session keyring. Obviously, the keyring has to be initialized. Hence, pam_keyinit or an equivalent module has to invoked prior to pam_e4crypt. Since other session modules may access encrypted directories, it is highly recommended to have pam_e4crypt invoked early.

As this module is considered experimental, users also may want to specify onerr=succeed. Furthermore, it has been reported that having the module required for the session phase may break some setups. Hence, new users are encouraged making the module optional for that phase, at least initially.

Salt

Users must provide a salt (up to 16 bytes) for generation of a key. If no salt is supplied, no key will be generated. By default, the (raw) salt is read from $HOME/.ext4_encryption_salt. You can initialize this file with the following commands:

head -c 16 /dev/urandom > ~/.ext4_encryption_salt

Alternatively, the module can be configured to read the salt from files in a dedicated directory using the saltpath parameter:

auth        required        pam_e4crypt.so  saltpath=/home/.e4crypt

The module will then read the salt from /home/.e4crypt/$USER

Note that the e4crypt will read salt from various places by default. When using the e4crypt add_key command, specify the intended user's salt via the -S option for compatibility with this module.

Keyring

By default, keys are added to the session keyring. Using the keyring argument in the PAM config, it is possible to specify an alternative keyring to which the keys should be added. Use like:

session     required        pam_e4crypt.so  keyring=<desc>

As <desc>, one may specify either a keyring's description or one of the "special values" understood by keyctl (1.5), e.g. @u for the user specific keyring.

Dependencies

At runtime, the module requires:

  • Linux-Kernel>=4.1
  • PAM
  • keyutils
  • OpenSSL (or some compatible replacement like libressl)
  • libuuid (util-linux)

At build time, the developer-packages for all the runtime-dependencies are required in addition to:

  • CMake>=3.5
  • A C-compiler (e.g. gcc or clang)

Installation

The module is built using CMake. Run

cmake <path-to-source>
make
make install

in the directory in which you indent to build the module. In-tree builds are supported (supply . as the source directory).

Additional cflags and ldflags can be supplied via the CMAKE_C_FLAGS and CMAKE_MODULE_LINKER_FLAGS when generating the build system, e.g.:

cmake -DCMAKE_C_FLAGS="-O2 -fstack-protector-strong" <path-to-source>

The module is automatically installed in a directory security which resides in the same folder as the PAM library. If those directories are symlinks on the target platform, the actual installation path may differ from the installation path originally used by PAM due to the default search order used by CMake.

Albeit the module should still be found by PAM, users may choose to specify the library base path used for installation manually by setting the CMAKE_INSTALL_LIBDIR variable.

For example, run

cmake -DCMAKE_INSTALL_LIBDIR=<lib-base-path> <path-to-source>

to prepare the module for installation to <lib-base-path>/security/.

About passwords, mounts and policies

"policies" are actually keys generated from a passphrase and a salt. This PAM module will generate keys from the user's passphrase and add them as policies, just like e4crypt add_key. If you view you session keyring, e.g. using keyctl show @s, those keys will be visible as "logon" keys with a descriptor prefixed with "ext4:". The hexadecimal string following the prefix is the actual policy descriptor which you can pass to e4crypt set_policy.

The correct process for encrypting a folder once logged in with pam_e4crypt is:

$ keyctl show
Session Keyring
 111111111 --alswrv      0     0  keyring: _ses
 222222222 ----s-rv      0     0   \_ user: invocation_id
 333333333 --als-rv   1000  1000   \_ logon: ext4:abcdef012345678
$ mkdir crypted
$ e4crypt set_policy abcdef012345678 crypted

Licensing

The module is currently licensed under the GPLv2. Have a look at the LICENSE file for more information. Also, you might want to consult a lawyer if you intend to ship this module together which a BSD-licensed version of PAM.

The license was chosen because some code was cargo-culted from the e2fsprogs, which was authored by Michael Halcrow and Ildar Muslukhov, copyrighted by Google and licensed under the GPLv2. Maybe, one day, if all the affected functions are rewritten to a degree where they are legally re-implementations, none of the eventual co-authors object and none of the dependencies switched to GPL-only, I'll re-release the thing under the LGPL or a BSD-license.

pam_e4crypt's People

Contributors

fbarthelery avatar flowdalic avatar jnvsor avatar neithernut avatar seebaclo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

pam_e4crypt's Issues

pam_e4crypt: Failed to retrieve key list!

I'm sorry to disturb you again but I can't get it working after installation and the Readme isn't very detailed.

I've set following in pam.d/system-auth:

auth      sufficient    pam_unix.so     try_first_pass nullok
auth      optional   pam_e4crypt.so
auth      optional  pam_permit.so
auth      required  pam_env.so

session    optional   pam_keyinit.so       force revoke debug
session    optional   pam_e4crypt.so
session   required  pam_limits.so
session   required  pam_unix.so
session   optional  pam_permit.so

And it doesn't add my ext4 keys after login. I have following error in syslog:
pam_e4crypt: Failed to retrieve key list!
what are the correct entries in pam.d?

Re-introduce support for EXT4_IOC_GET_ENCRYPTION_PWSALT and iterating over mtab

I am very curious why support for the EXT4_IOC_GET_ENCRYPTION_PWSALT ioctl() and the iteration routine over mtab was removed.

After reading some e2fsprogs and linux kernel source, it appears the idea of e4crypt is to store the salt in the superblock of the ext4 filesystem, in an effort to become more "user-friendly" (see tytso/e2fsprogs@41f2210). And this appears sensible to me. And while pam_e4crypt once had support for the EXT4_IOC_GET_ENCRYPTION_PWSALT ioctl() which returns the (per ext4 filesystem) salt, it was removed with #27. Furthermore, iterating over all filesystem entries in mtab was removed with #25.

I can not think of a good reason, especially since ext4 appears to be moving towards storing the salt in the filesystem superblock. And if pam_e4crypt would simply create a policiy (key+salt) for every ext4 filesystem in mtab, then the usage of pam_e4crypt would become much easier.

Slightly related side-node: pam_e4crypt's README currently stats that "Users must provide a salt (up to 16 bytes)". This is not entirely correct, e4crypt is able to handle salts of much larger sizes. Only the salt stored in the superblock and returned by the ioctl() is 16 bytes in size.

Would you accept patches that re-introduce EXT4_IOC_GET_ENCRYPTION_PWSALT and iterating over mtab?

PAM failed: Cannot make/remove an entry for the specified session

Some part of the PAM open-session step fails on my system if (and only if) I enable pam_e4crypt.
The weird part is that the error occurs before pam_e4crypt is executed.

Good session start
No session [...] pam_e4crypt.so was enabled.
journalctl:

Jan 08 21:44:54 hostname login[464]: pam_e4crypt: Generating key with salt length 34 from file '/.ext4-salts/samuel'
Jan 08 21:44:54 hostname login[464]: pam_unix(login:session): session opened for user samuel by LOGIN(uid=0)
Jan 08 21:44:54 hostname systemd[1]: Created slice User Slice of samuel.
Jan 08 21:44:54 hostname systemd[1]: Starting User Manager for UID 1000...
Jan 08 21:44:54 hostname systemd-logind[447]: New session c1 of user samuel.
Jan 08 21:44:54 hostname systemd[1]: Started Session c1 of user samuel.
Jan 08 21:44:54 hostname systemd[797]: pam_unix(systemd-user:session): session opened for user samuel by (uid=0)
Jan 08 21:44:54 hostname systemd[797]: Listening on GnuPG cryptographic agent and passphrase cache (access for web browsers).
Jan 08 21:44:54 hostname systemd[797]: Listening on GnuPG cryptographic agent and passphrase cache (restricted).
Jan 08 21:44:54 hostname login[464]: LOGIN ON tty1 BY samuel
Jan 08 21:44:54 hostname systemd[797]: Reached target Timers.
Jan 08 21:44:54 hostname systemd[797]: Listening on Sound System.
Jan 08 21:44:54 hostname systemd[797]: Listening on GnuPG cryptographic agent (ssh-agent emulation).
Jan 08 21:44:54 hostname systemd[797]: Reached target Paths.
Jan 08 21:44:54 hostname systemd[797]: Starting D-Bus User Message Bus Socket.
Jan 08 21:44:54 hostname systemd[797]: Listening on GnuPG cryptographic agent and passphrase cache.
Jan 08 21:44:54 hostname systemd[797]: Listening on GnuPG network certificate management daemon.
Jan 08 21:44:54 hostname systemd[797]: Listening on D-Bus User Message Bus Socket.
Jan 08 21:44:54 hostname systemd[797]: Reached target Sockets.
Jan 08 21:44:54 hostname systemd[797]: Reached target Basic System.
Jan 08 21:44:54 hostname systemd[797]: Reached target Default.
Jan 08 21:44:54 hostname systemd[797]: Startup finished in 23ms.
Jan 08 21:44:54 hostname systemd[1]: Started User Manager for UID 1000.

Bad session start
session required pam_e4crypt.so debug was appended to the end of /etc/pam.d/system-login (I know the debug option has no effect).
journalctl:

Jan 08 21:54:31 hostname login[458]: pam_e4crypt: Generating key with salt length 34 from file '/.ext4-salts/samuel'
Jan 08 21:54:31 hostname login[458]: pam_unix(login:session): session opened for user samuel by LOGIN(uid=0)
Jan 08 21:54:31 hostname systemd[1]: Created slice User Slice of samuel.
Jan 08 21:54:31 hostname systemd[1]: Starting User Manager for UID 1000...
Jan 08 21:54:31 hostname systemd-logind[440]: New session c1 of user samuel.
Jan 08 21:54:31 hostname systemd[1]: Started Session c1 of user samuel.
Jan 08 21:54:31 hostname systemd[801]: pam_unix(systemd-user:session): session opened for user samuel by (uid=0)
Jan 08 21:54:31 hostname systemd[801]: PAM failed: Cannot make/remove an entry for the specified session
Jan 08 21:54:31 hostname systemd[801]: [email protected]: Failed to set up PAM session: Operation not permitted
Jan 08 21:54:31 hostname systemd[801]: [email protected]: Failed at step PAM spawning /usr/lib/systemd/systemd: Operation not pe$
Jan 08 21:54:31 hostname systemd[1]: [email protected]: Failed with result 'protocol'.
Jan 08 21:54:31 hostname systemd[1]: Failed to start User Manager for UID 1000.
Jan 08 21:54:31 hostname login[458]: pam_systemd(login:session): Failed to create session: Start job for unit [email protected] $
Jan 08 21:54:31 hostname login[458]: pam_e4crypt: Unknown option for open_session: debug
Jan 08 21:54:31 hostname login[458]: pam_e4crypt: Inserting key with reference ext4:1661114a43da0fbf as 1000:1000
Jan 08 21:54:31 hostname login[458]: LOGIN ON tty1 BY samuel

Both tests were done immediately after a fresh reboot.

The end effect of this is that the user services don't start.

Any ideas why this might happen? Has anyone seen this before?
A Google search turned this up, but the main thing I learned from that is that PAM's error message is useless.
Does PAM load all modules up front and then just call the pam_sm_open_session functions in order?

Wipe potential secrets off memory

We use buffers to calculate/store keys. Those buffers are not zeroed before being free()d/brefore they scope out. This is a security risk.

Mention cron problems in documentation

Cronjobs for a user with an encrypted home folder of course fail if the user is nog logged on and the job needs access to the home folder. It might (or might not) also fail because the cronjob does not take over the session keys.

Example:

[evert@alfheim ~]$ keyctl list @s
3 keys in keyring:
778734583: --alswrv  1001 65534 keyring: _uid.1001
1053809321: --alsw-v  1001  1001 logon: ext4:743de876a7ff9436
156760729: --alsw-v  1001  1001 logon: ext4:95a45eb6e555fa2f

Cron <evert@alfheim>
1 key in keyring:
 58334521: ----s-rv     0     0 user: invocation_id

Note the logon: ext4 stuff missing in the cron session.

Sometimes it looks like the script kinda works because of the cache. More about that:

https://lkml.org/lkml/2016/9/14/364

I couldn't get cron to work reliably so I wrote a shellscript to have my periodic stuff executed while I'm logged on:

https://github.com/evert-mouw/session.sh

Suggestion: just mention these problems in the documentation / wiki / whatever. Of course there is no solution for it, but the problem is hard to debug and could hit others.

Changing LIBDIR to /usr/lib

Hello, I'm trying build your module and I have to set install path as /usr/lib but it's falling to /usr/lib64 instead.
Here is relevant part from https://github.com/neithernut/pam_e4crypt/blob/e026ffe267b42f774a04358a9f55d7dd86d4ec80/CMakeLists.txt

# install the module in the same place where all the other modules should be
# NOTE: we actually disrespect the install prefix here
get_filename_component(LIBDIR ${PAM_LIBRARY} DIRECTORY)
install(TARGETS pam_e4crypt
LIBRARY DESTINATION "${LIBDIR}/security/

Could you guide me how to fix this?

Thank you for this great work!

systemd --user instance doesn't inherit user's session keyring

Systemd --user instance which is started through pam_systemd.so module doesn't use user's session keyring so all user services don't have access to encrypted files. I already reported it upstream but it looks like a design choice which breaks many types of authentication. I don't know if pam_e4crypt could help with this linking keys from user keyring to systemd-user keyring or add keys to system-user keyring directly.

Failure to transport keys from auth to session stage with pam-1.4.0

After upgrading PAM on one of my machines pam_e4crypt ceased working: apparently, the retrieval of policies in the session stage fails. I'll have to investigate whether this is a general problem or whether its just some quirk with my setup (pretty much the standard Gentoo setup with elogind rather than systemd). I didn't find anything suspicious in the release notes, at least.

On the up-side, pam-1.4.0 introduces an API for providing an alternative config directory, which enables some testing setups which were not possible, previously.

[Idea] Add an option for system-wide user specific salt

I'm sorry for constantly disturbing you but I wanted to share one more idea :)

Currently user can set her specific salt in ~/.ext4_encryption_salt which is unfortunately incompatible with encrypted $HOME directory. My idea is to add option to set system-wide salt directory like /var/e4crypt or /home/.e4crypt where pam_e4crypt will look for user salts instead taking precedence.

This option could be like this:
salt_path=$PATHNAME

User could setup it like this:

auth        required        pam_e4crypt.so salt_path=${PATHNAME}
session     required        pam_e4crypt.so salt_path=${PATHNAME}

I'm not sure if it needs to be set for both auth and session or for only one of them.

Now to be available for different users in case of salt_path is set, pam_e4crypt will look for $PATHNAME/$USERNAME-ext4_encryption_salt file instead of $HOME/.ext4_encryption_salt file.

Specific example:

auth        required        pam_e4crypt.so salt_path=/var/e4crypt
session     required        pam_e4crypt.so salt_path=/var/e4crypt

For user Bob pam_e4crypt uses salt from /var/e4crypt/Bob-ext4_encryption_salt
For user Alice pam_e4crypt uses salt from /var/e4crypt/Alice-ext4_encryption_salt

Unfortunately I can't help implementing this due to lack of programming skill but I can show you implementation of similar option in pam_yubico module. In this case the option name is chalresp_path and it overrides default $HOME/.yubico/

I hope above will help you in some way. What do you think about this?

Userspace usage

A bit late since I've already submitted a PR and everything, but how do you handle the userspace side of this? I know I can e4crypt add_key -S $salt $dir to set up an encrypted folder, but this key doesn't end up enabled after login through pam_e4crypt.

Is there something else I need to be doing in userspace to get it to work?

Implement password management function

We currently don't react on password changes performed by users. After an user changes his/her password, the files and directories previously encrypted are still encrypted with the old keys.

We should implement the corresponding PAM password management functions and document the issue for users.

sshd support

Hello!
It will be nice if your very useful module got ssh support :)

This is the plain local login
Mar 1 18:45:56 fluffy login[20716]: pam_e4crypt: Generating key with salt length 16 from file '/etc/pam.d/fox'
Mar 1 18:45:56 fluffy login[20716]: pam_e4crypt: Inserting key with reference ext4:826f76abc8542ebc as 1000:10
Mar 1 18:45:56 fluffy login[20716]: pam_unix(login:session): session opened for user fox(uid=1000) by LOGIN(uid=0)

And this is the login log via ssh
Mar 1 18:45:37 fluffy sshd[20765]: pam_e4crypt: Generating key with salt length 16 from file '/etc/pam.d/fox'
Mar 1 18:45:37 fluffy sshd[20762]: Accepted keyboard-interactive/pam for fox from 10.10.10.4 port 52155 ssh2
Mar 1 18:45:37 fluffy sshd[20762]: pam_e4crypt: Failed to retrieve key list!

As i see, ssh key insertion doesn't happens in the via ssh login case...

Packaged for distros

It would be great if this was in the debian repos - it should be possible to automatically add to PAM too since the ecryptfs-utils package does the same

Build test executable

... to ensure we linked agains all the things we are using. I believe CMake already supports this, but I have forgotton what I have to do to activate this.

Is the 16-byte salt length required ?

I used a custom salt that was not a fixed 16 bytes length and it still worked. Also in the code I see nowhere where there is a hard check for the 16-byte length, is there a reason for keeping this detail on the README ?

Salt handling does not match `e4crypt add_key`

The key pam_e4crypt creates doesn't match the one created by e4crypt using the same salt.

As an example on a fresh VM:

j@debian:~$ keyctl show
Session Keyring
 839405059 --alswrv      0     0  keyring: _ses
 391939558 ----s-rv      0     0   \_ user: invocation_id
1068008579 --alsw-v   1000  1000   \_ logon: ext4:d10d0fa4d20bf12d
 272528715 --alsw-v   1000  1000   \_ logon: ext4:ed04c65c899cb4cf
j@debian:~$ e4crypt add_key -S `cat .ext4_encryption_salt`
Enter passphrase (echo disabled): 
Added key with descriptor [1c6e284e1169c44e]
j@debian:~$ cat .ext4_encryption_salt 
s:ac335322fe640688b17a41708517fc96
j@debian:~$ e4crypt add_key -S s:ac335322fe640688b17a41708517fc96
Enter passphrase (echo disabled): 
Key with descriptor [1c6e284e1169c44e] already exists

As you can see, something pam_e4crypt is doing doesn't fit with e4crypt since they generate different keys.

Reboot and log into a different user and attempt to decrypt, and you'll see it doesn't work.

Keys not flushed from cache after logout

There is known issue that keys aren't cleared from inode cache automatically after user session is closed. See here

Other issues include the filesystem cache that is not invalidated when the key is unlinked and still lets you see the plaintext filenames.

and here (same author)

Plaintext filenames still appear after detaching the key

That is a kernel issue. The dentries cache is not invalidated when you remove the key and still contains the plaintext filenames.

You must remount the device or force a filesystem cache flush with:

# echo 2 > /proc/sys/vm/drop_caches

During my tests it not only shows filenames as plaintext but their context too. You can see all keys in /proc/keys directory. keyctl show command display only keys set from current session.

Actual remedy for this is executing # sync && echo 2 > /proc/sys/vm/drop_caches command as described above. It may need executing as sync && echo 2 | sudo tee /proc/sys/vm/drop_caches in case of insufficient permissions. See here for avalaible documentation. According to this executing this command is only an one-off and hasn't any further consequences for running system.

The only question is, does pam_e4crypt has capability to taking care of this (flushing caches after session close) or some external tools have to be involved?

nice work

This is not a real issue. I just wanted to say "thanks" because I'm making use of this module ๐Ÿ‘
I encountered a few small problems. Some of my config files were not saved (XFCE4, Arch Linux), I could not unlock my session (LightDM) and so on. It might be correlated with the systemd login "features". Anyway I just activated all keyring methods (s, us, u) and it seems to work so far... I'll share my pam config:

/etc/pam.d/system-login

#%PAM-1.0

auth       required   pam_tally.so         onerr=succeed file=/var/log/faillog
auth       required   pam_shells.so
auth       requisite  pam_nologin.so
auth       include    system-auth
auth       required   pam_e4crypt.so       saltpath=/home/.e4crypt keyring=@s
auth       required   pam_e4crypt.so       saltpath=/home/.e4crypt keyring=@us
auth       required   pam_e4crypt.so       saltpath=/home/.e4crypt keyring=@u

account    required   pam_access.so
account    required   pam_nologin.so
account    include    system-auth

password   include    system-auth

session    optional   pam_loginuid.so
session    optional   pam_keyinit.so       force revoke
session    required   pam_e4crypt.so       saltpath=/home/.e4crypt keyring=@s
session    required   pam_e4crypt.so       saltpath=/home/.e4crypt keyring=@us
session    required   pam_e4crypt.so       saltpath=/home/.e4crypt keyring=@u
session    include    system-auth
session    optional   pam_motd.so          motd=/etc/motd
session    optional   pam_mail.so          dir=/var/spool/mail standard quiet
-session   optional   pam_systemd.so
session    required   pam_env.so

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.