Check-in [cca6a7fec4]
Overview
Comment:Merged in "dodcerts-on-seperate-slot" branch
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:cca6a7fec4ae194f2ccf66057ae9097e93405f96
User & Date: rkeene on 2012-07-25 02:31:15
Other Links: manifest | tags
Context
2012-07-25
02:33
CACKey 0.6.7 check-in: 11563df531 user: rkeene tags: trunk, 0.6.7
02:31
Merged in "dodcerts-on-seperate-slot" branch check-in: cca6a7fec4 user: rkeene tags: trunk
02:30
Merged from trunk Closed-Leaf check-in: 62f39ca124 user: rkeene tags: dodcerts-on-seperate-slot
2012-07-24
22:24
Updated Mac OS X build script to support building a Snow Leopard to Mountain Lion-compatible package. check-in: 07c7888bc0 user: kvanals tags: trunk
Changes

Modified build/cackey_osx_build/build_osx.sh from [3980f85216] to [04fe9e319d].

134
135
136
137
138
139
140




















141
142
143
144
145
146
147
...
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
	CUROSXVER=10.6
	for HOST in i386-apple-darwin10 x86_64-apple-darwin10; do
		genbuild
	done
	libbuild
	pkgbuild
}





















# Generic build function
genbuild() {
	make distclean
	ARCH=`echo ${HOST} | cut -d "-" -f 1`
	if [ ${ARCH} == "powerpc" ]; then
		if [ ${OSX} == "Leopard" ]; then
................................................................................
			ARCH="ppc -mcpu=G4"
		else
			ARCH="ppc -mcpu=G3"
		fi
	fi
	if [ "${LIONBUILD}" = 1 ]; then
		if [ "${ARCH}" == "ppc -mcpu=G4" ]; then
			CC=powerpc-apple-darwin11-gcc-4.2.1 CPP=powerpc-apple-darwin11-cpp-4.2.1 CFLAGS="-m32 -I/Developer/Platforms/iPhoneOS.platform/Developer/usr/lib/gcc/powerpc-apple-darwin10/4.2.1/include -isysroot /Developer/SDKs/MacOSX10.5.sdk" CPPFLAGS="-D_LIBC_LIMITS_H_" ./configure --with-pcsc-headers=${HEADERS} --with-pcsc-libs=${LIBRARY} --host=${HOST}
		else
			CFLAGS="-arch ${ARCH}" ./configure --with-pcsc-headers=${HEADERS} --with-pcsc-libs=${LIBRARY} --host=${HOST}
		fi
	else
		CFLAGS="-arch ${ARCH}" ./configure --with-pcsc-headers=${HEADERS} --with-pcsc-libs=${LIBRARY} --host=${HOST}
	fi
	make
	cp libcackey.dylib macbuild/${OSX}/libcackey.dylib.`echo ${ARCH} | cut -d ' ' -f 1`
	cp libcackey_g.dylib macbuild/${OSX}/libcackey_g.dylib.`echo ${ARCH} | cut -d ' ' -f 1` 
}

# Library build function







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







 







|

|


|







134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
...
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
	CUROSXVER=10.6
	for HOST in i386-apple-darwin10 x86_64-apple-darwin10; do
		genbuild
	done
	libbuild
	pkgbuild
}

# Build function for Snow Leopard/Lion/Mountain Lion
sltoml() {
	makedir
	HEADERS=/Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/PCSC.framework/Versions/A/Headers/
	LIBRARY=/Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/PCSC.framework/PCSC
	LIB=""
	ARCHLIST=""
	DLIB=""
	DARCHLIST=""
	OSX=Sltoml
	PKTARGETOS=3
	NEXTOSXVER=10.9
	CUROSXVER=10.6
	for HOST in i386-apple-darwin10 x86_64-apple-darwin10; do
		genbuild
	done
	libbuild
	pkgbuild
}

# Generic build function
genbuild() {
	make distclean
	ARCH=`echo ${HOST} | cut -d "-" -f 1`
	if [ ${ARCH} == "powerpc" ]; then
		if [ ${OSX} == "Leopard" ]; then
................................................................................
			ARCH="ppc -mcpu=G4"
		else
			ARCH="ppc -mcpu=G3"
		fi
	fi
	if [ "${LIONBUILD}" = 1 ]; then
		if [ "${ARCH}" == "ppc -mcpu=G4" ]; then
			CC=powerpc-apple-darwin11-gcc-4.2.1 CPP=powerpc-apple-darwin11-cpp-4.2.1 CFLAGS="-m32 -I/Developer/Platforms/iPhoneOS.platform/Developer/usr/lib/gcc/powerpc-apple-darwin10/4.2.1/include -isysroot /Developer/SDKs/MacOSX10.5.sdk" CPPFLAGS="-D_LIBC_LIMITS_H_" ./configure --with-pcsc-headers=${HEADERS} --with-pcsc-libs=${LIBRARY} --host=${HOST} --enable-dod-certs-on-hw-slots
		else
			CFLAGS="-arch ${ARCH}" ./configure --with-pcsc-headers=${HEADERS} --with-pcsc-libs=${LIBRARY} --host=${HOST} --enable-dod-certs-on-hw-slots
		fi
	else
		CFLAGS="-arch ${ARCH}" ./configure --with-pcsc-headers=${HEADERS} --with-pcsc-libs=${LIBRARY} --host=${HOST} --enable-dod-certs-on-hw-slots
	fi
	make
	cp libcackey.dylib macbuild/${OSX}/libcackey.dylib.`echo ${ARCH} | cut -d ' ' -f 1`
	cp libcackey_g.dylib macbuild/${OSX}/libcackey_g.dylib.`echo ${ARCH} | cut -d ' ' -f 1` 
}

# Library build function

Modified cackey.c from [1be2f8a22e] to [0661f619de].

709
710
711
712
713
714
715

716
717
718
719
720
721
722
...
853
854
855
856
857
858
859





860
861
862
863
864
865
866
....
2602
2603
2604
2605
2606
2607
2608






2609
2610
2611
2612
2613
2614
2615
....
3396
3397
3398
3399
3400
3401
3402




















3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415




3416

3417


3418


3419





3420
3421
3422








3423
3424

3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436


3437

3438
3439
3440
3441
3442
3443
3444
....
3449
3450
3451
3452
3453
3454
3455






3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476

3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
....
3519
3520
3521
3522
3523
3524
3525















3526
3527
3528
3529
3530
3531
3532
....
3566
3567
3568
3569
3570
3571
3572




3573
3574
3575
3576
3577
3578
3579
....
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
....
3658
3659
3660
3661
3662
3663
3664




3665
3666
3667
3668
3669
3670
3671
....
3706
3707
3708
3709
3710
3711
3712

3713







3714
3715
3716
3717
3718
3719
3720
....
3728
3729
3730
3731
3732
3733
3734

3735
3736
3737
3738
3739
3740
3741
3742
3743



3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
....
3779
3780
3781
3782
3783
3784
3785


3786
3787
3788
3789
3790
3791


















3792








3793
3794
3795
3796
3797
3798
3799
....
3837
3838
3839
3840
3841
3842
3843



3844

3845
3846
3847
3848
3849
3850
3851
	CK_VOID_PTR decrypt_mech_parm;
	CK_ULONG decrypt_mech_parmlen;
	struct cackey_identity *decrypt_identity;
};

struct cackey_slot {
	int active;


	char *pcsc_reader;

	int pcsc_card_connected;
	SCARDHANDLE pcsc_card;

	int transaction_depth;
................................................................................
 */
static void cackey_slots_disconnect_all(void) {
	uint32_t idx;

	CACKEY_DEBUG_PRINTF("Called.");

	for (idx = 0; idx < (sizeof(cackey_slots) / sizeof(cackey_slots[0])); idx++) {





		if (cackey_slots[idx].pcsc_card_connected) {
			CACKEY_DEBUG_PRINTF("SCardDisconnect(%lu) called", (unsigned long) idx);

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

		if (cackey_slots[idx].label) {
................................................................................
static cackey_ret cackey_token_present(struct cackey_slot *slot) {
	cackey_ret pcsc_connect_ret;
	DWORD reader_len, state, protocol, atr_len;
	BYTE atr[MAX_ATR_SIZE];
	LONG status_ret, scard_reconn_ret;

	CACKEY_DEBUG_PRINTF("Called.");







	pcsc_connect_ret = cackey_connect_card(slot);
	if (pcsc_connect_ret != CACKEY_PCSC_S_OK) {
		CACKEY_DEBUG_PRINTF("Unable to connect to card, returning token absent");

		return(CACKEY_PCSC_E_TOKENABSENT);
	}
................................................................................

			cackey_free_certs(identities[id_idx].pcsc_identity, 1, 1);
		}
	}

	free(identities);
}





















static struct cackey_identity *cackey_read_identities(struct cackey_slot *slot, unsigned long *ids_found) {
	struct cackey_pcsc_identity *pcsc_identities;
	struct cackey_identity *identities;
	unsigned long num_ids, id_idx, curr_id_type;
	unsigned long num_certs, num_extra_certs, cert_idx;
	int include_extra_certs = 1;

	CACKEY_DEBUG_PRINTF("Called.");

	if (getenv("CACKEY_NO_EXTRA_CERTS") != NULL) {
		CACKEY_DEBUG_PRINTF("Asked not to include extra (DoD) certificates");





		include_extra_certs = 0;

	}





	if (include_extra_certs) {





		num_extra_certs = sizeof(extra_certs) / sizeof(extra_certs[0]);

		CACKEY_DEBUG_PRINTF("Including %li DoD Certificates as objects on this token", num_extra_certs);








	} else {
		num_extra_certs = 0;

	}

	if (ids_found == NULL) {
		CACKEY_DEBUG_PRINTF("Error.  ids_found is NULL");

		return(NULL);
	}

	pcsc_identities = cackey_read_certs(slot, 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;


		num_ids += num_extra_certs * 3;


		identities = malloc(num_ids * sizeof(*identities));

		/* Add certificates, public keys, and private keys from the smartcard */
		id_idx = 0;
		for (cert_idx = 0; cert_idx < num_certs; cert_idx++) {
			for (curr_id_type = CKO_CERTIFICATE; curr_id_type <= CKO_PRIVATE_KEY; curr_id_type++) {
................................................................................

				identities[id_idx].pcsc_identity->certificate = malloc(pcsc_identities[cert_idx].certificate_len);
				memcpy(identities[id_idx].pcsc_identity->certificate, pcsc_identities[cert_idx].certificate, pcsc_identities[cert_idx].certificate_len);

				id_idx++;
			}
		}







		cackey_free_certs(pcsc_identities, num_certs, 1);

		/* Add DoD Certificates and Netscape Trust Objects */
		for (cert_idx = 0; cert_idx < num_extra_certs; cert_idx++) {
			identities[id_idx].pcsc_identity = NULL;
			identities[id_idx].attributes = cackey_get_attributes(CKO_CERTIFICATE, &extra_certs[cert_idx], 0xf000 | cert_idx, &identities[id_idx].attributes_count);
			id_idx++;

			identities[id_idx].pcsc_identity = NULL;
			identities[id_idx].attributes = cackey_get_attributes(CKO_PUBLIC_KEY, &extra_certs[cert_idx], 0xf000 | cert_idx, &identities[id_idx].attributes_count);
			id_idx++;

			identities[id_idx].pcsc_identity = NULL;
			identities[id_idx].attributes = cackey_get_attributes(CKO_NETSCAPE_TRUST, &extra_certs[cert_idx], 0xf000 | cert_idx, &identities[id_idx].attributes_count);
			id_idx++;
		}

		*ids_found = num_ids;
		return(identities);
	}


	*ids_found = 0;
	return(NULL);
}

CK_DEFINE_FUNCTION(CK_RV, C_Initialize)(CK_VOID_PTR pInitArgs) {
	CK_C_INITIALIZE_ARGS CK_PTR args;
	uint32_t idx;
	int mutex_init_ret;

	CACKEY_DEBUG_PRINTF("Called.");

	if (cackey_initialized) {
		CACKEY_DEBUG_PRINTF("Error.  Already initialized.");

................................................................................
		cackey_slots[idx].active = 0;
		cackey_slots[idx].pcsc_reader = NULL;
		cackey_slots[idx].transaction_depth = 0;
		cackey_slots[idx].transaction_need_hw_lock = 0;
		cackey_slots[idx].slot_reset = 0;
		cackey_slots[idx].token_flags = 0;
		cackey_slots[idx].label = NULL;















	}

	cackey_initialized = 1;

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

................................................................................
			C_CloseSession(idx);
		}
	}

	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();

................................................................................

/*
 * Process list of readers, and create mapping between reader name and slot ID
 */
CK_DEFINE_FUNCTION(CK_RV, C_GetSlotList)(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount) {
	int mutex_retval;
	int pcsc_connect_ret;
	CK_ULONG count, slot_count = 0, currslot;
	char *pcsc_readers, *pcsc_readers_s, *pcsc_readers_e;
	DWORD pcsc_readers_len;
	LONG scard_listreaders_ret;
	size_t curr_reader_len;

	CACKEY_DEBUG_PRINTF("Called.");

................................................................................
	if (pSlotList) {
		CACKEY_DEBUG_PRINTF("Purging all slot information.");

		/* Only update the list of slots if we are actually being supply the slot information */
		cackey_slots_disconnect_all();

		for (currslot = 0; currslot < (sizeof(cackey_slots) / sizeof(cackey_slots[0])); currslot++) {




			if (cackey_slots[currslot].pcsc_reader) {
				free(cackey_slots[currslot].pcsc_reader);

				cackey_slots[currslot].pcsc_reader = NULL;
			}

			if (cackey_slots[currslot].label) {
................................................................................
			scard_listreaders_ret = SCardListReaders(*cackey_pcsc_handle, NULL, pcsc_readers, &pcsc_readers_len);
			if (scard_listreaders_ret == SCARD_S_SUCCESS) {
				pcsc_readers_e = pcsc_readers + pcsc_readers_len;

				/* Start with Slot ID 1, to avoid a bug in GDM on RHEL */
				/* Bug 594911: https://bugzilla.redhat.com/show_bug.cgi?id=594911 */
				currslot = 1;

				while (pcsc_readers < pcsc_readers_e) {







					curr_reader_len = strlen(pcsc_readers);

					if ((pcsc_readers + curr_reader_len) > pcsc_readers_e) {
						break;
					}

					if (curr_reader_len == 0) {
................................................................................
					}

					CACKEY_DEBUG_PRINTF("Found reader: %s", pcsc_readers);

					/* Only update the list of slots if we are actually being asked 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].transaction_need_hw_lock = 0;
						cackey_slots[currslot].slot_reset = 1;
						cackey_slots[currslot].token_flags = CKF_LOGIN_REQUIRED;
						cackey_slots[currslot].label = NULL;

						cackey_mark_slot_reset(&cackey_slots[currslot]);



					}
					currslot++;

					pcsc_readers += curr_reader_len + 1;
				}

				/* Start with Slot ID 1, to avoid a bug in GDM on RHEL */
				/* Bug 594911: https://bugzilla.redhat.com/show_bug.cgi?id=594911 */
				if (currslot > 1) {
					/* Start with Slot ID 1, to avoid a bug in GDM on RHEL */
					/* Bug 594911: https://bugzilla.redhat.com/show_bug.cgi?id=594911 */
					slot_count = currslot - 1;
				}
			} else {
				CACKEY_DEBUG_PRINTF("Second call to SCardListReaders failed, return %s/%li", CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(scard_listreaders_ret), (long) scard_listreaders_ret);
			}

			free(pcsc_readers_s);
		} else {
................................................................................
		return(CKR_OK);
	}

	count = *pulCount;
	if (count < slot_count) {
		CACKEY_DEBUG_PRINTF("Error. User allocated %lu entries, but we have %lu entries.", count, slot_count);



		return(CKR_BUFFER_TOO_SMALL);	
	}

	for (currslot = 0; currslot < slot_count; currslot++) {
		/* Start with Slot ID 1, to avoid a bug in GDM on RHEL */
		/* Bug 594911: https://bugzilla.redhat.com/show_bug.cgi?id=594911 */


















		pSlotList[currslot] = currslot + 1;








	}

	*pulCount = slot_count;

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

	return(CKR_OK);
................................................................................
		CACKEY_DEBUG_PRINTF("Error. Invalid slot requested (%lu), slot not currently active", slotID);

		cackey_mutex_unlock(cackey_biglock);

		return(CKR_SLOT_ID_INVALID);
	}




	pInfo->flags = CKF_REMOVABLE_DEVICE | CKF_HW_SLOT;


	if (cackey_token_present(&cackey_slots[slotID]) == CACKEY_PCSC_S_TOKENPRESENT) {
		pInfo->flags |= CKF_TOKEN_PRESENT;
	}

	bytes_to_copy = strlen(cackey_slots[slotID].pcsc_reader);
	if (sizeof(pInfo->manufacturerID) < bytes_to_copy) {







>







 







>
>
>
>
>







 







>
>
>
>
>
>







 







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





|
|



|
|

>
>
>
>
|
>
|
>
>
|
>
>
|
>
>
>
>
>
|
|
<
>
>
>
>
>
>
>
>
|
<
>
|

|
<

|






>
>
|
>







 







>
>
>
>
>
>



|
<
<
<
<

<
<
<
<
<
<
<
<
<
<


>







|







 







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







 







>
>
>
>







 







|







 







>
>
>
>







 







>

>
>
>
>
>
>
>







 







>









>
>
>






|
|
|
|
|
|







 







>
>



<
<
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>







 







>
>
>
|
>







709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
...
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
....
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
....
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467

3468
3469
3470
3471
3472
3473
3474
3475
3476

3477
3478
3479
3480

3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
....
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520




3521










3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
....
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
....
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
....
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
....
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
....
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
....
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
....
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873


3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
....
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
	CK_VOID_PTR decrypt_mech_parm;
	CK_ULONG decrypt_mech_parmlen;
	struct cackey_identity *decrypt_identity;
};

struct cackey_slot {
	int active;
	int internal;

	char *pcsc_reader;

	int pcsc_card_connected;
	SCARDHANDLE pcsc_card;

	int transaction_depth;
................................................................................
 */
static void cackey_slots_disconnect_all(void) {
	uint32_t idx;

	CACKEY_DEBUG_PRINTF("Called.");

	for (idx = 0; idx < (sizeof(cackey_slots) / sizeof(cackey_slots[0])); idx++) {
		if (cackey_slots[idx].internal) {
			/* Skip internal slots */
			continue;
		}

		if (cackey_slots[idx].pcsc_card_connected) {
			CACKEY_DEBUG_PRINTF("SCardDisconnect(%lu) called", (unsigned long) idx);

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

		if (cackey_slots[idx].label) {
................................................................................
static cackey_ret cackey_token_present(struct cackey_slot *slot) {
	cackey_ret pcsc_connect_ret;
	DWORD reader_len, state, protocol, atr_len;
	BYTE atr[MAX_ATR_SIZE];
	LONG status_ret, scard_reconn_ret;

	CACKEY_DEBUG_PRINTF("Called.");

	if (slot->internal) {
		CACKEY_DEBUG_PRINTF("Returning token present (internal token)");

		return(CACKEY_PCSC_S_TOKENPRESENT);
	}

	pcsc_connect_ret = cackey_connect_card(slot);
	if (pcsc_connect_ret != CACKEY_PCSC_S_OK) {
		CACKEY_DEBUG_PRINTF("Unable to connect to card, returning token absent");

		return(CACKEY_PCSC_E_TOKENABSENT);
	}
................................................................................

			cackey_free_certs(identities[id_idx].pcsc_identity, 1, 1);
		}
	}

	free(identities);
}

static unsigned long cackey_read_dod_identities(struct cackey_identity *identities, unsigned long id_idx, unsigned long num_dod_certs) {
	unsigned long cert_idx;

	for (cert_idx = 0; cert_idx < num_dod_certs; cert_idx++) {
		identities[id_idx].pcsc_identity = NULL;
		identities[id_idx].attributes = cackey_get_attributes(CKO_CERTIFICATE, &extra_certs[cert_idx], 0xf000 | cert_idx, &identities[id_idx].attributes_count);
		id_idx++;

		identities[id_idx].pcsc_identity = NULL;
		identities[id_idx].attributes = cackey_get_attributes(CKO_PUBLIC_KEY, &extra_certs[cert_idx], 0xf000 | cert_idx, &identities[id_idx].attributes_count);
		id_idx++;

		identities[id_idx].pcsc_identity = NULL;
		identities[id_idx].attributes = cackey_get_attributes(CKO_NETSCAPE_TRUST, &extra_certs[cert_idx], 0xf000 | cert_idx, &identities[id_idx].attributes_count);
		id_idx++;
	}

	return(id_idx);
}

static struct cackey_identity *cackey_read_identities(struct cackey_slot *slot, unsigned long *ids_found) {
	struct cackey_pcsc_identity *pcsc_identities;
	struct cackey_identity *identities;
	unsigned long num_ids, id_idx, curr_id_type;
	unsigned long num_certs, num_dod_certs, cert_idx;
	int include_extra_certs = 0;

	CACKEY_DEBUG_PRINTF("Called.");

	if (ids_found == NULL) {
		CACKEY_DEBUG_PRINTF("Error.  ids_found is NULL");

		return(NULL);
	}

#ifdef CACKEY_CARD_SLOT_INCLUDE_EXTRA_CERTS
	include_extra_certs = 1;
#endif

	if (getenv("CACKEY_DOD_CERTS_ON_HW_SLOTS") != NULL) {
		include_extra_certs = 1;
	}

	if (getenv("CACKEY_NO_DOD_CERTS_ON_HW_SLOTS") != NULL) {
		include_extra_certs = 0;
	}

	if (getenv("CACKEY_NO_EXTRA_CERTS") != NULL) {
		num_dod_certs = 0;
	} else {
		num_dod_certs = sizeof(extra_certs) / sizeof(extra_certs[0]);
	}


	if (slot->internal) {
		num_ids = num_dod_certs;

		if (num_ids != 0) {
			identities = malloc(num_ids * sizeof(*identities));

			cackey_read_dod_identities(identities, 0, num_dod_certs);
		} else {

			identities = NULL;
		}

		*ids_found = num_ids;


		return(identities);
	}

	pcsc_identities = cackey_read_certs(slot, 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;

		if (include_extra_certs) {
			num_ids += num_dod_certs;
		}

		identities = malloc(num_ids * sizeof(*identities));

		/* Add certificates, public keys, and private keys from the smartcard */
		id_idx = 0;
		for (cert_idx = 0; cert_idx < num_certs; cert_idx++) {
			for (curr_id_type = CKO_CERTIFICATE; curr_id_type <= CKO_PRIVATE_KEY; curr_id_type++) {
................................................................................

				identities[id_idx].pcsc_identity->certificate = malloc(pcsc_identities[cert_idx].certificate_len);
				memcpy(identities[id_idx].pcsc_identity->certificate, pcsc_identities[cert_idx].certificate, pcsc_identities[cert_idx].certificate_len);

				id_idx++;
			}
		}

		if (include_extra_certs) {
			CACKEY_DEBUG_PRINTF("Including DoD Certificates on hardware slot");

			cackey_read_dod_identities(identities, id_idx, num_dod_certs);
		}

		cackey_free_certs(pcsc_identities, num_certs, 1);

		*ids_found = num_ids;















		return(identities);
	}


	*ids_found = 0;
	return(NULL);
}

CK_DEFINE_FUNCTION(CK_RV, C_Initialize)(CK_VOID_PTR pInitArgs) {
	CK_C_INITIALIZE_ARGS CK_PTR args;
	uint32_t idx, highest_slot;
	int mutex_init_ret;

	CACKEY_DEBUG_PRINTF("Called.");

	if (cackey_initialized) {
		CACKEY_DEBUG_PRINTF("Error.  Already initialized.");

................................................................................
		cackey_slots[idx].active = 0;
		cackey_slots[idx].pcsc_reader = NULL;
		cackey_slots[idx].transaction_depth = 0;
		cackey_slots[idx].transaction_need_hw_lock = 0;
		cackey_slots[idx].slot_reset = 0;
		cackey_slots[idx].token_flags = 0;
		cackey_slots[idx].label = NULL;
		cackey_slots[idx].internal = 0;
	}

	if (getenv("CACKEY_NO_EXTRA_CERTS") != NULL) {
		CACKEY_DEBUG_PRINTF("Asked not to include DoD certificates");
	} else {
		highest_slot = (sizeof(cackey_slots) / sizeof(cackey_slots[0])) - 1;

		CACKEY_DEBUG_PRINTF("Including DoD certs in slot %lu", (unsigned long) highest_slot);

		cackey_slots[highest_slot].active = 1;
		cackey_slots[highest_slot].internal = 1;
		cackey_slots[highest_slot].label = (unsigned char *) "DoD Certificates";
		cackey_slots[highest_slot].pcsc_reader = "CACKey";
		cackey_slots[highest_slot].token_flags = 0;
	}

	cackey_initialized = 1;

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

................................................................................
			C_CloseSession(idx);
		}
	}

	cackey_slots_disconnect_all();

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

		if (cackey_slots[idx].pcsc_reader) {
			free(cackey_slots[idx].pcsc_reader);
		}
	}

	cackey_pcsc_disconnect();

................................................................................

/*
 * Process list of readers, and create mapping between reader name and slot ID
 */
CK_DEFINE_FUNCTION(CK_RV, C_GetSlotList)(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount) {
	int mutex_retval;
	int pcsc_connect_ret;
	CK_ULONG count, slot_count = 0, currslot, slot_idx;
	char *pcsc_readers, *pcsc_readers_s, *pcsc_readers_e;
	DWORD pcsc_readers_len;
	LONG scard_listreaders_ret;
	size_t curr_reader_len;

	CACKEY_DEBUG_PRINTF("Called.");

................................................................................
	if (pSlotList) {
		CACKEY_DEBUG_PRINTF("Purging all slot information.");

		/* Only update the list of slots if we are actually being supply the slot information */
		cackey_slots_disconnect_all();

		for (currslot = 0; currslot < (sizeof(cackey_slots) / sizeof(cackey_slots[0])); currslot++) {
			if (cackey_slots[currslot].internal) {
				continue;
			}

			if (cackey_slots[currslot].pcsc_reader) {
				free(cackey_slots[currslot].pcsc_reader);

				cackey_slots[currslot].pcsc_reader = NULL;
			}

			if (cackey_slots[currslot].label) {
................................................................................
			scard_listreaders_ret = SCardListReaders(*cackey_pcsc_handle, NULL, pcsc_readers, &pcsc_readers_len);
			if (scard_listreaders_ret == SCARD_S_SUCCESS) {
				pcsc_readers_e = pcsc_readers + pcsc_readers_len;

				/* Start with Slot ID 1, to avoid a bug in GDM on RHEL */
				/* Bug 594911: https://bugzilla.redhat.com/show_bug.cgi?id=594911 */
				currslot = 1;
				slot_count = 0;
				while (pcsc_readers < pcsc_readers_e) {
					/* Find next available slot */
					for (; currslot < (sizeof(cackey_slots) / sizeof(cackey_slots[0])); currslot++) {
						if (!cackey_slots[currslot].active) {
							break;
						}
					}

					curr_reader_len = strlen(pcsc_readers);

					if ((pcsc_readers + curr_reader_len) > pcsc_readers_e) {
						break;
					}

					if (curr_reader_len == 0) {
................................................................................
					}

					CACKEY_DEBUG_PRINTF("Found reader: %s", pcsc_readers);

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

						cackey_mark_slot_reset(&cackey_slots[currslot]);
					} else {
						/* Artificially increase the number of active slots by what will become active */
						slot_count++;
					}
					currslot++;

					pcsc_readers += curr_reader_len + 1;
				}

				for (currslot = 0; currslot < (sizeof(cackey_slots) / sizeof(cackey_slots[0])); currslot++) {
					if (cackey_slots[currslot].active) {
						CACKEY_DEBUG_PRINTF("Found active slot %lu", (unsigned long) currslot);

						slot_count++;
					}
				}
			} else {
				CACKEY_DEBUG_PRINTF("Second call to SCardListReaders failed, return %s/%li", CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(scard_listreaders_ret), (long) scard_listreaders_ret);
			}

			free(pcsc_readers_s);
		} else {
................................................................................
		return(CKR_OK);
	}

	count = *pulCount;
	if (count < slot_count) {
		CACKEY_DEBUG_PRINTF("Error. User allocated %lu entries, but we have %lu entries.", count, slot_count);

		CACKEY_DEBUG_PRINTF("Returning CKR_BUFFER_TOO_SMALL");

		return(CKR_BUFFER_TOO_SMALL);	
	}



	mutex_retval = cackey_mutex_lock(cackey_biglock);
	if (mutex_retval != 0) {
		CACKEY_DEBUG_PRINTF("Error.  Locking failed.");

		return(CKR_GENERAL_ERROR);
	}

	slot_idx = 0;
	for (currslot = 0; (currslot < (sizeof(cackey_slots) / sizeof(cackey_slots[0]))); currslot++) {
		if (!cackey_slots[currslot].active) {
			continue;
		}

		if (slot_idx >= count) {
			CACKEY_DEBUG_PRINTF("Error. User allocated %lu entries, but we just tried to write to the %lu index -- ignoring", count, slot_idx);

			continue;
		}

		pSlotList[slot_idx] = currslot;
		slot_idx++;
	}

	mutex_retval = cackey_mutex_unlock(cackey_biglock);
	if (mutex_retval != 0) {
		CACKEY_DEBUG_PRINTF("Error.  Unlocking failed.");

		return(CKR_GENERAL_ERROR);
	}

	*pulCount = slot_count;

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

	return(CKR_OK);
................................................................................
		CACKEY_DEBUG_PRINTF("Error. Invalid slot requested (%lu), slot not currently active", slotID);

		cackey_mutex_unlock(cackey_biglock);

		return(CKR_SLOT_ID_INVALID);
	}

	pInfo->flags = CKF_HW_SLOT;

	if (!cackey_slots[slotID].internal) {
		pInfo->flags |= CKF_REMOVABLE_DEVICE;
	}

	if (cackey_token_present(&cackey_slots[slotID]) == CACKEY_PCSC_S_TOKENPRESENT) {
		pInfo->flags |= CKF_TOKEN_PRESENT;
	}

	bytes_to_copy = strlen(cackey_slots[slotID].pcsc_reader);
	if (sizeof(pInfo->manufacturerID) < bytes_to_copy) {

Modified configure.ac from [8952b0e3fb] to [34ff5a91b6].

138
139
140
141
142
143
144











145
146
147
148
149
150
151
152
153
154
155
156
		AC_MSG_RESULT(okay)
	], [
		AC_MSG_RESULT(failed)

		AC_MSG_FAILURE([simple PC/SC program failed])
	]
)












dnl Set version script, to limit the scope of symbols
DC_SETVERSIONSCRIPT(libcackey.vers, libcackey.syms)

dnl Upate LDFLAGS to include setting the run-time linker path to the same as our compile-time linker
DC_SYNC_RPATH

dnl If we updated LIBOBJS, update SHLIBOBJS -- must be last.
DC_SYNC_SHLIBOBJS

dnl Produce Makefile
AC_OUTPUT(Makefile libcackey.syms)







>
>
>
>
>
>
>
>
>
>
>












138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
		AC_MSG_RESULT(okay)
	], [
		AC_MSG_RESULT(failed)

		AC_MSG_FAILURE([simple PC/SC program failed])
	]
)

dnl Option to enable DoD certs on hardware slot
AC_ARG_ENABLE(dod-certs-on-hw-slots, AC_HELP_STRING([--enable-dod-certs-on-hw-slots], [Specify that DoD certificates should be made available on hardware token slots]), [
	dodcertsonhwslots=$enableval
], [
	dodcertsonhwslots=no
])

if ! test "${dodcertsonhwslots}" = 'no'; then
	AC_DEFINE(CACKEY_CARD_SLOT_INCLUDE_EXTRA_CERTS, [1], [Specify that DoD certificates should be made available on hardware token slots])
fi

dnl Set version script, to limit the scope of symbols
DC_SETVERSIONSCRIPT(libcackey.vers, libcackey.syms)

dnl Upate LDFLAGS to include setting the run-time linker path to the same as our compile-time linker
DC_SYNC_RPATH

dnl If we updated LIBOBJS, update SHLIBOBJS -- must be last.
DC_SYNC_SHLIBOBJS

dnl Produce Makefile
AC_OUTPUT(Makefile libcackey.syms)

Modified test.c from [7438606333] to [86bd0fe2e2].

234
235
236
237
238
239
240

241
242
243
244
245
246
247
...
325
326
327
328
329
330
331





332
333
334
335
336
337
338
		printf("  Slot %lu:\n", currSlot);

		chk_rv = C_GetSlotInfo(slots[currSlot], &slotInfo);
		if (chk_rv != CKR_OK) {
			return(1);
		}


		printf("    Desc   : %.*s\n", 32, slotInfo.slotDescription);
		printf("    ManufID: %.*s\n", 32, slotInfo.manufacturerID);
		printf("    HWVers : %i.%i\n", slotInfo.hardwareVersion.major, slotInfo.hardwareVersion.minor);
		printf("    FWVers : %i.%i\n", slotInfo.firmwareVersion.major, slotInfo.firmwareVersion.minor);
		printf("    Flags  : ");
		if ((slotInfo.flags & CKF_TOKEN_PRESENT) == CKF_TOKEN_PRESENT) {
			printf("CKF_TOKEN_PRESENT ");
................................................................................
			}
			printf("\n");
		}
	}

	chk_rv = C_OpenSession(slots[0], CKF_SERIAL_SESSION, NULL, NULL, &hSession);
	if (chk_rv == CKR_OK) {





		if ((tokenInfo.flags & CKF_LOGIN_REQUIRED) == CKF_LOGIN_REQUIRED) {
			fgets_ret = NULL;

			while (fgets_ret == NULL) {
				printf("** ENTER PIN: ");
				fflush(stdout);








>







 







>
>
>
>
>







234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
...
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
		printf("  Slot %lu:\n", currSlot);

		chk_rv = C_GetSlotInfo(slots[currSlot], &slotInfo);
		if (chk_rv != CKR_OK) {
			return(1);
		}

		printf("    Id     : %lu\n", (unsigned long) slots[currSlot]);
		printf("    Desc   : %.*s\n", 32, slotInfo.slotDescription);
		printf("    ManufID: %.*s\n", 32, slotInfo.manufacturerID);
		printf("    HWVers : %i.%i\n", slotInfo.hardwareVersion.major, slotInfo.hardwareVersion.minor);
		printf("    FWVers : %i.%i\n", slotInfo.firmwareVersion.major, slotInfo.firmwareVersion.minor);
		printf("    Flags  : ");
		if ((slotInfo.flags & CKF_TOKEN_PRESENT) == CKF_TOKEN_PRESENT) {
			printf("CKF_TOKEN_PRESENT ");
................................................................................
			}
			printf("\n");
		}
	}

	chk_rv = C_OpenSession(slots[0], CKF_SERIAL_SESSION, NULL, NULL, &hSession);
	if (chk_rv == CKR_OK) {
		chk_rv = C_GetTokenInfo(slots[0], &tokenInfo);
		if (chk_rv != CKR_OK) {
			return(1);
		}

		if ((tokenInfo.flags & CKF_LOGIN_REQUIRED) == CKF_LOGIN_REQUIRED) {
			fgets_ret = NULL;

			while (fgets_ret == NULL) {
				printf("** ENTER PIN: ");
				fflush(stdout);