/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
#!/bin/sh
# This script can be called in the following ways:
#
# After the package was installed:
#       <postinst> configure <old-version>
#
#
# If prerm fails during upgrade or fails on failed upgrade:
#       <old-postinst> abort-upgrade <new-version>
#
# If prerm fails during deconfiguration of a package:
#       <postinst> abort-deconfigure in-favour <new-package> <version>
#                  removing <old-package> <version>
#
# If prerm fails during replacement due to conflict:
#       <postinst> abort-remove in-favour <new-package> <version>

. /usr/share/debconf/confmodule

set -e

# Update the initial RAM file system image
update_initramfs()
{
    if command -v update-initramfs >/dev/null; then
	update-initramfs -k all -u 1>&2
    elif command -v dracut >/dev/null; then
	dracut_version="`dpkg-query --showformat='${Version}' --show dracut`"
	if dpkg --compare-versions "$dracut_version" lt 043-1 \
		&& bash -c '. /etc/dracut.conf; . /etc/dracut.conf.d/*; [ "$hostonly" != yes ]'; then
	    echo 'Dracut is not configured to use hostonly mode!' >&2
	    return 1
	fi
	# Logic taken from dracut.postinst
	for kernel in /boot/vmlinu[xz]-*; do
	    kversion="${kernel#/boot/vmlinu[xz]-}"
	    # Dracut preserves old permissions of initramfs image
	    # files, so we adjust permissions before creating new
	    # initramfs image containing secret keys.
	    if [ -e /boot/initrd.img-"$kversion" ]; then
		chmod go-r /boot/initrd.img-"$kversion"
	    else
		# An initrd image has not yet been created for this
		# kernel, possibly because this new kernel is about to
		# be, but has not yet been, installed.  In this case,
		# we create an empty file with the right permissions
		# so that Dracut will preserve those permissions when
		# it creates the real, new initrd image for this
		# kernel.
		install --mode=u=rw /dev/null \
			/boot/initrd.img-"$kversion"
	    fi
	    if [ "$kversion" != "*" ]; then
		/etc/kernel/postinst.d/dracut "$kversion" 1>&2
	    fi
	done
    fi
    
    if dpkg --compare-versions "$2" lt-nl "1.0.10-1"; then
        # Make old initrd.img files unreadable too, in case they were
        # created with mandos-client 1.0.8 or older.
	find /boot -maxdepth 1 -type f -name "initrd.img-*.bak" \
	    -print0 | xargs --null --no-run-if-empty chmod o-r
    fi
}

# Add user and group
add_mandos_user(){
    # Rename old "mandos" user and group
    if dpkg --compare-versions "$2" lt "1.0.3-1"; then
	case "`getent passwd mandos`" in
	    *:Mandos\ password\ system,,,:/nonexistent:/bin/false)
		usermod --login _mandos mandos 1>&2
		groupmod --new-name _mandos mandos 1>&2
		return
		;;
	esac
    fi
    # Create new user and group
    if ! getent passwd _mandos >/dev/null; then
	adduser --system --force-badname --quiet --home /nonexistent \
	    --no-create-home --group --disabled-password \
	    --gecos "Mandos password system" _mandos 1>&2
    fi
}

# Create client key pairs
create_keys(){
    # If the OpenPGP key files do not exist, generate all keys using
    # mandos-keygen
    if ! [ -r /etc/keys/mandos/pubkey.txt \
	      -a -r /etc/keys/mandos/seckey.txt ]; then
	mandos-keygen 1>&2
	gpg-connect-agent KILLAGENT /bye 1>&2 || :
	return 0
    fi

    # Remove any bad TLS keys by 1.8.0-1
    if dpkg --compare-versions "$2" eq "1.8.0-1" \
       || dpkg --compare-versions "$2" eq "1.8.0-1~bpo9+1"; then
	# Is the key bad?
	if ! certtool --password='' \
	     --load-privkey=/etc/keys/mandos/tls-privkey.pem \
	     --outfile=/dev/null --pubkey-info --no-text \
	      1>&2 2>/dev/null; then
	    shred --remove -- /etc/keys/mandos/tls-privkey.pem \
		  2>/dev/null || :
	    rm --force -- /etc/keys/mandos/tls-pubkey.pem
	fi
    fi

    # If the TLS keys already exists, do nothing
    if [ -r /etc/keys/mandos/tls-privkey.pem \
	    -a -r /etc/keys/mandos/tls-pubkey.pem ]; then
	return 0
    fi

    # Try to create the TLS keys

    TLS_PRIVKEYTMP="`mktemp -t mandos-client-privkey.XXXXXXXXXX`"

    if certtool --generate-privkey --password='' \
		--outfile "$TLS_PRIVKEYTMP" --sec-param ultra \
		--key-type=ed25519 --pkcs8 --no-text 1>&2 \
		2>/dev/null; then

	local umask=$(umask)
	umask 077
	cp --archive "$TLS_PRIVKEYTMP" /etc/keys/mandos/tls-privkey.pem
	shred --remove -- "$TLS_PRIVKEYTMP" 2>/dev/null || :

	# First try certtool from GnuTLS
	if ! certtool --password='' \
	     --load-privkey=/etc/keys/mandos/tls-privkey.pem \
	     --outfile=/etc/keys/mandos/tls-pubkey.pem --pubkey-info \
	     --no-text 1>&2 2>/dev/null; then
	    # Otherwise try OpenSSL
	    if ! openssl pkey -in /etc/keys/mandos/tls-privkey.pem \
		 -out /etc/keys/mandos/tls-pubkey.pem -pubout \
		 1>&2; then
		rm --force /etc/keys/mandos/tls-pubkey.pem
		# None of the commands succeded; give up
		umask $umask
		return 1
	    fi
	fi
	umask $umask

	key_id=$(mandos-keygen --passfile=/dev/null \
		     | grep --regexp="^key_id[ =]")

	db_version 2.0
	db_fset mandos-client/key_id seen false
	db_reset mandos-client/key_id
	db_subst mandos-client/key_id key_id $key_id
	db_input critical mandos-client/key_id || true
	db_go
	db_stop
    else
	shred --remove -- "$TLS_PRIVKEYTMP" 2>/dev/null || :
    fi
}

create_dh_params(){
    if [ -r /etc/keys/mandos/dhparams.pem ]; then
	return 0
    fi
    # Create a Diffe-Hellman parameters file
    DHFILE="`mktemp -t mandos-client-dh-parameters.XXXXXXXXXX.pem`"
    # First try certtool from GnuTLS
    if ! certtool --generate-dh-params --sec-param high \
	 --outfile "$DHFILE" 1>&2; then
	# Otherwise try OpenSSL
	if ! openssl genpkey -genparam -algorithm DH -out "$DHFILE" \
	     -pkeyopt dh_paramgen_prime_len:3072 1>&2; then
	    # None of the commands succeded; give up
	    rm --force -- "$DHFILE"
	    return 1
	fi
    fi
    sed --in-place --expression='0,/^-----BEGIN DH PARAMETERS-----$/d' \
	"$DHFILE"
    sed --in-place --expression='1i-----BEGIN DH PARAMETERS-----' \
	    "$DHFILE"
    cp --archive "$DHFILE" /etc/keys/mandos/dhparams.pem
    rm --force -- "$DHFILE"
}

case "$1" in
    configure)
	add_mandos_user "$@"
	create_keys "$@"
	create_dh_params "$@" || :
	update_initramfs "$@"
	if dpkg --compare-versions "$2" lt-nl "1.7.10-1"; then
	    PLUGINHELPERDIR=/usr/lib/$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null)/mandos/plugin-helpers
	    if ! dpkg-statoverride --list "$PLUGINHELPERDIR" \
		 >/dev/null 2>&1; then
		chmod u=rwx,go= -- "$PLUGINHELPERDIR"
	    fi
	    if ! dpkg-statoverride --list /etc/mandos/plugin-helpers \
		 >/dev/null 2>&1; then
		chmod u=rwx,go= -- /etc/mandos/plugin-helpers
	    fi
	fi
	;;
    abort-upgrade|abort-deconfigure|abort-remove)
	;;

    *)
	echo "$0 called with unknown argument '$1'" 1>&2
	exit 1
	;;
esac

#DEBHELPER#

exit 0