=== modified file 'Makefile' --- Makefile 2008-08-12 23:13:41 +0000 +++ Makefile 2008-08-14 02:24:59 +0000 @@ -13,6 +13,12 @@ #COVERAGE=--coverage OPTIMIZE=-Os LANGUAGE=-std=gnu99 +# PREFIX=/usr/local +PREFIX=/usr +# CONFDIR=/usr/local/lib/mandos +CONFDIR=/etc/mandos +# MANDIR=/usr/local/man +MANDIR=/usr/share/man # Do not change these two CFLAGS=$(WARN) $(DEBUG) $(FORTIFY) $(COVERAGE) $(OPTIMIZE) $(LANGUAGE) @@ -26,11 +32,11 @@ --param man.authors.section.enabled 0 PLUGINS=plugins.d/password-prompt plugins.d/password-request -PROGS=mandos-client $(PLUGINS) -DOCS=mandos.8 mandos-client.8mandos mandos-keygen.8 \ +PROGS=plugin-runner $(PLUGINS) +DOCS=mandos.8 plugin-runner.8mandos mandos-keygen.8 \ plugins.d/password-request.8mandos \ plugins.d/password-prompt.8mandos mandos.conf.5 \ - mandos-clients.conf.5 + mandos-clients.conf.5 objects=$(shell for p in $(PROGS); do echo $${p}.o; done) @@ -47,7 +53,7 @@ %.8mandos: %.xml cd $(dir $^); $(DOCBOOKTOMAN) $(notdir $^) -mandos-client: mandos-client.o +plugin-runner: plugin-runner.o $(LINK.o) -lgnutls $(COMMON) $^ $(LOADLIBES) $(LDLIBS) -o $@ plugins.d/password-request: plugins.d/password-request.o @@ -75,7 +81,7 @@ run-client: all -mkdir keydir -./mandos-keygen --dir keydir - ./mandos-client --plugin-dir=plugins.d \ + ./plugin-runner --plugin-dir=plugins.d \ --options-for=password-request:--keydir=keydir run-server: @@ -84,77 +90,85 @@ install: install-server install-client install-server: doc - mkdir --mode=0755 --parents /etc/mandos - install --mode=0755 mandos /usr/sbin/mandos - install --mode=0644 --target-directory=/etc/mandos mandos.conf - install --mode=0640 --target-directory=/etc/mandos \ + mkdir --mode=0755 --parents $(CONFDIR) $(MANDIR)/man5 \ + $(MANDIR)/man8 + install --mode=0755 mandos $(PREFIX)/sbin/mandos + install --mode=0644 --target-directory=$(CONFDIR) mandos.conf + install --mode=0640 --target-directory=$(CONFDIR) \ clients.conf gzip --best --to-stdout mandos.8 \ - > /usr/share/man/man8/mandos.8.gz + > $(MANDIR)/man8/mandos.8.gz gzip --best --to-stdout mandos.conf.5 \ - > /usr/share/man/man5/mandos.conf.5.gz + > $(MANDIR)/man5/mandos.conf.5.gz gzip --best --to-stdout mandos-clients.conf.5 \ - > /usr/share/man/man5/mandos-clients.conf.5.gz + > $(MANDIR)/man5/mandos-clients.conf.5.gz install-client: all doc /usr/share/initramfs-tools/hooks/. - mkdir --mode=0755 --parents /usr/lib/mandos /etc/mandos - -mkdir --mode=0700 /usr/lib/mandos/plugins.d - chmod u=rwx,g=,o= /usr/lib/mandos/plugins.d - install --mode=0755 --target-directory=/usr/lib/mandos \ - mandos-client - install --mode=0755 --target-directory=/usr/sbin mandos-keygen + mkdir --mode=0755 --parents $(PREFIX)/lib/mandos $(CONFDIR) \ + $(MANDIR)/man8 + -mkdir --mode=0700 $(PREFIX)/lib/mandos/plugins.d + chmod u=rwx,g=,o= $(PREFIX)/lib/mandos/plugins.d + install --mode=0755 --target-directory=$(PREFIX)/lib/mandos \ + plugin-runner + install --mode=0755 --target-directory=$(PREFIX)/sbin \ + mandos-keygen install --mode=0755 \ - --target-directory=/usr/lib/mandos/plugins.d \ + --target-directory=$(PREFIX)/lib/mandos/plugins.d \ plugins.d/password-prompt install --mode=4755 \ - --target-directory=/usr/lib/mandos/plugins.d \ + --target-directory=$(PREFIX)/lib/mandos/plugins.d \ plugins.d/password-request install initramfs-tools-hook \ /usr/share/initramfs-tools/hooks/mandos install initramfs-tools-hook-conf \ /usr/share/initramfs-tools/conf-hooks.d/mandos + install initramfs-tools-script \ + /usr/share/initramfs-tools/scripts/local-top/mandos gzip --best --to-stdout mandos-keygen.8 \ - > /usr/share/man/man8/mandos-keygen.8.gz - gzip --best --to-stdout mandos-client.8mandos \ - > /usr/share/man/man8/mandos-client.8mandos.gz + > $(MANDIR)/man8/mandos-keygen.8.gz + gzip --best --to-stdout plugin-runner.8mandos \ + > $(MANDIR)/man8/plugin-runner.8mandos.gz gzip --best --to-stdout plugins.d/password-prompt.8mandos \ - > /usr/share/man/man8/password-prompt.8mandos.gz + > $(MANDIR)/man8/password-prompt.8mandos.gz gzip --best --to-stdout plugins.d/password-request.8mandos \ - > /usr/share/man/man8/password-request.8mandos.gz - -/usr/sbin/mandos-keygen + > $(MANDIR)/man8/password-request.8mandos.gz + -$(PREFIX)/sbin/mandos-keygen update-initramfs -k all -u uninstall: uninstall-server uninstall-client -uninstall-server: /usr/sbin/mandos - -rm --force /usr/sbin/mandos /usr/share/man/man8/mandos.8.gz \ - /usr/share/man/man5/mandos.conf.5.gz \ - /usr/share/man/man5/mandos-clients.conf.5.gz - -rmdir /etc/mandos +uninstall-server: $(PREFIX)/sbin/mandos + -rm --force $(PREFIX)/sbin/mandos \ + $(MANDIR)/man8/mandos.8.gz \ + $(MANDIR)/man5/mandos.conf.5.gz \ + $(MANDIR)/man5/mandos-clients.conf.5.gz + -rmdir $(CONFDIR) uninstall-client: -# Refuse to uninstall client if /etc/crypttab is configured to use it - ! grep --regexp='^ *[^ #].*keyscript=/usr/lib/mandos/mandos-client' \ +# Refuse to uninstall client if /etc/crypttab is explicitly configured +# to use it. + ! grep --regexp='^ *[^ #].*keyscript=[^,=]*/mandos/' \ /etc/crypttab - -rm --force /usr/sbin/mandos-keygen \ - /usr/lib/mandos/mandos-client \ - /usr/lib/mandos/plugins.d/password-prompt \ - /usr/lib/mandos/plugins.d/password-request \ + -rm --force $(PREFIX)/sbin/mandos-keygen \ + $(PREFIX)/lib/mandos/plugin-runner \ + $(PREFIX)/lib/mandos/plugins.d/password-prompt \ + $(PREFIX)/lib/mandos/plugins.d/password-request \ /usr/share/initramfs-tools/hooks/mandos \ /usr/share/initramfs-tools/conf-hooks.d/mandos \ - /usr/share/man/man8/mandos-client.8mandos.gz \ - /usr/share/man/man8/mandos-keygen.8.gz \ - /usr/share/man/man8/password-prompt.8mandos.gz \ - /usr/share/man/man8/password-request.8mandos.gz - -rmdir /usr/lib/mandos/plugins.d /usr/lib/mandos \ - /etc/mandos/plugins.d /etc/mandos + $(MANDIR)/man8/plugin-runner.8mandos.gz \ + $(MANDIR)/man8/mandos-keygen.8.gz \ + $(MANDIR)/man8/password-prompt.8mandos.gz \ + $(MANDIR)/man8/password-request.8mandos.gz + -rmdir $(PREFIX)/lib/mandos/plugins.d $(CONFDIR)/plugins.d \ + $(PREFIX)/lib/mandos $(CONFDIR) + update-initramfs -k all -u purge: purge-server purge-client purge-server: uninstall-server - -rm --force /etc/mandos/mandos.conf /etc/mandos/clients.conf - -rmdir /etc/mandos + -rm --force $(CONFDIR)/mandos.conf $(CONFDIR)/clients.conf + -rmdir $(CONFDIR) purge-client: uninstall-client - -rm --force /etc/mandos/seckey.txt /etc/mandos/pubkey.txt - -rmdir /etc/mandos /etc/mandos/plugins.d + -rm --force $(CONFDIR)/seckey.txt $(CONFDIR)/pubkey.txt + -rmdir $(CONFDIR) $(CONFDIR)/plugins.d === modified file 'TODO' --- TODO 2008-08-12 23:13:41 +0000 +++ TODO 2008-08-14 02:24:59 +0000 @@ -26,6 +26,8 @@ ** use strsep instead of strtok? ** use config file in addition to arguments ** pass things in environment, like device name, etc +** Keydir move: /etc/mandos -> /etc/keys/mandos + Must create in preinst if not pre-depending on cryptsetup * Password-request ** [#A] Man page: man8/password-request.8mandos @@ -63,6 +65,9 @@ * Password-prompt ** [#A] Man page: man8/password-prompt.8mandos +** Show getenv("cryptsource") and getenv("crypttarget") if set + cryptsource will be the device, like "/dev/sda3", and crypttarget + will be the device mapper name, like "sda3_crypt". *** DESCRIPTION Move options to new OPTIONS section. *** EXIT STATUS === modified file 'initramfs-tools-hook' --- initramfs-tools-hook 2008-08-12 19:47:50 +0000 +++ initramfs-tools-hook 2008-08-14 02:24:59 +0000 @@ -1,52 +1,17 @@ #!/bin/sh -# -# This is an example hook script. It will be run by 'mkinitramfs' -# when it creates the image. It's job is to decide which files to -# install, then install them into the staging area, where the -# initramfs is being created. This happens when a new 'linux-image' -# package is installed, or when the administrator runs 'mkinitramfs' -# by hand to update an initramfs image. -# -# TODO: What about the case where you install something that should be -# added to the initramfs, but the linux-image it relates to has -# already been installed previously? Does this happen often -# enough that it needs to be handled? How can it be handled? -# -# * Think about the 'usplash'. The initramfs will need to be -# updated if a theme change or update is desired. Maybe it -# should not be totally automatic, but offered on upgrade -# predicated on a user response to a debconf question? That -# issue needs to be explored and a solution specified. -# -# * Do not assume that any needed subdirectories have been created -# yet, but don't bail out if they are already there. -# -# * All of the standard system tools are available, of course, since -# this hook is running in the real system, not the initramfs. -# -# * TODO: ... ? Anything else to tell them in this bullet-list? -# +# This script will be run by 'mkinitramfs' when it creates the image. +# Its job is to decide which files to install, then install them into +# the staging area, where the initramfs is being created. This +# happens when a new 'linux-image' package is installed, or when the +# administrator runs 'update-initramfs' by hand to update an initramfs +# image. -# # The environment contains at least: # -# CONFDIR -- usually /etc/mkinitramfs, can be set on mkinitramfs -# command line. -# -# DESTDIR -- The staging directory where we are building the image. -# -# TODO: Decide what environment variables are meaningful and defined -# in this context, then document them as part of the interface. -# -# TODO: May need a version_compare function for comparison of VERSION? - - -# -# List the soft prerequisites here. This is a space separated list of -# names, of scripts that are in the same directory as this one, that -# must be run before this one can be. -# +# DESTDIR -- The staging directory where the image is being built. + +# No initramfs pre-requirements PREREQ="cryptroot" prereqs() @@ -62,32 +27,38 @@ ;; esac - -# You can do anything you need to from here on. -# - -# Source the optional 'hook-functions' scriptlet, if you need the -# functions defined within it. Read it to see what is available to -# you. It contains functions for copying dynamically linked program -# binaries, and kernel modules into the DESTDIR. -# . /usr/share/initramfs-tools/hook-functions +if [ -d /usr/lib/mandos ]; then + prefix=/usr +elif [ -d /usr/local/lib/mandos ]; then + prefix=/usr/local +else + # Mandos not found + exit 1 +fi + +# The Mandos network client uses the network auto_add_modules net -# force_load tg3 +# The Mandos network client uses IPv6 force_load ipv6 +# These are directories inside the initrd CONFDIR="/conf/conf.d/mandos" -DESTCONFDIR="${DESTDIR}${CONFDIR}" -mkdir --parents "${DESTCONFDIR}" -PLUGINDIR="${CONFDIR}/plugins.d" +MANDOSDIR="/lib/mandos" +PLUGINDIR="${MANDOSDIR}/plugins.d" + +# Make directories +mkdir --parents "${DESTDIR}${CONFDIR}" mkdir --parents "${DESTDIR}${PLUGINDIR}" -# We don't need to copy_exec mandos-client, hooks/cryptroot will do -# that. That will not copy the plugins, however, so we do that here. - -# The standard plugins -for file in /usr/lib/mandos/plugins.d/*; do +# Copy the Mandos plugin runner +copy_exec "$prefix"/lib/mandos/plugin-runner "${DESTDIR}${MANDOSDIR}" + +# Copy the plugins + +# Copy the packaged plugins +for file in "$prefix"/lib/mandos/plugins.d/*; do base="`basename \"$file\"`" # Is this plugin overridden? if [ -e "/etc/mandos/plugins.d/$base" ]; then @@ -99,7 +70,7 @@ esac done -# Any user-supplied plugins +# Copy any user-supplied plugins for file in /etc/mandos/plugins.d/*; do base="`basename \"$file\"`" case "$base" in @@ -109,7 +80,8 @@ done # GPGME needs /usr/bin/gpg -if [ -n "`ls \"${DESTDIR}\"/usr/lib/libgpgme.so* 2>/dev/null`" ]; then +if ! [ -e "${DESTDIR}/usr/bin/gpg" ] \ + && [ -n "`ls \"${DESTDIR}\"/usr/lib/libgpgme.so* 2>/dev/null`" ]; then copy_exec /usr/bin/gpg fi @@ -118,30 +90,37 @@ if [ -d "$file" ]; then continue fi - cp --archive --sparse=always "$file" "${DESTCONFDIR}" + cp --archive --sparse=always "$file" "${DESTDIR}${CONFDIR}" done # Create key ring files gpg --no-random-seed-file --quiet --batch --no-tty \ - --no-default-keyring --no-options --homedir "${DESTCONFDIR}" \ - --no-permission-warning --import-options import-minimal \ - --import "${DESTCONFDIR}/seckey.txt" -chown nobody "${DESTCONFDIR}/secring.gpg" + --no-default-keyring --no-options \ + --homedir "${DESTDIR}${CONFDIR}" --no-permission-warning \ + --import-options import-minimal \ + --import "${DESTDIR}${CONFDIR}/seckey.txt" +chown nobody "${DESTDIR}${CONFDIR}/secring.gpg" -# /keyscripts/mandos-client will drop priviliges, but needs access to -# its plugin directory. However, since almost all files in initrd -# have been created with umask 027, this opening of permissions is needed. +# /lib/mandos/plugin-runner will drop priviliges, but needs access to +# its plugin directory and its config file. However, since almost all +# files in initrd have been created with umask 027, this opening of +# permissions is needed. # # (The umask is not really intended to affect the files inside the -# initrd, but the initrd.img file itself, since it now contains secret -# key files. There is, however, no other way to set the permission of -# the initrd.img file without a race condition. This umask is set by -# "/usr/share/initramfs-tools/conf-hooks.d/mandos".) +# initrd; it is intended to affect the initrd.img file itself, since +# it now contains secret key files. There is, however, no other way +# to set the permission of the initrd.img file without a race +# condition. This umask is set by "initramfs-tools-hook-conf", +# installed as "/usr/share/initramfs-tools/conf-hooks.d/mandos".) # -full="${PLUGINDIR}" -while [ "$full" != "/" ]; do - chmod a+rX "${DESTDIR}$full" - full="`dirname \"$full\"`" +for full in "${PLUGINDIR}" "${CONFDIR}"; do + while [ "$full" != "/" ]; do + chmod a+rX "${DESTDIR}$full" + full="`dirname \"$full\"`" + done done + +# Reset some other things to sane permissions which we have +# inadvertently affected with our umask setting. for dir in / /bin /etc /keyscripts /sbin /scripts /usr /usr/bin; do chmod a+rX "${DESTDIR}$dir" done === added file 'initramfs-tools-script' --- initramfs-tools-script 1970-01-01 00:00:00 +0000 +++ initramfs-tools-script 2008-08-14 02:24:59 +0000 @@ -0,0 +1,74 @@ +#!/bin/sh -e +# +# This script will run in the initrd environment at boot and edit +# /conf/conf.d/cryptroot to set /lib/mandos/plugin-runner as keyscript +# when no other keyscript is set, before cryptsetup. +# + +# This script should be installed as +# "/usr/share/initramfs-tools/scripts/local-top/mandos" which will +# eventually be "/scripts/local-top/mandos" in the initrd.img file. + +# No initramfs pre-requirements; we must instead run BEFORE cryptroot. +# This is not a problem, since cryptroot forces itself to run LAST. +PREREQ="" +prereqs() +{ + echo "$PREREQ" +} + +case $1 in +prereqs) + prereqs + exit 0 + ;; +esac + +test -w /conf/conf.d/cryptroot + +# Do not replace cryptroot file unless we need to. +replace_cryptroot=no + +# Our keyscript +mandos=/lib/mandos/plugin-runner + +# parse /conf/conf.d/cryptroot. Format: +# target=sda2_crypt,source=/dev/sda2,key=none,keyscript=/foo/bar/baz +exec 3>/conf/conf.d/cryptroot.mandos +while read options; do + newopts="" + # Split option line on commas + old_ifs="$IFS" + IFS="$IFS," + for opt in $options; do + # Find the keyscript option, if any + case "$opt" in + keyscript=*) + keyscript="${opt#keyscript=}" + newopts="$newopts,$opt" + ;; + "") : ;; + *) + newopts="$newopts,$opt" + ;; + esac + done + IFS="$old_ifs" + unset old_ifs + # If there was no keyscript option, add one. + if [ -z "$keyscript" ]; then + replace_cryptroot=yes + newopts="$newopts,keyscript=$mandos" + fi + newopts="${newopts#,}" + echo "$newopts" >&3 +done < /conf/conf.d/cryptroot +exec 3>&- + +# If we need to, replace the old cryptroot file with the new file. +if [ "$replace_cryptroot" = yes ]; then + mv /conf/conf.d/cryptroot /conf/conf.d/cryptroot.mandos-old + mv /conf/conf.d/cryptroot.mandos /conf/conf.d/cryptroot +else + rm /conf/conf.d/cryptroot.mandos +fi === renamed file 'mandos-client.c' => 'plugin-runner.c' --- mandos-client.c 2008-08-12 16:47:22 +0000 +++ plugin-runner.c 2008-08-14 02:24:59 +0000 @@ -66,7 +66,7 @@ #define BUFFER_SIZE 256 -const char *argp_program_version = "mandos-client 1.0"; +const char *argp_program_version = "plugin-runner 1.0"; const char *argp_program_bug_address = ""; struct process; @@ -186,7 +186,7 @@ } int main(int argc, char *argv[]){ - const char *plugindir = "/conf/conf.d/mandos/plugins.d"; + const char *plugindir = "/lib/mandos/plugins.d"; size_t d_name_len; DIR *dir = NULL; struct dirent *dirst; === renamed file 'mandos-client.xml' => 'plugin-runner.xml' --- mandos-client.xml 2008-08-10 19:14:12 +0000 +++ plugin-runner.xml 2008-08-14 02:24:59 +0000 @@ -4,7 +4,7 @@ - + ]> === added file 'plugins.d/usplash' --- plugins.d/usplash 1970-01-01 00:00:00 +0000 +++ plugins.d/usplash 2008-08-14 02:24:59 +0000 @@ -0,0 +1,42 @@ +#!/bin/sh -e + +# If not on a tty, then get rid of possibly disrupting stderr output +if ! tty -s; then + exec 2>/dev/null +fi + +test -x /sbin/usplash + +usplash="`pidof usplash -o $$`" +test -n "$usplash" + +# We get some variables from cryptsetup: +# $cryptsource the device node, like "/dev/sda3" +# $crypttarget the device mapper name, like "sda3_crypt". + +prompt="Enter passphrase to unlock" +if [ -n "$crypttarget" ]; then + prompt="$prompt the disk $crypttarget" +fi +if [ -n "$cryptsource" ]; then + prompt="$prompt ($cryptsource)" +fi + +splash_input_password(){ + test -p /dev/.initramfs/usplash_outfifo || return 1 + /sbin/usplash_write "INPUTQUIET $1" || return 1 + cat /dev/.initramfs/usplash_outfifo 2> /dev/null || return 1 +} + +# Usplash keeps waiting for input even if some other plugin provided +# the password, so we must kill it +trap "kill -TERM $usplash; sleep 2; kill -KILL $usplash; + kill -TERM $$" TERM HUP + +password="`splash_input_password \"$prompt: \" password`" + +trap - TERM + +/sbin/usplash_write "TIMEOUT 15" + +echo -n "$password"