3 ################################################
 
   4 ### Managed by someone's ansible provisioner ###
 
   5 ################################################
 
   6 # Part of: https://git.somenet.org/root/pub/somesible.git
 
   7 # 2017-2025 by someone <someone@somenet.org>
 
  10 PREREQ="cryptroot-prepare"
 
  13 # Standard initramfs preamble
 
  17         # Make sure that cryptroot is run last in local-top
 
  19         for req in "${0%/*}"/*; do
 
  21                 if [ "$script" != "${0##*/}" ]; then
 
  22                         printf '%s\n' "$script"
 
  36 [ -f /lib/cryptsetup/functions ] || return 0
 
  37 . /lib/cryptsetup/functions
 
  41 #   Wait for encrypted $CRYPTTAB_SOURCE . Set $CRYPTTAB_SOURCE
 
  42 #   to its normalized device name when it shows up;
 
  43 #   return 1 if timeout.
 
  47     if crypttab_resolve_source; then
 
  48         # the device is here already, no need to loop
 
  52     # If the source device hasn't shown up yet, give it a little while
 
  53     # to allow for asynchronous device discovery (e.g. USB).
 
  55     # We also need to take into account RAID or other devices that may
 
  56     # only be available on local-block stage. So, wait 5 seconds upfront,
 
  57     # in local-top; if that fails, end execution relying on local-block
 
  58     # invocations. Allow $ROOTDELAY/4 invocations with 1s sleep times (with
 
  59     # a minimum of 20 invocations), and if after that we still fail, then it's
 
  60     # really time to give-up. Variable $initrd_cnt tracks the re-invocations.
 
  62     # Part of the lines below has been taken from initramfs-tools
 
  63     # scripts/local's local_device_setup(), as suggested per
 
  64     # https://launchpad.net/bugs/164044 .
 
  67     if [ "${CRYPTROOT_STAGE-}" = "local-block" ]; then
 
  71     cryptsetup_message "Waiting for encrypted source device $CRYPTTAB_SOURCE..."
 
  73     while [ $slumber -gt 0 ]; do
 
  76         if crypttab_resolve_source; then
 
  81         slumber=$(( $slumber - 1 ))
 
  87 #   Set up a crypttab(5) mapping defined by $CRYPTTAB_NAME,
 
  88 #   $CRYPTTAB_SOURCE, $CRYPTTAB_KEY, $CRYPTTAB_OPTIONS.
 
  92     # We control here the number of re-invocations of this script from
 
  93     # local-block - the heuristic is $ROOTDELAY/4, with a minimum of 20.
 
  95     if [ -f "$CRYPTROOT_COUNT_FILE" ]; then
 
  96         initrd_cnt="$(cat <"$CRYPTROOT_COUNT_FILE")"
 
  98         initrd_cnt="${ROOTDELAY:-180}"
 
  99         initrd_cnt=$(( initrd_cnt/4 ))
 
 100         if [ $initrd_cnt -lt 20 ]; then
 
 103         echo "$initrd_cnt" >"$CRYPTROOT_COUNT_FILE"
 
 106     # The same target can be specified multiple times
 
 107     # e.g. root and resume lvs-on-lvm-on-crypto
 
 108     if dm_blkdevname "$CRYPTTAB_NAME" >/dev/null; then
 
 112     crypttab_parse_options --export --missing-path=fail || return 1
 
 114     if ! wait_for_source; then
 
 115         if [ $initrd_cnt -eq 0 ]; then
 
 117             if [ -n "$panic" ]; then
 
 118                 panic "ALERT! encrypted source device $CRYPTTAB_SOURCE does not exist, can't unlock $CRYPTTAB_NAME."
 
 120                 # let the user fix matters if they can
 
 121                 echo "  ALERT! encrypted source device $CRYPTTAB_SOURCE does not exist, can't unlock $CRYPTTAB_NAME."
 
 122                 echo "  Check cryptopts=source= bootarg: cat /proc/cmdline"
 
 123                 echo "  or missing modules, devices: cat /proc/modules; ls /dev"
 
 124                 panic "Dropping to a shell."
 
 126             return 1 # can't continue because environment is lost
 
 128             initrd_cnt=$(( initrd_cnt - 1 ))
 
 129             echo "$initrd_cnt" >"$CRYPTROOT_COUNT_FILE"
 
 130             return 0 # allow some attempts on local-block stage
 
 134     # our `cryptroot-unlock` script searches for cryptsetup processes
 
 135     # with a given CRYPTTAB_NAME it their environment
 
 138     if [ -z "${CRYPTTAB_OPTION_keyscript+x}" ]; then
 
 139         # no keyscript: interactive unlocking, or key file
 
 141         if [ "${CRYPTTAB_KEY#/FIXME-initramfs-rootmnt/}" != "$CRYPTTAB_KEY" ]; then
 
 142             # skip the mapping for now if the root FS is not mounted yet
 
 143             sed -rn 's/^\s*[^#[:blank:]]\S*\s+(\S+)\s.*/\1/p' /proc/mounts | grep -Fxq -- "$rootmnt" || return 1
 
 144             # substitute the "/FIXME-initramfs-rootmnt/" prefix by the real root FS mountpoint otherwise
 
 145             CRYPTTAB_KEY="$rootmnt/${CRYPTTAB_KEY#/FIXME-initramfs-rootmnt/}"
 
 148         if [ "$CRYPTTAB_KEY" != "none" ]; then
 
 149             if [ ! -e "$CRYPTTAB_KEY" ]; then
 
 150                 cryptsetup_message "ERROR: Skipping target $CRYPTTAB_NAME: non-existing key file $CRYPTTAB_KEY"
 
 153             # try only once if we have a key file
 
 154             CRYPTTAB_OPTION_tries=1
 
 158     local count=0 maxtries="${CRYPTTAB_OPTION_tries:-3}" fstype vg rv
 
 159     while [ $maxtries -le 0 ] || [ $count -lt $maxtries ]; do
 
 160         if [ -z "${CRYPTTAB_OPTION_keyscript+x}" ] && [ "$CRYPTTAB_KEY" != "none" ]; then
 
 162             unlock_mapping "$CRYPTTAB_KEY"
 
 163             # added by <someone@somenet.org>
 
 165             if [ $urv -ne 0 ]; then
 
 166                 cryptsetup_message "ERROR: Failed to unlock $CRYPTTAB_NAME with $CRYPTTAB_KEY"
 
 167                 /lib/cryptsetup/askpass "Try interactively. Passphrase: " | unlock_mapping
 
 169             # / added by <someone@somenet.org>
 
 171             # unlock interactively or via keyscript
 
 172             run_keyscript "$count" | unlock_mapping
 
 173             # added by <someone@somenet.org>
 
 175             if [ $urv -ne 0 ]; then
 
 176                 cryptsetup_message "ERROR: Failed to unlock $CRYPTTAB_NAME with $CRYPTTAB_KEY"
 
 177                 /lib/cryptsetup/askpass "Try interactively. Passphrase: " | unlock_mapping
 
 179             # / added by <someone@somenet.org>
 
 182         count=$(( $count + 1 ))
 
 184         if [ $rv -ne 0 ]; then
 
 185             cryptsetup_message "ERROR: $CRYPTTAB_NAME: cryptsetup failed, bad password or options?"
 
 188         elif ! dev="$(dm_blkdevname "$CRYPTTAB_NAME")"; then
 
 189             cryptsetup_message "ERROR: $CRYPTTAB_NAME: unknown error setting up device mapping"
 
 193         if ! fstype="$(get_fstype "$dev")" || [ "$fstype" = "unknown" ]; then
 
 194             if [ "$CRYPTTAB_TYPE" != "luks" ]; then
 
 195                 # bad password for plain dm-crypt device?  or mkfs not run yet?
 
 196                 cryptsetup_message "ERROR: $CRYPTTAB_NAME: unknown fstype, bad password or options?"
 
 198                 /sbin/cryptsetup remove -- "$CRYPTTAB_NAME"
 
 204         cryptsetup_message "$CRYPTTAB_NAME: set up successfully"
 
 209     cryptsetup_message "ERROR: $CRYPTTAB_NAME: maximum number of tries exceeded"
 
 214 #######################################################################
 
 215 # Begin real processing
 
 217 mkdir -p /cryptroot # might not exist yet if the main system has no crypttab(5)
 
 219 # Do we have any kernel boot arguments?
 
 220 if ! grep -qE '^(.*\s)?cryptopts=' /proc/cmdline; then
 
 221     # ensure $TABFILE exists and has a mtime greater than the boot time
 
 222     # (existing $TABFILE is preserved)
 
 225     # let the read builtin unescape the '\' as GRUB substitutes '\' by '\\' in the cmdline
 
 226     tr ' ' '\n' </proc/cmdline | sed -n 's/^cryptopts=//p' | while IFS= read cryptopts; do
 
 227         # skip empty values (which can be used to disable the initramfs
 
 228         # scripts for a particular boot, cf. #873840)
 
 229         [ -n "$cryptopts" ] || continue
 
 230         unset -v target source key options
 
 233         for x in $cryptopts; do
 
 235                 target=*) target="${x#target=}";;
 
 236                 source=*) source="${x#source=}";;
 
 237                 key=*) key="${x#key=}";;
 
 238                 *) options="${options+$options,}$x";;
 
 242         if [ -z "${source:+x}" ]; then
 
 243             cryptsetup_message "ERROR: Missing source= value in kernel parameter cryptopts=$cryptopts"
 
 246             printf '%s %s %s %s\n' "${target:-cryptroot}" "$source" "${key:-none}" "${options-}"
 
 251 # Do we have any settings from the $TABFILE?
 
 252 if [ -s "$TABFILE" ]; then
 
 253     # Create locking directory before invoking cryptsetup(8) to avoid warnings
 
 254     mkdir -pm0700 /run/cryptsetup
 
 257     crypttab_foreach_entry setup_mapping