Diff

Differences From Artifact [1be2f8a22e]:

To Artifact [42750d148e]:


   709    709   	CK_VOID_PTR decrypt_mech_parm;
   710    710   	CK_ULONG decrypt_mech_parmlen;
   711    711   	struct cackey_identity *decrypt_identity;
   712    712   };
   713    713   
   714    714   struct cackey_slot {
   715    715   	int active;
          716  +	int internal;
   716    717   
   717    718   	char *pcsc_reader;
   718    719   
   719    720   	int pcsc_card_connected;
   720    721   	SCARDHANDLE pcsc_card;
   721    722   
   722    723   	int transaction_depth;
................................................................................
   853    854    */
   854    855   static void cackey_slots_disconnect_all(void) {
   855    856   	uint32_t idx;
   856    857   
   857    858   	CACKEY_DEBUG_PRINTF("Called.");
   858    859   
   859    860   	for (idx = 0; idx < (sizeof(cackey_slots) / sizeof(cackey_slots[0])); idx++) {
          861  +		if (cackey_slots[idx].internal) {
          862  +			/* Skip internal slots */
          863  +			continue;
          864  +		}
          865  +
   860    866   		if (cackey_slots[idx].pcsc_card_connected) {
   861    867   			CACKEY_DEBUG_PRINTF("SCardDisconnect(%lu) called", (unsigned long) idx);
   862    868   
   863    869   			SCardDisconnect(cackey_slots[idx].pcsc_card, SCARD_LEAVE_CARD);
   864    870   		}
   865    871   
   866    872   		if (cackey_slots[idx].label) {
................................................................................
  2602   2608   static cackey_ret cackey_token_present(struct cackey_slot *slot) {
  2603   2609   	cackey_ret pcsc_connect_ret;
  2604   2610   	DWORD reader_len, state, protocol, atr_len;
  2605   2611   	BYTE atr[MAX_ATR_SIZE];
  2606   2612   	LONG status_ret, scard_reconn_ret;
  2607   2613   
  2608   2614   	CACKEY_DEBUG_PRINTF("Called.");
         2615  +
         2616  +	if (slot->internal) {
         2617  +		CACKEY_DEBUG_PRINTF("Returning token present (internal token)");
         2618  +
         2619  +		return(CACKEY_PCSC_S_TOKENPRESENT);
         2620  +	}
  2609   2621   
  2610   2622   	pcsc_connect_ret = cackey_connect_card(slot);
  2611   2623   	if (pcsc_connect_ret != CACKEY_PCSC_S_OK) {
  2612   2624   		CACKEY_DEBUG_PRINTF("Unable to connect to card, returning token absent");
  2613   2625   
  2614   2626   		return(CACKEY_PCSC_E_TOKENABSENT);
  2615   2627   	}
................................................................................
  3401   3413   	free(identities);
  3402   3414   }
  3403   3415   
  3404   3416   static struct cackey_identity *cackey_read_identities(struct cackey_slot *slot, unsigned long *ids_found) {
  3405   3417   	struct cackey_pcsc_identity *pcsc_identities;
  3406   3418   	struct cackey_identity *identities;
  3407   3419   	unsigned long num_ids, id_idx, curr_id_type;
  3408         -	unsigned long num_certs, num_extra_certs, cert_idx;
  3409         -	int include_extra_certs = 1;
         3420  +	unsigned long num_certs, num_dod_certs, cert_idx;
  3410   3421   
  3411   3422   	CACKEY_DEBUG_PRINTF("Called.");
  3412   3423   
  3413         -	if (getenv("CACKEY_NO_EXTRA_CERTS") != NULL) {
  3414         -		CACKEY_DEBUG_PRINTF("Asked not to include extra (DoD) certificates");
  3415         -
  3416         -		include_extra_certs = 0;
  3417         -	}
  3418         -
  3419         -	if (include_extra_certs) {
  3420         -		num_extra_certs = sizeof(extra_certs) / sizeof(extra_certs[0]);
  3421         -
  3422         -		CACKEY_DEBUG_PRINTF("Including %li DoD Certificates as objects on this token", num_extra_certs);
  3423         -	} else {
  3424         -		num_extra_certs = 0;
  3425         -	}
  3426         -
  3427   3424   	if (ids_found == NULL) {
  3428   3425   		CACKEY_DEBUG_PRINTF("Error.  ids_found is NULL");
  3429   3426   
  3430   3427   		return(NULL);
  3431   3428   	}
         3429  +
         3430  +	if (slot->internal) {
         3431  +		/* Add DoD Certificates and Netscape Trust Objects */
         3432  +		num_dod_certs = sizeof(extra_certs) / sizeof(extra_certs[0]);
         3433  +
         3434  +		num_ids = num_dod_certs * 3;
         3435  +
         3436  +		identities = malloc(num_ids * sizeof(*identities));
         3437  +
         3438  +		id_idx = 0;
         3439  +		for (cert_idx = 0; cert_idx < num_dod_certs; cert_idx++) {
         3440  +			identities[id_idx].pcsc_identity = NULL;
         3441  +			identities[id_idx].attributes = cackey_get_attributes(CKO_CERTIFICATE, &extra_certs[cert_idx], 0xf000 | cert_idx, &identities[id_idx].attributes_count);
         3442  +			id_idx++;
         3443  +
         3444  +			identities[id_idx].pcsc_identity = NULL;
         3445  +			identities[id_idx].attributes = cackey_get_attributes(CKO_PUBLIC_KEY, &extra_certs[cert_idx], 0xf000 | cert_idx, &identities[id_idx].attributes_count);
         3446  +			id_idx++;
         3447  +
         3448  +			identities[id_idx].pcsc_identity = NULL;
         3449  +			identities[id_idx].attributes = cackey_get_attributes(CKO_NETSCAPE_TRUST, &extra_certs[cert_idx], 0xf000 | cert_idx, &identities[id_idx].attributes_count);
         3450  +			id_idx++;
         3451  +		}
         3452  +
         3453  +		*ids_found = num_ids;
         3454  +
         3455  +		return(identities);
         3456  +	}
  3432   3457   
  3433   3458   	pcsc_identities = cackey_read_certs(slot, NULL, &num_certs);
  3434   3459   	if (pcsc_identities != NULL) {
  3435   3460   		/* Convert number of Certs to number of objects */
  3436   3461   		num_ids = (CKO_PRIVATE_KEY - CKO_CERTIFICATE + 1) * num_certs;
  3437         -		num_ids += num_extra_certs * 3;
  3438   3462   
  3439   3463   		identities = malloc(num_ids * sizeof(*identities));
  3440   3464   
  3441   3465   		/* Add certificates, public keys, and private keys from the smartcard */
  3442   3466   		id_idx = 0;
  3443   3467   		for (cert_idx = 0; cert_idx < num_certs; cert_idx++) {
  3444   3468   			for (curr_id_type = CKO_CERTIFICATE; curr_id_type <= CKO_PRIVATE_KEY; curr_id_type++) {
................................................................................
  3452   3476   
  3453   3477   				id_idx++;
  3454   3478   			}
  3455   3479   		}
  3456   3480   
  3457   3481   		cackey_free_certs(pcsc_identities, num_certs, 1);
  3458   3482   
  3459         -		/* Add DoD Certificates and Netscape Trust Objects */
  3460         -		for (cert_idx = 0; cert_idx < num_extra_certs; cert_idx++) {
  3461         -			identities[id_idx].pcsc_identity = NULL;
  3462         -			identities[id_idx].attributes = cackey_get_attributes(CKO_CERTIFICATE, &extra_certs[cert_idx], 0xf000 | cert_idx, &identities[id_idx].attributes_count);
  3463         -			id_idx++;
  3464         -
  3465         -			identities[id_idx].pcsc_identity = NULL;
  3466         -			identities[id_idx].attributes = cackey_get_attributes(CKO_PUBLIC_KEY, &extra_certs[cert_idx], 0xf000 | cert_idx, &identities[id_idx].attributes_count);
  3467         -			id_idx++;
  3468         -
  3469         -			identities[id_idx].pcsc_identity = NULL;
  3470         -			identities[id_idx].attributes = cackey_get_attributes(CKO_NETSCAPE_TRUST, &extra_certs[cert_idx], 0xf000 | cert_idx, &identities[id_idx].attributes_count);
  3471         -			id_idx++;
  3472         -		}
  3473         -
  3474   3483   		*ids_found = num_ids;
         3484  +
  3475   3485   		return(identities);
  3476   3486   	}
  3477   3487   
  3478   3488   	*ids_found = 0;
  3479   3489   	return(NULL);
  3480   3490   }
  3481   3491   
  3482   3492   CK_DEFINE_FUNCTION(CK_RV, C_Initialize)(CK_VOID_PTR pInitArgs) {
  3483   3493   	CK_C_INITIALIZE_ARGS CK_PTR args;
  3484         -	uint32_t idx;
         3494  +	uint32_t idx, highest_slot;
  3485   3495   	int mutex_init_ret;
  3486   3496   
  3487   3497   	CACKEY_DEBUG_PRINTF("Called.");
  3488   3498   
  3489   3499   	if (cackey_initialized) {
  3490   3500   		CACKEY_DEBUG_PRINTF("Error.  Already initialized.");
  3491   3501   
................................................................................
  3519   3529   		cackey_slots[idx].active = 0;
  3520   3530   		cackey_slots[idx].pcsc_reader = NULL;
  3521   3531   		cackey_slots[idx].transaction_depth = 0;
  3522   3532   		cackey_slots[idx].transaction_need_hw_lock = 0;
  3523   3533   		cackey_slots[idx].slot_reset = 0;
  3524   3534   		cackey_slots[idx].token_flags = 0;
  3525   3535   		cackey_slots[idx].label = NULL;
         3536  +		cackey_slots[idx].internal = 0;
         3537  +	}
         3538  +
         3539  +	if (getenv("CACKEY_NO_EXTRA_CERTS") != NULL) {
         3540  +		CACKEY_DEBUG_PRINTF("Asked not to include DoD certificates");
         3541  +	} else {
         3542  +		highest_slot = (sizeof(cackey_slots) / sizeof(cackey_slots[0])) - 1;
         3543  +
         3544  +		CACKEY_DEBUG_PRINTF("Including DoD certs in slot %lu", (unsigned long) highest_slot);
         3545  +
         3546  +		cackey_slots[highest_slot].active = 1;
         3547  +		cackey_slots[highest_slot].internal = 1;
         3548  +		cackey_slots[highest_slot].label = (unsigned char *) "DoD Certificates";
         3549  +		cackey_slots[highest_slot].pcsc_reader = "CACKey";
         3550  +		cackey_slots[highest_slot].token_flags = 0;
  3526   3551   	}
  3527   3552   
  3528   3553   	cackey_initialized = 1;
  3529   3554   
  3530   3555   	if (!cackey_biglock_init) {
  3531   3556   		mutex_init_ret = cackey_mutex_create(&cackey_biglock);
  3532   3557   
................................................................................
  3566   3591   			C_CloseSession(idx);
  3567   3592   		}
  3568   3593   	}
  3569   3594   
  3570   3595   	cackey_slots_disconnect_all();
  3571   3596   
  3572   3597   	for (idx = 0; idx < (sizeof(cackey_slots) / sizeof(cackey_slots[0])); idx++) {
         3598  +		if (cackey_slots[idx].internal) {
         3599  +			continue;
         3600  +		}
         3601  +
  3573   3602   		if (cackey_slots[idx].pcsc_reader) {
  3574   3603   			free(cackey_slots[idx].pcsc_reader);
  3575   3604   		}
  3576   3605   	}
  3577   3606   
  3578   3607   	cackey_pcsc_disconnect();
  3579   3608   
................................................................................
  3623   3652   
  3624   3653   /*
  3625   3654    * Process list of readers, and create mapping between reader name and slot ID
  3626   3655    */
  3627   3656   CK_DEFINE_FUNCTION(CK_RV, C_GetSlotList)(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount) {
  3628   3657   	int mutex_retval;
  3629   3658   	int pcsc_connect_ret;
  3630         -	CK_ULONG count, slot_count = 0, currslot;
         3659  +	CK_ULONG count, slot_count = 0, currslot, slot_idx;
  3631   3660   	char *pcsc_readers, *pcsc_readers_s, *pcsc_readers_e;
  3632   3661   	DWORD pcsc_readers_len;
  3633   3662   	LONG scard_listreaders_ret;
  3634   3663   	size_t curr_reader_len;
  3635   3664   
  3636   3665   	CACKEY_DEBUG_PRINTF("Called.");
  3637   3666   
................................................................................
  3658   3687   	if (pSlotList) {
  3659   3688   		CACKEY_DEBUG_PRINTF("Purging all slot information.");
  3660   3689   
  3661   3690   		/* Only update the list of slots if we are actually being supply the slot information */
  3662   3691   		cackey_slots_disconnect_all();
  3663   3692   
  3664   3693   		for (currslot = 0; currslot < (sizeof(cackey_slots) / sizeof(cackey_slots[0])); currslot++) {
         3694  +			if (cackey_slots[currslot].internal) {
         3695  +				continue;
         3696  +			}
         3697  +
  3665   3698   			if (cackey_slots[currslot].pcsc_reader) {
  3666   3699   				free(cackey_slots[currslot].pcsc_reader);
  3667   3700   
  3668   3701   				cackey_slots[currslot].pcsc_reader = NULL;
  3669   3702   			}
  3670   3703   
  3671   3704   			if (cackey_slots[currslot].label) {
................................................................................
  3706   3739   			scard_listreaders_ret = SCardListReaders(*cackey_pcsc_handle, NULL, pcsc_readers, &pcsc_readers_len);
  3707   3740   			if (scard_listreaders_ret == SCARD_S_SUCCESS) {
  3708   3741   				pcsc_readers_e = pcsc_readers + pcsc_readers_len;
  3709   3742   
  3710   3743   				/* Start with Slot ID 1, to avoid a bug in GDM on RHEL */
  3711   3744   				/* Bug 594911: https://bugzilla.redhat.com/show_bug.cgi?id=594911 */
  3712   3745   				currslot = 1;
         3746  +				slot_count = 0;
  3713   3747   				while (pcsc_readers < pcsc_readers_e) {
         3748  +					/* Find next available slot */
         3749  +					for (; currslot < (sizeof(cackey_slots) / sizeof(cackey_slots[0])); currslot++) {
         3750  +						if (!cackey_slots[currslot].active) {
         3751  +							break;
         3752  +						}
         3753  +					}
         3754  +
  3714   3755   					curr_reader_len = strlen(pcsc_readers);
  3715   3756   
  3716   3757   					if ((pcsc_readers + curr_reader_len) > pcsc_readers_e) {
  3717   3758   						break;
  3718   3759   					}
  3719   3760   
  3720   3761   					if (curr_reader_len == 0) {
................................................................................
  3728   3769   					}
  3729   3770   
  3730   3771   					CACKEY_DEBUG_PRINTF("Found reader: %s", pcsc_readers);
  3731   3772   
  3732   3773   					/* Only update the list of slots if we are actually being asked supply the slot information */
  3733   3774   					if (pSlotList) {
  3734   3775   						cackey_slots[currslot].active = 1;
         3776  +						cackey_slots[currslot].internal = 0;
  3735   3777   						cackey_slots[currslot].pcsc_reader = strdup(pcsc_readers);
  3736   3778   						cackey_slots[currslot].pcsc_card_connected = 0;
  3737   3779   						cackey_slots[currslot].transaction_depth = 0;
  3738   3780   						cackey_slots[currslot].transaction_need_hw_lock = 0;
  3739   3781   						cackey_slots[currslot].slot_reset = 1;
  3740   3782   						cackey_slots[currslot].token_flags = CKF_LOGIN_REQUIRED;
  3741   3783   						cackey_slots[currslot].label = NULL;
  3742   3784   
  3743   3785   						cackey_mark_slot_reset(&cackey_slots[currslot]);
         3786  +					} else {
         3787  +						/* Artificially increase the number of active slots by what will become active */
         3788  +						slot_count++;
  3744   3789   					}
  3745   3790   					currslot++;
  3746   3791   
  3747   3792   					pcsc_readers += curr_reader_len + 1;
  3748   3793   				}
  3749   3794   
  3750         -				/* Start with Slot ID 1, to avoid a bug in GDM on RHEL */
  3751         -				/* Bug 594911: https://bugzilla.redhat.com/show_bug.cgi?id=594911 */
  3752         -				if (currslot > 1) {
  3753         -					/* Start with Slot ID 1, to avoid a bug in GDM on RHEL */
  3754         -					/* Bug 594911: https://bugzilla.redhat.com/show_bug.cgi?id=594911 */
  3755         -					slot_count = currslot - 1;
         3795  +				for (currslot = 0; currslot < (sizeof(cackey_slots) / sizeof(cackey_slots[0])); currslot++) {
         3796  +					if (cackey_slots[currslot].active) {
         3797  +						CACKEY_DEBUG_PRINTF("Found active slot %lu", (unsigned long) currslot);
         3798  +
         3799  +						slot_count++;
         3800  +					}
  3756   3801   				}
  3757   3802   			} else {
  3758   3803   				CACKEY_DEBUG_PRINTF("Second call to SCardListReaders failed, return %s/%li", CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(scard_listreaders_ret), (long) scard_listreaders_ret);
  3759   3804   			}
  3760   3805   
  3761   3806   			free(pcsc_readers_s);
  3762   3807   		} else {
................................................................................
  3779   3824   		return(CKR_OK);
  3780   3825   	}
  3781   3826   
  3782   3827   	count = *pulCount;
  3783   3828   	if (count < slot_count) {
  3784   3829   		CACKEY_DEBUG_PRINTF("Error. User allocated %lu entries, but we have %lu entries.", count, slot_count);
  3785   3830   
         3831  +		CACKEY_DEBUG_PRINTF("Returning CKR_BUFFER_TOO_SMALL");
         3832  +
  3786   3833   		return(CKR_BUFFER_TOO_SMALL);	
  3787   3834   	}
  3788   3835   
  3789         -	for (currslot = 0; currslot < slot_count; currslot++) {
  3790         -		/* Start with Slot ID 1, to avoid a bug in GDM on RHEL */
  3791         -		/* Bug 594911: https://bugzilla.redhat.com/show_bug.cgi?id=594911 */
  3792         -		pSlotList[currslot] = currslot + 1;
         3836  +	slot_idx = 0;
         3837  +	for (currslot = 0; (currslot < (sizeof(cackey_slots) / sizeof(cackey_slots[0]))); currslot++) {
         3838  +		if (!cackey_slots[currslot].active) {
         3839  +			continue;
         3840  +		}
         3841  +
         3842  +		if (slot_idx >= count) {
         3843  +			CACKEY_DEBUG_PRINTF("Error. User allocated %lu entries, but we just tried to write to the %lu index.", count, slot_idx);
         3844  +
         3845  +			CACKEY_DEBUG_PRINTF("Returning CKR_BUFFER_TOO_SMALL");
         3846  +
         3847  +			return(CKR_BUFFER_TOO_SMALL);	
         3848  +		}
         3849  +
         3850  +		pSlotList[slot_idx] = currslot;
         3851  +		slot_idx++;
  3793   3852   	}
  3794   3853   
  3795   3854   	*pulCount = slot_count;
  3796   3855   
  3797   3856   	CACKEY_DEBUG_PRINTF("Returning CKR_OK (%i).  Found %lu readers.", CKR_OK, (unsigned long) slot_count);
  3798   3857   
  3799   3858   	return(CKR_OK);
................................................................................
  3837   3896   		CACKEY_DEBUG_PRINTF("Error. Invalid slot requested (%lu), slot not currently active", slotID);
  3838   3897   
  3839   3898   		cackey_mutex_unlock(cackey_biglock);
  3840   3899   
  3841   3900   		return(CKR_SLOT_ID_INVALID);
  3842   3901   	}
  3843   3902   
  3844         -	pInfo->flags = CKF_REMOVABLE_DEVICE | CKF_HW_SLOT;
         3903  +	pInfo->flags = CKF_HW_SLOT;
         3904  +
         3905  +	if (!cackey_slots[slotID].internal) {
         3906  +		pInfo->flags |= CKF_REMOVABLE_DEVICE;
         3907  +	}
  3845   3908   
  3846   3909   	if (cackey_token_present(&cackey_slots[slotID]) == CACKEY_PCSC_S_TOKENPRESENT) {
  3847   3910   		pInfo->flags |= CKF_TOKEN_PRESENT;
  3848   3911   	}
  3849   3912   
  3850   3913   	bytes_to_copy = strlen(cackey_slots[slotID].pcsc_reader);
  3851   3914   	if (sizeof(pInfo->manufacturerID) < bytes_to_copy) {