Diff

Differences From Artifact [ebe379d38c]:

To Artifact [6db8eb96eb]:


   813    813   
   814    814   	unsigned char *label;
   815    815   
   816    816   	DWORD protocol;
   817    817   
   818    818   	unsigned int cached_certs_count;
   819    819   	struct cackey_pcsc_identity *cached_certs;
          820  +
          821  +	cackey_pcsc_id_type id_type_hint;
   820    822   };
   821    823   
   822    824   typedef enum {
   823    825   	CACKEY_TLV_APP_GENERIC = 0x01,
   824    826   	CACKEY_TLV_APP_SKI     = 0x02,
   825    827   	CACKEY_TLV_APP_PKI     = 0x04
   826    828   } cackey_tlv_apptype;
................................................................................
   934    936   
   935    937   	return(retval);
   936    938   }
   937    939   
   938    940   /* PC/SC Related Functions */
   939    941   /*
   940    942    * SYNPOSIS
   941         - *     void cackey_slots_disconnect_all(void);
          943  + *     void cackey_slots_disconnect_all(int unitialize_all_readers);
   942    944    *
   943    945    * ARGUMENTS
   944         - *     None
          946  + *     int unitialize_all_readers      Free the "pcsc_reader" object associated with
          947  + *                           each slot (boolean)
   945    948    *
   946    949    * RETURN VALUE
   947    950    *     None
   948    951    *
   949    952    * NOTES
   950    953    *     This function disconnects from all cards.
   951    954    *
   952    955    */
   953         -static void cackey_slots_disconnect_all(void) {
          956  +static void cackey_slots_disconnect_all(int unitialize_all_readers) {
   954    957   	uint32_t idx;
   955    958   
   956    959   	CACKEY_DEBUG_PRINTF("Called.");
   957    960   
   958    961   	for (idx = 0; idx < (sizeof(cackey_slots) / sizeof(cackey_slots[0])); idx++) {
   959    962   		if (cackey_slots[idx].internal) {
   960    963   			/* Skip internal slots */
................................................................................
   968    971   		}
   969    972   
   970    973   		if (cackey_slots[idx].label) {
   971    974   			free(cackey_slots[idx].label);
   972    975   
   973    976   			cackey_slots[idx].label = NULL;
   974    977   		}
          978  +
          979  +		if (unitialize_all_readers || !cackey_slots[idx].active) {
          980  +			if (cackey_slots[idx].pcsc_reader) {
          981  +				free(cackey_slots[idx].pcsc_reader);
          982  +
          983  +				cackey_slots[idx].pcsc_reader = NULL;
          984  +			}
          985  +
          986  +			cackey_slots[idx].transaction_need_hw_lock = 0;
          987  +			cackey_slots[idx].transaction_depth = 0;
          988  +			cackey_slots[idx].id_type_hint = CACKEY_ID_TYPE_UNKNOWN;
          989  +		} else {
          990  +			if (cackey_slots[idx].transaction_depth > 0) {
          991  +				cackey_slots[idx].transaction_need_hw_lock = 1;
          992  +			}
          993  +		}
   975    994   
   976    995   		cackey_slots[idx].pcsc_card_connected = 0;
   977         -		cackey_slots[idx].transaction_depth = 0;
   978         -		cackey_slots[idx].transaction_need_hw_lock = 0;
   979    996   
   980    997   		if (cackey_slots[idx].active) {
   981    998   			CACKEY_DEBUG_PRINTF("Marking active slot %lu as being reset", (unsigned long) idx);
          999  +
         1000  +			cackey_slots[idx].slot_reset = 1;
   982   1001   		}
   983         -
   984         -		cackey_slots[idx].slot_reset = 1;
   985   1002   	}
   986   1003   
   987   1004   	CACKEY_DEBUG_PRINTF("Returning");
   988   1005   
   989   1006   	return;
   990   1007   }
   991   1008   
................................................................................
  1014   1031   	CACKEY_DEBUG_PRINTF("Called.");
  1015   1032   
  1016   1033   	if (cackey_pcsc_handle == NULL) {
  1017   1034   		cackey_pcsc_handle = malloc(sizeof(*cackey_pcsc_handle));
  1018   1035   		if (cackey_pcsc_handle == NULL) {
  1019   1036   			CACKEY_DEBUG_PRINTF("Call to malloc() failed, returning in failure");
  1020   1037   
  1021         -			cackey_slots_disconnect_all();
         1038  +			cackey_slots_disconnect_all(0);
  1022   1039   
  1023   1040   			return(CACKEY_PCSC_E_GENERIC);
  1024   1041   		}
  1025   1042   
  1026   1043   		CACKEY_DEBUG_PRINTF("SCardEstablishContext() called");
  1027   1044   		scard_est_context_ret = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, cackey_pcsc_handle);
  1028   1045   		if (scard_est_context_ret != SCARD_S_SUCCESS) {
  1029   1046   			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);
  1030   1047   
  1031   1048   			free(cackey_pcsc_handle);
  1032   1049   			cackey_pcsc_handle = NULL;
  1033   1050   
  1034         -			cackey_slots_disconnect_all();
         1051  +			cackey_slots_disconnect_all(0);
  1035   1052   
  1036   1053   			return(CACKEY_PCSC_E_GENERIC);
  1037   1054   		}
  1038   1055   	}
  1039   1056   
  1040   1057   #ifdef HAVE_SCARDISVALIDCONTEXT
  1041   1058   	CACKEY_DEBUG_PRINTF("SCardIsValidContext() called");
................................................................................
  1047   1064   		scard_est_context_ret = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, cackey_pcsc_handle);
  1048   1065   		if (scard_est_context_ret != SCARD_S_SUCCESS) {
  1049   1066   			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);
  1050   1067   
  1051   1068   			free(cackey_pcsc_handle);
  1052   1069   			cackey_pcsc_handle = NULL;
  1053   1070   
  1054         -			cackey_slots_disconnect_all();
         1071  +			cackey_slots_disconnect_all(0);
  1055   1072   
  1056   1073   			return(CACKEY_PCSC_E_GENERIC);
  1057   1074   		}
  1058   1075   
  1059   1076   		CACKEY_DEBUG_PRINTF("Handle has been re-established");
  1060   1077   	}
  1061   1078   #endif
................................................................................
  1097   1114   	
  1098   1115   		cackey_pcsc_handle = NULL;
  1099   1116   	}
  1100   1117   
  1101   1118   	if (scard_rel_context_ret != SCARD_S_SUCCESS) {
  1102   1119   		return(CACKEY_PCSC_E_GENERIC);
  1103   1120   	}
         1121  +
         1122  +	cackey_slots_disconnect_all(0);
  1104   1123   
  1105   1124   	return(CACKEY_PCSC_S_OK);
  1106   1125   }
  1107   1126   
  1108   1127   /*
  1109   1128    * SYNPOSIS
  1110   1129    *     void cackey_mark_slot_reset(struct cackey_slot *slot);
................................................................................
  1490   1509   	CACKEY_DEBUG_PRINTF("Called.");
  1491   1510   
  1492   1511   	if (!slot) {
  1493   1512   		CACKEY_DEBUG_PRINTF("Invalid slot specified.");
  1494   1513   
  1495   1514   		return(CACKEY_PCSC_E_GENERIC);
  1496   1515   	}
         1516  +
         1517  +	if (respcode) {
         1518  +		*respcode = 0xffff;
         1519  +	}
  1497   1520   
  1498   1521   	pcsc_connect_ret = cackey_connect_card(slot);
  1499   1522   	if (pcsc_connect_ret != CACKEY_PCSC_S_OK) {
  1500   1523   		CACKEY_DEBUG_PRINTF("Unable to connect to card, returning in failure");
  1501   1524   
  1502   1525   		return(CACKEY_PCSC_E_GENERIC);
  1503   1526   	}
................................................................................
  2138   2161   	cackey_pcsc_id_type try_types[2], try_type;
  2139   2162   	int send_ret;
  2140   2163   	int idx;
  2141   2164   
  2142   2165   	CACKEY_DEBUG_PRINTF("Reselecting the root applet");
  2143   2166   
  2144   2167   	if (type_hint == CACKEY_ID_TYPE_UNKNOWN) {
  2145         -		if (slot->cached_certs && slot->cached_certs_count > 0) {
  2146         -			type_hint = slot->cached_certs[0].id_type;
  2147         -		}
         2168  +		type_hint = slot->id_type_hint;
  2148   2169   	}
         2170  +
         2171  +	slot->id_type_hint = CACKEY_ID_TYPE_UNKNOWN;
  2149   2172   
  2150   2173   	switch (type_hint) {
  2151   2174   		case CACKEY_ID_TYPE_PIV:
  2152   2175   			CACKEY_DEBUG_PRINTF("Trying to reselect the PIV root applet first");
  2153   2176   
  2154   2177   			try_types[0] = CACKEY_ID_TYPE_PIV;
  2155   2178   			try_types[1] = CACKEY_ID_TYPE_CAC;
................................................................................
  2184   2207   
  2185   2208   		if (send_ret == CACKEY_PCSC_S_OK) {
  2186   2209   			CACKEY_DEBUG_PRINTF("Successfully selected the %s applet -- setting the \"LOGIN REQUIRED\" flag on the token",
  2187   2210   				try_type == CACKEY_ID_TYPE_CAC ? "CAC" : "PIV"
  2188   2211   			);
  2189   2212   
  2190   2213   			slot->token_flags = CKF_LOGIN_REQUIRED;
         2214  +
         2215  +			slot->id_type_hint = try_type;
  2191   2216   
  2192   2217   			return(try_type);
  2193   2218   		}
  2194   2219   	}
  2195   2220   
  2196   2221   	CACKEY_DEBUG_PRINTF("Unable to select any applet, returning in failure");
  2197   2222   
................................................................................
  3158   3183   
  3159   3184   				return(CACKEY_PCSC_E_TOKENABSENT);
  3160   3185   			}
  3161   3186   
  3162   3187   			CACKEY_DEBUG_PRINTF("Something went wrong during signing, resetting the slot and hoping for the best.");
  3163   3188   
  3164   3189   			cackey_pcsc_disconnect();
         3190  +
  3165   3191   			cackey_pcsc_connect();
         3192  +
         3193  +			cackey_detect_and_select_root_applet(slot, CACKEY_ID_TYPE_UNKNOWN);
  3166   3194   
  3167   3195   			return(CACKEY_PCSC_E_GENERIC);
  3168   3196   		}
  3169   3197   
  3170   3198   		tmpbuf += bytes_to_send;
  3171   3199   		tmpbuflen -= bytes_to_send;
  3172   3200   
................................................................................
  4583   4611   		cackey_slots[idx].pcsc_reader = NULL;
  4584   4612   		cackey_slots[idx].transaction_depth = 0;
  4585   4613   		cackey_slots[idx].transaction_need_hw_lock = 0;
  4586   4614   		cackey_slots[idx].slot_reset = 0;
  4587   4615   		cackey_slots[idx].token_flags = 0;
  4588   4616   		cackey_slots[idx].label = NULL;
  4589   4617   		cackey_slots[idx].internal = 0;
         4618  +		cackey_slots[idx].id_type_hint = CACKEY_ID_TYPE_UNKNOWN;
  4590   4619   	}
  4591   4620   
  4592   4621   #ifdef CACKEY_NO_EXTRA_CERTS
  4593   4622   	if (getenv("CACKEY_EXTRA_CERTS") != NULL) {
  4594   4623   		include_dod_certs = 1;
  4595   4624   	} else {
  4596   4625   		include_dod_certs = 0;
................................................................................
  4702   4731   
  4703   4732   	for (idx = 0; idx < (sizeof(cackey_sessions) / sizeof(cackey_sessions[0])); idx++) {
  4704   4733   		if (cackey_sessions[idx].active) {
  4705   4734   			C_CloseSession(idx);
  4706   4735   		}
  4707   4736   	}
  4708   4737   
  4709         -	cackey_slots_disconnect_all();
         4738  +	cackey_slots_disconnect_all(1);
  4710   4739   
  4711   4740   	for (idx = 0; idx < (sizeof(cackey_slots) / sizeof(cackey_slots[0])); idx++) {
  4712   4741   		if (cackey_slots[idx].internal) {
  4713   4742   			continue;
  4714   4743   		}
  4715   4744   
  4716         -		if (cackey_slots[idx].pcsc_reader) {
  4717         -			free(cackey_slots[idx].pcsc_reader);
  4718         -		}
  4719         -
  4720   4745   		if (cackey_slots[idx].cached_certs) {
  4721   4746   			cackey_free_certs(cackey_slots[idx].cached_certs, cackey_slots[idx].cached_certs_count, 1);
  4722   4747   
  4723   4748   			cackey_slots[idx].cached_certs = NULL;
  4724   4749   		}
  4725   4750   	}
  4726   4751   
................................................................................
  4851   4876   			}
  4852   4877   		}
  4853   4878   
  4854   4879   		if (slot_reset) {
  4855   4880   			CACKEY_DEBUG_PRINTF("Purging all slot information.");
  4856   4881   
  4857   4882   			/* Only update the list of slots if we are actually being supply the slot information */
  4858         -			cackey_slots_disconnect_all();
         4883  +			cackey_slots_disconnect_all(1);
  4859   4884   
  4860   4885   			for (currslot = 0; currslot < (sizeof(cackey_slots) / sizeof(cackey_slots[0])); currslot++) {
  4861   4886   				if (cackey_slots[currslot].internal) {
  4862   4887   					continue;
  4863   4888   				}
  4864   4889   
  4865         -				if (cackey_slots[currslot].pcsc_reader) {
  4866         -					free(cackey_slots[currslot].pcsc_reader);
  4867         -
  4868         -					cackey_slots[currslot].pcsc_reader = NULL;
  4869         -				}
  4870         -
  4871         -				if (cackey_slots[currslot].label) {
  4872         -					free(cackey_slots[currslot].label);
  4873         -
  4874         -					cackey_slots[currslot].label = NULL;
  4875         -				}
  4876         -
  4877   4890   				cackey_slots[currslot].active = 0;
  4878   4891   			}
  4879   4892   		}
  4880   4893   	}
  4881   4894   
  4882   4895   	/* Determine list of readers */
  4883   4896   	pcsc_connect_ret = cackey_pcsc_connect();