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.

1064 lines
32 KiB

  1. //Copyright (c) 1998 - 1999 Microsoft Corporation
  2. /*******************************************************************************
  3. *
  4. * security.c
  5. *
  6. * WinStation ACL editing functions (based on code from NT PRINTMAN security.c)
  7. *
  8. * copyright notice: Copyright 1995, Citrix Systems Inc.
  9. *
  10. * $Author: donm $ Butch Davis
  11. *
  12. * $Log: N:\nt\private\utils\citrix\winutils\tscfg\VCS\security.c $
  13. *
  14. * Rev 1.12 19 Mar 1998 16:38:40 donm
  15. * was looking for old help file
  16. *
  17. * Rev 1.11 20 Sep 1996 20:37:18 butchd
  18. * update
  19. *
  20. * Rev 1.10 19 Sep 1996 15:58:44 butchd
  21. * update
  22. *
  23. * Rev 1.9 12 Sep 1996 16:16:38 butchd
  24. * update
  25. *
  26. *******************************************************************************/
  27. /*
  28. * We must compile for UNICODE because of ACL edit structures & interface, which
  29. * is UNICODE-only.
  30. */
  31. #ifndef UNICODE
  32. #define UNICODE 1
  33. #endif
  34. #ifndef _UNICODE
  35. #define _UNICODE 1
  36. #endif
  37. /*
  38. * include files
  39. */
  40. #include <stdio.h>
  41. #include <stdlib.h>
  42. #include <string.h>
  43. #include <windows.h>
  44. #include <tchar.h>
  45. #include <wchar.h>
  46. #include <sedapi.h>
  47. #include <winsta.h>
  48. #include "defines.h"
  49. #include "resource.h"
  50. #include "security.h"
  51. #include "common.h"
  52. #include <utildll.h>
  53. /*
  54. * Global variables for WINUTILS Common functions.
  55. */
  56. LPCTSTR WinUtilsAppName;
  57. HWND WinUtilsAppWindow;
  58. HINSTANCE WinUtilsAppInstance;
  59. ////////////////////////////////////////////////////////////////////////////////
  60. // typedefs, defines, persistant storage, and private function prototypes
  61. /*
  62. * Indexes into the APPLICATION_ACCESSES structure:
  63. */
  64. #define PERMS_SPECIAL_QUERY 0 /* query information access */
  65. #define PERMS_SPECIAL_SET 1 /* set information access */
  66. #define PERMS_SPECIAL_RESET 2 /* reset access */
  67. #define PERMS_SPECIAL_SHADOW 3 /* shadow access */
  68. #define PERMS_SPECIAL_LOGON 4 /* logon access */
  69. #define PERMS_SPECIAL_LOGOFF 5 /* logoff access */
  70. #define PERMS_SPECIAL_MSG 6 /* message access */
  71. #define PERMS_SPECIAL_CONNECT 7 /* connect access */
  72. #define PERMS_SPECIAL_DISCONNECT 8 /* disconnect access */
  73. #define PERMS_SPECIAL_DELETE 9 /* delete access */
  74. #define PERMS_RESOURCE_NOACCESS 10 /* no access grouping */
  75. #define PERMS_RESOURCE_GUEST 11 /* guest access grouping */
  76. #define PERMS_RESOURCE_USER 12 /* user access grouping */
  77. #define PERMS_RESOURCE_ADMIN 13 /* all (admin) access grouping */
  78. #define PERMS_COUNT 14 /* Total number of permissions */
  79. /*
  80. * Typedefs and static storage.
  81. */
  82. typedef struct _SECURITY_CONTEXT
  83. {
  84. PWINSTATIONNAME pWSName;
  85. }
  86. SECURITY_CONTEXT, *PSECURITY_CONTEXT;
  87. /*
  88. * We need this structure even though we're not doing generic access mapping.
  89. */
  90. GENERIC_MAPPING GenericMapping =
  91. { /* GenericMapping: */
  92. GENERIC_READ, /* GenericRead */
  93. GENERIC_WRITE, /* GenericWrite */
  94. GENERIC_EXECUTE, /* GenericExecute */
  95. GENERIC_ALL /* GenericAll */
  96. };
  97. WCHAR szLWinCfgHlp[] = L"TSCFG.HLP";
  98. TCHAR szAclEdit[] = TEXT("ACLEDIT"); /* DLL containing ACL Edit Dialog */
  99. char szSedDiscretionaryAclEditor[] = "SedDiscretionaryAclEditor";
  100. LPWSTR pwstrWinStation = NULL;
  101. LPWSTR pwstrSpecial = NULL;
  102. #define IDD_BASE 0x20000 // makehelp.bat uses this base offset to form HIDD_ symbol
  103. SED_HELP_INFO PermissionsHelpInfo =
  104. { /* HelpInfo */
  105. szLWinCfgHlp,
  106. IDD_HELP_PERMISSIONS_MAIN+IDD_BASE,
  107. IDD_HELP_PERMISSIONS_SPECIAL_ACCESS+IDD_BASE,
  108. 0,
  109. IDD_HELP_PERMISSIONS_ADD_USER+IDD_BASE,
  110. IDD_HELP_PERMISSIONS_LOCAL_GROUP+IDD_BASE,
  111. IDD_HELP_PERMISSIONS_GLOBAL_GROUP+IDD_BASE,
  112. IDD_HELP_PERMISSIONS_FIND_ACCOUNT+IDD_BASE
  113. };
  114. SED_OBJECT_TYPE_DESCRIPTOR ObjectTypeDescriptor =
  115. {
  116. SED_REVISION1, /* Revision */
  117. FALSE, /* IsContainer */
  118. FALSE, /* AllowNewObjectPerms */
  119. FALSE, /* MapSpecificPermsToGeneric */
  120. &GenericMapping, /* GenericMapping */
  121. NULL, /* GenericMappingNewObjects */
  122. NULL, /* ObjectTypeName */
  123. NULL, /* HelpInfo */
  124. NULL, /* ApplyToSubContainerTitle */
  125. NULL, /* ApplyToObjectsTitle */
  126. NULL, /* ApplyToSubContainerConfirmation */
  127. NULL, /* SpecialObjectAccessTitle */
  128. NULL /* SpecialNewObjectAccessTitle */
  129. };
  130. /*
  131. * Application accesses passed to the discretionary ACL editor.
  132. */
  133. SED_APPLICATION_ACCESS pDiscretionaryAccessGroup[PERMS_COUNT] =
  134. {
  135. /* query (Special...)
  136. */
  137. {
  138. SED_DESC_TYPE_RESOURCE_SPECIAL, /* Type */
  139. WINSTATION_QUERY, /* AccessMask1 */
  140. 0, /* AccessMask2 */
  141. NULL /* PermissionTitle */
  142. },
  143. /* set (Special...)
  144. */
  145. {
  146. SED_DESC_TYPE_RESOURCE_SPECIAL,
  147. WINSTATION_SET,
  148. 0,
  149. NULL
  150. },
  151. /* reset (Special...)
  152. */
  153. {
  154. SED_DESC_TYPE_RESOURCE_SPECIAL,
  155. WINSTATION_RESET,
  156. 0,
  157. NULL
  158. },
  159. /* shadow (Special...)
  160. */
  161. {
  162. SED_DESC_TYPE_RESOURCE_SPECIAL,
  163. WINSTATION_SHADOW,
  164. 0,
  165. NULL
  166. },
  167. /* logon (Special...)
  168. */
  169. {
  170. SED_DESC_TYPE_RESOURCE_SPECIAL,
  171. WINSTATION_LOGON,
  172. 0,
  173. NULL
  174. },
  175. /* logoff (Special...)
  176. */
  177. {
  178. SED_DESC_TYPE_RESOURCE_SPECIAL,
  179. WINSTATION_LOGOFF,
  180. 0,
  181. NULL
  182. },
  183. /* message (Special...)
  184. */
  185. {
  186. SED_DESC_TYPE_RESOURCE_SPECIAL,
  187. WINSTATION_MSG,
  188. 0,
  189. NULL
  190. },
  191. /* connect (Special...)
  192. */
  193. {
  194. SED_DESC_TYPE_RESOURCE_SPECIAL,
  195. WINSTATION_CONNECT,
  196. 0,
  197. NULL
  198. },
  199. /* disconnect (Special...)
  200. */
  201. {
  202. SED_DESC_TYPE_RESOURCE_SPECIAL,
  203. WINSTATION_DISCONNECT,
  204. 0,
  205. NULL
  206. },
  207. /* delete (Special...)
  208. */
  209. {
  210. SED_DESC_TYPE_RESOURCE_SPECIAL,
  211. DELETE,
  212. 0,
  213. NULL
  214. },
  215. /* no access (grouping):
  216. */
  217. {
  218. SED_DESC_TYPE_RESOURCE,
  219. 0,
  220. 0,
  221. NULL
  222. },
  223. /* guest access (grouping)
  224. */
  225. {
  226. SED_DESC_TYPE_RESOURCE,
  227. WINSTATION_GUEST_ACCESS,
  228. 0,
  229. NULL
  230. },
  231. /* user access (grouping)
  232. */
  233. {
  234. SED_DESC_TYPE_RESOURCE,
  235. WINSTATION_USER_ACCESS,
  236. 0,
  237. NULL
  238. },
  239. /* administrator access (grouping)
  240. */
  241. {
  242. SED_DESC_TYPE_RESOURCE,
  243. GENERIC_ALL, // maps to WINSTATION_ALL_ACCESS on WinStationOpen()
  244. 0,
  245. NULL
  246. }
  247. };
  248. #define PRIV_SECURITY 0
  249. #define PRIV_COUNT 1
  250. LUID SecurityValue;
  251. /*
  252. * Definitions from SEDAPI.H:
  253. * (unfortunately we have to do this if we want to link dynamically)
  254. */
  255. typedef DWORD (WINAPI *SED_DISCRETIONARY_ACL_EDITOR)(
  256. HWND Owner,
  257. HANDLE Instance,
  258. LPWSTR Server,
  259. PSED_OBJECT_TYPE_DESCRIPTOR ObjectType,
  260. PSED_APPLICATION_ACCESSES ApplicationAccesses,
  261. LPWSTR ObjectName,
  262. PSED_FUNC_APPLY_SEC_CALLBACK ApplySecurityCallbackRoutine,
  263. ULONG CallbackContext,
  264. PSECURITY_DESCRIPTOR SecurityDescriptor,
  265. BOOLEAN CouldntReadDacl,
  266. BOOLEAN CantWriteDacl,
  267. LPDWORD SEDStatusReturn,
  268. DWORD Flags
  269. );
  270. SED_DISCRETIONARY_ACL_EDITOR lpfnSedDiscretionaryAclEditor = NULL;
  271. /*
  272. * Private function prototypes (public prototypes are in security.h).
  273. */
  274. DWORD SetWinStationSecurity( PWINSTATIONNAME pWSName,
  275. PSECURITY_DESCRIPTOR pSecurityDescriptor );
  276. DWORD ValidateSecurityDescriptor(PSECURITY_DESCRIPTOR pSecurityDescriptor);
  277. FARPROC LoadLibraryGetProcAddress( HWND hwnd,
  278. LPTSTR LibraryName,
  279. LPCSTR ProcName,
  280. PHANDLE phLibrary );
  281. void InitializeSecurityStrings( );
  282. VOID ReportSecurityFailure(HWND hwnd, DWORD ErrorResource, LPCTSTR String, DWORD Error);
  283. LPVOID AllocSplMem( DWORD cb );
  284. BOOL FreeSplMem( LPVOID pMem );
  285. LPWSTR GetUnicodeString( int id );
  286. DWORD WINAPI SedCallback( HWND hwndParent,
  287. HANDLE hInstance,
  288. ULONG CallBackContext,
  289. PSECURITY_DESCRIPTOR pNewSecurityDescriptor,
  290. PSECURITY_DESCRIPTOR pSecDescNewObjects,
  291. BOOLEAN ApplyToSubContainers,
  292. BOOLEAN ApplyToSubObjects,
  293. LPDWORD StatusReturn );
  294. ////////////////////////////////////////////////////////////////////////////////
  295. // public functions
  296. /*******************************************************************************
  297. *
  298. * CallPermissionsDialog (public function)
  299. *
  300. * Call the SedDiscretionaryAclEditor() function in ACLEDIT dll.
  301. *
  302. * ENTRY:
  303. * hwnd (input)
  304. * window handle of parent for ACL edit dialog.
  305. * bAdmin (input)
  306. * TRUE if user is an Administrator (can write to WinStation registry)
  307. * FALSE otherwise (permissions will be read-only).
  308. * pWSName (input)
  309. * Name of WinStation to edit security for.
  310. * EXIT:
  311. * (BOOL) TRUE if any winstations were modified; FALSE otherwise.
  312. *
  313. ******************************************************************************/
  314. BOOL
  315. CallPermissionsDialog( HWND hwnd,
  316. BOOL bAdmin,
  317. PWINSTATIONNAME pWSName )
  318. {
  319. SECURITY_CONTEXT SecurityContext;
  320. BOOLEAN CantWriteDacl;
  321. SED_APPLICATION_ACCESSES ApplicationAccesses;
  322. HANDLE hLibrary;
  323. PSECURITY_DESCRIPTOR pSecurityDescriptor;
  324. DWORD Status = SED_STATUS_NOT_MODIFIED;
  325. DWORD Error;
  326. HCURSOR hOldCursor;
  327. hOldCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
  328. /*
  329. * Get the current WinStation security
  330. */
  331. if ( (Error = GetWinStationSecurity(pWSName, &pSecurityDescriptor)) != ERROR_SUCCESS ) {
  332. ReportSecurityFailure( hwnd,
  333. IDP_ERROR_GET_SECURITY_WINSTATION,
  334. pWSName, Error );
  335. SetCursor(hOldCursor);
  336. return(FALSE);
  337. }
  338. /*
  339. * If we're not allowed access to write to WinStation registry, flag such.
  340. */
  341. CantWriteDacl = !(BOOL)bAdmin;
  342. if( !lpfnSedDiscretionaryAclEditor )
  343. lpfnSedDiscretionaryAclEditor =
  344. (SED_DISCRETIONARY_ACL_EDITOR)LoadLibraryGetProcAddress(
  345. hwnd, szAclEdit, szSedDiscretionaryAclEditor, &hLibrary);
  346. if( lpfnSedDiscretionaryAclEditor )
  347. {
  348. InitializeSecurityStrings( );
  349. ObjectTypeDescriptor.ObjectTypeName = pwstrWinStation;
  350. /*
  351. * Pass all the permissions to the ACL editor,
  352. * and set up the type required:
  353. */
  354. ApplicationAccesses.Count = PERMS_COUNT;
  355. ApplicationAccesses.AccessGroup = pDiscretionaryAccessGroup;
  356. ApplicationAccesses.DefaultPermName =
  357. pDiscretionaryAccessGroup[PERMS_RESOURCE_USER].PermissionTitle;
  358. ObjectTypeDescriptor.HelpInfo = &PermissionsHelpInfo;
  359. ObjectTypeDescriptor.SpecialObjectAccessTitle = pwstrSpecial;
  360. SecurityContext.pWSName = pWSName;
  361. Error = (*lpfnSedDiscretionaryAclEditor )
  362. (hwnd, NULL, NULL, &ObjectTypeDescriptor,
  363. &ApplicationAccesses, pWSName,
  364. (PSED_FUNC_APPLY_SEC_CALLBACK)SedCallback,
  365. (ULONG)&SecurityContext,
  366. pSecurityDescriptor,
  367. FALSE, CantWriteDacl,
  368. &Status, 0);
  369. if( Error != ERROR_SUCCESS )
  370. ReportSecurityFailure(hwnd, IDP_ERROR_PERMISSIONS_EDITOR_FAILED, NULL, Error);
  371. }
  372. SetCursor(hOldCursor);
  373. LocalFree(pSecurityDescriptor);
  374. return( ((Status == SED_STATUS_NOT_MODIFIED) ||
  375. (Status == SED_STATUS_NOT_ALL_MODIFIED)) ? FALSE : TRUE );
  376. } // end CallPermissionsDialog
  377. /*******************************************************************************
  378. *
  379. * GetWinStationSecurityA (public function - ANSI stub)
  380. *
  381. * (see GetWinStationSecurityW)
  382. *
  383. * ENTRY:
  384. * (see GetWinStationSecurityW)
  385. * EXIT:
  386. * (see GetWinStationSecurityW)
  387. *
  388. ******************************************************************************/
  389. DWORD
  390. GetWinStationSecurityA( PWINSTATIONNAMEA pWSName,
  391. PSECURITY_DESCRIPTOR *ppSecurityDescriptor )
  392. {
  393. WINSTATIONNAMEW WSNameW;
  394. /*
  395. * Copy ANSI WinStation name to UNICODE and call GetWinStationNameW().
  396. */
  397. mbstowcs(WSNameW, pWSName, sizeof(WSNameW));
  398. return( GetWinStationSecurityW(WSNameW, ppSecurityDescriptor) );
  399. } // GetWinStationSecurityA
  400. /*******************************************************************************
  401. *
  402. * GetWinStationSecurityW (public function - UNICODE)
  403. *
  404. * Obtain the security descriptor for the specified WinStation. If the
  405. * WinStation does not have a security descriptor associated with it,
  406. * will quietly call GetDefaultWinStationSecurity() to get the default
  407. * security descriptor for it.
  408. *
  409. * ENTRY:
  410. * pWSName (input)
  411. * UNICODE name of WinStation to get security descriptor for.
  412. * ppSecurityDescriptor (output)
  413. * on success, set to pointer to allocated memory containing the
  414. * WinStation's security descriptor.
  415. * EXIT:
  416. * ERROR_SUCCESS if all is OK; error code and *pSecurityDescriptor set to
  417. * NULL if error.
  418. *
  419. * NOTE: on success, the memory pointed to by *ppSecurityDescriptor should be
  420. * LocalFree()'d by the caller when the security descriptor is no longer
  421. * needed.
  422. *
  423. ******************************************************************************/
  424. DWORD
  425. GetWinStationSecurityW( PWINSTATIONNAMEW pWSName,
  426. PSECURITY_DESCRIPTOR *ppSecurityDescriptor )
  427. {
  428. DWORD Error, SDLength, SDLengthRequired;
  429. *ppSecurityDescriptor = NULL;
  430. if ( (Error = RegWinStationQuerySecurity( SERVERNAME_CURRENT,
  431. pWSName,
  432. NULL,
  433. 0, &SDLengthRequired ))
  434. == ERROR_INSUFFICIENT_BUFFER ) {
  435. if ( !(*ppSecurityDescriptor =
  436. (PSECURITY_DESCRIPTOR)LocalAlloc(
  437. 0, SDLength = SDLengthRequired)) ) {
  438. Error = ERROR_NOT_ENOUGH_MEMORY;
  439. } else {
  440. Error = RegWinStationQuerySecurity( SERVERNAME_CURRENT,
  441. pWSName,
  442. *ppSecurityDescriptor,
  443. SDLength, &SDLengthRequired );
  444. }
  445. } else {
  446. /*
  447. * Unexpected error. If 'not found', fetch the default WinStation SD.
  448. */
  449. if ( Error == ERROR_FILE_NOT_FOUND )
  450. return( GetDefaultWinStationSecurity(ppSecurityDescriptor) );
  451. }
  452. /*
  453. * Check for a valid SD before returning.
  454. */
  455. if ( Error == ERROR_SUCCESS ) {
  456. Error = ValidateSecurityDescriptor(*ppSecurityDescriptor);
  457. } else if ( *ppSecurityDescriptor ) {
  458. LocalFree(*ppSecurityDescriptor);
  459. *ppSecurityDescriptor = NULL;
  460. }
  461. return(Error);
  462. } // GetWinStationSecurityW
  463. /*******************************************************************************
  464. *
  465. * GetDefaultWinStationSecurity (public function)
  466. *
  467. * Obtain the default WinStation security descriptor.
  468. *
  469. * ENTRY:
  470. * ppSecurityDescriptor (output)
  471. * on success, set to pointer to allocated memory containing the
  472. * default WinStation security descriptor.
  473. * EXIT:
  474. * ERROR_SUCCESS if all is OK; error code and *pSecurityDescriptor set to
  475. * NULL if error.
  476. *
  477. * NOTE: on success, the memory pointed to by *ppSecurityDescriptor should be
  478. * LocalFree()'d by the caller when the security descriptor is no longer
  479. * needed.
  480. *
  481. ******************************************************************************/
  482. DWORD
  483. GetDefaultWinStationSecurity( PSECURITY_DESCRIPTOR *ppSecurityDescriptor )
  484. {
  485. DWORD Error, SDLength, SDLengthRequired;
  486. *ppSecurityDescriptor = NULL;
  487. if ( (Error = RegWinStationQueryDefaultSecurity( SERVERNAME_CURRENT,
  488. NULL,
  489. 0, &SDLengthRequired ))
  490. == ERROR_INSUFFICIENT_BUFFER ) {
  491. if ( !(*ppSecurityDescriptor =
  492. (PSECURITY_DESCRIPTOR)LocalAlloc(
  493. 0, SDLength = SDLengthRequired)) ) {
  494. Error = ERROR_NOT_ENOUGH_MEMORY;
  495. } else {
  496. Error = RegWinStationQueryDefaultSecurity( SERVERNAME_CURRENT,
  497. *ppSecurityDescriptor,
  498. SDLength, &SDLengthRequired );
  499. }
  500. }
  501. /*
  502. * Check for a valid SD before returning.
  503. */
  504. if ( Error == ERROR_SUCCESS ) {
  505. Error = ValidateSecurityDescriptor(*ppSecurityDescriptor);
  506. } else if ( *ppSecurityDescriptor ) {
  507. LocalFree(*ppSecurityDescriptor);
  508. *ppSecurityDescriptor = NULL;
  509. }
  510. return(Error);
  511. } // GetDefaultWinStationSecurity
  512. /*******************************************************************************
  513. *
  514. * FreeSecurityStrings (public function)
  515. *
  516. * Free allocated memory for ACL edit string resources. This function
  517. * should be called when the application exits.
  518. *
  519. * ENTRY:
  520. * EXIT:
  521. *
  522. ******************************************************************************/
  523. void
  524. FreeSecurityStrings( )
  525. {
  526. /*
  527. * Only perform free if the strings have been allocated and loaded.
  528. */
  529. if( pwstrWinStation )
  530. {
  531. FreeSplMem(pwstrWinStation);
  532. FreeSplMem(pwstrSpecial);
  533. FreeSplMem(pDiscretionaryAccessGroup[PERMS_SPECIAL_QUERY].PermissionTitle);
  534. FreeSplMem(pDiscretionaryAccessGroup[PERMS_SPECIAL_SET].PermissionTitle);
  535. FreeSplMem(pDiscretionaryAccessGroup[PERMS_SPECIAL_RESET].PermissionTitle);
  536. FreeSplMem(pDiscretionaryAccessGroup[PERMS_SPECIAL_SHADOW].PermissionTitle);
  537. FreeSplMem(pDiscretionaryAccessGroup[PERMS_SPECIAL_LOGON].PermissionTitle);
  538. FreeSplMem(pDiscretionaryAccessGroup[PERMS_SPECIAL_LOGOFF].PermissionTitle);
  539. FreeSplMem(pDiscretionaryAccessGroup[PERMS_SPECIAL_MSG].PermissionTitle);
  540. FreeSplMem(pDiscretionaryAccessGroup[PERMS_SPECIAL_CONNECT].PermissionTitle);
  541. FreeSplMem(pDiscretionaryAccessGroup[PERMS_SPECIAL_DISCONNECT].PermissionTitle);
  542. FreeSplMem(pDiscretionaryAccessGroup[PERMS_SPECIAL_DELETE].PermissionTitle);
  543. FreeSplMem(pDiscretionaryAccessGroup[PERMS_RESOURCE_NOACCESS].PermissionTitle);
  544. FreeSplMem(pDiscretionaryAccessGroup[PERMS_RESOURCE_GUEST].PermissionTitle);
  545. FreeSplMem(pDiscretionaryAccessGroup[PERMS_RESOURCE_USER].PermissionTitle);
  546. FreeSplMem(pDiscretionaryAccessGroup[PERMS_RESOURCE_ADMIN].PermissionTitle);
  547. }
  548. } // end FreeSecurityStrings
  549. ////////////////////////////////////////////////////////////////////////////////
  550. // private functions
  551. /*******************************************************************************
  552. *
  553. * InitializeSecurityStrings (private function)
  554. *
  555. * Allocate and load ACL editing string resources if not done already.
  556. * The application should call the public FreeSecurityStrings() function
  557. * to free allocated memory when the application exits.
  558. *
  559. * ENTRY:
  560. * EXIT:
  561. *
  562. ******************************************************************************/
  563. void
  564. InitializeSecurityStrings()
  565. {
  566. if( !pwstrWinStation )
  567. {
  568. pwstrWinStation = GetUnicodeString(IDS_WINSTATION);
  569. pwstrSpecial = GetUnicodeString(IDS_SPECIALACCESS);
  570. pDiscretionaryAccessGroup[PERMS_SPECIAL_QUERY].PermissionTitle =
  571. GetUnicodeString(IDS_PERMS_SPECIAL_QUERY);
  572. pDiscretionaryAccessGroup[PERMS_SPECIAL_SET].PermissionTitle =
  573. GetUnicodeString(IDS_PERMS_SPECIAL_SET);
  574. pDiscretionaryAccessGroup[PERMS_SPECIAL_RESET].PermissionTitle =
  575. GetUnicodeString(IDS_PERMS_SPECIAL_RESET);
  576. pDiscretionaryAccessGroup[PERMS_SPECIAL_SHADOW].PermissionTitle =
  577. GetUnicodeString(IDS_PERMS_SPECIAL_SHADOW);
  578. pDiscretionaryAccessGroup[PERMS_SPECIAL_LOGON].PermissionTitle =
  579. GetUnicodeString(IDS_PERMS_SPECIAL_LOGON);
  580. pDiscretionaryAccessGroup[PERMS_SPECIAL_LOGOFF].PermissionTitle =
  581. GetUnicodeString(IDS_PERMS_SPECIAL_LOGOFF);
  582. pDiscretionaryAccessGroup[PERMS_SPECIAL_MSG].PermissionTitle =
  583. GetUnicodeString(IDS_PERMS_SPECIAL_MSG);
  584. pDiscretionaryAccessGroup[PERMS_SPECIAL_CONNECT].PermissionTitle =
  585. GetUnicodeString(IDS_PERMS_SPECIAL_CONNECT);
  586. pDiscretionaryAccessGroup[PERMS_SPECIAL_DISCONNECT].PermissionTitle =
  587. GetUnicodeString(IDS_PERMS_SPECIAL_DISCONNECT);
  588. pDiscretionaryAccessGroup[PERMS_SPECIAL_DELETE].PermissionTitle =
  589. GetUnicodeString(IDS_PERMS_SPECIAL_DELETE);
  590. pDiscretionaryAccessGroup[PERMS_RESOURCE_NOACCESS].PermissionTitle =
  591. GetUnicodeString(IDS_PERMS_RESOURCE_NOACCESS);
  592. pDiscretionaryAccessGroup[PERMS_RESOURCE_GUEST].PermissionTitle =
  593. GetUnicodeString(IDS_PERMS_RESORUCE_GUEST);
  594. pDiscretionaryAccessGroup[PERMS_RESOURCE_USER].PermissionTitle =
  595. GetUnicodeString(IDS_PERMS_RESORUCE_USER);
  596. pDiscretionaryAccessGroup[PERMS_RESOURCE_ADMIN].PermissionTitle =
  597. GetUnicodeString(IDS_PERMS_RESOURCE_ADMIN);
  598. }
  599. } // end InitializeSecurityStrings
  600. /*******************************************************************************
  601. *
  602. * ReportSecurityFailure (private function)
  603. *
  604. * Output an appropriate error message for security failure.
  605. *
  606. * ENTRY:
  607. * hwnd (input)
  608. * window handle of parent for message box.
  609. * ErrorResource (input)
  610. * resource ID of error format string.
  611. * String (input)
  612. * If not NULL, points to string to output as part of message.
  613. * Error (input)
  614. * Error code
  615. * EXIT:
  616. *
  617. * NOTE: all ErrorResource format strings should specify a %d for Error code
  618. * and %S for system error message string as the last two substitution
  619. * arguments. The %S is optional, and must be present in the format
  620. * string if the String argument is non-NULL.
  621. *
  622. ******************************************************************************/
  623. VOID
  624. ReportSecurityFailure(HWND hwnd, DWORD ErrorResource, LPCTSTR String, DWORD Error)
  625. {
  626. HWND hwndSave = WinUtilsAppWindow;
  627. /*
  628. * Set parent window in WinUtilsAppWindow global for use
  629. * by STANDARD_ERROR_MESSAGE macro (StandardErrorMessage function).
  630. */
  631. WinUtilsAppWindow = hwnd;
  632. if ( String )
  633. STANDARD_ERROR_MESSAGE((WINAPPSTUFF, LOGONID_NONE, Error, ErrorResource, String))
  634. else
  635. STANDARD_ERROR_MESSAGE((WINAPPSTUFF, LOGONID_NONE, Error, ErrorResource))
  636. /*
  637. * Restore original WinUtilsAppWindow to global.
  638. */
  639. WinUtilsAppWindow = hwndSave;
  640. } // end ReportSecurityFailure
  641. /*******************************************************************************
  642. *
  643. * SedCallback (private function)
  644. *
  645. * Callback function from ACL edit dialog DLL
  646. *
  647. * ENTRY:
  648. * (see sedapi.h)
  649. * EXIT:
  650. * (see sedapi.h)
  651. *
  652. ******************************************************************************/
  653. DWORD WINAPI
  654. SedCallback( HWND hwndParent,
  655. HANDLE hInstance,
  656. ULONG CallBackContext,
  657. PSECURITY_DESCRIPTOR pUpdatedSecurityDescriptor,
  658. PSECURITY_DESCRIPTOR pSecDescNewObjects,
  659. BOOLEAN ApplyToSubContainers,
  660. BOOLEAN ApplyToSubObjects,
  661. LPDWORD StatusReturn )
  662. {
  663. WINSTATIONNAME WSName;
  664. PSECURITY_CONTEXT pSecurityContext;
  665. DWORD Error;
  666. BOOL OK = TRUE;
  667. pSecurityContext = (PSECURITY_CONTEXT)CallBackContext;
  668. /*
  669. * Apply security to the WinStation.
  670. */
  671. lstrcpy(WSName, pSecurityContext->pWSName);
  672. if ( (Error = SetWinStationSecurity( WSName,
  673. pUpdatedSecurityDescriptor))
  674. != ERROR_SUCCESS ) {
  675. ReportSecurityFailure( hwndParent,
  676. IDP_ERROR_SET_SECURITY_WINSTATION,
  677. WSName,
  678. Error );
  679. OK = FALSE;
  680. *StatusReturn = SED_STATUS_NOT_ALL_MODIFIED;
  681. }
  682. if ( OK == TRUE )
  683. *StatusReturn = SED_STATUS_MODIFIED;
  684. return( OK ? 0 : 1 );
  685. } // end SedCallback
  686. /*******************************************************************************
  687. *
  688. * LoadLibraryGetProcAddress (private function)
  689. *
  690. * Load the specified library and retrieve FARPROC pointer to specified
  691. * procedure's entry point.
  692. *
  693. * ENTRY:
  694. * hwnd (input)
  695. * window handle of owner for error message display
  696. * LibraryName (input)
  697. * name of library dll to load
  698. * ProcName (input)
  699. * name of library procedure to reference
  700. * phLibrary (output)
  701. * set to handle of loaded library on return
  702. * EXIT:
  703. * FARPROC pointer to library procedure's entry point.
  704. *
  705. ******************************************************************************/
  706. FARPROC
  707. LoadLibraryGetProcAddress( HWND hwnd,
  708. LPTSTR LibraryName,
  709. LPCSTR ProcName,
  710. PHANDLE phLibrary )
  711. {
  712. HANDLE hLibrary;
  713. FARPROC lpfn = NULL;
  714. hLibrary = LoadLibrary(LibraryName);
  715. if ( hLibrary ) {
  716. lpfn = GetProcAddress(hLibrary, ProcName);
  717. if(!lpfn) {
  718. ERROR_MESSAGE(( IDP_ERROR_COULDNOTFINDPROCEDURE,
  719. ProcName, LibraryName ))
  720. FreeLibrary(hLibrary);
  721. }
  722. } else
  723. ERROR_MESSAGE((IDP_ERROR_COULDNOTLOADLIBRARY, LibraryName))
  724. *phLibrary = hLibrary;
  725. return(lpfn);
  726. } // end LoadLibraryGetProcAddress
  727. /*******************************************************************************
  728. *
  729. * AllocSplMem (private function)
  730. *
  731. * Allocate and zero-fill specified amount of memory.
  732. *
  733. * ENTRY:
  734. * cb (input)
  735. * number of bytes to allocate
  736. * EXIT:
  737. * LPVOID pointer to allocated memory; NULL if error.
  738. *
  739. ******************************************************************************/
  740. LPVOID
  741. AllocSplMem( DWORD cb )
  742. {
  743. return(LocalAlloc(LPTR, cb));
  744. } // end AllocSplMem
  745. /*******************************************************************************
  746. *
  747. * FreeSplMem (private function)
  748. *
  749. * Free the specified memory block.
  750. *
  751. * ENTRY:
  752. * pMem (input)
  753. * memory to free
  754. * EXIT:
  755. * TRUE if sucess; FALSE if error.
  756. *
  757. ******************************************************************************/
  758. BOOL
  759. FreeSplMem( LPVOID pMem )
  760. {
  761. return( LocalFree((HLOCAL)pMem) == NULL );
  762. } // end FreeSplMem
  763. /*******************************************************************************
  764. *
  765. * GetUnicodeString (private function)
  766. *
  767. * Load a resource string and allocate/save in memory block.
  768. *
  769. * ENTRY:
  770. * id (input)
  771. * resource id of string to get
  772. * EXIT:
  773. * pointer to allocated and loaded UNICODE string
  774. *
  775. ******************************************************************************/
  776. LPWSTR
  777. GetUnicodeString(int id)
  778. {
  779. WCHAR ResString[256];
  780. DWORD length = 0;
  781. LPWSTR pUnicode;
  782. DWORD cbUnicode;
  783. length = LoadStringW(NULL, id, ResString, 256);
  784. cbUnicode = (length * sizeof(WCHAR)) + sizeof(WCHAR);
  785. pUnicode = AllocSplMem(cbUnicode);
  786. if( pUnicode )
  787. memcpy(pUnicode, ResString, cbUnicode);
  788. return(pUnicode);
  789. } // end GetUnicodeString
  790. /*******************************************************************************
  791. *
  792. * ValidateSecurityDescriptor (private function)
  793. *
  794. * Check the specified security descriptor for valid structure as well as
  795. * valid ACLs and SIDs.
  796. *
  797. * ENTRY:
  798. * pSecurityDescriptor (input)
  799. * Security descriptor to validate.
  800. * EXIT:
  801. * ERROR_SUCCESS if valid; error otherwise.
  802. *
  803. ******************************************************************************/
  804. DWORD
  805. ValidateSecurityDescriptor(PSECURITY_DESCRIPTOR pSecurityDescriptor)
  806. {
  807. DWORD Error = ERROR_SUCCESS;
  808. if ( !IsValidSecurityDescriptor(pSecurityDescriptor) ) {
  809. Error = GetLastError();
  810. } else {
  811. BOOL bAclPresent, bDefaulted;
  812. PACL pACL;
  813. PSID pSID;
  814. for ( ; ; ) {
  815. if ( !GetSecurityDescriptorDacl( pSecurityDescriptor,
  816. &bAclPresent, &pACL, &bDefaulted ) ) {
  817. Error = GetLastError();
  818. break;
  819. }
  820. if ( bAclPresent && pACL )
  821. if ( !IsValidAcl(pACL) ) {
  822. Error = GetLastError();
  823. break;
  824. }
  825. if ( !GetSecurityDescriptorSacl( pSecurityDescriptor,
  826. &bAclPresent, &pACL, &bDefaulted ) ) {
  827. Error = GetLastError();
  828. break;
  829. }
  830. if ( bAclPresent && pACL )
  831. if ( !IsValidAcl(pACL) ) {
  832. Error = GetLastError();
  833. break;
  834. }
  835. if ( !GetSecurityDescriptorOwner( pSecurityDescriptor,
  836. &pSID, &bDefaulted ) ) {
  837. Error = GetLastError();
  838. break;
  839. }
  840. if ( pSID )
  841. if ( !IsValidSid(pSID) ) {
  842. Error = GetLastError();
  843. break;
  844. }
  845. if ( !GetSecurityDescriptorGroup( pSecurityDescriptor,
  846. &pSID, &bDefaulted ) ) {
  847. Error = GetLastError();
  848. break;
  849. }
  850. if ( pSID )
  851. if ( !IsValidSid(pSID) ) {
  852. Error = GetLastError();
  853. break;
  854. }
  855. break;
  856. }
  857. }
  858. return(Error);
  859. } // end ValidateSecurityDescriptor
  860. /*******************************************************************************
  861. *
  862. * SetWinStationSecurity (private function)
  863. *
  864. * Set the specified WinStation's registry and kernel object security.
  865. *
  866. * ENTRY:
  867. * pWSName (input)
  868. * Name of WinStation to set security for.
  869. * pSecurityDescriptor (input)
  870. * Security descriptor to set for winstation.
  871. * EXIT:
  872. * ERROR_SUCCESS if valid; error otherwise.
  873. *
  874. ******************************************************************************/
  875. DWORD
  876. SetWinStationSecurity( PWINSTATIONNAME pWSName,
  877. PSECURITY_DESCRIPTOR pSecurityDescriptor )
  878. {
  879. DWORD Error = ERROR_SUCCESS;
  880. Error = RegWinStationSetSecurity( SERVERNAME_CURRENT,
  881. pWSName,
  882. pSecurityDescriptor,
  883. GetSecurityDescriptorLength(pSecurityDescriptor) );
  884. return(Error);
  885. } // SetWinStationSecurity