/mandos/trunk

To get this branch, use:
bzr branch http://bzr.recompile.se/loggerhead/mandos/trunk
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
#!/bin/sh

# 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 an
# administrator runs 'update-initramfs' by hand to update an initramfs
# image.

# The environment contains at least:
#
#  DESTDIR -- The staging directory where the image is being built.

# No initramfs pre-requirements
PREREQ="cryptroot"

prereqs()
{
	echo "$PREREQ"
}

case $1 in
# get pre-requisites
prereqs)
	prereqs
	exit 0
	;;
esac

. /usr/share/initramfs-tools/hook-functions

for d in /usr/lib \
    "/usr/lib/`dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null`" \
    "`rpm --eval='%{_libdir}' 2>/dev/null`" /usr/local/lib; do
    if [ -d "$d"/mandos ]; then
	libdir="$d"
	break
    fi
done
if [ -z "$libdir" ]; then
    # Mandos not found
    exit 1
fi

for d in /etc/keys/mandos /etc/mandos/keys; do
    if [ -d "$d" ]; then
	keydir="$d"
	break
    fi
done
if [ -z "$keydir" ]; then
    # Mandos key directory not found
    exit 1
fi

set `{ getent passwd _mandos \
    || getent passwd nobody \
    || echo ::65534:65534:::; } \
    | cut --delimiter=: --fields=3,4 --only-delimited \
    --output-delimiter=" "`
mandos_user="$1"
mandos_group="$2"

# The Mandos network client uses the network
auto_add_modules net
# The Mandos network client uses IPv6
force_load ipv6

# These are directories inside the initrd
CONFDIR="/conf/conf.d/mandos"
MANDOSDIR="/lib/mandos"
PLUGINDIR="${MANDOSDIR}/plugins.d"
PLUGINHELPERDIR="${MANDOSDIR}/plugin-helpers"
HOOKDIR="${MANDOSDIR}/network-hooks.d"

# Make directories
install --directory --mode=u=rwx,go=rx "${DESTDIR}${CONFDIR}" \
	"${DESTDIR}${MANDOSDIR}" "${DESTDIR}${HOOKDIR}"
install --owner=${mandos_user} --group=${mandos_group} --directory \
	--mode=u=rwx "${DESTDIR}${PLUGINDIR}" \
	"${DESTDIR}${PLUGINHELPERDIR}"

copy_exec "$libdir"/mandos/mandos-to-cryptroot-unlock "${MANDOSDIR}"

# Copy the Mandos plugin runner
copy_exec "$libdir"/mandos/plugin-runner "${MANDOSDIR}"

# Copy the plugins

# Copy the packaged plugins
for file in "$libdir"/mandos/plugins.d/*; do
    base="`basename \"$file\"`"
    # Is this plugin overridden?
    if [ -e "/etc/mandos/plugins.d/$base" ]; then
	continue
    fi
    case "$base" in
	*~|.*|\#*\#|*.dpkg-old|*.dpkg-bak|*.dpkg-new|*.dpkg-divert)
	    : ;;
	"*") echo "W: Mandos client plugin directory is empty." >&2 ;;
	*) copy_exec "$file" "${PLUGINDIR}" ;;
    esac
done

# Copy the packaged plugin helpers
for file in "$libdir"/mandos/plugin-helpers/*; do
    base="`basename \"$file\"`"
    # Is this plugin overridden?
    if [ -e "/etc/mandos/plugin-helpers/$base" ]; then
	continue
    fi
    case "$base" in
	*~|.*|\#*\#|*.dpkg-old|*.dpkg-bak|*.dpkg-new|*.dpkg-divert)
	    : ;;
	"*") : ;;
	*) copy_exec "$file" "${PLUGINHELPERDIR}" ;;
    esac
done

# Copy any user-supplied plugins
for file in /etc/mandos/plugins.d/*; do
    base="`basename \"$file\"`"
    case "$base" in
	*~|.*|\#*\#|*.dpkg-old|*.dpkg-bak|*.dpkg-new|*.dpkg-divert)
	    : ;;
	"*") : ;;
	*) copy_exec "$file" "${PLUGINDIR}" ;;
    esac
done

# Copy any user-supplied plugin helpers
for file in /etc/mandos/plugin-helpers/*; do
    base="`basename \"$file\"`"
    case "$base" in
	*~|.*|\#*\#|*.dpkg-old|*.dpkg-bak|*.dpkg-new|*.dpkg-divert)
	    : ;;
	"*") : ;;
	*) copy_exec "$file" "${PLUGINHELPERDIR}" ;;
    esac
done

# Get DEVICE from initramfs.conf and other files
. /etc/initramfs-tools/initramfs.conf
for conf in /etc/initramfs-tools/conf.d/*; do
    if [ -n "`basename \"$conf\" \
	| grep '^[[:alnum:]][[:alnum:]\._-]*$' \
	| grep -v '\.dpkg-.*$'`" ]; then
	[ -f "${conf}" ] && . "${conf}"
    fi
done
export DEVICE

# Copy network hooks
for hook in /etc/mandos/network-hooks.d/*; do
    case "`basename \"$hook\"`" in
	"*") continue ;;
	*[!A-Za-z0-9_.-]*) continue ;;
	*) test -d "$hook" || copy_exec "$hook" "${HOOKDIR}" ;;
    esac
    if [ -x "$hook" ]; then
        # Copy any files needed by the network hook
	MANDOSNETHOOKDIR=/etc/mandos/network-hooks.d MODE=files \
	    VERBOSITY=0 "$hook" files | while read -r file target; do
	    if [ ! -e "${file}" ]; then
		echo "WARNING: file ${file} not found, requested by Mandos network hook '${hook##*/}'" >&2
	    fi
	    if [ -z "${target}" ]; then
		copy_exec "$file"
	    else
		copy_exec "$file" "$target"
	    fi
	done
        # Copy and load any modules needed by the network hook
	MANDOSNETHOOKDIR=/etc/mandos/network-hooks.d MODE=modules \
	    VERBOSITY=0 "$hook" modules | while read -r module; do
	    force_load "$module"
	done
    fi
done

# GPGME needs GnuPG
gpg=/usr/bin/gpg
libgpgme11_version="`dpkg-query --showformat='${Version}' --show libgpgme11`"
if dpkg --compare-versions "$libgpgme11_version" ge 1.5.0-0.1; then
    if [ -e /usr/bin/gpgconf ]; then
	if [ ! -e "${DESTDIR}/usr/bin/gpgconf" ]; then
	    copy_exec /usr/bin/gpgconf
	fi
	gpg="`/usr/bin/gpgconf|sed --quiet --expression='s/^gpg:[^:]*://p'`"
	gpgagent="`/usr/bin/gpgconf|sed --quiet --expression='s/^gpg-agent:[^:]*://p'`"
	# Newer versions of GnuPG 2 requires the gpg-agent binary
	if [ -e "$gpgagent" ] && [ ! -e "${DESTDIR}$gpgagent" ]; then
	    copy_exec "$gpgagent"
	fi
    fi
elif dpkg --compare-versions "$libgpgme11_version" ge 1.4.1-0.1; then
    gpg=/usr/bin/gpg2
fi
if [ ! -e "${DESTDIR}$gpg" ]; then
    copy_exec "$gpg"
fi
unset gpg
unset libgpgme11_version

# Config files
for file in /etc/mandos/plugin-runner.conf; do
    if [ -d "$file" ]; then
	continue
    fi
    cp --archive --sparse=always "$file" "${DESTDIR}${CONFDIR}"
done

if [ ${mandos_user} != 65534 ]; then
    sed --in-place --expression="1i--userid=${mandos_user}" \
	"${DESTDIR}${CONFDIR}/plugin-runner.conf"
fi

if [ ${mandos_group} != 65534 ]; then
    sed --in-place --expression="1i--groupid=${mandos_group}" \
	"${DESTDIR}${CONFDIR}/plugin-runner.conf"
fi

# Key files
for file in "$keydir"/*; do
    if [ -d "$file" ]; then
	continue
    fi
    case "$file" in
	*~|.*|\#*\#|*.dpkg-old|*.dpkg-bak|*.dpkg-new|*.dpkg-divert)
	    : ;;
	"*") : ;;
	*)
	    cp --archive --sparse=always "$file" \
	       "${DESTDIR}${CONFDIR}"
	    chown ${mandos_user}:${mandos_group} \
		  "${DESTDIR}${CONFDIR}/`basename \"$file\"`"
	    ;;
    esac
done
# Use Diffie-Hellman parameters file if available
if [ -e "${DESTDIR}${CONFDIR}"/dhparams.pem ]; then
    sed --in-place \
	--expression="1i--options-for=mandos-client:--dh-params=${CONFDIR}/dhparams.pem" \
	"${DESTDIR}/${CONFDIR}/plugin-runner.conf"
fi

# /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; 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-conf", installed
# as "/usr/share/initramfs-tools/conf.d/mandos-conf".)
# 
for full in "${MANDOSDIR}" "${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
    if [ -d "${DESTDIR}$dir" ]; then
	chmod a+rX "${DESTDIR}$dir"
    fi
done
for dir in "${DESTDIR}"/lib* "${DESTDIR}"/usr/lib*; do
    if [ -d "$dir" ]; then
	find "$dir" \! -perm -u+rw,g+r -prune -or \! -type l -print0 \
	    | xargs --null --no-run-if-empty chmod a+rX --
    fi
done