/mandos/trunk

To get this branch, use:
bzr branch http://bzr.recompile.se/loggerhead/mandos/trunk

« back to all changes in this revision

Viewing changes to initramfs-tools-hook

  • Committer: Teddy Hogeborn
  • Date: 2019-08-02 22:16:53 UTC
  • Revision ID: teddy@recompile.se-20190802221653-ic1iko9hbefzwsk7
Fix bug in server Debian package: Fails to start on first install

There has been a very long-standing bug where installation of the
server (the "mandos" Debian package) would fail to start the server
properly right after installation.  It would work on manual (re)start
after installation, or after reboot, and even after package purge and
reinstall, it would then work the first time.  The problem, it turns
out, is when the new "_mandos" user (and corresponding group) is
created, the D-Bus server is not reloaded, and is therefore not aware
of that user, and does not recognize the user and group name in the
/etc/dbus-1/system.d/mandos.conf file.  The Mandos server, when it
tries to start and access the D-Bus, is then not permitted to connect
to its D-Bus bus name, and disables D-Bus use as a fallback measure;
i.e. the server works, but it is not controllable via D-Bus commands
(via mandos-ctl or mandos-monitor).  The next time the D-Bus daemon is
reloaded for any reason, the new user & group would become visible to
the D-Bus daemon and after that, any restart of the Mandos server
would succeed and it would bind to its D-Bus name properly, and
thereby be visible and controllable by mandos-ctl & mandos-monitor.
This was mostly invisible when using sysvinit, but systemd makes the
problem visible since the systemd service file for the Mandos server
is configured to not consider the Mandos server "started" until the
D-Bus name has been bound; this makes the starting of the service wait
for 90 seconds and then fail with a timeout error.

Fixing this should also make the Debian CI autopkgtest tests work.

* debian/mandos.postinst (configure): After creating (or renaming)
                                      user & group, reload D-Bus
                                      daemon (if present).

Show diffs side-by-side

added added

removed removed

Lines of Context:
3
3
# This script will be run by 'mkinitramfs' when it creates the image.
4
4
# Its job is to decide which files to install, then install them into
5
5
# the staging area, where the initramfs is being created.  This
6
 
# happens when a new 'linux-image' package is installed, or when the
 
6
# happens when a new 'linux-image' package is installed, or when an
7
7
# administrator runs 'update-initramfs' by hand to update an initramfs
8
8
# image.
9
9
 
29
29
 
30
30
. /usr/share/initramfs-tools/hook-functions
31
31
 
32
 
if [ -d /usr/lib/mandos ]; then
33
 
    prefix=/usr
34
 
elif [ -d /usr/local/lib/mandos ]; then
35
 
    prefix=/usr/local
36
 
else
 
32
for d in /usr/lib \
 
33
    "/usr/lib/`dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null`" \
 
34
    "`rpm --eval='%{_libdir}' 2>/dev/null`" /usr/local/lib; do
 
35
    if [ -d "$d"/mandos ]; then
 
36
        libdir="$d"
 
37
        break
 
38
    fi
 
39
done
 
40
if [ -z "$libdir" ]; then
37
41
    # Mandos not found
38
42
    exit 1
39
43
fi
40
44
 
 
45
for d in /etc/keys/mandos /etc/mandos/keys; do
 
46
    if [ -d "$d" ]; then
 
47
        keydir="$d"
 
48
        break
 
49
    fi
 
50
done
 
51
if [ -z "$keydir" ]; then
 
52
    # Mandos key directory not found
 
53
    exit 1
 
54
fi
 
55
 
 
56
set `{ getent passwd _mandos \
 
57
    || getent passwd nobody \
 
58
    || echo ::65534:65534:::; } \
 
59
    | cut --delimiter=: --fields=3,4 --only-delimited \
 
60
    --output-delimiter=" "`
 
61
mandos_user="$1"
 
62
mandos_group="$2"
 
63
 
41
64
# The Mandos network client uses the network
42
65
auto_add_modules net
43
66
# The Mandos network client uses IPv6
47
70
CONFDIR="/conf/conf.d/mandos"
48
71
MANDOSDIR="/lib/mandos"
49
72
PLUGINDIR="${MANDOSDIR}/plugins.d"
 
73
PLUGINHELPERDIR="${MANDOSDIR}/plugin-helpers"
 
74
HOOKDIR="${MANDOSDIR}/network-hooks.d"
50
75
 
51
76
# Make directories
52
 
mkdir --parents "${DESTDIR}${CONFDIR}"
53
 
mkdir --parents "${DESTDIR}${PLUGINDIR}"
 
77
install --directory --mode=u=rwx,go=rx "${DESTDIR}${CONFDIR}" \
 
78
        "${DESTDIR}${MANDOSDIR}" "${DESTDIR}${HOOKDIR}"
 
79
install --owner=${mandos_user} --group=${mandos_group} --directory \
 
80
        --mode=u=rwx "${DESTDIR}${PLUGINDIR}" \
 
81
        "${DESTDIR}${PLUGINHELPERDIR}"
 
82
 
 
83
copy_exec "$libdir"/mandos/mandos-to-cryptroot-unlock "${MANDOSDIR}"
54
84
 
55
85
# Copy the Mandos plugin runner
56
 
copy_exec "$prefix"/lib/mandos/plugin-runner "${DESTDIR}${MANDOSDIR}"
 
86
copy_exec "$libdir"/mandos/plugin-runner "${MANDOSDIR}"
57
87
 
58
88
# Copy the plugins
59
89
 
60
90
# Copy the packaged plugins
61
 
for file in "$prefix"/lib/mandos/plugins.d/*; do
 
91
for file in "$libdir"/mandos/plugins.d/*; do
62
92
    base="`basename \"$file\"`"
63
93
    # Is this plugin overridden?
64
94
    if [ -e "/etc/mandos/plugins.d/$base" ]; then
65
95
        continue
66
96
    fi
67
97
    case "$base" in
68
 
        *~|.*|\#*\#|*.dpkg-old|*.dpkg-new|*.dpkg-divert) : ;;
69
 
        *) copy_exec "$file" "${PLUGINDIR}";;
 
98
        *~|.*|\#*\#|*.dpkg-old|*.dpkg-bak|*.dpkg-new|*.dpkg-divert)
 
99
            : ;;
 
100
        "*") echo "W: Mandos client plugin directory is empty." >&2 ;;
 
101
        *) copy_exec "$file" "${PLUGINDIR}" ;;
 
102
    esac
 
103
done
 
104
 
 
105
# Copy the packaged plugin helpers
 
106
for file in "$libdir"/mandos/plugin-helpers/*; do
 
107
    base="`basename \"$file\"`"
 
108
    # Is this plugin overridden?
 
109
    if [ -e "/etc/mandos/plugin-helpers/$base" ]; then
 
110
        continue
 
111
    fi
 
112
    case "$base" in
 
113
        *~|.*|\#*\#|*.dpkg-old|*.dpkg-bak|*.dpkg-new|*.dpkg-divert)
 
114
            : ;;
 
115
        "*") : ;;
 
116
        *) copy_exec "$file" "${PLUGINHELPERDIR}" ;;
70
117
    esac
71
118
done
72
119
 
74
121
for file in /etc/mandos/plugins.d/*; do
75
122
    base="`basename \"$file\"`"
76
123
    case "$base" in
77
 
        *~|.*|*.dpkg-old|*.dpkg-new|*.dpkg-divert) : ;;
78
 
        *) copy_exec "$file" "${PLUGINDIR}";;
79
 
    esac
80
 
done
81
 
 
82
 
# GPGME needs /usr/bin/gpg
83
 
if ! [ -e "${DESTDIR}/usr/bin/gpg" ] \
84
 
    && [ -n "`ls \"${DESTDIR}\"/usr/lib/libgpgme.so* 2>/dev/null`" ]; then
85
 
    copy_exec /usr/bin/gpg
 
124
        *~|.*|\#*\#|*.dpkg-old|*.dpkg-bak|*.dpkg-new|*.dpkg-divert)
 
125
            : ;;
 
126
        "*") : ;;
 
127
        *) copy_exec "$file" "${PLUGINDIR}" ;;
 
128
    esac
 
129
done
 
130
 
 
131
# Copy any user-supplied plugin helpers
 
132
for file in /etc/mandos/plugin-helpers/*; do
 
133
    base="`basename \"$file\"`"
 
134
    case "$base" in
 
135
        *~|.*|\#*\#|*.dpkg-old|*.dpkg-bak|*.dpkg-new|*.dpkg-divert)
 
136
            : ;;
 
137
        "*") : ;;
 
138
        *) copy_exec "$file" "${PLUGINHELPERDIR}" ;;
 
139
    esac
 
140
done
 
141
 
 
142
# Get DEVICE from initramfs.conf and other files
 
143
. /etc/initramfs-tools/initramfs.conf
 
144
for conf in /etc/initramfs-tools/conf.d/*; do
 
145
    if [ -n `basename \"$conf\" | grep '^[[:alnum:]][[:alnum:]\._-]*$' \
 
146
        | grep -v '\.dpkg-.*$'` ]; then
 
147
        [ -f "${conf}" ] && . "${conf}"
 
148
    fi
 
149
done
 
150
export DEVICE
 
151
 
 
152
# Copy network hooks
 
153
for hook in /etc/mandos/network-hooks.d/*; do
 
154
    case "`basename \"$hook\"`" in
 
155
        "*") continue ;;
 
156
        *[!A-Za-z0-9_.-]*) continue ;;
 
157
        *) test -d "$hook" || copy_exec "$hook" "${HOOKDIR}" ;;
 
158
    esac
 
159
    if [ -x "$hook" ]; then
 
160
        # Copy any files needed by the network hook
 
161
        MANDOSNETHOOKDIR=/etc/mandos/network-hooks.d MODE=files \
 
162
            VERBOSITY=0 "$hook" files | while read -r file target; do
 
163
            if [ ! -e "${file}" ]; then
 
164
                echo "WARNING: file ${file} not found, requested by Mandos network hook '${hook##*/}'" >&2
 
165
            fi
 
166
            if [ -z "${target}" ]; then
 
167
                copy_exec "$file"
 
168
            else
 
169
                copy_exec "$file" "$target"
 
170
            fi
 
171
        done
 
172
        # Copy and load any modules needed by the network hook
 
173
        MANDOSNETHOOKDIR=/etc/mandos/network-hooks.d MODE=modules \
 
174
            VERBOSITY=0 "$hook" modules | while read -r module; do
 
175
            force_load "$module"
 
176
        done
 
177
    fi
 
178
done
 
179
 
 
180
# GPGME needs GnuPG
 
181
gpg=/usr/bin/gpg
 
182
libgpgme11_version="`dpkg-query --showformat='${Version}' --show libgpgme11`"
 
183
if dpkg --compare-versions "$libgpgme11_version" ge 1.5.0-0.1; then
 
184
    if [ -e /usr/bin/gpgconf ]; then
 
185
        if [ ! -e "${DESTDIR}/usr/bin/gpgconf" ]; then
 
186
            copy_exec /usr/bin/gpgconf
 
187
        fi
 
188
        gpg="`/usr/bin/gpgconf|sed --quiet --expression='s/^gpg:[^:]*://p'`"
 
189
        gpgagent="`/usr/bin/gpgconf|sed --quiet --expression='s/^gpg-agent:[^:]*://p'`"
 
190
        # Newer versions of GnuPG 2 requires the gpg-agent binary
 
191
        if [ -e "$gpgagent" ] && [ ! -e "${DESTDIR}$gpgagent" ]; then
 
192
            copy_exec "$gpgagent"
 
193
        fi
 
194
    fi
 
195
elif dpkg --compare-versions "$libgpgme11_version" ge 1.4.1-0.1; then
 
196
    gpg=/usr/bin/gpg2
 
197
fi
 
198
if [ ! -e "${DESTDIR}$gpg" ]; then
 
199
    copy_exec "$gpg"
 
200
fi
 
201
unset gpg
 
202
unset libgpgme11_version
 
203
 
 
204
# Config files
 
205
for file in /etc/mandos/plugin-runner.conf; do
 
206
    if [ -d "$file" ]; then
 
207
        continue
 
208
    fi
 
209
    cp --archive --sparse=always "$file" "${DESTDIR}${CONFDIR}"
 
210
done
 
211
 
 
212
if [ ${mandos_user} != 65534 ]; then
 
213
    sed --in-place --expression="1i--userid=${mandos_user}" \
 
214
        "${DESTDIR}${CONFDIR}/plugin-runner.conf"
 
215
fi
 
216
 
 
217
if [ ${mandos_group} != 65534 ]; then
 
218
    sed --in-place --expression="1i--groupid=${mandos_group}" \
 
219
        "${DESTDIR}${CONFDIR}/plugin-runner.conf"
86
220
fi
87
221
 
88
222
# Key files
89
 
for file in /etc/mandos/*; do
 
223
for file in "$keydir"/*; do
90
224
    if [ -d "$file" ]; then
91
225
        continue
92
226
    fi
93
 
    cp --archive --sparse=always "$file" "${DESTDIR}${CONFDIR}"
 
227
    case "$file" in
 
228
        *~|.*|\#*\#|*.dpkg-old|*.dpkg-bak|*.dpkg-new|*.dpkg-divert)
 
229
            : ;;
 
230
        "*") : ;;
 
231
        *)
 
232
            cp --archive --sparse=always "$file" \
 
233
               "${DESTDIR}${CONFDIR}"
 
234
            chown ${mandos_user}:${mandos_group} \
 
235
                  "${DESTDIR}${CONFDIR}/`basename \"$file\"`"
 
236
            ;;
 
237
    esac
94
238
done
95
 
# Create key ring files
96
 
gpg --no-random-seed-file --quiet --batch --no-tty --armor \
97
 
    --no-default-keyring --no-options --enable-dsa2 \
98
 
    --homedir "${DESTDIR}${CONFDIR}" --no-permission-warning \
99
 
    --trust-model always --import-options import-minimal \
100
 
    --import "${DESTDIR}${CONFDIR}/seckey.txt"
101
 
chown nobody "${DESTDIR}${CONFDIR}/secring.gpg"
 
239
# Use Diffie-Hellman parameters file if available
 
240
if [ -e "${DESTDIR}${CONFDIR}"/dhparams.pem ]; then
 
241
    sed --in-place \
 
242
        --expression="1i--options-for=mandos-client:--dh-params=${CONFDIR}/dhparams.pem" \
 
243
        "${DESTDIR}/${CONFDIR}/plugin-runner.conf"
 
244
fi
102
245
 
103
246
# /lib/mandos/plugin-runner will drop priviliges, but needs access to
104
247
# its plugin directory and its config file.  However, since almost all
109
252
# initrd; it is intended to affect the initrd.img file itself, since
110
253
# it now contains secret key files.  There is, however, no other way
111
254
# to set the permission of the initrd.img file without a race
112
 
# condition.  This umask is set by "initramfs-tools-hook-conf",
113
 
# installed as "/usr/share/initramfs-tools/conf-hooks.d/mandos".)
 
255
# condition.  This umask is set by "initramfs-tools-conf", installed
 
256
# as "/usr/share/initramfs-tools/conf.d/mandos-conf".)
114
257
115
 
for full in "${PLUGINDIR}" "${CONFDIR}"; do
 
258
for full in "${MANDOSDIR}" "${CONFDIR}"; do
116
259
    while [ "$full" != "/" ]; do
117
260
        chmod a+rX "${DESTDIR}$full"
118
261
        full="`dirname \"$full\"`"
122
265
# Reset some other things to sane permissions which we have
123
266
# inadvertently affected with our umask setting.
124
267
for dir in / /bin /etc /keyscripts /sbin /scripts /usr /usr/bin; do
125
 
    chmod a+rX "${DESTDIR}$dir"
 
268
    if [ -d "${DESTDIR}$dir" ]; then
 
269
        chmod a+rX "${DESTDIR}$dir"
 
270
    fi
126
271
done
127
 
for dir in /lib /usr/lib; do
128
 
    chmod --recursive a+rX "${DESTDIR}$dir"
 
272
for dir in "${DESTDIR}"/lib* "${DESTDIR}"/usr/lib*; do
 
273
    if [ -d "$dir" ]; then
 
274
        find "$dir" \! -perm -u+rw,g+r -prune -or \! -type l -print0 \
 
275
            | xargs --null --no-run-if-empty chmod a+rX --
 
276
    fi
129
277
done