#!/bin/bash # author: phga # date: 2020-04-04 # desc: script to configure hmac/hotp on yubikeys + add required local configurations me=$(basename "$0") uname=$(logname) # DEFINITIONS # Add new types like |XY G='\033[0;32m' R='\033[0;31m' N='\033[0m' # Normal y_or_n() { read -p "(y/n): " answ } generate_new_secret() { secret_key=$(dd if=/dev/urandom bs=1 count=20 status=none | sha256sum | cut -b 1-40) } ask_for_mode() { while [[ ! "$mode" =~ ^(hmac|hotp)$ ]]; do read -p "Which mode do you want to configure (hmac|hotp): " mode done } ask_for_secret() { echo -e "Do you already have a secret? " && y_or_n if [ ! "$answ" = "y" ]; then generate_new_secret else read -p "Enter your secret key: " secret_key fi } check_secret() { while [[ ! "$secret_key" =~ [a-f0-9]{40} ]]; do echo -e "${R}Key must be 40 char HEX string${N}" ask_for_secret done } ask_for_otp_slot() { while [[ ! "$slot" =~ ^[12]$ ]]; do read -p "Onto which slot should I configure htop (1|2): " slot done } delete_old_users() { echo -e "${R}Deleted every hotp mapping in /etc/users.oath${N}" sudo sed -i '/^HOTP.*/d' /etc/users.oath echo "# Config automatically generated by $me <3" | sudo tee -a /etc/users.oath > /dev/null } write_hotp_config() { echo -e "Writing config to Yubikeys Slot $slot and creating initial mapping in /etc/users.oath" sudo ykpersonalize -"$slot" -o oath-hotp -o oath-hotp8 -o append-cr -a "$secret_key" -y [ ! -f "/etc/users.oath" ] && sudo touch "/etc/users.oath" sudo sed -i "$ a HOTP ${uname} - ${secret_key}" /etc/users.oath echo -e "Do you want to configure another Yubikey?" echo -e "If so, unplug this Yubikey and insert the next one!" echo -e "${G}NOTE: Using one Yubikey with multiple devices to authenticate doesn't make much sense" echo -e "since the hex value on the Key increases per use => Key/Device(users.oath) out of sync${N}" y_or_n } write_pam_config() { echo -e "Writing oath config lines into /etc/pam.d/login and /etc/pam.d/sudo" echo -e "${R}Make sure to install oath-toolkit or similar package which provides pam_oath.so${N}" sudo sed -i '/.*pam_oath\.so*/d' /etc/pam.d/login sudo sed -i "2 i auth sufficient pam_oath.so usersfile=/etc/users.oath window=50 digits=8" /etc/pam.d/login sudo sed -i '/.*pam_oath\.so*/d' /etc/pam.d/sudo sudo sed -i "2 i auth sufficient pam_oath.so usersfile=/etc/users.oath window=50 digits=8" /etc/pam.d/sudo } write_hmac_config() { echo -e "Do you want to touch the key every time you need the chal-resp? " && y_or_n to="-t" [ ! "$answ" = "y" ] && to=" " echo -e "Writing config to Yubikeys Slot $slot" sudo ykman otp chalresp $to -f "$slot" "$secret_key" echo -e "Do you want to configure another Yubikey?" echo -e "If so, unplug this Yubikey and insert the next one!" echo -e "${R}IMPORTANT: This secret has to be the same on all yubikeys, so that if we lose one, we are still able to decryt our password db.${N}" y_or_n } save_secret() { echo "Let me save the secret as an encrypted file in ./secret.bak" echo "$secret_key" | gpg -c -a -o ./secret.bak } ask_to_save_secret() { echo -e "Do you want me to save the secret for you?\n${R}It is REALLY IMPORTANT that you don't lose this secret!${N}\nYou will need GPG for the next step tho..." && y_or_n [ "$answ" = "y" ] && save_secret } check_requirements() { if [ ! -f /lib/security/pam_oath.so ]; then echo -e "${R}[WARNING]${N} It seems like /lib/security/pam_oath.so is missing" else echo -e "${G}[OK]${N} pam_oath.so found in /lib/security/" fi if ! hash ykman; then echo -e "${R}[WARNING]${N} It seems like ykman is missing" else echo -e "${G}[OK]${N} ykman is installed" fi if ! hash ykpersonalize; then echo -e "${R}[WARNING]${N} It seems like ykpersonalize is missing" else echo -e "${G}[OK]${N} ykpersonalize is installed" fi } while getopts "k:s:m:dh" opt; do case $opt in k) secret_key=${OPTARG} ;; s) slot=${OPTARG} ;; m) mode=${OPTARG} ;; d) delete=1 ;; h) echo -e "\nUsage: $me [OPTIONS]\n\nExamples:\n\n $ $me -m hmac -s 2 -k 583fa46c3d9bb0936ae36569dfacca2a304fa090 -d\n\nOptions:\n -m [hmac|hotp] mode to configure\n -s [1|2] slot to use\n -k SECRET 40 char secret key (hex)\n -d delete entries in /etc/users.oath\n" >&2 && exit ;; \?) echo -e "-$OPTARG is not valid\nUsage: $me [OPTIONS]\n\nExamples:\n\n $ $me -m hmac -s 2 -k 583fa46c3d9bb0936ae36569dfacca2a304fa090 -d\n\nOptions:\n -m [hmac|hotp] mode to configure\n -s [1|2] slot to use\n -k SECRET 40 char secret key (hex)\n -d delete entries in /etc/users.oath\n" >&2 && exit ;; esac done echo -e "+------------------------------+" echo -e "| Yubikey configuration script |" echo -e "| Written by ${G}toerd${N} with ${R}<3${N} |" echo -e "+------------------------------+" check_requirements ask_for_mode check_secret ask_for_otp_slot case $mode in hmac) write_hmac_config while [ "$answ" = "y" ]; do write_hmac_config done ask_to_save_secret ;; hotp) [ "$delete" = 1 ] && delete_old_users write_hotp_config while [ "$answ" = "y" ]; do write_hotp_config done write_pam_config ;; *) echo -e "${R}No mode entered :(${N}" ;; esac echo -e "${R}+------------------------------------------------------+" echo -e "| WRITE THE SECRET KEY DOWN TO CONFIGURE OTHER DEVICES | " echo -e "| SK: $secret_key |" echo -e "| Used slot on Yubikey: $slot |" echo -e "+------------------------------------------------------+${N}" exit