Check-in [491b6e0b00]
Overview
Comment:Updated to check for token presence using PC/SC rather than probing the CCC

Updated to cache token label

Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:491b6e0b000796fc656ce1a539c79756f96e83e5
User & Date: rkeene on 2010-05-18 15:31:54
Other Links: manifest | tags
Context
2010-05-18
15:35
Moved PC/SC calls within big global lock check-in: 468216a439 user: rkeene tags: trunk
15:31
Updated to check for token presence using PC/SC rather than probing the CCC

Updated to cache token label check-in: 491b6e0b00 user: rkeene tags: trunk

14:28
Updated to always flush stderr check-in: b8b081a8e4 user: rkeene tags: trunk
Changes

Modified cackey.c from [a15198f18c] to [f66c56f731].

   460    460   #  define CACKEY_DEBUG_FUNC_APPTYPE_TO_STR(x) "DEBUG_DISABLED"
   461    461   #endif
   462    462   
   463    463   struct cackey_pcsc_identity {
   464    464   	unsigned char applet[7];
   465    465   	uint16_t file;
   466    466   
   467         -	unsigned char *label;
   468         -
   469    467   	size_t certificate_len;
   470    468   	unsigned char *certificate;
   471    469   
   472    470   	ssize_t keysize;
   473    471   };
   474    472   
   475    473   struct cackey_identity {
................................................................................
   521    519   	SCARDHANDLE pcsc_card;
   522    520   
   523    521   	int transaction_depth;
   524    522   
   525    523   	int slot_reset;
   526    524   
   527    525   	CK_FLAGS token_flags;
          526  +
          527  +	unsigned char *label;
   528    528   };
   529    529   
   530    530   typedef enum {
   531    531   	CACKEY_TLV_APP_GENERIC = 0x01,
   532    532   	CACKEY_TLV_APP_SKI     = 0x02,
   533    533   	CACKEY_TLV_APP_PKI     = 0x04
   534    534   } cackey_tlv_apptype;
................................................................................
   647    647   
   648    648   	for (idx = 0; idx < (sizeof(cackey_slots) / sizeof(cackey_slots[0])); idx++) {
   649    649   		if (cackey_slots[idx].pcsc_card_connected) {
   650    650   			CACKEY_DEBUG_PRINTF("SCardDisconnect(%lu) called", (unsigned long) idx);
   651    651   
   652    652   			SCardDisconnect(cackey_slots[idx].pcsc_card, SCARD_LEAVE_CARD);
   653    653   		}
          654  +
          655  +		if (cackey_slots[idx].label) {
          656  +			free(cackey_slots[idx].label);
          657  +
          658  +			cackey_slots[idx].label = NULL;
          659  +		}
   654    660   
   655    661   		cackey_slots[idx].pcsc_card_connected = 0;
   656    662   		cackey_slots[idx].transaction_depth = 0;
   657    663   
   658    664   		if (cackey_slots[idx].active) {
   659    665   			CACKEY_DEBUG_PRINTF("Marking active slot %lu as being reset", (unsigned long) idx);
   660    666   		}
................................................................................
  1784   1790   			}
  1785   1791   
  1786   1792   			curr_id = &certs[outidx];
  1787   1793   			outidx++;
  1788   1794   
  1789   1795   			memcpy(curr_id->applet, curr_aid, sizeof(curr_id->applet));
  1790   1796   			curr_id->file = ccc_curr->value_cardurl->objectid;
  1791         -			curr_id->label = NULL;
  1792   1797   			curr_id->keysize = -1;
  1793   1798   
  1794   1799   			CACKEY_DEBUG_PRINTF("Filling curr_id->applet (%p) with %lu bytes:", curr_id->applet, (unsigned long) sizeof(curr_id->applet));
  1795   1800   			CACKEY_DEBUG_PRINTBUF("VAL:", curr_id->applet, sizeof(curr_id->applet));
  1796   1801   
  1797   1802   			curr_id->certificate_len = app_curr->length;
  1798   1803   
................................................................................
  2168   2173    *     ...
  2169   2174    *
  2170   2175    * NOTES
  2171   2176    *     ...
  2172   2177    *
  2173   2178    */
  2174   2179   static cackey_ret cackey_token_present(struct cackey_slot *slot) {
  2175         -	unsigned char ccc_aid[] = {GSCIS_AID_CCC};
  2176         -	int send_ret;
         2180  +	cackey_ret pcsc_connect_ret;
         2181  +	DWORD reader_len, state, protocol, atr_len;
         2182  +	BYTE atr[MAX_ATR_SIZE];
         2183  +	LONG status_ret, scard_reconn_ret;
  2177   2184   
  2178         -	/* Select the CCC Applet */
  2179         -	send_ret = cackey_select_applet(slot, ccc_aid, sizeof(ccc_aid));
  2180         -	if (send_ret != CACKEY_PCSC_S_OK) {
         2185  +	CACKEY_DEBUG_PRINTF("Called.");
         2186  +
         2187  +	pcsc_connect_ret = cackey_connect_card(slot);
         2188  +	if (pcsc_connect_ret != CACKEY_PCSC_S_OK) {
         2189  +		CACKEY_DEBUG_PRINTF("Unable to connect to card, returning token absent");
         2190  +
         2191  +		return(CACKEY_PCSC_S_TOKENABSENT);
         2192  +	}
         2193  +
         2194  +	atr_len = sizeof(atr);
         2195  +	status_ret = SCardStatus(slot->pcsc_card, NULL, &reader_len, &state, &protocol, atr, &atr_len);
         2196  +	if (status_ret != SCARD_S_SUCCESS) {
         2197  +		if (status_ret == SCARD_W_RESET_CARD) {
         2198  +			CACKEY_DEBUG_PRINTF("Reset required, please hold...");
         2199  +
         2200  +			scard_reconn_ret = SCardReconnect(slot->pcsc_card, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, SCARD_RESET_CARD, &protocol);
         2201  +			if (scard_reconn_ret == SCARD_S_SUCCESS) {
         2202  +				/* Re-establish transaction, if it was present */
         2203  +				if (slot->transaction_depth > 0) {
         2204  +					slot->transaction_depth--;
         2205  +					cackey_begin_transaction(slot);
         2206  +				}
         2207  +
         2208  +				CACKEY_DEBUG_PRINTF("Reset successful, requerying");
         2209  +				status_ret = SCardStatus(slot->pcsc_card, NULL, &reader_len, &state, &protocol, atr, &atr_len);
         2210  +				if (status_ret != SCARD_S_SUCCESS) {
         2211  +					CACKEY_DEBUG_PRINTF("Still unable to query card status, returning token absent.  SCardStatus() = %s", CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(status_ret));
         2212  +
         2213  +					return(CACKEY_PCSC_S_TOKENABSENT);
         2214  +				}
         2215  +			} else {
         2216  +				CACKEY_DEBUG_PRINTF("Unable to reconnect to card, returning token absent.  SCardReconnect() = %s", CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(scard_reconn_ret));
         2217  +
         2218  +				return(CACKEY_PCSC_S_TOKENABSENT);
         2219  +			}
         2220  +		} else {
         2221  +			CACKEY_DEBUG_PRINTF("Unable to query card status, returning token absent.  SCardStatus() = %s", CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(status_ret));
         2222  +
         2223  +			return(CACKEY_PCSC_S_TOKENABSENT);
         2224  +		}
         2225  +	}
         2226  +
         2227  +	if ((state & SCARD_ABSENT) == SCARD_ABSENT) {
         2228  +		CACKEY_DEBUG_PRINTF("Card is absent, returning token absent");
         2229  +
  2181   2230   		return(CACKEY_PCSC_S_TOKENABSENT);
  2182   2231   	}
         2232  +
         2233  +	CACKEY_DEBUG_PRINTF("Returning token present.");
  2183   2234   
  2184   2235   	return(CACKEY_PCSC_S_TOKENPRESENT);
  2185   2236   }
  2186   2237   
  2187   2238   /*
  2188   2239    * SYNPOSIS
  2189   2240    *     ...
................................................................................
  2813   2864   
  2814   2865   	for (idx = 0; idx < (sizeof(cackey_slots) / sizeof(cackey_slots[0])); idx++) {
  2815   2866   		cackey_slots[idx].active = 0;
  2816   2867   		cackey_slots[idx].pcsc_reader = NULL;
  2817   2868   		cackey_slots[idx].transaction_depth = 0;
  2818   2869   		cackey_slots[idx].slot_reset = 0;
  2819   2870   		cackey_slots[idx].token_flags = 0;
         2871  +		cackey_slots[idx].label = NULL;
  2820   2872   	}
  2821   2873   
  2822   2874   	cackey_initialized = 1;
  2823   2875   
  2824   2876   	if (!cackey_biglock_init) {
  2825   2877   		mutex_init_ret = cackey_mutex_create(&cackey_biglock);
  2826   2878   
................................................................................
  2946   2998   		CACKEY_DEBUG_PRINTF("Error.  Locking failed.");
  2947   2999   
  2948   3000   		return(CKR_GENERAL_ERROR);
  2949   3001   	}
  2950   3002   
  2951   3003   	/* Clear list of slots */
  2952   3004   	if (pSlotList) {
         3005  +		CACKEY_DEBUG_PRINTF("Purging all slot information.");
         3006  +
  2953   3007   		/* Only update the list of slots if we are actually being supply the slot information */
  2954   3008   		cackey_slots_disconnect_all();
  2955   3009   
  2956   3010   		for (currslot = 0; currslot < (sizeof(cackey_slots) / sizeof(cackey_slots[0])); currslot++) {
  2957   3011   			if (cackey_slots[currslot].pcsc_reader) {
  2958   3012   				free(cackey_slots[currslot].pcsc_reader);
  2959   3013   
  2960   3014   				cackey_slots[currslot].pcsc_reader = NULL;
  2961   3015   			}
         3016  +
         3017  +			if (cackey_slots[currslot].label) {
         3018  +				free(cackey_slots[currslot].label);
         3019  +
         3020  +				cackey_slots[currslot].label = NULL;
         3021  +			}
  2962   3022   
  2963   3023   			cackey_slots[currslot].active = 0;
  2964   3024   		}
  2965   3025   	}
  2966   3026   
  2967   3027   	/* Determine list of readers */
  2968   3028   	pcsc_connect_ret = cackey_pcsc_connect();
................................................................................
  2998   3058   						CACKEY_DEBUG_PRINTF("Found more readers than slots are available!");
  2999   3059   
  3000   3060   						break;
  3001   3061   					}
  3002   3062   
  3003   3063   					CACKEY_DEBUG_PRINTF("Found reader: %s", pcsc_readers);
  3004   3064   
  3005         -					/* Only update the list of slots if we are actually being supply the slot information */
         3065  +					/* Only update the list of slots if we are actually being asked supply the slot information */
  3006   3066   					if (pSlotList) {
  3007   3067   						cackey_slots[currslot].active = 1;
  3008   3068   						cackey_slots[currslot].pcsc_reader = strdup(pcsc_readers);
  3009   3069   						cackey_slots[currslot].pcsc_card_connected = 0;
  3010   3070   						cackey_slots[currslot].transaction_depth = 0;
  3011   3071   						cackey_slots[currslot].slot_reset = 1;
  3012   3072   						cackey_slots[currslot].token_flags = CKF_LOGIN_REQUIRED;
         3073  +						cackey_slots[currslot].label = NULL;
  3013   3074   					}
  3014   3075   					currslot++;
  3015   3076   
  3016   3077   					pcsc_readers += curr_reader_len + 1;
  3017   3078   				}
  3018   3079   
  3019   3080   				if (currslot > 0) {
................................................................................
  3199   3260   		return(CKR_GENERAL_ERROR);
  3200   3261   	}
  3201   3262   
  3202   3263   	/* Determine token label from certificates */
  3203   3264   	memset(pInfo->label, ' ', sizeof(pInfo->label));
  3204   3265   	use_default_label = 1;
  3205   3266   
  3206         -	pcsc_identities = cackey_read_certs(&cackey_slots[slotID], NULL, &num_certs);
  3207         -	if (pcsc_identities != NULL) {
  3208         -		if (num_certs > 0) {
  3209         -			label_ret = cackey_pcsc_identity_to_label(pcsc_identities, pInfo->label, sizeof(pInfo->label));
  3210         -			if (label_ret > 0) {
  3211         -				use_default_label = 0;
         3267  +	if (cackey_slots[slotID].label == NULL) {
         3268  +		pcsc_identities = cackey_read_certs(&cackey_slots[slotID], NULL, &num_certs);
         3269  +		if (pcsc_identities != NULL) {
         3270  +			if (num_certs > 0) {
         3271  +				label_ret = cackey_pcsc_identity_to_label(pcsc_identities, pInfo->label, sizeof(pInfo->label));
         3272  +				if (label_ret > 0) {
         3273  +					use_default_label = 0;
         3274  +
         3275  +					cackey_slots[slotID].label = malloc(sizeof(pInfo->label));
         3276  +
         3277  +					memcpy(cackey_slots[slotID].label, pInfo->label, sizeof(pInfo->label));
         3278  +				}
  3212   3279   			}
         3280  +
         3281  +			cackey_free_certs(pcsc_identities, num_certs, 1);
  3213   3282   		}
         3283  +	} else {
         3284  +		memcpy(pInfo->label, cackey_slots[slotID].label, sizeof(pInfo->label));
  3214   3285   
  3215         -		cackey_free_certs(pcsc_identities, num_certs, 1);
         3286  +		use_default_label = 0;
  3216   3287   	}
  3217   3288   
  3218   3289   	if (use_default_label) {
  3219   3290   		memcpy(pInfo->label, defaultLabel, sizeof(defaultLabel) - 1);
  3220   3291   	}
  3221   3292   
  3222   3293   	memset(pInfo->manufacturerID, ' ', sizeof(pInfo->manufacturerID));
................................................................................
  4073   4144   
  4074   4145   		if (cackey_sessions[hSession].identities != NULL) {
  4075   4146   			cackey_free_identities(cackey_sessions[hSession].identities, cackey_sessions[hSession].identities_count);
  4076   4147   
  4077   4148   			cackey_sessions[hSession].identities = NULL;
  4078   4149   			cackey_sessions[hSession].identities_count = 0;
  4079   4150   		}
         4151  +
         4152  +		if (cackey_slots[cackey_sessions[hSession].slotID].label != NULL) {
         4153  +			free(cackey_slots[cackey_sessions[hSession].slotID].label);
         4154  +			cackey_slots[cackey_sessions[hSession].slotID].label = NULL;
         4155  +		}
  4080   4156   
  4081   4157   		cackey_slots[cackey_sessions[hSession].slotID].slot_reset = 0;
  4082   4158   		cackey_slots[cackey_sessions[hSession].slotID].token_flags = CKF_LOGIN_REQUIRED;
  4083   4159   	}
  4084   4160   
  4085   4161   	if (cackey_sessions[hSession].identities == NULL) {
  4086   4162   		cackey_sessions[hSession].identities = cackey_read_identities(&cackey_slots[cackey_sessions[hSession].slotID], &cackey_sessions[hSession].identities_count);