Changes On Branch 20ddc7185337fda2

Changes In Branch protected-auth-path Through [20ddc71853] Excluding Merge-Ins

This is equivalent to a diff from f42b92cf98 to 20ddc71853

2013-08-14
04:22
Merged in trunk check-in: 8c73344738 user: rkeene tags: piv
04:16
Added return value printing for C_Login() and removed requirement that PIN not be provided if using protected authentication path (some tools provide it anyway) check-in: a68e222d00 user: rkeene tags: protected-auth-path
04:15
Added start of script to ask for PIN via X11 check-in: 20ddc71853 user: rkeene tags: protected-auth-path
03:55
Updated to allow the Protected Authentication Path to be set only if an X server display is available check-in: b6ea2dbe0a user: rkeene tags: protected-auth-path
02:26
Create new branch named "protected-auth-path" check-in: 93bebaff52 user: rkeene tags: protected-auth-path
2013-02-07
23:29
Added script to generate certificate bundles in heirarchy order check-in: 6a49836224 user: rkeene tags: piv
2013-01-16
15:46
Updated macbuild contact information to have valid government email addresses to contact us. check-in: f42b92cf98 user: kvanals tags: piv
15:21
Updated to determine what kind of authentication to perform based on token present (PIV/CAC) check-in: def08b9deb user: rkeene tags: piv

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





































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#! /usr/bin/env bash

ZENITY="$(which 'zenity' 2>/dev/null)"
GDIALOG="$(which 'gdialog' 2>/dev/null)"
ASKPASS="$(which 'ssh-askpass' 'x11-ssh-askpass' '/usr/libexec/x11-ssh-askpass' 2>/dev/null | head -n 1)"
DIALOG="$(which 'dialog' 2>/dev/null)"
XTERM="$(which 'xterm' 2>/dev/null)"

if [ -x "${ZENITY}" ]; then
	# XXX: TODO: Zenity
	true
fi

if [ -x "${GDIALOG}" ]; then
	# XXX: TODO: Gdialog
	true
fi

if [ -x "${ASKPASS}" ]; then
	exec "${ASKPASS}" "$@"
	exit 1
fi

if [ -x "${DIALOG}" -a -x "${XTERM}" ]; then
	# XXX: TODO: dialog
	true
fi

if [ -x "${XTERM}" ]; then
	# XXX: TODO: xterm
	true
fi

exit 1

Modified cackey.c from [8554f45411] to [b4f00ff994].

866
867
868
869
870
871
872






873
874
875
876
877
878
879
CK_C_INITIALIZE_ARGS cackey_args;

/** Extra certificates to include in token **/
struct cackey_pcsc_identity extra_certs[] = {
#include "cackey_builtin_certs.h"
};







/* PCSC Global Handles */
static LPSCARDCONTEXT cackey_pcsc_handle = NULL;

static unsigned long cackey_getversion(void) {
	static unsigned long retval = 255;
	unsigned long major = 0;
	unsigned long minor = 0;







>
>
>
>
>
>







866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
CK_C_INITIALIZE_ARGS cackey_args;

/** Extra certificates to include in token **/
struct cackey_pcsc_identity extra_certs[] = {
#include "cackey_builtin_certs.h"
};

/* 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;
static char *cackey_pin_command_xonly = NULL;

/* PCSC Global Handles */
static LPSCARDCONTEXT cackey_pcsc_handle = NULL;

static unsigned long cackey_getversion(void) {
	static unsigned long retval = 255;
	unsigned long major = 0;
	unsigned long minor = 0;
3046
3047
3048
3049
3050
3051
3052







3053
3054
3055
3056
3057
3058
3059

	/* Apparently, CAC PINs are *EXACTLY* 8 bytes long -- pad with 0xFF if too short */
	if (pin_len >= 8) {
		memcpy(cac_pin, pin, 8);
	} else {
		memcpy(cac_pin, pin, pin_len);
	}








	/* PIV authentication uses a "key_reference" of 0x80 */
	pcsc_identities = cackey_read_certs(slot, NULL, &num_certs);
	if (num_certs > 0 && pcsc_identities != NULL) {
		switch (pcsc_identities[0].id_type) {
			case CACKEY_ID_TYPE_PIV:
				CACKEY_DEBUG_PRINTF("We recently had a PIV card, so we will attempt to authenticate using the PIV Application key reference");







>
>
>
>
>
>
>







3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072

	/* Apparently, CAC PINs are *EXACTLY* 8 bytes long -- pad with 0xFF if too short */
	if (pin_len >= 8) {
		memcpy(cac_pin, pin, 8);
	} else {
		memcpy(cac_pin, pin, pin_len);
	}

	/* Reject PINs which are too short */
	if (pin_len < 5) {
		CACKEY_DEBUG_PRINTF("Rejecting PIN which is too short (length = %lu, must be atleast 5)", pin_len);

		return(CACKEY_PCSC_E_BADPIN);
	}

	/* PIV authentication uses a "key_reference" of 0x80 */
	pcsc_identities = cackey_read_certs(slot, NULL, &num_certs);
	if (num_certs > 0 && pcsc_identities != NULL) {
		switch (pcsc_identities[0].id_type) {
			case CACKEY_ID_TYPE_PIV:
				CACKEY_DEBUG_PRINTF("We recently had a PIV card, so we will attempt to authenticate using the PIV Application key reference");
4113
4114
4115
4116
4117
4118
4119




















4120
4121
4122
4123
4124
4125
4126
			CACKEY_DEBUG_PRINTF("Error.  Mutex initialization failed.");

			return(CKR_CANT_LOCK);
		}

		cackey_biglock_init = 1;
	}





















	CACKEY_DEBUG_PRINTF("Returning CKR_OK (%i)", CKR_OK);

	return(CKR_OK);
}

CK_DEFINE_FUNCTION(CK_RV, C_Finalize)(CK_VOID_PTR pReserved) {







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
			CACKEY_DEBUG_PRINTF("Error.  Mutex initialization failed.");

			return(CKR_CANT_LOCK);
		}

		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);
#endif
#ifdef CACKEY_PIN_COMMAND_XONLY_DEFAULT
	cackey_pin_command_xonly = CACKEY_PIN_COMMAND_DEFAULT_XSTR(CACKEY_PIN_COMMAND_XONLY_DEFAULT);
#endif

	if (getenv("DISPLAY") != NULL) {
		cackey_pin_command = cackey_pin_command_xonly;
	}

	if (getenv("CACKEY_PIN_COMMAND_XONLY") != NULL && getenv("DISPLAY") != NULL) {
		cackey_pin_command = getenv("CACKEY_PIN_COMMAND_XONLY");
	}

	if (getenv("CACKEY_PIN_COMMAND") != NULL) {
		cackey_pin_command = getenv("CACKEY_PIN_COMMAND");
	}

	CACKEY_DEBUG_PRINTF("Returning CKR_OK (%i)", CKR_OK);

	return(CKR_OK);
}

CK_DEFINE_FUNCTION(CK_RV, C_Finalize)(CK_VOID_PTR pReserved) {
4645
4646
4647
4648
4649
4650
4651




4652
4653
4654
4655
4656
4657
4658
	pInfo->hardwareVersion.major = (cackey_getversion() >> 16) & 0xff;
	pInfo->hardwareVersion.minor = (cackey_getversion() >> 8) & 0xff;

	pInfo->firmwareVersion.major = 0x00;
	pInfo->firmwareVersion.minor = 0x00;

	pInfo->flags = CKF_WRITE_PROTECTED | CKF_USER_PIN_INITIALIZED | CKF_TOKEN_INITIALIZED | cackey_slots[slotID].token_flags;





	pInfo->ulMaxSessionCount = (sizeof(cackey_sessions) / sizeof(cackey_sessions[0])) - 1;
	pInfo->ulSessionCount = CK_UNAVAILABLE_INFORMATION;
	pInfo->ulMaxRwSessionCount = 0;
	pInfo->ulRwSessionCount = CK_UNAVAILABLE_INFORMATION;
	pInfo->ulMaxPinLen = 128;
	pInfo->ulMinPinLen = 0;







>
>
>
>







4678
4679
4680
4681
4682
4683
4684
4685
4686
4687
4688
4689
4690
4691
4692
4693
4694
4695
	pInfo->hardwareVersion.major = (cackey_getversion() >> 16) & 0xff;
	pInfo->hardwareVersion.minor = (cackey_getversion() >> 8) & 0xff;

	pInfo->firmwareVersion.major = 0x00;
	pInfo->firmwareVersion.minor = 0x00;

	pInfo->flags = CKF_WRITE_PROTECTED | CKF_USER_PIN_INITIALIZED | CKF_TOKEN_INITIALIZED | cackey_slots[slotID].token_flags;

	if (cackey_pin_command != NULL) {
		pInfo->flags |= CKF_PROTECTED_AUTHENTICATION_PATH;
	}

	pInfo->ulMaxSessionCount = (sizeof(cackey_sessions) / sizeof(cackey_sessions[0])) - 1;
	pInfo->ulSessionCount = CK_UNAVAILABLE_INFORMATION;
	pInfo->ulMaxRwSessionCount = 0;
	pInfo->ulRwSessionCount = CK_UNAVAILABLE_INFORMATION;
	pInfo->ulMaxPinLen = 128;
	pInfo->ulMinPinLen = 0;
5108
5109
5110
5111
5112
5113
5114


5115
5116
5117

5118
5119
5120
5121
5122
5123
5124
	CACKEY_DEBUG_PRINTF("Returning CKR_FUNCTION_NOT_SUPPORTED (%i)", CKR_FUNCTION_NOT_SUPPORTED);

	return(CKR_FUNCTION_NOT_SUPPORTED);
}

CK_DEFINE_FUNCTION(CK_RV, C_Login)(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen) {
	CK_SLOT_ID slotID;


	int mutex_retval;
	int tries_remaining;
	int login_ret;


	CACKEY_DEBUG_PRINTF("Called.");

	if (!cackey_initialized) {
		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");

		return(CKR_CRYPTOKI_NOT_INITIALIZED);







>
>



>







5145
5146
5147
5148
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163
5164
	CACKEY_DEBUG_PRINTF("Returning CKR_FUNCTION_NOT_SUPPORTED (%i)", CKR_FUNCTION_NOT_SUPPORTED);

	return(CKR_FUNCTION_NOT_SUPPORTED);
}

CK_DEFINE_FUNCTION(CK_RV, C_Login)(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen) {
	CK_SLOT_ID slotID;
	FILE *pinfd;
	char *pincmd, pinbuf[64], *fgets_ret;
	int mutex_retval;
	int tries_remaining;
	int login_ret;
	int pclose_ret;

	CACKEY_DEBUG_PRINTF("Called.");

	if (!cackey_initialized) {
		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");

		return(CKR_CRYPTOKI_NOT_INITIALIZED);
5162
5163
5164
5165
5166
5167
5168



















































5169
5170
5171
5172
5173
5174
5175
	if (cackey_slots[slotID].active == 0) {
		CACKEY_DEBUG_PRINTF("Error. Invalid slot requested (%lu), slot not currently active", slotID);

		cackey_mutex_unlock(cackey_biglock);

		return(CKR_GENERAL_ERROR);
	}




















































	login_ret = cackey_login(&cackey_slots[slotID], pPin, ulPinLen, &tries_remaining);
	if (login_ret != CACKEY_PCSC_S_OK) {
		cackey_mutex_unlock(cackey_biglock);

		if (login_ret == CACKEY_PCSC_E_LOCKED) {
			CACKEY_DEBUG_PRINTF("Error.  Token is locked.");







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
	if (cackey_slots[slotID].active == 0) {
		CACKEY_DEBUG_PRINTF("Error. Invalid slot requested (%lu), slot not currently active", slotID);

		cackey_mutex_unlock(cackey_biglock);

		return(CKR_GENERAL_ERROR);
	}

	pincmd = cackey_pin_command;
	if (pincmd != NULL) {
		CACKEY_DEBUG_PRINTF("CACKEY_PIN_COMMAND = %s", pincmd);

		if (pPin != NULL) {
			CACKEY_DEBUG_PRINTF("Error.  Protected authentication path in effect and PIN provided !?");

			cackey_mutex_unlock(cackey_biglock);

			return(CKR_GENERAL_ERROR);
		}

		pinfd = popen(pincmd, "r");
		if (pinfd == NULL) {
			CACKEY_DEBUG_PRINTF("Error.  %s: Unable to run", pincmd);

			cackey_mutex_unlock(cackey_biglock);

			return(CKR_PIN_INCORRECT);
		}

		fgets_ret = fgets(pinbuf, sizeof(pinbuf), pinfd);
		if (fgets_ret == NULL) {
			pinbuf[0] = '\0';
		}

		pclose_ret = pclose(pinfd);
		if (pclose_ret != 0) {
			CACKEY_DEBUG_PRINTF("Error.  %s: exited with non-zero status of %i", pincmd, pclose_ret);

			cackey_mutex_unlock(cackey_biglock);

			return(CKR_PIN_INCORRECT);
		}

		if (strlen(pinbuf) < 1) {
			CACKEY_DEBUG_PRINTF("Error.  %s: returned no data", pincmd);

			cackey_mutex_unlock(cackey_biglock);

			return(CKR_PIN_INCORRECT);
		}

		if (pinbuf[strlen(pinbuf) - 1] == '\n') {
			pinbuf[strlen(pinbuf) - 1] = '\0';
		}

		pPin = (CK_UTF8CHAR_PTR) pinbuf;
		ulPinLen = strlen(pinbuf);
	}

	login_ret = cackey_login(&cackey_slots[slotID], pPin, ulPinLen, &tries_remaining);
	if (login_ret != CACKEY_PCSC_S_OK) {
		cackey_mutex_unlock(cackey_biglock);

		if (login_ret == CACKEY_PCSC_E_LOCKED) {
			CACKEY_DEBUG_PRINTF("Error.  Token is locked.");

Modified configure.ac from [9a7cfcd810] to [34fbe03317].

149
150
151
152
153
154
155





















156
157
158
159
160
161
162
163
164
165
166
167
], [
	dodcertsonhwslots=no
])

if ! test "${dodcertsonhwslots}" = 'no'; then
	AC_DEFINE(CACKEY_CARD_SLOT_INCLUDE_EXTRA_CERTS, [1], [Specify that DoD certificates should be made available on hardware token slots])
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
DC_SYNC_RPATH

dnl If we updated LIBOBJS, update SHLIBOBJS -- must be last.
DC_SYNC_SHLIBOBJS

dnl Produce Makefile
AC_OUTPUT(Makefile libcackey.syms)







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>












149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
], [
	dodcertsonhwslots=no
])

if ! test "${dodcertsonhwslots}" = 'no'; then
	AC_DEFINE(CACKEY_CARD_SLOT_INCLUDE_EXTRA_CERTS, [1], [Specify that DoD certificates should be made available on hardware token slots])
fi

dnl Option to hard-code a command to run to request a PIN (enabling protected authentication path)
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.]), [
	pincommand="${withval}"
], [
	pincommand="no"
])

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]), [
	pincommandxonly="${withval}"
], [
	pincommandxonly="no"
])

if ! test "${pincommand}" = 'no'; then
	AC_DEFINE_UNQUOTED(CACKEY_PIN_COMMAND_DEFAULT, [$pincommand], [Command to run to prompt user for PIN])
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

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
DC_SYNC_RPATH

dnl If we updated LIBOBJS, update SHLIBOBJS -- must be last.
DC_SYNC_SHLIBOBJS

dnl Produce Makefile
AC_OUTPUT(Makefile libcackey.syms)

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

331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
	chk_rv = C_OpenSession(slots[0], CKF_SERIAL_SESSION, NULL, NULL, &hSession);
	if (chk_rv == CKR_OK) {
		chk_rv = C_GetTokenInfo(slots[0], &tokenInfo);
		if (chk_rv != CKR_OK) {
			return(1);
		}

		if ((tokenInfo.flags & CKF_LOGIN_REQUIRED) == CKF_LOGIN_REQUIRED) {
			fgets_ret = NULL;

			while (fgets_ret == NULL) {
				printf("** ENTER PIN: ");
				fflush(stdout);

				fgets_ret = fgets((char *) user_pin, sizeof(user_pin), stdin);







|







331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
	chk_rv = C_OpenSession(slots[0], CKF_SERIAL_SESSION, NULL, NULL, &hSession);
	if (chk_rv == CKR_OK) {
		chk_rv = C_GetTokenInfo(slots[0], &tokenInfo);
		if (chk_rv != CKR_OK) {
			return(1);
		}

		if ((tokenInfo.flags & CKF_LOGIN_REQUIRED) == CKF_LOGIN_REQUIRED && (tokenInfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH) == 0) {
			fgets_ret = NULL;

			while (fgets_ret == NULL) {
				printf("** ENTER PIN: ");
				fflush(stdout);

				fgets_ret = fgets((char *) user_pin, sizeof(user_pin), stdin);