]> git.pld-linux.org Git - projects/geninitrd.git/blob - mod-luks.sh
- magic to get the LUKS lower level device name when initialized with old cryptsetup
[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 LUKSDEV=""
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         local name=${devpath#/dev/mapper/}
78         LUKSDEV=$(/sbin/cryptsetup status $name 2>/dev/null | awk '/device:/{print $2}')
79         if [ -z "$LUKSDEV" ]; then
80                 # could be initialized by old cryptsetup, we need some magic
81                 vars=$(dmsetup deps lolek_crypt | awk '/dependencies.*(.*)/ { left=index($0, "("); right=index($0, ")"); split(substr($0, left + 1, right - left - 1), A, " *, *") ; print "major=" A[1] "; minor=" A[2] }')
82                 eval "$vars"
83                 if [ -n "$major" -a -n "$minor" ] ; then
84                         LUKSDEV=$(awk "\$1 == $major && \$2 == $minor { print \"/dev/\" \$4 }" /proc/partitions)
85                 fi
86
87         fi
88         if [ -z "$LUKSDEV" ]; then
89                 die "Lost cryptsetup device meanwhile?"
90         fi
91
92         find_module "dm-crypt"
93
94         # TODO: autodetect
95         find_module "aes"
96         find_module "cbc"
97
98         have_luks=yes
99
100         # recurse
101         find_modules_for_devpath $LUKSDEV
102 }
103
104
105 # generate initrd fragment for cryptsetup luks init
106 # @access       public
107 initrd_gen_luks() {
108         if ! is_yes "$have_luks"; then
109                 return
110         fi
111
112         inst_d /bin
113         inst_exec $cryptsetup /bin/cryptsetup
114
115         mount_dev
116         mount_sys
117         initrd_gen_devices
118         # TODO: 'udevadm settle' is called by lukssetup, is udev optional?
119
120         debug "luks: process /etc/crypttab $LUKSDEV"
121         luks_crypttab $LUKSDEV
122 }
123
124
125 # PRIVATE METHODS
126 key_is_random() {
127         [ "$1" = "/dev/urandom" -o "$1" = "/dev/hw_random" -o "$1" = "/dev/random" ]
128 }
129
130 # produce cryptsetup from $name from /etc/crypttab
131 luks_crypttab() {
132         local LUKSDEV="$1"
133
134         # copy from /etc/rc.d/init.d/cryptsetup
135         local dst src key opt mode owner
136
137         while read dst src key opt; do
138                 [ -z "$dst" -o "${dst#\#}" != "$dst" ] && continue
139                 [ "$src" != "$LUKSDEV" ] && [ "$(readlink -f $src)" != "$LUKSDEV" ] && continue
140
141                 if [ -n "$key" -a "x$key" != "xnone" ]; then
142                         if test -e "$key" ; then
143                                 mode=$(LC_ALL=C ls -l "$key" | cut -c 5-10)
144                                 owner=$(LC_ALL=C ls -l $key | awk '{ print $3 }')
145                                 if [ "$mode" != "------" ] && ! key_is_random "$key"; then
146                                         die "INSECURE MODE FOR $key"
147                                 fi
148                                 if [ "$owner" != root ]; then
149                                         die "INSECURE OWNER FOR $key"
150                                 fi
151                         else
152                                 die "Key file for $dst not found"
153                         fi
154                 else
155                         key=""
156                 fi
157
158                 if /sbin/cryptsetup isLuks "$src" 2>/dev/null; then
159                         if key_is_random "$key"; then
160                                 die "$dst: LUKS requires non-random key, skipping"
161                         fi
162                         if [ -n "$opt" ]; then
163                                 warn "$dst: options are invalid for LUKS partitions, ignoring them"
164                         fi
165                         if [ "$key" ]; then
166                                 keyfile=/etc/.$dst.key
167                                 inst $key $keyfile
168                         fi
169
170                         debug "+ cryptsetup ${keyfile:+-d $keyfile} luksOpen '$src' '$dst'"
171                         add_linuxrc <<-EOF
172                         # cryptsetup can be called twice and in case on crypt on lvm only second
173                         # will succeed because there will be no src device in first cryptsetup call
174                         # this can be called multiple times, before lvm and after lvm.
175                         luksdev='$src'
176                         if [ \${luksdev##/dev/disk/by-uuid/} != \${luksdev} ]; then
177                                 src_uuid=\${luksdev##/dev/disk/by-uuid/}
178                                 while read x y z name; do
179                                         found_uuid=\$(cryptsetup luksUUID /dev/\${name} 2>/dev/null)
180                                         if [ "\$found_uuid" = "\$src_uuid" ]; then
181                                                 luksdev=/dev/\$name
182                                                 break
183                                         fi
184                                 done < /proc/partitions
185                         fi
186
187                         if [ -e "\$luksdev" ]; then
188                                 crypt_status=\$(cryptsetup status '$dst')
189                                 if [ "\${crypt_status%%is inactive.}" != "\$crypt_status" ]; then
190                                         # is inactive
191                                         cryptsetup ${keyfile:+-d $keyfile} luksOpen "\$luksdev" '$dst' <&1
192                                 fi
193                         fi
194
195                         debugshell
196                         EOF
197                 else
198                         die "$dst: only LUKS encryption supported"
199                 fi
200         done < /etc/crypttab
201 }
This page took 0.048041 seconds and 4 git commands to generate.