/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 dracut-module/module-setup.sh

  • 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:
 
1
#!/bin/sh
 
2
#
 
3
# This file should be present in the root file system directory
 
4
# /usr/lib/dracut/modules.d/90mandos.  When dracut creates the
 
5
# initramfs image, dracut will source this file and run the shell
 
6
# functions defined in this file: "install", "check", "depends",
 
7
# "cmdline", and "installkernel".
 
8
 
9
# Despite the above #!/bin/sh line and the executable flag, this file
 
10
# is not executed; this file is sourced by dracut when creating the
 
11
# initramfs image file.
 
12
 
 
13
mandos_libdir(){
 
14
    for dir in /usr/lib \
 
15
        "/usr/lib/`dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null`" \
 
16
        "`rpm --eval='%{_libdir}' 2>/dev/null`" /usr/local/lib; do
 
17
        if [ -d "$dir"/mandos ]; then
 
18
            echo "$dir"/mandos
 
19
            return
 
20
        fi
 
21
    done
 
22
    # Mandos not found
 
23
    return 1
 
24
}
 
25
 
 
26
mandos_keydir(){
 
27
    for dir in /etc/keys/mandos /etc/mandos/keys; do
 
28
        if [ -d "$dir" ]; then
 
29
            echo "$dir"
 
30
            return
 
31
        fi
 
32
    done
 
33
    # Mandos key directory not found
 
34
    return 1
 
35
}
 
36
 
 
37
check(){
 
38
    if [ "${hostonly:-no}" = "no" ]; then
 
39
        dwarning "Mandos: Dracut not in hostonly mode"
 
40
        return 1
 
41
    fi
 
42
 
 
43
    local libdir=`mandos_libdir`
 
44
    if [ -z "$libdir" ]; then
 
45
        dwarning "Mandos lib directory not found"
 
46
        return 1
 
47
    fi
 
48
 
 
49
    local keydir=`mandos_keydir`
 
50
    if [ -z "$keydir" ]; then
 
51
        dwarning "Mandos key directory not found"
 
52
        return 1
 
53
    fi
 
54
}
 
55
 
 
56
install(){
 
57
    chmod go+w,+t "$initdir"/tmp
 
58
    local libdir=`mandos_libdir`
 
59
    local keydir=`mandos_keydir`
 
60
    set `{ getent passwd _mandos \
 
61
        || getent passwd nobody \
 
62
        || echo ::65534:65534:::; } \
 
63
        | cut --delimiter=: --fields=3,4 --only-delimited \
 
64
        --output-delimiter=" "`
 
65
    local mandos_user="$1"
 
66
    local mandos_group="$2"
 
67
    inst "${libdir}" /lib/mandos
 
68
    if dracut_module_included "systemd"; then
 
69
        plugindir=/lib/mandos
 
70
        inst "${libdir}/plugins.d/mandos-client" \
 
71
             "${plugindir}/mandos-client"
 
72
        chmod u-s "${initdir}/${plugindir}/mandos-client"
 
73
        inst "${moddir}/ask-password-mandos.service" \
 
74
             "${systemdsystemunitdir}/ask-password-mandos.service"
 
75
        if [ ${mandos_user} != 65534 ]; then
 
76
            sed --in-place \
 
77
                --expression="s,^ExecStart=/lib/mandos/password-agent ,&--user=${mandos_user} ," \
 
78
                "${initdir}/${systemdsystemunitdir}/ask-password-mandos.service"
 
79
        fi
 
80
        if [ ${mandos_group} != 65534 ]; then
 
81
            sed --in-place \
 
82
                --expression="s,^ExecStart=/lib/mandos/password-agent ,&--group=${mandos_group} ," \
 
83
                "${initdir}/${systemdsystemunitdir}/ask-password-mandos.service"
 
84
        fi
 
85
    else
 
86
        inst_hook cmdline 20 "$moddir"/cmdline-mandos.sh
 
87
        plugindir=/lib/mandos/plugins.d
 
88
        inst "${libdir}/plugin-runner" /lib/mandos/plugin-runner
 
89
        inst /etc/mandos/plugin-runner.conf
 
90
        sed --in-place \
 
91
            --expression='1i--options-for=mandos-client:--pubkey=/etc/mandos/keys/pubkey.txt,--seckey=/etc/mandos/keys/seckey.txt,--tls-pubkey=/etc/mandos/keys/tls-pubkey.pem,--tls-privkey=/etc/mandos/keys/tls-privkey.pem' \
 
92
            "${initdir}/etc/mandos/plugin-runner.conf"
 
93
        if [ ${mandos_user} != 65534 ]; then
 
94
            sed --in-place --expression="1i--userid=${mandos_user}" \
 
95
                "${initdir}/etc/mandos/plugin-runner.conf"
 
96
        fi
 
97
        if [ ${mandos_group} != 65534 ]; then
 
98
            sed --in-place \
 
99
                --expression="1i--groupid=${mandos_group}" \
 
100
                "${initdir}/etc/mandos/plugin-runner.conf"
 
101
        fi
 
102
        inst "${libdir}/plugins.d" "$plugindir"
 
103
        chown ${mandos_user}:${mandos_group} "${initdir}/${plugindir}"
 
104
        # Copy the packaged plugins
 
105
        for file in "$libdir"/plugins.d/*; do
 
106
            base="`basename \"$file\"`"
 
107
            # Is this plugin overridden?
 
108
            if [ -e "/etc/mandos/plugins.d/$base" ]; then
 
109
                continue
 
110
            fi
 
111
            case "$base" in
 
112
                *~|.*|\#*\#|*.dpkg-old|*.dpkg-bak|*.dpkg-new|*.dpkg-divert)
 
113
                    : ;;
 
114
                "*") dwarning "Mandos client plugin directory is empty." >&2 ;;
 
115
                askpass-fifo) : ;; # Ignore packaged for dracut
 
116
                *) inst "${file}" "${plugindir}/${base}" ;;
 
117
            esac
 
118
        done
 
119
        # Copy any user-supplied plugins
 
120
        for file in /etc/mandos/plugins.d/*; do
 
121
            base="`basename \"$file\"`"
 
122
            case "$base" in
 
123
                *~|.*|\#*\#|*.dpkg-old|*.dpkg-bak|*.dpkg-new|*.dpkg-divert)
 
124
                    : ;;
 
125
                "*") : ;;
 
126
                *) inst "$file" "${plugindir}/${base}" ;;
 
127
            esac
 
128
        done
 
129
        # Copy any user-supplied plugin helpers
 
130
        for file in /etc/mandos/plugin-helpers/*; do
 
131
            base="`basename \"$file\"`"
 
132
            case "$base" in
 
133
                *~|.*|\#*\#|*.dpkg-old|*.dpkg-bak|*.dpkg-new|*.dpkg-divert)
 
134
                    : ;;
 
135
                "*") : ;;
 
136
                *) inst "$file" "/lib/mandos/plugin-helpers/$base";;
 
137
            esac
 
138
        done
 
139
    fi
 
140
    # Copy network hooks
 
141
    for hook in /etc/mandos/network-hooks.d/*; do
 
142
        basename=`basename "$hook"`
 
143
        case "$basename" in
 
144
            "*") continue ;;
 
145
            *[!A-Za-z0-9_.-]*) continue ;;
 
146
            *) test -d "$hook" || inst "$hook" "/lib/mandos/network-hooks.d/$basename" ;;
 
147
        esac
 
148
        if [ -x "$hook" ]; then
 
149
            # Copy any files needed by the network hook
 
150
            MANDOSNETHOOKDIR=/etc/mandos/network-hooks.d MODE=files \
 
151
                VERBOSITY=0 "$hook" files | while read file target; do
 
152
                if [ ! -e "${file}" ]; then
 
153
                    dwarning "WARNING: file ${file} not found, requested by Mandos network hook '${basename}'" >&2
 
154
                fi
 
155
                if [ -z "${target}" ]; then
 
156
                    inst "$file"
 
157
                else
 
158
                    inst "$file" "$target"
 
159
                fi
 
160
            done
 
161
        fi
 
162
    done
 
163
    # Copy the packaged plugin helpers
 
164
    for file in "$libdir"/plugin-helpers/*; do
 
165
        base="`basename \"$file\"`"
 
166
        # Is this plugin overridden?
 
167
        if [ -e "/etc/mandos/plugin-helpers/$base" ]; then
 
168
            continue
 
169
        fi
 
170
        case "$base" in
 
171
            *~|.*|\#*\#|*.dpkg-old|*.dpkg-bak|*.dpkg-new|*.dpkg-divert)
 
172
                : ;;
 
173
            "*") : ;;
 
174
            *) inst "$file" "/lib/mandos/plugin-helpers/$base";;
 
175
        esac
 
176
    done
 
177
    local gpg=/usr/bin/gpg
 
178
    if [ -e /usr/bin/gpgconf ]; then
 
179
        inst /usr/bin/gpgconf
 
180
        gpg="`/usr/bin/gpgconf|sed --quiet --expression='s/^gpg:[^:]*://p'`"
 
181
        gpgagent="`/usr/bin/gpgconf|sed --quiet --expression='s/^gpg-agent:[^:]*://p'`"
 
182
        # Newer versions of GnuPG 2 requires the gpg-agent binary
 
183
        if [ -e "$gpgagent" ]; then
 
184
            inst "$gpgagent"
 
185
        fi
 
186
    fi
 
187
    inst "$gpg"
 
188
    if dracut_module_included "systemd"; then
 
189
        inst "${moddir}/password-agent" /lib/mandos/password-agent
 
190
        inst "${moddir}/ask-password-mandos.path" \
 
191
             "${systemdsystemunitdir}/ask-password-mandos.path"
 
192
        ln_r "${systemdsystemunitdir}/ask-password-mandos.path" \
 
193
             "${systemdsystemunitdir}/sysinit.target.wants/ask-password-mandos.path"
 
194
    fi
 
195
    # Key files
 
196
    for file in "$keydir"/*; do
 
197
        if [ -d "$file" ]; then
 
198
            continue
 
199
        fi
 
200
        case "$file" in
 
201
            *~|.*|\#*\#|*.dpkg-old|*.dpkg-bak|*.dpkg-new|*.dpkg-divert)
 
202
                : ;;
 
203
            "*") : ;;
 
204
            *)
 
205
                inst "$file" "/etc/mandos/keys/`basename \"$file\"`"
 
206
                chown ${mandos_user}:${mandos_group} \
 
207
                      "${initdir}/etc/mandos/keys/`basename \"$file\"`"
 
208
                if [ `basename "$file"` = dhparams.pem ]; then
 
209
                    # Use Diffie-Hellman parameters file
 
210
                    if dracut_module_included "systemd"; then
 
211
                        sed --in-place \
 
212
                            --expression='/^ExecStart/s/$/ --dh-params=\/etc\/mandos\/keys\/dhparams.pem/' \
 
213
                            "${initdir}/${systemdsystemunitdir}/ask-password-mandos.service"
 
214
                    else
 
215
                        sed --in-place \
 
216
                            --expression="1i--options-for=mandos-client:--dh-params=/etc/mandos/keys/dhparams.pem" \
 
217
                            "${initdir}/etc/mandos/plugin-runner.conf"
 
218
                    fi
 
219
                fi
 
220
                ;;
 
221
        esac
 
222
    done
 
223
}
 
224
 
 
225
installkernel(){
 
226
    instmods =drivers/net
 
227
    hostonly='' instmods ipv6
 
228
    # Copy any kernel modules needed by network hooks
 
229
    for hook in /etc/mandos/network-hooks.d/*; do
 
230
        basename=`basename "$hook"`
 
231
        case "$basename" in
 
232
            "*") continue ;;
 
233
            *[!A-Za-z0-9_.-]*) continue ;;
 
234
        esac
 
235
        if [ -x "$hook" ]; then
 
236
            # Copy and load any modules needed by the network hook
 
237
            MANDOSNETHOOKDIR=/etc/mandos/network-hooks.d MODE=modules \
 
238
                VERBOSITY=0 "$hook" modules | while read module; do
 
239
                if [ -z "${target}" ]; then
 
240
                    instmods "$module"
 
241
                fi
 
242
            done
 
243
        fi
 
244
    done
 
245
}
 
246
 
 
247
depends(){
 
248
    echo crypt
 
249
}
 
250
 
 
251
cmdline(){
 
252
    :
 
253
}