Index: cackey.c ================================================================== --- cackey.c +++ cackey.c @@ -879,16 +879,21 @@ /** Extra certificates to include in token **/ struct cackey_pcsc_identity extra_certs[] = { #include "cackey_builtin_certs.h" }; + +#define CACKEY_MACRO_DEFAULT_XSTR(str) CACKEY_MACRO_DEFAULT_STR(str) +#define CACKEY_MACRO_DEFAULT_STR(str) #str /* Protected Authentication Path command */ -#define CACKEY_PIN_COMMAND_DEFAULT_XSTR(str) CACKEY_PIN_COMMAND_DEFAULT_STR(str) -#define CACKEY_PIN_COMMAND_DEFAULT_STR(str) #str static char *cackey_pin_command = NULL; +/* Reader Exclusion or Include-only */ +static char *cackey_readers_include_only = NULL; +static char *cackey_readers_exclude = NULL; + /* PCSC Global Handles */ static LPSCARDCONTEXT cackey_pcsc_handle = NULL; static unsigned long cackey_getversion(void) { static unsigned long retval = 255; @@ -3324,10 +3329,13 @@ } CACKEY_DEBUG_PRINTF("PIN Change succeeded"); return(CACKEY_PCSC_S_OK); + + /* Disable a warning, since this is only used in debug mode */ + tries_remaining = tries_remaining; } /* * SYNPOSIS * ... @@ -4450,25 +4458,53 @@ cackey_biglock_init = 1; } /* Define a command to prompt user for a PIN */ #ifdef CACKEY_PIN_COMMAND_DEFAULT - cackey_pin_command = CACKEY_PIN_COMMAND_DEFAULT_XSTR(CACKEY_PIN_COMMAND_DEFAULT); + cackey_pin_command = strdup(CACKEY_MACRO_DEFAULT_XSTR(CACKEY_PIN_COMMAND_DEFAULT)); #endif #ifdef CACKEY_PIN_COMMAND_XONLY_DEFAULT if (getenv("DISPLAY") != NULL) { - cackey_pin_command = CACKEY_PIN_COMMAND_DEFAULT_XSTR(CACKEY_PIN_COMMAND_XONLY_DEFAULT); + cackey_pin_command = strdup(CACKEY_MACRO_DEFAULT_XSTR(CACKEY_PIN_COMMAND_XONLY_DEFAULT)); } #endif if (getenv("CACKEY_PIN_COMMAND") != NULL) { - cackey_pin_command = getenv("CACKEY_PIN_COMMAND"); + cackey_pin_command = strdup(getenv("CACKEY_PIN_COMMAND")); } if (getenv("CACKEY_PIN_COMMAND_XONLY") != NULL && getenv("DISPLAY") != NULL) { - cackey_pin_command = getenv("CACKEY_PIN_COMMAND_XONLY"); + cackey_pin_command = strdup(getenv("CACKEY_PIN_COMMAND_XONLY")); + } + +#ifdef CACKEY_READERS_INCLUDE_ONLY_DEFAULT + cackey_readers_include_only = strdup(CACKEY_MACRO_DEFAULT_XSTR(CACKEY_READERS_INCLUDE_ONLY_DEFAULT)); +#endif + +#ifdef CACKEY_READERS_EXCLUDE_DEFAULT + cackey_readers_exclude = strdup(CACKEY_MACRO_DEFAULT_XSTR(CACKEY_READERS_EXCLUDE_DEFAULT)); +#endif + + if (getenv("CACKEY_READERS_INCLUDE_ONLY") != NULL) { + cackey_readers_include_only = strdup(getenv("CACKEY_READERS_INCLUDE_ONLY")); + + if (cackey_readers_include_only[0] == '\0') { + free(cackey_readers_include_only); + + cackey_readers_include_only = NULL; + } + } + + if (getenv("CACKEY_READERS_EXCLUDE") != NULL) { + cackey_readers_exclude = strdup(getenv("CACKEY_READERS_EXCLUDE")); + + if (cackey_readers_exclude[0] == '\0') { + free(cackey_readers_exclude); + + cackey_readers_exclude = NULL; + } } CACKEY_DEBUG_PRINTF("Returning CKR_OK (%i)", CKR_OK); return(CKR_OK); @@ -4514,10 +4550,28 @@ cackey_slots[idx].cached_certs = NULL; } } cackey_pcsc_disconnect(); + + if (cackey_pin_command != NULL) { + free(cackey_pin_command); + + cackey_pin_command = NULL; + } + + if (cackey_readers_include_only != NULL) { + free(cackey_readers_include_only); + + cackey_readers_include_only = NULL; + } + + if (cackey_readers_exclude != NULL) { + free(cackey_readers_exclude); + + cackey_readers_exclude = NULL; + } cackey_initialized = 0; CACKEY_DEBUG_PRINTF("Returning CKR_OK (%i)", CKR_OK); @@ -4568,14 +4622,16 @@ static int first_call = 1; int mutex_retval; int pcsc_connect_ret; CK_ULONG count, slot_count = 0, currslot, slot_idx; char *pcsc_readers, *pcsc_readers_s, *pcsc_readers_e; + char *reader_check_pattern; DWORD pcsc_readers_len; LONG scard_listreaders_ret; size_t curr_reader_len; int slot_reset; + int include_reader; CACKEY_DEBUG_PRINTF("Called."); if (pulCount == NULL) { CACKEY_DEBUG_PRINTF("Error. pulCount is NULL."); @@ -4709,10 +4765,41 @@ break; } CACKEY_DEBUG_PRINTF("Found reader: %s (currslot = %lu)", pcsc_readers, (unsigned long) currslot); + + if (cackey_readers_include_only != NULL) { + CACKEY_DEBUG_PRINTF("Asked to include only readers matching: %s", cackey_readers_include_only); + + include_reader = 0; + reader_check_pattern = cackey_readers_include_only; + } else if (cackey_readers_exclude != NULL) { + CACKEY_DEBUG_PRINTF("Asked to exclude readers matching: %s", cackey_readers_exclude); + + include_reader = 1; + reader_check_pattern = cackey_readers_exclude; + } else { + include_reader = 1; + reader_check_pattern = NULL; + } + + if (reader_check_pattern != NULL) { + if (strstr(pcsc_readers, reader_check_pattern) != NULL) { + CACKEY_DEBUG_PRINTF("This reader matched the pattern."); + + include_reader = !include_reader; + } + } + + if (include_reader != 1) { + CACKEY_DEBUG_PRINTF("Skipping this reader."); + + pcsc_readers += curr_reader_len + 1; + + continue; + } /* Only update the list of slots if we are actually being asked supply the slot information */ if (pSlotList) { if (slot_reset) { cackey_slots[currslot].active = 1; Index: configure.ac ================================================================== --- configure.ac +++ configure.ac @@ -183,10 +183,30 @@ fi if ! test "${pincommandxonly}" = 'no'; then AC_DEFINE_UNQUOTED(CACKEY_PIN_COMMAND_XONLY_DEFAULT, [$pincommandxonly], [Command to run to prompt user for PIN only if DISPLAY environment variable is set]) fi + +AC_ARG_WITH(readers-include-only, AC_HELP_STRING([--with-readers-include-only=], [Specify a string to match in a reader to include it, all other readers will be excluded. The user may override this with the CACKEY_READERS_INCLUDE_ONLY environment variable.]), [ + readers_include_only="${withval}" +], [ + readers_include_only="no" +]) + +AC_ARG_WITH(readers-exclude, AC_HELP_STRING([--with-readers-exclude=], [Specify a string to match in a reader to exclude it, all other readers will be included. The user may override this with the CACKEY_READERS_EXCLUDE environment variable.]), [ + readers_exclude="${withval}" +], [ + readers_exclude="no" +]) + +if ! test "${readers_include_only}" = 'no'; then + AC_DEFINE_UNQUOTED(CACKEY_READERS_INCLUDE_ONLY_DEFAULT, [$readers_include_only], [Substring to match to include readers]) +fi + +if ! test "${readers_exclude}" = 'no'; then + AC_DEFINE_UNQUOTED(CACKEY_READERS_EXCLUDE_DEFAULT, [$readers_exclude], [Substring to match to exclude readers]) +fi dnl Set version script, to limit the scope of symbols DC_SETVERSIONSCRIPT(libcackey.vers, libcackey.syms) dnl Upate LDFLAGS to include setting the run-time linker path to the same as our compile-time linker