]>
Commit | Line | Data |
---|---|---|
04effa9c JR |
1 | #!/bin/sh |
2 | ||
3 | # | |
4 | # Standard initramfs preamble | |
5 | # | |
6 | prereqs() | |
7 | { | |
8 | # Make sure that cryptroot is run last in local-top | |
9 | for req in /scripts/local-top/*; do | |
10 | script=${req##*/} | |
11 | if [ $script != cryptroot ]; then | |
12 | echo $script | |
13 | fi | |
14 | done | |
15 | } | |
16 | ||
17 | case $1 in | |
18 | prereqs) | |
19 | prereqs | |
20 | exit 0 | |
21 | ;; | |
22 | esac | |
23 | ||
24 | ||
25 | # | |
26 | # Helper functions | |
27 | # | |
28 | message() | |
29 | { | |
30 | if [ -p /dev/.initramfs/usplash_outfifo ] && [ -x /sbin/usplash_write ]; then | |
31 | usplash_write "TEXT-URGENT $@" | |
32 | else | |
33 | echo "$@" >&2 | |
34 | fi | |
35 | return 0 | |
36 | } | |
37 | ||
38 | parse_options() | |
39 | { | |
40 | local cryptopts | |
41 | cryptopts="$1" | |
42 | ||
43 | if [ -z "$cryptopts" ]; then | |
44 | return 1 | |
45 | fi | |
46 | ||
47 | # Defaults | |
48 | cryptcipher=aes-cbc-essiv:sha256 | |
49 | cryptsize=256 | |
50 | crypthash=ripemd160 | |
51 | crypttarget=cryptroot | |
52 | cryptsource="" | |
53 | cryptlvm="" | |
54 | cryptkeyscript="" | |
55 | cryptkey="" # This is only used as an argument to an eventual keyscript | |
56 | crypttries=3 | |
57 | ||
58 | local IFS=" ," | |
59 | for x in $cryptopts; do | |
60 | case $x in | |
61 | hash=*) | |
62 | crypthash=${x#hash=} | |
63 | ;; | |
64 | size=*) | |
65 | cryptsize=${x#size=} | |
66 | ;; | |
67 | cipher=*) | |
68 | cryptcipher=${x#cipher=} | |
69 | ;; | |
70 | target=*) | |
71 | crypttarget=${x#target=} | |
72 | ;; | |
73 | source=*) | |
74 | cryptsource=${x#source=} | |
75 | if [ ${cryptsource#UUID=} != $cryptsource ]; then | |
76 | cryptsource="/dev/disk/by-uuid/${cryptsource#UUID=}" | |
77 | elif [ ${cryptsource#LABEL=} != $cryptsource ]; then | |
78 | cryptsource="/dev/disk/by-label/${cryptsource#LABEL=}" | |
79 | fi | |
80 | ;; | |
81 | lvm=*) | |
82 | cryptlvm=${x#lvm=} | |
83 | ;; | |
84 | keyscript=*) | |
85 | cryptkeyscript=${x#keyscript=} | |
86 | ;; | |
87 | key=*) | |
88 | if [ "${x#key=}" != "none" ]; then | |
89 | cryptkey=${x#key=} | |
90 | fi | |
91 | ;; | |
92 | tries=*) | |
93 | crypttries="${x#tries=}" | |
94 | case "$crypttries" in | |
95 | *[![:digit:].]*) | |
96 | crypttries=3 | |
97 | ;; | |
98 | esac | |
99 | ;; | |
100 | esac | |
101 | done | |
102 | ||
103 | if [ -z "$cryptsource" ]; then | |
104 | message "cryptsetup: source parameter missing" | |
105 | return 1 | |
106 | fi | |
107 | return 0 | |
108 | } | |
109 | ||
110 | activate_vg() | |
111 | { | |
112 | local vg | |
113 | vg="${1#/dev/mapper/}" | |
114 | ||
115 | # Sanity checks | |
116 | if [ ! -x /sbin/lvm ] || [ "$vg" = "$1" ]; then | |
117 | return 1 | |
118 | fi | |
119 | ||
120 | # Make sure that the device contains at least one dash | |
121 | if [ "${vg%%-*}" = "$vg" ]; then | |
122 | return 1 | |
123 | fi | |
124 | ||
125 | # Split volume group from logical volume. | |
126 | vg=$(echo ${vg} | sed -e 's#\(.*\)\([^-]\)-[^-].*#\1\2#') | |
127 | ||
128 | # Reduce padded --'s to -'s | |
129 | vg=$(echo ${vg} | sed -e 's#--#-#g') | |
130 | ||
131 | lvm vgchange -ay ${vg} | |
132 | return $? | |
133 | } | |
134 | ||
135 | activate_evms() | |
136 | { | |
137 | local dev module | |
138 | dev="${1#/dev/evms/}" | |
139 | ||
140 | # Sanity checks | |
141 | if [ ! -x /sbin/evms_activate ] || [ "$dev" = "$1" ]; then | |
142 | return 1 | |
143 | fi | |
144 | ||
145 | # Load modules used by evms | |
146 | for module in dm-mod linear raid0 raid1 raid10 raid5 raid6; do | |
147 | /sbin/modprobe -q $module | |
148 | done | |
149 | ||
150 | # Activate it | |
151 | /sbin/evms_activate | |
152 | return $? | |
153 | } | |
154 | ||
155 | setup_mapping() | |
156 | { | |
157 | local opts count cryptcreate cryptremove NEWROOT | |
158 | opts="$1" | |
159 | ||
160 | if [ -z "$opts" ]; then | |
161 | return 0 | |
162 | fi | |
163 | ||
164 | parse_options "$opts" || return 1 | |
165 | ||
166 | if [ -n "$cryptkeyscript" ] && [ ! -x "$cryptkeyscript" ]; then | |
167 | message "cryptsetup: error - script \"$cryptkeyscript\" missing" | |
168 | return 1 | |
169 | fi | |
170 | ||
171 | # The same target can be specified multiple times | |
172 | # e.g. root and resume lvs-on-lvm-on-crypto | |
173 | if [ -e "/dev/mapper/$crypttarget" ]; then | |
174 | return 0 | |
175 | fi | |
176 | ||
177 | /sbin/modprobe -q dm_crypt | |
178 | ||
179 | # Make sure the cryptsource device is available | |
180 | if [ ! -e $cryptsource ]; then | |
181 | activate_vg $cryptsource | |
182 | activate_evms $cryptsource | |
183 | fi | |
184 | ||
185 | /sbin/udevadm settle --timeout=30 | |
186 | ||
187 | if [ ! -e $cryptsource ]; then | |
188 | message "cryptsetup: source device $cryptsource not found" | |
189 | return 1 | |
190 | fi | |
191 | ||
192 | # Prepare commands | |
193 | if /sbin/cryptsetup isLuks $cryptsource > /dev/null 2>&1; then | |
194 | cryptcreate="/sbin/cryptsetup -T 1 luksOpen $cryptsource $crypttarget" | |
195 | else | |
196 | cryptcreate="/sbin/cryptsetup -T 1 -c $cryptcipher -s $cryptsize -h $crypthash create $crypttarget $cryptsource" | |
197 | fi | |
198 | cryptremove="/sbin/cryptsetup remove $crypttarget" | |
199 | NEWROOT="/dev/mapper/$crypttarget" | |
200 | ||
201 | # Try to get a satisfactory password $crypttries times | |
202 | count=0 | |
203 | while [ $crypttries -le 0 ] || [ $count -lt $crypttries ]; do | |
204 | count=$(( $count + 1 )) | |
205 | ||
206 | if [ $count -gt 1 ]; then | |
207 | sleep 3 | |
208 | fi | |
209 | ||
210 | if [ $crypttries -gt 0 ] && [ $count -gt $crypttries ]; then | |
211 | message "cryptsetup: maximum number of tries exceeded for $crypttarget" | |
212 | return 1 | |
213 | fi | |
214 | ||
215 | if [ -z "$cryptkeyscript" ]; then | |
216 | cryptkeyscript="/lib/cryptsetup/askpass" | |
217 | cryptkey="Enter passphrase to unlock the disk $cryptsource ($crypttarget): " | |
218 | fi | |
219 | ||
220 | ||
221 | if ! crypttarget="$crypttarget" cryptsource="$cryptsource" \ | |
222 | $cryptkeyscript "$cryptkey" | $cryptcreate --key-file=- ; then | |
223 | message "cryptsetup: cryptsetup failed, bad password or options?" | |
224 | continue | |
225 | fi | |
226 | ||
227 | if [ ! -e "$NEWROOT" ]; then | |
228 | message "cryptsetup: unknown error setting up device mapping" | |
229 | return 1 | |
230 | fi | |
231 | ||
232 | FSTYPE='' | |
233 | eval $(fstype < "$NEWROOT") | |
234 | ||
235 | # See if we need to setup lvm on the crypto device | |
236 | if [ "$FSTYPE" = "lvm" ] || [ "$FSTYPE" = "lvm2" ]; then | |
237 | if [ -z "$cryptlvm" ]; then | |
238 | message "cryptsetup: lvm fs found but no lvm configured" | |
239 | return 1 | |
240 | elif ! activate_vg "/dev/mapper/$cryptlvm"; then | |
241 | message "cryptsetup: failed to setup lvm device" | |
242 | return 1 | |
243 | fi | |
244 | ||
245 | NEWROOT="/dev/mapper/$cryptlvm" | |
246 | eval $(fstype < "$NEWROOT") | |
247 | fi | |
248 | ||
249 | if [ -z "$FSTYPE" ] || [ "$FSTYPE" = "unknown" ]; then | |
250 | message "cryptsetup: unknown fstype, bad password or options?" | |
251 | $cryptremove | |
252 | continue | |
253 | fi | |
254 | ||
255 | message "cryptsetup: $crypttarget setup successfully" | |
256 | break | |
257 | done | |
258 | ||
259 | /sbin/udevadm settle --timeout=30 | |
260 | return 0 | |
261 | } | |
262 | ||
263 | # | |
264 | # Begin real processing | |
265 | # | |
266 | ||
267 | # Do we have any kernel boot arguments? | |
268 | found='' | |
269 | for opt in $(cat /proc/cmdline); do | |
270 | case $opt in | |
271 | cryptopts=*) | |
272 | found=yes | |
273 | setup_mapping "${opt#cryptopts=}" | |
274 | ;; | |
275 | esac | |
276 | done | |
277 | ||
278 | if [ -n "$found" ]; then | |
279 | exit 0 | |
280 | fi | |
281 | ||
282 | # Do we have any settings from the /conf/conf.d/cryptroot file? | |
283 | if [ -r /conf/conf.d/cryptroot ]; then | |
284 | while read mapping <&3; do | |
285 | setup_mapping "$mapping" | |
286 | done 3< /conf/conf.d/cryptroot | |
287 | fi | |
288 | ||
289 | exit 0 |