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.

812 lines
20 KiB

  1. //+-----------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (c) Microsoft Corporation 1991 - 1992
  6. //
  7. // File: util.c
  8. //
  9. // Contents: General Purpose functions for the security interface
  10. //
  11. // Functions: SPException -- Handler for exceptions in packages
  12. // WLsaControlFunction -- Worker for SecurityPackageControl()
  13. // LsaControlFunction -- User mode stub
  14. // LsaQueryPackage -- User mode stub
  15. //
  16. //
  17. // History: 14 Aug 92 RichardW Created
  18. //
  19. //------------------------------------------------------------------------
  20. #include <lsapch.hxx>
  21. extern "C"
  22. {
  23. #include "sesmgr.h"
  24. }
  25. //+---------------------------------------------------------------------------
  26. //
  27. // Function: SpExceptionFilter
  28. //
  29. // Synopsis: General Exception filter, invoked by the SP_EXCEPTION macro.
  30. //
  31. // Arguments: [pSession] --
  32. // [pException] --
  33. //
  34. //
  35. // History: 8-09-95 RichardW Created
  36. //
  37. // Notes:
  38. //
  39. //----------------------------------------------------------------------------
  40. LONG
  41. SpExceptionFilter( PVOID pSession,
  42. EXCEPTION_POINTERS * pException)
  43. {
  44. DWORD_PTR CurrentPackage;
  45. PLSAP_SECURITY_PACKAGE pPackage = NULL;
  46. UNICODE_STRING LsaString = { 3 * sizeof( WCHAR ), 4 * sizeof( WCHAR ), L"LSA" };
  47. CurrentPackage = GetCurrentPackageId();
  48. if (CurrentPackage != SPMGR_ID)
  49. {
  50. pPackage = SpmpLocatePackage( CurrentPackage );
  51. }
  52. SpmpReportEventU(
  53. EVENTLOG_ERROR_TYPE,
  54. SPMEVENT_PACKAGE_FAULT,
  55. CATEGORY_SPM,
  56. sizeof(EXCEPTION_RECORD),
  57. pException->ExceptionRecord,
  58. 1,
  59. ((CurrentPackage == SPMGR_ID || pPackage == NULL) ?
  60. &LsaString :
  61. &pPackage->Name )
  62. );
  63. if (pException->ExceptionRecord->ExceptionCode != STATUS_POSSIBLE_DEADLOCK)
  64. {
  65. //
  66. // Fail new calls (just in case we don't go away immediately)
  67. //
  68. ShutdownBegun = TRUE;
  69. }
  70. return EXCEPTION_CONTINUE_SEARCH;
  71. }
  72. //+-------------------------------------------------------------------------
  73. //
  74. // Function: SPException
  75. //
  76. // Synopsis: Handles an exception in a security package.
  77. //
  78. // Effects: Varies, but may force an unload of a package.
  79. //
  80. // Arguments:
  81. //
  82. // Requires:
  83. //
  84. // Returns:
  85. //
  86. // Notes: This routine should, ideally, never be called as
  87. // SpExceptionFilter should always bubble the exception
  88. // all the way up to the top-level handler (i.e., the
  89. // unhandled exception filter), causing the LSA to exit.
  90. // However, just in case something catches the exception
  91. // and presses on, we'll disable the package as a
  92. // token effort.
  93. //
  94. //--------------------------------------------------------------------------
  95. NTSTATUS
  96. SPException(NTSTATUS scRet,
  97. ULONG_PTR dwPackageID)
  98. {
  99. PSession pSession;
  100. PLSAP_SECURITY_PACKAGE pPackage;
  101. #if DBG
  102. PSpmExceptDbg pException = (PSpmExceptDbg) TlsGetValue(dwExceptionInfo);
  103. #endif
  104. pSession = GetCurrentSession();
  105. DebugLog((DEB_ERROR, "[%x] Exception in a package, code %x\n", pSession->dwProcessID, scRet));
  106. DebugLog((DEB_ERROR, "[%x] Address was @%x, %s address %x\n",
  107. pSession->dwProcessID,
  108. pException->pInstruction,
  109. (pException->Access ? "write" : "read"),
  110. pException->pMemory));
  111. if (dwPackageID == SPMGR_ID)
  112. {
  113. DebugLog((DEB_ERROR, " LSA itself hit a fault, thread %d\n", GetCurrentThreadId()));
  114. DebugLog((DEB_ERROR, " (ExceptionInfo @%x)\n", TlsGetValue(dwExceptionInfo)));
  115. #if DBG
  116. DsysAssertMsg( 0, "exception in LSA" );
  117. #endif
  118. return(scRet);
  119. }
  120. pPackage = SpmpLocatePackage( dwPackageID );
  121. if (!pPackage)
  122. {
  123. DebugLog((DEB_ERROR, " Invalid package ID passed\n"));
  124. return(scRet);
  125. }
  126. if ((scRet == STATUS_ACCESS_VIOLATION) ||
  127. (scRet == E_POINTER))
  128. {
  129. DebugLog((DEB_ERROR, " Package %ws created an access violation\n",
  130. pPackage->Name.Buffer));
  131. // Flag package as invalid
  132. pPackage->fPackage |= SP_INVALID;
  133. }
  134. if ((scRet == STATUS_NO_MEMORY) ||
  135. (scRet == STATUS_INSUFFICIENT_RESOURCES))
  136. {
  137. DebugLog((DEB_ERROR, " Out of memory situation exists\n"));
  138. DebugLog((DEB_ERROR, " Further requests may fail unless memory is freed\n"));
  139. }
  140. //
  141. // if the code is a success code, it is probably a WIN32 error so we
  142. // map it as such
  143. return(scRet);
  144. }
  145. //+-------------------------------------------------------------------------
  146. //
  147. // Function: WLsaQueryPackage
  148. //
  149. // Synopsis: Get info on a package (short enum), copy to client's address
  150. // space
  151. //
  152. // Effects: none
  153. //
  154. // Arguments:
  155. //
  156. // Requires:
  157. //
  158. // Returns:
  159. //
  160. // Notes:
  161. //
  162. //--------------------------------------------------------------------------
  163. NTSTATUS
  164. WLsaQueryPackageInfo(
  165. PSECURITY_STRING pPackageName,
  166. PSecPkgInfo * ppInfo
  167. )
  168. {
  169. NTSTATUS scRet;
  170. PLSAP_SECURITY_PACKAGE pPackage;
  171. WCHAR * pszString;
  172. PSession pSession = GetCurrentSession();
  173. ULONG cbData;
  174. PSecPkgInfo pClientInfo = NULL;
  175. PBYTE Where;
  176. UNICODE_STRING CommentString;
  177. UNICODE_STRING NameString;
  178. PSecPkgInfo pLocalInfo = NULL;
  179. SecPkgInfo PackageInfo = { 0 };
  180. LONG_PTR ClientOffset;
  181. ULONG ulStructureSize = sizeof(SecPkgInfo);
  182. DebugLog((DEB_TRACE, "QueryPackage\n"));
  183. *ppInfo = NULL;
  184. pPackage = SpmpLookupPackage(pPackageName);
  185. if (!pPackage)
  186. {
  187. return(STATUS_NO_SUCH_PACKAGE);
  188. }
  189. SetCurrentPackageId(pPackage->dwPackageID);
  190. StartCallToPackage( pPackage );
  191. __try
  192. {
  193. scRet = pPackage->FunctionTable.GetInfo(&PackageInfo);
  194. }
  195. __except (SP_EXCEPTION)
  196. {
  197. scRet = GetExceptionCode();
  198. scRet = SPException(scRet, pPackage->dwPackageID);
  199. }
  200. EndCallToPackage( pPackage );
  201. if (FAILED(scRet))
  202. {
  203. return(scRet);
  204. }
  205. //
  206. // Marshall the data to copy to the client
  207. //
  208. RtlInitUnicodeString(
  209. &NameString,
  210. PackageInfo.Name
  211. );
  212. RtlInitUnicodeString(
  213. &CommentString,
  214. PackageInfo.Comment
  215. );
  216. cbData = ulStructureSize +
  217. NameString.MaximumLength +
  218. CommentString.MaximumLength;
  219. SafeAllocaAllocate(pLocalInfo, cbData);
  220. if (pLocalInfo == NULL)
  221. {
  222. return(STATUS_INSUFFICIENT_RESOURCES);
  223. }
  224. pClientInfo = (PSecPkgInfo) LsapClientAllocate(cbData);
  225. if (pClientInfo == NULL)
  226. {
  227. SafeAllocaFree(pLocalInfo);
  228. return(STATUS_INSUFFICIENT_RESOURCES);
  229. }
  230. ClientOffset = (LONG_PTR) ((PBYTE) pClientInfo - (PBYTE) pLocalInfo);
  231. Where = (PBYTE) (pLocalInfo + 1);
  232. *pLocalInfo = PackageInfo;
  233. pLocalInfo->Name = (LPWSTR) (Where + ClientOffset);
  234. RtlCopyMemory(
  235. Where,
  236. NameString.Buffer,
  237. NameString.MaximumLength
  238. );
  239. Where += NameString.MaximumLength;
  240. pLocalInfo->Comment = (LPWSTR) (Where + ClientOffset);
  241. RtlCopyMemory(
  242. Where,
  243. CommentString.Buffer,
  244. CommentString.MaximumLength
  245. );
  246. Where += CommentString.MaximumLength;
  247. DsysAssert(Where - (PBYTE) pLocalInfo == (LONG) cbData);
  248. scRet = LsapCopyToClient(
  249. pLocalInfo,
  250. pClientInfo,
  251. cbData);
  252. SafeAllocaFree(pLocalInfo);
  253. if (FAILED(scRet))
  254. {
  255. LsapClientFree(pClientInfo);
  256. pClientInfo = NULL;
  257. }
  258. *ppInfo = pClientInfo;
  259. return(scRet);
  260. }
  261. //+-------------------------------------------------------------------------
  262. //
  263. // Function: WLsaGetSecurityUserInfo
  264. //
  265. // Synopsis: worker function to get info about a logon session
  266. //
  267. // Effects:
  268. //
  269. // Arguments:
  270. //
  271. // Requires:
  272. //
  273. // Returns:
  274. //
  275. // Notes:
  276. //
  277. //
  278. //--------------------------------------------------------------------------
  279. NTSTATUS
  280. WLsaGetSecurityUserInfo(
  281. IN PLUID pLogonId,
  282. IN ULONG fFlags,
  283. OUT PSECURITY_USER_DATA * pUserInfo
  284. )
  285. {
  286. PLSAP_LOGON_SESSION pSession;
  287. NTSTATUS Status;
  288. PSECURITY_USER_DATA LocalUserData = NULL;
  289. PSECURITY_USER_DATA ClientBuffer = NULL;
  290. SECPKG_CLIENT_INFO ClientInfo;
  291. ULONG BufferSize;
  292. PUCHAR Where;
  293. LONG_PTR Offset;
  294. ULONG ulStructureSize = sizeof(SECURITY_USER_DATA);
  295. DebugLog((DEB_TRACE_WAPI,"WLsaGetSecurityUserInfo called\n"));
  296. //
  297. // if the logon ID is null, it is for the caller
  298. // so we know to go to the primary package.
  299. //
  300. if (pLogonId == NULL)
  301. {
  302. Status = LsapGetClientInfo(&ClientInfo);
  303. if (!NT_SUCCESS(Status))
  304. {
  305. return Status;
  306. }
  307. pLogonId = &ClientInfo.LogonId;
  308. }
  309. pSession = LsapLocateLogonSession( pLogonId );
  310. if (!pSession)
  311. {
  312. DebugLog((DEB_WARN,"WLsaGetSecurityUserInfo called for non-existent LUID 0x%x:0x%x\n",
  313. pLogonId->LowPart,pLogonId->HighPart));
  314. Status = STATUS_NO_SUCH_LOGON_SESSION;
  315. goto Cleanup;
  316. }
  317. BufferSize = ulStructureSize +
  318. pSession->AccountName.Length +
  319. pSession->AuthorityName.Length +
  320. pSession->LogonServer.Length +
  321. RtlLengthSid(pSession->UserSid);
  322. SafeAllocaAllocate(LocalUserData, BufferSize);
  323. if (LocalUserData == NULL)
  324. {
  325. Status = STATUS_INSUFFICIENT_RESOURCES;
  326. goto Cleanup;
  327. }
  328. ClientBuffer = (PSECURITY_USER_DATA) LsapClientAllocate(BufferSize);
  329. if (ClientBuffer == NULL)
  330. {
  331. Status = STATUS_INSUFFICIENT_RESOURCES;
  332. goto Cleanup;
  333. }
  334. Offset = (LONG_PTR) ((PUCHAR) ClientBuffer - (PUCHAR) LocalUserData);
  335. Where = (PUCHAR) (LocalUserData + 1);
  336. //
  337. // Copy in all the fields from the logon session.
  338. //
  339. LocalUserData->pSid = (PSID) (Where + Offset);
  340. RtlCopyMemory(
  341. Where,
  342. pSession->UserSid,
  343. RtlLengthSid(pSession->UserSid)
  344. );
  345. Where += RtlLengthSid(pSession->UserSid);
  346. //
  347. // Copy in the user name
  348. //
  349. LocalUserData->UserName.Length =
  350. LocalUserData->UserName.MaximumLength = pSession->AccountName.Length;
  351. LocalUserData->UserName.Buffer = (LPWSTR) (Where + Offset);
  352. RtlCopyMemory(
  353. Where,
  354. pSession->AccountName.Buffer,
  355. pSession->AccountName.Length
  356. );
  357. Where += pSession->AccountName.Length;
  358. //
  359. // Copy in the domain name
  360. //
  361. LocalUserData->LogonDomainName.Length =
  362. LocalUserData->LogonDomainName.MaximumLength = pSession->AuthorityName.Length;
  363. LocalUserData->LogonDomainName.Buffer = (LPWSTR) (Where + Offset);
  364. RtlCopyMemory(
  365. Where,
  366. pSession->AuthorityName.Buffer,
  367. pSession->AuthorityName.Length
  368. );
  369. Where += pSession->AuthorityName.Length;
  370. //
  371. // Copy in the logon server
  372. //
  373. LocalUserData->LogonServer.Length =
  374. LocalUserData->LogonServer.MaximumLength = pSession->LogonServer.Length;
  375. LocalUserData->LogonServer.Buffer = (LPWSTR) (Where + Offset);
  376. RtlCopyMemory(
  377. Where,
  378. pSession->LogonServer.Buffer,
  379. pSession->LogonServer.Length
  380. );
  381. Where += pSession->LogonServer.Length;
  382. //
  383. // Copy this to the client
  384. //
  385. LsapReleaseLogonSession( pSession );
  386. pSession = NULL;
  387. Status = LsapCopyToClient(
  388. LocalUserData,
  389. ClientBuffer,
  390. BufferSize
  391. );
  392. if (!NT_SUCCESS(Status))
  393. {
  394. goto Cleanup;
  395. }
  396. *pUserInfo = ClientBuffer;
  397. ClientBuffer = NULL;
  398. Cleanup:
  399. SafeAllocaFree(LocalUserData);
  400. if (ClientBuffer != NULL)
  401. {
  402. LsapClientFree(ClientBuffer);
  403. }
  404. if (pSession != NULL)
  405. {
  406. LsapReleaseLogonSession(pSession);
  407. pSession = NULL;
  408. }
  409. DebugLog((DEB_TRACE_WAPI,"GetUserInfo returned %x\n",Status));
  410. return(Status);
  411. }
  412. HANDLE hEventLog = INVALID_HANDLE_VALUE;
  413. DWORD LoggingLevel = (1 << EVENTLOG_ERROR_TYPE) | (1 << EVENTLOG_WARNING_TYPE) |
  414. (1 << EVENTLOG_INFORMATION_TYPE) ;
  415. WCHAR EventSourceName[] = TEXT("LsaSrv");
  416. #define MAX_EVENT_STRINGS 8
  417. //+---------------------------------------------------------------------------
  418. //
  419. // Function: SpmpInitializeEvents
  420. //
  421. // Synopsis: Connects to event log service
  422. //
  423. // Arguments: (none)
  424. //
  425. // History: 1-03-95 RichardW Created
  426. //
  427. // Notes:
  428. //
  429. //----------------------------------------------------------------------------
  430. BOOL
  431. SpmpInitializeEvents(void)
  432. {
  433. HKEY hKey;
  434. int err;
  435. DWORD disp;
  436. err = RegCreateKeyEx( HKEY_LOCAL_MACHINE,
  437. TEXT("System\\CurrentControlSet\\Services\\EventLog\\System\\LsaSrv"),
  438. 0,
  439. TEXT(""),
  440. REG_OPTION_NON_VOLATILE,
  441. KEY_WRITE,
  442. NULL,
  443. &hKey,
  444. &disp);
  445. if (err)
  446. {
  447. return(FALSE);
  448. }
  449. if (disp == REG_CREATED_NEW_KEY)
  450. {
  451. RegSetValueEx( hKey,
  452. TEXT("EventMessageFile"),
  453. 0,
  454. REG_EXPAND_SZ,
  455. (PBYTE) TEXT("%SystemRoot%\\system32\\lsasrv.dll"),
  456. sizeof(TEXT("%SystemRoot%\\system32\\lsasrv.dll")) );
  457. RegSetValueEx( hKey,
  458. TEXT("CategoryMessageFile"),
  459. 0,
  460. REG_EXPAND_SZ,
  461. (PBYTE) TEXT("%SystemRoot%\\system32\\lsasrv.dll"),
  462. sizeof(TEXT("%SystemRoot%\\system32\\lsasrv.dll")) );
  463. disp = 7;
  464. RegSetValueEx( hKey,
  465. TEXT("TypesSupported"),
  466. 0,
  467. REG_DWORD,
  468. (PBYTE) &disp,
  469. sizeof(DWORD) );
  470. disp = CATEGORY_MAX_CATEGORY - 1;
  471. RegSetValueEx( hKey,
  472. TEXT("CategoryCount"),
  473. 0,
  474. REG_DWORD,
  475. (PBYTE) &disp,
  476. sizeof(DWORD) );
  477. }
  478. RegCloseKey(hKey);
  479. hEventLog = RegisterEventSource(NULL, EventSourceName);
  480. if (hEventLog)
  481. {
  482. return(TRUE);
  483. }
  484. hEventLog = INVALID_HANDLE_VALUE;
  485. DebugLog((DEB_ERROR, "Could not open event log, error %d\n", GetLastError()));
  486. return(FALSE);
  487. }
  488. //+---------------------------------------------------------------------------
  489. //
  490. // Function: SpmpReportEvent
  491. //
  492. // Synopsis: Reports an event to the event log
  493. //
  494. // Arguments: [EventType] -- EventType (ERROR, WARNING, etc.)
  495. // [EventId] -- Event ID
  496. // [SizeOfRawData] -- Size of raw data
  497. // [RawData] -- Raw data
  498. // [NumberOfStrings] -- number of strings
  499. // ... -- PWSTRs to string data
  500. //
  501. // History: 1-03-95 RichardW Created
  502. //
  503. // Notes:
  504. //
  505. //----------------------------------------------------------------------------
  506. DWORD
  507. SpmpReportEvent(
  508. IN BOOL Unicode,
  509. IN WORD EventType,
  510. IN DWORD EventId,
  511. IN DWORD Category,
  512. IN DWORD SizeOfRawData,
  513. IN PVOID RawData,
  514. IN DWORD NumberOfStrings,
  515. ...
  516. )
  517. {
  518. va_list arglist;
  519. ULONG i;
  520. PWSTR Strings[ MAX_EVENT_STRINGS ];
  521. PSTR StringsA[ MAX_EVENT_STRINGS ];
  522. DWORD rv;
  523. if (hEventLog == INVALID_HANDLE_VALUE)
  524. {
  525. if (!SpmpInitializeEvents())
  526. {
  527. return((DWORD) -1);
  528. }
  529. }
  530. //
  531. // We're not supposed to be logging this, so nuke it
  532. //
  533. if ((LoggingLevel & (1 << EventType)) == 0)
  534. {
  535. return(0);
  536. }
  537. //
  538. // Look at the strings, if they were provided
  539. //
  540. va_start( arglist, NumberOfStrings );
  541. if (NumberOfStrings > MAX_EVENT_STRINGS) {
  542. NumberOfStrings = MAX_EVENT_STRINGS;
  543. }
  544. for (i=0; i<NumberOfStrings; i++) {
  545. if (Unicode)
  546. {
  547. Strings[ i ] = va_arg( arglist, PWSTR );
  548. }
  549. else
  550. {
  551. StringsA[ i ] = va_arg( arglist, PSTR );
  552. }
  553. }
  554. //
  555. // Report the event to the eventlog service
  556. //
  557. if (Unicode)
  558. {
  559. if (!ReportEventW( hEventLog,
  560. EventType,
  561. (WORD) Category,
  562. EventId,
  563. NULL,
  564. (WORD)NumberOfStrings,
  565. SizeOfRawData,
  566. (const WCHAR * *) Strings,
  567. RawData) )
  568. {
  569. rv = GetLastError();
  570. DebugLog((DEB_ERROR, "ReportEvent( %u ) failed - %u\n", EventId, GetLastError() ));
  571. }
  572. else
  573. {
  574. rv = ERROR_SUCCESS;
  575. }
  576. }
  577. else
  578. {
  579. if (!ReportEventA( hEventLog,
  580. EventType,
  581. (WORD) Category,
  582. EventId,
  583. NULL,
  584. (WORD)NumberOfStrings,
  585. SizeOfRawData,
  586. (const char * *) StringsA,
  587. RawData) )
  588. {
  589. rv = GetLastError();
  590. DebugLog((DEB_ERROR, "ReportEvent( %u ) failed - %u\n", EventId, GetLastError() ));
  591. }
  592. else
  593. {
  594. rv = ERROR_SUCCESS;
  595. }
  596. }
  597. return rv;
  598. }
  599. //+---------------------------------------------------------------------------
  600. //
  601. // Function: SpmpReportEventU
  602. //
  603. // Synopsis: Reports an event to the event log
  604. //
  605. // Arguments: [EventType] -- EventType (ERROR, WARNING, etc.)
  606. // [EventId] -- Event ID
  607. // [SizeOfRawData] -- Size of raw data
  608. // [RawData] -- Raw data
  609. // [NumberOfStrings] -- number of strings
  610. // ... -- PUNICODE_STRINGs to string data
  611. //
  612. // Notes:
  613. //
  614. //----------------------------------------------------------------------------
  615. DWORD
  616. SpmpReportEventU(
  617. IN WORD EventType,
  618. IN DWORD EventId,
  619. IN DWORD Category,
  620. IN DWORD SizeOfRawData,
  621. IN PVOID RawData,
  622. IN DWORD NumberOfStrings,
  623. ...
  624. )
  625. {
  626. va_list arglist;
  627. ULONG i;
  628. PUNICODE_STRING Strings[ MAX_EVENT_STRINGS ];
  629. DWORD rv;
  630. if (hEventLog == INVALID_HANDLE_VALUE) {
  631. if ( !SpmpInitializeEvents()) {
  632. return( -1 );
  633. }
  634. }
  635. //
  636. // We're not supposed to be logging this, so nuke it
  637. //
  638. if (( LoggingLevel & ( 1 << EventType )) == 0 ) {
  639. return( 0 );
  640. }
  641. //
  642. // Look at the strings, if they were provided
  643. //
  644. va_start( arglist, NumberOfStrings );
  645. if ( NumberOfStrings > MAX_EVENT_STRINGS ) {
  646. NumberOfStrings = MAX_EVENT_STRINGS;
  647. }
  648. for ( i = 0 ; i < NumberOfStrings ; i++ ) {
  649. Strings[ i ] = va_arg( arglist, PUNICODE_STRING );
  650. }
  651. //
  652. // Report the event to the eventlog service
  653. //
  654. rv = ElfReportEventW(
  655. hEventLog,
  656. EventType,
  657. ( USHORT )Category,
  658. EventId,
  659. NULL,
  660. ( USHORT )NumberOfStrings,
  661. SizeOfRawData,
  662. Strings,
  663. RawData,
  664. 0,
  665. NULL,
  666. NULL
  667. );
  668. if ( !NT_SUCCESS( rv )) {
  669. DebugLog((DEB_ERROR, "ReportEvent( %u ) failed - %u\n", EventId, rv ));
  670. goto Cleanup;
  671. }
  672. rv = ERROR_SUCCESS;
  673. Cleanup:
  674. return rv;
  675. }