Check-in [d52881feec]
Overview
Comment:Improved waiting for slot event to allow C_Finalize to terminate any waiting
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | wait-for-slot-event
Files: files | file ages | folders
SHA1:d52881feec0a9e75f2d968f4aa98efb2105274a3
User & Date: rkeene on 2013-08-19 03:14:12
Other Links: manifest | tags
Context
2013-08-19
03:14
Improved waiting for slot event to allow C_Finalize to terminate any waiting Leaf check-in: d52881feec user: rkeene tags: wait-for-slot-event
2013-08-18
07:02
Added support for CKF_DONT_BLOCK check-in: 0058a3b41b user: rkeene tags: wait-for-slot-event
Changes

Modified cackey.c from [5d076538a2] to [ee6ec0dbf4].

   883    883   #define CACKEY_PIN_COMMAND_DEFAULT_XSTR(str) CACKEY_PIN_COMMAND_DEFAULT_STR(str)
   884    884   #define CACKEY_PIN_COMMAND_DEFAULT_STR(str) #str
   885    885   static char *cackey_pin_command = NULL;
   886    886   static char *cackey_pin_command_xonly = NULL;
   887    887   
   888    888   /* PCSC Global Handles */
   889    889   static LPSCARDCONTEXT cackey_pcsc_handle = NULL;
          890  +static LPSCARDCONTEXT cackey_waiting_pcsc_handle = NULL;
   890    891   
   891    892   static unsigned long cackey_getversion(void) {
   892    893   	static unsigned long retval = 255;
   893    894   	unsigned long major = 0;
   894    895   	unsigned long minor = 0;
   895    896   	char *major_str = NULL;
   896    897   	char *minor_str = NULL;
................................................................................
  1020   1021   			cackey_pcsc_handle = NULL;
  1021   1022   
  1022   1023   			cackey_slots_disconnect_all();
  1023   1024   
  1024   1025   			return(CACKEY_PCSC_E_GENERIC);
  1025   1026   		}
  1026   1027   	}
         1028  +
         1029  +	if (cackey_waiting_pcsc_handle == NULL) {
         1030  +		cackey_waiting_pcsc_handle = malloc(sizeof(*cackey_waiting_pcsc_handle));
         1031  +		if (cackey_waiting_pcsc_handle == NULL) {
         1032  +			CACKEY_DEBUG_PRINTF("Call to malloc() failed, returning in failure");
         1033  +
         1034  +			cackey_slots_disconnect_all();
         1035  +
         1036  +			free(cackey_pcsc_handle);
         1037  +			cackey_pcsc_handle = NULL;
         1038  +
         1039  +			return(CACKEY_PCSC_E_GENERIC);
         1040  +		}
         1041  +
         1042  +		CACKEY_DEBUG_PRINTF("SCardEstablishContext() called");
         1043  +		scard_est_context_ret = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, cackey_waiting_pcsc_handle);
         1044  +		if (scard_est_context_ret != SCARD_S_SUCCESS) {
         1045  +			CACKEY_DEBUG_PRINTF("Call to SCardEstablishContext failed (returned %s/%li), returning in failure", CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(scard_est_context_ret), (long) scard_est_context_ret);
         1046  +
         1047  +			free(cackey_pcsc_handle);
         1048  +			cackey_pcsc_handle = NULL;
         1049  +			free(cackey_waiting_pcsc_handle);
         1050  +			cackey_waiting_pcsc_handle = NULL;
         1051  +
         1052  +			cackey_slots_disconnect_all();
         1053  +
         1054  +			return(CACKEY_PCSC_E_GENERIC);
         1055  +		}
         1056  +	}
  1027   1057   
  1028   1058   #ifdef HAVE_SCARDISVALIDCONTEXT
  1029   1059   	CACKEY_DEBUG_PRINTF("SCardIsValidContext() called");
  1030   1060   	scard_isvalid_ret = SCardIsValidContext(*cackey_pcsc_handle);
  1031   1061   	if (scard_isvalid_ret != SCARD_S_SUCCESS) {
  1032   1062   		CACKEY_DEBUG_PRINTF("Handle has become invalid (SCardIsValidContext = %s/%li), trying to re-establish...", CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(scard_isvalid_ret), (long) scard_isvalid_ret);
  1033   1063   
................................................................................
  1042   1072   			cackey_slots_disconnect_all();
  1043   1073   
  1044   1074   			return(CACKEY_PCSC_E_GENERIC);
  1045   1075   		}
  1046   1076   
  1047   1077   		CACKEY_DEBUG_PRINTF("Handle has been re-established");
  1048   1078   	}
         1079  +
         1080  +	CACKEY_DEBUG_PRINTF("SCardIsValidContext() called");
         1081  +	scard_isvalid_ret = SCardIsValidContext(*cackey_waiting_pcsc_handle);
         1082  +	if (scard_isvalid_ret != SCARD_S_SUCCESS) {
         1083  +		CACKEY_DEBUG_PRINTF("Handle has become invalid (SCardIsValidContext = %s/%li), trying to re-establish...", CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(scard_isvalid_ret), (long) scard_isvalid_ret);
         1084  +
         1085  +		CACKEY_DEBUG_PRINTF("SCardEstablishContext() called");
         1086  +		scard_est_context_ret = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, cackey_waiting_pcsc_handle);
         1087  +		if (scard_est_context_ret != SCARD_S_SUCCESS) {
         1088  +			CACKEY_DEBUG_PRINTF("Call to SCardEstablishContext failed (returned %s/%li), returning in failure", CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(scard_est_context_ret), (long) scard_est_context_ret);
         1089  +
         1090  +			free(cackey_waiting_pcsc_handle);
         1091  +			cackey_waiting_pcsc_handle = NULL;
         1092  +
         1093  +			cackey_slots_disconnect_all();
         1094  +
         1095  +			return(CACKEY_PCSC_E_GENERIC);
         1096  +		}
         1097  +
         1098  +		CACKEY_DEBUG_PRINTF("Waiting handle has been re-established");
         1099  +	}
  1049   1100   #endif
  1050   1101   
  1051   1102   	CACKEY_DEBUG_PRINTF("Sucessfully connected to PC/SC, returning in success");
  1052   1103   
  1053   1104   	return(CACKEY_PCSC_S_OK);
  1054   1105   }
  1055   1106   
................................................................................
  1067   1118    * NOTES
  1068   1119    *     This function disconnects from the PC/SC Connection manager and updates
  1069   1120    *     the global handle.
  1070   1121    *
  1071   1122    */
  1072   1123   static cackey_ret cackey_pcsc_disconnect(void) {
  1073   1124   	LONG scard_rel_context_ret;
         1125  +	cackey_ret retval = CACKEY_PCSC_S_OK;
  1074   1126   
  1075   1127   	CACKEY_DEBUG_PRINTF("Called.");
  1076   1128   
  1077         -	if (cackey_pcsc_handle == NULL) {
  1078         -		return(CACKEY_PCSC_S_OK);
  1079         -	}
         1129  +	if (cackey_pcsc_handle != NULL) {
         1130  +		scard_rel_context_ret = SCardReleaseContext(*cackey_pcsc_handle);
         1131  +		if (scard_rel_context_ret != SCARD_S_SUCCESS) {
         1132  +			retval = CACKEY_PCSC_E_GENERIC;
         1133  +		}
  1080   1134   
  1081         -	scard_rel_context_ret = SCardReleaseContext(*cackey_pcsc_handle);
  1082         -
  1083         -	if (cackey_pcsc_handle) {
  1084   1135   		free(cackey_pcsc_handle);
  1085   1136   	
  1086   1137   		cackey_pcsc_handle = NULL;
  1087   1138   	}
  1088   1139   
  1089         -	if (scard_rel_context_ret != SCARD_S_SUCCESS) {
  1090         -		return(CACKEY_PCSC_E_GENERIC);
         1140  +	if (cackey_waiting_pcsc_handle != NULL) {
         1141  +		scard_rel_context_ret = SCardReleaseContext(*cackey_waiting_pcsc_handle);
         1142  +		if (scard_rel_context_ret != SCARD_S_SUCCESS) {
         1143  +			retval = CACKEY_PCSC_E_GENERIC;
         1144  +		}
         1145  +
         1146  +		free(cackey_waiting_pcsc_handle);
         1147  +	
         1148  +		cackey_waiting_pcsc_handle = NULL;
  1091   1149   	}
  1092   1150   
  1093         -	return(CACKEY_PCSC_S_OK);
         1151  +	return(retval);
  1094   1152   }
  1095   1153   
  1096   1154   /*
  1097   1155    * SYNPOSIS
  1098   1156    *     void cackey_mark_slot_reset(struct cackey_slot *slot);
  1099   1157    *
  1100   1158    * ARGUMENTS
................................................................................
  4201   4259   
  4202   4260   	for (idx = 0; idx < (sizeof(cackey_sessions) / sizeof(cackey_sessions[0])); idx++) {
  4203   4261   		if (cackey_sessions[idx].active) {
  4204   4262   			C_CloseSession(idx);
  4205   4263   		}
  4206   4264   	}
  4207   4265   
         4266  +	cackey_mutex_lock(cackey_biglock);
         4267  +
  4208   4268   	cackey_slots_disconnect_all();
  4209   4269   
  4210   4270   	for (idx = 0; idx < (sizeof(cackey_slots) / sizeof(cackey_slots[0])); idx++) {
  4211   4271   		if (cackey_slots[idx].internal) {
  4212   4272   			continue;
  4213   4273   		}
  4214   4274   
................................................................................
  4222   4282   			cackey_slots[idx].cached_certs = NULL;
  4223   4283   		}
  4224   4284   	}
  4225   4285   
  4226   4286   	cackey_pcsc_disconnect();
  4227   4287   
  4228   4288   	cackey_initialized = 0;
         4289  +
         4290  +	cackey_mutex_unlock(cackey_biglock);
  4229   4291   
  4230   4292   	CACKEY_DEBUG_PRINTF("Returning CKR_OK (%i)", CKR_OK);
  4231   4293   
  4232   4294   	return(CKR_OK);
  4233   4295   }
  4234   4296   
  4235   4297   CK_DEFINE_FUNCTION(CK_RV, C_GetInfo)(CK_INFO_PTR pInfo) {
................................................................................
  4727   4789   	CACKEY_DEBUG_PRINTF("Returning CKR_OK (%i)", CKR_OK);
  4728   4790   
  4729   4791   	return(CKR_OK);
  4730   4792   }
  4731   4793   
  4732   4794   CK_DEFINE_FUNCTION(CK_RV, C_WaitForSlotEvent)(CK_FLAGS flags, CK_SLOT_ID_PTR pSlotID, CK_VOID_PTR pReserved) {
  4733   4795   	SCARD_READERSTATE reader_states[(sizeof(cackey_slots) / sizeof(cackey_slots[0])) + 1];
  4734         -	SCARDCONTEXT pcsc_handle;
         4796  +	LPSCARDCONTEXT handle;
  4735   4797   	LONG scard_getstatchng_ret;
  4736         -	LONG scard_est_context_ret;
         4798  +	cackey_ret pcsc_connect_ret;
  4737   4799   	struct cackey_slot *cackey_slot;
  4738         -	unsigned int currslot, reader_state_slot;
  4739         -	int pcsc_connect_ret;
         4800  +	unsigned int currslot, reader_state_slot, reader_state_slot_cnt;
         4801  +	int mutex_retval;
  4740   4802   	int slot_changed;
  4741   4803   
  4742   4804   	CACKEY_DEBUG_PRINTF("Called.");
  4743   4805   
  4744   4806   	if (pReserved != NULL) {
  4745   4807   		CACKEY_DEBUG_PRINTF("Error. pReserved is not NULL.");
  4746   4808   
................................................................................
  4754   4816   	}
  4755   4817   
  4756   4818   	if (!cackey_initialized) {
  4757   4819   		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
  4758   4820   
  4759   4821   		return(CKR_CRYPTOKI_NOT_INITIALIZED);
  4760   4822   	}
         4823  +
         4824  +	mutex_retval = cackey_mutex_lock(cackey_biglock);
         4825  +	if (mutex_retval != 0) {
         4826  +		CACKEY_DEBUG_PRINTF("Error.  Locking failed.");
         4827  +
         4828  +		return(CKR_GENERAL_ERROR);
         4829  +	}
  4761   4830   
  4762   4831   	pcsc_connect_ret = cackey_pcsc_connect();
  4763   4832   	if (pcsc_connect_ret != CACKEY_PCSC_S_OK) {
         4833  +		cackey_mutex_unlock(cackey_biglock);
         4834  +
  4764   4835   		CACKEY_DEBUG_PRINTF("Connection to PC/SC failed, returning in failure");
  4765   4836   
  4766   4837   		return(CKR_GENERAL_ERROR);
  4767   4838   	}
  4768   4839   
  4769   4840   	for (reader_state_slot = currslot = 0; currslot < (sizeof(cackey_slots) / sizeof(cackey_slots[0])); currslot++) {
  4770   4841   		if (cackey_slots[currslot].internal) {
................................................................................
  4782   4853   			reader_states[reader_state_slot].dwCurrentState = SCARD_STATE_UNAWARE;
  4783   4854   		} else {
  4784   4855   			reader_states[reader_state_slot].dwCurrentState = cackey_slots[currslot].pcsc_state;
  4785   4856   		}
  4786   4857   
  4787   4858   		reader_state_slot++;
  4788   4859   	}
         4860  +
         4861  +	mutex_retval = cackey_mutex_unlock(cackey_biglock);
         4862  +	if (mutex_retval != 0) {
         4863  +		CACKEY_DEBUG_PRINTF("Error.  Unlocking failed.");
         4864  +
         4865  +		return(CKR_GENERAL_ERROR);
         4866  +	}
  4789   4867   
  4790   4868   	reader_states[reader_state_slot].szReader = "\\\\?PnP?\\Notification";
  4791   4869   	reader_states[reader_state_slot].pvUserData = NULL;
  4792   4870   	reader_states[reader_state_slot].dwCurrentState = SCARD_STATE_UNAWARE;
  4793   4871   	reader_state_slot++;
  4794   4872   
  4795         -	scard_est_context_ret = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &pcsc_handle);
  4796         -	if (scard_est_context_ret != SCARD_S_SUCCESS) {
  4797         -		CACKEY_DEBUG_PRINTF("Returning CKR_GENERAL_ERROR (%i) because SCardEstablishContext failed: %lx", CKR_GENERAL_ERROR, scard_est_context_ret);
         4873  +	reader_state_slot_cnt = reader_state_slot;
  4798   4874   
  4799         -		return(CKR_GENERAL_ERROR);
         4875  +	while (1) {
         4876  +		cackey_mutex_lock(cackey_biglock);
         4877  +
         4878  +		handle = cackey_waiting_pcsc_handle;
         4879  +
         4880  +		cackey_mutex_unlock(cackey_biglock);
         4881  +
         4882  +		if (handle == NULL) {
         4883  +			CACKEY_DEBUG_PRINTF("Waiting handle disappeared, not attempting to wait.");
         4884  +
         4885  +			break;
         4886  +		}
         4887  +
         4888  +		CACKEY_DEBUG_PRINTF("Calling SCardGetStatusChange(), which will block for 1 second");
         4889  +		scard_getstatchng_ret = SCardGetStatusChange(*handle, 1000, reader_states, reader_state_slot_cnt);
         4890  +
         4891  +		if (scard_getstatchng_ret == SCARD_E_TIMEOUT) {
         4892  +			continue;
         4893  +		}
         4894  +
         4895  +		break;
  4800   4896   	}
  4801   4897   
  4802         -	scard_getstatchng_ret = SCardGetStatusChange(pcsc_handle, INFINITE, reader_states, reader_state_slot);
  4803         -
  4804         -	SCardReleaseContext(pcsc_handle);
  4805         -
  4806   4898   	if (scard_getstatchng_ret != SCARD_S_SUCCESS) {
  4807   4899   		CACKEY_DEBUG_PRINTF("Returning CKR_GENERAL_ERROR (%i) because SCardGetStatusChange failed: %lx", CKR_GENERAL_ERROR, scard_getstatchng_ret);
  4808   4900   
  4809   4901   		return(CKR_GENERAL_ERROR);
  4810   4902   	}
  4811   4903   
  4812         -	for (currslot = 0; currslot < reader_state_slot; currslot++) {
  4813         -		CACKEY_DEBUG_PRINTF("[slot = %u] CurrentState = %lx, EventState = %lx",
  4814         -		    currslot,
  4815         -		    reader_states[currslot].dwCurrentState & 0xffff,
  4816         -		    reader_states[currslot].dwEventState & 0xffff
         4904  +	mutex_retval = cackey_mutex_lock(cackey_biglock);
         4905  +	if (mutex_retval != 0) {
         4906  +		CACKEY_DEBUG_PRINTF("Error.  Locking failed.");
         4907  +
         4908  +		return(CKR_GENERAL_ERROR);
         4909  +	}
         4910  +
         4911  +	for (reader_state_slot = 0; reader_state_slot < reader_state_slot_cnt; reader_state_slot++) {
         4912  +		CACKEY_DEBUG_PRINTF("[pcsc/slot = %u] CurrentState = %lx, EventState = %lx",
         4913  +		    reader_state_slot,
         4914  +		    reader_states[reader_state_slot].dwCurrentState & 0xffff,
         4915  +		    reader_states[reader_state_slot].dwEventState & 0xffff
  4817   4916   		);
  4818   4917   
  4819         -		cackey_slot = (struct cackey_slot *) reader_states[currslot].pvUserData;
         4918  +		cackey_slot = NULL;
         4919  +		for (currslot = 0; currslot < (sizeof(cackey_slots) / sizeof(cackey_slots[0])); currslot++) {
         4920  +			if (cackey_slots[currslot].internal) {
         4921  +				continue;
         4922  +			}
         4923  +
         4924  +			if (reader_states[reader_state_slot].szReader == NULL) {
         4925  +				continue;
         4926  +			}
         4927  +
         4928  +			if (cackey_slots[currslot].pcsc_reader == NULL) {
         4929  +				continue;
         4930  +			}
         4931  +
         4932  +			CACKEY_DEBUG_PRINTF("Checking to see if pcsc/slot:%u (%s) is cackey/slot:%u (%s)...",
         4933  +			    reader_state_slot,
         4934  +			    reader_states[reader_state_slot].szReader,
         4935  +			    currslot,
         4936  +			    cackey_slots[currslot].pcsc_reader
         4937  +			);
         4938  +
         4939  +			if (strcmp(reader_states[reader_state_slot].szReader, cackey_slots[currslot].pcsc_reader) != 0) {
         4940  +				CACKEY_DEBUG_PRINTF("   no match");
         4941  +
         4942  +				continue;
         4943  +			}
         4944  +
         4945  +			cackey_slot = &cackey_slots[currslot];
         4946  +
         4947  +			CACKEY_DEBUG_PRINTF("   match, slot = %p", cackey_slot);
         4948  +
         4949  +			break;
         4950  +		}
  4820   4951   
  4821   4952   		if (cackey_slot == NULL) {
  4822         -			/* XXX: TODO: Someone plugged in a new slot */
         4953  +			/* XXX: TODO: Someone plugged in a new slot or removed a slot */
         4954  +			CACKEY_DEBUG_PRINTF("WARNING: Unhandled code.  Slot inserted or removed.");
         4955  +
  4823   4956   			continue;
  4824   4957   		}
  4825   4958   
  4826   4959   		slot_changed = 0;
  4827   4960   
  4828   4961   		if ((flags & CKF_DONT_BLOCK) == CKF_DONT_BLOCK) {
  4829         -			if (cackey_slot->pcsc_state != reader_states[currslot].dwEventState) {
         4962  +			if (cackey_slot->pcsc_state != reader_states[reader_state_slot].dwEventState) {
  4830   4963   				slot_changed = 1;
  4831   4964   			}
  4832   4965   		} else {
  4833         -			if (reader_states[currslot].dwCurrentState != reader_states[currslot].dwEventState) {
         4966  +			if (reader_states[reader_state_slot].dwCurrentState != reader_states[reader_state_slot].dwEventState) {
  4834   4967   				slot_changed = 1;
  4835   4968   			}
  4836   4969   		}
  4837   4970   
  4838   4971   		if (slot_changed == 0) {
         4972  +			CACKEY_DEBUG_PRINTF("[pcsc/slot = %u] Slot did not change", (unsigned int) reader_state_slot);
         4973  +
  4839   4974   			continue;
  4840   4975   		}
  4841   4976   
  4842   4977   		CACKEY_DEBUG_PRINTF("Returning slot changed: %u", (unsigned int) cackey_slot->id);
  4843   4978   
  4844         -		cackey_slot->pcsc_state = reader_states[currslot].dwEventState;
         4979  +		cackey_slot->pcsc_state = reader_states[reader_state_slot].dwEventState;
  4845   4980   		*pSlotID = (CK_SLOT_ID) cackey_slot->id;
  4846   4981   
  4847   4982   		CACKEY_DEBUG_PRINTF("Returning CKR_OK (%i)", CKR_OK);
         4983  +
         4984  +		mutex_retval = cackey_mutex_unlock(cackey_biglock);
         4985  +		if (mutex_retval != 0) {
         4986  +			CACKEY_DEBUG_PRINTF("Error.  Unlocking failed.");
         4987  +
         4988  +			return(CKR_GENERAL_ERROR);
         4989  +		}
  4848   4990   
  4849   4991   		return(CKR_OK);
  4850   4992   	}
         4993  +
         4994  +	mutex_retval = cackey_mutex_unlock(cackey_biglock);
         4995  +	if (mutex_retval != 0) {
         4996  +		CACKEY_DEBUG_PRINTF("Error.  Unlocking failed.");
         4997  +
         4998  +		return(CKR_GENERAL_ERROR);
         4999  +	}
  4851   5000   
  4852   5001   	if ((flags & CKF_DONT_BLOCK) != CKF_DONT_BLOCK) {
  4853   5002   		CACKEY_DEBUG_PRINTF("Returning CKR_NO_EVENT (%i), but asked to block !? BUG ENCOUNTERED.", CKR_NO_EVENT);
  4854   5003   	} else {
  4855   5004   		CACKEY_DEBUG_PRINTF("Returning CKR_NO_EVENT (%i)", CKR_NO_EVENT);
  4856   5005   	}
  4857   5006