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.

814 lines
19 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 "kdcsvr.hxx"
  18. #include <netlib.h>
  19. extern "C" {
  20. #include <lmserver.h>
  21. #include <srvann.h>
  22. }
  23. HANDLE hEventLog = (HANDLE)NULL;
  24. DWORD LoggingLevel = (1 << EVENTLOG_ERROR_TYPE) | (1 << EVENTLOG_WARNING_TYPE);
  25. WCHAR EventSourceName[] = TEXT("KDC");
  26. #define MAX_EVENT_STRINGS 8
  27. #define MAX_ETYPE_LONG 999
  28. #define MIN_ETYPE_LONG -999
  29. #define MAX_ETYPE_STRING 16 // 4wchar + , + 2 space
  30. #define WSZ_NO_KEYS L"< >"
  31. //+---------------------------------------------------------------------------
  32. //
  33. // Function: InitializeEvents
  34. //
  35. // Synopsis: Connects to event log service
  36. //
  37. // Arguments: (none)
  38. //
  39. // History: 1-03-95 RichardW Created
  40. //
  41. // Notes:
  42. //
  43. //----------------------------------------------------------------------------
  44. BOOL
  45. InitializeEvents(void)
  46. {
  47. TRACE(KDC, InitializeEvents, DEB_FUNCTION);
  48. //
  49. // Interval with which we'll log the same event twice
  50. //
  51. #define KDC_EVENT_LIFETIME (60*60*1000)
  52. hEventLog = NetpEventlogOpen(EventSourceName, KDC_EVENT_LIFETIME);
  53. if (hEventLog)
  54. {
  55. return(TRUE);
  56. }
  57. DebugLog((DEB_ERROR, "Could not open event log, error %d\n", GetLastError()));
  58. return(FALSE);
  59. }
  60. //+---------------------------------------------------------------------------
  61. //
  62. // Function: ReportServiceEvent
  63. //
  64. // Synopsis: Reports an event to the event log
  65. //
  66. // Arguments: [EventType] -- EventType (ERROR, WARNING, etc.)
  67. // [EventId] -- Event ID
  68. // [SizeOfRawData] -- Size of raw data
  69. // [RawData] -- Raw data
  70. // [NumberOfStrings] -- number of strings
  71. // ... -- PWSTRs to string data
  72. //
  73. // History: 1-03-95 RichardW Created
  74. //
  75. // Notes:
  76. //
  77. //----------------------------------------------------------------------------
  78. DWORD
  79. ReportServiceEvent(
  80. IN WORD EventType,
  81. IN DWORD EventId,
  82. IN DWORD SizeOfRawData,
  83. IN PVOID RawData,
  84. IN DWORD NumberOfStrings,
  85. ...
  86. )
  87. {
  88. TRACE(KDC, ReportServiceEvent, DEB_FUNCTION);
  89. va_list arglist;
  90. ULONG i;
  91. PWSTR Strings[ MAX_EVENT_STRINGS ];
  92. DWORD rv;
  93. if (!hEventLog)
  94. {
  95. DebugLog((DEB_ERROR, "Cannot log event, no handle!\n"));
  96. return((DWORD)-1);
  97. }
  98. //
  99. // Look at the strings, if they were provided
  100. //
  101. va_start( arglist, NumberOfStrings );
  102. if (NumberOfStrings > MAX_EVENT_STRINGS) {
  103. NumberOfStrings = MAX_EVENT_STRINGS;
  104. }
  105. for (i = 0; i<NumberOfStrings; i++) {
  106. Strings[ i ] = va_arg( arglist, PWSTR );
  107. }
  108. //
  109. // Report the event to the eventlog service
  110. //
  111. if ((rv = NetpEventlogWrite(
  112. hEventLog,
  113. EventId,
  114. EventType,
  115. (PBYTE) RawData,
  116. SizeOfRawData,
  117. (LPWSTR *) Strings,
  118. NumberOfStrings
  119. )) != ERROR_SUCCESS)
  120. {
  121. DebugLog((DEB_ERROR, "NetpEventlogWrite( 0x%x ) failed - %u\n", EventId, rv ));
  122. }
  123. return rv;
  124. }
  125. BOOL
  126. ShutdownEvents(void)
  127. {
  128. TRACE(KDC, ShutdownEvents, DEB_FUNCTION);
  129. NetpEventlogClose(hEventLog);
  130. return TRUE;
  131. }
  132. NTSTATUS
  133. KdcBuildEtypeStringFromStoredCredential(
  134. IN OPTIONAL PKERB_STORED_CREDENTIAL Cred,
  135. IN OUT PWSTR* EtypeString
  136. )
  137. {
  138. ULONG BuffSize;
  139. PWSTR Ret = NULL;
  140. SIZE_T Len = 0;
  141. WCHAR Buff[12];
  142. *EtypeString = NULL;
  143. if (Cred == NULL
  144. || ((Cred->CredentialCount + Cred->OldCredentialCount) == 0))
  145. {
  146. BuffSize = (ULONG) sizeof(WCHAR) * (ULONG) (wcslen(WSZ_NO_KEYS)+1);
  147. *EtypeString = (LPWSTR)MIDL_user_allocate(BuffSize);
  148. if (NULL == *EtypeString)
  149. {
  150. return STATUS_INSUFFICIENT_RESOURCES;
  151. }
  152. wcscpy(*EtypeString, WSZ_NO_KEYS);
  153. return STATUS_SUCCESS;
  154. }
  155. // Guess maximum buffer... Etypes are 4 chars at most
  156. BuffSize = ((Cred->CredentialCount + Cred->OldCredentialCount ) * MAX_ETYPE_STRING);
  157. Ret = (LPWSTR)MIDL_user_allocate(BuffSize + sizeof(WCHAR));
  158. if (NULL == Ret)
  159. {
  160. return STATUS_INSUFFICIENT_RESOURCES;
  161. }
  162. for (LONG Index = 0; Index < (Cred->CredentialCount + Cred->OldCredentialCount ); Index++)
  163. {
  164. if (Cred->Credentials[Index].Key.keytype > MAX_ETYPE_LONG ||
  165. Cred->Credentials[Index].Key.keytype < MIN_ETYPE_LONG)
  166. {
  167. DebugLog((DEB_ERROR, "Keytype too large for string conversion\n"));
  168. DsysAssert(FALSE);
  169. }
  170. else
  171. {
  172. _itow(Cred->Credentials[Index].Key.keytype, Buff, 10);
  173. wcscat(Ret, Buff);
  174. wcscat(Ret, L" ");
  175. }
  176. }
  177. //
  178. // stripping out trailing white spaces
  179. //
  180. Len = wcslen(Ret);
  181. while (Len && iswspace(Ret[Len - 1]))
  182. {
  183. Ret[(Len--) - 1] = L'\0';
  184. }
  185. *EtypeString = Ret;
  186. return STATUS_SUCCESS;
  187. }
  188. NTSTATUS
  189. KdcBuildEtypeStringFromCryptList(
  190. IN OPTIONAL PKERB_CRYPT_LIST CryptList,
  191. IN OUT LPWSTR * EtypeString
  192. )
  193. {
  194. SIZE_T Len = 0;
  195. ULONG BuffSize = 0;
  196. PWSTR Ret = NULL;
  197. WCHAR Buff[30];
  198. PKERB_CRYPT_LIST ListPointer = CryptList;
  199. *EtypeString = NULL;
  200. if (CryptList == NULL)
  201. {
  202. BuffSize = (ULONG) sizeof(WCHAR) * (ULONG) (wcslen(WSZ_NO_KEYS)+1);
  203. *EtypeString = (LPWSTR)MIDL_user_allocate(BuffSize);
  204. if (NULL == *EtypeString)
  205. {
  206. return STATUS_INSUFFICIENT_RESOURCES;
  207. }
  208. wcscpy(*EtypeString, WSZ_NO_KEYS);
  209. return STATUS_SUCCESS;
  210. }
  211. while (TRUE)
  212. {
  213. if (ListPointer->value > MAX_ETYPE_LONG || ListPointer->value < MIN_ETYPE_LONG)
  214. {
  215. DebugLog((DEB_ERROR, "Maximum etype exceeded\n"));
  216. return STATUS_INVALID_PARAMETER;
  217. }
  218. BuffSize += MAX_ETYPE_STRING;
  219. if (NULL == ListPointer->next)
  220. {
  221. break;
  222. }
  223. ListPointer = ListPointer->next;
  224. }
  225. Ret = (LPWSTR) MIDL_user_allocate(BuffSize + sizeof(WCHAR));
  226. if (NULL == Ret)
  227. {
  228. return STATUS_INSUFFICIENT_RESOURCES;
  229. }
  230. while (TRUE)
  231. {
  232. _itow(CryptList->value, Buff, 10);
  233. wcscat(Ret, Buff);
  234. wcscat(Ret, L" ");
  235. if (NULL == CryptList->next)
  236. {
  237. break;
  238. }
  239. CryptList = CryptList->next;
  240. }
  241. //
  242. // stripping out trailing white spaces
  243. //
  244. Len = wcslen(Ret);
  245. while (Len && iswspace(Ret[Len - 1]))
  246. {
  247. Ret[(Len--) - 1] = L'\0';
  248. }
  249. *EtypeString = Ret;
  250. return STATUS_SUCCESS;
  251. }
  252. void
  253. KdcReportKeyError(
  254. IN PUNICODE_STRING AccountName,
  255. IN OPTIONAL PUNICODE_STRING ServerName,
  256. IN ULONG DescriptionID, // uniquely descibe the location of key error
  257. IN ULONG EventId,
  258. IN OPTIONAL PKERB_CRYPT_LIST RequestEtypes,
  259. IN PKDC_TICKET_INFO AccountTicketInfo
  260. )
  261. {
  262. ULONG NumberOfStrings;
  263. NTSTATUS Status;
  264. PWSTR Strings[ MAX_EVENT_STRINGS ];
  265. PWSTR RequestEtypeString = NULL;
  266. PWSTR StoredEtypeString = NULL;
  267. DWORD rv;
  268. ULONG KdcEtypes[KERB_MAX_CRYPTO_SYSTEMS];
  269. ULONG KdcEtypeCount = 0;
  270. BOOL IsEtypeSupported = FALSE;
  271. WCHAR Description[16] = {0};
  272. if (!hEventLog)
  273. {
  274. DebugLog((DEB_ERROR, "Cannot log event, no handle!\n"));
  275. return;
  276. }
  277. _snwprintf(Description, RTL_NUMBER_OF(Description) - 1, L"%d", DescriptionID);
  278. Status = CDBuildIntegrityVect(
  279. &KdcEtypeCount,
  280. KdcEtypes
  281. );
  282. if (!NT_SUCCESS(Status))
  283. {
  284. return;
  285. }
  286. //
  287. // is there at least one etype in RequestEtypes supported?
  288. //
  289. for (ULONG i = 0; i < KdcEtypeCount; i++)
  290. {
  291. if ((AccountTicketInfo->UserAccountControl & USER_USE_DES_KEY_ONLY)
  292. && ((KdcEtypes[i] == KERB_ETYPE_RC4_LM)
  293. || (KdcEtypes[i]== KERB_ETYPE_RC4_MD4)
  294. || (KdcEtypes[i] == KERB_ETYPE_RC4_HMAC_OLD)
  295. || (KdcEtypes[i] == KERB_ETYPE_RC4_HMAC_OLD_EXP)
  296. || (KdcEtypes[i] == KERB_ETYPE_RC4_HMAC_NT)
  297. || (KdcEtypes[i] == KERB_ETYPE_RC4_HMAC_NT_EXP)
  298. || (KdcEtypes[i] == KERB_ETYPE_NULL)) )
  299. {
  300. continue;
  301. }
  302. for (PKERB_CRYPT_LIST cur = RequestEtypes; cur != NULL; cur = cur->next)
  303. {
  304. if ((LONG) KdcEtypes[i] == cur->value)
  305. {
  306. IsEtypeSupported = TRUE;
  307. break;
  308. }
  309. }
  310. }
  311. Status = KdcBuildEtypeStringFromCryptList(
  312. RequestEtypes,
  313. &RequestEtypeString
  314. );
  315. if (!NT_SUCCESS(Status))
  316. {
  317. DebugLog((DEB_ERROR, "KdcBuildEtypeFromCryptList failed\n"));
  318. goto cleanup;
  319. }
  320. Status = KdcBuildEtypeStringFromStoredCredential(
  321. AccountTicketInfo->Passwords,
  322. &StoredEtypeString
  323. );
  324. if (!NT_SUCCESS(Status))
  325. {
  326. DebugLog((DEB_ERROR, "KdcBuildEtypeFromStoredCredential failed\n"));
  327. goto cleanup;
  328. }
  329. if (EventId == KDCEVENT_NO_KEY_INTERSECTION_TGS)
  330. {
  331. if (!ARGUMENT_PRESENT(ServerName))
  332. {
  333. DebugLog((DEB_ERROR, "Invalid arg to KdcReportKeyError: missing ServerName!\n"));
  334. DsysAssert(FALSE);
  335. goto cleanup;
  336. }
  337. }
  338. else if (EventId != KDCEVENT_NO_KEY_INTERSECTION_AS)
  339. {
  340. DebugLog((DEB_ERROR, "Invalid arg to KdcReportKeyError: unexpected event id %#x!\n", EventId));
  341. DsysAssert(FALSE);
  342. goto cleanup;
  343. }
  344. Strings[0] = ServerName ? ServerName->Buffer : KDC_PRINCIPAL_NAME;
  345. Strings[1] = AccountName->Buffer;
  346. Strings[2] = Description;
  347. Strings[3] = RequestEtypeString;
  348. Strings[4] = StoredEtypeString;
  349. if (IsEtypeSupported)
  350. {
  351. //
  352. // these can be corrected by resetting/changing the passwords
  353. //
  354. Strings[5] = AccountTicketInfo->AccountName.Buffer;
  355. NumberOfStrings = 6;
  356. }
  357. else
  358. {
  359. //
  360. // these can not be corrected by resetting/changing the password
  361. //
  362. DebugLog((DEB_ERROR, "KdcReportKeyError etype not supported %ws\n", RequestEtypeString));
  363. if (EventId == KDCEVENT_NO_KEY_INTERSECTION_TGS)
  364. {
  365. EventId = KDCEVENT_UNSUPPORTED_ETYPE_REQUEST_TGS;
  366. }
  367. else if (EventId == KDCEVENT_NO_KEY_INTERSECTION_AS)
  368. {
  369. EventId = KDCEVENT_UNSUPPORTED_ETYPE_REQUEST_AS;
  370. }
  371. NumberOfStrings = 5;
  372. }
  373. if ((rv = NetpEventlogWrite(
  374. hEventLog,
  375. EventId,
  376. EVENTLOG_ERROR_TYPE,
  377. NULL,
  378. 0, // no raw data
  379. (LPWSTR *) Strings,
  380. NumberOfStrings
  381. )) != ERROR_SUCCESS)
  382. {
  383. DebugLog((DEB_ERROR, "KdcReportKeyError NetpEventlogWrite( 0x%x ) failed - %u\n", EventId, rv));
  384. }
  385. cleanup:
  386. if (NULL != RequestEtypeString)
  387. {
  388. MIDL_user_free(RequestEtypeString);
  389. }
  390. if (NULL != StoredEtypeString)
  391. {
  392. MIDL_user_free(StoredEtypeString);
  393. }
  394. }
  395. void
  396. KdcReportInvalidMessage(
  397. IN ULONG EventId,
  398. IN PCWSTR pMesageDescription
  399. )
  400. {
  401. ULONG NumberOfStrings;
  402. PWSTR Strings[ MAX_EVENT_STRINGS ] = {0};
  403. DWORD rv;
  404. if (!hEventLog)
  405. {
  406. DebugLog((DEB_ERROR, "KdcReportInvalidMessage cannot log event, no handle!\n"));
  407. return;
  408. }
  409. Strings[0] = (PWSTR) pMesageDescription;
  410. NumberOfStrings = 1;
  411. if ((rv = NetpEventlogWrite(
  412. hEventLog,
  413. EventId,
  414. EVENTLOG_ERROR_TYPE,
  415. NULL,
  416. 0, // no raw data
  417. (LPWSTR *) Strings,
  418. NumberOfStrings
  419. )) != ERROR_SUCCESS)
  420. {
  421. DebugLog((DEB_ERROR, "KdcReportInvalidMessage NetpEventlogWrite( 0x%x ) failed - %u\n", EventId, rv));
  422. }
  423. }
  424. void
  425. KdcReportBadClientCertificate(
  426. IN PUNICODE_STRING CName,
  427. IN PVOID ChainStatus,
  428. IN ULONG ChainStatusSize,
  429. IN DWORD Error
  430. )
  431. {
  432. LPWSTR UCName = NULL;
  433. LPWSTR UCRealm = NULL;
  434. PUNICODE_STRING Realm = SecData.KdcRealmName();
  435. LPWSTR MessageBuffer = NULL;
  436. DWORD MessageSize = 0;
  437. //
  438. // May not want this logged.
  439. //
  440. if (( KdcExtraLogLevel & LOG_PKI_ERRORS ) == 0)
  441. {
  442. return;
  443. }
  444. //
  445. // Put the strings together - Null terminate the buffers...
  446. //
  447. SafeAllocaAllocate(UCName, (CName->MaximumLength + sizeof(WCHAR)) );
  448. if (UCName == NULL)
  449. {
  450. goto Cleanup;
  451. }
  452. RtlZeroMemory(
  453. UCName,
  454. (CName->MaximumLength + sizeof(WCHAR))
  455. );
  456. RtlCopyMemory(
  457. UCName,
  458. CName->Buffer,
  459. CName->Length
  460. );
  461. SafeAllocaAllocate(UCRealm,(Realm->MaximumLength + sizeof(WCHAR)) );
  462. if (UCRealm == NULL)
  463. {
  464. goto Cleanup;
  465. }
  466. RtlZeroMemory(
  467. UCRealm,
  468. (Realm->MaximumLength + sizeof(WCHAR))
  469. );
  470. RtlCopyMemory(
  471. UCRealm,
  472. Realm->Buffer,
  473. Realm->Length
  474. );
  475. MessageSize = FormatMessageW(
  476. FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  477. NULL,
  478. Error,
  479. 0,
  480. (WCHAR*) &MessageBuffer,
  481. MessageSize,
  482. NULL
  483. );
  484. if ( MessageSize == 0)
  485. {
  486. goto Cleanup;
  487. }
  488. ReportServiceEvent(
  489. EVENTLOG_WARNING_TYPE,
  490. KDCEVENT_INVALID_CLIENT_CERTIFICATE,
  491. ChainStatusSize,
  492. ChainStatus,
  493. 3,
  494. UCRealm,
  495. UCName,
  496. MessageBuffer
  497. );
  498. Cleanup:
  499. SafeAllocaFree(UCName);
  500. SafeAllocaFree(UCRealm);
  501. if ( MessageBuffer )
  502. {
  503. LocalFree(MessageBuffer);
  504. }
  505. }
  506. VOID
  507. KdcReportPolicyErrorEvent(
  508. IN ULONG EventType,
  509. IN ULONG EventId,
  510. IN PUNICODE_STRING CName,
  511. IN PUNICODE_STRING SName,
  512. IN NTSTATUS NtStatus,
  513. IN ULONG RawDataSize,
  514. IN OPTIONAL PBYTE RawDataBuffer
  515. )
  516. {
  517. ULONG NumberOfStrings = 0;
  518. PWSTR Strings[ MAX_EVENT_STRINGS ] = {0};
  519. ULONG rv = 0;
  520. if (!hEventLog)
  521. {
  522. DebugLog((DEB_ERROR, "KdcReportPolicyEvent cannot log event, no handle!\n"));
  523. return;
  524. }
  525. //
  526. // may not want this logged
  527. //
  528. if (( KdcExtraLogLevel & LOG_POLICY_ERROR ) == 0)
  529. {
  530. return;
  531. }
  532. if ((EventId == KDCEVENT_POLICY_USER2USER_REQUIRED) && (NtStatus == STATUS_USER2USER_REQUIRED))
  533. {
  534. NumberOfStrings = 2;
  535. //
  536. // this is in the error path, validate buffers
  537. //
  538. if ((CName->Buffer == NULL) || (SName->Buffer == NULL))
  539. {
  540. goto Cleanup;
  541. }
  542. //
  543. // Put the strings together - Null terminate the buffers...
  544. //
  545. SafeAllocaAllocate(Strings[0], (CName->Length + sizeof(WCHAR)));
  546. if (Strings[0] == NULL)
  547. {
  548. goto Cleanup;
  549. }
  550. RtlZeroMemory(
  551. Strings[0],
  552. (CName->Length + sizeof(WCHAR))
  553. );
  554. RtlCopyMemory(
  555. Strings[0],
  556. CName->Buffer,
  557. CName->Length
  558. );
  559. SafeAllocaAllocate(Strings[1], (SName->Length + sizeof(WCHAR)));
  560. if (Strings[1] == NULL)
  561. {
  562. goto Cleanup;
  563. }
  564. RtlZeroMemory(
  565. Strings[1],
  566. (SName->Length + sizeof(WCHAR))
  567. );
  568. RtlCopyMemory(
  569. Strings[1],
  570. SName->Buffer,
  571. SName->Length
  572. );
  573. }
  574. else
  575. {
  576. D_DebugLog((DEB_ERROR, "KdcReportPolicyEvent unsupported event id %#x\n", EventId));
  577. goto Cleanup;
  578. }
  579. if ((rv = NetpEventlogWrite(
  580. hEventLog,
  581. EventId,
  582. EventType,
  583. NULL, // RawDataBuffer
  584. 0, // RawDataSize
  585. (PWSTR *) Strings,
  586. NumberOfStrings
  587. )) != ERROR_SUCCESS)
  588. {
  589. DebugLog((DEB_ERROR, "KdcReportPolicyEvent NetpEventlogWrite( event id %#x ) failed with %#x\n", EventId, rv));
  590. }
  591. Cleanup:
  592. for (ULONG i = 0; i <= NumberOfStrings; i++)
  593. {
  594. SafeAllocaFree(Strings[i]);
  595. }
  596. }
  597. #define S4U_EVENT_STRING_COUNT 3
  598. VOID
  599. KdcReportS4UGroupExpansionError(
  600. IN PUSER_INTERNAL6_INFORMATION UserInfo,
  601. IN PKDC_S4U_TICKET_INFO CallerInfo,
  602. IN DWORD Error
  603. )
  604. {
  605. KERBERR KerbErr;
  606. ULONG rv = 0;
  607. PWSTR CallerSName = NULL;
  608. PWSTR Client = NULL;
  609. PWSTR Strings[S4U_EVENT_STRING_COUNT];
  610. UNICODE_STRING CallerName ={0};
  611. if (!hEventLog)
  612. {
  613. DebugLog((DEB_ERROR, "KdcReportPolicyEvent cannot log event, no handle!\n"));
  614. return;
  615. }
  616. //
  617. // may not want this logged
  618. //
  619. if (( KdcExtraLogLevel & LOG_S4USELF_ACCESS_ERROR ) == 0)
  620. {
  621. return;
  622. }
  623. KerbErr = KerbConvertKdcNameToString(
  624. &CallerName,
  625. CallerInfo->RequestorServiceName,
  626. NULL
  627. );
  628. if (!KERB_SUCCESS( KerbErr ))
  629. {
  630. return;
  631. }
  632. CallerSName = CallerName.Buffer;
  633. //
  634. // Verify that the user info string is null terminated.
  635. //
  636. SafeAllocaAllocate(Client, (UserInfo->I1.UserName.Length + sizeof(WCHAR)));
  637. if (Client == NULL)
  638. {
  639. goto Cleanup;
  640. }
  641. RtlZeroMemory(
  642. Client,
  643. (UserInfo->I1.UserName.Length + sizeof(WCHAR))
  644. );
  645. RtlCopyMemory(
  646. Client,
  647. UserInfo->I1.UserName.Buffer,
  648. UserInfo->I1.UserName.Length
  649. );
  650. Strings[0] = CallerSName;
  651. Strings[1] = CallerInfo->RequestorServiceRealm.Buffer;
  652. Strings[2] = Client;
  653. if ((rv = NetpEventlogWrite(
  654. hEventLog,
  655. KDCEVENT_S4USELF_ACCESS_FAILED,
  656. EVENTLOG_WARNING_TYPE,
  657. (LPBYTE)&Error,
  658. sizeof(DWORD), // RawDataSize
  659. (PWSTR *) Strings,
  660. S4U_EVENT_STRING_COUNT
  661. )) != ERROR_SUCCESS)
  662. {
  663. D_DebugLog((DEB_ERROR, "KdcReportPolicyEvent NetpEventlogWrite( event id %#x ) failed with %#x\n", KDCEVENT_S4USELF_ACCESS_FAILED, rv));
  664. }
  665. Cleanup:
  666. KerbFreeString( &CallerName );
  667. if ( Client )
  668. {
  669. SafeAllocaFree( Client );
  670. }
  671. }