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.

1362 lines
36 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1993.
  5. //
  6. // File: events.cxx
  7. //
  8. // Contents:
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 1-03-95 RichardW Created
  15. //
  16. //----------------------------------------------------------------------------
  17. #include <kerb.hxx>
  18. #include <kerbp.h>
  19. #include "krbevent.h"
  20. #include "kerbevt.h"
  21. #include <limits.h>
  22. #ifdef DEBUG_SUPPORT
  23. static TCHAR THIS_FILE[]=TEXT(__FILE__);
  24. #endif
  25. HANDLE KerbEventLogHandle = NULL;
  26. WCHAR KerbEventSourceName[] = L"Kerberos";
  27. LONG KerbUdpTimeoutEvents = 0;
  28. TimeStamp KerbUdpNextUpdate;
  29. RTL_RESOURCE KerbUdpLock;
  30. #define UDPTIMEOUT_LOGGING_THRESHHOLD 20
  31. #define UDPTIMEOUT_LOGGING_INTERVAL 30
  32. #define KerbWriteLockUdpStats() RtlAcquireResourceExclusive(&KerbUdpLock, TRUE)
  33. #define KerbReadLockUdpStats() RtlAcquireResourceShared(&KerbUdpLock, TRUE)
  34. #define KerbReadToWriteLockUdpStats() RtlConvertSharedToExclusive(&KerbUdpLock);
  35. #define KerbUnlockUdpStats() RtlReleaseResource(&KerbUdpLock)
  36. //+-------------------------------------------------------------------------
  37. //
  38. // Function: KerbInitUdpStatistics
  39. //
  40. // Synopsis: returns a string from the data segment pointing to the name
  41. // of an error
  42. //
  43. // Effects:
  44. //
  45. // Arguments:
  46. //
  47. // Requires:
  48. //
  49. // Returns:
  50. //
  51. // Notes:
  52. //
  53. //
  54. //-
  55. NTSTATUS
  56. KerbInitUdpStatistics()
  57. {
  58. NTSTATUS Status = STATUS_SUCCESS;
  59. TimeStamp CurrentTime, Delta;
  60. GetSystemTimeAsFileTime((LPFILETIME) &CurrentTime );
  61. KerbSetTimeInMinutes(&Delta, UDPTIMEOUT_LOGGING_INTERVAL);
  62. __try
  63. {
  64. RtlInitializeResource(&KerbUdpLock);
  65. }
  66. __except(EXCEPTION_EXECUTE_HANDLER)
  67. {
  68. Status = STATUS_INSUFFICIENT_RESOURCES;
  69. return Status;
  70. }
  71. KerbWriteLockUdpStats();
  72. KerbSetTime(&KerbUdpNextUpdate,(KerbGetTime(CurrentTime) + KerbGetTime(Delta)));
  73. KerbUdpTimeoutEvents = 0;
  74. KerbUnlockUdpStats();
  75. return Status;
  76. }
  77. //+-------------------------------------------------------------------------
  78. //
  79. // Function: KerbErrorToString
  80. //
  81. // Synopsis: returns a string from the data segment pointing to the name
  82. // of an error
  83. //
  84. // Effects:
  85. //
  86. // Arguments:
  87. //
  88. // Requires:
  89. //
  90. // Returns:
  91. //
  92. // Notes:
  93. //
  94. //
  95. //--------------------------------------------------------------------------
  96. LPWSTR
  97. KerbErrorToString(
  98. IN KERBERR KerbErr
  99. )
  100. {
  101. LPWSTR String;
  102. switch (KerbErr)
  103. {
  104. case KDC_ERR_NONE : String = L"KDC_ERR_NONE"; break;
  105. case KDC_ERR_NAME_EXP : String = L"KDC_ERR_NAME_EXP"; break;
  106. case KDC_ERR_SERVICE_EXP : String = L"KDC_ERR_SERVICE_EXP"; break;
  107. case KDC_ERR_BAD_PVNO : String = L"KDC_ERR_BAD_PVNO"; break;
  108. case KDC_ERR_C_OLD_MAST_KVNO : String = L"KDC_ERR_C_OLD_MAST_KVNO"; break;
  109. case KDC_ERR_S_OLD_MAST_KVNO : String = L"KDC_ERR_S_OLD_MAST_KVNO"; break;
  110. case KDC_ERR_C_PRINCIPAL_UNKNOWN : String = L"KDC_ERR_C_PRINCIPAL_UNKNOWN"; break;
  111. case KDC_ERR_S_PRINCIPAL_UNKNOWN : String = L" KDC_ERR_S_PRINCIPAL_UNKNOWN"; break;
  112. case KDC_ERR_PRINCIPAL_NOT_UNIQUE : String = L"KDC_ERR_PRINCIPAL_NOT_UNIQUE"; break;
  113. case KDC_ERR_NULL_KEY : String = L"KDC_ERR_NULL_KEY"; break;
  114. case KDC_ERR_CANNOT_POSTDATE : String = L"KDC_ERR_CANNOT_POSTDATE"; break;
  115. case KDC_ERR_NEVER_VALID : String = L"KDC_ERR_NEVER_VALID"; break;
  116. case KDC_ERR_POLICY : String = L"KDC_ERR_POLICY"; break;
  117. case KDC_ERR_BADOPTION : String = L"KDC_ERR_BADOPTION"; break;
  118. case KDC_ERR_ETYPE_NOTSUPP : String = L"KDC_ERR_ETYPE_NOTSUPP"; break;
  119. case KDC_ERR_SUMTYPE_NOSUPP : String = L"KDC_ERR_SUMTYPE_NOSUPP"; break;
  120. case KDC_ERR_PADATA_TYPE_NOSUPP : String = L"KDC_ERR_PADATA_TYPE_NOSUPP"; break;
  121. case KDC_ERR_TRTYPE_NO_SUPP : String = L"KDC_ERR_TRTYPE_NO_SUPP"; break;
  122. case KDC_ERR_CLIENT_REVOKED : String = L"KDC_ERR_CLIENT_REVOKED"; break;
  123. case KDC_ERR_SERVICE_REVOKED : String = L"KDC_ERR_SERVICE_REVOKED"; break;
  124. case KDC_ERR_TGT_REVOKED : String = L"KDC_ERR_TGT_REVOKED"; break;
  125. case KDC_ERR_CLIENT_NOTYET : String = L"KDC_ERR_CLIENT_NOTYET"; break;
  126. case KDC_ERR_SERVICE_NOTYET : String = L"KDC_ERR_SERVICE_NOTYET"; break;
  127. case KDC_ERR_KEY_EXPIRED : String = L"KDC_ERR_KEY_EXPIRED"; break;
  128. case KDC_ERR_PREAUTH_FAILED : String = L"KDC_ERR_PREAUTH_FAILED"; break;
  129. case KDC_ERR_PREAUTH_REQUIRED : String = L"KDC_ERR_PREAUTH_REQUIRED"; break;
  130. case KDC_ERR_SERVER_NOMATCH : String = L"KDC_ERR_SERVER_NOMATCH"; break;
  131. case KDC_ERR_SVC_UNAVAILABLE : String = L"KDC_ERR_SVC_UNAVAILABLE"; break;
  132. case KRB_AP_ERR_BAD_INTEGRITY : String = L"KRB_AP_ERR_BAD_INTEGRITY"; break;
  133. case KRB_AP_ERR_TKT_EXPIRED : String = L"KRB_AP_ERR_TKT_EXPIRED"; break;
  134. case KRB_AP_ERR_TKT_NYV : String = L"KRB_AP_ERR_TKT_NYV"; break;
  135. case KRB_AP_ERR_REPEAT : String = L"KRB_AP_ERR_REPEAT"; break;
  136. case KRB_AP_ERR_NOT_US : String = L"KRB_AP_ERR_NOT_US"; break;
  137. case KRB_AP_ERR_BADMATCH : String = L"KRB_AP_ERR_BADMATCH"; break;
  138. case KRB_AP_ERR_SKEW : String = L"KRB_AP_ERR_SKEW"; break;
  139. case KRB_AP_ERR_BADADDR : String = L"KRB_AP_ERR_BADADDR"; break;
  140. case KRB_AP_ERR_BADVERSION : String = L"KRB_AP_ERR_BADVERSION"; break;
  141. case KRB_AP_ERR_MSG_TYPE : String = L"KRB_AP_ERR_MSG_TYPE"; break;
  142. case KRB_AP_ERR_MODIFIED : String = L"KRB_AP_ERR_MODIFIED"; break;
  143. case KRB_AP_ERR_BADORDER : String = L"KRB_AP_ERR_BADORDER"; break;
  144. case KRB_AP_ERR_BADKEYVER : String = L"KRB_AP_ERR_BADKEYVER"; break;
  145. case KRB_AP_ERR_NOKEY : String = L"KRB_AP_ERR_NOKEY"; break;
  146. case KRB_AP_ERR_MUT_FAIL : String = L"KRB_AP_ERR_MUT_FAIL"; break;
  147. case KRB_AP_ERR_BADDIRECTION : String = L"KRB_AP_ERR_BADDIRECTION"; break;
  148. case KRB_AP_ERR_METHOD : String = L"KRB_AP_ERR_METHOD"; break;
  149. case KRB_AP_ERR_BADSEQ : String = L"KRB_AP_ERR_BADSEQ"; break;
  150. case KRB_AP_ERR_INAPP_CKSUM : String = L"KRB_AP_ERR_INAPP_CKSUM"; break;
  151. case KRB_AP_PATH_NOT_ACCEPTED : String = L"KRB_AP_PATH_NOT_ACCEPTED"; break;
  152. case KRB_ERR_RESPONSE_TOO_BIG : String = L"KRB_ERR_RESPONSE_TOO_BIG"; break;
  153. case KRB_ERR_GENERIC : String = L"KRB_ERR_GENERIC"; break;
  154. case KRB_ERR_FIELD_TOOLONG : String = L"KRB_ERR_FIELD_TOOLONG"; break;
  155. case KDC_ERR_CLIENT_NOT_TRUSTED : String = L"KDC_ERR_CLIENT_NOT_TRUSTED"; break;
  156. case KDC_ERR_KDC_NOT_TRUSTED : String = L"KDC_ERR_KDC_NOT_TRUSTED"; break;
  157. case KDC_ERR_INVALID_SIG : String = L"KDC_ERR_INVALID_SIG"; break;
  158. case KDC_ERR_KEY_TOO_WEAK : String = L"KDC_ERR_KEY_TOO_WEAK"; break;
  159. case KRB_AP_ERR_USER_TO_USER_REQUIRED : String = L"KRB_AP_ERR_USER_TO_USER_REQUIRED"; break;
  160. case KRB_AP_ERR_NO_TGT : String = L"KRB_AP_ERR_NO_TGT"; break;
  161. case KDC_ERR_WRONG_REALM : String = L"KDC_ERR_WRONG_REALM"; break;
  162. default : String = L"Unknown Error"; break;
  163. }
  164. return(String);
  165. }
  166. //+---------------------------------------------------------------------------
  167. //
  168. // Function: InitializeEvents
  169. //
  170. // Synopsis: Connects to event log service
  171. //
  172. // Arguments: (none)
  173. //
  174. // History: 1-03-95 RichardW Created
  175. //
  176. // Notes:
  177. //
  178. //----------------------------------------------------------------------------
  179. NTSTATUS
  180. KerbInitializeEvents(
  181. VOID
  182. )
  183. {
  184. return STATUS_SUCCESS;
  185. }
  186. //+-------------------------------------------------------------------------
  187. //
  188. // Function: KerbInitEventLogHandle
  189. //
  190. // Synopsis:
  191. //
  192. // Effects:
  193. //
  194. // Arguments:
  195. //
  196. // Requires:
  197. //
  198. // Returns:
  199. //
  200. // Notes:
  201. //
  202. //
  203. //--------------------------------------------------------------------------
  204. NTSTATUS
  205. KerbInitEventLogHandle()
  206. {
  207. NTSTATUS Status = STATUS_SUCCESS;
  208. if (KerbEventLogHandle == NULL)
  209. {
  210. HANDLE EventLogHandle;
  211. //
  212. // open an instance of kerb event sources, that discards duplicate
  213. // events in a one hour window.
  214. //
  215. EventLogHandle = NetpEventlogOpen( KerbEventSourceName, 60000*60 );
  216. if (EventLogHandle != NULL)
  217. {
  218. //
  219. // atomically store the new handle value. If there was a race,
  220. // free the one we just created.
  221. //
  222. if(InterlockedCompareExchangePointer(
  223. &KerbEventLogHandle,
  224. EventLogHandle,
  225. NULL
  226. ) != NULL)
  227. {
  228. NetpEventlogClose( EventLogHandle );
  229. }
  230. }
  231. if (KerbEventLogHandle == NULL)
  232. {
  233. D_DebugLog((DEB_ERROR, "Could not open event log, error %d. %ws, line %d - %x\n", GetLastError(), THIS_FILE, __LINE__, Status));
  234. return STATUS_EVENTLOG_CANT_START;
  235. }
  236. }
  237. return Status;
  238. }
  239. //+-------------------------------------------------------------------------
  240. //
  241. // Function: KerbReportNtstatus
  242. //
  243. // Synopsis:
  244. //
  245. // Effects:
  246. //
  247. // Arguments:
  248. //
  249. // Requires:
  250. //
  251. // Returns:
  252. //
  253. // Notes:
  254. //
  255. //
  256. //--------------------------------------------------------------------------
  257. #define MAX_NTSTATUS_STRINGS 10
  258. #define MAX_ULONG_STRING 20
  259. VOID
  260. KerbReportNtstatus(
  261. IN ULONG ErrorClass,
  262. IN NTSTATUS Status,
  263. IN LPWSTR* ErrorStrings,
  264. IN ULONG NumberOfStrings,
  265. IN PULONG Data,
  266. IN ULONG NumberOfUlong
  267. )
  268. {
  269. ULONG StringCount, i, j, allocstart = 0;
  270. LPWSTR Strings[MAX_NTSTATUS_STRINGS];
  271. StringCount = NumberOfUlong + NumberOfStrings;
  272. if (StringCount > MAX_NTSTATUS_STRINGS)
  273. {
  274. return;
  275. }
  276. //
  277. // Validate params
  278. //
  279. switch (ErrorClass)
  280. {
  281. case KERBEVT_INSUFFICIENT_TOKEN_SIZE:
  282. if ((NumberOfStrings != 0) || (NumberOfUlong > 3))
  283. {
  284. DsysAssert(FALSE);
  285. return;
  286. }
  287. break;
  288. default:
  289. return;
  290. }
  291. if (KerbEventLogHandle == NULL)
  292. {
  293. NTSTATUS TmpStatus;
  294. TmpStatus = KerbInitEventLogHandle();
  295. if (TmpStatus != STATUS_SUCCESS)
  296. {
  297. return;
  298. }
  299. }
  300. ZeroMemory( Strings, (StringCount * sizeof(Strings[0])) );
  301. for (i = 0; i < NumberOfStrings; i++)
  302. {
  303. Strings[i] = ErrorStrings[i];
  304. }
  305. allocstart = i; // save for cleanup
  306. for (j = 0; j < NumberOfUlong; j++)
  307. {
  308. UNICODE_STRING DummyString = { MAX_ULONG_STRING, MAX_ULONG_STRING, NULL};
  309. DummyString.Buffer = (LPWSTR) LsaFunctions->AllocatePrivateHeap(MAX_ULONG_STRING);
  310. if ( DummyString.Buffer == NULL )
  311. {
  312. goto Cleanup;
  313. }
  314. //
  315. // Use this since they don't export
  316. // RtlIntegerToUnicode(), and we don't want to
  317. // bring in _itow.
  318. //
  319. RtlIntegerToUnicodeString(
  320. Data[j],
  321. 16,
  322. &DummyString
  323. );
  324. Strings[i] = DummyString.Buffer;
  325. i++;
  326. }
  327. if (ERROR_SUCCESS != NetpEventlogWriteEx(
  328. KerbEventLogHandle,
  329. EVENTLOG_WARNING_TYPE,
  330. 0,
  331. ErrorClass,
  332. (WORD) StringCount,
  333. sizeof(NTSTATUS),
  334. Strings,
  335. &Status
  336. ))
  337. {
  338. D_DebugLog((DEB_ERROR,"Failed to report event: %d. %ws, line %d\n",GetLastError(), THIS_FILE, __LINE__));
  339. }
  340. Cleanup:
  341. for (i = allocstart ; i < (allocstart+NumberOfUlong) ; i++)
  342. {
  343. if (Strings[i] != NULL)
  344. {
  345. LsaFunctions->FreePrivateHeap(Strings[i]);
  346. }
  347. }
  348. return;
  349. }
  350. //+-------------------------------------------------------------------------
  351. //
  352. // Function: KerbReportKerbError
  353. //
  354. // Synopsis:
  355. //
  356. // Effects:
  357. //
  358. // Arguments:
  359. //
  360. // Requires:
  361. //
  362. // Returns:
  363. //
  364. // Notes:
  365. //
  366. //
  367. //--------------------------------------------------------------------------
  368. VOID
  369. KerbReportKerbError(
  370. IN OPTIONAL PKERB_INTERNAL_NAME PrincipalName,
  371. IN OPTIONAL PUNICODE_STRING PrincipalRealm,
  372. IN OPTIONAL PKERB_LOGON_SESSION LogonSession,
  373. IN OPTIONAL PKERB_CREDENTIAL Credential,
  374. IN ULONG KlinInfo,
  375. IN OPTIONAL PKERB_ERROR ErrorMsg,
  376. IN ULONG KerbError,
  377. IN OPTIONAL PKERB_EXT_ERROR pExtendedError,
  378. IN BOOLEAN RequiredEvent
  379. )
  380. {
  381. #ifdef WIN32_CHICAGO
  382. return;
  383. #else
  384. UNICODE_STRING ClientRealm = {0};
  385. UNICODE_STRING ClientName = {0};
  386. UNICODE_STRING ServerRealm = {0};
  387. UNICODE_STRING ServerName = {0};
  388. UNICODE_STRING ErrorText = {0};
  389. UNICODE_STRING LogonSessionName = {0};
  390. UNICODE_STRING TargetFullName = {0};
  391. WCHAR ClientTime[50] = {0};
  392. WCHAR ServerTime[50] = {0};
  393. WCHAR LineString[12] = {0};
  394. WCHAR FileString[12] = {0};
  395. WCHAR ErrorCode[12] = {0};
  396. WCHAR ExtendedError[128] = {0};
  397. KERBERR KerbErr;
  398. ULONG NameType;
  399. NTSTATUS Status = STATUS_SUCCESS;
  400. STRING KerbString = {0};
  401. #define KERB_ERROR_STRING_COUNT 14
  402. LPWSTR Strings[KERB_ERROR_STRING_COUNT];
  403. ULONG RawDataSize = 0;
  404. PVOID RawData = NULL;
  405. ULONG Index;
  406. if ( !RequiredEvent && (KerbGlobalLoggingLevel == 0) )
  407. {
  408. return;
  409. }
  410. if (KerbEventLogHandle == NULL)
  411. {
  412. Status = KerbInitEventLogHandle();
  413. if (Status != STATUS_SUCCESS)
  414. {
  415. return;
  416. }
  417. }
  418. //
  419. // Get the user name from the logon session
  420. //
  421. if (ARGUMENT_PRESENT(LogonSession))
  422. {
  423. KerbReadLockLogonSessions( LogonSession );
  424. KerbErr = KerbBuildFullServiceName(
  425. &LogonSession->PrimaryCredentials.DomainName,
  426. &LogonSession->PrimaryCredentials.UserName,
  427. &LogonSessionName
  428. );
  429. KerbUnlockLogonSessions( LogonSession );
  430. if (!KERB_SUCCESS(KerbErr))
  431. {
  432. goto Cleanup;
  433. }
  434. }
  435. if (ARGUMENT_PRESENT(pExtendedError))
  436. {
  437. swprintf(ExtendedError, L"0x%x KLIN(%x)", pExtendedError->status, pExtendedError->klininfo);
  438. }
  439. if (ARGUMENT_PRESENT(PrincipalName) && ARGUMENT_PRESENT(PrincipalRealm))
  440. {
  441. KerbConvertKdcNameToString(
  442. &TargetFullName,
  443. PrincipalName,
  444. PrincipalRealm
  445. );
  446. }
  447. swprintf(LineString, L"%x", (KlinInfo & 0xFFFF));
  448. swprintf(FileString, L"%x", (KlinInfo >> 16));
  449. if (ARGUMENT_PRESENT(ErrorMsg))
  450. {
  451. swprintf(ErrorCode, L"0x%x", ErrorMsg->error_code);
  452. //
  453. // Get the client and server realms
  454. //
  455. if ((ErrorMsg->bit_mask & client_realm_present) != 0)
  456. {
  457. KerbErr = KerbConvertRealmToUnicodeString(
  458. &ClientRealm,
  459. &ErrorMsg->client_realm
  460. );
  461. if (!KERB_SUCCESS(KerbErr))
  462. {
  463. goto Cleanup;
  464. }
  465. }
  466. if (ErrorMsg->realm != NULL)
  467. {
  468. KerbErr = KerbConvertRealmToUnicodeString(
  469. &ServerRealm,
  470. &ErrorMsg->realm
  471. );
  472. if (!KERB_SUCCESS(KerbErr))
  473. {
  474. goto Cleanup;
  475. }
  476. }
  477. if ((ErrorMsg->bit_mask & KERB_ERROR_client_name_present) != 0)
  478. {
  479. KerbErr = KerbConvertPrincipalNameToString(
  480. &ClientName,
  481. &NameType,
  482. &ErrorMsg->KERB_ERROR_client_name
  483. );
  484. if (!KERB_SUCCESS(KerbErr))
  485. {
  486. goto Cleanup;
  487. }
  488. }
  489. KerbErr = KerbConvertPrincipalNameToString(
  490. &ServerName,
  491. &NameType,
  492. &ErrorMsg->server_name
  493. );
  494. if (!KERB_SUCCESS(KerbErr))
  495. {
  496. goto Cleanup;
  497. }
  498. if ((ErrorMsg->bit_mask & client_time_present) != 0)
  499. {
  500. swprintf(ClientTime,L"%d:%d:%d.%04d %d/%d/%d %ws",
  501. ErrorMsg->client_time.hour,
  502. ErrorMsg->client_time.minute,
  503. ErrorMsg->client_time.second,
  504. ErrorMsg->client_time.millisecond,
  505. ErrorMsg->client_time.month,
  506. ErrorMsg->client_time.day,
  507. ErrorMsg->client_time.year,
  508. (ErrorMsg->client_time.universal) ? L"Z" : L""
  509. );
  510. }
  511. swprintf(ServerTime,L"%d:%d:%d.%04d %d/%d/%d %ws",
  512. ErrorMsg->server_time.hour,
  513. ErrorMsg->server_time.minute,
  514. ErrorMsg->server_time.second,
  515. ErrorMsg->server_time.millisecond,
  516. ErrorMsg->server_time.month,
  517. ErrorMsg->server_time.day,
  518. ErrorMsg->server_time.year,
  519. (ErrorMsg->server_time.universal) ? L"Z" : L""
  520. );
  521. if (((ErrorMsg->bit_mask & error_text_present) != 0) &&
  522. (ErrorMsg->error_text.length < SHRT_MAX))
  523. {
  524. KerbString.Buffer = ErrorMsg->error_text.value;
  525. KerbString.Length = (USHORT) ErrorMsg->error_text.length;
  526. KerbErr = KerbStringToUnicodeString(
  527. &ErrorText,
  528. &KerbString
  529. );
  530. if (!KERB_SUCCESS(KerbErr))
  531. {
  532. goto Cleanup;
  533. }
  534. }
  535. if ((ErrorMsg->bit_mask & error_data_present) != 0)
  536. {
  537. RawDataSize = ErrorMsg->error_data.length;
  538. RawData = ErrorMsg->error_data.value;
  539. }
  540. }
  541. else
  542. {
  543. swprintf(ErrorCode, L"0x%x", KerbError);
  544. }
  545. //
  546. // Build the array of strings
  547. //
  548. Strings[0] = LogonSessionName.Buffer;
  549. Strings[1] = ClientTime;
  550. Strings[2] = ServerTime;
  551. Strings[3] = ErrorCode;
  552. Strings[4] = (ARGUMENT_PRESENT(ErrorMsg)
  553. ? KerbErrorToString(ErrorMsg->error_code) :
  554. KerbErrorToString(KerbError));
  555. Strings[5] = ExtendedError;
  556. Strings[6] = ClientRealm.Buffer;
  557. Strings[7] = ClientName.Buffer;
  558. Strings[8] = ServerRealm.Buffer;
  559. Strings[9] = ServerName.Buffer;
  560. Strings[10] = TargetFullName.Buffer;
  561. Strings[11] = ErrorText.Buffer;
  562. Strings[12] = FileString;
  563. Strings[13] = LineString;
  564. //
  565. // Replace NULLs with an empty string.
  566. //
  567. for (Index = 0; Index < KERB_ERROR_STRING_COUNT ; Index++ )
  568. {
  569. if (Strings[Index] == NULL)
  570. {
  571. Strings[Index] = L"";
  572. }
  573. }
  574. if (ERROR_SUCCESS != NetpEventlogWriteEx(
  575. KerbEventLogHandle,
  576. EVENTLOG_ERROR_TYPE,
  577. 0,
  578. KERBEVT_KERB_ERROR_MSG,
  579. KERB_ERROR_STRING_COUNT,
  580. RawDataSize,
  581. Strings,
  582. RawData
  583. ))
  584. {
  585. D_DebugLog((DEB_ERROR,"Failed to report event: %d. %ws, line %d\n",GetLastError(), THIS_FILE, __LINE__));
  586. }
  587. Cleanup:
  588. KerbFreeString( &LogonSessionName );
  589. KerbFreeString( &ClientRealm );
  590. KerbFreeString( &ClientName );
  591. KerbFreeString( &ServerRealm );
  592. KerbFreeString( &ServerName );
  593. KerbFreeString( &ErrorText );
  594. KerbFreeString( &TargetFullName );
  595. }
  596. //+-------------------------------------------------------------------------
  597. //
  598. // Function: KerbReportApModifiedError
  599. //
  600. // Synopsis: Reports error of type KRB_AP_ERR_MODIFIED
  601. //
  602. // Effects:
  603. //
  604. // Arguments:
  605. //
  606. // Requires:
  607. //
  608. // Returns:
  609. //
  610. // Notes:
  611. //
  612. //
  613. //--------------------------------------------------------------------------
  614. #define MAX_STRINGS 3
  615. VOID
  616. KerbReportApError(
  617. PKERB_ERROR ErrorMsg,
  618. IN OPTIONAL PUNICODE_STRING TargetName
  619. )
  620. {
  621. KERBERR KerbErr;
  622. LPWSTR Strings[MAX_STRINGS] = {NULL, NULL, NULL};
  623. DWORD EventId = 0, dwDataSize = 0;
  624. WORD StringCount = 2;
  625. LPVOID lpRawData = NULL;
  626. UNICODE_STRING ServerName = {0};
  627. UNICODE_STRING ServerRealm = {0};
  628. UNICODE_STRING NewTargetName = {0};
  629. ULONG NameType;
  630. NTSTATUS Status;
  631. if (KerbEventLogHandle == NULL)
  632. {
  633. Status = KerbInitEventLogHandle();
  634. if (Status != STATUS_SUCCESS)
  635. {
  636. return;
  637. }
  638. }
  639. KerbErr = KerbConvertPrincipalNameToString(
  640. &ServerName,
  641. &NameType,
  642. &ErrorMsg->server_name
  643. );
  644. if (!KERB_SUCCESS(KerbErr))
  645. {
  646. goto Cleanup;
  647. }
  648. if (ErrorMsg->realm != NULL)
  649. {
  650. KerbErr = KerbConvertRealmToUnicodeString(
  651. &ServerRealm,
  652. &ErrorMsg->realm
  653. );
  654. if (!KERB_SUCCESS(KerbErr))
  655. {
  656. goto Cleanup;
  657. }
  658. }
  659. Strings[0] = ServerName.Buffer;
  660. Strings[1] = ServerRealm.Buffer;
  661. switch (ErrorMsg->error_code)
  662. {
  663. case KRB_AP_ERR_MODIFIED:
  664. EventId = KERBEVT_KRB_AP_ERR_MODIFIED;
  665. // not sure if this is always null terminated, so do it.
  666. Status = KerbDuplicateString(
  667. &NewTargetName,
  668. TargetName
  669. );
  670. if (Status != STATUS_SUCCESS)
  671. {
  672. return;
  673. }
  674. Strings[2] = NewTargetName.Buffer;
  675. StringCount++;
  676. break;
  677. case KRB_AP_ERR_TKT_NYV:
  678. EventId = KERBEVT_KRB_AP_ERR_TKT_NYV;
  679. break;
  680. default:
  681. D_DebugLog((DEB_ERROR, "Unknown error to KerbReportApError %x\n", ErrorMsg->error_code));
  682. goto Cleanup;
  683. }
  684. if (ERROR_SUCCESS != NetpEventlogWriteEx(
  685. KerbEventLogHandle,
  686. EVENTLOG_ERROR_TYPE,
  687. 0,
  688. EventId,
  689. StringCount,
  690. dwDataSize,
  691. Strings,
  692. lpRawData
  693. ))
  694. {
  695. D_DebugLog((DEB_ERROR,"Failed to report event: %d. %ws, line %d\n",GetLastError(), THIS_FILE, __LINE__));
  696. }
  697. Cleanup:
  698. KerbFreeString( &ServerRealm );
  699. KerbFreeString( &ServerName );
  700. KerbFreeString( &NewTargetName );
  701. }
  702. #endif // WIN32_CHICAGO
  703. //+-------------------------------------------------------------------------
  704. //
  705. // Function: KerbShutdownEvents
  706. //
  707. // Synopsis: Shutsdown event log reporting
  708. //
  709. // Effects:
  710. //
  711. // Arguments:
  712. //
  713. // Requires:
  714. //
  715. // Returns:
  716. //
  717. // Notes:
  718. //
  719. //
  720. //--------------------------------------------------------------------------
  721. VOID
  722. KerbShutdownEvents(
  723. VOID
  724. )
  725. {
  726. HANDLE EventLogHandle;
  727. EventLogHandle = InterlockedExchangePointer( &KerbEventLogHandle, NULL );
  728. if( EventLogHandle )
  729. {
  730. NetpEventlogClose( EventLogHandle );
  731. }
  732. }
  733. //+-------------------------------------------------------------------------
  734. //
  735. // Function: KerbReportPACError
  736. //
  737. // Synopsis: Reports error of type KERBEVT_KRB_PAC_VERIFICATION_FAILURE
  738. //
  739. // Effects:
  740. //
  741. // Arguments:
  742. //
  743. // Requires:
  744. //
  745. // Returns:
  746. //
  747. // Notes:
  748. //
  749. //
  750. //--------------------------------------------------------------------------
  751. VOID
  752. KerbReportPACError(
  753. PUNICODE_STRING ClientName,
  754. PUNICODE_STRING ClientDomain,
  755. NTSTATUS FailureStatus
  756. )
  757. {
  758. LPWSTR Strings[MAX_STRINGS] = {NULL, NULL};
  759. NTSTATUS Status;
  760. if (KerbEventLogHandle == NULL)
  761. {
  762. Status = KerbInitEventLogHandle();
  763. if (Status != STATUS_SUCCESS)
  764. {
  765. return;
  766. }
  767. }
  768. //
  769. // There's a small window of oppty when KDCs might try to validate
  770. // the PAC locally, even though the kdcsvc.dll hasn't been loaded into
  771. // lsass.exe yet.
  772. //
  773. if ( FailureStatus == STATUS_MUST_BE_KDC )
  774. {
  775. return;
  776. }
  777. Strings[0] = ClientName->Buffer; // this is null terminated in this case
  778. Strings[1] = ClientDomain->Buffer; // this is null terminated in this case
  779. if (ERROR_SUCCESS != NetpEventlogWriteEx(
  780. KerbEventLogHandle,
  781. EVENTLOG_ERROR_TYPE,
  782. 0,
  783. KERBEVT_KRB_PAC_VERIFICATION_FAILURE,
  784. 2,
  785. sizeof(NTSTATUS),
  786. Strings,
  787. &FailureStatus
  788. ))
  789. {
  790. D_DebugLog((DEB_ERROR,"Failed to report event: %d. %ws, line %d\n",GetLastError(), THIS_FILE, __LINE__));
  791. }
  792. }
  793. //+-------------------------------------------------------------------------
  794. //
  795. // Function: KerbReportUdpEvent
  796. //
  797. // Synopsis: See if its time to log an event.
  798. //
  799. // Effects:
  800. //
  801. // Arguments:
  802. //
  803. // Requires:
  804. //
  805. // Returns:
  806. //
  807. // Notes:
  808. //
  809. //
  810. //--------------------------------------------------------------------------
  811. BOOLEAN
  812. KerbReportUdpEvent()
  813. {
  814. TimeStamp CurrentTime;
  815. BOOLEAN fRet = FALSE;
  816. GetSystemTimeAsFileTime((LPFILETIME) &CurrentTime);
  817. InterlockedIncrement(&KerbUdpTimeoutEvents);
  818. KerbReadLockUdpStats();
  819. if (( KerbUdpTimeoutEvents > UDPTIMEOUT_LOGGING_THRESHHOLD ) &&
  820. ( KerbGetTime(CurrentTime) < KerbGetTime( KerbUdpNextUpdate )))
  821. {
  822. fRet = TRUE;
  823. KerbReadToWriteLockUdpStats();
  824. KerbUdpTimeoutEvents = 0;
  825. }
  826. else if ( KerbGetTime( CurrentTime ) > KerbGetTime( KerbUdpNextUpdate ))
  827. {
  828. //
  829. // Time to reset our counter, and our time
  830. //
  831. KerbReadToWriteLockUdpStats();
  832. TimeStamp Delta;
  833. KerbSetTimeInMinutes(&Delta, UDPTIMEOUT_LOGGING_INTERVAL);
  834. KerbSetTime(&KerbUdpNextUpdate,(KerbGetTime(CurrentTime) + KerbGetTime(Delta)));
  835. KerbUdpTimeoutEvents = 0;
  836. }
  837. KerbUnlockUdpStats();
  838. return fRet;
  839. }
  840. //+-------------------------------------------------------------------------
  841. //
  842. // Function: KerbReportMissingRDN.
  843. //
  844. // Synopsis: Reports error when we don't have enough information in the
  845. // subject RDN.
  846. // Effects:
  847. //
  848. // Arguments:
  849. //
  850. // Requires:
  851. //
  852. // Returns:
  853. //
  854. // Notes:
  855. //
  856. //
  857. //--------------------------------------------------------------------------
  858. VOID
  859. KerbReportMissingRDN()
  860. {
  861. NTSTATUS Status;
  862. if (KerbEventLogHandle == NULL)
  863. {
  864. Status = KerbInitEventLogHandle();
  865. if (Status != STATUS_SUCCESS)
  866. {
  867. return;
  868. }
  869. }
  870. if (ERROR_SUCCESS != NetpEventlogWriteEx(
  871. KerbEventLogHandle,
  872. EVENTLOG_ERROR_TYPE,
  873. 0,
  874. KERBEVT_NO_RDN,
  875. 0,
  876. 0,
  877. NULL,
  878. NULL
  879. ))
  880. {
  881. D_DebugLog((DEB_TRACE,"Failed to report event: %d. %ws, line %d\n",GetLastError(), THIS_FILE, __LINE__));
  882. }
  883. }
  884. //+-------------------------------------------------------------------------
  885. //
  886. // Function: KerbReportTransportError.
  887. //
  888. // Synopsis: Reports warning when we're hitting UDP timeouts.
  889. //
  890. // Effects:
  891. //
  892. // Arguments:
  893. //
  894. // Requires:
  895. //
  896. // Returns:
  897. //
  898. // Notes:
  899. //
  900. //
  901. //--------------------------------------------------------------------------
  902. VOID
  903. KerbReportTransportError(
  904. NTSTATUS FailureStatus
  905. )
  906. {
  907. NTSTATUS Status;
  908. if (KerbEventLogHandle == NULL)
  909. {
  910. Status = KerbInitEventLogHandle();
  911. if (Status != STATUS_SUCCESS)
  912. {
  913. return;
  914. }
  915. }
  916. //
  917. // Only log every 20th event.
  918. //
  919. if (!KerbReportUdpEvent())
  920. {
  921. return;
  922. }
  923. D_DebugLog((DEB_TRACE, "Logging UDP event\n"));
  924. if (ERROR_SUCCESS != NetpEventlogWriteEx(
  925. KerbEventLogHandle,
  926. EVENTLOG_WARNING_TYPE,
  927. 0,
  928. KERBEVT_UDP_TIMEOUT,
  929. 0,
  930. sizeof(NTSTATUS),
  931. NULL,
  932. &FailureStatus
  933. ))
  934. {
  935. D_DebugLog((DEB_TRACE,"Failed to report event: %d. %ws, line %d\n",GetLastError(), THIS_FILE, __LINE__));
  936. }
  937. }
  938. //+-------------------------------------------------------------------------
  939. //
  940. // Function: KerbResetTransmissionCounter
  941. //
  942. // Synopsis: Don't log UDP problems if we have no network, or can't
  943. // reach a DC.
  944. //
  945. // Effects:
  946. //
  947. // Arguments:
  948. //
  949. // Requires:
  950. //
  951. // Returns:
  952. //
  953. // Notes:
  954. //
  955. //
  956. //--------------------------------------------------------------------------
  957. VOID
  958. KerbResetTransportCounter()
  959. {
  960. KerbReadLockUdpStats();
  961. if (KerbUdpTimeoutEvents != 0)
  962. {
  963. //
  964. // Avoid taking write lock unless needed.
  965. //
  966. D_DebugLog((DEB_ERROR, "Resetting transmission counter. Current (%x)\n", KerbUdpTimeoutEvents));
  967. KerbReadToWriteLockUdpStats();
  968. KerbUdpTimeoutEvents = 0;
  969. }
  970. KerbUnlockUdpStats();
  971. }
  972. //+-------------------------------------------------------------------------
  973. //
  974. // Function: KerbReportPkinit
  975. //
  976. // Synopsis: Reports errors generated by invalid client certificates
  977. //
  978. // Effects:
  979. //
  980. // Arguments:
  981. //
  982. // Requires:
  983. //
  984. // Returns:
  985. //
  986. // Notes:
  987. //
  988. //
  989. //--------------------------------------------------------------------------
  990. VOID
  991. KerbReportPkinitError(
  992. IN ULONG PolicyStatus,
  993. IN OPTIONAL PCCERT_CONTEXT KdcCert
  994. )
  995. {
  996. LPWSTR Strings[MAX_STRINGS] = {NULL, NULL, NULL};
  997. WCHAR SubjectName[DNS_MAX_NAME_LENGTH + 1];
  998. DWORD NameMaxLength = DNS_MAX_NAME_LENGTH + 1;
  999. DWORD SubjectLength;
  1000. NTSTATUS Status;
  1001. ULONG StringCount = 1;
  1002. LPWSTR MessageBuffer = NULL;
  1003. DWORD MessageSize = 0;
  1004. if (KerbEventLogHandle == NULL)
  1005. {
  1006. Status = KerbInitEventLogHandle();
  1007. if (Status != STATUS_SUCCESS)
  1008. {
  1009. return;
  1010. }
  1011. }
  1012. MessageSize = FormatMessageW(
  1013. FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  1014. NULL,
  1015. PolicyStatus,
  1016. 0,
  1017. (WCHAR*) &MessageBuffer,
  1018. MessageSize,
  1019. NULL
  1020. );
  1021. if ( MessageSize != 0 )
  1022. {
  1023. Strings[0] = MessageBuffer;
  1024. if (ARGUMENT_PRESENT(KdcCert))
  1025. {
  1026. RtlZeroMemory(
  1027. SubjectName,
  1028. NameMaxLength
  1029. );
  1030. SubjectLength = CertGetNameString(
  1031. KdcCert,
  1032. CERT_NAME_DNS_TYPE,
  1033. 0,
  1034. NULL,
  1035. SubjectName,
  1036. NameMaxLength
  1037. );
  1038. if (SubjectLength != 0)
  1039. {
  1040. Strings[1] = SubjectName;
  1041. StringCount++;
  1042. }
  1043. else
  1044. {
  1045. Strings[1] = L"<no dns name present>";
  1046. StringCount++;
  1047. }
  1048. }
  1049. if (ERROR_SUCCESS != NetpEventlogWriteEx(
  1050. KerbEventLogHandle,
  1051. EVENTLOG_ERROR_TYPE,
  1052. 0,
  1053. (ARGUMENT_PRESENT(KdcCert) ?
  1054. KERBEVT_BAD_KDC_CERTIFICATE :
  1055. KERBEVT_BAD_CLIENT_CERTIFICATE),
  1056. StringCount,
  1057. sizeof(ULONG),
  1058. Strings,
  1059. &PolicyStatus
  1060. ))
  1061. {
  1062. D_DebugLog((DEB_ERROR,"Failed to report event: %d. %ws, line %d\n",GetLastError(), THIS_FILE, __LINE__));
  1063. }
  1064. LocalFree(MessageBuffer);
  1065. }
  1066. else
  1067. {
  1068. D_DebugLog((DEB_ERROR, "Formatmessage failed %x\n", GetLastError()));
  1069. DsysAssert(FALSE);
  1070. }
  1071. }
  1072. //+-------------------------------------------------------------------------
  1073. //
  1074. // Function: KerbReportRasCardError
  1075. //
  1076. // Synopsis: Problem w/ *Session && Smartcard error.
  1077. //
  1078. // Effects:
  1079. //
  1080. // Arguments:
  1081. //
  1082. // Requires:
  1083. //
  1084. // Returns:
  1085. //
  1086. // Notes:
  1087. //
  1088. //
  1089. //---------------------------------------------------------------------------
  1090. VOID
  1091. KerbReportRasCardError(
  1092. NTSTATUS CardStatus
  1093. )
  1094. {
  1095. NTSTATUS Status;
  1096. if (KerbEventLogHandle == NULL)
  1097. {
  1098. Status = KerbInitEventLogHandle();
  1099. if (Status != STATUS_SUCCESS)
  1100. {
  1101. return;
  1102. }
  1103. }
  1104. NetpEventlogWriteEx(
  1105. KerbEventLogHandle,
  1106. EVENTLOG_WARNING_TYPE,
  1107. 0,
  1108. KERBEVT_RAS_CARD_ERROR,
  1109. 0,
  1110. sizeof(NTSTATUS),
  1111. NULL,
  1112. &CardStatus
  1113. );
  1114. }
  1115. //+-------------------------------------------------------------------------
  1116. //
  1117. // Function: KerbReportCredmanError
  1118. //
  1119. // Synopsis: Problem w/ credman creds
  1120. //
  1121. // Effects:
  1122. //
  1123. // Arguments:
  1124. //
  1125. // Requires:
  1126. //
  1127. // Returns:
  1128. //
  1129. // Notes:
  1130. //
  1131. //
  1132. //---------------------------------------------------------------------------
  1133. VOID
  1134. KerbReportCredmanError(
  1135. IN PUNICODE_STRING UserName,
  1136. IN PUNICODE_STRING Domain,
  1137. IN BOOLEAN Pkinit,
  1138. IN NTSTATUS CardStatus
  1139. )
  1140. {
  1141. NTSTATUS Status;
  1142. ULONG StringCount = 1;
  1143. LPWSTR Strings[3] ={0};
  1144. if (KerbEventLogHandle == NULL)
  1145. {
  1146. Status = KerbInitEventLogHandle();
  1147. if (Status != STATUS_SUCCESS)
  1148. {
  1149. return;
  1150. }
  1151. }
  1152. Strings[0] = UserName->Buffer;
  1153. if (( Domain->Length > 0 ) &&
  1154. ( Domain->Buffer ))
  1155. {
  1156. Strings[0] = Domain->Buffer;
  1157. Strings[1] = L"\\";
  1158. Strings[2] = UserName->Buffer;
  1159. StringCount = 3;
  1160. }
  1161. NetpEventlogWriteEx(
  1162. KerbEventLogHandle,
  1163. EVENTLOG_WARNING_TYPE,
  1164. 0,
  1165. (Pkinit ? KERBEVT_CREDMAN_CARD_ERROR : KERBEVT_CREDMAN_PWD_ERROR),
  1166. StringCount,
  1167. sizeof(NTSTATUS),
  1168. Strings,
  1169. &CardStatus
  1170. );
  1171. }