aboutsummaryrefslogtreecommitdiffstats
path: root/pre-partman.sh
blob: 5c394ed1ff1d2f47d5497f0cc1450244dbc72c8a (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
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
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
#!/bin/sh
#
# Set up a SSH daemon, the sole purpose of which is to slurp the key for
# full disk encryption, so that it doesn't have to be manually entered
# to the installer.
#
# Copyright 2013 Guilhem Moulin <guilhem@fripost.org>
#
# Licensed under the GNU GPL version 3 or higher.

set -ue
root=/cdrom

. /usr/share/debconf/confmodule

debconf-loadtemplate fripost-install $root/preseed/fripost-install.template

db_input high fripost-install/full-disk-encryption || true
db_go
db_get fripost-install/full-disk-encryption
[ x"${RET:-true}" = x"false" ] && exit 0

##############################################################################
# Crypto, disk and network modules, required to unlock the system from
# our initramfs.
# TODO: should probably be stored in debconf, since we'll need the
# modules in the target only
while read k rest; do /sbin/modinfo -F filename "$k"; done < /proc/modules \
| sed -nr "s@^/lib/modules/`uname -r`/kernel/(arch|drivers/(ata|scsi))(/.*)?/([^/]+)\.ko\$@\4@p" \
> /tmp/initramfs-modules


##############################################################################
# Slurp encryption key

db_input high fripost-install/full-disk-encryption-password || true
db_go
db_get fripost-install/full-disk-encryption-password

keyfile=~root/root.key
if [ -n "$RET" ]; then
    touch "$keyfile"
    chmod 0644 "$keyfile"
    echo $RET >> "$keyfile"
    # TODO: remove passord from debconf
else
    anna-install openssh-server-udeb

    mkdir -pm0755 /etc/ssh/
    sshHostKey=/etc/ssh/ssh_host_rsa_key
    ssh-keygen -b 4096 -t rsa -N '' -C $sshHostKey -f $sshHostKey

    cat > /etc/ssh/sshd_config <<- EOF
	Port 22
	Protocol 2
	HostKey $sshHostKey
	UsePrivilegeSeparation no

	PasswordAuthentication no
	ChallengeResponseAuthentication no
	HostbasedAuthentication no
	PubkeyAuthentication yes

	PermitRootLogin yes
	AllowUsers root
	StrictModes yes

	#ForceCommand /bin/sh -c 'umask 0077; cat > $keyfile'
	EOF

    # Populate the authorized keys.
    test -d ~root/.ssh || mkdir -m 0700 ~root/.ssh
    sed 's/^/no-agent-forwarding,no-port-forwarding,no-pty,no-user-rc,no-X11-forwarding /' \
            $root/preseed/authorized_keys > ~root/.ssh/authorized_keys
    chmod og-rwx ~root/.ssh/authorized_keys

    # Start the SSH daemon
    touch /var/log/lastlog
    /usr/sbin/sshd

    # Tell the user we're ready
    db_subst fripost-install/full-disk-encryption-slurpkey_text IPv4 \
        "$(ip addr show eth0 | sed -nr 's/^\s+inet\s([0-9.]{4,32}).*/\1/p')"
    db_subst fripost-install/full-disk-encryption-slurpkey_text SSHFPR_SERVER \
        "$(ssh-keygen -lf $sshHostKey)"
    db_subst fripost-install/full-disk-encryption-slurpkey_text SSHFPR_AUTHORIZED \
        "$($root/preseed/sshfprs.sh ~root/.ssh/authorized_keys '    - ')"

    # Anything sent to the SSH is stored into $keyfile, which is our LUKS key.
    until test -r "$keyfile"; do
        db_settitle fripost-install/full-disk-encryption-slurpkey_title
        db_input critical fripost-install/full-disk-encryption-slurpkey_text
        db_go
    done

    kill `cat /var/run/sshd.pid` || true
fi


##############################################################################
# Fill the disk with random data

db_input high fripost-install/full-disk-encryption-fill || true
db_go
db_get fripost-install/full-disk-encryption-fill
dev="$RET"

heartbeat () {
    local pid sig sleep
    pid=$1
    sig=${2:-SIGHUP}
    sleep=${3:-1}

    until false; do
        sleep $sleep
        /bin/kill -$sig $pid 2>/dev/null || break
    done
}
if [ x"$RET" != x"none" ]; then
    source="/dev/$RET"
    bs=4096
    disk=$(list-devices disk | head -1)
    size=$(parted_devices "$disk" | cut -f2)

    fill="dd if=$source of=$disk bs=$bs"
    db_subst fripost-install/full-disk-encryption-fill_progress_title DISK "$disk"
    db_subst fripost-install/full-disk-encryption-fill_progress_title SIZE "$size"
    if [ x"$source" = x"/dev/zero" ]; then
        db_subst fripost-install/full-disk-encryption-fill_progress_title WHAT "zeroes"
    elif [ x"$source" = x"/dev/random" -o x"$source" = x"/dev/urandom" ]; then
        db_subst fripost-install/full-disk-encryption-fill_progress_title WHAT "bytes of random data"
    else
        db_subst fripost-install/full-disk-encryption-fill_progress_title WHAT "bytes"
    fi
    db_progress START 0 $(( $size / $bs )) fripost-install/full-disk-encryption-fill_progress_title
    db_subst fripost-install/full-disk-encryption-fill_progress_info COMMAND "$fill"
    db_progress INFO fripost-install/full-disk-encryption-fill_progress_info

    fifo=$(mktemp -u)
    mknod "$fifo" p
    trap 'echo kill $pid' EXIT
    $fill 2> "$fifo" & pid=$!
    heartbeat $pid USR1 &

    while read -u 7 n records dir; do
        [ x"$records" = x"records" -a x"$dir" = x"out" ] && db_progress SET ${n%+*}
    done 7< "$fifo"

    rm "$fifo"
    trap '' EXIT

    db_progress STOP
    db_unregister fripost-install/full-disk-encryption-fill_progress_title
    db_unregister fripost-install/full-disk-encryption-fill_progress_info

    # http://horde.net/~jwm/blog/progress-bars-with-debconf/
    # http://horde.net/~jwm/blog/how-shell-scripts-communicate-with-debconf/
fi


##############################################################################
# Partitioning

anna-install parted-udeb
dev=/dev/sda

offset=`cat /sys/block/${dev#/dev/}/alignment_offset`
bs=`cat /sys/block/${dev#/dev/}/queue/physical_block_size`

if [ $offset -eq 0 ]; then
    offset=64
else
    offset=$(( $offset / $bs ))
fi

parted            -sm $dev mklabel gpt
grain=$(( 256*32 ))
# All offset2's must be multiple of 256*32 = 8192
if [ -d /proc/efi ] || [ -d /sys/firmware/efi ]; then
    offset2=$(( 256 * 1024**2 / $bs ))
    offset2=$(( $offset2 - $offset2 % $grain ))
    parted -a minimal -sm $dev mkpart uefi ${offset}s $(( $offset2 - 1 ))s
    offset=$offset2
    offset2=$(( $offset + 64 * 1024**2 / $bs ))
    offset2=$(( $offset2 - $offset2 % $grain ))
    parted -a minimal -sm $dev mkpart boot ${offset}s $(( $offset2 - 1))s
    parted -sm $dev set 1 boot on
else
    offset2=$(( 64 * 1024**2 / $bs ))
    parted -a minimal -sm $dev mkpart boot ${offset}s $(( $offset2 - 1))s
fi
offset=$offset2
offset2=$(( `cat /sys/block/${dev#/dev/}/size` - 1 ))
offset2=$(( $offset2 - $offset2 % $grain ))
parted -a optimal -sm $dev mkpart system ${offset}s $(( $offset2 - 1))s
system=${dev}$(parted -sm $dev p | grep -m 1 '^[1-9][0-9]*:.*:system:[^:]*;$' | sed 's/:.*//')
parted -sm $dev align-check opt ${system#$dev}


##############################################################################
# Encryption

anna-install cryptsetup-udeb crypto-dm-modules
if dmsetup targets | cut -d' ' -f1 | grep -q '^crypt$'; then true; else
    insmod /lib/modules/`uname -r`/kernel/drivers/md/dm-crypt.ko
fi

arch=$(uname -m)
if [ x"$arch" = x"x86_64" ]; then
    keysize=256
    hash=sha512
elif [ x"$arch" = x"i386" -o x"$arch" = x"i686" ]; then
    keysize=128
    hash=sha256
fi
# Notes: 1/ XTS requires the key size to be doubled, 2/ We use AES128
# and SHA-256 on 32-bits platforms, and AES256 and SHA-512 on 64-bits
# platforms.
# TODO: Note: Generating key... (this may take a while)
/sbin/cryptsetup -q --align-payload $grain \
    --cipher aes-xts-plain64 --key-size $(( $keysize * 2 )) --hash $hash \
    --iter-time 5000 --use-random --key-file="$keyfile" \
    luksFormat $system
/sbin/cryptsetup luksOpen --key-file="$keyfile" $system system_crypt
rm "$keyfile" # We are on a ramdisk, so it's good enough to unlink(2)


##############################################################################
# LVM

/sbin/pvcreate /dev/mapper/system_crypt
db_get netcfg/get_hostname
/sbin/vgcreate "$RET" /dev/mapper/system_crypt

# TODO: Point the installer at the partitions we created