From b86e58f61ff27a08468b87d67b6040415edace97 Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Wed, 16 Apr 2014 19:15:59 +0200 Subject: save a challenge for every key --- Makefile | 1 + README.md | 2 -- bin/ykfde | 51 ++++++++++++++-------------------------- install/ykfde | 2 +- udev/ykfde.c | 75 +++++++++++++++++++++++++++++++---------------------------- 5 files changed, 59 insertions(+), 72 deletions(-) mode change 100644 => 100755 bin/ykfde diff --git a/Makefile b/Makefile index b925a83..b8c548a 100644 --- a/Makefile +++ b/Makefile @@ -21,6 +21,7 @@ install-bin: udev/ykfde $(INSTALL) -D -m0644 conf/ykfde.conf $(DESTDIR)/etc/ykfde.conf $(INSTALL) -D -m0755 bin/ykfde $(DESTDIR)/usr/bin/ykfde $(INSTALL) -D -m0644 install/ykfde $(DESTDIR)/usr/lib/initcpio/install/ykfde + $(INSTALL) -d -m0700 $(DESTDIR)/etc/ykfde.d/ install-doc: README.md README.html $(INSTALL) -D -m0644 README.md $(DESTDIR)/usr/share/doc/ykfde/README.md diff --git a/README.md b/README.md index 8faba4a..ce95385 100644 --- a/README.md +++ b/README.md @@ -59,5 +59,3 @@ Limitation / TODO * The challenge is not updated. The file is accessible read only in initramfs, but we have no easy way to write it to persistant storage. So probably this is a design limitation... -* It may be worth to have a challenge for every key, named with the - serial number. diff --git a/bin/ykfde b/bin/ykfde old mode 100644 new mode 100755 index 3901f2e..41f2718 --- a/bin/ykfde +++ b/bin/ykfde @@ -8,15 +8,13 @@ function help() { echo " -2 use Yubico key slot 2 (default)" echo " -d DEVICE add key to device DEVICE" echo " -h show this help" - echo " -k keep challenge, just add a new slot" } TMPDIR="$(mktemp --directory --tmpdir=/tmp/ .$(basename ${0})-${$}-XXXXXX)" -PASS="" SLOT="2" -KEEP="0" +SERIAL="$(ykinfo -sq)" -while getopts "12d:hk" opt; do +while getopts "12d:h" opt; do case ${opt} in 1) SLOT="1" @@ -31,12 +29,10 @@ while getopts "12d:hk" opt; do help exit 0 ;; - k) - KEEP="1" - ;; esac done +# check we have all information if [ -z "${DEVICE}" ]; then echo "No device given." >&2 help @@ -45,48 +41,37 @@ elif [ ! -b "${DEVICE}" ]; then echo "Device '${DEVICE}' does not exist or is not a block device." >&2 exit 1 elif ! cryptsetup isLuks "${DEVICE}" 2>/dev/null; then - echo "Device '${DEVICE}' does not exist." >&2 + echo "Device '${DEVICE}' is not a LUKS device." >&2 + exit 1 +elif [ -z "${SERIAL}" ]; then + echo "Did not get a serial number from key." >&2 exit 1 fi -if [ "${YKFDE_SLOT}" != "${SLOT}" ]; then - echo "Please update /etc/ykfde.conf to match your slot!" -fi - -echo "Please give extra password if you want to activate two factor" -echo -n "authentication, just ENTER for none: " -stty -echo -read PASS -stty echo -echo - -if [ -n "${PASS}" ]; then - echo "Do not forget to add 'ykfde_twofactor=y' to your boot parameters!" +# This directroy should exist, but we create it in case it does not +if [ ! -d "/etc/ykfde.d/" ]; then + install -d -m 0700 "/etc/ykfde.d/" fi -# generate challenge -if [ "${KEEP}" = "1" ] && [ -s "/etc/ykfde-challenge" ]; then - echo "User requested to keep challenge, not generating a new one." - ln -s "/etc/ykfde-challenge" "${TMPDIR}/ykfde-challenge" -else - makepasswd --chars=$((64-${#PASS})) | tr -d '\n' > "${TMPDIR}/ykfde-challenge" +# generate the challenge +if ! makepasswd --chars=64 | tr -d '\n' > "/etc/ykfde.d/challenge-${SERIAL}"; then + exit 1 fi -# generate response and add key to LUKS device -if ! ykchalresp -${SLOT} "${PASS}$(cat ${TMPDIR}/ykfde-challenge)" | tr -d '\n' > "${TMPDIR}/ykfde-response"; then +# generate response +if ! ykchalresp -${SLOT} "$(cat "/etc/ykfde.d/challenge-${SERIAL}")" | tr -d '\n' > "${TMPDIR}/ykfde-response"; then # ykchalresp should have shouted, so do not complain here exit 1 fi + +# add key to LUKS device if ! cryptsetup luksAddKey "${DEVICE}" "${TMPDIR}/ykfde-response"; then # cryptsetup should have shouted, ... exit 1 fi -# shred response and install challenge +# shred response and remove temporary directory shred --remove "${TMPDIR}/ykfde-response" -if [ "${KEEP}" != "1" ] && [ -s "${TMPDIR}/ykfde-challenge" ] && [ ! -L "${TMPDIR}/ykfde-challenge" ]; then - install -D -m 0400 "${TMPDIR}/ykfde-challenge" "/etc/ykfde-challenge" -fi rm -rf "${TMPDIR}" echo "Please do not forget to remove old keys when changing challenge!" diff --git a/install/ykfde b/install/ykfde index fc9ce17..0b2e50a 100644 --- a/install/ykfde +++ b/install/ykfde @@ -4,7 +4,7 @@ build() { add_binary /usr/lib/udev/ykfde add_file /usr/lib/initcpio/udev/20-ykfde.rules /usr/lib/udev/rules.d/20-ykfde.rules add_file /etc/ykfde.conf - add_file /etc/ykfde-challenge / + add_full_dir /etc/ykfde.d/ add_module 'usbhid' } diff --git a/udev/ykfde.c b/udev/ykfde.c index 51a8e17..c97c9bd 100644 --- a/udev/ykfde.c +++ b/udev/ykfde.c @@ -40,7 +40,7 @@ #define ASK_MESSAGE "Please enter passphrase for disk" #define CONFIGFILE "/etc/ykfde.conf" -#define CHALLENGEFILE "/ykfde-challenge" +#define CHALLENGEDIR "/etc/ykfde.d/" static int send_on_socket(int fd, const char *socket_name, const void *packet, size_t size) { union { @@ -112,6 +112,7 @@ int main(int argc, char **argv) { /* read challenge */ size_t fsize; char * challenge; + char challengefilename[sizeof(CHALLENGEDIR) + 11 /* "/challenge-" */ + 10 /* unsigned int in char */ + 1]; FILE * challengefile; /* read dir */ DIR * dir; @@ -124,14 +125,33 @@ int main(int argc, char **argv) { /* reopening stderr to /dev/console may help debugging... */ /* freopen("/dev/console", "w", stderr); */ - /* check if challenge file exists */ - if (access(CHALLENGEFILE, R_OK) == -1) + /* init and open first Yubikey */ + if (!yk_init()) { + perror("yk_init() failed"); goto out10; + } + + if ((yk = yk_open_first_key()) == NULL) { + perror("yk_open_first_key() failed"); + goto out20; + } + + /* read the serial number from key */ + if(!yk_get_serial(yk, 0, 0, &serial)) { + perror("yk_get_serial() failed"); + goto out30; + } + + sprintf(challengefilename, CHALLENGEDIR "/challenge-%d", serial); + + /* check if challenge file exists */ + if (access(challengefilename, R_OK) == -1) + goto out30; /* read challenge from file */ - if ((challengefile = fopen(CHALLENGEFILE, "r")) == NULL) { + if ((challengefile = fopen(challengefilename, "r")) == NULL) { perror("Failed opening challenge file for reading"); - goto out10; + goto out30; } fseek(challengefile, 0, SEEK_END); fsize = ftell(challengefile); @@ -139,33 +159,16 @@ int main(int argc, char **argv) { if ((challenge = malloc(fsize + 1)) == NULL) { perror("malloc() failed"); - goto out20; + goto out40; } if ((fread(challenge, fsize, 1, challengefile)) != 1) { perror("Failed reading challenge from file"); - goto out30; + goto out50; } challenge[fsize] = 0; /* finished reading challenge */ - /* init and open Yubikey */ - if (!yk_init()) { - perror("yk_init() failed"); - goto out30; - } - - if ((yk = yk_open_first_key()) == NULL) { - perror("yk_open_first_key() failed"); - goto out40; - } - - /* read the serial number from key */ - if(!yk_get_serial(yk, 0, 0, &serial)) { - perror("yk_get_serial() failed"); - goto out40; - } - /* try to read config file * if anything here fails we do not care... slot 2 is the default */ if ((ini = iniparser_load(CONFIGFILE)) != NULL) { @@ -255,6 +258,17 @@ out60: close(fd_inotify); out50: + /* free challenge */ + free(challenge); + +out40: + /* close the challenge file */ + fclose(challengefile); + /* Unlink it if we were successful, we can not try again later! */ + if (ret == EXIT_SUCCESS) + unlink(challengefilename); + +out30: /* wipe response (cleartext password!) from memory */ memset(response, 0, sizeof(response)); memset(response_hex, 0, sizeof(response_hex)); @@ -264,22 +278,11 @@ out50: if (!yk_close_key(yk)) perror("yk_close_key() failed"); -out40: +out20: /* release Yubikey */ if (!yk_release()) perror("yk_release() failed"); -out30: - /* free challenge */ - free(challenge); - -out20: - /* close the challenge file */ - fclose(challengefile); - /* Unlink it if we were successful, we can not try again later! */ - if (ret == EXIT_SUCCESS) - unlink(CHALLENGEFILE); - out10: return ret; } -- cgit v1.2.3-54-g00ecf