Source code of Windows XP (NT5)
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.

862 lines
18 KiB

  1. #ifdef SMARTCARD_DOGFOOD
  2. #include "msgina.h"
  3. #include <stdio.h>
  4. #include <Wincrypt.h>
  5. #include "tchar.h"
  6. #include "authmon.h"
  7. #include "sql.h"
  8. #include "sqlext.h"
  9. #include "sqltypes.h"
  10. #include "odbcss.h"
  11. #define SQL_CALL_SUCCESS(status) (status == SQL_SUCCESS || status == SQL_SUCCESS_WITH_INFO)
  12. #if DBG || DEBUG
  13. #define DebugPrint(a) _DebugPrint a
  14. void
  15. __cdecl
  16. _DebugPrint(
  17. LPCTSTR szFormat,
  18. ...
  19. )
  20. {
  21. TCHAR szBuffer[512];
  22. va_list ap;
  23. va_start(ap, szFormat);
  24. _vstprintf(szBuffer, szFormat, ap);
  25. OutputDebugString(szBuffer);
  26. }
  27. int debugLine = __LINE__;
  28. #define DEBUG_MARKER debugLine = __LINE__
  29. #else
  30. #define DebugPrint(a)
  31. #define DEBUG_MARKER
  32. #endif
  33. typedef struct _AUTH_DATA {
  34. HANDLE hHeap;
  35. BOOL bConsole;
  36. WCHAR szUser[64];
  37. AUTH_OPERATION AuthOperation;
  38. WCHAR szReader[32];
  39. WCHAR szCard[48];
  40. ULONG StopWatch;
  41. NTSTATUS Status;
  42. WCHAR szDomain[32];
  43. WCHAR szDC[32];
  44. BYTE pCertBlob[4096];
  45. ULONG uCertBlob;
  46. SQLWCHAR szSQLServer[64];
  47. SQLWCHAR szSQLUser[64];
  48. SQLWCHAR szSQLPassword[64];
  49. SQLWCHAR szSQLDatabase[64];
  50. } AUTH_DATA, *PAUTH_DATA;
  51. DWORD
  52. WINAPI
  53. WriteLogonData(
  54. PAUTH_DATA pAuthData
  55. )
  56. {
  57. SQLRETURN RetCode = SQL_SUCCESS;
  58. HSTMT hStmt = NULL;
  59. HENV hEnv = NULL, hDbc = NULL;
  60. BOOL bConnected = FALSE;
  61. SQLSMALLINT cbConnect = 0;
  62. static SQLWCHAR szConnect[256], szInConnect[256];
  63. __try {
  64. RetCode = SQLAllocHandle(
  65. SQL_HANDLE_ENV,
  66. SQL_NULL_HANDLE,
  67. &hEnv
  68. );
  69. if(!SQL_CALL_SUCCESS(RetCode)) {
  70. DEBUG_MARKER;
  71. __leave;
  72. }
  73. RetCode = SQLSetEnvAttr(
  74. hEnv,
  75. SQL_ATTR_ODBC_VERSION,
  76. (SQLPOINTER) SQL_OV_ODBC3,
  77. SQL_IS_INTEGER
  78. );
  79. if(!SQL_CALL_SUCCESS(RetCode)) {
  80. DEBUG_MARKER;
  81. __leave;
  82. }
  83. RetCode = SQLAllocHandle(
  84. SQL_HANDLE_DBC,
  85. hEnv,
  86. &hDbc
  87. );
  88. if(!SQL_CALL_SUCCESS(RetCode)) {
  89. DEBUG_MARKER;
  90. __leave;
  91. }
  92. RetCode = SQLSetConnectAttr(
  93. hDbc,
  94. SQL_ATTR_LOGIN_TIMEOUT,
  95. (SQLPOINTER) 120,
  96. SQL_IS_UINTEGER
  97. );
  98. if(!SQL_CALL_SUCCESS(RetCode)) {
  99. DEBUG_MARKER;
  100. __leave;
  101. }
  102. RetCode = SQLSetConnectAttr(
  103. hDbc,
  104. SQL_COPT_SS_INTEGRATED_SECURITY,
  105. (SQLPOINTER) SQL_IS_OFF,
  106. SQL_IS_INTEGER
  107. );
  108. if(!SQL_CALL_SUCCESS(RetCode)) {
  109. DEBUG_MARKER;
  110. __leave;
  111. }
  112. _snwprintf(
  113. szInConnect,
  114. sizeof(szInConnect) / sizeof(SQLWCHAR),
  115. (const wchar_t *) L"DRIVER=SQL Server;Server=%s;UID=%s;PWD=%s;DATABASE=%s",
  116. pAuthData->szSQLServer,
  117. pAuthData->szSQLUser,
  118. pAuthData->szSQLPassword,
  119. pAuthData->szSQLDatabase
  120. );
  121. RetCode = SQLDriverConnect(
  122. hDbc,
  123. NULL,
  124. szInConnect,
  125. SQL_NTS,
  126. szConnect,
  127. sizeof(szConnect) / sizeof(szConnect[0]),
  128. &cbConnect,
  129. SQL_DRIVER_NOPROMPT
  130. );
  131. if(!SQL_CALL_SUCCESS(RetCode)) {
  132. DEBUG_MARKER;
  133. __leave;
  134. }
  135. bConnected = TRUE;
  136. RetCode = SQLAllocHandle(
  137. SQL_HANDLE_STMT,
  138. hDbc,
  139. &hStmt
  140. );
  141. if(!SQL_CALL_SUCCESS(RetCode)) {
  142. DEBUG_MARKER;
  143. __leave;
  144. }
  145. static WCHAR szStatement[] =
  146. L"INSERT INTO AuthMonitor ("
  147. L"BUILDLAB,"
  148. L"CARD,"
  149. L"CERTISSUER,"
  150. L"DC,"
  151. L"DOMAIN,"
  152. L"MACHINENAME,"
  153. L"READER,"
  154. L"SESSION,"
  155. L"STATUS,"
  156. L"STOPWATCH,"
  157. L"TIMESTAMP,"
  158. L"UNLOCK,"
  159. L"USERNAME"
  160. L") VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)";
  161. RetCode = SQLPrepare(
  162. hStmt,
  163. szStatement,
  164. SQL_NTS
  165. );
  166. if(!SQL_CALL_SUCCESS(RetCode)) {
  167. DEBUG_MARKER;
  168. __leave;
  169. }
  170. SQLUSMALLINT iParamNo = 1;
  171. //
  172. // BUILDLAB
  173. //
  174. HKEY hKey;
  175. DWORD dwStatus = RegOpenKeyEx(
  176. HKEY_LOCAL_MACHINE,
  177. L"Software\\Microsoft\\Windows NT\\CurrentVersion",
  178. 0,
  179. KEY_READ,
  180. &hKey
  181. );
  182. static WCHAR szBuild[MAX_PATH];
  183. DWORD cbBuild = sizeof(szBuild);
  184. wcscpy(szBuild, L"");
  185. if (dwStatus == ERROR_SUCCESS) {
  186. DWORD dwType = REG_SZ;
  187. dwStatus = RegQueryValueEx(
  188. hKey,
  189. L"BuildLab",
  190. 0,
  191. &dwType,
  192. (LPBYTE) szBuild,
  193. &cbBuild
  194. );
  195. if (dwStatus != ERROR_SUCCESS) {
  196. dwStatus = RegQueryValueEx(
  197. hKey,
  198. L"CurrentBuildNumber",
  199. 0,
  200. &dwType,
  201. (LPBYTE) szBuild,
  202. &cbBuild
  203. );
  204. }
  205. RegCloseKey(hKey);
  206. }
  207. SQLLEN cbBuildLab = SQL_NTS;
  208. SQLBindParameter(
  209. hStmt,
  210. iParamNo++,
  211. SQL_PARAM_INPUT,
  212. SQL_C_WCHAR,
  213. SQL_WCHAR,
  214. 64,
  215. 0,
  216. szBuild,
  217. 0,
  218. &cbBuildLab
  219. );
  220. //
  221. // CARD
  222. //
  223. SQLLEN cbCard = SQL_NTS;
  224. SQLBindParameter(
  225. hStmt,
  226. iParamNo++,
  227. SQL_PARAM_INPUT,
  228. SQL_C_WCHAR,
  229. SQL_WCHAR,
  230. 48,
  231. 0,
  232. pAuthData->szCard,
  233. 0,
  234. &cbCard
  235. );
  236. //
  237. // CERTISSUER
  238. //
  239. PCERT_CONTEXT pCert = (PCERT_CONTEXT) CertCreateCertificateContext(
  240. X509_ASN_ENCODING,
  241. pAuthData->pCertBlob,
  242. pAuthData->uCertBlob
  243. );
  244. WCHAR szIssuer[64] = L"";
  245. if (pCert) {
  246. // intentionally ignore errors
  247. CertGetNameString(
  248. pCert,
  249. CERT_NAME_FRIENDLY_DISPLAY_TYPE,
  250. CERT_NAME_ISSUER_FLAG,
  251. NULL,
  252. szIssuer,
  253. sizeof(szIssuer) / sizeof(szIssuer[0])
  254. );
  255. CertFreeCertificateContext(pCert);
  256. }
  257. SQLLEN cbIssuer = SQL_NTS;
  258. SQLBindParameter(
  259. hStmt,
  260. iParamNo++,
  261. SQL_PARAM_INPUT,
  262. SQL_C_WCHAR,
  263. SQL_WCHAR,
  264. 64,
  265. 0,
  266. szIssuer,
  267. 0,
  268. &cbIssuer
  269. );
  270. //
  271. // DC
  272. //
  273. PDOMAIN_CONTROLLER_INFO pDCInfo = NULL;
  274. dwStatus = DsGetDcName(
  275. NULL,
  276. pAuthData->szDomain,
  277. NULL,
  278. NULL,
  279. DS_IS_FLAT_NAME | DS_RETURN_FLAT_NAME,
  280. &pDCInfo
  281. );
  282. static WCHAR szDC[MAX_PATH];
  283. wcscpy(szDC, L"");
  284. static WCHAR szDomain[sizeof(pAuthData->szDomain)];
  285. wcscpy(szDomain, L"");
  286. if (dwStatus == ERROR_SUCCESS) {
  287. wcscpy(szDC, pDCInfo->DomainControllerName);
  288. wcscpy(szDomain, pDCInfo->DomainName);
  289. NetApiBufferFree(pDCInfo);
  290. }
  291. SQLLEN cbDC = SQL_NTS;
  292. SQLBindParameter(
  293. hStmt,
  294. iParamNo++,
  295. SQL_PARAM_INPUT,
  296. SQL_C_WCHAR,
  297. SQL_WCHAR,
  298. 32,
  299. 0,
  300. szDC,
  301. 0,
  302. &cbDC
  303. );
  304. //
  305. // DOMAIN
  306. //
  307. if (pAuthData->szDomain[0] == L'\0') {
  308. PWCHAR pszPos;
  309. if (pszPos = wcschr(pAuthData->szUser, L'@')) {
  310. wcscpy(szDomain, pszPos + 1);
  311. if (pszPos = wcschr(szDomain, L'.')) {
  312. *pszPos = L'\0';
  313. }
  314. }
  315. } else {
  316. wcscpy(szDomain, pAuthData->szDomain);
  317. }
  318. SQLLEN cbDomain = SQL_NTS;
  319. SQLBindParameter(
  320. hStmt,
  321. iParamNo++,
  322. SQL_PARAM_INPUT,
  323. SQL_C_WCHAR,
  324. SQL_WCHAR,
  325. 32,
  326. 0,
  327. szDomain,
  328. 0,
  329. &cbDomain
  330. );
  331. //
  332. // MACHINENAME
  333. //
  334. static WCHAR szMachineName[MAX_PATH];
  335. wcscpy(szMachineName, L"");
  336. DWORD dwMachineName = sizeof(szMachineName)/sizeof(szMachineName[0]);
  337. // intentionally ignore any failures
  338. GetComputerNameEx(
  339. ComputerNameDnsHostname,
  340. szMachineName,
  341. &dwMachineName
  342. );
  343. SQLLEN cbMachineName = SQL_NTS;
  344. SQLBindParameter(
  345. hStmt,
  346. iParamNo++,
  347. SQL_PARAM_INPUT,
  348. SQL_C_WCHAR,
  349. SQL_WCHAR,
  350. 64,
  351. 0,
  352. szMachineName,
  353. 0,
  354. &cbMachineName
  355. );
  356. //
  357. // READER
  358. //
  359. SQLLEN cbReader = SQL_NTS;
  360. SQLBindParameter(
  361. hStmt,
  362. iParamNo++,
  363. SQL_PARAM_INPUT,
  364. SQL_C_WCHAR,
  365. SQL_WCHAR,
  366. 32,
  367. 0,
  368. pAuthData->szReader,
  369. 0,
  370. &cbReader
  371. );
  372. //
  373. // SESSION
  374. //
  375. SQLLEN cbSession = 0;
  376. BOOL bSession = !pAuthData->bConsole;
  377. SQLBindParameter(
  378. hStmt,
  379. iParamNo++,
  380. SQL_PARAM_INPUT,
  381. SQL_C_SHORT,
  382. SQL_SMALLINT,
  383. 0,
  384. 0,
  385. &bSession,
  386. 0,
  387. &cbSession
  388. );
  389. //
  390. // STATUS
  391. //
  392. SQLLEN cbStatus = 0;
  393. SQLBindParameter(
  394. hStmt,
  395. iParamNo++,
  396. SQL_PARAM_INPUT,
  397. SQL_C_LONG,
  398. SQL_INTEGER,
  399. 0,
  400. 0,
  401. &pAuthData->Status,
  402. 0,
  403. &cbStatus
  404. );
  405. //
  406. // STOPWATCH
  407. //
  408. SQLLEN cbStopWatch = 0;
  409. SQLBindParameter(
  410. hStmt,
  411. iParamNo++,
  412. SQL_PARAM_INPUT,
  413. SQL_C_ULONG,
  414. SQL_INTEGER,
  415. 0,
  416. 0,
  417. &pAuthData->StopWatch,
  418. 0,
  419. &cbStopWatch
  420. );
  421. //
  422. // TIMESTAMP
  423. //
  424. TIMESTAMP_STRUCT TimeStamp;
  425. SYSTEMTIME SystemTime;
  426. GetLocalTime(&SystemTime);
  427. TimeStamp.day = SystemTime.wDay;
  428. TimeStamp.month = SystemTime.wMonth;
  429. TimeStamp.year = SystemTime.wYear;
  430. TimeStamp.hour = SystemTime.wHour;
  431. TimeStamp.minute = SystemTime.wMinute;
  432. TimeStamp.second = SystemTime.wSecond;
  433. TimeStamp.fraction = 0;
  434. SQLLEN cbTimeStamp = 0;
  435. SQLBindParameter(
  436. hStmt,
  437. iParamNo++,
  438. SQL_PARAM_INPUT,
  439. SQL_C_TIMESTAMP,
  440. SQL_TIMESTAMP,
  441. 19,
  442. 0,
  443. &TimeStamp,
  444. 0,
  445. &cbTimeStamp
  446. );
  447. //
  448. // UNLOCK
  449. //
  450. SQLLEN cbAuthOperation = 0;
  451. SQLBindParameter(
  452. hStmt,
  453. iParamNo++,
  454. SQL_PARAM_INPUT,
  455. SQL_C_SHORT,
  456. SQL_SMALLINT,
  457. 0,
  458. 0,
  459. &pAuthData->AuthOperation,
  460. 0,
  461. &cbAuthOperation
  462. );
  463. //
  464. // USERNAME
  465. //
  466. static WCHAR szUser[sizeof(pAuthData->szUser)];
  467. wcscpy(szUser, pAuthData->szUser);
  468. if (PWCHAR pszPos = wcschr(szUser, L'@')) {
  469. *pszPos = L'\0';
  470. }
  471. SQLLEN cbUserName = SQL_NTS;
  472. SQLBindParameter(
  473. hStmt,
  474. iParamNo++,
  475. SQL_PARAM_INPUT,
  476. SQL_C_WCHAR,
  477. SQL_WCHAR,
  478. 64,
  479. 0,
  480. szUser,
  481. 0,
  482. &cbUserName
  483. );
  484. RetCode = SQLExecute(hStmt);
  485. DEBUG_MARKER;
  486. }
  487. __finally {
  488. }
  489. if (!SQL_CALL_SUCCESS(RetCode)) {
  490. SDWORD swError;
  491. static SQLWCHAR szErrorMsg[SQL_MAX_MESSAGE_LENGTH];
  492. SWORD swErrorMsg;
  493. SQLWCHAR szSQLState[50];
  494. SQLError(
  495. hEnv,
  496. hDbc,
  497. hStmt,
  498. szSQLState,
  499. &swError,
  500. szErrorMsg,
  501. SQL_MAX_MESSAGE_LENGTH - 1,
  502. &swErrorMsg
  503. );
  504. DebugPrint(
  505. (L"AuthMonitor: Error WriteLogonData (%d) - %s (%s)\n [%s]",
  506. debugLine,
  507. szErrorMsg,
  508. szSQLState,
  509. szInConnect)
  510. );
  511. }
  512. if (hStmt) {
  513. SQLFreeHandle(SQL_HANDLE_STMT, hStmt);
  514. hStmt = NULL;
  515. }
  516. if (hDbc) {
  517. if (bConnected) {
  518. SQLDisconnect(hDbc);
  519. bConnected = FALSE;
  520. }
  521. SQLFreeHandle(SQL_HANDLE_DBC, hDbc);
  522. hDbc = NULL;
  523. }
  524. if (hEnv) {
  525. SQLFreeHandle(SQL_HANDLE_ENV, hEnv);
  526. hEnv = NULL;
  527. }
  528. HeapFree(pAuthData->hHeap, 0, pAuthData);
  529. DebugPrint(
  530. (L"AuthMonitor: WriteLogonData %s\n",
  531. (SQL_CALL_SUCCESS(RetCode) ? L"succeeded" : L"failed"))
  532. );
  533. return 0;
  534. }
  535. EXTERN_C HANDLE AuthMonitor(
  536. AUTH_OPERATION AuthOper,
  537. BOOL Console,
  538. PUNICODE_STRING User,
  539. PUNICODE_STRING Domain,
  540. PWSTR Card,
  541. PWSTR Reader,
  542. PKERB_SMART_CARD_PROFILE Profile,
  543. DWORD Timer,
  544. NTSTATUS Status
  545. )
  546. {
  547. PAUTH_DATA pAuthData = NULL;
  548. HANDLE hHeap = NULL;
  549. HANDLE hThread = NULL;
  550. HKEY hKey = NULL;
  551. LONG lResult = RegOpenKeyEx(
  552. HKEY_LOCAL_MACHINE,
  553. TEXT("SOFTWARE\\Policies\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon"),
  554. 0,
  555. KEY_READ,
  556. &hKey
  557. );
  558. if (lResult != ERROR_SUCCESS) {
  559. return NULL;
  560. }
  561. __try {
  562. DWORD dwSize, dwType, dwEnabled = 0;
  563. dwSize = sizeof(dwEnabled);
  564. lResult = RegQueryValueEx(
  565. hKey,
  566. TEXT("AuthMonEnabled"),
  567. 0,
  568. &dwType,
  569. (PBYTE) &dwEnabled,
  570. &dwSize
  571. );
  572. if (lResult != ERROR_SUCCESS || dwType != REG_DWORD || dwEnabled == 0) {
  573. DEBUG_MARKER;
  574. __leave;
  575. }
  576. hHeap = GetProcessHeap();
  577. if (hHeap == NULL) {
  578. DEBUG_MARKER;
  579. __leave;
  580. }
  581. pAuthData = (PAUTH_DATA) HeapAlloc(hHeap, HEAP_ZERO_MEMORY, sizeof(AUTH_DATA));
  582. if (pAuthData == NULL) {
  583. DEBUG_MARKER;
  584. __leave;
  585. }
  586. dwSize = sizeof(pAuthData->szSQLServer);
  587. lResult = RegQueryValueEx(
  588. hKey,
  589. TEXT("AuthMonServer"),
  590. 0,
  591. &dwType,
  592. (PBYTE) &pAuthData->szSQLServer,
  593. &dwSize
  594. );
  595. if (lResult != ERROR_SUCCESS || dwType != REG_SZ) {
  596. DEBUG_MARKER;
  597. __leave;
  598. }
  599. dwSize = sizeof(pAuthData->szSQLUser);
  600. lResult = RegQueryValueEx(
  601. hKey,
  602. TEXT("AuthMonUser"),
  603. 0,
  604. &dwType,
  605. (PBYTE) &pAuthData->szSQLUser,
  606. &dwSize
  607. );
  608. if (lResult != ERROR_SUCCESS || dwType != REG_SZ) {
  609. DEBUG_MARKER;
  610. __leave;
  611. }
  612. dwSize = sizeof(pAuthData->szSQLPassword);
  613. lResult = RegQueryValueEx(
  614. hKey,
  615. TEXT("AuthMonPassword"),
  616. 0,
  617. &dwType,
  618. (PBYTE) &pAuthData->szSQLPassword,
  619. &dwSize
  620. );
  621. if (lResult != ERROR_SUCCESS || dwType != REG_SZ) {
  622. DEBUG_MARKER;
  623. __leave;
  624. }
  625. dwSize = sizeof(pAuthData->szSQLDatabase);
  626. lResult = RegQueryValueEx(
  627. hKey,
  628. TEXT("AuthMonDatabase"),
  629. 0,
  630. &dwType,
  631. (PBYTE) &pAuthData->szSQLDatabase,
  632. &dwSize
  633. );
  634. if (lResult != ERROR_SUCCESS || dwType != REG_SZ) {
  635. DEBUG_MARKER;
  636. __leave;
  637. }
  638. pAuthData->hHeap = hHeap;
  639. pAuthData->AuthOperation = AuthOper;
  640. pAuthData->bConsole = Console;
  641. memcpy(pAuthData->szDomain, Domain->Buffer, Domain->Length);
  642. memcpy(pAuthData->szUser, User->Buffer, User->Length);
  643. if (Card) {
  644. wcscpy(pAuthData->szCard, Card);
  645. }
  646. if (Reader) {
  647. wcscpy(pAuthData->szReader, Reader);
  648. }
  649. if (Profile && Profile->CertificateData && (Profile->CertificateSize < sizeof(pAuthData->pCertBlob))) {
  650. memcpy(
  651. pAuthData->pCertBlob,
  652. Profile->CertificateData,
  653. Profile->CertificateSize
  654. );
  655. pAuthData->uCertBlob = Profile->CertificateSize;
  656. }
  657. pAuthData->StopWatch = Timer;
  658. pAuthData->Status = Status;
  659. hThread = CreateThread(
  660. NULL,
  661. 0,
  662. (LPTHREAD_START_ROUTINE) WriteLogonData,
  663. pAuthData,
  664. 0,
  665. NULL
  666. );
  667. DEBUG_MARKER;
  668. }
  669. __finally {
  670. if (hKey) {
  671. RegCloseKey(hKey);
  672. }
  673. if (hThread == NULL) {
  674. if (pAuthData) {
  675. HeapFree(hHeap, 0, pAuthData);
  676. }
  677. DebugPrint((L"AuthMonitor: Error line %d\n", debugLine));
  678. }
  679. #ifndef TEST
  680. else
  681. {
  682. CloseHandle(hThread);
  683. hThread = NULL;
  684. }
  685. #endif
  686. }
  687. return hThread;
  688. }
  689. #ifdef TEST
  690. _cdecl main()
  691. {
  692. UNICODE_STRING Domain, User;
  693. HANDLE hThread = NULL;
  694. RtlInitUnicodeString(
  695. &Domain,
  696. L""
  697. );
  698. RtlInitUnicodeString(
  699. &User,
  700. L"Klaus"
  701. );
  702. hThread = AuthMonitor(
  703. AuthOperLogon,
  704. 0,
  705. &User,
  706. &Domain,
  707. L"Gemplus",
  708. L"Utimaco",
  709. NULL,
  710. 10,
  711. 0
  712. );
  713. if (hThread) {
  714. WaitForSingleObjectEx(hThread, INFINITE, FALSE);
  715. }
  716. }
  717. #endif
  718. #endif