]> git.pld-linux.org Git - projects/geninitrd.git/blob - mod-luks.sh
- do not try to extract encrypted device name from an active LUKS device – the
[projects/geninitrd.git] / mod-luks.sh
1 #!/bin/sh
2 LUKS_RCSID='$Revision$ $Date::                            $'
3
4 # geninitrd mod: cryptsetup luks
5 USE_LUKS=${USE_LUKS:-yes}
6
7 # true if root device is crypted with cryptsetup luks
8 # and we should init cryptsetup luks at boot
9 have_luks=no
10
11 # device to use for name for cryptsetup luks
12 LUKSNAME=""
13
14 # setup geninitrd module
15 # @access       public
16 setup_mod_luks() {
17         cryptsetup=$(find_tool $initrd_dir/cryptsetup /sbin/cryptsetup-initrd)
18
19         if [ ! -x /sbin/cryptsetup ] || [ ! -x "$cryptsetup" ]; then
20                 USE_LUKS=no
21         fi
22 }
23
24 # return true if node is cryptsetup luks encrypted
25 # @param        string $node device node to be examined
26 # @access       public
27 is_luks() {
28         local node="$1"
29
30         # luks not wanted
31         if is_no "$USE_LUKS"; then
32                 return 1
33         fi
34
35         if [ ! -e "$node" ]; then
36                 warn "is_luks(): node $node doesn't exist!"
37                 return 1
38         fi
39
40         local dev dm_status dm_name=${node#/dev/mapper/}
41         if [ "$node" = "$dm_name" ]; then
42                 debug "is_luks: $node is not device mapper name"
43                 return 1
44         fi
45
46         dev=$(/sbin/cryptsetup status $dm_name 2>/dev/null | awk '/device:/{print $2}')
47         if [ "$dev" ]; then
48                 /sbin/cryptsetup isLuks $dev
49                 rc=$?
50         else
51                 # If luks partition was activated using old cryptsetup (at initrd level)
52                 # then "device:" report could be missing from cryptsetup status above.
53                 # Fallback to dmsetup report in such case.
54                 dm_status=$(/sbin/dmsetup status --target crypt $dm_name 2>/dev/null)
55                 if [ -n "$dm_status" ]; then
56                         rc=0
57                 else
58                         rc=1
59                 fi
60         fi
61
62         if [ $rc = 0 ]; then
63                 debug "is_luks: $node is cryptsetup luks"
64         else
65                 debug "is_luks: $node is not cryptsetup luks"
66         fi
67         return $rc
68 }
69
70 # find modules for $devpath
71 # @param        $devpath        device to be examined
72 # @access       public
73 find_modules_luks() {
74         local devpath="$1"
75         local dev=""
76
77         LUKSNAME=${devpath#/dev/mapper/}
78
79         find_module "dm-crypt"
80
81         # TODO: autodetect
82         find_module "aes"
83         find_module "cbc"
84
85         # recurse
86         dev=$(awk '$1 == "'"$LUKSNAME"'" { print $2 }' /etc/crypttab)
87         if [ -n "$dev" ] ; then 
88                 find_modules_for_devpath $dev
89                 have_luks=yes
90         else
91                 die "Cannot find '$LUKSNAME' in /etc/crypttab"
92         fi
93 }
94
95
96 # generate initrd fragment for cryptsetup luks init
97 # @access       public
98 initrd_gen_luks() {
99         if ! is_yes "$have_luks"; then
100                 return
101         fi
102
103         inst_d /bin
104         inst_exec $cryptsetup /bin/cryptsetup
105
106         mount_dev
107         mount_sys
108         initrd_gen_devices
109         # TODO: 'udevadm settle' is called by lukssetup, is udev optional?
110
111         debug "luks: process /etc/crypttab $LUKSNAME"
112         luks_crypttab $LUKSNAME
113 }
114
115
116 # PRIVATE METHODS
117 key_is_random() {
118         [ "$1" = "/dev/urandom" -o "$1" = "/dev/hw_random" -o "$1" = "/dev/random" ]
119 }
120
121 # produce cryptsetup from $name from /etc/crypttab
122 luks_crypttab() {
123         local LUKSNAME="$1"
124
125         # copy from /etc/rc.d/init.d/cryptsetup
126         local dst src key opt mode owner
127
128         while read dst src key opt; do
129                 [ "$dst" != "$LUKSNAME" ] && continue
130
131                 if [ -n "$key" -a "x$key" != "xnone" ]; then
132                         if test -e "$key" ; then
133                                 mode=$(LC_ALL=C ls -l "$key" | cut -c 5-10)
134                                 owner=$(LC_ALL=C ls -l $key | awk '{ print $3 }')
135                                 if [ "$mode" != "------" ] && ! key_is_random "$key"; then
136                                         die "INSECURE MODE FOR $key"
137                                 fi
138                                 if [ "$owner" != root ]; then
139                                         die "INSECURE OWNER FOR $key"
140                                 fi
141                         else
142                                 die "Key file for $dst not found"
143                         fi
144                 else
145                         key=""
146                 fi
147
148                 if /sbin/cryptsetup isLuks "$src" 2>/dev/null; then
149                         if key_is_random "$key"; then
150                                 die "$dst: LUKS requires non-random key, skipping"
151                         fi
152                         if [ -n "$opt" ]; then
153                                 warn "$dst: options are invalid for LUKS partitions, ignoring them"
154                         fi
155                         if [ "$key" ]; then
156                                 keyfile=/etc/.$dst.key
157                                 inst $key $keyfile
158                         fi
159
160                         debug "+ cryptsetup ${keyfile:+-d $keyfile} luksOpen '$src' '$dst'"
161                         add_linuxrc <<-EOF
162                         # cryptsetup can be called twice and in case on crypt on lvm only second
163                         # will succeed because there will be no src device in first cryptsetup call
164                         # this can be called multiple times, before lvm and after lvm.
165                         luksdev='$src'
166                         if [ \${luksdev##/dev/disk/by-uuid/} != \${luksdev} ]; then
167                                 src_uuid=\${luksdev##/dev/disk/by-uuid/}
168                                 while read x y z name; do
169                                         found_uuid=\$(cryptsetup luksUUID /dev/\${name} 2>/dev/null)
170                                         if [ "\$found_uuid" = "\$src_uuid" ]; then
171                                                 luksdev=/dev/\$name
172                                                 break
173                                         fi
174                                 done < /proc/partitions
175                         fi
176
177                         if [ -e "\$luksdev" ]; then
178                                 crypt_status=\$(cryptsetup status '$dst')
179                                 if [ "\${crypt_status%%is inactive.}" != "\$crypt_status" ]; then
180                                         # is inactive
181                                         cryptsetup ${keyfile:+-d $keyfile} luksOpen "\$luksdev" '$dst' <&1
182                                 fi
183                         fi
184
185                         debugshell
186                         EOF
187                 else
188                         die "$dst: only LUKS encryption supported"
189                 fi
190         done < /etc/crypttab
191 }
This page took 0.044013 seconds and 4 git commands to generate.