aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Christian Hesse <mail@eworm.de>2014-04-16 19:15:59 +0200
committerGravatar Christian Hesse <mail@eworm.de>2014-04-16 19:15:59 +0200
commitb86e58f61ff27a08468b87d67b6040415edace97 (patch)
treed8f25500861d5f2d94dd16772e7405e65aae3ce1
parentfb6551d506d9f74f9d2a85d39ed5f2f111cc04aa (diff)
downloadmkinitcpio-ykfde-b86e58f61ff27a08468b87d67b6040415edace97.tar.gz
mkinitcpio-ykfde-b86e58f61ff27a08468b87d67b6040415edace97.tar.zst
save a challenge for every key
-rw-r--r--Makefile1
-rw-r--r--README.md2
-rwxr-xr-x[-rw-r--r--]bin/ykfde51
-rw-r--r--install/ykfde2
-rw-r--r--udev/ykfde.c75
5 files changed, 59 insertions, 72 deletions
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
index 3901f2e..41f2718 100644..100755
--- 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;
}