This post describes how to encrypt the home directory of your users on GNU Linux with the help of TrueCrypt and PAM using the login-password as encryption key.
I wrote about Automatic encryption of home directories using TrueCrypt before. This time we’ll use TrueCrypt 6.2a. Futhermore we’ll use Ubuntu 9.04 Jaunty Jackalope and we replaced pam_mount by pam_exec. For convenience this post will be selfcontained (ie. I copy redundant parts from the old one).
Using the method described below is no silver bullet and has some issues:
- Your user passwords may be weak.
- If your computer gets stolen while turned on, the passwort may be easier to recover than you might think (see here).
- Changing the password requires to log in as root.
- Some programs (e.g. qmail) rely on an accessible home directory.
- The home may accidently stay mounted after logout until the next reboot.
- Suspend to ram and suspend to disk are not treated carefully enough.
- There may be glitches in my scripts.
Prequisites
- GNU Linux (Ubuntu 9.04 Jacky Jackalope )
- TrueCrypt (I used 6.2a)
- a modern pam_exec.so (see below)
Setup
We will create one file for each user to hold his encrypted home directory. To keep them we create a directory:
mkdir /home/private
For each user we have to create an encrypted file in /home/private. We start with the user bart (if you leave out the --text
you’ll get a graphical user interface).
root@mybox:~# truecrypt --text --create /home/private/bart.tc Volume type: 1) Normal 2) Hidden Select [1]: 1 Enter volume size (bytes - size/sizeK/sizeM/sizeG): 1G Encryption algorithm: 1) AES 2) Serpent 3) Twofish 4) AES-Twofish 5) AES-Twofish-Serpent 6) Serpent-AES 7) Serpent-Twofish-AES 8 ) Twofish-Serpent Select [1]: 1 Hash algorithm: 1) RIPEMD-160 2) SHA-512 3) Whirlpool Select [1]: 1 Filesystem: 1) FAT 2) None Select [1]: 2 Enter password: ************* WARNING: Short passwords are easy to crack using brute force techniques! We recommend choosing a password consisting of more than 20 characters. Are you sure you want to use a short password? (y=Yes/n=No) [No]: y Re-enter password:************* Enter keyfile path [none]: Please type at least 320 randomly chosen characters and then press Enter: dsglregmm;adsf;dsafdsasasadfdsafdsagfdsadsafdsafdsafadsfdsahfarweqasddsaglfdsakg;lrewqk;lggkqqqqqewrgsadgdsag.... Done: 100.000% Speed: 18.0 MB/s Left: 0 s The TrueCrypt volume has been successfully created.
Then we assign the same password as the login password to bart:
root@mybox:~# passwd bart Enter new UNIX password: Retype new UNIX password:
Next, we need to format the encrypted partition and move the old home directory into it:
root@mybox:~# truecrypt --text --filesystem=none /home/private/bart.tc Enter password for /home/hgerlach/newcrypt.tc: ************* Enter keyfile [none]: Protect hidden volume? (y=Yes/n=No) [No]: root@mybox:~# truecrypt --text -l 1: /home/private/bart.tc /dev/mapper/truecrypt1 - root@mybox:~# mkfs.ext2 /dev/mapper/truecrypt1 root@mybox:~# mount /dev/mapper/truecrypt1 /mnt/ root@mybox:~# shopt -s dotglob #make dotfiles visible root@mybox:~# mv /home/bart/* /mnt/ root@mybox:~# chown bart.users /mnt/ root@mybox:~# umount /mnt root@mybox:~# truecrypt -d /dev/mapper/truecrypt1
Now we have to make sure the homedir gets mounted on login. Previously I used pam_mount but they dropped truecrypt support and sound somewhat angry on trucrypt (because they changed their interface). I was not so happy with pam_mount myself and reported a bug which got fixed quickly but will take some time to appear downstream in Ubuntu or Debian.
This time I decided to roll my own mount/umount script. It relies on a “modern” version of pam_exec that supports the expose_authok
option. Unfortunally Ubuntu does not come with this modern version yet, so you either have to download it from me (i386-32bit, no guarantees, infected with rootkit by now) or compile it yourself. You should copy the lib to
/lib/security/pam_exec_UNSTABLE.so
so pam can find it.
To the file ‘/etc/pam.d/common-auth’ we add the line:
auth optional pam_exec_UNSTABLE.so debug expose_authtok seteuid /bin/bash /bin/cryptmount.sh
so it looks like
# /etc/pam.d/common-auth # here are the per-package modules (the "Primary" block) auth [success=1 default=ignore] pam_unix.so nullok_secure # here's the fallback if no module succeeds auth requisite pam_deny.so # prime the stack with a positive return value if there isn't one already; # this avoids us returning an error just because nothing sets a success code # since the modules above will each just jump around auth required pam_permit.so # and here are more per-package modules (the "Additional" block) # end of pam-auth-update config auth optional pam_exec_UNSTABLE.so debug expose_authtok seteuid /bin/bash /bin/cryptmount.sh
and to ‘/etc/pam.d/common-session’ we add the line
session optional pam_exec_UNSTABLE.so seteuid /bin/bash /bin/cryptmount.sh
so it looks like
# ... # here are the per-package modules (the "Primary" block) session [default=1] pam_permit.so # here's the fallback if no module succeeds session requisite pam_deny.so # prime the stack with a positive return value if there isn't one already; # this avoids us returning an error just because nothing sets a success code # since the modules above will each just jump around session required pam_permit.so # and here are more per-package modules (the "Additional" block) session required pam_unix.so session optional pam_ck_connector.so nox11 # end of pam-auth-update config session optional pam_exec_UNSTABLE.so seteuid /bin/bash /bin/cryptmount.sh
Everytime we log in or a new session starts the script /bin/cryptmount.sh
gets executed.
Thats what I propose it to look like:
#!/bin/bash # /bin/cryptmount.sh CRYPTVOLUME=/home/private/$PAM_USER.tc MOUNTPOINT=/home/$PAM_USER case "$PAM_USER" in root | lisa ) #homedirs of root and lisa are not encrypted exit 0 ;; esac case "$PAM_TYPE" in auth ) head -c -1 | truecrypt -t --protect-hidden=no -k "" \ "$CRYPTVOLUME" "$MOUNTPOINT" ;; close_session ) MOUNTS=$(mount | grep " $MOUNTPOINT ") if test -z $MOUNTS ; then echo MOUNTS $MOUNTS > /tmp/debug exit 0 fi OTHER=$(who | grep "^$PAM_USER " | grep -v " $PAM_TTY ") if test -z "$OTHER"; then echo truecrypt -d $MOUNTPOINT | at now + 1 minute fi ;; esac exit 0
It first checks whether root or lisa (adapt to your own needs) is calling it. Both of them do not have encrypted homedirs, so the script exits. In the second case clause it checks wheter it is called while authenticating and mounts the homdir using the login passphrase or if it is called for closing a session. In the latter case it schedules unmounting the homedir in one minute.
Now bart can login and use the encrypted home. One minute after logoff the homedir will be umounted and encrypted again.
How to roll your own pam_exec_UNSTABLE.so
# get the source (after searching packages.debian.org) wget http://ftp.de.debian.org/debian/pool/main/p/pam/pam_1.1.0.orig.tar.gz tar xfzv pam_1.1.0.orig.tar.gz cd Linux-PAM-1.1.0/ ./configure # install all packages needed for configure to run through cd modules/pam_exec/ make # yes this is dirty, but who cares. sudo cp .libs/pam_exec.so /lib/security/pam_exec_UNSTABLE.so