aboutsummaryrefslogtreecommitdiff
blob: 54ed1a04543fe205c98dfbc7cb16332053d96857 (plain)
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
#!/bin/sh

print_usage() {
	echo "Usage: $0 root|swap" >&2
}

if [ -z "${1}" ]
then
	print_usage
	exit 1
fi

case "${1}" in
	root)
		NAME="${1}"
		TYPE=ROOT
		;;
	swap)
		NAME="${1}"
		TYPE=SWAP
		;;
	*)
		echo "ERROR: Unknown type '${1}' specified!"
		print_usage
		exit 1
		;;
esac

. /etc/initrd.defaults
. /etc/initrd.scripts
. "${CRYPT_ENV_FILE}"

GK_INIT_LOG_PREFIX=${0}
if [ -n "${SSH_CLIENT_IP}" ] && [ -n "${SSH_CLIENT_PORT}" ]
then
	GK_INIT_LOG_PREFIX="${0}[${SSH_CLIENT_IP}:${SSH_CLIENT_PORT}]"
fi

main() {
	if ! hash cryptsetup >/dev/null 2>&1
	then
		bad_msg "cryptsetup program is missing. Was initramfs built without --luks parameter?"
		exit 1
	fi

	local LUKS_NAME="${NAME}"
	eval local LUKS_DEVICE='"${CRYPT_'${TYPE}'}"'
	eval local LUKS_KEY='"${CRYPT_'${TYPE}'_KEYFILE}"'
	eval local cryptsetup_options='"${CRYPT_'${TYPE}'_OPTIONS}"'
	cryptsetup_options="$(trim "${cryptsetup_options}")"
	eval local OPENED_LOCKFILE='"${CRYPT_'${TYPE}'_OPENED_LOCKFILE}"'

	if [ -z "${LUKS_DEVICE}" ]
	then
		bad_msg "'crypt_${NAME}' kernel command-line argument is not set!"
		exit 1
	fi

	while true
	do
		# Reset cryptsetup_options on each iteration
		eval local cryptsetup_options='"${CRYPT_'${TYPE}'_OPTIONS}"'
		cryptsetup_options="$(trim "${cryptsetup_options}")"

		local gpg_cmd crypt_filter_ret

		if [ -e "${OPENED_LOCKFILE}" ]
		then
			good_msg "The LUKS device ${LUKS_DEVICE} was opened by someone else in the meanwhile."
			break
		else
			LUKS_DEVICE=$(find_real_device "${LUKS_DEVICE}")
			if [ -z "${LUKS_DEVICE}" ]
			then
				bad_msg "Failed to find LUKS device. If crypt_${NAME} kernel command-line argument is correct you are probably missing kernel support for your storage!" ${CRYPT_SILENT}
				exit 1
			fi

			if ! run cryptsetup isLuks "${LUKS_DEVICE}"
			then
				bad_msg "The LUKS device ${LUKS_DEVICE} does not contain a LUKS header" ${CRYPT_SILENT}

				# User has SSH access and is able to call script again or
				# able to investigate the problem on its own.
				exit 1
			else
				if [ -n "${cryptsetup_options}" ]
				then
					good_msg "Using the following cryptsetup options for ${LUKS_NAME}: ${cryptsetup_options}" ${CRYPT_SILENT}
				fi

				# Handle keys
				if [ -s "${LUKS_KEY}" ]
				then
					# we received raw, unencrypted key through SSH -- no GPG possible
					cryptsetup_options="${cryptsetup_options} -d ${LUKS_KEY}"
				fi

				# At this point, keyfile or not, we're ready!
				crypt_filter "${gpg_cmd}cryptsetup ${cryptsetup_options} luksOpen ${LUKS_DEVICE} ${LUKS_NAME}"
				crypt_filter_ret=$?

				[ -e /dev/tty.org ] \
					&& run rm -f /dev/tty \
					&& run mv /dev/tty.org /dev/tty

				if [ ${crypt_filter_ret} -eq 0 ]
				then
					run touch "${OPENED_LOCKFILE}"
					good_msg "LUKS device ${LUKS_DEVICE} opened" ${CRYPT_SILENT}
					break
				else
					bad_msg "Failed to open LUKS device ${LUKS_DEVICE}" ${CRYPT_SILENT}

					# We need to stop here with a non-zero exit code to prevent
					# a loop when invalid keyfile was sent.
					exit 1
				fi
			fi
		fi
	done

	udevsettle

	if [ -s "${LUKS_KEY}" ]
	then
		if  ! is_debug
		then
			run rm -f "${LUKS_KEY}"
		else
			warn_msg "LUKS key file '${LUKS_KEY}' not deleted because DEBUG mode is enabled!"
		fi
	fi

	if [ "${crypt_filter_ret}" = '0' ]
	then
		# Kill any running cryptsetup prompt for this device.
		# But SIGINT only to keep shell functional.
		run pkill -2 -f "luksOpen.*${LUKS_NAME}\$" >/dev/null 2>&1
	fi
}

main

exit 0