Skip to content

Commit

Permalink
Improved portability (configure script!)
Browse files Browse the repository at this point in the history
Moved post-unlock actions to a reap-success script to make it easier to customize.
Made unlock much more paranoid, more checking.
specfile (mostly) passes rpmlint
Verified on CentOS6/7
  • Loading branch information
mdcurtis committed Aug 10, 2014
1 parent aeed5a8 commit ba9d573
Show file tree
Hide file tree
Showing 18 changed files with 234 additions and 91 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
*.o
*~
/build
config.mk
12 changes: 5 additions & 7 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,24 +1,22 @@

export VERSION=1.0.2

export OLDDRACUT=0
export LIBDIR=/lib
export ROOTHOME=/root/
include config.mk

export DESTDIR=
export MODULEDIR=${DESTDIR}/usr/share/dracut/modules.d/
export MODULEDIR=${DESTDIR}/usr/$(DRACUT_MODULEDIR)

SUBDIRS=modules/earlyssh modules/cryptsettle-patch src

ifeq ($(OLDDRACUT),1)
ifeq ($(NEED_CRYPTSETTLE),1)
CRYPTSETTLE=modules/cryptsettle-patch
else
CRYPTSETTLE=
endif

.PHONY: src dist $(SUBDIRS)

all: $(CRYPTSETTLE) modules/earlyssh
all: src $(CRYPTSETTLE) modules/earlyssh

install: src modules/earlyssh $(CRYPTSETTLE)
mkdir -p $(DESTDIR)/etc/dracut.conf.d/
Expand All @@ -29,7 +27,7 @@ clean: src modules/earlyssh modules/cryptsettle-patch
dist:
$(MAKE) clean
mkdir -p tmp/dracut-earlyssh-${VERSION}
cp -R src modules Makefile earlyssh.conf COPYING README.md tmp/dracut-earlyssh-${VERSION}
cp -R configure src modules Makefile earlyssh.conf COPYING README.md tmp/dracut-earlyssh-${VERSION}
tar -C tmp -czf ../dracut-earlyssh-${VERSION}.tgz dracut-earlyssh-${VERSION}
rm -rf tmp

Expand Down
53 changes: 28 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,12 @@ for automating the unlock process. Finally, there is a RPM spec file which shou
it very easy to deploy (and doesn't introduce a runtime dependency on a compiler).

Users are strictly authenticated by provided SSH public keys. These can be either:
root's ~/.ssh/authorized_keys or a custom file ("dropbear_acl" option).
root's ~/.ssh/authorized_keys or a custom file ("dropbear_acl" option). Depending
on your environment, it may make sense to make the preboot authorized_keys file
quite different to the normal one.

See dropbear(8) manpage for full list of supported restrictions there (which are
fairly similar to openssh). If using in combination with the unlock utility (see below), a useful
restriction may be to make /bin/unlock a 'forced command' in SSH.
fairly similar to openssh). If using in combination with the unlock utility (see below), a useful restriction may be to make /bin/unlock a 'forced command' in SSH.


### Usage
Expand All @@ -32,15 +33,8 @@ First of all, you must have dropbear. CentOS/RHEL users can get this from EPEL.

You will need gcc and libblkid(-devel) installed to build console_auth and the unlock tools.

- You should be able to build everything by running make/make install. There
are some additional variables to make that you may need to override.
These are
OLDDRACUT Defaults to 0, set to 1 if using an old version of Dracut (e.g. 004)
ROOTHOME root's home on the initrd. On RHEL6 this is /, Exherbo apparently /root
Note that this is NOT the same as root's home in the normal system!
LIBDIR On RHEL6 and above /lib64, otherwise /lib
For example (RHEL6):
make OLDDRACUT=1 ROOTHOME=/ LIBDIR=/lib64 install
- You should be able to build everything by running configure, make, make install as usual.
The configure script should detect and compensate for the various differences in dracut versions.

- The provided RPM spec file should take care of these things for RHEL6/7

Expand All @@ -58,10 +52,10 @@ You will need gcc and libblkid(-devel) installed to build console_auth and the u
Simplest way might be just passing `ip=dhcp rd.neednet=1` on cmdline, if dhcp
can assign predictable ip and pass proper routes.

On older Dracut's, a more tortuous route is required. Networking is only configured
if you have configured a network root. In order to work around this, the system will
install a dummyroot script (if OLDDRACUT=1 at build-time). The cmdline for these versions
should be `ip=dhcp netroot=dummy`.
On older Dracut versions (e.g. 004 in RHEL6), networking is only configured
if you have configured a network root. In order to work around this, dracut-earlyssh
system will install a dummyroot script (if it detects dracut v004 at build-time).
The cmdline for these versions should be `ip=dhcp netroot=dummy`.

- Run dracut to build initramfs with the thing.

Expand Down Expand Up @@ -120,7 +114,7 @@ The `unlock` binary takes a passphrase in stdin, reads `/etc/crypttab` and attem
call `cryptsetup luksOpen` on all luks-encrypted drives that don't have a keyfile,
passing the passphrase that unlock got in stdin to luksOpen.

What this means in practise is you can do:
What this means in practice is you can do:
```console
% ssh root@remote.server -p 2222 unlock < passwordFile
```
Expand Down Expand Up @@ -149,10 +143,11 @@ successfully. This means:
In short, if you have more than one volume in /etc/crypttab, you will need to be careful
about how use this tool.

If the process is successful, `unlock` will kill cryptroot-ask, which, at least on RHEL,
forces the boot process to proceed. Note that the plymouth splash screen (if you happen to be
watching the console...) will still appear to ask for your password, but this is an artificat.
Disable plymouth (rhgb command line) if this annoys you.
If the process is successful, `unlock` will launch the script `/sbin/unlock-reap-success`.
This can be found in the modules.d/earlyssh folder. This will attempt to kill systemd-cryptsetup,
and failing that, attempt to kill cryptroot-ask. On RHEL6 & 7, this aborts the builtin decrypt
password request processes and allows the boot process to proceed.
Note that the plymouth splash screen on RHEL6 (if you happen to be watching the console...) will still appear to ask for your password, but this is an artificat. Disable plymouth (rhgb command line) if this annoys you.

### dracut.conf parameters

Expand Down Expand Up @@ -253,12 +248,14 @@ either enable "debug" dracut module or add `dracut_install netstat ip` line to
naming mixup, no traffic (e.g. unrelated connection issue), etc.


### Bad things
### TODO

- Limited testing. Original (before fork) only tested with customized source-based distro
([Exherbo](http://exherbo.org/)), current version only tested with CentOS 6.5 and CentOS 7.0.
However, the configure script should allow it to be fairly adaptable to a range of distro's.

- Only tested with customized source-based distro
([Exherbo](http://exherbo.org/)), no idea how easy it is to use with generic
debian or ubuntu.
- Need to document & form recommendations on how to unlock multiple systems using the unlock script.
Something with gpg-agent seems like it may work well.

- `check()` in module_setup.sh should probably not be empty no-op.

Expand All @@ -270,6 +267,12 @@ naming mixup, no traffic (e.g. unrelated connection issue), etc.
- Some notes on threat model where such thing might be useful would be nice, so
people won't assume too much.

- Remote initramfs hash verification, etc. See above point, a determined attacker could potentially
circumvent or fake the outputs of various commands in order to pretend that the verification had succeeded.
One possibility would be to dynamically upload a special hashing binary that has a compiled-in nonce. This
would be hard to fake, I think. However, it would require a compiler for each supported architecture on the
verification machine.


### Based on code, examples and ideas from

Expand Down
128 changes: 128 additions & 0 deletions configure
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
#!/bin/bash

while [[ $# -gt 0 ]]; do
case $1 in
--print-moduledir)
[[ -f config.mk ]] && source config.mk
[[ -z $DRACUT_MODULEDIR ]] && exit 1
echo $DRACUT_MODULEDIR
exit 0
;;
--dracut)
DRACUT=$2
shift
;;
--root-home)
ROOTHOME=$2
shift
;;
esac
shift
done

echo -n "Searching for dracut... "
if [[ -z $DRACUT ]]; then
DRACUT=$(which dracut)
if [[ $? -eq 0 ]]; then
echo $DRACUT
else
echo "not found"
exit 1
fi
else
echo "[provided] $DRACUT"
fi

echo -n "Checking dracut version... "
DRACUT_VERSION=$(${DRACUT} --help | egrep "Version:[ \t]+[0-9]+" | egrep -o [0-9]+)
if [[ $? -ne 0 ]]; then
echo -n "[old version - fallback] "
DRACUT_VERSION=004
else
DRACUT_VERSION=$(echo ${DRACUT_VERSION} | cut -f 1 -d " ")
fi
echo ${DRACUT_VERSION}

echo -n "Checking dracut module prefix... "
DRACUT_MODULEDIR=""
if [[ -d /usr/lib/dracut/modules.d ]]; then
DRACUT_MODULEDIR=lib/dracut/modules.d
elif [[ -d /usr/share/dracut/modules.d ]]; then
DRACUT_MODULEDIR=share/dracut/modules.d
else
echo "failed"
exit 1
fi
echo ${DRACUT_MODULEDIR}

NEED_CRYPTSETTLE=0
CRYPTPARSE=/usr/${DRACUT_MODULEDIR}/90crypt/parse-crypt.sh
if [[ -f $CRYPTPARSE ]]; then
echo -n "Checking whether crypt-settle patch is needed... "
grep -c -- "--settled" ${CRYPTPARSE} >/dev/null
if [[ $? -ne 0 ]]; then
NEED_CRYPTSETTLE=1
echo "yes"
else
echo "no"
fi
fi

echo -n "Checking for old-style modules... "
OLDSTYLE=1
if [[ -f /usr/${DRACUT_MODULEDIR}/99base/module-setup.sh ]]; then
OLDSTYLE=0
echo "no"
else
echo "yes"
fi

echo -n "Checking for root's home... "
if [[ -z ${ROOTHOME} ]]; then
ROOTHOME=/
module=module-setup.sh
[[ ${OLDSTYLE} -eq 1 ]] && module=install
MODULEBASE=/usr/${DRACUT_MODULEDIR}/99base/${module}
if [[ -f $MODULEBASE ]]; then
grep -c "root:" ${MODULEBASE} >/dev/null
if [[ $? -eq 0 ]]; then
ROOTHOME=/root
fi
fi
else
echo -n "[provided] "
fi
echo ${ROOTHOME}


echo -n "Checking for libnss_files.so ... "
DIRS="/usr/lib /usr/lib64 /lib64 /lib"
NSSFILES=""
for dir in ${DIRS}; do
for check in ${dir}/libnss_files.so*; do
if [[ -f $check ]]; then
NSSFILES=${check}
break
fi
done
done
if [[ -z $NSSFILES ]]; then
echo "not found"
exit 1
else
echo $NSSFILES
fi

OLDDRACUT=0
[[ $DRACUT_VERSION -le 4 ]] && OLDDRACUT=1

cat >config.mk <<EOF
export DRACUT=${DRACUT}
export DRACUT_VERSION=${DRACUT_VERSION}
export DRACUT_MODULEDIR=${DRACUT_MODULEDIR}
export NEED_CRYPTSETTLE=${NEED_CRYPTSETTLE}
export ROOTHOME=${ROOTHOME}
export OLDSTYLE=${OLDSTYLE}
export NSSFILES=${NSSFILES}
export OLDDRACUT=${OLDDRACUT}
EOF
24 changes: 8 additions & 16 deletions dracut-earlyssh.spec
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
%define olddracut 0

%if 0%{?rhel} && 0%{?rhel} <= 6
%define olddracut 1
%endif

Summary: A dracut module that adds ssh to the boot image (also known as earlyssh)
Name: dracut-earlyssh
Version: 1.0.2
Release: 1
License: GPL
Release: 4
License: GPLv2+
Source: dracut-earlyssh-%{version}.tgz
Packager: Michael Curtis <michael@moltenmercury.org>
BuildRequires: dracut
Expand All @@ -24,28 +18,26 @@ Requires: openssh
A dracut module that includes dropbear in the boot image, along with some
helper utilities for unlocking encrypted drives over a remote connection.

Please read the README and configuration parameters in /etc/dracut.conf.d/earlyssh.conf
before use.
Please read the README and configuration parameters in
/etc/dracut.conf.d/earlyssh.conf before use.

%prep
%setup
./configure

%build
make LIBDIR=/lib64 ROOTHOME=/ OLDDRACUT=%{olddracut}
make

%install
make install OLDDRACUT=%{olddracut} DESTDIR=$RPM_BUILD_ROOT
make install DESTDIR=$RPM_BUILD_ROOT
cp README.md README

%files
%defattr(-,root,root,0755)
%doc README COPYING
%config(noreplace) %{_sysconfdir}/dracut.conf.d/earlyssh.conf
%{_libexecdir}/dracut-earlyssh
%{_datadir}/dracut/modules.d/60earlyssh
%if %{olddracut}
%{_datadir}/dracut/modules.d/91cryptsettle-patch
%endif
%{_prefix}/*/dracut/modules.d/*



6 changes: 6 additions & 0 deletions modules/check.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/bin/bash

source $(dirname $0)/module-setup.sh

check
exit $?
11 changes: 6 additions & 5 deletions modules/cryptsettle-patch/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ all:
clean:


install: install.sh check.sh
install: ../install.sh ../check.sh module-setup.sh
mkdir -p $(INSTDIR)
cp install.sh $(INSTDIR)/install
cp check.sh $(INSTDIR)/check
chmod 755 $(INSTDIR)/{install,check}

install -m 0755 module-setup.sh $(INSTDIR)/
ifeq ($(OLDSTYLE),1)
install -m 0755 ../install.sh $(INSTDIR)/install
install -m 0755 ../check.sh $(INSTDIR)/check
endif
4 changes: 0 additions & 4 deletions modules/cryptsettle-patch/check.sh

This file was deleted.

7 changes: 0 additions & 7 deletions modules/cryptsettle-patch/install.sh

This file was deleted.

15 changes: 15 additions & 0 deletions modules/cryptsettle-patch/module-setup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/bin/bash

check() {
return 0
}

install() {
for file in ${initdir}/cmdline/*parse-crypt.sh; do
dinfo "Patching ${file}"
sed -i -e "s!/sbin/initqueue!/sbin/initqueue --settled!g" ${file}
done

return 0
}

Loading

0 comments on commit ba9d573

Please sign in to comment.