|
|
@@ -1,4 +1,4 @@
|
|
|
-#!/bin/bash
|
|
|
+#!/usr/bin/env bash
|
|
|
|
|
|
PATH="$PATH:/usr/sbin:/sbin"
|
|
|
RED="\e[31;1m" GREEN="\e[32;1m" YELLOW="\e[33;1m" BLUE="\e[34;1m" PURPLE="\e[35;1m" RESET="\e[0m"
|
|
|
@@ -18,6 +18,7 @@ CONFIG_VARS='
|
|
|
USE_LOCAL_AUTHORIZED_KEYS
|
|
|
USB_GADGET
|
|
|
ETH_DEV
|
|
|
+ NETCFG_IFUPDOWN
|
|
|
'
|
|
|
STATES='
|
|
|
card_partitioned
|
|
|
@@ -44,6 +45,7 @@ USER_OPTS_INFO="
|
|
|
USB_GADGET - enable disk unlocking via SSH over USB (g_ether)
|
|
|
ETH_DEV - select the network device manually (default: auto)
|
|
|
VERBOSE - produce verbose output
|
|
|
+ NETCFG_IFUPDOWN - force configuration of network interface using ifupdown
|
|
|
"
|
|
|
RSYNC_VERBOSITY='--info=progress2'
|
|
|
|
|
|
@@ -55,6 +57,8 @@ print_help() {
|
|
|
'-d' Produce tons of debugging output
|
|
|
'-f' Force reconfiguration of target system
|
|
|
'-F' Force a complete rebuild of target system
|
|
|
+ '-I' Force configuration of target system network interface using
|
|
|
+ ifupdown (/etc/network/interfaces)
|
|
|
'-m' Add all currently loaded modules to the initramfs (may help
|
|
|
fix blank screen on bootup issues)
|
|
|
'-o' Add specified modules to the initramfs (comma-separated list)
|
|
|
@@ -382,14 +386,11 @@ _get_user_vars() {
|
|
|
|
|
|
if [ "$IP_ADDRESS" == 'none' ]; then
|
|
|
UNLOCKING_USERHOST=
|
|
|
- elif [ -e 'authorized_keys' -a "$USE_LOCAL_AUTHORIZED_KEYS" ]; then
|
|
|
- UNLOCKING_USERHOST=
|
|
|
else
|
|
|
_get_user_var 'UNLOCKING_USERHOST' 'USER@HOST' '' \
|
|
|
"Enter the user@host of the machine you'll be unlocking from:" \
|
|
|
'\S+@\S+' \
|
|
|
- 'malformed USER@HOST' \
|
|
|
- '_test_unlocking_host_available'
|
|
|
+ 'malformed USER@HOST'
|
|
|
fi
|
|
|
|
|
|
_get_user_var 'SERIAL_CONSOLE' 'serial console unlocking' '' \
|
|
|
@@ -437,15 +438,13 @@ _test_sdcard_mounted() {
|
|
|
}
|
|
|
|
|
|
get_authorized_keys() {
|
|
|
- if [ -f 'authorized_keys' ]; then
|
|
|
- rm -rf /tmp/armbian_rootenc_build-authorized_keys_file
|
|
|
- mv 'authorized_keys' /tmp/armbian_rootenc_build-authorized_keys_file
|
|
|
- mkdir 'authorized_keys'
|
|
|
- mv /tmp/armbian_rootenc_build-authorized_keys_file 'authorized_keys'
|
|
|
- fi
|
|
|
- [ -e 'authorized_keys' -a "$USE_LOCAL_AUTHORIZED_KEYS" ] || {
|
|
|
- mkdir -p 'authorized_keys'
|
|
|
- rsync "$UNLOCKING_USERHOST:.ssh/id_*.pub" 'authorized_keys'
|
|
|
+ [ -f 'authorized_keys' ] && rm -rf 'authorized_keys' # remove legacy file if present
|
|
|
+ authorized_keys_dir="authorized_keys-$UNLOCKING_USERHOST"
|
|
|
+ [ -e $authorized_keys_dir -a "$USE_LOCAL_AUTHORIZED_KEYS" ] || {
|
|
|
+ _test_unlocking_host_available
|
|
|
+ mkdir -p $authorized_keys_dir
|
|
|
+ rsync "$UNLOCKING_USERHOST:.ssh/id_*.pub" $authorized_keys_dir
|
|
|
+ NEW_AUTHORIZED_KEYS='y'
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -478,6 +477,7 @@ _print_pkgs_to_install() {
|
|
|
pkgs='cryptsetup-initramfs' pkgs_ssh='dropbear-initramfs'
|
|
|
warn "Warning: unrecognized target distribution '$target_distro'" ;;
|
|
|
esac
|
|
|
+ [ "$NETCFG_IFUPDOWN" == 'y' ] && pkgs+=" ifupdown"
|
|
|
[ "$IP_ADDRESS" != 'none' ] && pkgs+=" $pkgs_ssh" ;;
|
|
|
esac
|
|
|
for i in $pkgs; do
|
|
|
@@ -558,6 +558,20 @@ _preclean() {
|
|
|
remove_build_dir
|
|
|
}
|
|
|
|
|
|
+_print_success_msg() {
|
|
|
+ gmsg "All done!"
|
|
|
+ imsg ""
|
|
|
+ imsg " You may now shut down your board, switch removable media if applicable,"
|
|
|
+ imsg " and restart."
|
|
|
+ if [ "$IP_ADDRESS" != "none" ]; then
|
|
|
+ imsg ""
|
|
|
+ imsg " To unlock the disk on the target machine, execute the following from the"
|
|
|
+ imsg " unlocking host:"
|
|
|
+ imsg ""
|
|
|
+ imsg " ssh -p 2222 root@${IP_ADDRESS/dhcp/TARGET_IP}"
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
_clean() {
|
|
|
pu_msg "Cleaning up, please wait..."
|
|
|
_show_output
|
|
|
@@ -566,8 +580,9 @@ _clean() {
|
|
|
umount_target
|
|
|
update_config_vars_file
|
|
|
_close_device_maps 'mounted_on_target'
|
|
|
- [ -e 'authorized_keys' -a -z "$USE_LOCAL_AUTHORIZED_KEYS" ] && shred -u 'authorized_keys'
|
|
|
remove_build_dir
|
|
|
+ [ "$build_success" ] && _print_success_msg
|
|
|
+ true
|
|
|
}
|
|
|
|
|
|
get_armbian_image() {
|
|
|
@@ -607,7 +622,7 @@ _confirm_user_vars() {
|
|
|
[ "$NETMASK" ] && echo " Target netmask: $NETMASK"
|
|
|
echo " Boot partition label: $BOOTPART_LABEL"
|
|
|
echo " Disk password: $DISK_PASSWD"
|
|
|
- [ "$UNLOCKING_USERHOST" ] && echo " user@host of unlocking host: $UNLOCKING_USERHOST"
|
|
|
+ [ "$UNLOCKING_USERHOST" ] && echo " unlocking user@host: $UNLOCKING_USERHOST"
|
|
|
echo " Serial console unlocking: ${SERIAL_CONSOLE:-no}"
|
|
|
echo " SSH over USB unlocking: ${USB_GADGET:-no}"
|
|
|
echo " Ethernet device: ${ETH_DEV:-auto}"
|
|
|
@@ -646,6 +661,9 @@ _update_state_from_config_vars() {
|
|
|
local saved_states cfgvar_changed
|
|
|
saved_states="$(_print_states)"
|
|
|
cfgvar_changed=
|
|
|
+
|
|
|
+ [ "$NEW_AUTHORIZED_KEYS" ] && cfgvar_changed+=' NEW_AUTHORIZED_KEYS' target_configured='n'
|
|
|
+
|
|
|
[ $cARMBIAN_IMAGE != $ARMBIAN_IMAGE ] && cfgvar_changed+=' ARMBIAN_IMAGE' card_partitioned='n'
|
|
|
[ $cBOOTPART_LABEL != $BOOTPART_LABEL ] && cfgvar_changed+=' BOOTPART_LABEL' bootpart_label_created='n'
|
|
|
[ $cROOTFS_NAME != $ROOTFS_NAME ] && cfgvar_changed+=' ROOTFS_NAME' target_configured='n'
|
|
|
@@ -662,6 +680,7 @@ _update_state_from_config_vars() {
|
|
|
[ "$cADD_MODS" != "$ADD_MODS" ] && cfgvar_changed+=' ADD_MODS' target_configured='n'
|
|
|
[ "$cUSB_GADGET" != "$USB_GADGET" ] && cfgvar_changed+=' USB_GADGET' target_configured='n'
|
|
|
[ "$cETH_DEV" != "$ETH_DEV" ] && cfgvar_changed+=' ETH_DEV' target_configured='n'
|
|
|
+ [ "$cNETCFG_IFUPDOWN" != "$NETCFG_IFUPDOWN" ] && cfgvar_changed+=' NETCFG_IFUPDOWN' target_configured='n'
|
|
|
[ "$IP_ADDRESS" -a "$cUSE_LOCAL_AUTHORIZED_KEYS" != "$USE_LOCAL_AUTHORIZED_KEYS" ] && {
|
|
|
cfgvar_changed+=' USE_LOCAL_AUTHORIZED_KEYS' target_configured='n'
|
|
|
}
|
|
|
@@ -804,12 +823,13 @@ create_partition_label() {
|
|
|
}
|
|
|
|
|
|
copy_boot_loader() {
|
|
|
- local bs=4096 skip count
|
|
|
- case $partition_table_type in 'dos') skip=0;; 'gpt') skip=8;; esac # LBA8 (0x8000): boot loader magic string
|
|
|
- count=$((start_sector / 8 - $skip))
|
|
|
- pu_msg "Copying boot loader ($count 4K blocks [$((count*8)) sectors], starting at $skip blocks [$((skip*8)) sectors]):"
|
|
|
+ local skip count
|
|
|
+ # GPT bootloader starts at LBA 8 (0x8000, sector 64):
|
|
|
+ case $partition_table_type in 'dos') skip=0;; 'gpt') skip=64;; esac
|
|
|
+ count=$((start_sector - skip))
|
|
|
+ pu_msg "Copying boot loader ($count sectors, starting at sector $skip [LBA $((skip / 8))]):"
|
|
|
_show_output
|
|
|
- dd if=$ARMBIAN_IMAGE of="/dev/$SDCARD_DEVNAME" status='progress' bs=$bs count=$count skip=$skip seek=$skip
|
|
|
+ dd if=$ARMBIAN_IMAGE of="/dev/$SDCARD_DEVNAME" status='progress' bs=512 count=$count skip=$skip seek=$skip
|
|
|
_hide_output
|
|
|
do_partprobe
|
|
|
}
|
|
|
@@ -907,7 +927,7 @@ copy_system_root() {
|
|
|
|
|
|
pu_msg "Copying system to encrypted root partition:"
|
|
|
_show_output
|
|
|
- rsync $RSYNC_VERBOSITY --archive --exclude=boot $SRC_ROOT/* $TARGET_ROOT
|
|
|
+ rsync $RSYNC_VERBOSITY --archive --exclude='boot' --exclude='var/cache/apt/archives' $SRC_ROOT/* $TARGET_ROOT
|
|
|
_hide_output
|
|
|
sync
|
|
|
|
|
|
@@ -1163,7 +1183,7 @@ edit_initramfs_modules() {
|
|
|
copy_authorized_keys() {
|
|
|
local dest="$TARGET_ROOT$dropbear_dir"
|
|
|
mkdir -p $dest
|
|
|
- /bin/cat authorized_keys/* > "$dest/authorized_keys"
|
|
|
+ /bin/cat $authorized_keys_dir/* > "$dest/authorized_keys"
|
|
|
chmod 644 "$dest/authorized_keys"
|
|
|
_display_file "$dest/authorized_keys"
|
|
|
}
|
|
|
@@ -1224,18 +1244,12 @@ ifupdown_config_usb0() {
|
|
|
local file bu_file text
|
|
|
file="$TARGET_ROOT/etc/network/interfaces"
|
|
|
bu_file="$file.rootenc.orig"
|
|
|
- text="
|
|
|
-
|
|
|
-auto usb0
|
|
|
-iface usb0 inet static
|
|
|
- address $IP_ADDRESS
|
|
|
- netmask $NETMASK
|
|
|
-"
|
|
|
+ text="\nauto usb0\niface usb0 inet static\n\taddress $IP_ADDRESS\n\tnetmask $NETMASK"
|
|
|
if [ -e $file ]; then
|
|
|
if [ "$USB_GADGET" -a "$IP_ADDRESS" != 'dhcp' ]; then
|
|
|
grep -q '^auto usb0' $file || {
|
|
|
/bin/cp $file $bu_file
|
|
|
- echo "$text" >> $file
|
|
|
+ echo -e "$text" >> $file
|
|
|
}
|
|
|
systemctl mask network-manager
|
|
|
else
|
|
|
@@ -1269,11 +1283,15 @@ exit 0'
|
|
|
|
|
|
# begin chroot functions:
|
|
|
|
|
|
+_pkg_remove() {
|
|
|
+ dpkg -s $1 2>/dev/null | grep ^Status | grep -q installed && apt-get --yes purge $1 || :
|
|
|
+}
|
|
|
+
|
|
|
apt_remove_target_pkgs() {
|
|
|
- if [ "$IP_ADDRESS" == 'none' ]; then
|
|
|
- apt --yes purge 'dropbear-initramfs' || :
|
|
|
- fi
|
|
|
- apt --yes purge 'bash-completion' 'command-not-found' || :
|
|
|
+ [ "$IP_ADDRESS" == 'none' ] && _pkg_remove 'dropbear-initramfs'
|
|
|
+ _pkg_remove 'bash-completion'
|
|
|
+ _pkg_remove 'command-not-found'
|
|
|
+ true
|
|
|
}
|
|
|
|
|
|
apt_install_target_pkgs() {
|
|
|
@@ -1300,6 +1318,29 @@ apt_install_target_pkgs() {
|
|
|
true
|
|
|
}
|
|
|
|
|
|
+ifupdown_config_eth0() {
|
|
|
+ local dir file text
|
|
|
+ dir="/etc/network/interfaces.d"
|
|
|
+ mkdir -p $dir
|
|
|
+ file="$dir/$eth_dev"
|
|
|
+ rm -rf $file
|
|
|
+ if [ "$NETCFG_IFUPDOWN" == 'y' ]; then
|
|
|
+ if [ "$IP_ADDRESS" == 'dhcp' ]; then
|
|
|
+ text="auto $eth_dev\niface $eth_dev inet dhcp"
|
|
|
+ else
|
|
|
+ text="auto $eth_dev\niface $eth_dev inet static\n\taddress $IP_ADDRESS\n\tnetmask $NETMASK"
|
|
|
+ fi
|
|
|
+ systemctl -q is-enabled 'networking' || { systemctl unmask 'networking'; systemctl enable 'networking'; }
|
|
|
+ systemctl -q is-enabled 'networking' || die "fatal error: unable to enable networking service (ifupdown)"
|
|
|
+ echo -e "$text" > $file
|
|
|
+ _display_file $file
|
|
|
+ else
|
|
|
+ systemctl -q is-enabled 'networking' && systemctl mask 'networking'
|
|
|
+ systemctl -q is-enabled 'networking' && die "fatal error: unable to mask networking service"
|
|
|
+ true
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
update_initramfs() {
|
|
|
[ "$ROOTENC_TESTING" ] && return 0
|
|
|
_show_output
|
|
|
@@ -1364,7 +1405,7 @@ configure_target() {
|
|
|
|
|
|
_show_output # this must be done before entering chroot
|
|
|
/bin/cp $0 $TARGET_ROOT
|
|
|
- export 'ROOTFS_NAME' 'IP_ADDRESS' 'target_distro' 'ROOTENC_TESTING' 'ROOTENC_PAUSE' 'ROOTENC_IGNORE_APT_ERRORS' 'APT_UPGRADE'
|
|
|
+ export 'ROOTFS_NAME' 'IP_ADDRESS' 'target_distro' 'ROOTENC_TESTING' 'ROOTENC_PAUSE' 'ROOTENC_IGNORE_APT_ERRORS' 'APT_UPGRADE' 'eth_dev'
|
|
|
|
|
|
chroot $TARGET_ROOT "./$PROGNAME" $ORIG_OPTS 'in_target'
|
|
|
|
|
|
@@ -1398,13 +1439,14 @@ _mount_target_and_exit() {
|
|
|
|
|
|
set -e
|
|
|
|
|
|
-while getopts hCfFmo:MUpRsudvz OPT
|
|
|
+while getopts hCfFImo:MUpRsudvz OPT
|
|
|
do
|
|
|
case "$OPT" in
|
|
|
h) print_help; exit ;;
|
|
|
C) NO_CLEANUP='y' ;;
|
|
|
f) FORCE_RECONFIGURE='y' ;;
|
|
|
F) FORCE_REBUILD='y' ;;
|
|
|
+ I) NETCFG_IFUPDOWN='y' ;;
|
|
|
m) ADD_ALL_MODS='y' ;;
|
|
|
o) ADD_MODS=$OPTARG ;;
|
|
|
M) MOUNT_TARGET_ONLY='y' ;;
|
|
|
@@ -1454,6 +1496,7 @@ if [ "$ARG1" == 'in_target' ]; then
|
|
|
}
|
|
|
apt_remove_target_pkgs
|
|
|
apt_install_target_pkgs
|
|
|
+ ifupdown_config_eth0
|
|
|
[ "$initramfs_updated" ] || update_initramfs
|
|
|
gen_target_ssh_host_keys
|
|
|
check_initramfs
|
|
|
@@ -1504,10 +1547,5 @@ else
|
|
|
[ "$target_configured" == 'n' ] && configure_target
|
|
|
|
|
|
sync
|
|
|
- gmsg 'All done!'
|
|
|
-
|
|
|
- if [ "$IP_ADDRESS" != 'none' ]; then
|
|
|
- imsg "To unlock the target disk, execute the following from the unlocking host:"
|
|
|
- imsg " ssh -p 2222 root@${IP_ADDRESS/dhcp/TARGET_IP}"
|
|
|
- fi
|
|
|
+ build_success=1
|
|
|
fi
|