X-Original-To: alpine-devel@lists.alpinelinux.org Delivered-To: alpine-devel@mail.alpinelinux.org Received: from mx1.riseup.net (mx1.riseup.net [198.252.153.129]) (using TLSv1 with cipher ECDHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mail.alpinelinux.org (Postfix) with ESMTPS id B52B4DC02F4 for ; Wed, 8 Oct 2014 11:14:12 +0000 (UTC) Received: from berryeater.riseup.net (berryeater-pn.riseup.net [10.0.1.120]) (using TLSv1 with cipher ECDHE-RSA-AES256-SHA (256/256 bits)) (Client CN "*.riseup.net", Issuer "Gandi Standard SSL CA" (not verified)) by mx1.riseup.net (Postfix) with ESMTPS id D7DC650F21 for ; Wed, 8 Oct 2014 04:14:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=riseup.net; s=squak; t=1412766851; bh=JAmGsiZoEJ37FPliW+t8z2UFaS0FA5dKc0DDX4J1mG0=; h=From:To:Cc:Subject:Date:From; b=OC4IneM7F2wIKz6suixqkJPx+LrpXJRbbGAsweqwoV+4ZKpCIexxdR26mhB0IB/06 c9Ag3NaoHryFFCP2FbVsqCwVILgSqlV73XTtLUSmkEqmLC/NGWpS/H3386rsivvnb8 IS90FyYgNnP+0K+KVRXSSDZy2vSUGiVqv8QOfhPU= Received: from [127.0.0.1] (localhost [127.0.0.1]) (Authenticated sender: roger.newman) with ESMTPSA id C423042C16 From: Roger Newman To: alpine-devel@lists.alpinelinux.org Cc: Roger Newman Subject: [alpine-devel] [PATCH] main/cryptsetup: add support for dmcrypt at boot Date: Wed, 8 Oct 2014 13:11:22 +0200 Message-Id: <1412766682-8436-1-git-send-email-roger.newman@riseup.net> X-Mailer: git-send-email 2.0.0 X-Virus-Scanned: clamav-milter 0.98.4 at mx1 X-Virus-Status: Clean X-Mailinglist: alpine-devel Precedence: list List-Id: Alpine Development List-Unsubscribe: List-Post: List-Help: List-Subscribe: modified: APKBUILD new file: dmcrypt.confd new file: dmcrypt.rc --- main/cryptsetup/APKBUILD | 18 ++- main/cryptsetup/dmcrypt.confd | 98 ++++++++++++ main/cryptsetup/dmcrypt.rc | 350 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 463 insertions(+), 3 deletions(-) create mode 100644 main/cryptsetup/dmcrypt.confd create mode 100644 main/cryptsetup/dmcrypt.rc diff --git a/main/cryptsetup/APKBUILD b/main/cryptsetup/APKBUILD index 798864f..89ec2db 100644 --- a/main/cryptsetup/APKBUILD +++ b/main/cryptsetup/APKBUILD @@ -10,6 +10,8 @@ depends="" makedepends="lvm2-dev openssl-dev popt-dev util-linux-dev !libiconv-dev" subpackages="$pkgname-dev $pkgname-doc $pkgname-libs" source="https://www.kernel.org/pub/linux/utils/cryptsetup/v${pkgver%.*}/cryptsetup-$pkgver.tar.gz + dmcrypt.confd + dmcrypt.rc " _builddir="$srcdir"/$pkgname-$pkgver @@ -42,6 +44,10 @@ package() { rm "$pkgdir"/lib/*.la || return 1 mkdir -p "$pkgdir"/usr/lib mv "$pkgdir"/lib/pkgconfig "$pkgdir"/usr/lib/ + + install -m644 -D "$srcdir"/dmcrypt.confd "$pkgdir"/etc/conf.d/dmcrypt + install -m755 -D "$srcdir"/dmcrypt.rc "$pkgdir"/etc/init.d/dmcrypt + } libs() { @@ -50,6 +56,12 @@ libs() { mv "$pkgdir"/lib "$subpkgdir"/ } -md5sums="24790bd4f4fa24570d7ea9af27ccf079 cryptsetup-1.6.6.tar.gz" -sha256sums="38ccd1ceff41760ccfbaaa5394ebb6117d69bd0ea2e00bf07c0d1353c41be6ac cryptsetup-1.6.6.tar.gz" -sha512sums="ce8ea9402f0eb9f3ab920df51837492802dd35394422ef4643a0eb82e6aad67cf72ac428b7caf622539af188f9fe5ba530f06b522f65ed55b0133c5c67ab2723 cryptsetup-1.6.6.tar.gz" +md5sums="24790bd4f4fa24570d7ea9af27ccf079 cryptsetup-1.6.6.tar.gz +1369aeaed84e41c8d585695596a24bd6 dmcrypt.confd +bef4b9289822c47a293f2a0be3526e9c dmcrypt.rc" +sha256sums="38ccd1ceff41760ccfbaaa5394ebb6117d69bd0ea2e00bf07c0d1353c41be6ac cryptsetup-1.6.6.tar.gz +0c30e081c0b8f879964ae49735f10b05a1d92f4f481042851958860945e13271 dmcrypt.confd +02faf27470ea0e50b764c923786724847e77dfdf9680a50cc202546cad2bf02f dmcrypt.rc" +sha512sums="ce8ea9402f0eb9f3ab920df51837492802dd35394422ef4643a0eb82e6aad67cf72ac428b7caf622539af188f9fe5ba530f06b522f65ed55b0133c5c67ab2723 cryptsetup-1.6.6.tar.gz +d04ae17d3708ef20ade7afb223d4ef19e1b6812e0be8f9499e37e9c71344568b42030d9dd8f6918a9bfb211a3a94b40a9354e3b32a009cb165e84508d0a5e14b dmcrypt.confd +660d1a29294e8e01343aea0b92d9159d42891261d41313c3f9e77ed3bd69e648d19d3799a8ad1b00884b6f4c0f48d4e12cb406ca291e64b789e71ba70ab3c29f dmcrypt.rc" diff --git a/main/cryptsetup/dmcrypt.confd b/main/cryptsetup/dmcrypt.confd new file mode 100644 index 0000000..35a1fd2 --- /dev/null +++ b/main/cryptsetup/dmcrypt.confd @@ -0,0 +1,98 @@ +# /etc/conf.d/dmcrypt + +# For people who run dmcrypt on top of some other layer (like raid), +# use rc_need to specify that requirement. See the runscript(8) man +# page for more information. + +#-------------------- +# Instructions +#-------------------- + +# Note regarding the syntax of this file. This file is *almost* bash, +# but each line is evaluated separately. Separate swaps/targets can be +# specified. The init-script which reads this file assumes that a +# swap= or target= line starts a new section, similar to lilo or grub +# configuration. + +# Note when using gpg keys and /usr on a separate partition, you will +# have to copy /usr/bin/gpg to /bin/gpg so that it will work properly +# and ensure that gpg has been compiled statically. +# See http://bugs.gentoo.org/90482 for more information. + +# Note that the init-script which reads this file detects whether your +# partition is LUKS or not. No mkfs is run unless you specify a makefs +# option. + +# Global options: +#---------------- + +# Max number of checks to perform (1 per second) +#dmcrypt_max_timeout=120 + +# Arguments: +#----------- +# target= == Mapping name for partition. +# swap= == Mapping name for swap partition. +# source='' == Real device for partition. +# key='[:]' == Fullpath from / or from inside removable media. +# remdev='' == Device that will be assigned to removable media. +# gpg_options='' == Default are --quiet --decrypt +# options='' == cryptsetup, for LUKS you can only use --readonly +# loop_file='' == Loopback file. +# pre_mount='cmds' == commands to execute before mounting partition. +# post_mount='cmds' == commands to execute after mounting partition. +#----------- +# Supported Modes +# gpg == decrypt and pipe key into cryptsetup. +# Note: new-line character must not be part of key. +# Command to erase \n char: 'cat key | tr -d '\n' > cleanKey' + +#-------------------- +# dm-crypt examples +#-------------------- + +## swap +# Swap partitions. These should come first so that no keys make their +# way into unencrypted swap. +# If no options are given, they will default to: -c aes -h sha1 -d /dev/urandom +# If no makefs is given then mkswap will be assumed +#swap=crypt-swap +#source='/dev/hda2' + +## /home with passphrase +#target=crypt-home +#source='/dev/hda5' + +## /home with regular keyfile +#target=crypt-home +#source='/dev/hda5' +#key='/full/path/to/homekey' + +## /home with gpg protected key +#target=crypt-home +#source='/dev/hda5' +#key='/full/path/to/homekey:gpg' + +## /home with regular keyfile on removable media(such as usb-stick) +#target=crypt-home +#source='/dev/hda5' +#key='/full/path/to/homekey' +#remdev='/dev/sda1' + +##/home with gpg protected key on removable media(such as usb-stick) +#target=crypt-home +#source='/dev/hda5' +#key='/full/path/to/homekey:gpg' +#remdev='/dev/sda1' + +##/tmp with regular keyfile +#target=crypt-tmp +#source='/dev/hda6' +#key='/full/path/to/tmpkey' +#pre_mount='/sbin/mkreiserfs -f -f ${dev}' +#post_mount='chown root:root ${mount_point}; chmod 1777 ${mount_point}' + +## Loopback file example +#mount='crypt-loop-home' +#source='/dev/loop0' +#loop_file='/mnt/crypt/home' diff --git a/main/cryptsetup/dmcrypt.rc b/main/cryptsetup/dmcrypt.rc new file mode 100644 index 0000000..fed2cc6 --- /dev/null +++ b/main/cryptsetup/dmcrypt.rc @@ -0,0 +1,350 @@ +#!/sbin/runscript +# Copyright 1999-2013 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-x86/sys-fs/cryptsetup/files/1.5.1-dmcrypt.rc,v 1.1 2013/01/17 23:35:08 robbat2 Exp $ + +depend() { + before checkfs fsck +} + +# We support multiple dmcrypt instances based on $SVCNAME +execute_hook="dm_crypt_execute_dmcrypt" +# XXX: Should we drop this ? +# execute_hook="dm_crypt_execute_localmount" +conf_file="/etc/conf.d/${SVCNAME}" + +# Get splash helpers if available. +if [ -e /sbin/splash-functions.sh ] ; then + . /sbin/splash-functions.sh +fi + +# Setup mappings for an individual target/swap +# Note: This relies on variables localized in the main body below. +dm_crypt_execute_dmcrypt() { + local dev ret mode foo + + if [ -n "${target}" ] ; then + # let user set options, otherwise leave empty + : ${options:=' '} + elif [ -n "${swap}" ] ; then + if cryptsetup isLuks ${source} 2>/dev/null ; then + ewarn "The swap you have defined is a LUKS partition. Aborting crypt-swap setup." + return + fi + target=${swap} + # swap contents do not need to be preserved between boots, luks not required. + # suspend2 users should have initramfs's init handling their swap partition either way. + : ${options:='-c aes -h sha1 -d /dev/urandom'} + : ${pre_mount:='mkswap ${dev}'} + else + return + fi + if [ "x${source#UUID}" != "x${source}" ]; then + source=${source#UUID=} + source="$(blkid -U ${source})" + fi + if [ -z "${source}" ] && [ ! -e "${source}" ] ; then + ewarn "source \"${source}\" for ${target} missing, skipping..." + return + fi + + if [ -n "${loop_file}" ] ; then + dev="/dev/mapper/${target}" + ebegin " Setting up loop device ${source}" + losetup ${source} ${loop_file} + fi + + # cryptsetup: + # luksOpen # is $source + # create # is $target + local arg1="create" arg2="${target}" arg3="${source}" luks=0 + + cryptsetup isLuks ${source} 2>/dev/null && { arg1="luksOpen"; arg2="${source}"; arg3="${target}"; luks=1; } + + # Older versions reported: + # ${target} is active: + # Newer versions report: + # ${target} is active[ and is in use.] + if cryptsetup status ${target} | egrep -q ' is active' ; then + einfo "dm-crypt mapping ${target} is already configured" + return + fi + splash svc_input_begin ${SVCNAME} >/dev/null 2>&1 + + # Handle keys + if [ -n "${key}" ] ; then + read_abort() { + # some colors + local ans savetty resettty + [ -z "${NORMAL}" ] && eval $(eval_ecolors) + einfon " $1? (${WARN}yes${NORMAL}/${GOOD}No${NORMAL}) " + shift + # This is ugly as s**t. But POSIX doesn't provide `read -t`, so + # we end up having to implement our own crap with stty/etc... + savetty=$(stty -g) + resettty='stty ${savetty}; trap - EXIT HUP INT TERM' + trap 'eval "${resettty}"' EXIT HUP INT TERM + stty -icanon + [ "${1}" = -t ] && stty min 0 time "$(( $2 * 10 ))" + ans=$(dd count=1 bs=1 2>/dev/null) || ans='' + eval "${resettty}" + if [ -z "${ans}" ] ; then + printf '\r' + else + echo + fi + case ${ans} in + [yY]) return 0;; + *) return 1;; + esac + } + + # Notes: sed not used to avoid case where /usr partition is encrypted. + mode=${key/*:/} && ( [ "${mode}" = "${key}" ] || [ -z "${mode}" ] ) && mode=reg + key=${key/:*/} + case "${mode}" in + gpg|reg) + # handle key on removable device + if [ -n "${remdev}" ] ; then + # temp directory to mount removable device + local mntrem="${RC_SVCDIR}/dm-crypt-remdev.$$" + if [ ! -d "${mntrem}" ] ; then + if ! mkdir -p "${mntrem}" ; then + ewarn "${source} will not be decrypted ..." + einfo "Reason: Unable to create temporary mount point '${mntrem}'" + return + fi + fi + i=0 + einfo "Please insert removable device for ${target}" + while [ ${i} -lt ${dmcrypt_max_timeout:-120} ] ; do + foo="" + if mount -n -o ro "${remdev}" "${mntrem}" 2>/dev/null >/dev/null ; then + # keyfile exists? + if [ ! -e "${mntrem}${key}" ] ; then + umount -n "${mntrem}" + rmdir "${mntrem}" + einfo "Cannot find ${key} on removable media." + read_abort "Abort" ${read_timeout:--t 1} && return + else + key="${mntrem}${key}" + break + fi + else + [ -e "${remdev}" ] \ + && foo="mount failed" \ + || foo="mount source not found" + fi + : $((i += 1)) + read_abort "Stop waiting after $i attempts (${foo})" -t 1 && return + done + else # keyfile ! on removable device + if [ ! -e "${key}" ] ; then + ewarn "${source} will not be decrypted ..." + einfo "Reason: keyfile ${key} does not exist." + return + fi + fi + ;; + *) + ewarn "${source} will not be decrypted ..." + einfo "Reason: mode ${mode} is invalid." + return + ;; + esac + else + mode=none + fi + ebegin " ${target} using: ${options} ${arg1} ${arg2} ${arg3}" + if [ "${mode}" = "gpg" ] ; then + : ${gpg_options:='-q -d'} + # gpg available ? + if type -p gpg >/dev/null ; then + for i in 0 1 2 ; do + # paranoid, don't store key in a variable, pipe it so it stays very little in ram unprotected. + # save stdin stdout stderr "values" + gpg ${gpg_options} ${key} 2>/dev/null | cryptsetup ${options} ${arg1} ${arg2} ${arg3} + ret=$? + [ ${ret} -eq 0 ] && break + done + eend ${ret} "failure running cryptsetup" + else + ewarn "${source} will not be decrypted ..." + einfo "Reason: cannot find gpg application." + einfo "You have to install app-crypt/gnupg first." + einfo "If you have /usr on its own partition, try copying gpg to /bin ." + fi + else + if [ "${mode}" = "reg" ] ; then + cryptsetup ${options} -d ${key} ${arg1} ${arg2} ${arg3} + ret=$? + eend ${ret} "failure running cryptsetup" + else + cryptsetup ${options} ${arg1} ${arg2} ${arg3} + ret=$? + eend ${ret} "failure running cryptsetup" + fi + fi + if [ -d "${mntrem}" ] ; then + umount -n ${mntrem} 2>/dev/null >/dev/null + rmdir ${mntrem} 2>/dev/null >/dev/null + fi + splash svc_input_end ${SVCNAME} >/dev/null 2>&1 + + if [ ${ret} -ne 0 ] ; then + cryptfs_status=1 + else + if [ -n "${pre_mount}" ] ; then + dev="/dev/mapper/${target}" + ebegin " pre_mount: ${pre_mount}" + eval "${pre_mount}" > /dev/null + ewend $? || cryptfs_status=1 + fi + fi +} + +# Run any post_mount commands for an individual mount +# +# Note: This relies on variables localized in the main body below. +dm_crypt_execute_localmount() { + local mount_point + + [ -z "${target}" ] && [ -z "${post_mount}" ] && return + + if ! cryptsetup status ${target} | egrep -q '\/dev/null + eend $? || cryptfs_status=1 + fi +} + +# Lookup optional bootparams +get_bootparam_val() { + # We're given something like: + # foo=bar=cow + # Return the "bar=cow" part. + case $1 in + *\=*) + local key=$(echo "$1" | cut -f1 -d=) + echo "$1" | cut -c $(( ${#key} + 2 )) + ;; + esac +} + +start() { + local header=true cryptfs_status=0 + local gpg_options key loop_file target targetline options pre_mount post_mount source swap remdev + + local x + for x in $(cat /proc/cmdline) ; do + case "${x}" in + key_timeout\=*) + local KEY_TIMEOUT=$(get_bootparam_val "${x}") + if [ ${KEY_TIMEOUT} -gt 0 ] ; then + read_timeout="-t ${KEY_TIMEOUT}" + fi + ;; + esac + done + + while read -u 3 targetline ; do + case ${targetline} in + # skip comments and blank lines + ""|"#"*) continue ;; + # skip service-specific openrc configs #377927 + rc_*) continue ;; + esac + + ${header} && ebegin "Setting up dm-crypt mappings" + header=false + + # check for the start of a new target/swap + case ${targetline} in + target=*|swap=*) + # If we have a target queued up, then execute it + ${execute_hook} + + # Prepare for the next target/swap by resetting variables + unset gpg_options key loop_file target options pre_mount post_mount source swap remdev + ;; + + gpg_options=*|remdev=*|key=*|loop_file=*|options=*|pre_mount=*|post_mount=*|source=*) + if [ -z "${target}${swap}" ] ; then + ewarn "Ignoring setting outside target/swap section: ${targetline}" + continue + fi + ;; + + dmcrypt_max_timeout=*) + # ignore global options + continue + ;; + + *) + ewarn "Skipping invalid line in ${conf_file}: ${targetline}" + ;; + esac + + # Queue this setting for the next call to dm_crypt_execute_xxx + eval "${targetline}" + done 3< ${conf_file} + + # If we have a target queued up, then execute it + ${execute_hook} + + ewend ${cryptfs_status} "Failed to setup dm-crypt devices" +} + +stop() { + local line header + + # Break down all mappings + header=true + egrep "^(target|swap)=" ${conf_file} | \ + while read line ; do + ${header} && einfo "Removing dm-crypt mappings" + header=false + + target= swap= + eval ${line} + + [ -n "${swap}" ] && target=${swap} + if [ -z "${target}" ] ; then + ewarn "invalid line in ${conf_file}: ${line}" + continue + fi + + ebegin " ${target}" + cryptsetup remove ${target} + eend $? + done + + # Break down loop devices + header=true + grep '^source=./dev/loop' ${conf_file} | \ + while read line ; do + ${header} && einfo "Detaching dm-crypt loop devices" + header=false + + source= + eval ${line} + + ebegin " ${source}" + losetup -d "${source}" + eend $? + done + + return 0 +} -- 2.0.0 --- Unsubscribe: alpine-devel+unsubscribe@lists.alpinelinux.org Help: alpine-devel+help@lists.alpinelinux.org ---