/mandos/release

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

« back to all changes in this revision

Viewing changes to debian/mandos-client.postinst

  • Committer: teddy at recompile
  • Date: 2020-04-05 21:30:59 UTC
  • mto: This revision was merged to the branch mainline in revision 398.
  • Revision ID: teddy@recompile.se-20200405213059-fb2a61ckqynrmatk
Fix file descriptor leak in mandos-client

When the local network has Mandos servers announcing themselves using
real, globally reachable, IPv6 addresses (i.e. not link-local
addresses), but there is no router on the local network providing IPv6
RA (Router Advertisement) packets, the client cannot reach the server
by normal means, since the client only has a link-local IPv6 address,
and has no usable route to reach the server's global IPv6 address.
(This is not a common situation, and usually only happens when the
router itself reboots and runs a Mandos client, since it cannot then
give RA packets to itself.)  The client code has a solution for
this, which consists of adding a temporary local route to reach the
address of the server during communication, and removing this
temporary route afterwards.

This solution with a temporary route works, but has a file descriptor
leak; it leaks one file descriptor for each addition and for each
removal of a route.  If one server requiring an added route is present
on the network, but no servers gives a password, making the client
retry after the default ten seconds, and we furthermore assume a
default 1024 open files limit, the client runs out of file descriptors
after about 90 minutes, after which time the client process will be
useless and fail to retrieve any passwords, necessitating manual
password entry via the keyboard.

Fix this by eliminating the file descriptor leak in the client.

* plugins.d/mandos-client.c (add_delete_local_route): Do
  close(devnull) also in parent process, also if fork() fails, and on
  any failure in child process.

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
update_initramfs()
24
24
{
25
25
    if command -v update-initramfs >/dev/null; then
26
 
        update-initramfs -k all -u 1>&2
 
26
        update-initramfs -k all -u
27
27
    elif command -v dracut >/dev/null; then
28
28
        dracut_version="`dpkg-query --showformat='${Version}' --show dracut`"
29
29
        if dpkg --compare-versions "$dracut_version" lt 043-1 \
37
37
            # Dracut preserves old permissions of initramfs image
38
38
            # files, so we adjust permissions before creating new
39
39
            # initramfs image containing secret keys.
40
 
            if [ -e /boot/initrd.img-"$kversion" ]; then
41
 
                chmod go-r /boot/initrd.img-"$kversion"
42
 
            else
43
 
                # An initrd image has not yet been created for this
44
 
                # kernel, possibly because this new kernel is about to
45
 
                # be, but has not yet been, installed.  In this case,
46
 
                # we create an empty file with the right permissions
47
 
                # so that Dracut will preserve those permissions when
48
 
                # it creates the real, new initrd image for this
49
 
                # kernel.
50
 
                install --mode=u=rw /dev/null \
51
 
                        /boot/initrd.img-"$kversion"
52
 
            fi
 
40
            chmod go-r /boot/initrd.img-"$kversion"
53
41
            if [ "$kversion" != "*" ]; then
54
 
                /etc/kernel/postinst.d/dracut "$kversion" 1>&2
 
42
                /etc/kernel/postinst.d/dracut "$kversion"
55
43
            fi
56
44
        done
57
45
    fi
70
58
    if dpkg --compare-versions "$2" lt "1.0.3-1"; then
71
59
        case "`getent passwd mandos`" in
72
60
            *:Mandos\ password\ system,,,:/nonexistent:/bin/false)
73
 
                usermod --login _mandos mandos 1>&2
74
 
                groupmod --new-name _mandos mandos 1>&2
 
61
                usermod --login _mandos mandos
 
62
                groupmod --new-name _mandos mandos
75
63
                return
76
64
                ;;
77
65
        esac
80
68
    if ! getent passwd _mandos >/dev/null; then
81
69
        adduser --system --force-badname --quiet --home /nonexistent \
82
70
            --no-create-home --group --disabled-password \
83
 
            --gecos "Mandos password system" _mandos 1>&2
 
71
            --gecos "Mandos password system" _mandos
84
72
    fi
85
73
}
86
74
 
90
78
    # mandos-keygen
91
79
    if ! [ -r /etc/keys/mandos/pubkey.txt \
92
80
              -a -r /etc/keys/mandos/seckey.txt ]; then
93
 
        mandos-keygen 1>&2
94
 
        gpg-connect-agent KILLAGENT /bye 1>&2 || :
 
81
        mandos-keygen
 
82
        gpg-connect-agent KILLAGENT /bye || :
95
83
        return 0
96
84
    fi
97
85
 
102
90
        if ! certtool --password='' \
103
91
             --load-privkey=/etc/keys/mandos/tls-privkey.pem \
104
92
             --outfile=/dev/null --pubkey-info --no-text \
105
 
              1>&2 2>/dev/null; then
 
93
             2>/dev/null; then
106
94
            shred --remove -- /etc/keys/mandos/tls-privkey.pem \
107
95
                  2>/dev/null || :
108
96
            rm --force -- /etc/keys/mandos/tls-pubkey.pem
121
109
 
122
110
    if certtool --generate-privkey --password='' \
123
111
                --outfile "$TLS_PRIVKEYTMP" --sec-param ultra \
124
 
                --key-type=ed25519 --pkcs8 --no-text 1>&2 \
125
 
                2>/dev/null; then
 
112
                --key-type=ed25519 --pkcs8 --no-text 2>/dev/null; then
126
113
 
127
114
        local umask=$(umask)
128
115
        umask 077
133
120
        if ! certtool --password='' \
134
121
             --load-privkey=/etc/keys/mandos/tls-privkey.pem \
135
122
             --outfile=/etc/keys/mandos/tls-pubkey.pem --pubkey-info \
136
 
             --no-text 1>&2 2>/dev/null; then
 
123
             --no-text 2>/dev/null; then
137
124
            # Otherwise try OpenSSL
138
125
            if ! openssl pkey -in /etc/keys/mandos/tls-privkey.pem \
139
 
                 -out /etc/keys/mandos/tls-pubkey.pem -pubout \
140
 
                 1>&2; then
 
126
                 -out /etc/keys/mandos/tls-pubkey.pem -pubout; then
141
127
                rm --force /etc/keys/mandos/tls-pubkey.pem
142
128
                # None of the commands succeded; give up
143
129
                umask $umask
169
155
    DHFILE="`mktemp -t mandos-client-dh-parameters.XXXXXXXXXX.pem`"
170
156
    # First try certtool from GnuTLS
171
157
    if ! certtool --generate-dh-params --sec-param high \
172
 
         --outfile "$DHFILE" 1>&2; then
 
158
         --outfile "$DHFILE"; then
173
159
        # Otherwise try OpenSSL
174
160
        if ! openssl genpkey -genparam -algorithm DH -out "$DHFILE" \
175
 
             -pkeyopt dh_paramgen_prime_len:3072 1>&2; then
 
161
             -pkeyopt dh_paramgen_prime_len:3072; then
176
162
            # None of the commands succeded; give up
177
 
            rm --force -- "$DHFILE"
 
163
            rm -- "$DHFILE"
178
164
            return 1
179
165
        fi
180
166
    fi
183
169
    sed --in-place --expression='1i-----BEGIN DH PARAMETERS-----' \
184
170
            "$DHFILE"
185
171
    cp --archive "$DHFILE" /etc/keys/mandos/dhparams.pem
186
 
    rm --force -- "$DHFILE"
 
172
    rm -- "$DHFILE"
187
173
}
188
174
 
189
175
case "$1" in