sys: new luksheaders option to backup the Luks header of every Luks device
[matthijs/upstream/backupninja.git] / handlers / sys.in
index 2c48883ce11576639a7ae7231249b59ccd840c6f..de81435463d01e4b44e2bdb051aaee483fab59cb 100755 (executable)
@@ -1,7 +1,7 @@
 # -*- mode: sh; sh-basic-offset: 3; indent-tabs-mode: nil; -*-
 #
 # this handler will save various reports of vital system information.
-# by default, all the reports are enabled and are saved in /var/backups.
+# by default, all the reports are saved in /var/backups.
 #
 # (1) a capture of the debconf package selection states. This file
 #     can be used to restore the answers to debconf questions for
 # (4) hardware information. 
 #     write to a text file the important things which hwinfo can gleen.
 #
+# (5) the Luks header of every Luks block device, if option luksheaders
+#     is enabled.
+#     in case you (have to) scramble such a Luks header (for some time),
+#     and restore it later by running "dd if=luksheader.sda2.bin of=/dev/sda2"
+#     (MAKE SURE YOU PASS THE CORRECT DEVICE AS of= !!!)
+#
 
 if [ -f /etc/debian_version ]
 then
@@ -53,8 +59,8 @@ then
    getconf packagesfile $parentdir/dpkg-selections.txt
    getconf packagemgr   `which dpkg`
    getconf packagemgroptions ' --get-selections *'
-   getconf selectionsfile $parentir/debconfsel.txt
-   getconf debconfgetselections `debconf-get-selections`
+   getconf selectionsfile $parentdir/debconfsel.txt
+   getconf debconfgetselections `which debconf-get-selections`
 elif [ $os = "redhat" ]
 then
    getconf packagesfile  $parentdir/rpmpackages.txt 
@@ -82,6 +88,11 @@ getconf HWINFO `which hwinfo`
 getconf sfdisk_options ""
 getconf hwinfo_options ""
 
+getconf CRYPTSETUP `which cryptsetup`
+getconf DD `which dd`
+getconf luksheaders no
+getconf luksheadersfile $parentdir/luksheader.__star__.bin
+
 getconf vsnames all
 
 # If vservers are configured, check that the ones listed in $vsnames are running.
@@ -97,6 +108,19 @@ if [ $vservers_are_available = yes ]; then
    usevserver=yes
 fi
 
+## SANITY CHECKS #########################
+
+if [ "$luksheaders" == "yes" ]; then
+   if [ ! -x "$DD" ]; then
+      warning "can't find dd, skipping backup of Luks headers."
+      luksheaders="no"
+   fi
+   if [ ! -x "$CRYPTSETUP" ]; then
+      warning "can't find cryptsetup, skipping backup of Luks headers."
+      luksheaders="no"
+   fi
+fi
+
 ## PACKAGES ##############################
 
 #
@@ -116,7 +140,7 @@ if [ "$packages" == "yes" ]; then
             continue
          fi
          # is $packagemgr available inside $vserver ?
-         if [ ! -x "$VROOTDIR/$vserver`$VSERVER $vserver exec which $packagemgr`" ]; then
+         if [ ! -x "${VROOTDIR}/${vserver}${packagemgr}" ]; then
             warning "can't find $packagemgr in vserver $vserver, skipping installed packages report."
          else
             # don't expand * since it can be used in $packagemgroptions
@@ -126,12 +150,21 @@ if [ "$packages" == "yes" ]; then
             set +o noglob
          fi
          # is $debconfgetselections available inside $vserver ?
-         if [ ! -x "$VROOTDIR/$vserver`$VSERVER $vserver exec which $debconfgetselections`" ]; then
-            warning "can't find $debconfgetselections in vserver $vserver, skipping package selection states."
+         found=no
+         # case #1: it is available on the host, is it available inside $vserver ?
+         if [ -n "$debconfgetselections" ]; then
+            [ -x "${VROOTDIR}/${vserver}${debconfgetselections}" ] && found=yes
+         # case #2: it is not available on the host, is it available inside $vserver ?
+         else
+            [ -n "`$VSERVER $vserver exec which debconf-get-selections`" ] && found=yes
+         fi
+         if [ "$found" != yes ]; then
+            warning "can't find debconf-get-selections in vserver $vserver, skipping package selection states. You may want to install the debconf-utils package."
          else
             debug "$VSERVER $vserver exec $debconfgetselections > $VROOTDIR/$vserver$selectionsfile"
-            $VSERVER $vserver exec $debconfgetselections > $VROOTDIR/$vserver$selectionsfile || fatal "can not save $debconfgetselections info to $selectionsfile"
+            $VSERVER $vserver exec $debconfgetselections > $VROOTDIR/$vserver$selectionsfile || fatal "can not save debconf-get-selections info to $selectionsfile"
          fi
+         unset found
       done
    fi
    
@@ -146,7 +179,7 @@ if [ "$packages" == "yes" ]; then
       set +o noglob
    fi
    if [ -z "$debconfgetselections" ]; then
-      warning "can't find ${debconfgetselections}, skilling package selection states."
+      warning "can't find debconf-get-selections, skipping package selection states. You might want to install the debconf-utils package."
    else
       debug "$debconfgetselections > $selectionsfile"
       $debconfgetselections > $selectionsfile || fatal "can not save $debconfgetselections info to $selectionsfile"
@@ -188,10 +221,12 @@ catiffile () {
 } 
 
 catifexec () {
-   echo $HASHES >> $sysreportfile
-   echo "# $STATUS" >> $sysreportfile
-   echo $HASHES >> $sysreportfile
-   $1  >> $sysreportfile 2>&1 || info "executing of $1 failed"
+   if [ -x $1 ]; then
+      echo $HASHES >> $sysreportfile
+      echo "# $STATUS" >> $sysreportfile
+      echo $HASHES >> $sysreportfile
+      $*  >> $sysreportfile 2>&1 || info "executing of $1 failed"
+   fi
 }
    
 
@@ -215,7 +250,7 @@ catifexec "/bin/df" "-al"
 
 STATUS="Collecting what services run at what run level:"
 if [ $os = "redhat" ]; then
-   catifexec "/sbin/chkconfig --list"
+   catifexec "/sbin/chkconfig" "--list"
    STATUS="Collecting information about /etc/rc.d:"
    catiffile "/bin/ls /etc/rc.d/rc*.d/"
 
@@ -234,7 +269,7 @@ elif [ $os = "debian" ]; then
 fi
 
 STATUS="Getting bootloader information:"
-catifexec "/bin/ls -alR /boot"
+catifexec "/bin/ls" "-alR /boot"
 
 # This covers sparc, alpha, and intel (respectively)
 # updated for grub -mpg
@@ -249,7 +284,7 @@ fi
 if [ -f /etc/lilo.conf ]; then
   STATUS="Collecting information about the boot process (lilo):"
   catiffile "/etc/lilo.conf"
-  catifexec "/sbin/lilo -q"
+  catifexec "/sbin/lilo" "-q"
 fi
 if [ -d /boot/grub -a -f /boot/grub/grub.conf -a -f /boot/grub/device.map ]; then
   STATUS="Collecting information about the boot process (grub.conf):"
@@ -275,13 +310,13 @@ STATUS="Gathering sysctl information (/etc/sysctl.conf):"
 catiffile "/etc/sysctl.conf"
 
 STATUS="Gathering IP information (/sbin/ifconfig):"
-catifexec "/sbin/ifconfig -a"
+catifexec "/sbin/ifconfig" "-a"
 
 STATUS="Gathering additional IP information (/bin/ip addr list):"
-catifexec "/bin/ip addr list"
+catifexec "/bin/ip" "addr list"
 
 STATUS="Checking network routes:"
-catifexec "/sbin/route -n"
+catifexec "/sbin/route" "-n"
 
 STATUS="Collecting Name Service Switch config information:"
 catiffile "/etc/nsswitch.conf"
@@ -300,7 +335,7 @@ catifexec "/sbin/lsmod"
 for x  in $(/sbin/lsmod | /bin/cut -f1 -d" " 2>/dev/null | /bin/grep -v Module 2>/dev/null 
 ) ; do
   STATUS="Checking module information $x:"
-  catifexec "/sbin/modinfo  $x"
+  catifexec "/sbin/modinfo" "$x"
 done
 
 STATUS="Gathering information about your filesystems:"
@@ -380,7 +415,7 @@ STATUS="Gathering information about your ide drivers:"
 catiffile "/proc/ide"
 
 STATUS="Gathering information about your bus:"
-catifexec lspci
+catifexec "/usr/bin/lspci"
 catiffile "/proc/bus"
 
 echo
@@ -391,7 +426,7 @@ STATUS="Collecting information from /etc/fstab:"
 catiffile "/etc/fstab"
 
 STATUS="Collecting disk partition information:"
-catifexec "fdisk -l"
+catifexec "/sbin/fdisk" "-l"
 
 STATUS="Checking mounted file systems (mount) "
 catifexec "/bin/mount"
@@ -408,6 +443,9 @@ catiffile "/etc/raidtab"
 STATUS="Collecting Software RAID information (/etc/mdadm.conf)"
 catiffile "/etc/mdadm.conf"
 
+STATUS="Collecting Software RAID information (/sbin/mdadm -Q)"
+catifexec "/sbin/mdadm" "-Q" "--detail" '/dev/md?*'
+
 STATUS="Collecting Automount information (auto.master)"
 catiffile "/etc/auto.master"
 
@@ -527,3 +565,42 @@ if [ "$partitions" == "yes" ]; then
       $HWINFO --disk >> $hardwarefile
    fi
 fi
+
+if [ "$luksheaders" == "yes" ]; then
+   devices=`LC_ALL=C $SFDISK -l 2>/dev/null | grep "^Disk /dev" | @AWK@ '{print $2}' | cut -d: -f1`
+   [ -n "$devices" ] || warning "No block device found"
+   targetdevices=""
+   for dev in $devices; do
+      [ -b $dev ] || continue
+      debug "$CRYPTSETUP isLuks $dev"
+      $CRYPTSETUP isLuks $dev
+      [ $? -eq 0 ] && targetdevices="$targetdevices $dev"
+   done
+   for dev in $targetdevices; do
+      label=${dev#/dev/}
+      label=${label//\//-}
+      outputfile=${luksheadersfile//__star__/$label}
+      # the following sizes are expressed in terms of 512-byte sectors
+      debug "Let us find out the Luks header size for $dev"
+      debug "$CRYPTSETUP luksDump \"$dev\" | grep '^Payload offset:' | @AWK@ '{print $3}'"
+      headersize=`$CRYPTSETUP luksDump "$dev" | grep '^Payload offset:' | @AWK@ '{print $3}'`
+      if [ $? -ne 0 ]; then
+         warning "Could not compute the size of Luks header, skipping device $dev"
+         continue
+      elif [ -z "$headersize" -o -n "`echo \"$headersize\" | sed 's/[0-9]*//g'`" ]; then
+         warning "The computed size of Luks header is not an integer, skipping device $dev"
+         continue
+      fi
+      debug "Let us backup the Luks header of device $dev"
+      debug "$DD if=\"${dev}\" of=\"${outputfile}\" bs=512 count=\"${headersize}\""
+      output=`$DD if="${dev}" of="${outputfile}" bs=512 count="${headersize}" 2>&1`
+      exit_code=$?
+      if [ $exit_code -eq 0 ]; then
+         debug $output
+         info "The Luks header of $dev was saved to $outputfile."
+      else
+         debug $output
+         fatal "The Luks header of $dev could not be saved."
+      fi
+   done
+fi