From 0498dd512161b7fb07e703e03bc9b8ca8b3dd400 Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Mon, 22 Dec 2014 22:03:21 +0100 Subject: replace shell script with C code, and many more * place bin/ykfde with C source code bin/ykfde.c * challenge/response can be updated in place WARNING: This required config file syntax change! * updates and simplification to udev/ykfde * a lot more... Signed-off-by: Christian Hesse --- .gitignore | 1 + Makefile | 11 ++- README.md | 30 +++++- bin/Makefile | 17 ++++ bin/ykfde | 74 --------------- bin/ykfde.c | 280 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ conf/ykfde.conf | 20 +++- install/ykfde | 13 --- mkinitcpio/ykfde | 18 ++++ udev/ykfde.c | 107 ++++++++++----------- 10 files changed, 421 insertions(+), 150 deletions(-) create mode 100644 bin/Makefile delete mode 100755 bin/ykfde create mode 100644 bin/ykfde.c delete mode 100644 install/ykfde create mode 100644 mkinitcpio/ykfde diff --git a/.gitignore b/.gitignore index 94ca1e7..4da39b0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ README.html +bin/ykfde udev/ykfde diff --git a/Makefile b/Makefile index 1cc25a7..cd126e7 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,10 @@ RM := rm # a release tarball... VERSION := 0.3.4 -all: udev/ykfde README.html +all: bin/ykfde udev/ykfde README.html + +bin/ykfde: bin/ykfde.c + $(MAKE) -C bin udev/ykfde: udev/ykfde.c $(MAKE) -C udev @@ -16,11 +19,12 @@ README.html: README.md install: install-bin install-doc -install-bin: udev/ykfde +install-bin: bin/ykfde udev/ykfde + $(MAKE) -C bin install $(MAKE) -C udev install $(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 -m0644 mkinitcpio/ykfde $(DESTDIR)/usr/lib/initcpio/install/ykfde $(INSTALL) -d -m0700 $(DESTDIR)/etc/ykfde.d/ install-doc: README.md README.html @@ -28,6 +32,7 @@ install-doc: README.md README.html $(INSTALL) -D -m0644 README.html $(DESTDIR)/usr/share/doc/ykfde/README.html clean: + $(MAKE) -C bin clean $(MAKE) -C udev clean $(RM) -f README.html diff --git a/README.md b/README.md index 083a19b..6f47e94 100644 --- a/README.md +++ b/README.md @@ -43,8 +43,23 @@ adding a line to `/etc/crypttab.initramfs`. It should read like: > `mapping-name` /dev/`LUKS-device` - -`ykfde` will read its information from there. Then prepare the key. Plug -it in, make sure it is configured for `HMAC-SHA1`. After that run: +Update `/etc/ykfde.conf` with correct settings. Add `mapping-name` from +above to `device name` in the `general` section. Then add a new section +with your key's decimal serial number containing the key slot setting. +The file should look like this: + + [general] + device name = crypt + + [1234567] + luks slot = 1 + +*Be warned*: Do not remove or overwrite your interactive key! Keep that +for backup and rescue! + +`ykfde` will read its information from these files. Then prepare +the key. Plug it in, make sure it is configured for `HMAC-SHA1`. +After that run: > ykfde @@ -62,6 +77,13 @@ Limitation / TODO * At the moment this is specific to Arch Linux. Though everything should run with upstream `systemd` just fine anybody has to hook things up with [dracut](https://dracut.wiki.kernel.org/) or whatever. -* The challenge is not updated. The file is accessible read only in +* The challenge is not updated on boot. 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... + So probably this is a design limitation... However the install hook does + update the challenge when building a new initramfs and and Yubikey is + inserted. + +### Upstream + +URL: [GitHub.com](https://github.com/eworm-de/mkinitcpio-ykfde) +Mirror: [eworm.de](http://git.eworm.de/cgit.cgi/mkinitcpio-ykfde/) diff --git a/bin/Makefile b/bin/Makefile new file mode 100644 index 0000000..daa77f2 --- /dev/null +++ b/bin/Makefile @@ -0,0 +1,17 @@ +# commands +CC := gcc +INSTALL := install +RM := rm +# flags +CFLAGS += -std=c11 -O2 -fpic -pie -Wall -Werror + +all: ykfde + +ykfde: ykfde.c + $(CC) $(CFLAGS) -lykpers-1 -lyubikey -liniparser -lcryptsetup $(LDFLAGS) -o ykfde ykfde.c + +install: ykfde + $(INSTALL) -D -m0755 ykfde $(DESTDIR)/usr/bin/ykfde + +clean: + $(RM) -f ykfde diff --git a/bin/ykfde b/bin/ykfde deleted file mode 100755 index 41601b1..0000000 --- a/bin/ykfde +++ /dev/null @@ -1,74 +0,0 @@ -#!/bin/sh - -function help() { - echo "usage: ${0} [OPTIONS]" - echo - echo "where OPTIONS are:" - echo " -1 use Yubico key slot 1" - echo " -2 use Yubico key slot 2 (default)" - echo " -h show this help" -} - -DEVICE="$(egrep -v '^(#|$)' /etc/crypttab.initramfs 2>/dev/null | head -n1 | sed 's/\s\+/:/g' | cut -d: -f2)" -SERIAL="$(ykinfo -sq)" -SLOT="2" -TMPDIR="$(mktemp --directory --tmpdir=/tmp/ .$(basename ${0})-${$}-XXXXXX)" - -while getopts "12h" opt; do - case ${opt} in - 1) - SLOT="1" - ;; - 2) - SLOT="2" - ;; - h) - help - exit 0 - ;; - esac -done - -# check we have all information -if [ -z "${DEVICE}" ]; then - echo "Failed to get device from /etc/crypttab.initramfs." >&2 - exit 1 -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}' is not a LUKS device." >&2 - exit 1 -elif [ -z "${SERIAL}" ]; then - echo "Did not get a serial number from key. Did you insert one?" >&2 - exit 1 -fi - -# 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 the challenge -if ! makepasswd --chars=64 | tr -d '\n' > "/etc/ykfde.d/challenge-${SERIAL}"; then - exit 1 -fi - -# 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 remove temporary directory -shred --remove "${TMPDIR}/ykfde-response" -rm -rf "${TMPDIR}" - -echo "Please do not forget to remove old keys when changing challenge!" -echo "Now run 'mkinitcpio' to build a new initramfs!" diff --git a/bin/ykfde.c b/bin/ykfde.c new file mode 100644 index 0000000..43735d5 --- /dev/null +++ b/bin/ykfde.c @@ -0,0 +1,280 @@ +/* + * (C) 2014 by Christian Hesse + * + * This software may be used and distributed according to the terms + * of the GNU General Public License, incorporated herein by reference. + * + * compile with: + * $ gcc -o ykfde ykfde.c -lykpers-1 -lyubikey -lcryptsetup -liniparser + */ + +#ifndef _DEFAULT_SOURCE +#define _DEFAULT_SOURCE +#endif + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include + +/* challenge is 64 byte, + * HMAC-SHA1 response is 40 byte */ +#define CHALLENGELEN 64 +#define RESPONSELEN SHA1_MAX_BLOCK_SIZE +#define PASSPHRASELEN SHA1_DIGEST_SIZE * 2 + +#define CONFIGFILE "/etc/ykfde.conf" +#define CHALLENGEDIR "/etc/ykfde.d/" +#define CONFYKSLOT "yk slot" +#define CONFLUKSSLOT "luks slot" +#define CONFDEVNAME "device name" + +int main(int argc, char **argv) { + char challenge_old[CHALLENGELEN + 1], + challenge_new[CHALLENGELEN + 1], + repose_old[RESPONSELEN], + repose_new[RESPONSELEN], + passphrase_old[PASSPHRASELEN + 1], + passphrase_new[PASSPHRASELEN + 1]; + char challengefilename[sizeof(CHALLENGEDIR) + 11 /* "/challenge-" */ + 10 /* unsigned int in char */ + 1], + challengefiletmpname[sizeof(CHALLENGEDIR) + 11 /* "/challenge-" */ + 10 /* unsigned int in char */ + 7 /* -XXXXXX */ + 1]; + int challengefile = 0, challengefiletmp = 0; + struct timeval tv; + int i; + int8_t rc = EXIT_FAILURE; + /* cryptsetup */ + char * device_name; + int8_t luks_slot = -1; + struct crypt_device *cd; + crypt_status_info cs; + crypt_keyslot_info ck; + /* yubikey */ + YK_KEY * yk; + uint8_t yk_slot = SLOT_CHAL_HMAC2; + unsigned int serial = 0; + /* iniparser */ + dictionary * ini; + char section_ykslot[10 /* unsigned int in char */ + 1 + sizeof(CONFYKSLOT) + 1]; + char section_luksslot[10 /* unsigned int in char */ + 1 + sizeof(CONFLUKSSLOT) + 1]; + + /* initialize random seed */ + gettimeofday(&tv, NULL); + srand(tv.tv_usec * tv.tv_sec); + + memset(challenge_old, 0, CHALLENGELEN + 1); + memset(challenge_new, 0, CHALLENGELEN + 1); + memset(repose_old, 0, RESPONSELEN); + memset(repose_new, 0, RESPONSELEN); + memset(passphrase_old, 0, PASSPHRASELEN + 1); + memset(passphrase_new, 0, PASSPHRASELEN + 1); + + if ((ini = iniparser_load(CONFIGFILE)) == NULL) { + rc = EXIT_FAILURE; + fprintf(stderr, "Could not parse configuration file.\n"); + goto out10; + } + + if ((device_name = iniparser_getstring(ini, "general:" CONFDEVNAME, NULL)) == NULL) { + rc = EXIT_FAILURE; + /* read from crypttab? */ + /* get device from currently open devices? */ + fprintf(stderr, "Could not read LUKS device from configuration file.\n"); + goto out20; + } + + /* init and open first Yubikey */ + if ((rc = yk_init()) < 0) { + perror("yk_init() failed"); + goto out20; + } + + if ((yk = yk_open_first_key()) == NULL) { + rc = EXIT_FAILURE; + perror("yk_open_first_key() failed"); + goto out30; + } + + /* read the serial number from key */ + if ((rc = yk_get_serial(yk, 0, 0, &serial)) < 0) { + perror("yk_get_serial() failed"); + goto out40; + } + + /* get the yk slot */ + sprintf(section_ykslot, "%d:" CONFYKSLOT, serial); + yk_slot = iniparser_getint(ini, "general:" CONFYKSLOT, yk_slot); + yk_slot = iniparser_getint(ini, section_ykslot, yk_slot); + switch (yk_slot) { + case 1: + case SLOT_CHAL_HMAC1: + yk_slot = SLOT_CHAL_HMAC1; + break; + case 2: + case SLOT_CHAL_HMAC2: + default: + yk_slot = SLOT_CHAL_HMAC2; + break; + } + + /* get the luks slot */ + sprintf(section_luksslot, "%d:" CONFLUKSSLOT, serial); + luks_slot = iniparser_getint(ini, section_luksslot, luks_slot); + if (luks_slot < 0) { + rc = EXIT_FAILURE; + fprintf(stderr, "Please set LUKS key slot for Yubikey with serial %d!\n", serial); + printf("Add something like this to " CONFIGFILE ":\n\n[%d]\nluks slot = 1\n", serial); + goto out40; + } + + /* get random number and limit to printable ASCII character (32 to 126) */ + for(i = 0; i < CHALLENGELEN; i++) + challenge_new[i] = (rand() % (126 - 32)) + 32; + + /* do challenge/response and encode to hex */ + if ((rc = yk_challenge_response(yk, yk_slot, true, + CHALLENGELEN, (unsigned char *)challenge_new, + RESPONSELEN, (unsigned char *)repose_new)) < 0) { + perror("yk_challenge_response() failed"); + goto out40; + } + yubikey_hex_encode((char *)passphrase_new, (char *)repose_new, 20); + + /* initialize crypt device */ + if ((rc = crypt_init_by_name(&cd, device_name)) < 0) { + fprintf(stderr, "Device %s failed to initialize.\n", device_name); + goto out40; + } + + /* these are the filenames for challenge + * we need this for reading and writing */ + sprintf(challengefilename, CHALLENGEDIR "/challenge-%d", serial); + sprintf(challengefiletmpname, CHALLENGEDIR "/challenge-%d-XXXXXX", serial); + + /* write new challenge to file */ + if ((rc = challengefiletmp = mkstemp(challengefiletmpname)) < 0) { + fprintf(stderr, "Could not open file %s for writing.\n", challengefiletmpname); + goto out50; + } + if ((rc = write(challengefiletmp, challenge_new, CHALLENGELEN)) < 0) { + fprintf(stderr, "Failed to write challenge to file.\n"); + goto out60; + } + challengefiletmp = close(challengefiletmp); + + /* get status of crypt device + * We expect this to be active (or busy). It is the actual root device, no? */ + cs = crypt_status(cd, device_name); + if (cs != CRYPT_ACTIVE && cs != CRYPT_BUSY) { + rc = EXIT_FAILURE; + fprintf(stderr, "Device %s is invalid or inactive.\n", device_name); + goto out60; + } + + ck = crypt_keyslot_status(cd, luks_slot); + if (ck == CRYPT_SLOT_INVALID) { + rc = EXIT_FAILURE; + fprintf(stderr, "Key slot %d is invalid.\n", luks_slot); + goto out60; + } else if (ck == CRYPT_SLOT_ACTIVE || ck == CRYPT_SLOT_ACTIVE_LAST) { + /* read challenge from file */ + if ((rc = challengefile = open(challengefilename, O_RDONLY)) < 0) { + perror("Failed opening challenge file for reading"); + goto out60; + } + + if ((rc = read(challengefile, challenge_old, CHALLENGELEN)) < 0) { + perror("Failed reading challenge from file"); + goto out60; + } + + challengefile = close(challengefile); + /* finished reading challenge */ + + /* do challenge/response and encode to hex */ + if ((rc = yk_challenge_response(yk, yk_slot, true, + CHALLENGELEN, (unsigned char *)challenge_old, + RESPONSELEN, (unsigned char *)repose_old)) < 0) { + perror("yk_challenge_response() failed"); + goto out60; + } + yubikey_hex_encode((char *)passphrase_old, (char *)repose_old, 20); + + if ((rc = crypt_keyslot_change_by_passphrase(cd, luks_slot, luks_slot, + passphrase_old, PASSPHRASELEN, + passphrase_new, PASSPHRASELEN)) < 0) { + fprintf(stderr, "Could not update passphrase for key slot %d.\n", luks_slot); + goto out60; + } + + if ((rc = unlink(challengefilename)) < 0) { + fprintf(stderr, "Failed to delete old challenge file.\n"); + goto out60; + } + } else { /* ck == CRYPT_SLOT_INACTIVE */ + if ((rc = crypt_keyslot_add_by_passphrase(cd, luks_slot, NULL, 0, + passphrase_new, PASSPHRASELEN)) < 0) { + fprintf(stderr, "Could add passphrase for key slot %d.\n", luks_slot); + goto out60; + } + } + + if ((rc = rename(challengefiletmpname, challengefilename)) < 0) { + fprintf(stderr, "Failed to rename new challenge file.\n"); + goto out60; + } + + rc = EXIT_SUCCESS; + +out60: + /* close the challenge file */ + if (challengefile) + close(challengefile); + if (challengefiletmp) + close(challengefiletmp); + if (access(challengefiletmpname, F_OK ) == 0 ) { + unlink(challengefiletmpname); + } + +out50: + /* free crypt context */ + crypt_free(cd); + +out40: + /* close Yubikey */ + if (!yk_close_key(yk)) + perror("yk_close_key() failed"); + +out30: + /* release Yubikey */ + if (!yk_release()) + perror("yk_release() failed"); + +out20: + /* free iniparser dictionary */ + iniparser_freedict(ini); + + +out10: + /* wipe response (cleartext password!) from memory */ + /* This is statically allocated and always save to wipe! */ + memset(challenge_old, 0, CHALLENGELEN + 1); + memset(challenge_new, 0, CHALLENGELEN + 1); + memset(repose_old, 0, RESPONSELEN); + memset(repose_new, 0, RESPONSELEN); + memset(passphrase_old, 0, PASSPHRASELEN + 1); + memset(passphrase_new, 0, PASSPHRASELEN + 1); + + return rc; +} + +// vim: set syntax=c: diff --git a/conf/ykfde.conf b/conf/ykfde.conf index af25ad7..0525053 100644 --- a/conf/ykfde.conf +++ b/conf/ykfde.conf @@ -1,8 +1,20 @@ [general] -# Specify what Yubikey slot to use for full disk encryption +# Specify what Yubikey slot to use for full disk encryption. +# This is just the system default, you can configure one or more +# Yubikeys below. # The specified slot has to be configured for HMAC-SHA1. -slot = 2 +yk slot = 2 -# you can specify slot for one or more specific Yubikeys as well +# This is the LUKS device. Make sure you use the name, not +# block device, e.g. it has to match first column of +# /etc/crypttab.initramfs. +device name = crypt + +# For every Yubikey in use add a section here. +# * 'yk slot' is optional and only required for keys differing +# from system default. +# * 'luks slot' is required to make sure one Yukikey is associated +# with exactly one LUKS slot! #[1234567] -#slot = 1 +#yk slot = 1 +#luks slot = 1 diff --git a/install/ykfde b/install/ykfde deleted file mode 100644 index 71e5eb5..0000000 --- a/install/ykfde +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh - -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_full_dir /etc/ykfde.d/ -} - -help() { - echo "This hook adds support for opening LUKS devices with Yubico key." - echo "Please use command 'ykfde' to prepare." -} diff --git a/mkinitcpio/ykfde b/mkinitcpio/ykfde new file mode 100644 index 0000000..f4115d6 --- /dev/null +++ b/mkinitcpio/ykfde @@ -0,0 +1,18 @@ +#!/bin/sh + +build() { + # This will update to LUKS key slot if Yubikey is available. + # Do not fail if key is not present! + /usr/bin/ykfde >/dev/null 2>/dev/null || true + + # install files to initramfs + 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_full_dir /etc/ykfde.d/ +} + +help() { + echo "This hook adds support for opening LUKS devices with Yubico key." + echo "Please use command 'ykfde' to prepare." +} diff --git a/udev/ykfde.c b/udev/ykfde.c index 0f5bd17..2adedbb 100644 --- a/udev/ykfde.c +++ b/udev/ykfde.c @@ -13,6 +13,7 @@ #include #include +#include #include #include #include @@ -36,12 +37,18 @@ #define EVENT_SIZE (sizeof (struct inotify_event)) #define EVENT_BUF_LEN (1024 * (EVENT_SIZE + 16)) +#define CHALLENGELEN 64 +#define RESPONSELEN SHA1_MAX_BLOCK_SIZE +#define PASSPHRASELEN SHA1_DIGEST_SIZE * 2 + #define ASK_PATH "/run/systemd/ask-password/" #define ASK_MESSAGE "Please enter passphrase for disk" #define CONFIGFILE "/etc/ykfde.conf" #define CHALLENGEDIR "/etc/ykfde.d/" +#define CONFYKSLOT "yk slot" + static int send_on_socket(int fd, const char *socket_name, const void *packet, size_t size) { union { struct sockaddr sa; @@ -61,7 +68,7 @@ static int send_on_socket(int fd, const char *socket_name, const void *packet, s } static int try_answer(char * ask_file, char * response) { - int8_t ret = EXIT_FAILURE; + int8_t rc = EXIT_FAILURE; dictionary * ini; char * ask_message, * ask_socket; int fd_askpass; @@ -81,12 +88,12 @@ static int try_answer(char * ask_file, char * response) { goto out1; } - if (send_on_socket(fd_askpass, ask_socket, response, strlen(response)) < 0) { + if (send_on_socket(fd_askpass, ask_socket, response, PASSPHRASELEN + 1) < 0) { perror("send_on_socket() failed"); goto out2; } - ret = EXIT_SUCCESS; + rc = EXIT_SUCCESS; out2: close(fd_askpass); @@ -94,26 +101,23 @@ out2: out1: iniparser_freedict(ini); - return ret; + return rc; } int main(int argc, char **argv) { - int8_t ret = EXIT_FAILURE; + int8_t rc = EXIT_FAILURE; /* Yubikey */ YK_KEY * yk; uint8_t slot = SLOT_CHAL_HMAC2; unsigned int serial = 0; - unsigned char response[SHA1_MAX_BLOCK_SIZE]; - unsigned char response_hex[(SHA1_MAX_BLOCK_SIZE * 2) + 1]; - char response_askpass[(SHA1_MAX_BLOCK_SIZE * 2) + 2]; + char response[RESPONSELEN], passphrase[PASSPHRASELEN + 1], passphrase_askpass[PASSPHRASELEN + 2]; /* iniparser */ dictionary * ini; - char section_serial[10 /* unsigned int in char */ + 5 /* ":slot" */ + 1]; + char section_ykslot[10 /* unsigned int in char */ + 1 + sizeof(CONFYKSLOT) + 1]; /* read challenge */ - size_t fsize; - char * challenge; + char challenge[CHALLENGELEN + 1]; char challengefilename[sizeof(CHALLENGEDIR) + 11 /* "/challenge-" */ + 10 /* unsigned int in char */ + 1]; - FILE * challengefile; + int challengefile; /* read dir */ DIR * dir; struct dirent * ent; @@ -127,19 +131,22 @@ int main(int argc, char **argv) { freopen("/dev/console", "w", stderr); #endif + memset(challenge, 0, CHALLENGELEN); + /* init and open first Yubikey */ - if (!yk_init()) { + if ((rc = yk_init()) < 0) { perror("yk_init() failed"); goto out10; } if ((yk = yk_open_first_key()) == NULL) { + rc = EXIT_FAILURE; perror("yk_open_first_key() failed"); goto out20; } /* read the serial number from key */ - if(!yk_get_serial(yk, 0, 0, &serial)) { + if((rc = !yk_get_serial(yk, 0, 0, &serial)) < 0) { perror("yk_get_serial() failed"); goto out30; } @@ -151,42 +158,37 @@ int main(int argc, char **argv) { goto out30; /* read challenge from file */ - if ((challengefile = fopen(challengefilename, "r")) == NULL) { + if ((rc = challengefile = open(challengefilename, O_RDONLY)) < 0) { perror("Failed opening challenge file for reading"); goto out30; } - fseek(challengefile, 0, SEEK_END); - fsize = ftell(challengefile); - fseek(challengefile, 0, SEEK_SET); - if ((challenge = malloc(fsize + 1)) == NULL) { - perror("malloc() failed"); - goto out40; - } - - if ((fread(challenge, fsize, 1, challengefile)) != 1) { + if ((rc = read(challengefile, challenge, CHALLENGELEN)) < 0) { perror("Failed reading challenge from file"); goto out50; } - challenge[fsize] = 0; + challengefile = close(challengefile); /* finished reading challenge */ /* try to read config file * if anything here fails we do not care... slot 2 is the default */ if ((ini = iniparser_load(CONFIGFILE)) != NULL) { /* first try the general setting */ - slot = iniparser_getint(ini, "general:slot", slot); + slot = iniparser_getint(ini, "general:" CONFYKSLOT, slot); - sprintf(section_serial, "%d:slot", serial); + sprintf(section_ykslot, "%d:" CONFYKSLOT, serial); /* then probe for setting with serial number */ - slot = iniparser_getint(ini, section_serial, slot); + slot = iniparser_getint(ini, section_ykslot, slot); switch (slot) { - case '1': + case 1: + case SLOT_CHAL_HMAC1: slot = SLOT_CHAL_HMAC1; break; - default: /* slot 2 is default */ + case 2: + case SLOT_CHAL_HMAC2: + default: slot = SLOT_CHAL_HMAC2; break; } @@ -194,26 +196,28 @@ int main(int argc, char **argv) { iniparser_freedict(ini); } - memset(response, 0, sizeof(response)); - memset(response_hex, 0, sizeof(response_hex)); + memset(response, 0, RESPONSELEN); + memset(passphrase, 0, PASSPHRASELEN + 1); /* do challenge/response and encode to hex */ - if (!yk_challenge_response(yk, slot, true, strlen(challenge), (unsigned char *)challenge, sizeof(response), response)) { + if ((rc = yk_challenge_response(yk, slot, true, + CHALLENGELEN, (unsigned char *)challenge, + RESPONSELEN, (unsigned char *)response)) < 0) { perror("yk_challenge_response() failed"); goto out50; } - yubikey_hex_encode((char *)response_hex, (char *)response, 20); + yubikey_hex_encode((char *)passphrase, (char *)response, 20); - sprintf(response_askpass, "+%s", response_hex); + sprintf(passphrase_askpass, "+%s", passphrase); /* change to directory so we do not have to assemble complete/absolute path */ - if (chdir(ASK_PATH) != 0) { + if ((rc = chdir(ASK_PATH)) != 0) { perror("chdir() failed"); goto out50; } /* creating the INOTIFY instance and add ASK_PATH directory into watch list */ - if ((fd_inotify = inotify_init()) < 0) { + if ((rc = fd_inotify = inotify_init()) < 0) { perror("inotify_init() failed"); goto out50; } @@ -225,17 +229,18 @@ int main(int argc, char **argv) { if ((dir = opendir(ASK_PATH)) != NULL) { while ((ent = readdir(dir)) != NULL) { if (strncmp(ent->d_name, "ask.", 4) == 0) { - if ((ret = try_answer(ent->d_name, response_askpass)) == EXIT_SUCCESS) + if ((rc = try_answer(ent->d_name, passphrase_askpass)) == EXIT_SUCCESS) goto out70; } } } else { + rc = EXIT_FAILURE; perror ("opendir() failed"); goto out60; } /* read to determine the event change happens. Actually this read blocks until the change event occurs */ - if ((length = read(fd_inotify, buffer, EVENT_BUF_LEN)) < 0) { + if ((rc = length = read(fd_inotify, buffer, EVENT_BUF_LEN)) < 0) { perror("read() failed"); goto out70; } @@ -245,7 +250,7 @@ int main(int argc, char **argv) { while (i < length) { event = (struct inotify_event *)&buffer[i]; if (event->len > 0) - if ((ret = try_answer(event->name, response_askpass)) == EXIT_SUCCESS) + if ((rc = try_answer(event->name, passphrase_askpass)) == EXIT_SUCCESS) goto out70; i += EVENT_SIZE + event->len; } @@ -260,33 +265,31 @@ out60: close(fd_inotify); out50: - /* free challenge */ - free(challenge); - -out40: /* close the challenge file */ - fclose(challengefile); + if (challengefile) + close(challengefile); /* Unlink it if we were successful, we can not try again later! */ - if (ret == EXIT_SUCCESS) + if (rc == EXIT_SUCCESS) unlink(challengefilename); out30: /* wipe response (cleartext password!) from memory */ - memset(response, 0, sizeof(response)); - memset(response_hex, 0, sizeof(response_hex)); - memset(response_askpass, 0, sizeof(response_askpass)); + memset(challenge, 0, CHALLENGELEN); + memset(response, 0, RESPONSELEN); + memset(passphrase, 0, PASSPHRASELEN + 1); + memset(passphrase_askpass, 0, PASSPHRASELEN + 2); /* close Yubikey */ - if (!yk_close_key(yk)) + if (yk_close_key(yk) < 0) perror("yk_close_key() failed"); out20: /* release Yubikey */ - if (!yk_release()) + if (yk_release() < 0) perror("yk_release() failed"); out10: - return ret; + return rc; } // vim: set syntax=c: -- cgit v1.2.3-54-g00ecf