summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore4
-rw-r--r--Makefile27
-rw-r--r--cryptfs.bin.in236
-rw-r--r--cryptfs.in150
-rw-r--r--cryptfs.rc.in33
-rw-r--r--cryptfs.service.in13
6 files changed, 304 insertions, 159 deletions
diff --git a/.gitignore b/.gitignore
index 69509e1..b354d05 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,3 @@
-cryptfs
+cryptfs.bin
+cryptfs.rc
+cryptfs.service
diff --git a/Makefile b/Makefile
index 4cc0ebe..a793d83 100644
--- a/Makefile
+++ b/Makefile
@@ -20,26 +20,37 @@
#
DESTDIR =
-ETCDIR = /etc
+BINDIR = /usr/bin
DEVDIR = /dev
+ETCDIR = /etc
UUIDDIR = $(DEVDIR)/disk/by-uuid
MAPDIR = $(DEVDIR)/mapper
RCDDIR = $(ETCDIR)/rc.d
+SYSTEMDDIR = /usr/lib/systemd/system
+CONF_PREFIXES =
-VERSION = 0.3
+VERSION = 0.4
-all: cryptfs
+all: cryptfs.bin cryptfs.rc cryptfs.service
%: %.in
- sed "s/#VERSION#/$(VERSION)/; s@#DEVDIR#@$(DEVDIR)@; s@#ETCDIR#@$(ETCDIR)@; s@#UUIDDIR#@$(UUIDDIR)@; s@#MAPDIR#@$(MAPDIR)@; s@#RCDDIR#@$(RCDDIR)@" $< > $@
+ sed "s/#VERSION#/$(VERSION)/; s@#DEVDIR#@$(DEVDIR)@; s@#ETCDIR#@$(ETCDIR)@; s@#UUIDDIR#@$(UUIDDIR)@; s@#MAPDIR#@$(MAPDIR)@; s@#RCDDIR#@$(RCDDIR)@; s@#CONF_PREFIXES#@$(CONF_PREFIXES)@" $< > $@
+ [ "$@" = "cryptfs.bin" ] && chmod +x "$@" || true
+ [ "$@" = "cryptfs.rc" ] && chmod +x "$@" || true
+
+.PHONY: install_bin install_systemd install_sysvinit dist clean
+
+install_bin:
+ install -D -m0755 cryptfs.bin $(DESTDIR)$(BINDIR)/cryptfs
-.PHONY: install dist clean
+install_systemd: install_bin
+ install -D -m0644 cryptfs.service $(DESTDIR)$(SYSTEMDDIR)/cryptfs
-install: all
- install -D -m0755 cryptfs $(DESTDIR)$(RCDDIR)/cryptfs
+install_sysvinit: install_bin
+ install -D -m0755 cryptfs.rc $(DESTDIR)$(RCDDIR)/cryptfs
clean:
- rm -f cryptfs
+ rm -f cryptfs.bin cryptfs.rc cryptfs.service
dist: clean
git status --porcelain 2> /dev/null | grep -q "\S" && (git add .; git commit -m"neue Version: $(VERSION)") || true
diff --git a/cryptfs.bin.in b/cryptfs.bin.in
new file mode 100644
index 0000000..fde3bd0
--- /dev/null
+++ b/cryptfs.bin.in
@@ -0,0 +1,236 @@
+#!/bin/bash
+#
+# #BINDIR#/cryptfs: mount/umount encrypted partitions
+#
+
+set -e
+
+if [ $# -eq 1 ] && [ "x$1" = 'x-u' ]; then
+ unmount=true
+elif [ $# -eq 0 ]; then
+ unmount=false
+else
+ >&2 printf 'Usage: %s [-u]\n' "$0"
+ exit 1
+fi
+
+give_all_parent_dirs() {
+ local odir
+ local dir
+ odir="$1"
+ odir="/${odir#/}"
+ dir="${odir%/*}"
+ while [ "${dir}" != '' ]; do
+ printf '%s %s\n' "${odir}" "${dir}"
+ dir="${dir%/*}"
+ done
+}
+
+inner_fs_to_mountorder() {
+ {
+ echo "${fstab}" | \
+ grep "^$1 " | \
+ awk '{print "x " $3}'
+ echo "${fstab}" | \
+ sed -n '
+ s|^\(\S\+\) \S\+ \(\S\+\)\( .*\)\?$|\1 \2|
+ T
+ p
+ ' | \
+ while read -r order dir; do
+ give_all_parent_dirs "${dir}" | \
+ awk '{print "'"${order}"' " $1 " " $2}'
+ done | \
+ sort -k3,3 -k2r,2 | \
+ uniq -f2 | \
+ cut -d' ' -f1,3
+ } | \
+ sort -k2r,2 -k1,1 | \
+ uniq -f1 -d | \
+ cut -d' ' -f1
+}
+
+mountpoint_to_file() {
+ {
+ echo "${fstab}" | \
+ awk '{print $1 " " $3}'
+ give_all_parent_dirs "$1" | \
+ awk '{print "x " $2}'
+ } | \
+ sort -k2r,2 -k1,1 | \
+ uniq -f1 -d | \
+ cut -d' ' -f1 | \
+ head -n1
+}
+
+mountorder_to_device() {
+ {
+ printf 'x %s\n' "$1"
+ echo "${fstab}" | \
+ awk '{print $1 " " $2}' | \
+ sort -k2,2 -u
+ } | \
+ sort -k2,2 -k1,1 | \
+ uniq -f1 -d | \
+ cut -d' ' -f1
+}
+
+crypttab=$(
+ sed '
+ s|^\s*#CONF_PREFIXES#\s*||
+ /^\s*#/d
+ /^\s*$/d
+ s/\s\+/ /g
+ ' '#ETCDIR#/crypttab' | \
+ sort -u | \
+ sed '
+ s|UUID=|#UUIDDIR#/|
+ s/\s\+/ /g
+ s/^ //
+ '
+)
+fstab=$(
+ sed '
+ s|^\s*#CONF_PREFIXES#\s*||
+ /^\s*#/d
+ /^\s*\S\+\s\+[^\/[:space:]]/d
+ /^\s*$/d
+ s/\s\+/ /g
+ ' '#ETCDIR#/fstab' | \
+ sort -u | \
+ cat -n | \
+ sed '
+ s|UUID=|#UUIDDIR#/|
+ s/\s\+/ /g
+ s/^ //
+ s/ \+$//
+ '
+)
+
+mount_details() {
+ echo "${fstab}" | \
+ grep "^$2 " | \
+ while read -r _ source dest fs opts _; do
+ case "$1" in
+ 'mp')
+ printf '%s\n' "${dest}"
+ ;;
+ 'dev')
+ printf '%s\n' "${source}"
+ ;;
+ 'fs')
+ printf '%s\n' "${fs}"
+ ;;
+ 'all')
+ printf -- '-t %s ' "${fs}"
+ if [ -n "${opts}" ] && \
+ [ "${opts}" != 'defaults' ]; then
+ printf -- '-o %s ' "${opts}"
+ fi
+ printf '%s %s\n' "${source}" "${dest}"
+ ;;
+ *)
+ >&2 printf 'unknown mount_details "%s"\n' "$1"
+ exit 42
+ ;;
+ esac
+ done
+}
+
+is_mounted() {
+ mountpoint -q "$(mount_details mp "$1")"
+}
+
+is_unlocked() {
+ cryptsetup status "$1" >/dev/null 2>&1
+}
+
+do_mount() {
+ local inner_fs
+ if is_mounted "$1"; then
+ return
+ fi
+ inner_fs=$(inner_fs_to_mountorder "$1")
+
+ case "$(mount_details fs "$1")" in
+ 'ext'*)
+ e2fsck $(mount_details dev "$1")
+ ;;
+ 'fuse.sshfs'|'fuse.ftps')
+ local max_wait
+ local host
+ max_wait=$(($(date +%s)+120))
+ host=$(
+ mount_details dev "$1" | \
+ sed 's>^\([^:@]*@\)\?\([^:@]\+\):\S*$>\2>"
+ )
+ while [ $(date +%s) -lt ${max_wait} ] && \
+ ! /bin/ping6 -c1 ${host} >/dev/null 2>&1 && \
+ ! /bin/ping -c1 ${host} >/dev/null 2>&1; do
+ >&2 printf ','
+ sleep 1
+ done
+ ;;
+ esac
+
+ if [ -n "${inner_fs}" ]; then
+ do_unmount -l "${inner_fs}"
+ fi
+ mount $(mount_details all "$1")
+ if [ -n "${inner_fs}" ]; then
+ do_mount "${inner_fs}"
+ fi
+}
+
+do_unmount() {
+ local inner_fs
+ local lazy
+ if [ "x$1" = 'x-l' ]; then
+ lazy='-l'
+ shift
+ else
+ lazy=''
+ fi
+ if ! is_mounted "$1"; then
+ return
+ fi
+ inner_fs=$(inner_fs_to_mountorder "$1")
+ if [ -n "${inner_fs}" ]; then
+ do_unmount -l "${inner_fs}"
+ fi
+ umount ${lazy} $(mount_details mp "$1")
+ if [ -n "${inner_fs}" ]; then
+ do_mount "${inner_fs}"
+ fi
+}
+
+do_crypt_close() {
+ if is_unlocked "$1"; then
+ cryptsetup luksClose "$1"
+ fi
+}
+
+do_crypt_open() {
+ if ! is_unlocked "$1"; then
+ cryptsetup luksOpen "$1" "$2" --key-file="$3"
+ fi
+}
+
+echo "${crypttab}" | \
+ while read -r name raw key; do
+ key="${key%% *}"
+ key_mount=$(mountpoint_to_file "${key}")
+ mount_order=$(mountorder_to_device "#MAPDIR#/${name}")
+
+ if ${unmount}; then
+ do_unmount "${mount_order}"
+ do_crypt_close "${name}"
+ else
+ do_mount "${key_mount}"
+ do_crypt_open "${name}" "${raw}" "${key}"
+ do_unmount -l "${key_mount}"
+ do_mount "${mount_order}"
+ fi
+ done
+
+# End of file
diff --git a/cryptfs.in b/cryptfs.in
deleted file mode 100644
index 8b5d1a8..0000000
--- a/cryptfs.in
+++ /dev/null
@@ -1,150 +0,0 @@
-#!/bin/bash
-#
-# #RCDDIR#/cryptfs: mount/umount encrypted partitions
-#
-
-set -o pipefail
-
-cryptTab="$(grep -v "^\s*\(#\|\$\)" #ETCDIR#/crypttab | sed "s/^\s*//")"
-fsTab="$(grep -v "^\s*\(#\|\$\)" #ETCDIR#/fstab | sed "s/^\s*//")"
-
-cryptedFss="$(echo "${cryptTab}" | awk '{print "#MAPDIR#/"$1}')"
-neededKeyFss="$(
- for fs in $(echo "${fsTab}" | awk '{print $2}' | grep "^/")
- do
- if echo "${cryptTab}" | grep -q "^\S\+\s\+\S\+\s\+${fs}\(/\|\s\)"
- then
- echo "${fs}"
- fi
- done
-)"
-innermostFss="$(
- for fs in ${cryptedFss}
- do
- echo "${fsTab}" | \
- awk '{print $2}' | \
- grep "^$(
- echo "${fsTab}" | \
- grep "^${fs}\s" | \
- awk '{print $2}'
- )/"
- done
-)"
-
-case $1 in
-
-start)
-
- for neededKeyFs in ${neededKeyFss}
- do
- if ! mountpoint -q "${neededKeyFs}"
- then
- if echo "${fsTab}" | grep -q "^\S\+\s\+${neededKeyFs}\s\+fuse\.\(ssh\|ftp\)fs\s"
- then
- maxWait=120
- while [ ${maxWait} -gt 0 ] && ! /sbin/ip -o addr show scope global | grep -q '\S'
- do
- >&2 echo -ne "."
- sleep 1
- maxWait=$[${maxWait}-1]
- done
- host="$(
- echo "${fsTab}" | \
- grep -m1 "^\S\+\s\+${neededKeyFs}\s\+fuse\.\(ssh\|ftp\)fs\s" | \
- sed "s>^\([^ :@]*@\)\?\([^ :@]\+\)\(:\S\+\)\?\s\+${neededKeyFs}\s.*$>\2>"
- )"
- while [ ${maxWait} -gt 0 ] && ! /bin/ping6 -c1 ${host} &> /dev/null && ! /bin/ping -c1 ${host} &> /dev/null
- do
- >&2 echo -ne ","
- sleep 1
- maxWait=$[${maxWait}-1]
- done
- fi
- mount ${neededKeyFs} || exit $?
- fi
- done
-
- for ((cryptDeviceNum=0; cryptDeviceNum<$(echo "${cryptTab}" | wc -l); cryptDeviceNum++))
- do
- zeile="$(echo "${cryptTab}" | head -n$[${cryptDeviceNum}+1] | tail -n1)"
- name="$(echo "${zeile}" | awk '{print $1}')"
- device="$(echo "${zeile}" | awk '{print $2}')"
- if [[ "${device}" == "UUID="* ]]
- then
- device="#UUIDDIR#/${device#UUID=}"
- fi
- keyfile="$(echo "${zeile}" | awk '{print $3}')"
- if [ ! -b "#MAPDIR#/${name}" ]
- then
- cryptsetup luksOpen "${device}" "${name}" --key-file="${keyfile}" || exit $?
- fi
- done
-
- for cryptedFs in ${cryptedFss}
- do
- if ! findmnt --source "${cryptedFs}" > /dev/null
- then
- e2fsck "${cryptedFs}"
- mount "${cryptedFs}" || exit $?
- fi
- done
-
- for innermostFs in ${innermostFss}
- do
- if ! mountpoint -q "${innermostFs}"
- then
- mount "${innermostFs}" || exit $?
- fi
- done
-
- ;;
-
-stop)
-
- for innermostFs in ${innermostFss}
- do
- if mountpoint -q "${innermostFs}"
- then
- umount "${innermostFs}" || exit $?
- fi
- done
-
- for cryptedFs in ${cryptedFss}
- do
- if findmnt --source "${cryptedFs}" > /dev/null
- then
- umount "${cryptedFs}" || exit $?
- fi
- done
-
- for name in $(echo "${cryptTab}" | awk '{print $1}')
- do
- if [ -b "#MAPDIR#/${name}" ]
- then
- cryptsetup luksClose "${name}" || exit $?
- fi
- done
-
- for neededKeyFs in ${neededKeyFss}
- do
- if [ ! "${neededKeyFs}" == "/" ] && mountpoint -q "${neededKeyFs}"
- then
- umount ${neededKeyFs} || exit $?
- fi
- done
-
- ;;
-
- restart)
- $0 stop
- sleep 2
- $0 start
- ;;
-
-*)
- echo "usage: $0 [start|stop|restart]"
- ;;
-
-esac
-
-# End of file
diff --git a/cryptfs.rc.in b/cryptfs.rc.in
new file mode 100644
index 0000000..bf52b9e
--- /dev/null
+++ b/cryptfs.rc.in
@@ -0,0 +1,33 @@
+#!/bin/bash
+#
+# #RCDDIR#/cryptfs: mount/umount encrypted partitions
+#
+
+case "$1" in
+
+ start)
+
+ cryptfs
+
+ ;;
+
+ stop)
+
+ cryptfs -u
+
+ ;;
+
+ restart)
+
+ "$0" stop
+ "$0" start
+
+ *)
+
+ echo "usage: $0 [start|stop|restart]"
+
+ ;;
+
+esac
+
+# End of file
diff --git a/cryptfs.service.in b/cryptfs.service.in
new file mode 100644
index 0000000..be1003e
--- /dev/null
+++ b/cryptfs.service.in
@@ -0,0 +1,13 @@
+[Unit]
+Description=Decrypt and mount encrypted partitions.
+Requires=network-online.target local-fs.target
+After=network-online.target local-fs.target
+
+[Service]
+Type=oneshot
+RemainAfterExit=yes
+ExecStart=#BINDIR#/cryptfs
+ExecStop=#BINDIR#/cryptfs -u
+
+[Install]
+WantedBy=multi-user.target