Diff

Differences From Artifact [e6fa629162]:

To Artifact [8c591e3548]:


1113
1114
1115
1116
1117
1118
1119

1120




1121
1122
1123
1124
1125
1126
1127
1113
1114
1115
1116
1117
1118
1119
1120

1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131







+
-
+
+
+
+








	if (slot->pcsc_card_connected) {
		SCardDisconnect(slot->pcsc_card, SCARD_LEAVE_CARD);
	}

	slot->slot_reset = 1;
	slot->pcsc_card_connected = 0;
	if (cackey_pin_command == NULL) {
	slot->token_flags = CKF_LOGIN_REQUIRED;
		slot->token_flags = CKF_LOGIN_REQUIRED;
	} else {
		slot->token_flags = 0;
	}

	CACKEY_DEBUG_PRINTF("Returning.");

	return;
}

/*
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882






2883
2884
2885
2886
2887
2888
2889
2890
2891
2869
2870
2871
2872
2873
2874
2875











2876
2877
2878
2879
2880
2881
2882

2883
2884
2885
2886
2887
2888
2889







-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+

-







				}
			}

			/* End transaction */
			cackey_end_transaction(slot);

			if (respcode == 0x6982 || respcode == 0x6e00) {
				CACKEY_DEBUG_PRINTF("Security status not satisified (respcode = 0x%04x).  Returning NEEDLOGIN", (int) respcode);

				cackey_mark_slot_reset(slot);
				slot->token_flags = CKF_LOGIN_REQUIRED;

				return(CACKEY_PCSC_E_NEEDLOGIN);
			}

			if (respcode == 0x6E00) {
				CACKEY_DEBUG_PRINTF("Got \"WRONG CLASS\", this means we are talking to the wrong object (likely because the card went away) -- resetting");

				if (respcode == 0x6E00) {
					CACKEY_DEBUG_PRINTF("Got \"WRONG CLASS\", this means we are talking to the wrong object (likely because the card went away) -- resetting");
				} else {
					CACKEY_DEBUG_PRINTF("Security status not satisified (respcode = 0x%04x).  Returning NEEDLOGIN", (int) respcode);
				}

				cackey_mark_slot_reset(slot);
				slot->token_flags = CKF_LOGIN_REQUIRED;

				return(CACKEY_PCSC_E_NEEDLOGIN);
			}

			if (send_ret == CACKEY_PCSC_E_TOKENABSENT) {
				CACKEY_DEBUG_PRINTF("Token absent.  Returning TOKENABSENT");

4430
4431
4432
4433
4434
4435
4436
4437

4438
4439
4440
4441
4442
4443
4444
4445
4446
4447

4448




4449
4450
4451
4452
4453

4454
4455





4456
4457
4458
4459
4460
4461
4462
4463
4464

4465
4466
4467
4468
4469
4470
4471
4428
4429
4430
4431
4432
4433
4434

4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446

4447
4448
4449
4450
4451
4452
4453
4454
4455
4456


4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469

4470
4471
4472
4473
4474
4475
4476
4477







-
+










+
-
+
+
+
+





+
-
-
+
+
+
+
+








-
+








					if (currslot >= (sizeof(cackey_slots) / sizeof(cackey_slots[0]))) {
						CACKEY_DEBUG_PRINTF("Found more readers than slots are available!");

						break;
					}

					CACKEY_DEBUG_PRINTF("Found reader: %s", pcsc_readers);
					CACKEY_DEBUG_PRINTF("Found reader: %s (currslot = %lu)", pcsc_readers, (unsigned long) currslot);

					/* Only update the list of slots if we are actually being asked supply the slot information */
					if (pSlotList) {
						if (slot_reset) {
							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;
							if (cackey_pin_command == NULL) {
							cackey_slots[currslot].token_flags = CKF_LOGIN_REQUIRED;
								cackey_slots[currslot].token_flags = CKF_LOGIN_REQUIRED;
							} else {
								cackey_slots[currslot].token_flags = 0;
							}
							cackey_slots[currslot].label = NULL;

							cackey_mark_slot_reset(&cackey_slots[currslot]);
						}
					} else {
						if (!cackey_slots[currslot].active) {
						/* Artificially increase the number of active slots by what will become active */
						slot_count++;
							/* Artificially increase the number of active slots by what will become active */
							CACKEY_DEBUG_PRINTF("Found in-active slot %lu, but it will be active after a reset -- marking as active for accounting purposes", (unsigned long) currslot);

							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);
						CACKEY_DEBUG_PRINTF("Found active slot %lu, reader = %s", (unsigned long) currslot, cackey_slots[currslot].pcsc_reader);

						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);
			}
5186
5187
5188
5189
5190
5191
5192
5193

5194
5195
5196
5197
5198
5199
5200
5192
5193
5194
5195
5196
5197
5198

5199
5200
5201
5202
5203
5204
5205
5206







-
+







	}

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

	return(CKR_FUNCTION_NOT_SUPPORTED);
}

CK_DEFINE_FUNCTION(CK_RV, C_Login)(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen) {
CK_DEFINE_FUNCTION(CK_RV, _C_LoginMutexArg)(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen, int lock_mutex) {
	CK_SLOT_ID slotID;
	FILE *pinfd;
	char *pincmd, pinbuf[64], *fgets_ret;
	int mutex_retval;
	int tries_remaining;
	int login_ret;
	int pclose_ret;
5215
5216
5217
5218
5219
5220
5221

5222
5223
5224



5225
5226


5227
5228
5229

5230


5231
5232
5233
5234
5235
5236
5237
5238
5239
5240




5241
5242
5243
5244
5245
5246
5247

5248


5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264

5265


5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280

5281


5282
5283
5284
5285
5286
5287
5288
5289
5290

5291


5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302
5303
5304
5305
5306
5307

5308


5309
5310
5311
5312
5313
5314
5315
5221
5222
5223
5224
5225
5226
5227
5228



5229
5230
5231
5232

5233
5234
5235
5236
5237
5238

5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262

5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281

5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299

5300
5301
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311

5312
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330

5331
5332
5333
5334
5335
5336
5337
5338
5339







+
-
-
-
+
+
+

-
+
+



+
-
+
+










+
+
+
+







+
-
+
+
















+
-
+
+















+
-
+
+









+
-
+
+
















+
-
+
+








	if (userType != CKU_USER) {
		CACKEY_DEBUG_PRINTF("Error.  We only support USER mode, asked for %lu mode.", (unsigned long) userType)

		return(CKR_USER_TYPE_INVALID);
	}

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

		return(CKR_GENERAL_ERROR);
			return(CKR_GENERAL_ERROR);
		}
	}

	if (!cackey_sessions[hSession].active) {
		if (lock_mutex) {
		cackey_mutex_unlock(cackey_biglock);
			cackey_mutex_unlock(cackey_biglock);
		}

		CACKEY_DEBUG_PRINTF("Error.  Session not active.");
		
		return(CKR_SESSION_HANDLE_INVALID);
	}

	slotID = cackey_sessions[hSession].slotID;

	if (slotID < 0 || slotID >= (sizeof(cackey_slots) / sizeof(cackey_slots[0]))) {
		CACKEY_DEBUG_PRINTF("Error. Invalid slot requested (%lu), outside of valid range", slotID);

		if (lock_mutex) {
			cackey_mutex_unlock(cackey_biglock);
		}

		return(CKR_GENERAL_ERROR);
	}

	if (cackey_slots[slotID].active == 0) {
		CACKEY_DEBUG_PRINTF("Error. Invalid slot requested (%lu), slot not currently active", slotID);

		if (lock_mutex) {
		cackey_mutex_unlock(cackey_biglock);
			cackey_mutex_unlock(cackey_biglock);
		}

		return(CKR_GENERAL_ERROR);
	}

	pincmd = cackey_pin_command;
	if (pincmd != NULL) {
		CACKEY_DEBUG_PRINTF("CACKEY_PIN_COMMAND = %s", pincmd);

		if (pPin != NULL) {
			CACKEY_DEBUG_PRINTF("Protected authentication path in effect and PIN provided !?");
		}

		pinfd = popen(pincmd, "r");
		if (pinfd == NULL) {
			CACKEY_DEBUG_PRINTF("Error.  %s: Unable to run", pincmd);

			if (lock_mutex) {
			cackey_mutex_unlock(cackey_biglock);
				cackey_mutex_unlock(cackey_biglock);
			}

			CACKEY_DEBUG_PRINTF("Returning CKR_PIN_INCORRECT (%i)", (int) CKR_PIN_INCORRECT);

			return(CKR_PIN_INCORRECT);
		}

		fgets_ret = fgets(pinbuf, sizeof(pinbuf), pinfd);
		if (fgets_ret == NULL) {
			pinbuf[0] = '\0';
		}

		pclose_ret = pclose(pinfd);
		if (pclose_ret != 0) {
			CACKEY_DEBUG_PRINTF("Error.  %s: exited with non-zero status of %i", pincmd, pclose_ret);

			if (lock_mutex) {
			cackey_mutex_unlock(cackey_biglock);
				cackey_mutex_unlock(cackey_biglock);
			}

			CACKEY_DEBUG_PRINTF("Returning CKR_PIN_INCORRECT (%i)", (int) CKR_PIN_INCORRECT);

			return(CKR_PIN_INCORRECT);
		}

		if (strlen(pinbuf) < 1) {
			CACKEY_DEBUG_PRINTF("Error.  %s: returned no data", pincmd);

			if (lock_mutex) {
			cackey_mutex_unlock(cackey_biglock);
				cackey_mutex_unlock(cackey_biglock);
			}

			CACKEY_DEBUG_PRINTF("Returning CKR_PIN_INCORRECT (%i)", (int) CKR_PIN_INCORRECT);

			return(CKR_PIN_INCORRECT);
		}

		if (pinbuf[strlen(pinbuf) - 1] == '\n') {
			pinbuf[strlen(pinbuf) - 1] = '\0';
		}

		pPin = (CK_UTF8CHAR_PTR) pinbuf;
		ulPinLen = strlen(pinbuf);
	}

	login_ret = cackey_login(&cackey_slots[slotID], pPin, ulPinLen, &tries_remaining);
	if (login_ret != CACKEY_PCSC_S_OK) {
		if (lock_mutex) {
		cackey_mutex_unlock(cackey_biglock);
			cackey_mutex_unlock(cackey_biglock);
		}

		if (login_ret == CACKEY_PCSC_E_LOCKED) {
			CACKEY_DEBUG_PRINTF("Error.  Token is locked.");

			cackey_slots[slotID].token_flags |= CKF_USER_PIN_LOCKED;

			CACKEY_DEBUG_PRINTF("Returning CKR_PIN_LOCKED (%i)", (int) CKR_PIN_LOCKED);
5334
5335
5336
5337
5338
5339
5340

5341
5342
5343



5344
5345


5346
5347
5348
5349
5350
5351




5352
5353
5354
5355
5356
5357
5358
5358
5359
5360
5361
5362
5363
5364
5365



5366
5367
5368
5369

5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380
5381
5382
5383
5384
5385
5386
5387
5388







+
-
-
-
+
+
+

-
+
+






+
+
+
+







		return(CKR_GENERAL_ERROR);
	}

	cackey_slots[slotID].token_flags &= ~(CKF_USER_PIN_LOCKED | CKF_USER_PIN_COUNT_LOW | CKF_LOGIN_REQUIRED | CKF_USER_PIN_FINAL_TRY);

	cackey_sessions[hSession].state = CKS_RO_USER_FUNCTIONS;

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

		return(CKR_GENERAL_ERROR);
			return(CKR_GENERAL_ERROR);
		}
	}

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

	return(CKR_OK);
}

CK_DEFINE_FUNCTION(CK_RV, C_Login)(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen) {
	return(_C_LoginMutexArg(hSession, userType, pPin, ulPinLen, 1));
}

CK_DEFINE_FUNCTION(CK_RV, C_Logout)(CK_SESSION_HANDLE hSession) {
	CK_SLOT_ID slotID;
	int mutex_retval;

	CACKEY_DEBUG_PRINTF("Called.");

5396
5397
5398
5399
5400
5401
5402


5403




5404
5405
5406
5407
5408
5409
5410
5426
5427
5428
5429
5430
5431
5432
5433
5434

5435
5436
5437
5438
5439
5440
5441
5442
5443
5444
5445







+
+
-
+
+
+
+








		cackey_mutex_unlock(cackey_biglock);

		return(CKR_GENERAL_ERROR);
	}

	cackey_sessions[hSession].state = CKS_RO_PUBLIC_SESSION;

	if (cackey_pin_command == NULL) {
	cackey_slots[slotID].token_flags = CKF_LOGIN_REQUIRED;
		cackey_slots[slotID].token_flags = CKF_LOGIN_REQUIRED;
	} else {
		cackey_slots[slotID].token_flags = 0;
	}

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

		return(CKR_GENERAL_ERROR);
	}
6320
6321
6322
6323
6324
6325
6326






6327
6328
6329
6330
6331
6332
6333
6355
6356
6357
6358
6359
6360
6361
6362
6363
6364
6365
6366
6367
6368
6369
6370
6371
6372
6373
6374







+
+
+
+
+
+







		return(CKR_GENERAL_ERROR);
	}

	switch (cackey_sessions[hSession].decrypt_mechanism) {
		case CKM_RSA_PKCS:
			/* Ask card to decrypt */
			buflen = cackey_signdecrypt(&cackey_slots[slotID], cackey_sessions[hSession].decrypt_identity, pEncryptedPart, ulEncryptedPartLen, buf, sizeof(buf), 0, 1);

			if (buflen == CACKEY_PCSC_E_NEEDLOGIN && cackey_pin_command != NULL) {
				if (_C_LoginMutexArg(hSession, CKU_USER, NULL, 0, 0) == CKR_OK) {
					buflen = cackey_signdecrypt(&cackey_slots[slotID], cackey_sessions[hSession].decrypt_identity, pEncryptedPart, ulEncryptedPartLen, buf, sizeof(buf), 0, 1);
				}
			}

			if (buflen < 0) {
				/* Decryption failed. */
				if (buflen == CACKEY_PCSC_E_NEEDLOGIN) {
					retval = CKR_USER_NOT_LOGGED_IN;
				} else if (buflen == CACKEY_PCSC_E_TOKENABSENT) {
					retval = CKR_DEVICE_REMOVED;
6831
6832
6833
6834
6835
6836
6837






6838
6839
6840
6841
6842
6843
6844
6872
6873
6874
6875
6876
6877
6878
6879
6880
6881
6882
6883
6884
6885
6886
6887
6888
6889
6890
6891







+
+
+
+
+
+







	}

	switch (cackey_sessions[hSession].sign_mechanism) {
		case CKM_RSA_PKCS:
			/* Ask card to sign */
			CACKEY_DEBUG_PRINTF("Asking to sign from identity %p in session %lu", (void *) cackey_sessions[hSession].sign_identity, (unsigned long) hSession);
			sigbuflen = cackey_signdecrypt(&cackey_slots[slotID], cackey_sessions[hSession].sign_identity, cackey_sessions[hSession].sign_buf, cackey_sessions[hSession].sign_bufused, sigbuf, sizeof(sigbuf), 1, 0);

			if (sigbuflen == CACKEY_PCSC_E_NEEDLOGIN && cackey_pin_command != NULL) {
				if (_C_LoginMutexArg(hSession, CKU_USER, NULL, 0, 0) == CKR_OK) {
					sigbuflen = cackey_signdecrypt(&cackey_slots[slotID], cackey_sessions[hSession].sign_identity, cackey_sessions[hSession].sign_buf, cackey_sessions[hSession].sign_bufused, sigbuf, sizeof(sigbuf), 1, 0);
				}
			}

			if (sigbuflen < 0) {
				/* Signing failed. */
				if (sigbuflen == CACKEY_PCSC_E_NEEDLOGIN) {
					retval = CKR_USER_NOT_LOGGED_IN;
				} else if (sigbuflen == CACKEY_PCSC_E_TOKENABSENT) {
					retval = CKR_DEVICE_REMOVED;