Check-in [fdd66a54cd]
Overview
Comment:Simplified some slot disconnect logic and updated to store an ID type hint on the slot itself so that if we reinitialize we treat it as the same type of device
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:fdd66a54cd37656c39bdcdb06e698840f89d4a02
User & Date: rkeene on 2016-02-16 23:24:33
Other Links: manifest | tags
Context
2016-02-19
13:30
ChromeOS: Added package icon check-in: e1dc965e9b user: rkeene tags: trunk
2016-02-16
23:24
Simplified some slot disconnect logic and updated to store an ID type hint on the slot itself so that if we reinitialize we treat it as the same type of device check-in: fdd66a54cd user: rkeene tags: trunk
17:04
Added workaround for Google's PCSC where we cannot determine the amount of space required to hold the reader list automatically check-in: 6218cc54fc user: rkeene tags: trunk
Changes

Modified cackey.c from [ebe379d38c] to [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();