Check-in [8a76f09a85]
Overview
Comment:Added support for enabling the PROTECTED_AUTHENTICATION_PATH flag for the token if a command to provide the PIN is configured
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | piv
Files: files | file ages | folders
SHA1:8a76f09a8527814062942585ce72b4fbe65ea877
User & Date: rkeene on 2013-08-14 04:54:24
Other Links: manifest | tags
Context
2013-08-19
03:19
Fixed memory leak when checking PIV certificates check-in: 182c88b988 user: rkeene tags: piv
2013-08-18
06:53
First work towards implementing C_WaitForSlotEvent check-in: 4d4946cc1f user: rkeene tags: wait-for-slot-event
2013-08-14
05:53
If using Protected Authentication Path, don't set the LOGIN_REQUIRED flag check-in: 14d49a499f user: rkeene tags: protected-auth-path
04:54
Added support for enabling the PROTECTED_AUTHENTICATION_PATH flag for the token if a command to provide the PIN is configured check-in: 8a76f09a85 user: rkeene tags: piv
04:49
Merged trunk check-in: 2e12e46ded user: rkeene tags: piv
04:22
Merged in updates check-in: 5469f9a4d0 user: rkeene tags: protected-auth-path
Changes

Added build/ask-pass/cackey-askpass version [5c6636f8ba].

            1  +#! /usr/bin/env bash
            2  +
            3  +ZENITY="$(which 'zenity' 2>/dev/null)"
            4  +GDIALOG="$(which 'gdialog' 2>/dev/null)"
            5  +ASKPASS="$(which 'ssh-askpass' 'x11-ssh-askpass' '/usr/libexec/x11-ssh-askpass' 2>/dev/null | head -n 1)"
            6  +DIALOG="$(which 'dialog' 2>/dev/null)"
            7  +XTERM="$(which 'xterm' 2>/dev/null)"
            8  +
            9  +if [ -x "${ZENITY}" ]; then
           10  +	# XXX: TODO: Zenity
           11  +	true
           12  +fi
           13  +
           14  +if [ -x "${GDIALOG}" ]; then
           15  +	# XXX: TODO: Gdialog
           16  +	true
           17  +fi
           18  +
           19  +if [ -x "${ASKPASS}" ]; then
           20  +	exec "${ASKPASS}" "$@"
           21  +	exit 1
           22  +fi
           23  +
           24  +if [ -x "${DIALOG}" -a -x "${XTERM}" ]; then
           25  +	# XXX: TODO: dialog
           26  +	true
           27  +fi
           28  +
           29  +if [ -x "${XTERM}" ]; then
           30  +	# XXX: TODO: xterm
           31  +	true
           32  +fi
           33  +
           34  +exit 1

Modified cackey.c from [13b6e88e7c] to [ce38432e82].

   872    872   CK_C_INITIALIZE_ARGS cackey_args;
   873    873   
   874    874   /** Extra certificates to include in token **/
   875    875   struct cackey_pcsc_identity extra_certs[] = {
   876    876   #include "cackey_builtin_certs.h"
   877    877   };
   878    878   
          879  +/* Protected Authentication Path command */
          880  +#define CACKEY_PIN_COMMAND_DEFAULT_XSTR(str) CACKEY_PIN_COMMAND_DEFAULT_STR(str)
          881  +#define CACKEY_PIN_COMMAND_DEFAULT_STR(str) #str
          882  +static char *cackey_pin_command = NULL;
          883  +static char *cackey_pin_command_xonly = NULL;
          884  +
   879    885   /* PCSC Global Handles */
   880    886   static LPSCARDCONTEXT cackey_pcsc_handle = NULL;
   881    887   
   882    888   static unsigned long cackey_getversion(void) {
   883    889   	static unsigned long retval = 255;
   884    890   	unsigned long major = 0;
   885    891   	unsigned long minor = 0;
................................................................................
  3052   3058   
  3053   3059   	/* Apparently, CAC PINs are *EXACTLY* 8 bytes long -- pad with 0xFF if too short */
  3054   3060   	if (pin_len >= 8) {
  3055   3061   		memcpy(cac_pin, pin, 8);
  3056   3062   	} else {
  3057   3063   		memcpy(cac_pin, pin, pin_len);
  3058   3064   	}
         3065  +
         3066  +	/* Reject PINs which are too short */
         3067  +	if (pin_len < 5) {
         3068  +		CACKEY_DEBUG_PRINTF("Rejecting PIN which is too short (length = %lu, must be atleast 5)", pin_len);
         3069  +
         3070  +		return(CACKEY_PCSC_E_BADPIN);
         3071  +	}
  3059   3072   
  3060   3073   	/* PIV authentication uses a "key_reference" of 0x80 */
  3061   3074   	pcsc_identities = cackey_read_certs(slot, NULL, &num_certs);
  3062   3075   	if (num_certs > 0 && pcsc_identities != NULL) {
  3063   3076   		switch (pcsc_identities[0].id_type) {
  3064   3077   			case CACKEY_ID_TYPE_PIV:
  3065   3078   				CACKEY_DEBUG_PRINTF("We recently had a PIV card, so we will attempt to authenticate using the PIV Application key reference");
................................................................................
  4133   4146   			CACKEY_DEBUG_PRINTF("Error.  Mutex initialization failed.");
  4134   4147   
  4135   4148   			return(CKR_CANT_LOCK);
  4136   4149   		}
  4137   4150   
  4138   4151   		cackey_biglock_init = 1;
  4139   4152   	}
         4153  +
         4154  +	/* Define a command to prompt user for a PIN */
         4155  +#ifdef CACKEY_PIN_COMMAND_DEFAULT
         4156  +	cackey_pin_command = CACKEY_PIN_COMMAND_DEFAULT_XSTR(CACKEY_PIN_COMMAND_DEFAULT);
         4157  +#endif
         4158  +#ifdef CACKEY_PIN_COMMAND_XONLY_DEFAULT
         4159  +	cackey_pin_command_xonly = CACKEY_PIN_COMMAND_DEFAULT_XSTR(CACKEY_PIN_COMMAND_XONLY_DEFAULT);
         4160  +#endif
         4161  +
         4162  +	if (getenv("DISPLAY") != NULL) {
         4163  +		cackey_pin_command = cackey_pin_command_xonly;
         4164  +	}
         4165  +
         4166  +	if (getenv("CACKEY_PIN_COMMAND_XONLY") != NULL && getenv("DISPLAY") != NULL) {
         4167  +		cackey_pin_command = getenv("CACKEY_PIN_COMMAND_XONLY");
         4168  +	}
         4169  +
         4170  +	if (getenv("CACKEY_PIN_COMMAND") != NULL) {
         4171  +		cackey_pin_command = getenv("CACKEY_PIN_COMMAND");
         4172  +	}
  4140   4173   
  4141   4174   	CACKEY_DEBUG_PRINTF("Returning CKR_OK (%i)", CKR_OK);
  4142   4175   
  4143   4176   	return(CKR_OK);
  4144   4177   }
  4145   4178   
  4146   4179   CK_DEFINE_FUNCTION(CK_RV, C_Finalize)(CK_VOID_PTR pReserved) {
................................................................................
  4665   4698   	pInfo->hardwareVersion.major = (cackey_getversion() >> 16) & 0xff;
  4666   4699   	pInfo->hardwareVersion.minor = (cackey_getversion() >> 8) & 0xff;
  4667   4700   
  4668   4701   	pInfo->firmwareVersion.major = 0x00;
  4669   4702   	pInfo->firmwareVersion.minor = 0x00;
  4670   4703   
  4671   4704   	pInfo->flags = CKF_WRITE_PROTECTED | CKF_USER_PIN_INITIALIZED | CKF_TOKEN_INITIALIZED | cackey_slots[slotID].token_flags;
         4705  +
         4706  +	if (cackey_pin_command != NULL) {
         4707  +		pInfo->flags |= CKF_PROTECTED_AUTHENTICATION_PATH;
         4708  +	}
  4672   4709   
  4673   4710   	pInfo->ulMaxSessionCount = (sizeof(cackey_sessions) / sizeof(cackey_sessions[0])) - 1;
  4674   4711   	pInfo->ulSessionCount = CK_UNAVAILABLE_INFORMATION;
  4675   4712   	pInfo->ulMaxRwSessionCount = 0;
  4676   4713   	pInfo->ulRwSessionCount = CK_UNAVAILABLE_INFORMATION;
  4677   4714   	pInfo->ulMaxPinLen = 128;
  4678   4715   	pInfo->ulMinPinLen = 0;
................................................................................
  5128   5165   	CACKEY_DEBUG_PRINTF("Returning CKR_FUNCTION_NOT_SUPPORTED (%i)", CKR_FUNCTION_NOT_SUPPORTED);
  5129   5166   
  5130   5167   	return(CKR_FUNCTION_NOT_SUPPORTED);
  5131   5168   }
  5132   5169   
  5133   5170   CK_DEFINE_FUNCTION(CK_RV, C_Login)(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen) {
  5134   5171   	CK_SLOT_ID slotID;
         5172  +	FILE *pinfd;
         5173  +	char *pincmd, pinbuf[64], *fgets_ret;
  5135   5174   	int mutex_retval;
  5136   5175   	int tries_remaining;
  5137   5176   	int login_ret;
         5177  +	int pclose_ret;
  5138   5178   
  5139   5179   	CACKEY_DEBUG_PRINTF("Called.");
  5140   5180   
  5141   5181   	if (!cackey_initialized) {
  5142   5182   		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
  5143   5183   
  5144   5184   		return(CKR_CRYPTOKI_NOT_INITIALIZED);
................................................................................
  5182   5222   	if (cackey_slots[slotID].active == 0) {
  5183   5223   		CACKEY_DEBUG_PRINTF("Error. Invalid slot requested (%lu), slot not currently active", slotID);
  5184   5224   
  5185   5225   		cackey_mutex_unlock(cackey_biglock);
  5186   5226   
  5187   5227   		return(CKR_GENERAL_ERROR);
  5188   5228   	}
         5229  +
         5230  +	pincmd = cackey_pin_command;
         5231  +	if (pincmd != NULL) {
         5232  +		CACKEY_DEBUG_PRINTF("CACKEY_PIN_COMMAND = %s", pincmd);
         5233  +
         5234  +		if (pPin != NULL) {
         5235  +			CACKEY_DEBUG_PRINTF("Protected authentication path in effect and PIN provided !?");
         5236  +		}
         5237  +
         5238  +		pinfd = popen(pincmd, "r");
         5239  +		if (pinfd == NULL) {
         5240  +			CACKEY_DEBUG_PRINTF("Error.  %s: Unable to run", pincmd);
         5241  +
         5242  +			cackey_mutex_unlock(cackey_biglock);
         5243  +
         5244  +			CACKEY_DEBUG_PRINTF("Returning CKR_PIN_INCORRECT (%i)", (int) CKR_PIN_INCORRECT);
         5245  +
         5246  +			return(CKR_PIN_INCORRECT);
         5247  +		}
         5248  +
         5249  +		fgets_ret = fgets(pinbuf, sizeof(pinbuf), pinfd);
         5250  +		if (fgets_ret == NULL) {
         5251  +			pinbuf[0] = '\0';
         5252  +		}
         5253  +
         5254  +		pclose_ret = pclose(pinfd);
         5255  +		if (pclose_ret != 0) {
         5256  +			CACKEY_DEBUG_PRINTF("Error.  %s: exited with non-zero status of %i", pincmd, pclose_ret);
         5257  +
         5258  +			cackey_mutex_unlock(cackey_biglock);
         5259  +
         5260  +			CACKEY_DEBUG_PRINTF("Returning CKR_PIN_INCORRECT (%i)", (int) CKR_PIN_INCORRECT);
         5261  +
         5262  +			return(CKR_PIN_INCORRECT);
         5263  +		}
         5264  +
         5265  +		if (strlen(pinbuf) < 1) {
         5266  +			CACKEY_DEBUG_PRINTF("Error.  %s: returned no data", pincmd);
         5267  +
         5268  +			cackey_mutex_unlock(cackey_biglock);
         5269  +
         5270  +			CACKEY_DEBUG_PRINTF("Returning CKR_PIN_INCORRECT (%i)", (int) CKR_PIN_INCORRECT);
         5271  +
         5272  +			return(CKR_PIN_INCORRECT);
         5273  +		}
         5274  +
         5275  +		if (pinbuf[strlen(pinbuf) - 1] == '\n') {
         5276  +			pinbuf[strlen(pinbuf) - 1] = '\0';
         5277  +		}
         5278  +
         5279  +		pPin = (CK_UTF8CHAR_PTR) pinbuf;
         5280  +		ulPinLen = strlen(pinbuf);
         5281  +	}
  5189   5282   
  5190   5283   	login_ret = cackey_login(&cackey_slots[slotID], pPin, ulPinLen, &tries_remaining);
  5191   5284   	if (login_ret != CACKEY_PCSC_S_OK) {
  5192   5285   		cackey_mutex_unlock(cackey_biglock);
  5193   5286   
  5194   5287   		if (login_ret == CACKEY_PCSC_E_LOCKED) {
  5195   5288   			CACKEY_DEBUG_PRINTF("Error.  Token is locked.");
  5196   5289   
  5197   5290   			cackey_slots[slotID].token_flags |= CKF_USER_PIN_LOCKED;
         5291  +
         5292  +			CACKEY_DEBUG_PRINTF("Returning CKR_PIN_LOCKED (%i)", (int) CKR_PIN_LOCKED);
  5198   5293   
  5199   5294   			return(CKR_PIN_LOCKED);
  5200   5295   		} else if (login_ret == CACKEY_PCSC_E_BADPIN) {
  5201   5296   			CACKEY_DEBUG_PRINTF("Error.  Invalid PIN.");
  5202   5297   
  5203   5298   			cackey_slots[slotID].token_flags |= CKF_USER_PIN_COUNT_LOW;
  5204   5299   
  5205   5300   			if (tries_remaining == 1) {
  5206   5301   				cackey_slots[slotID].token_flags |= CKF_USER_PIN_FINAL_TRY;
  5207   5302   			}
         5303  +
         5304  +			CACKEY_DEBUG_PRINTF("Returning CKR_PIN_INCORRECT (%i)", (int) CKR_PIN_INCORRECT);
  5208   5305   
  5209   5306   			return(CKR_PIN_INCORRECT);
  5210   5307   		}
  5211   5308   
  5212   5309   		CACKEY_DEBUG_PRINTF("Error.  Unknown error returned from cackey_login() (%i)", login_ret);
  5213   5310   
  5214   5311   		return(CKR_GENERAL_ERROR);

Modified configure.ac from [b325ed9a06] to [8333de68f9].

   160    160   ], [
   161    161   	dodcerts=yes
   162    162   ])
   163    163   
   164    164   if test "${dodcerts}" = 'no'; then
   165    165   	AC_DEFINE(CACKEY_NO_EXTRA_CERTS, [1], [Specify that DoD certificates should not be made available])
   166    166   fi
          167  +
          168  +dnl Option to hard-code a command to run to request a PIN (enabling protected authentication path)
          169  +AC_ARG_WITH(pin-command, AC_HELP_STRING([--with-pin-command=<command>], [Specify a command to run to request a PIN from the user.  The user may override this with the CACKEY_PIN_COMMAND environment variable.]), [
          170  +	pincommand="${withval}"
          171  +], [
          172  +	pincommand="no"
          173  +])
          174  +
          175  +AC_ARG_WITH(pin-command-x, AC_HELP_STRING([--with-pin-command-x=<command>], [Same as --with-pin-command, but only sets Protected Authentication Path if the DISPLAY environment variable is set]), [
          176  +	pincommandxonly="${withval}"
          177  +], [
          178  +	pincommandxonly="no"
          179  +])
          180  +
          181  +if ! test "${pincommand}" = 'no'; then
          182  +	AC_DEFINE_UNQUOTED(CACKEY_PIN_COMMAND_DEFAULT, [$pincommand], [Command to run to prompt user for PIN])
          183  +fi
          184  +
          185  +if ! test "${pincommandxonly}" = 'no'; then
          186  +	AC_DEFINE_UNQUOTED(CACKEY_PIN_COMMAND_XONLY_DEFAULT, [$pincommandxonly], [Command to run to prompt user for PIN only if DISPLAY environment variable is set])
          187  +fi
   167    188   
   168    189   dnl Set version script, to limit the scope of symbols
   169    190   DC_SETVERSIONSCRIPT(libcackey.vers, libcackey.syms)
   170    191   
   171    192   dnl Upate LDFLAGS to include setting the run-time linker path to the same as our compile-time linker
   172    193   DC_SYNC_RPATH
   173    194   
   174    195   dnl If we updated LIBOBJS, update SHLIBOBJS -- must be last.
   175    196   DC_SYNC_SHLIBOBJS
   176    197   
   177    198   dnl Produce Makefile
   178    199   AC_OUTPUT(Makefile libcackey.syms)

Modified test.c from [86bd0fe2e2] to [47338c5b52].

   331    331   	chk_rv = C_OpenSession(slots[0], CKF_SERIAL_SESSION, NULL, NULL, &hSession);
   332    332   	if (chk_rv == CKR_OK) {
   333    333   		chk_rv = C_GetTokenInfo(slots[0], &tokenInfo);
   334    334   		if (chk_rv != CKR_OK) {
   335    335   			return(1);
   336    336   		}
   337    337   
   338         -		if ((tokenInfo.flags & CKF_LOGIN_REQUIRED) == CKF_LOGIN_REQUIRED) {
          338  +		if ((tokenInfo.flags & CKF_LOGIN_REQUIRED) == CKF_LOGIN_REQUIRED && (tokenInfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH) == 0) {
   339    339   			fgets_ret = NULL;
   340    340   
   341    341   			while (fgets_ret == NULL) {
   342    342   				printf("** ENTER PIN: ");
   343    343   				fflush(stdout);
   344    344   
   345    345   				fgets_ret = fgets((char *) user_pin, sizeof(user_pin), stdin);