#!/bin/sh # -*- sh-basic-offset: 4; sh-indentation: 4; tab-width: 4; indent-tabs-mode: t; sh-indent-comment: t; -*- # This script encrypts an user's home # # Written by Yan Li , # Copyright (C) 2010 Intel Corporation # # Modified by Dustin Kirkland # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA # 02111-1307, USA. set -e PRIVATE_DIR="Private" usage() { echo " Usage: $0 -u USER -u,--user Migrate USER's home directory to an encrypted home directory WARNING: Make a complete backup copy of the non-encrypted data to another system or external media. This script is dangerous and, in case of an error, could result in data lost, or lock you out of your system! This program must be executed by root. " exit 1 } error() { echo "$(gettext 'ERROR: ')" "$@" 1>&2 exit 1 } warning() { echo "$(gettext 'WARNING: ')" "$@" 1>&2 } info() { echo "$(gettext 'INFO: ')" "$@" 1>&2 } assert_dir_empty() { local DIR="$1" if [ -e "$DIR" ]; then # if $DIR is a directory, make sure it's empty if [ -d "$DIR" ]; then ls=$(ls -A "$DIR" | wc -l) if [ "$ls" != "0" ]; then echo 1>&2 "If you already have some data in directory $DIR," echo 1>&2 "please move all of these files and directories out of the way, and" echo 1>&2 "follow the instructions in:" echo 1>&2 " ecryptfs-setup-private --undo" echo 1>&2 error "$DIR is not empty, cannot continue." fi else error "$DIR exists but is not an empty directory, cannot continue." fi fi } # get user home by username get_user_home () { local USER_NAME="$1" local USER_HOME=$(getent passwd $USER_NAME | cut -d":" -f 6) if [ -z "$USER_HOME" ]; then error "Cannot find the home directory of $USER_NAME." fi echo "$USER_HOME" } sanity_check () { local USER_NAME="$1" local USER_HOME="$2" if [ -e "$USER_HOME/.ecryptfs" ]; then error "$USER_HOME appears to be encrypted already." fi # Check for rsync if ! which rsync >/dev/null 2>&1; then error "Please install the rsync package." fi # Check free space: make sure we have sufficient disk space # available. To make a full copy, we will need at least 2.5x the # disk usage of the target home directory. info "Checking disk space, this may take a few moments. Please be patient." needed=$(du -s "$USER_HOME" | awk '{printf "%.0f", $1*2.5}') free=$(df -P "$USER_HOME" | tail -n 1 | awk '{print $4}') if [ $needed -gt $free ]; then info "2.5x the size your current home directory is required to perform a migration." info "Once the migration succeeds, you may recover most of this space by deleting the cleartext directory." error "Not enough free disk space." fi assert_dir_empty "$USER_HOME/.$PRIVATE_DIR" assert_dir_empty "$USER_HOME/.ecryptfs" assert_dir_empty "/home/.ecryptfs/$USER_NAME" } encrypt_dir () { local USER_NAME="$1" local USER_HOME="$2" if ! which lsof >/dev/null 2>&1; then info "Please install lsof." error "Can not tell whether $USER_HOME is in use or not." fi info "Checking for open files in $USER_HOME" lsof=$(lsof +D "$USER_HOME" | wc -l) if [ "$lsof" != "0" ]; then info "The following files are in use:" echo lsof +D "$USER_HOME" | sed "s/^/ /" echo error "Cannot proceed." fi # start encryption orig=$(mktemp /home/$USER_NAME.XXXXXXXX) rm "$orig" && mv "$USER_HOME" "$orig" chmod 700 "$orig" mkdir -p -m 700 "$USER_HOME" USER_GROUP=$(id -g "$USER_NAME") chown "$USER_NAME:$USER_GROUP" "$USER_HOME" "$orig" ECRYPTFS_SETUP_PRIVATE_ARGS="" if [ -n "$LOGINPASS" ]; then ECRYPTFS_SETUP_PRIVATE_ARGS="-l $LOGINPASS" fi if [ -n "$MOUNTPASS" ]; then ECRYPTFS_SETUP_PRIVATE_ARGS="$ECRYPTFS_SETUP_PRIVATE_ARGS -m $MOUNTPASS" fi if ! ecryptfs-setup-private -u "$USER_NAME" -b $ECRYPTFS_SETUP_PRIVATE_ARGS; then # too bad, something went wrong, we'll try to recover rm -rf "$USER_HOME" mv "$orig" "$USER_HOME" exit 1 fi info "Encrypted home has been set up, encrypting files now...this may take a while." rsync -a "$orig/" "$USER_HOME/" umount "$USER_HOME/" echo echo "========================================================================" echo "Some Important Notes!" echo echo " 1. The file encryption appears to have completed successfully, however," echo " $USER_NAME MUST LOGIN IMMEDIATELY, _BEFORE_THE_NEXT_REBOOT_," echo " TO COMPLETE THE MIGRATION!!!" echo echo " 2. If $USER_NAME can log in and read and write their files, then the migration is complete," echo " and you should remove $orig." echo " Otherwise, restore $orig back to $USER_HOME." echo echo " 3. $USER_NAME should also run 'ecryptfs-unwrap-passphrase' and record" echo " their randomly generated mount passphrase as soon as possible." echo echo " 4. To ensure the integrity of all encrypted data on this system, you" echo " should also encrypted swap space with 'ecryptfs-setup-swap'." echo "========================================================================" echo } DO_ENCRYPT= while true; do [ -z "$1" ] && break case "$1" in -u|--user) DO_ENCRYPT=1 USER_NAME="$2" shift 2 ;; *) usage ;; esac done if [ "$DO_ENCRYPT" != "1" ]; then usage fi if [ "$(id -u)" != "0" ]; then error "This program must be executed with root privileges" fi if [ "$DO_ENCRYPT" = "1" ]; then USER_HOME=$(get_user_home "$USER_NAME") sanity_check "$USER_NAME" "$USER_HOME" encrypt_dir "$USER_NAME" "$USER_HOME" "$LOGINPASS" "$MOUNTPASS" fi