#!/bin/bash # # Name: pam_panic_config # Description: Create a pam_panic configuration. # Author: Bandie # CONFIGFILE="/etc/pam.d/pampanic" LHBU="$HOME/LUKSHeaderBackup" # Set on build time SECUREDIR="__SECURELIBDIR__" PAMPANICPW="__PAMPANICPW__" VERSION="__VERSION__" # Localization N_(){ gettext "pam_panic" "$1" } NOT_BUILT=$(N_ "ERROR: Bash script was not built correctly.") RUN_AS_ROOT=$(N_ "Please run this script as root or use sudo.") BACKTITLE="$(N_ "pam_panic's Configuration Generator.") Version $VERSION" LEGAL_NOTICE=$(N_ "LEGAL NOTICE") LEGAL_HINT=$(N_ "You should not issue the panic function if you think that your data has been cloned before. This might cause more problems than it can help you.") BYE=$(N_ "Bye! :)") OK=$(N_ "OK") CANCEL=$(N_ "Cancel") AUTH=$(N_ "Authentication") PANIC=$(N_ "Panic") PREWARN_REMOVE=$(N_ "Please remove all removable media devices before you continue.") PREWARN_GPT=$(N_ "Note, if your device doesn't show up in the upcoming list it might not be a GPT formatted device.") PREWARN_INSERT_AUTH=$(N_ "Please insert the device you want to use as Authentication device and press OK.") PREWARN_INSERT_PANIC=$(N_ "Please insert the device you want to use as Panic device and press OK.") TITLE_RM_AUTH=$(N_ "Removable media: Authentication device") TITLE_RM_PANIC=$(N_ "Removable media: Panic device") CHOOSE_DEV=$(N_ "Choose your device:") DETECT_DEV=$(N_ "Detecting devices...") WELCOME=$(N_ "Welcome!") WELCOME1=$(N_ "Welcome to pam_panic's Configuration Generator.") WELCOME2=$(N_ "It will help you to create a valid pam_panic setup. It will also generate a PAM configuration file.") WELCOME3=$(N_ "After you're done with this Configuration Generator, you will see some hints how to integrate the new PAM configuration file in your system.") AUTH_MODE=$(N_ "Authentication mode") PASSWORDS=$(N_ "Passwords") REM_MEDIA=$(N_ "Media") CHOOSE_AUTH1=$(N_ "You can choose between the \"two removable media\" option and the \"two passwords\" option.") CHOOSE_AUTH2=$(N_ "See \"Help\" to learn what it is.") CHOOSE_AUTH3=$(N_ "Removable media or passwords?") UUID_AUTH=$(N_ "Authentication device chosen with UUID") UUID_PANIC=$(N_ "Panic device chosen with UUID") ASK_SET_PW=$(N_ "Do you want to set the passwords now?") SET_PW_FAILED=$(N_ "Failed to set the passwords. :(") PAM_PANICS_BEHAVIOUR=$(N_ "pam_panic's behaviour") ASK_SERIOUS1=$(N_ "Do you wish to destroy your LUKS header key slots in case of emergency?") ASK_SERIOUS2=$(N_ "This means that your encrypted root partition won't be decryptable anymore. After this question we will create a LUKS header backup, if you wish.") MSG_SERIOUS1=$(N_ "We will destroy") MSG_SERIOUS2=$(N_ "when you trigger the panic function.") ASK_LUKS_BU1=$(N_ "Do you want to make a LUKS-Header backup now?") ASK_LUKS_BU2=$(N_ "Save location:") LUKS_BU_SAVED=$(N_ "The LUKSHeader backup has been saved here:") SERIOUS_ERROR=$(N_ "ERROR: There is no encrypted root partition on /dev/sda.") REBOOT=$(N_ "Reboot") SHUTDOWN=$(N_ "Shutdown") NOTHING=$(N_ "Nothing") ASK_EXTENDED_BEHAVIOUR=$(N_ "Do you wish a reboot or a shutdown after issuing the panic function? Or shall we do nothing at all?") TITLE_STRICT=$(N_ "Strict mode") ASK_STRICT=$(N_ "Do you want to use the strict mode? It means that pam_panic will lock you out and reject any logins if the configuration is corrupt (like a missing password database).") GEN_CONFIG=$(N_ "Generating configuration...") CONFIG_EXISTS=$(N_ "Config file exists") CONFIG_OVERWRITE=$(N_ "exists. Overwrite it?") WHATNOW=$(N_ "What now?") SAVEDTO=$(N_ "Now we saved our configuration to") APPLY_THEM=$(N_ "If you want to let them apply to the other modules, proceed as follows:") OPEN_MOD=$(N_ "Open a module configuration in") TRY_OUT=$(N_ "You can try out:") AND=$(N_ "and") APPEND=$(N_ "After the line \"#%PAM-1.0\" append") UBUNTU_NOTICE=$(N_ "On Ubuntu you might want to separate the above mentioned lines on the files common-auth for the \"auth\" part and common-account for the \"account\" part.") PAMPANIC_ACTIVE=$(N_ "Once you have changed and saved those files, pam_panic will be active.") NEXT_LOGIN=$(N_ "At your next login you need to") TYPEPW=$(N_ "type your pam_panic authentification password or") INSRM=$(N_ "insert your removable authentication media") PREVTOREG=$(N_ "previous your regular user password.") MEMPOISONING=$(N_ "You want more security? Read section ADDITIONAL SECURITY: MEMORY POISONING in the man pages of pam_panic (\"man pam_panic\").") QUESTIONS=$(N_ "If you got any question, don't hesitate to ask via IRC (chat.freenode.net in room #pampanic) or via mail + GPG.") PRESSENTER=$(N_ "Press enter to exit.") [[ ! -d $SECUREDIR ]] || [[ ! -f $PAMPANICPW ]] && { echo "$NOT_BUILT" ; exit 1 ; } if [ $EUID -ne 0 ]; then echo "$RUN_AS_ROOT" exit 1 fi # Call when using the Cancel button function cancel(){ rm -f .pam_panic_media_choice clear echo "$BYE" exit 0 } # Call when CTRL+C trap "cancel" INT # Check, if $1 is a gpt formatted device function checkGPT(){ blkid $1 -t PTTYPE=gpt >> /dev/null return $? } # Get the GPT PartitionUUID function getPARTUUID(){ blkid $1 | awk '{print $4;}' | sed 's/PARTUUID="//;s/"//' } # Get the LUKS-Device's UUId function getLUKSDevice(){ if [ "$1" = "UUID" ]; then blkid /dev/sda*[1-9] | grep "crypto_LUKS" | awk '{print $2;}' | sed 's/UUID="//;s/"//' fi if [ "$1" = "NAME" ]; then blkid /dev/sda*[1-9] | grep "crypto_LUKS" | awk '{print $1;}' | sed 's/://' fi } # Generic dialog question function ask(){ dialog --backtitle "$BACKTITLE" --title "$1" --yesno "$2" 8 80 return $? } # Generic message box msg() { dialog --backtitle "$BACKTITLE" --title "$1" --msgbox "$2" 8 80 } # Generate a two dimensional flat array of all GPT devices from sdb-sdz function getMediaDevice(){ local i=0 local uuid for dev in $(ls /dev/sd[b-z] 2> /dev/null); do if $(checkGPT $dev); then for part in $(ls $dev*[1-9]); do echo -n "$i $part[$(getPARTUUID $part)] " (( i++ )) done fi done } # Hint for GPT formatted key before searching for it function chooseMediumPre(){ [[ $1 = "Authentication" ]] && { local title="$TITLE_RM_AUTH" ; local insert="$PREWARN_INSERT_AUTH" ; } [[ $1 = "Panic" ]] && { local title="$TITLE_RM_PANIC"; local insert="$PREWARN_INSERT_PANIC" ; } dialog --backtitle "$BACKTITLE" --title "$title" --yes-label "$OK" --no-label "$CANCEL" --yesno "$PREWARN_REMOVE\n$PREWARN_GPT\n\n$insert" 20 80 if [ $? -eq 1 ]; then cancel fi } # Choosing a GPT formatted key function chooseMedium(){ local ans [[ $1 = "Authentication" ]] && { local title="$TITLE_RM_AUTH" ; } [[ $1 = "Panic" ]] && { local title="$TITLE_RM_PANIC" ; } dialog --backtitle "$BACKTITLE" --title "$title" --menu "$CHOOSE_DEV" 10 80 5 $media 2> .pam_panic_media_choice if [ $? -eq 1 ]; then cancel fi ans=$(cat .pam_panic_media_choice) (( ans=(2*ans)+1 )) rm -f .pam_panic_media_choice return $ans } # A "Detecting devices...", assures to use a more up to date device list function showDetectDev(){ dialog --backtitle "$BACKTITLE" \ --title "$title" \ --infobox "$DETECT_DEV" 3 80 # Prevention for impatient beings sleep 2 } # Welcome dialog --backtitle "$BACKTITLE" \ --title "$WELCOME" \ --ok-label "Yip!" \ --msgbox "$WELCOME1\n\n$WELCOME2\n\n$WELCOME3" 20 80 # Legal notice msg "$LEGAL_NOTICE" "$LEGAL_HINT" # Authentication mode auth_mode=2 while [ $auth_mode -eq 2 ]; do dialog --backtitle "$BACKTITLE" \ --title "$AUTH_MODE" \ --help-button \ --extra-button --extra-label "$PASSWORDS" \ --ok-label "$REM_MEDIA" \ --yesno "$CHOOSE_AUTH1\n$CHOOSE_AUTH2\n\n$CHOOSE_AUTH3" 10 80 auth_mode=$? case $auth_mode in "0") # Removable media # Authentication while [ -z $media ]; do chooseMediumPre Authentication showDetectDev media=$(getMediaDevice) read -r -a mediaArray <<< "$media" done chooseMedium Authentication auth_dev=$(echo ${mediaArray[$?]} | sed 's/\/dev\/sd[b-z]*[0-1]\[//;s/\]//') msg "$TITLE_RM_AUTH" "$UUID_AUTH $auth_dev." # Panic unset media while [ -z $media ]; do chooseMediumPre Panic showDetectDev media=$(getMediaDevice) read -r -a mediaArray <<< "$media" done chooseMedium Panic panic_dev=$(echo ${mediaArray[$?]} | sed 's/\/dev\/sd[b-z]*[0-1]\[//;s/\]//') msg "$TITLE_RM_PANIC" "$UUID_PANIC $panic_dev." ;; "3") # Passwords ask "$PASSWORDS" "$ASK_SET_PW" setpw=$? case $setpw in "0") clear $PAMPANICPW if [ $? -ne 0 ]; then clear echo "$SET_PW_FAILED" exit 1 fi ;; esac ;; "2") # Help man pam_panic ;; "1") # Cancel cancel ;; esac done # serious flag ask "$PAM_PANICS_BEHAVIOUR" "$ASK_SERIOUS1\n$ASK_SERIOUS2" serious=$? if [ $serious -eq 0 ]; then serious_dev=$(getLUKSDevice UUID) if [ ! -z $serious_dev ]; then msg "$PAM_PANICS_BEHAVIOUR" "$MSG_SERIOUS1 $(getLUKSDevice NAME) [$serious_dev] $MSG_SERIOUS2" # LUKS header backup ask "LUKS Header backup" "$ASK_LUKS_BU1\n$ASK_LUKS_BU2 \"$LHBU\"." bu=$? case $bu in "0") cryptsetup luksHeaderBackup $(getLUKSDevice NAME) --header-backup-file "$LHBU" msg "LUKS Header backup" "$LUKS_BU_SAVED $LHBU" ;; esac else msg "$PAM_PANICS_BEHAVIOUR" "$SERIOUS_ERROR" serious=1 fi fi # poweroff / reboot behaviour dialog --backtitle "$BACKTITLE" \ --title "$PAM_PANICS_BEHAVIOUR" \ --ok-label "$REBOOT" \ --extra-button --extra-label "$SHUTDOWN" \ --cancel-label "$NOTHING" \ --yesno "$ASK_EXTENDED_BEHAVIOUR" 10 80 power=$? # strictness and lockout ask "$TITLE_STRICT" "$ASK_STRICT" strict=$? # Configuration generation dialog --backtitle "$BACKTITLE" \ --infobox "$GEN_CONFIG" 3 40 config="#%PAM-1.0\nauth requisite $SECUREDIR/pam_panic.so" case $power in "0") config="$config reboot" ;; "3") config="$config poweroff" ;; esac case $auth_mode in "3") config="$config password" ;; "0") config="$config allow=$auth_dev reject=$panic_dev" ;; esac case $serious in "0") config="$config serious=$serious_dev" ;; esac case $strict in "0") config="$config strict" esac config="$config\naccount requisite $SECUREDIR/pam_panic.so" # Write config file writeout=0 if [ -f $CONFIGFILE ]; then ask "CONFIG_EXISTS" "$CONFIGFILE $CONFIG_OVERWRITE" writeout=$? case $writeout in "0") echo -e "$config" > $CONFIGFILE ;; esac else echo -e "$config" > $CONFIGFILE fi # Finished message clear [ $writeout -eq 0 ] && echo "Done! <3" || echo "Nothing done!