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.

814 lines
19 KiB

  1. //+-----------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (c) Microsoft Corporation 1999
  6. //
  7. // File: events.c
  8. //
  9. // Contents: Schannel event log functions.
  10. //
  11. // Functions: SchInitializeEvents
  12. // SchReportEvent
  13. // SchShutdownEvents
  14. //
  15. // History: 03-05-99 jbanes Created
  16. //
  17. //------------------------------------------------------------------------
  18. #include "sslp.h"
  19. #include <lsapmsgs.h>
  20. #include <netlib.h>
  21. HANDLE g_hEventLog = NULL;
  22. HANDLE g_hDiscardDupEventLog = NULL;
  23. WCHAR EventSourceName[] = TEXT("Schannel");
  24. #define MAX_EVENT_STRINGS 8
  25. #define SCH_MESSAGE_FILENAME TEXT("%SystemRoot%\\system32\\lsasrv.dll")
  26. LPWSTR pszClientString = NULL;
  27. LPWSTR pszServerString = NULL;
  28. NTSTATUS
  29. SchGetMessageString(
  30. LPVOID Resource,
  31. DWORD Index,
  32. LPWSTR * pRetString);
  33. //+---------------------------------------------------------------------------
  34. //
  35. // Function: SchInitializeEvents
  36. //
  37. // Synopsis: Connects to event log service.
  38. //
  39. // Arguments: (none)
  40. //
  41. // History: 03-05-99 jbanes Created
  42. //
  43. // Notes:
  44. //
  45. //----------------------------------------------------------------------------
  46. BOOL
  47. SchInitializeEvents(void)
  48. {
  49. HKEY hKey;
  50. int err;
  51. DWORD disp;
  52. HMODULE hResource;
  53. //
  54. // Create registry entries, whether event logging is currently
  55. // enabled or not.
  56. //
  57. err = RegCreateKeyEx( HKEY_LOCAL_MACHINE,
  58. TEXT("System\\CurrentControlSet\\Services\\EventLog\\System\\Schannel"),
  59. 0,
  60. TEXT(""),
  61. REG_OPTION_NON_VOLATILE,
  62. KEY_WRITE,
  63. NULL,
  64. &hKey,
  65. &disp);
  66. if(err)
  67. {
  68. return(FALSE);
  69. }
  70. if (disp == REG_CREATED_NEW_KEY)
  71. {
  72. RegSetValueEx( hKey,
  73. TEXT("EventMessageFile"),
  74. 0,
  75. REG_EXPAND_SZ,
  76. (PBYTE)SCH_MESSAGE_FILENAME,
  77. sizeof(SCH_MESSAGE_FILENAME) );
  78. // RegSetValueEx( hKey,
  79. // TEXT("CategoryMessageFile"),
  80. // 0,
  81. // REG_EXPAND_SZ,
  82. // (PBYTE)SCH_MESSAGE_FILENAME,
  83. // sizeof(SCH_MESSAGE_FILENAME) );
  84. disp = 7;
  85. RegSetValueEx( hKey,
  86. TEXT("TypesSupported"),
  87. 0,
  88. REG_DWORD,
  89. (PBYTE) &disp,
  90. sizeof(DWORD) );
  91. // disp = CATEGORY_MAX_CATEGORY - 1;
  92. // RegSetValueEx( hKey,
  93. // TEXT("CategoryCount"),
  94. // 0,
  95. // REG_DWORD,
  96. // (PBYTE) &disp,
  97. // sizeof(DWORD) );
  98. RegFlushKey(hKey);
  99. }
  100. RegCloseKey(hKey);
  101. //
  102. // Read the event text strings from the resource file.
  103. //
  104. hResource = (HMODULE)LoadLibrary(TEXT("lsasrv.dll"));
  105. if(hResource == NULL)
  106. {
  107. return(FALSE);
  108. }
  109. SchGetMessageString(hResource,
  110. SSLEVENTTEXT_CLIENT,
  111. &pszClientString);
  112. SchGetMessageString(hResource,
  113. SSLEVENTTEXT_SERVER,
  114. &pszServerString);
  115. FreeLibrary(hResource);
  116. return(TRUE);
  117. }
  118. //+---------------------------------------------------------------------------
  119. //
  120. // Function: SchReportEvent
  121. //
  122. // Synopsis: Reports an event to the event log
  123. //
  124. // Arguments: [EventType] -- EventType (ERROR, WARNING, etc.)
  125. // [EventId] -- Event ID
  126. // [SizeOfRawData] -- Size of raw data
  127. // [RawData] -- Raw data
  128. // [NumberOfStrings] -- number of strings
  129. // ... -- PWSTRs to string data
  130. //
  131. // History: 03-05-99 jbanes Created
  132. //
  133. // Notes:
  134. //
  135. //----------------------------------------------------------------------------
  136. DWORD
  137. SchReportEvent(
  138. IN DWORD LogLevel,
  139. IN DWORD EventType,
  140. IN DWORD EventId,
  141. IN DWORD Category,
  142. IN DWORD SizeOfRawData,
  143. IN PVOID RawData,
  144. IN DWORD NumberOfStrings,
  145. ...
  146. )
  147. {
  148. va_list arglist;
  149. ULONG i;
  150. PWSTR Strings[ MAX_EVENT_STRINGS ];
  151. PSTR StringsA[ MAX_EVENT_STRINGS ];
  152. DWORD Status;
  153. BOOL fDiscardDuplicates = TRUE;
  154. BOOL fSuccess;
  155. //
  156. // Is this event supposed to be logged?
  157. //
  158. if ((g_dwEventLogging & LogLevel) == 0)
  159. {
  160. return ERROR_SUCCESS;
  161. }
  162. //
  163. // Open the event log if necessary.
  164. //
  165. if(g_dwEventLogging == DEFAULT_EVENT_LOGGING_SETTING)
  166. {
  167. // Only log identical event once per hour.
  168. if(g_hDiscardDupEventLog == NULL)
  169. {
  170. g_hDiscardDupEventLog = NetpEventlogOpen(EventSourceName, 60000*60);
  171. if(g_hDiscardDupEventLog == NULL)
  172. {
  173. Status = GetLastError();
  174. DebugLog((DEB_ERROR, "Could not open duplicate discard event log, error %d\n", Status));
  175. return Status;
  176. }
  177. }
  178. }
  179. else
  180. {
  181. // Log all events.
  182. if(g_hEventLog == NULL)
  183. {
  184. g_hEventLog = RegisterEventSource(NULL, EventSourceName);
  185. if(g_hEventLog == NULL)
  186. {
  187. Status = GetLastError();
  188. DebugLog((DEB_ERROR, "Could not open duplicate discard event log, error %d\n", Status));
  189. return Status;
  190. }
  191. }
  192. fDiscardDuplicates = FALSE;
  193. }
  194. //
  195. // Look at the strings, if they were provided
  196. //
  197. va_start( arglist, NumberOfStrings );
  198. if (NumberOfStrings > MAX_EVENT_STRINGS) {
  199. NumberOfStrings = MAX_EVENT_STRINGS;
  200. }
  201. for (i=0; i<NumberOfStrings; i++)
  202. {
  203. Strings[ i ] = va_arg( arglist, PWSTR );
  204. }
  205. //
  206. // Report the event to the eventlog service
  207. //
  208. if(fDiscardDuplicates)
  209. {
  210. fSuccess = NetpEventlogWriteEx(
  211. g_hDiscardDupEventLog,
  212. (WORD) EventType,
  213. (WORD) Category,
  214. EventId,
  215. (WORD)NumberOfStrings,
  216. SizeOfRawData,
  217. Strings,
  218. RawData);
  219. }
  220. else
  221. {
  222. fSuccess = ReportEvent(
  223. g_hEventLog,
  224. (WORD) EventType,
  225. (WORD) Category,
  226. EventId,
  227. NULL,
  228. (WORD)NumberOfStrings,
  229. SizeOfRawData,
  230. Strings,
  231. RawData);
  232. }
  233. if(!fSuccess)
  234. {
  235. Status = GetLastError();
  236. DebugLog((DEB_ERROR, "ReportEvent( %u ) failed - %u\n", EventId, Status));
  237. }
  238. else
  239. {
  240. Status = ERROR_SUCCESS;
  241. }
  242. return Status;
  243. }
  244. void
  245. SchShutdownEvents(void)
  246. {
  247. if(g_hDiscardDupEventLog != NULL)
  248. {
  249. NetpEventlogClose(g_hDiscardDupEventLog);
  250. g_hDiscardDupEventLog = NULL;
  251. }
  252. if(g_hEventLog != NULL)
  253. {
  254. DeregisterEventSource(g_hEventLog);
  255. g_hEventLog = NULL;
  256. }
  257. if(pszClientString)
  258. {
  259. LocalFree(pszClientString);
  260. pszClientString = NULL;
  261. }
  262. if(pszServerString)
  263. {
  264. LocalFree(pszServerString);
  265. pszServerString = NULL;
  266. }
  267. }
  268. void
  269. LogSchannelStartedEvent(void)
  270. {
  271. SchReportEvent( DEB_TRACE,
  272. EVENTLOG_INFORMATION_TYPE,
  273. SSLEVENT_SCHANNEL_STARTED,
  274. 0,
  275. 0,
  276. NULL,
  277. 0,
  278. NULL );
  279. }
  280. void
  281. LogGlobalAcquireContextFailedEvent(
  282. LPWSTR pwszName,
  283. DWORD Status)
  284. {
  285. WCHAR wszStatus[20];
  286. _ltow(Status, wszStatus, 16);
  287. SchReportEvent( DEB_ERROR,
  288. EVENTLOG_ERROR_TYPE,
  289. SSLEVENT_GLOBAL_ACQUIRE_CONTEXT_FAILED,
  290. 0,
  291. 0,
  292. NULL,
  293. 2,
  294. pwszName,
  295. wszStatus);
  296. }
  297. void
  298. LogCreateCredEvent(
  299. DWORD dwProtocol,
  300. PLSA_SCHANNEL_CRED pSchannelCred)
  301. {
  302. SchReportEvent(DEB_TRACE,
  303. EVENTLOG_INFORMATION_TYPE,
  304. SSLEVENT_CREATE_CRED,
  305. 0,
  306. sizeof(SCHANNEL_CRED),
  307. pSchannelCred,
  308. 1,
  309. (dwProtocol & SP_PROT_SERVERS) ? pszServerString : pszClientString);
  310. }
  311. void
  312. LogCredPropertiesEvent(
  313. DWORD dwProtocol,
  314. PCRYPT_KEY_PROV_INFO pProvInfo,
  315. PCCERT_CONTEXT pCertContext)
  316. {
  317. WCHAR wszType[20];
  318. WCHAR wszFlags[20];
  319. LPWSTR pwszKeySpec;
  320. if(!(g_dwEventLogging & DEB_TRACE))
  321. {
  322. return;
  323. }
  324. _ltow(pProvInfo->dwProvType, wszType, 10);
  325. _ltow(pProvInfo->dwFlags, wszFlags, 16);
  326. switch(pProvInfo->dwKeySpec)
  327. {
  328. case AT_KEYEXCHANGE:
  329. pwszKeySpec = L"key exchange";
  330. break;
  331. case AT_SIGNATURE:
  332. pwszKeySpec = L"signature";
  333. break;
  334. default:
  335. pwszKeySpec = L"unknown";
  336. }
  337. SchReportEvent( DEB_TRACE,
  338. EVENTLOG_INFORMATION_TYPE,
  339. SSLEVENT_CRED_PROPERTIES,
  340. 0,
  341. pCertContext->cbCertEncoded,
  342. pCertContext->pbCertEncoded,
  343. 6,
  344. (dwProtocol & SP_PROT_SERVERS) ? pszServerString : pszClientString,
  345. pProvInfo->pwszProvName,
  346. wszType,
  347. pProvInfo->pwszContainerName,
  348. pwszKeySpec,
  349. wszFlags);
  350. }
  351. void
  352. LogNoPrivateKeyEvent(
  353. DWORD dwProtocol)
  354. {
  355. SchReportEvent( DEB_ERROR,
  356. EVENTLOG_ERROR_TYPE,
  357. SSLEVENT_NO_PRIVATE_KEY,
  358. 0,
  359. 0,
  360. NULL,
  361. 1,
  362. (dwProtocol & SP_PROT_SERVERS) ? pszServerString : pszClientString);
  363. }
  364. void
  365. LogCredAcquireContextFailedEvent(
  366. DWORD dwProtocol,
  367. DWORD Status)
  368. {
  369. WCHAR wszStatus[20];
  370. _ltow(Status, wszStatus, 16);
  371. SchReportEvent( DEB_ERROR,
  372. EVENTLOG_ERROR_TYPE,
  373. SSLEVENT_CRED_ACQUIRE_CONTEXT_FAILED,
  374. 0,
  375. 0,
  376. NULL,
  377. 2,
  378. (dwProtocol & SP_PROT_SERVERS) ? pszServerString : pszClientString,
  379. wszStatus);
  380. }
  381. void
  382. LogCreateCredFailedEvent(
  383. DWORD dwProtocol)
  384. {
  385. SchReportEvent(DEB_ERROR,
  386. EVENTLOG_ERROR_TYPE,
  387. SSLEVENT_CREATE_CRED_FAILED,
  388. 0,
  389. 0,
  390. NULL,
  391. 1,
  392. (dwProtocol & SP_PROT_SERVERS) ? pszServerString : pszClientString);
  393. }
  394. void
  395. LogNoDefaultServerCredEvent(void)
  396. {
  397. SchReportEvent(DEB_ERROR,
  398. EVENTLOG_WARNING_TYPE,
  399. SSLEVENT_NO_DEFAULT_SERVER_CRED,
  400. 0,
  401. 0,
  402. NULL,
  403. 0,
  404. NULL);
  405. }
  406. void
  407. LogNoCiphersSupportedEvent(void)
  408. {
  409. SchReportEvent(DEB_ERROR,
  410. EVENTLOG_ERROR_TYPE,
  411. SSLEVENT_NO_CIPHERS_SUPPORTED,
  412. 0,
  413. 0,
  414. NULL,
  415. 0,
  416. NULL);
  417. }
  418. void
  419. LogCipherMismatchEvent(void)
  420. {
  421. SchReportEvent(DEB_ERROR,
  422. EVENTLOG_ERROR_TYPE,
  423. SSLEVENT_CIPHER_MISMATCH,
  424. 0,
  425. 0,
  426. NULL,
  427. 0,
  428. NULL);
  429. }
  430. void
  431. LogNoClientCertFoundEvent(void)
  432. {
  433. SchReportEvent(DEB_WARN,
  434. EVENTLOG_WARNING_TYPE,
  435. SSLEVENT_NO_CLIENT_CERT_FOUND,
  436. 0,
  437. 0,
  438. NULL,
  439. 0,
  440. NULL);
  441. }
  442. void
  443. LogBogusServerCertEvent(
  444. PCCERT_CONTEXT pCertContext,
  445. LPWSTR pwszServerName,
  446. DWORD Status)
  447. {
  448. WCHAR wszStatus[20];
  449. if(!(g_dwEventLogging & DEB_ERROR))
  450. {
  451. return;
  452. }
  453. switch(Status)
  454. {
  455. case SEC_E_CERT_EXPIRED:
  456. SchReportEvent( DEB_ERROR,
  457. EVENTLOG_ERROR_TYPE,
  458. SSLEVENT_EXPIRED_SERVER_CERT,
  459. 0,
  460. pCertContext->cbCertEncoded,
  461. pCertContext->pbCertEncoded,
  462. 0,
  463. NULL);
  464. break;
  465. case SEC_E_UNTRUSTED_ROOT:
  466. SchReportEvent( DEB_ERROR,
  467. EVENTLOG_ERROR_TYPE,
  468. SSLEVENT_UNTRUSTED_SERVER_CERT,
  469. 0,
  470. pCertContext->cbCertEncoded,
  471. pCertContext->pbCertEncoded,
  472. 0,
  473. NULL);
  474. break;
  475. case CRYPT_E_REVOKED:
  476. SchReportEvent( DEB_ERROR,
  477. EVENTLOG_ERROR_TYPE,
  478. SSLEVENT_REVOKED_SERVER_CERT,
  479. 0,
  480. pCertContext->cbCertEncoded,
  481. pCertContext->pbCertEncoded,
  482. 0,
  483. NULL);
  484. break;
  485. case SEC_E_WRONG_PRINCIPAL:
  486. SchReportEvent( DEB_ERROR,
  487. EVENTLOG_ERROR_TYPE,
  488. SSLEVENT_NAME_MISMATCHED_SERVER_CERT,
  489. 0,
  490. pCertContext->cbCertEncoded,
  491. pCertContext->pbCertEncoded,
  492. 1,
  493. pwszServerName);
  494. break;
  495. default:
  496. _ltow(Status, wszStatus, 16);
  497. SchReportEvent( DEB_ERROR,
  498. EVENTLOG_ERROR_TYPE,
  499. SSLEVENT_BOGUS_SERVER_CERT,
  500. 0,
  501. pCertContext->cbCertEncoded,
  502. pCertContext->pbCertEncoded,
  503. 1,
  504. wszStatus);
  505. }
  506. }
  507. void
  508. LogBogusClientCertEvent(
  509. PCCERT_CONTEXT pCertContext,
  510. DWORD Status)
  511. {
  512. WCHAR wszStatus[20];
  513. if(!(g_dwEventLogging & DEB_WARN))
  514. {
  515. return;
  516. }
  517. _ltow(Status, wszStatus, 16);
  518. SchReportEvent( DEB_WARN,
  519. EVENTLOG_WARNING_TYPE,
  520. SSLEVENT_BOGUS_CLIENT_CERT,
  521. 0,
  522. pCertContext->cbCertEncoded,
  523. pCertContext->pbCertEncoded,
  524. 1,
  525. wszStatus);
  526. }
  527. void
  528. LogFastMappingFailureEvent(
  529. PCCERT_CONTEXT pCertContext,
  530. DWORD Status)
  531. {
  532. WCHAR wszStatus[20];
  533. if(!(g_dwEventLogging & DEB_WARN))
  534. {
  535. return;
  536. }
  537. _ltow(Status, wszStatus, 16);
  538. SchReportEvent( DEB_WARN,
  539. EVENTLOG_WARNING_TYPE,
  540. SSLEVENT_FAST_MAPPING_FAILURE,
  541. 0,
  542. pCertContext->cbCertEncoded,
  543. pCertContext->pbCertEncoded,
  544. 1,
  545. wszStatus);
  546. }
  547. void
  548. LogCertMappingFailureEvent(
  549. DWORD Status)
  550. {
  551. WCHAR wszStatus[20];
  552. if(!(g_dwEventLogging & DEB_WARN))
  553. {
  554. return;
  555. }
  556. _ltow(Status, wszStatus, 16);
  557. SchReportEvent( DEB_WARN,
  558. EVENTLOG_WARNING_TYPE,
  559. SSLEVENT_CERT_MAPPING_FAILURE,
  560. 0,
  561. 0,
  562. NULL,
  563. 1,
  564. wszStatus);
  565. }
  566. void
  567. LogHandshakeInfoEvent(
  568. DWORD dwProtocol,
  569. PCipherInfo pCipherInfo,
  570. PHashInfo pHashInfo,
  571. PKeyExchangeInfo pExchangeInfo,
  572. DWORD dwExchangeStrength)
  573. {
  574. WCHAR wszCipherStrength[20];
  575. WCHAR wszExchangeStrength[20];
  576. LPWSTR pwszProtocol;
  577. LPWSTR pwszCipher;
  578. LPWSTR pwszHash;
  579. LPWSTR pwszExchange;
  580. if(!(g_dwEventLogging & DEB_TRACE))
  581. {
  582. return;
  583. }
  584. switch(dwProtocol)
  585. {
  586. case SP_PROT_PCT1_SERVER:
  587. case SP_PROT_PCT1_CLIENT:
  588. pwszProtocol = L"PCT";
  589. break;
  590. case SP_PROT_SSL2_SERVER:
  591. case SP_PROT_SSL2_CLIENT:
  592. pwszProtocol = L"SSL 2.0";
  593. break;
  594. case SP_PROT_SSL3_SERVER:
  595. case SP_PROT_SSL3_CLIENT:
  596. pwszProtocol = L"SSL 3.0";
  597. break;
  598. case SP_PROT_TLS1_SERVER:
  599. case SP_PROT_TLS1_CLIENT:
  600. pwszProtocol = L"TLS (SSL 3.1)";
  601. break;
  602. default:
  603. pwszProtocol = L"unknown";
  604. }
  605. switch(pCipherInfo->aiCipher)
  606. {
  607. case CALG_RC4:
  608. pwszCipher = L"RC4";
  609. break;
  610. case CALG_3DES:
  611. pwszCipher = L"Triple-DES";
  612. break;
  613. case CALG_RC2:
  614. pwszCipher = L"RC2";
  615. break;
  616. case CALG_DES:
  617. pwszCipher = L"DES";
  618. break;
  619. case CALG_SKIPJACK:
  620. pwszCipher = L"Skipjack";
  621. break;
  622. default:
  623. pwszCipher = L"unknown";
  624. }
  625. _ltow(pCipherInfo->dwStrength, wszCipherStrength, 10);
  626. switch(pHashInfo->aiHash)
  627. {
  628. case CALG_MD5:
  629. pwszHash = L"MD5";
  630. break;
  631. case CALG_SHA:
  632. pwszHash = L"SHA";
  633. break;
  634. default:
  635. pwszHash = L"unknown";
  636. }
  637. switch(pExchangeInfo->aiExch)
  638. {
  639. case CALG_RSA_SIGN:
  640. case CALG_RSA_KEYX:
  641. pwszExchange = L"RSA";
  642. break;
  643. case CALG_KEA_KEYX:
  644. pwszExchange = L"KEA";
  645. break;
  646. case CALG_DH_EPHEM:
  647. pwszExchange = L"Ephemeral DH";
  648. break;
  649. default:
  650. pwszExchange = L"unknown";
  651. }
  652. _ltow(dwExchangeStrength, wszExchangeStrength, 10);
  653. SchReportEvent( DEB_TRACE,
  654. EVENTLOG_INFORMATION_TYPE,
  655. SSLEVENT_HANDSHAKE_INFO,
  656. 0,
  657. 0,
  658. NULL,
  659. 7,
  660. (dwProtocol & SP_PROT_SERVERS) ? pszServerString : pszClientString,
  661. pwszProtocol,
  662. pwszCipher,
  663. wszCipherStrength,
  664. pwszHash,
  665. pwszExchange,
  666. wszExchangeStrength);
  667. }
  668. NTSTATUS
  669. SchGetMessageString(
  670. LPVOID Resource,
  671. DWORD Index,
  672. LPWSTR * pRetString)
  673. {
  674. DWORD Length;
  675. *pRetString = NULL;
  676. Length = FormatMessage(FORMAT_MESSAGE_FROM_HMODULE |
  677. FORMAT_MESSAGE_ALLOCATE_BUFFER,
  678. Resource,
  679. Index,
  680. 0, // Use caller's language
  681. (LPWSTR)pRetString,
  682. 0,
  683. NULL);
  684. if(Length == 0 || *pRetString == NULL)
  685. {
  686. return(STATUS_RESOURCE_DATA_NOT_FOUND);
  687. }
  688. //
  689. // Note that we are retrieving a message from a message file.
  690. // This message will have a cr/lf tacked on the end of it
  691. // (0x0d 0x0a) that we don't want to be part of our returned
  692. // strings. However, we do need to null terminate our string
  693. // so we will convert the 0x0d into a null terminator.
  694. //
  695. // Also note that FormatMessage() returns a character count,
  696. // not a byte count. So, we have to do some adjusting to make
  697. // the string lengths correct.
  698. //
  699. ASSERT(Length >= 2); // We always expect cr/lf on our strings
  700. //
  701. // Adjust character count
  702. //
  703. Length -= 1; // For the lf - we'll convert the cr.
  704. //
  705. // Set null terminator
  706. //
  707. (*pRetString)[Length - 1] = 0;
  708. return(STATUS_SUCCESS);
  709. }