Check-in [f006b206b1]
Overview
Comment:Fixed memory leaks

Updated to only rescan for identities if a slot reset has been detected

Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:f006b206b1065aedfb1de964c59c435123539363
User & Date: rkeene on 2010-05-14 23:11:47
Other Links: manifest | tags
Context
2010-05-14
23:33
Added untested support for Sign/Decrypt check-in: fc063dd0df user: rkeene tags: trunk
23:11
Fixed memory leaks

Updated to only rescan for identities if a slot reset has been detected check-in: f006b206b1 user: rkeene tags: trunk

22:10
Wrote function for freeing identities

Wrote function for determining label from identity

Consolidated freeing of identities to use new function

Consolidated label lookups to use new function

Fixed bug with releasing identities, but not reducing the number of identities check-in: 1b3d82054b user: rkeene tags: trunk

Changes

Modified cackey.c from [97ac9efbb9] to [ab26d90d17].

492
493
494
495
496
497
498


499
500
501
502
503
504
505
...
621
622
623
624
625
626
627






628
629
630
631
632
633
634
...
698
699
700
701
702
703
704





































705
706
707
708
709
710
711
...
976
977
978
979
980
981
982

983
984

985
986
987
988
989
990
991
....
1593
1594
1595
1596
1597
1598
1599
1600
1601

1602
1603
1604
1605
1606
1607
1608
....
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
....
2380
2381
2382
2383
2384
2385
2386

2387
2388
2389
2390
2391
2392
2393
....
2431
2432
2433
2434
2435
2436
2437


2438
2439
2440
2441
2442
2443
2444
....
2569
2570
2571
2572
2573
2574
2575

2576
2577
2578
2579
2580
2581
2582
....
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
....
3616
3617
3618
3619
3620
3621
3622



3623
3624
3625
3626
3627
3628



3629
3630
3631
3632
3633
3634
3635

	char *pcsc_reader;

	int pcsc_card_connected;
	SCARDHANDLE pcsc_card;

	int transaction_depth;


};

typedef enum {
	CACKEY_TLV_APP_GENERIC = 0x01,
	CACKEY_TLV_APP_SKI     = 0x02,
	CACKEY_TLV_APP_PKI     = 0x04
} cackey_tlv_apptype;
................................................................................
			CACKEY_DEBUG_PRINTF("SCardDisconnect(%lu) called", (unsigned long) idx);

			SCardDisconnect(cackey_slots[idx].pcsc_card, SCARD_LEAVE_CARD);
		}

		cackey_slots[idx].pcsc_card_connected = 0;
		cackey_slots[idx].transaction_depth = 0;






	}

	CACKEY_DEBUG_PRINTF("Returning");

	return;
}

................................................................................
		}

		CACKEY_DEBUG_PRINTF("Handle has been re-established");
	}
#endif

	CACKEY_DEBUG_PRINTF("Sucessfully connected to PC/SC, returning in success");






































	return(CACKEY_PCSC_S_OK);
}

/*
 * SYNPOSIS
 *     cackey_ret cackey_connect_card(struct cackey_slot *slot);
................................................................................

	CACKEY_DEBUG_PRINTBUF("Sending APDU:", xmit_buf, xmit_len);

	recv_len = sizeof(recv_buf);
	scard_xmit_ret = SCardTransmit(slot->pcsc_card, SCARD_PCI_T0, xmit_buf, xmit_len, SCARD_PCI_T1, recv_buf, &recv_len);
	if (scard_xmit_ret != SCARD_S_SUCCESS) {
		CACKEY_DEBUG_PRINTF("Failed to send APDU to card (SCardTransmit() = %s/%lx)", CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(scard_xmit_ret), (unsigned long) scard_xmit_ret);


		slot->transaction_depth = 0;


		if (scard_xmit_ret == SCARD_W_RESET_CARD) {
			CACKEY_DEBUG_PRINTF("Reset required, please hold...");

			scard_reconn_ret = SCardReconnect(slot->pcsc_card, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, SCARD_RESET_CARD, &protocol);
			if (scard_reconn_ret == SCARD_S_SUCCESS) {
				/* Re-establish transaction, if it was present */
................................................................................

	if (count == NULL) {
		CACKEY_DEBUG_PRINTF("count is NULL, returning in failure");

		return(NULL);
	}

	if (*count == 0) {
		if (certs != NULL) {

			CACKEY_DEBUG_PRINTF("Requested we return 0 objects, short-circuit");

			return(certs);
		}
	}

	/* Begin a SmartCard transaction */
................................................................................
	return(0);
}

static void cackey_free_identities(struct cackey_identity *identities, unsigned long identities_count) {
	CK_ATTRIBUTE *curr_attr;
	unsigned long id_idx, attr_idx;

	if (identities || identities_count == 0) {
		return;
	}

	for (id_idx = 0; id_idx < identities_count; id_idx++) {
		if (identities[id_idx].attributes) {
			for (attr_idx = 0; attr_idx < identities[id_idx].attributes_count; attr_idx++) {
				curr_attr = &identities[id_idx].attributes[attr_idx];
................................................................................
		cackey_sessions[idx].active = 0;
	}

	for (idx = 0; idx < (sizeof(cackey_slots) / sizeof(cackey_slots[0])); idx++) {
		cackey_slots[idx].active = 0;
		cackey_slots[idx].pcsc_reader = NULL;
		cackey_slots[idx].transaction_depth = 0;

	}

	cackey_initialized = 1;

	if (!cackey_biglock_init) {
		mutex_init_ret = cackey_mutex_create(&cackey_biglock);

................................................................................
	cackey_slots_disconnect_all();

	for (idx = 0; idx < (sizeof(cackey_slots) / sizeof(cackey_slots[0])); idx++) {
		if (cackey_slots[idx].pcsc_reader) {
			free(cackey_slots[idx].pcsc_reader);
		}
	}



	cackey_initialized = 0;

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

	return(CKR_OK);
}
................................................................................

					/* Only update the list of slots if we are actually being supply the slot information */
					if (pSlotList) {
						cackey_slots[currslot].active = 1;
						cackey_slots[currslot].pcsc_reader = strdup(pcsc_readers);
						cackey_slots[currslot].pcsc_card_connected = 0;
						cackey_slots[currslot].transaction_depth = 0;

					}
					currslot++;

					pcsc_readers += curr_reader_len + 1;
				}

				if (currslot > 0) {
................................................................................

	for (currslot = 0; currslot < slot_count; currslot++) {
		pSlotList[currslot] = currslot;
	}

	*pulCount = slot_count;

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

	return(CKR_OK);

	tokenPresent = tokenPresent; /* Supress unused variable warning */
}

CK_DEFINE_FUNCTION(CK_RV, C_GetSlotInfo)(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) {
................................................................................
		cackey_mutex_unlock(cackey_biglock);

		CACKEY_DEBUG_PRINTF("Error.  Search already active.");
		
		return(CKR_OPERATION_ACTIVE);
	}




	if (cackey_sessions[hSession].identities != NULL) {
		cackey_free_identities(cackey_sessions[hSession].identities, cackey_sessions[hSession].identities_count);

		cackey_sessions[hSession].identities = NULL;
		cackey_sessions[hSession].identities_count = 0;
	}




	if (cackey_sessions[hSession].identities == NULL) {
		pcsc_identities = cackey_read_certs(&cackey_slots[cackey_sessions[hSession].slotID], NULL, &num_certs);
		if (pcsc_identities != NULL) {
			/* Convert number of Certs to number of objects */
			num_ids = (CKO_PRIVATE_KEY - CKO_CERTIFICATE + 1) * num_certs;








>
>







 







>
>
>
>
>
>







 







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







 







>


>







 







<
|
>







 







|







 







>







 







>
>







 







>







 







|







 







>
>
>






>
>
>







492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
...
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
...
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
....
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
....
1640
1641
1642
1643
1644
1645
1646

1647
1648
1649
1650
1651
1652
1653
1654
1655
....
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
....
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
....
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
....
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
....
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
....
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692

	char *pcsc_reader;

	int pcsc_card_connected;
	SCARDHANDLE pcsc_card;

	int transaction_depth;

	int slot_reset;
};

typedef enum {
	CACKEY_TLV_APP_GENERIC = 0x01,
	CACKEY_TLV_APP_SKI     = 0x02,
	CACKEY_TLV_APP_PKI     = 0x04
} cackey_tlv_apptype;
................................................................................
			CACKEY_DEBUG_PRINTF("SCardDisconnect(%lu) called", (unsigned long) idx);

			SCardDisconnect(cackey_slots[idx].pcsc_card, SCARD_LEAVE_CARD);
		}

		cackey_slots[idx].pcsc_card_connected = 0;
		cackey_slots[idx].transaction_depth = 0;

		if (cackey_slots[idx].active) {
			CACKEY_DEBUG_PRINTF("Marking active slot %lu as being reset", (unsigned long) idx);
		}

		cackey_slots[idx].slot_reset = 1;
	}

	CACKEY_DEBUG_PRINTF("Returning");

	return;
}

................................................................................
		}

		CACKEY_DEBUG_PRINTF("Handle has been re-established");
	}
#endif

	CACKEY_DEBUG_PRINTF("Sucessfully connected to PC/SC, returning in success");

	return(CACKEY_PCSC_S_OK);
}

/*
 * SYNPOSIS
 *     cackey_ret cackey_pcsc_disconnect(void);
 *
 * ARGUMENTS
 *     None
 *
 * RETURN VALUE
 *     CACKEY_PCSC_S_OK         On success
 *     CACKEY_PCSC_E_GENERIC    On error
 *
 * NOTES
 *     This function disconnects from the PC/SC Connection manager and updates
 *     the global handle.
 *
 */
static cackey_ret cackey_pcsc_disconnect(void) {
	LONG scard_rel_context_ret;

	CACKEY_DEBUG_PRINTF("Called.");

	if (cackey_pcsc_handle == NULL) {
		return(CACKEY_PCSC_S_OK);
	}

	scard_rel_context_ret = SCardReleaseContext(*cackey_pcsc_handle);

	free(cackey_pcsc_handle);
	cackey_pcsc_handle = NULL;

	if (scard_rel_context_ret != SCARD_S_SUCCESS) {
		return(CACKEY_PCSC_E_GENERIC);
	}

	return(CACKEY_PCSC_S_OK);
}

/*
 * SYNPOSIS
 *     cackey_ret cackey_connect_card(struct cackey_slot *slot);
................................................................................

	CACKEY_DEBUG_PRINTBUF("Sending APDU:", xmit_buf, xmit_len);

	recv_len = sizeof(recv_buf);
	scard_xmit_ret = SCardTransmit(slot->pcsc_card, SCARD_PCI_T0, xmit_buf, xmit_len, SCARD_PCI_T1, recv_buf, &recv_len);
	if (scard_xmit_ret != SCARD_S_SUCCESS) {
		CACKEY_DEBUG_PRINTF("Failed to send APDU to card (SCardTransmit() = %s/%lx)", CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(scard_xmit_ret), (unsigned long) scard_xmit_ret);
		CACKEY_DEBUG_PRINTF("Marking slot as having been reset");

		slot->transaction_depth = 0;
		slot->slot_reset = 1;

		if (scard_xmit_ret == SCARD_W_RESET_CARD) {
			CACKEY_DEBUG_PRINTF("Reset required, please hold...");

			scard_reconn_ret = SCardReconnect(slot->pcsc_card, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, SCARD_RESET_CARD, &protocol);
			if (scard_reconn_ret == SCARD_S_SUCCESS) {
				/* Re-establish transaction, if it was present */
................................................................................

	if (count == NULL) {
		CACKEY_DEBUG_PRINTF("count is NULL, returning in failure");

		return(NULL);
	}


	if (certs != NULL) {
		if (*count == 0) {
			CACKEY_DEBUG_PRINTF("Requested we return 0 objects, short-circuit");

			return(certs);
		}
	}

	/* Begin a SmartCard transaction */
................................................................................
	return(0);
}

static void cackey_free_identities(struct cackey_identity *identities, unsigned long identities_count) {
	CK_ATTRIBUTE *curr_attr;
	unsigned long id_idx, attr_idx;

	if (identities == NULL || identities_count == 0) {
		return;
	}

	for (id_idx = 0; id_idx < identities_count; id_idx++) {
		if (identities[id_idx].attributes) {
			for (attr_idx = 0; attr_idx < identities[id_idx].attributes_count; attr_idx++) {
				curr_attr = &identities[id_idx].attributes[attr_idx];
................................................................................
		cackey_sessions[idx].active = 0;
	}

	for (idx = 0; idx < (sizeof(cackey_slots) / sizeof(cackey_slots[0])); idx++) {
		cackey_slots[idx].active = 0;
		cackey_slots[idx].pcsc_reader = NULL;
		cackey_slots[idx].transaction_depth = 0;
		cackey_slots[idx].slot_reset = 0;
	}

	cackey_initialized = 1;

	if (!cackey_biglock_init) {
		mutex_init_ret = cackey_mutex_create(&cackey_biglock);

................................................................................
	cackey_slots_disconnect_all();

	for (idx = 0; idx < (sizeof(cackey_slots) / sizeof(cackey_slots[0])); idx++) {
		if (cackey_slots[idx].pcsc_reader) {
			free(cackey_slots[idx].pcsc_reader);
		}
	}

	cackey_pcsc_disconnect();

	cackey_initialized = 0;

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

	return(CKR_OK);
}
................................................................................

					/* Only update the list of slots if we are actually being supply the slot information */
					if (pSlotList) {
						cackey_slots[currslot].active = 1;
						cackey_slots[currslot].pcsc_reader = strdup(pcsc_readers);
						cackey_slots[currslot].pcsc_card_connected = 0;
						cackey_slots[currslot].transaction_depth = 0;
						cackey_slots[currslot].slot_reset = 1;
					}
					currslot++;

					pcsc_readers += curr_reader_len + 1;
				}

				if (currslot > 0) {
................................................................................

	for (currslot = 0; currslot < slot_count; currslot++) {
		pSlotList[currslot] = currslot;
	}

	*pulCount = slot_count;

	CACKEY_DEBUG_PRINTF("Returning CKR_OK (%i).  Found %lu readers.", CKR_OK, (unsigned long) slot_count);

	return(CKR_OK);

	tokenPresent = tokenPresent; /* Supress unused variable warning */
}

CK_DEFINE_FUNCTION(CK_RV, C_GetSlotInfo)(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) {
................................................................................
		cackey_mutex_unlock(cackey_biglock);

		CACKEY_DEBUG_PRINTF("Error.  Search already active.");
		
		return(CKR_OPERATION_ACTIVE);
	}

	if (cackey_slots[cackey_sessions[hSession].slotID].slot_reset) {
		CACKEY_DEBUG_PRINTF("The slot has been reset since we last looked for identities -- rescanning");

		if (cackey_sessions[hSession].identities != NULL) {
			cackey_free_identities(cackey_sessions[hSession].identities, cackey_sessions[hSession].identities_count);

			cackey_sessions[hSession].identities = NULL;
			cackey_sessions[hSession].identities_count = 0;
		}

		cackey_slots[cackey_sessions[hSession].slotID].slot_reset = 0;
	}

	if (cackey_sessions[hSession].identities == NULL) {
		pcsc_identities = cackey_read_certs(&cackey_slots[cackey_sessions[hSession].slotID], NULL, &num_certs);
		if (pcsc_identities != NULL) {
			/* Convert number of Certs to number of objects */
			num_ids = (CKO_PRIVATE_KEY - CKO_CERTIFICATE + 1) * num_certs;