Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

693 lines
16 KiB

  1. #include <windows.h>
  2. #include <wincrypt.h>
  3. #include <winscard.h>
  4. #include <string.h>
  5. #include <stdlib.h>
  6. #include <stdio.h>
  7. #include "basecsp.h"
  8. #include <des.h>
  9. #include <tripldes.h>
  10. #include <modes.h>
  11. #include "wpscproxy.h"
  12. #include "physfile.h"
  13. #include "carddbg.h"
  14. #define wszCARDMOD_VERSION_ERROR \
  15. L"The version of the smart card module installed on the system is incorrect for use with this program."
  16. //
  17. // Debug Logging
  18. //
  19. // This uses the debug routines from dsysdbg.h
  20. // Debug output will only be available in chk
  21. // bits.
  22. //
  23. DEFINE_DEBUG2(Cardmod)
  24. #define LOG_BEGIN_FUNCTION(x) \
  25. { DebugLog((DEB_TRACE_FUNC, "%s: Entering\n", #x)); }
  26. #define LOG_END_FUNCTION(x, y) \
  27. { DebugLog((DEB_TRACE_FUNC, "%s: Leaving, status: 0x%x\n", #x, y)); }
  28. #define LOG_CHECK_ALLOC(x) \
  29. { if (NULL == x) { \
  30. dwError = ERROR_NOT_ENOUGH_MEMORY; \
  31. DebugLog((DEB_TRACE_MEM, "%s: Allocation failed\n", #x)); \
  32. goto Ret; \
  33. } }
  34. #define LOG_CHECK_SCW_CALL(x) \
  35. { if (ERROR_SUCCESS != (dwError = I_CardMapErrorCode(x))) { \
  36. DebugLog((DEB_TRACE_FUNC, "%s: failed, status: 0x%x\n", \
  37. #x, dwError)); \
  38. goto Ret; \
  39. } }
  40. #define TEST_CASE(X) { if (ERROR_SUCCESS != (dwSts = X)) { printf("%s", #X); goto Ret; } }
  41. DEBUG_KEY MyDebugKeys[] =
  42. {
  43. {DEB_ERROR, "Error"},
  44. {DEB_WARN, "Warning"},
  45. {DEB_TRACE, "Trace"},
  46. {DEB_TRACE_FUNC, "TraceFuncs"},
  47. {DEB_TRACE_MEM, "TraceMem"},
  48. {DEB_TRACE_TRANSMIT, "TraceTransmit"},
  49. {DEB_TRACE_PROXY, "TraceProxy"},
  50. {0, NULL}
  51. };
  52. #if DBG
  53. #include <stdio.h>
  54. #define CROW 16
  55. void I_DebugPrintBytes(LPWSTR pwszHdr, BYTE *pb, DWORD cbSize)
  56. {
  57. ULONG cb, i;
  58. CHAR rgsz[1024];
  59. ULONG cbOffset = 0;
  60. BOOL fTruncated = FALSE;
  61. if (NULL == pb || 0 == cbSize)
  62. return;
  63. memset(rgsz, 0, sizeof(rgsz));
  64. DebugLog((
  65. DEB_TRACE_TRANSMIT,
  66. "%S, %d bytes ::\n",
  67. pwszHdr,
  68. cbSize));
  69. // Don't overflow the debug library output buffer.
  70. if (cbSize > 50)
  71. {
  72. cbSize = 50;
  73. fTruncated = TRUE;
  74. }
  75. while (cbSize > 0)
  76. {
  77. // Start every row with extra space
  78. strcat(rgsz, " ");
  79. cbOffset = strlen(rgsz);
  80. cb = min(CROW, cbSize);
  81. cbSize -= cb;
  82. for (i = 0; i < cb; i++)
  83. {
  84. sprintf(
  85. rgsz + cbOffset,
  86. " %02x",
  87. pb[i]);
  88. cbOffset += 3;
  89. }
  90. for (i = cb; i < CROW; i++)
  91. {
  92. strcat(rgsz, " ");
  93. }
  94. strcat(rgsz, " '");
  95. cbOffset = strlen(rgsz);
  96. for (i = 0; i < cb; i++)
  97. {
  98. if (pb[i] >= 0x20 && pb[i] <= 0x7f)
  99. sprintf(
  100. rgsz + cbOffset,
  101. "%c",
  102. pb[i]);
  103. else
  104. sprintf(
  105. rgsz + cbOffset,
  106. ".",
  107. pb[i]);
  108. cbOffset++;
  109. }
  110. strcat(rgsz, "\n");
  111. pb += cb;
  112. }
  113. if (fTruncated)
  114. DebugLog((
  115. DEB_TRACE_TRANSMIT,
  116. "(truncated)\n%s",
  117. rgsz));
  118. else
  119. DebugLog((
  120. DEB_TRACE_TRANSMIT,
  121. "\n%s",
  122. rgsz));
  123. }
  124. #endif
  125. #ifndef cbCHALLENGE_RESPONSE_DATA
  126. #define cbCHALLENGE_RESPONSE_DATA 8
  127. #endif
  128. //
  129. // Defines for Admin challenge-response key
  130. //
  131. BYTE rgbAdminKey [] = {
  132. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  133. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  134. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  135. };
  136. //
  137. // Default User Pin
  138. //
  139. CHAR szUserPin [] = "0000";
  140. //
  141. // Function: CspAllocH
  142. //
  143. LPVOID WINAPI CspAllocH(
  144. IN SIZE_T cBytes)
  145. {
  146. return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cBytes);
  147. }
  148. //
  149. // Function: CspFreeH
  150. //
  151. void WINAPI CspFreeH(
  152. IN LPVOID pMem)
  153. {
  154. HeapFree(GetProcessHeap(), 0, pMem);
  155. }
  156. //
  157. // Function: CspReAllocH
  158. //
  159. LPVOID WINAPI CspReAllocH(
  160. IN LPVOID pMem,
  161. IN SIZE_T cBytes)
  162. {
  163. return HeapReAlloc(
  164. GetProcessHeap(), HEAP_ZERO_MEMORY, pMem, cBytes);
  165. }
  166. DWORD WINAPI CspCacheAddFile(
  167. IN PVOID pvCacheContext,
  168. IN LPWSTR wszTag,
  169. IN DWORD dwFlags,
  170. IN PBYTE pbData,
  171. IN DWORD cbData)
  172. {
  173. return ERROR_SUCCESS;
  174. }
  175. DWORD WINAPI CspCacheLookupFile(
  176. IN PVOID pvCacheContext,
  177. IN LPWSTR wszTag,
  178. IN DWORD dwFlags,
  179. IN PBYTE *ppbData,
  180. IN PDWORD pcbData)
  181. {
  182. return ERROR_NOT_FOUND;
  183. }
  184. DWORD WINAPI CspCacheDeleteFile(
  185. IN PVOID pvCacheContext,
  186. IN LPWSTR wszTag,
  187. IN DWORD dwFlags)
  188. {
  189. return ERROR_SUCCESS;
  190. }
  191. //
  192. // Gets the challenge bytes for an admin challenge-response
  193. // authentication.
  194. //
  195. DWORD GetAdminAuthResponse(
  196. IN PCARD_DATA pCardData,
  197. IN OUT PBYTE pbResponse,
  198. IN DWORD cbResponse)
  199. {
  200. DES3TABLE des3Table;
  201. PBYTE pbChallenge = NULL;
  202. DWORD cbChallenge = 0;
  203. DWORD dwSts = ERROR_SUCCESS;
  204. memset(&des3Table, 0, sizeof(des3Table));
  205. if (cbCHALLENGE_RESPONSE_DATA != cbResponse)
  206. {
  207. dwSts = ERROR_INVALID_PARAMETER;
  208. goto Ret;
  209. }
  210. // Get the challenge
  211. TEST_CASE(pCardData->pfnCardGetChallenge(
  212. pCardData,
  213. &pbChallenge,
  214. &cbChallenge));
  215. // Build a des key using the admin auth key
  216. tripledes3key(&des3Table, rgbAdminKey);
  217. // Encrypt the challenge to compute the response
  218. tripledes(pbResponse, pbChallenge, (PVOID) &des3Table, ENCRYPT);
  219. Ret:
  220. if (pbChallenge)
  221. pCardData->pfnCspFree(pbChallenge);
  222. return dwSts;
  223. }
  224. //
  225. // Authenticates the user principal on the target card.
  226. //
  227. DWORD AuthenticateCardUser(
  228. IN PCARD_DATA pCardData)
  229. {
  230. return pCardData->pfnCardSubmitPin(
  231. pCardData,
  232. wszCARD_USER_USER,
  233. szUserPin,
  234. strlen(szUserPin),
  235. NULL);
  236. }
  237. //
  238. // Authenticates the admin principal on the target card.
  239. //
  240. DWORD AuthenticateCardAdmin(
  241. IN PCARD_DATA pCardData)
  242. {
  243. DWORD dwSts = ERROR_SUCCESS;
  244. BYTE rgbResponse [cbCHALLENGE_RESPONSE_DATA];
  245. // Get a challenge-response
  246. dwSts = GetAdminAuthResponse(
  247. pCardData,
  248. rgbResponse,
  249. sizeof(rgbResponse));
  250. if (ERROR_SUCCESS != dwSts)
  251. goto Ret;
  252. TEST_CASE(pCardData->pfnCardAuthenticateChallenge(
  253. pCardData,
  254. rgbResponse,
  255. sizeof(rgbResponse),
  256. NULL));
  257. Ret:
  258. return dwSts;
  259. }
  260. //
  261. // Create and initialize the Card Cache File
  262. //
  263. DWORD InitializeCardCacheFile(
  264. IN PCARD_DATA pCardData)
  265. {
  266. DWORD dwSts = ERROR_SUCCESS;
  267. BYTE rgbContents [sizeof(CARD_CACHE_FILE_FORMAT)];
  268. printf("Installing the Card Cache File ...\n");
  269. memset(rgbContents, 0, sizeof(rgbContents));
  270. TEST_CASE(AuthenticateCardUser(pCardData));
  271. TEST_CASE(pCardData->pfnCardCreateFile(
  272. pCardData,
  273. wszCACHE_FILE_FULL_PATH,
  274. EveryoneReadUserWriteAc));
  275. TEST_CASE(pCardData->pfnCardWriteFile(
  276. pCardData,
  277. wszCACHE_FILE_FULL_PATH,
  278. 0,
  279. rgbContents,
  280. sizeof(rgbContents)));
  281. Ret:
  282. return dwSts;
  283. }
  284. //
  285. // Create and initialize the Personal Data File
  286. //
  287. DWORD InitializePersonalDataFile(
  288. IN PCARD_DATA pCardData)
  289. {
  290. DWORD dwSts = ERROR_SUCCESS;
  291. printf("Installing the Card Personal Data File ...\n");
  292. TEST_CASE(AuthenticateCardUser(pCardData));
  293. TEST_CASE(pCardData->pfnCardCreateFile(
  294. pCardData,
  295. wszPERSONAL_DATA_FILE_FULL_PATH,
  296. EveryoneReadUserWriteAc));
  297. Ret:
  298. return dwSts;
  299. }
  300. //
  301. // Create and initialize the Card Identifier File
  302. //
  303. DWORD InitializeCardIDFile(
  304. IN PCARD_DATA pCardData)
  305. {
  306. DWORD dwSts = ERROR_SUCCESS;
  307. BYTE rgbContents [16];
  308. HCRYPTPROV hProv = 0;
  309. printf("Installing the Card Identifier File ...\n");
  310. if (! CryptAcquireContext(
  311. &hProv, NULL, MS_STRONG_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
  312. {
  313. dwSts = GetLastError();
  314. goto Ret;
  315. }
  316. if (! CryptGenRandom(
  317. hProv, sizeof(rgbContents), rgbContents))
  318. {
  319. dwSts = GetLastError();
  320. goto Ret;
  321. }
  322. TEST_CASE(AuthenticateCardAdmin(pCardData));
  323. TEST_CASE(pCardData->pfnCardCreateFile(
  324. pCardData,
  325. wszCARD_IDENTIFIER_FILE_FULL_PATH,
  326. EveryoneReadAdminWriteAc));
  327. TEST_CASE(pCardData->pfnCardWriteFile(
  328. pCardData,
  329. wszCARD_IDENTIFIER_FILE_FULL_PATH,
  330. 0,
  331. rgbContents,
  332. sizeof(rgbContents)));
  333. Ret:
  334. if (hProv)
  335. CryptReleaseContext(hProv, 0);
  336. return dwSts;
  337. }
  338. //
  339. // Create and initialize the CSP directory and Container Map File
  340. //
  341. DWORD InitializeCardCSPApplication(
  342. IN PCARD_DATA pCardData)
  343. {
  344. DWORD dwSts = ERROR_SUCCESS;
  345. BYTE rgbContents [16];
  346. SCODE scode = SCW_S_OK;
  347. WCHAR wszDirectory [MAX_PATH];
  348. printf("Installing the CSP Application ...\n");
  349. memset(wszDirectory, 0, sizeof(wszDirectory));
  350. memcpy(
  351. wszDirectory,
  352. szPHYSICAL_CSP_DIR,
  353. cbPHYSICAL_CSP_DIR);
  354. TEST_CASE(AuthenticateCardUser(pCardData));
  355. // Create the CSP application directory
  356. scode = hScwCreateDirectory(
  357. *((SCARDHANDLE *) pCardData->pvVendorSpecific),
  358. wszDirectory,
  359. wszUserWritePhysicalAcl);
  360. if (SCW_E_ALREADYEXISTS == scode)
  361. printf("CSP Application directory already exists.\n");
  362. else if (SCW_S_OK != scode)
  363. {
  364. dwSts = (DWORD) scode;
  365. goto Ret;
  366. }
  367. TEST_CASE(pCardData->pfnCardCreateFile(
  368. pCardData,
  369. wszCONTAINER_MAP_FILE_FULL_PATH,
  370. EveryoneReadUserWriteAc));
  371. TEST_CASE(pCardData->pfnCardWriteFile(
  372. pCardData,
  373. wszCARD_IDENTIFIER_FILE_FULL_PATH,
  374. 0,
  375. rgbContents,
  376. sizeof(rgbContents)));
  377. Ret:
  378. return dwSts;
  379. }
  380. //
  381. // Find any card present in an attached reader using "minimal" scarddlg UI
  382. //
  383. DWORD GetCardHandleViaUI(
  384. IN SCARDCONTEXT hSCardContext,
  385. OUT SCARDHANDLE *phSCardHandle,
  386. IN DWORD cchMatchedCard,
  387. OUT LPWSTR wszMatchedCard,
  388. IN DWORD cchMatchedReader,
  389. OUT LPWSTR wszMatchedReader)
  390. {
  391. OPENCARDNAME_EXW ocnx;
  392. DWORD dwSts = ERROR_SUCCESS;
  393. memset(&ocnx, 0, sizeof(ocnx));
  394. ocnx.dwStructSize = sizeof(ocnx);
  395. ocnx.hSCardContext = hSCardContext;
  396. ocnx.lpstrCard = wszMatchedCard;
  397. ocnx.nMaxCard = cchMatchedCard;
  398. ocnx.lpstrRdr = wszMatchedReader;
  399. ocnx.nMaxRdr = cchMatchedReader;
  400. ocnx.dwShareMode = SCARD_SHARE_SHARED;
  401. ocnx.dwPreferredProtocols = SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1;
  402. ocnx.dwFlags = SC_DLG_MINIMAL_UI;
  403. TEST_CASE(SCardUIDlgSelectCardW(&ocnx));
  404. *phSCardHandle = ocnx.hCardHandle;
  405. Ret:
  406. return dwSts;
  407. }
  408. int _cdecl main(int argc, char * argv[])
  409. {
  410. PCARD_DATA pCardData = NULL;
  411. DWORD dwSts = ERROR_SUCCESS;
  412. PFN_CARD_ACQUIRE_CONTEXT pfnCardAcquireContext = NULL;
  413. SCARDCONTEXT hSCardContext = 0;
  414. SCARDHANDLE hSCardHandle = 0;
  415. LPWSTR mszReaders = NULL;
  416. DWORD cchReaders = SCARD_AUTOALLOCATE;
  417. LPWSTR mszCards = NULL;
  418. DWORD cchCards = SCARD_AUTOALLOCATE;
  419. DWORD dwActiveProtocol = 0;
  420. DWORD dwState = 0;
  421. BYTE rgbAtr [32];
  422. DWORD cbAtr = sizeof(rgbAtr);
  423. LPWSTR pszProvider = NULL;
  424. DWORD cchProvider = SCARD_AUTOALLOCATE;
  425. HMODULE hMod = INVALID_HANDLE_VALUE;
  426. WCHAR wszMatchedCard [MAX_PATH];
  427. WCHAR wszMatchedReader [MAX_PATH];
  428. BOOL fTransaction = FALSE;
  429. memset(rgbAtr, 0, sizeof(rgbAtr));
  430. //
  431. // Initialization
  432. //
  433. TEST_CASE(SCardEstablishContext(
  434. SCARD_SCOPE_USER, NULL, NULL, &hSCardContext));
  435. dwSts = GetCardHandleViaUI(
  436. hSCardContext,
  437. &hSCardHandle,
  438. MAX_PATH,
  439. wszMatchedCard,
  440. MAX_PATH,
  441. wszMatchedReader);
  442. if (ERROR_SUCCESS != dwSts)
  443. goto Ret;
  444. mszReaders = NULL;
  445. cchReaders = SCARD_AUTOALLOCATE;
  446. TEST_CASE(SCardStatusW(
  447. hSCardHandle,
  448. (LPWSTR) (&mszReaders),
  449. &cchReaders,
  450. &dwState,
  451. &dwActiveProtocol,
  452. rgbAtr,
  453. &cbAtr));
  454. TEST_CASE(SCardListCardsW(
  455. hSCardContext,
  456. rgbAtr,
  457. NULL,
  458. 0,
  459. (LPWSTR) (&mszCards),
  460. &cchCards));
  461. TEST_CASE(SCardGetCardTypeProviderNameW(
  462. hSCardContext,
  463. mszCards,
  464. SCARD_PROVIDER_CARD_MODULE,
  465. (LPWSTR) (&pszProvider),
  466. &cchProvider));
  467. hMod = LoadLibraryW(pszProvider);
  468. if (INVALID_HANDLE_VALUE == hMod)
  469. {
  470. wprintf(L"LoadLibrary %s", pszProvider);
  471. dwSts = GetLastError();
  472. goto Ret;
  473. }
  474. pfnCardAcquireContext =
  475. (PFN_CARD_ACQUIRE_CONTEXT) GetProcAddress(
  476. hMod,
  477. "CardAcquireContext");
  478. if (NULL == pfnCardAcquireContext)
  479. {
  480. printf("GetProcAddress");
  481. dwSts = GetLastError();
  482. goto Ret;
  483. }
  484. pCardData = (PCARD_DATA) CspAllocH(sizeof(CARD_DATA));
  485. if (NULL == pCardData)
  486. {
  487. dwSts = ERROR_NOT_ENOUGH_MEMORY;
  488. goto Ret;
  489. }
  490. pCardData->pbAtr = rgbAtr;
  491. pCardData->cbAtr = cbAtr;
  492. pCardData->pwszCardName = mszCards;
  493. pCardData->dwVersion = CARD_DATA_CURRENT_VERSION;
  494. pCardData->pfnCspAlloc = CspAllocH;
  495. pCardData->pfnCspReAlloc = CspReAllocH;
  496. pCardData->pfnCspFree = CspFreeH;
  497. pCardData->pfnCspCacheAddFile = CspCacheAddFile;
  498. pCardData->pfnCspCacheDeleteFile = CspCacheDeleteFile;
  499. pCardData->pfnCspCacheLookupFile = CspCacheLookupFile;
  500. pCardData->hScard = hSCardHandle;
  501. hSCardHandle = 0;
  502. // First, connect to the card
  503. dwSts = pfnCardAcquireContext(pCardData, 0);
  504. switch (dwSts)
  505. {
  506. case ERROR_SUCCESS:
  507. // Keep going
  508. break;
  509. case ERROR_REVISION_MISMATCH:
  510. MessageBoxEx(
  511. GetDesktopWindow(),
  512. wszCARDMOD_VERSION_ERROR,
  513. NULL,
  514. MB_ICONWARNING | MB_OK | MB_TASKMODAL,
  515. 0);
  516. // fall through
  517. default:
  518. goto Ret;
  519. }
  520. TEST_CASE(SCardBeginTransaction(pCardData->hScard));
  521. fTransaction = TRUE;
  522. TEST_CASE(InitializeCardCacheFile(pCardData));
  523. TEST_CASE(InitializeCardIDFile(pCardData));
  524. TEST_CASE(InitializePersonalDataFile(pCardData));
  525. TEST_CASE(InitializeCardCSPApplication(pCardData));
  526. // Deauthenticate
  527. pCardData->pfnCardDeauthenticate(
  528. pCardData,
  529. wszCARD_USER_ADMIN,
  530. 0);
  531. pCardData->pfnCardDeauthenticate(
  532. pCardData,
  533. wszCARD_USER_USER,
  534. 0);
  535. // Cleanup the card context
  536. TEST_CASE(pCardData->pfnCardDeleteContext(pCardData));
  537. Ret:
  538. if (fTransaction)
  539. SCardEndTransaction(pCardData->hScard, SCARD_RESET_CARD);
  540. if (mszCards)
  541. SCardFreeMemory(hSCardContext, mszCards);
  542. if (mszReaders)
  543. SCardFreeMemory(hSCardContext, mszReaders);
  544. if (pszProvider)
  545. SCardFreeMemory(hSCardContext, pszProvider);
  546. if (hSCardHandle)
  547. SCardDisconnect(hSCardHandle, SCARD_RESET_CARD);
  548. if (pCardData)
  549. {
  550. if (pCardData->hScard)
  551. SCardDisconnect(pCardData->hScard, SCARD_RESET_CARD);
  552. CspFreeH(pCardData);
  553. pCardData = NULL;
  554. }
  555. if (hSCardContext)
  556. SCardReleaseContext(hSCardContext);
  557. if (ERROR_SUCCESS != dwSts)
  558. {
  559. printf(" failed, 0x%x\n", dwSts);
  560. exit(1);
  561. }
  562. else
  563. {
  564. printf("Success.\n");
  565. return 0;
  566. }
  567. }