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.

3028 lines
93 KiB

  1. /*++
  2. Copyright (c) 1990 - 1995 Microsoft Corporation
  3. Module Name:
  4. security.c
  5. Abstract:
  6. This module interfaces with the security system
  7. Author:
  8. Andrew Bell (andrewbe) June 1992
  9. Revision History:
  10. --*/
  11. #include <precomp.h>
  12. /******************************************************************************
  13. The printing security model
  14. ---------------------------
  15. In printing we define a hierarchy of three objects:
  16. SERVER
  17. / \
  18. / \
  19. / ...
  20. /
  21. PRINTER
  22. / \
  23. / \
  24. / ...
  25. /
  26. DOCUMENT
  27. The following types of operation may be performed on each of these objects:
  28. SERVER: Install/Deinstall Driver
  29. Create Printer
  30. Enumerate Printers
  31. PRINTER: Pause/Resume
  32. Delete
  33. Connect to/Disconnect
  34. Set
  35. Enumerate Documents
  36. DOCUMENT: Pause/Resume
  37. Delete
  38. Set Attributes
  39. For product LanMan NT, five classes of user are defined, and,
  40. for Windows NT, four classes are defined.
  41. The following privileges are assigned to each class:
  42. Administrators
  43. Print Operators
  44. System Operators
  45. Power Users
  46. Owners
  47. Everyone (World)
  48. ******************************************************************************/
  49. #define DBGCHK( Condition, ErrorInfo ) \
  50. if( Condition ) DBGMSG( DBG_WARNING, ErrorInfo )
  51. #define TOKENLENGTH( Token ) ( *( ( (PDWORD)Token ) - 1 ) )
  52. /*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  53. Came from \\orville\razzle\src\private\newsam\server\bldsam3.c
  54. >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
  55. GENERIC_MAPPING GenericMapping[SPOOLER_OBJECT_COUNT] =
  56. {
  57. { SERVER_READ, SERVER_WRITE, SERVER_EXECUTE, SERVER_ALL_ACCESS },
  58. { PRINTER_READ, PRINTER_WRITE, PRINTER_EXECUTE, PRINTER_ALL_ACCESS },
  59. { JOB_READ, JOB_WRITE, JOB_EXECUTE, JOB_ALL_ACCESS }
  60. };
  61. /* !!! Should these be translatable??? */
  62. LPWSTR ObjectTypeName[SPOOLER_OBJECT_COUNT] =
  63. {
  64. L"Server", L"Printer", L"Document"
  65. };
  66. WCHAR *szSpooler = L"Spooler";
  67. LUID AuditValue;
  68. PSECURITY_DESCRIPTOR pServerSecurityDescriptor;
  69. LUID gLoadDriverPrivilegeLuid;
  70. PSID pLocalSystemSid;
  71. PSID pGuestsSid;
  72. PSID pNetworkLogonSid;
  73. BOOL ServerGenerateOnClose; /* Do we need this for the server? */
  74. #if DBG
  75. #define DBG_ACCESS_TYPE_SERVER_ALL_ACCESS 0
  76. #define DBG_ACCESS_TYPE_SERVER_READ 1
  77. #define DBG_ACCESS_TYPE_SERVER_WRITE 2
  78. #define DBG_ACCESS_TYPE_SERVER_EXECUTE 3
  79. #define DBG_ACCESS_TYPE_PRINTER_ALL_ACCESS 4
  80. #define DBG_ACCESS_TYPE_PRINTER_READ 5
  81. #define DBG_ACCESS_TYPE_PRINTER_WRITE 6
  82. #define DBG_ACCESS_TYPE_PRINTER_EXECUTE 7
  83. #define DBG_ACCESS_TYPE_JOB_ALL_ACCESS 8
  84. #define DBG_ACCESS_TYPE_JOB_READ 9
  85. #define DBG_ACCESS_TYPE_JOB_WRITE 10
  86. #define DBG_ACCESS_TYPE_JOB_EXECUTE 11
  87. #define DBG_ACCESS_TYPE_PRINTER_ACCESS_USE 12
  88. #define DBG_ACCESS_TYPE_PRINTER_ACCESS_ADMINISTER 13
  89. #define DBG_ACCESS_TYPE_SERVER_ACCESS_ENUMERATE 14
  90. #define DBG_ACCESS_TYPE_SERVER_ACCESS_ADMINISTER 15
  91. #define DBG_ACCESS_TYPE_JOB_ACCESS_ADMINISTER 16
  92. #define DBG_ACCESS_TYPE_DELETE 17
  93. #define DBG_ACCESS_TYPE_WRITE_DAC 18
  94. #define DBG_ACCESS_TYPE_WRITE_OWNER 19
  95. #define DBG_ACCESS_TYPE_ACCESS_SYSTEM_SECURITY 20
  96. // These two should come last:
  97. #define DBG_ACCESS_TYPE_UNKNOWN 21
  98. #define DBG_ACCESS_TYPE_COUNT 22
  99. typedef struct _DBG_ACCESS_TYPE_MAPPING
  100. {
  101. DWORD Type;
  102. LPWSTR Name;
  103. }
  104. DBG_ACCESS_TYPE_MAPPING, *PDBG_ACCESS_TYPE_MAPPING;
  105. DBG_ACCESS_TYPE_MAPPING DbgAccessTypeMapping[DBG_ACCESS_TYPE_COUNT] =
  106. {
  107. { SERVER_ALL_ACCESS, L"SERVER_ALL_ACCESS" },
  108. { SERVER_READ, L"SERVER_READ" },
  109. { SERVER_WRITE, L"SERVER_WRITE" },
  110. { SERVER_EXECUTE, L"SERVER_EXECUTE" },
  111. { PRINTER_ALL_ACCESS, L"PRINTER_ALL_ACCESS" },
  112. { PRINTER_READ, L"PRINTER_READ" },
  113. { PRINTER_WRITE, L"PRINTER_WRITE" },
  114. { PRINTER_EXECUTE, L"PRINTER_EXECUTE" },
  115. { JOB_ALL_ACCESS, L"JOB_ALL_ACCESS" },
  116. { JOB_READ, L"JOB_READ" },
  117. { JOB_WRITE, L"JOB_WRITE" },
  118. { JOB_EXECUTE, L"JOB_EXECUTE" },
  119. { PRINTER_ACCESS_USE, L"PRINTER_ACCESS_USE" },
  120. { PRINTER_ACCESS_ADMINISTER, L"PRINTER_ACCESS_ADMINISTER" },
  121. { SERVER_ACCESS_ENUMERATE, L"SERVER_ACCESS_ENUMERATE" },
  122. { SERVER_ACCESS_ADMINISTER, L"SERVER_ACCESS_ADMINISTER" },
  123. { JOB_ACCESS_ADMINISTER, L"JOB_ACCESS_ADMINISTER" },
  124. { DELETE, L"DELETE" },
  125. { WRITE_DAC, L"WRITE_DAC" },
  126. { WRITE_OWNER, L"WRITE_OWNER" },
  127. { ACCESS_SYSTEM_SECURITY, L"ACCESS_SYSTEM_SECURITY" },
  128. { 0, L"UNKNOWN" }
  129. };
  130. LPWSTR DbgGetAccessTypeName( DWORD AccessType )
  131. {
  132. PDBG_ACCESS_TYPE_MAPPING pMapping;
  133. DWORD i;
  134. pMapping = DbgAccessTypeMapping;
  135. i = 0;
  136. while( ( i < ( DBG_ACCESS_TYPE_COUNT - 1 ) ) && ( pMapping[i].Type != AccessType ) )
  137. i++;
  138. return pMapping[i].Name;
  139. }
  140. #endif /* DBG */
  141. BOOL
  142. BuildJobOwnerSecurityDescriptor(
  143. IN HANDLE hToken,
  144. OUT PSECURITY_DESCRIPTOR *ppSD
  145. );
  146. VOID
  147. DestroyJobOwnerSecurityDescriptor(
  148. IN PSECURITY_DESCRIPTOR pSD
  149. );
  150. BOOL
  151. SetRequiredPrivileges(
  152. IN HANDLE TokenHandle,
  153. OUT PTOKEN_PRIVILEGES *ppPreviousTokenPrivileges,
  154. OUT PDWORD pPreviousTokenPrivilegesLength
  155. );
  156. BOOL
  157. ResetRequiredPrivileges(
  158. IN HANDLE TokenHandle,
  159. IN PTOKEN_PRIVILEGES pPreviousTokenPrivileges,
  160. IN DWORD PreviousTokenPrivilegesLength
  161. );
  162. PSECURITY_DESCRIPTOR
  163. AllocateLocalSD(
  164. PSECURITY_DESCRIPTOR pSystemAllocatedSD
  165. );
  166. DWORD
  167. GetHackOutAce(
  168. PACL pDacl
  169. );
  170. #define MAX_ACE 20
  171. #if DBG
  172. typedef struct _STANDARD_ACE {
  173. ACE_HEADER Header;
  174. ACCESS_MASK Mask;
  175. PSID Sid;
  176. } STANDARD_ACE;
  177. typedef STANDARD_ACE *PSTANDARD_ACE;
  178. //
  179. // The following macros used by DumpAcl(), these macros and DumpAcl() are
  180. // stolen from private\ntos\se\ctaccess.c (written by robertre) for
  181. // debugging purposes.
  182. //
  183. //
  184. // Returns a pointer to the first Ace in an Acl (even if the Acl is empty).
  185. //
  186. #define FirstAce(Acl) ((PVOID)((LPBYTE)(Acl) + sizeof(ACL)))
  187. //
  188. // Returns a pointer to the next Ace in a sequence (even if the input
  189. // Ace is the one in the sequence).
  190. //
  191. #define NextAce(Ace) ((PVOID)((LPBYTE)(Ace) + ((PACE_HEADER)(Ace))->AceSize))
  192. VOID
  193. DumpAcl(
  194. IN PACL Acl
  195. );
  196. #endif //if DBG
  197. /* Dummy access mask which will never be checked, but required
  198. * by the ACL editor, so that Document Properties is not undefined
  199. * for containers (i.e. printers).
  200. * This mask alone must not be used for any other ACE, since it
  201. * will be used to find the no-inherit ACE which propagates
  202. * onto printers.
  203. */
  204. #define DUMMY_ACE_ACCESS_MASK READ_CONTROL
  205. /* CreateServerSecurityDescriptor
  206. *
  207. * Arguments: None
  208. *
  209. * Return: The security descriptor returned by BuildPrintObjectProtection.
  210. *
  211. */
  212. PSECURITY_DESCRIPTOR
  213. CreateServerSecurityDescriptor(
  214. VOID
  215. )
  216. {
  217. DWORD ObjectType = SPOOLER_OBJECT_SERVER;
  218. NT_PRODUCT_TYPE NtProductType;
  219. PSID AceSid[MAX_ACE]; // Don't expect more than MAX_ACE ACEs in any of these.
  220. ACCESS_MASK AceMask[MAX_ACE]; // Access masks corresponding to Sids
  221. BYTE InheritFlags[MAX_ACE]; //
  222. UCHAR AceType[MAX_ACE];
  223. DWORD AceCount;
  224. SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
  225. SID_IDENTIFIER_AUTHORITY WorldSidAuthority = SECURITY_WORLD_SID_AUTHORITY;
  226. SID_IDENTIFIER_AUTHORITY CreatorSidAuthority = SECURITY_CREATOR_SID_AUTHORITY;
  227. PSID WorldSid = NULL;
  228. PSID AdminsAliasSid = NULL;
  229. PSID PrintOpsAliasSid = NULL;
  230. PSID SystemOpsAliasSid = NULL;
  231. PSID PowerUsersAliasSid = NULL;
  232. PSID CreatorOwnerSid = NULL;
  233. PSECURITY_DESCRIPTOR ServerSD = NULL;
  234. BOOL OK;
  235. //
  236. // Printer SD
  237. //
  238. AceCount = 0;
  239. /* Creator-Owner SID: */
  240. OK = AllocateAndInitializeSid( &CreatorSidAuthority, 1,
  241. SECURITY_CREATOR_OWNER_RID,
  242. 0, 0, 0, 0, 0, 0, 0,
  243. &CreatorOwnerSid );
  244. DBGCHK( !OK, ( "Couldn't Allocate and initialize SID" ) );
  245. if ( !OK ) {
  246. goto CleanUp;
  247. }
  248. /* The following is a dummy ACE needed for the ACL editor.
  249. * Note this is a gross hack, and will result in two ACEs
  250. * being propagated onto printers when they are created,
  251. * one of which must be deleted.
  252. */
  253. AceType[AceCount] = ACCESS_ALLOWED_ACE_TYPE;
  254. AceSid[AceCount] = CreatorOwnerSid;
  255. AceMask[AceCount] = DUMMY_ACE_ACCESS_MASK;
  256. InheritFlags[AceCount] = INHERIT_ONLY_ACE | CONTAINER_INHERIT_ACE;
  257. AceCount++;
  258. AceType[AceCount] = ACCESS_ALLOWED_ACE_TYPE;
  259. AceSid[AceCount] = CreatorOwnerSid;
  260. AceMask[AceCount] = GENERIC_ALL;
  261. InheritFlags[AceCount] = INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE;
  262. AceCount++;
  263. /* World SID */
  264. OK = AllocateAndInitializeSid( &WorldSidAuthority, 1,
  265. SECURITY_WORLD_RID,
  266. 0, 0, 0, 0, 0, 0, 0,
  267. &WorldSid );
  268. DBGCHK( !OK, ( "Couldn't Allocate and initialize SID" ) );
  269. if ( !OK ) {
  270. goto CleanUp;
  271. }
  272. AceType[AceCount] = ACCESS_ALLOWED_ACE_TYPE;
  273. AceSid[AceCount] = WorldSid;
  274. AceMask[AceCount] = SERVER_EXECUTE;
  275. InheritFlags[AceCount] = 0;
  276. AceCount++;
  277. AceType[AceCount] = ACCESS_ALLOWED_ACE_TYPE;
  278. AceSid[AceCount] = WorldSid;
  279. AceMask[AceCount] = GENERIC_EXECUTE;
  280. InheritFlags[AceCount] = INHERIT_ONLY_ACE | CONTAINER_INHERIT_ACE;
  281. AceCount++;
  282. /* Admins alias SID */
  283. OK = AllocateAndInitializeSid( &NtAuthority, 2,
  284. SECURITY_BUILTIN_DOMAIN_RID,
  285. DOMAIN_ALIAS_RID_ADMINS,
  286. 0, 0, 0, 0, 0, 0,
  287. &AdminsAliasSid );
  288. DBGCHK( !OK, ( "Couldn't Allocate and initialize SID" ) );
  289. if ( !OK ) {
  290. goto CleanUp;
  291. }
  292. AceType[AceCount] = ACCESS_ALLOWED_ACE_TYPE;
  293. AceSid[AceCount] = AdminsAliasSid;
  294. AceMask[AceCount] = SERVER_ALL_ACCESS;
  295. InheritFlags[AceCount] = 0;
  296. AceCount++;
  297. AceType[AceCount] = ACCESS_ALLOWED_ACE_TYPE;
  298. AceSid[AceCount] = AdminsAliasSid;
  299. AceMask[AceCount] = GENERIC_ALL;
  300. InheritFlags[AceCount] = INHERIT_ONLY_ACE | CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE;
  301. AceCount++;
  302. OK = RtlGetNtProductType( &NtProductType );
  303. DBGCHK( !OK, ( "Couldn't get product type" ) );
  304. if ( !OK ) {
  305. goto CleanUp;
  306. }
  307. switch (NtProductType) {
  308. case NtProductLanManNt:
  309. // case NtProductMember:
  310. /* Print Ops alias SID */
  311. OK = AllocateAndInitializeSid( &NtAuthority, 2,
  312. SECURITY_BUILTIN_DOMAIN_RID,
  313. DOMAIN_ALIAS_RID_PRINT_OPS,
  314. 0, 0, 0, 0, 0, 0,
  315. &PrintOpsAliasSid );
  316. DBGCHK( !OK, ( "Couldn't Allocate and initialize SID" ) );
  317. if ( !OK ) {
  318. goto CleanUp;
  319. }
  320. AceType[AceCount] = ACCESS_ALLOWED_ACE_TYPE;
  321. AceSid[AceCount] = PrintOpsAliasSid;
  322. AceMask[AceCount] = SERVER_ALL_ACCESS;
  323. InheritFlags[AceCount] = 0;
  324. AceCount++;
  325. AceType[AceCount] = ACCESS_ALLOWED_ACE_TYPE;
  326. AceSid[AceCount] = PrintOpsAliasSid;
  327. AceMask[AceCount] = GENERIC_ALL;
  328. InheritFlags[AceCount] = INHERIT_ONLY_ACE | CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE;
  329. AceCount++;
  330. /* System Ops alias SID */
  331. OK = AllocateAndInitializeSid( &NtAuthority, 2,
  332. SECURITY_BUILTIN_DOMAIN_RID,
  333. DOMAIN_ALIAS_RID_SYSTEM_OPS,
  334. 0, 0, 0, 0, 0, 0,
  335. &SystemOpsAliasSid );
  336. DBGCHK( !OK, ( "Couldn't Allocate and initialize SID" ) );
  337. if ( !OK ) {
  338. goto CleanUp;
  339. }
  340. AceType[AceCount] = ACCESS_ALLOWED_ACE_TYPE;
  341. AceSid[AceCount] = SystemOpsAliasSid;
  342. AceMask[AceCount] = SERVER_ALL_ACCESS;
  343. InheritFlags[AceCount] = 0;
  344. AceCount++;
  345. AceType[AceCount] = ACCESS_ALLOWED_ACE_TYPE;
  346. AceSid[AceCount] = SystemOpsAliasSid;
  347. AceMask[AceCount] = GENERIC_ALL;
  348. InheritFlags[AceCount] = INHERIT_ONLY_ACE | CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE;
  349. AceCount++;
  350. break;
  351. case NtProductWinNt:
  352. default:
  353. {
  354. OSVERSIONINFOEX OsVersion = {0};
  355. OsVersion.dwOSVersionInfoSize = sizeof(OsVersion);
  356. //
  357. // Whistler Personal does not have the Power Users group.
  358. //
  359. if (GetVersionEx((LPOSVERSIONINFO)&OsVersion) &&
  360. !(OsVersion.wProductType==VER_NT_WORKSTATION && OsVersion.wSuiteMask & VER_SUITE_PERSONAL)) {
  361. OK = AllocateAndInitializeSid( &NtAuthority, 2,
  362. SECURITY_BUILTIN_DOMAIN_RID,
  363. DOMAIN_ALIAS_RID_POWER_USERS,
  364. 0, 0, 0, 0, 0, 0,
  365. &PowerUsersAliasSid );
  366. DBGCHK( !OK, ( "Couldn't Allocate and initialize SID" ) );
  367. if ( !OK ) {
  368. goto CleanUp;
  369. }
  370. AceType[AceCount] = ACCESS_ALLOWED_ACE_TYPE;
  371. AceSid[AceCount] = PowerUsersAliasSid;
  372. AceMask[AceCount] = SERVER_ALL_ACCESS;
  373. InheritFlags[AceCount] = 0;
  374. AceCount++;
  375. AceType[AceCount] = ACCESS_ALLOWED_ACE_TYPE;
  376. AceSid[AceCount] = PowerUsersAliasSid;
  377. AceMask[AceCount] = GENERIC_ALL;
  378. InheritFlags[AceCount] = INHERIT_ONLY_ACE | CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE;
  379. AceCount++;
  380. }
  381. }
  382. break;
  383. }
  384. DBGCHK( ( AceCount > MAX_ACE ), ( "ACE count exceeded" ) );
  385. if ( AceCount > MAX_ACE ) {
  386. goto CleanUp;
  387. }
  388. OK = BuildPrintObjectProtection( AceType,
  389. AceCount,
  390. AceSid,
  391. AceMask,
  392. InheritFlags,
  393. AdminsAliasSid,
  394. AdminsAliasSid,
  395. &GenericMapping[ObjectType],
  396. &ServerSD );
  397. DBGCHK( !OK, ( "BuildPrintObjectProtection failed" ) );
  398. CleanUp:
  399. if (WorldSid) {
  400. FreeSid( WorldSid );
  401. }
  402. if (AdminsAliasSid) {
  403. FreeSid( AdminsAliasSid );
  404. }
  405. if (CreatorOwnerSid) {
  406. FreeSid( CreatorOwnerSid );
  407. }
  408. if (PrintOpsAliasSid) {
  409. FreeSid( PrintOpsAliasSid );
  410. }
  411. if (SystemOpsAliasSid) {
  412. FreeSid( SystemOpsAliasSid );
  413. }
  414. if (PowerUsersAliasSid) {
  415. FreeSid( PowerUsersAliasSid );
  416. }
  417. pServerSecurityDescriptor = ServerSD;
  418. return ServerSD;
  419. }
  420. /* CreatePrinterSecurityDescriptor
  421. *
  422. * Creates a default security descriptor for a printer by inheritance
  423. * of the access flags in the local spooler's security descriptor.
  424. * The resulting descriptor is allocated from the process' heap
  425. * and should be freed by DeletePrinterSecurityDescriptor.
  426. *
  427. * Argument: pCreatorSecurityDescriptor - if the creator supplies
  428. * a security descriptor, this should point to it. Otherwise
  429. * it should be NULL.
  430. *
  431. * Return: The printer's security descriptor
  432. *
  433. */
  434. PSECURITY_DESCRIPTOR
  435. CreatePrinterSecurityDescriptor(
  436. PSECURITY_DESCRIPTOR pCreatorSecurityDescriptor
  437. )
  438. {
  439. HANDLE ClientToken;
  440. PSECURITY_DESCRIPTOR pPrivateObjectSecurity;
  441. PSECURITY_DESCRIPTOR pPrinterSecurityDescriptor;
  442. DWORD ObjectType = SPOOLER_OBJECT_PRINTER;
  443. BOOL OK;
  444. HANDLE hToken;
  445. BOOL DaclPresent;
  446. PACL pDacl;
  447. BOOL DaclDefaulted = FALSE;
  448. DWORD HackOutAce;
  449. if( GetTokenHandle( &ClientToken ) )
  450. {
  451. hToken = RevertToPrinterSelf( );
  452. OK = CreatePrivateObjectSecurity( pServerSecurityDescriptor,
  453. pCreatorSecurityDescriptor,
  454. &pPrivateObjectSecurity,
  455. TRUE, // This is a container
  456. ClientToken,
  457. &GenericMapping[ObjectType] );
  458. ImpersonatePrinterClient(hToken);
  459. CloseHandle(ClientToken);
  460. DBGCHK( !OK, ( "CreatePrivateObjectSecurity failed: Error %d", GetLastError() ) );
  461. if( !OK )
  462. return NULL;
  463. pPrinterSecurityDescriptor = pPrivateObjectSecurity;
  464. if( !pCreatorSecurityDescriptor )
  465. {
  466. GetSecurityDescriptorDacl( pPrinterSecurityDescriptor,
  467. &DaclPresent,
  468. &pDacl,
  469. &DaclDefaulted );
  470. /* HACK HACK HACK HACK HACK
  471. *
  472. * We defined an extra ACE for the benefit of the ACL editor.
  473. * This is container-inherit,
  474. * and we want it to propagate onto documents.
  475. * However, this means it will also propagate onto printers,
  476. * which we definitely don't want.
  477. */
  478. HackOutAce = GetHackOutAce( pDacl );
  479. if( HackOutAce != (DWORD)-1 )
  480. DeleteAce( pDacl, HackOutAce );
  481. #if DBG
  482. if( MODULE_DEBUG & DBG_SECURITY ){
  483. DBGMSG( DBG_SECURITY, ( "Printer security descriptor DACL:\n" ));
  484. DumpAcl( pDacl );
  485. }
  486. #endif /* DBG */
  487. }
  488. }
  489. else
  490. {
  491. OK = FALSE;
  492. }
  493. return ( OK ? pPrinterSecurityDescriptor : NULL );
  494. }
  495. /*
  496. *
  497. */
  498. DWORD GetHackOutAce( PACL pDacl )
  499. {
  500. DWORD i;
  501. PACCESS_ALLOWED_ACE pAce;
  502. BOOL OK = TRUE;
  503. i = 0;
  504. while( OK )
  505. {
  506. OK = GetAce( pDacl, i, (LPVOID *)&pAce );
  507. DBGCHK( !OK, ( "Failed to get ACE. Error %d", GetLastError() ) );
  508. /* Find the dummy ace that isn't inherit-only:
  509. */
  510. if( OK && ( pAce->Mask == DUMMY_ACE_ACCESS_MASK )
  511. &&( !( pAce->Header.AceFlags & INHERIT_ONLY_ACE ) ) )
  512. return i;
  513. }
  514. return (DWORD)-1;
  515. }
  516. /* SetPrinterSecurityDescriptor
  517. *
  518. * Arguments:
  519. *
  520. * SecurityInformation - Type of security information to be applied,
  521. * typically DACL_SECURITY_INFORMATION. (This is a 32-bit array.)
  522. *
  523. * pModificationDescriptor - A pointer to a pointer to a security
  524. * descriptor to be applied to the previous descriptor.
  525. *
  526. * pObjectSecurityDescriptor - The previous descriptor which is to be
  527. * modified.
  528. *
  529. *
  530. * Return:
  531. *
  532. * Boolean indicating success or otherwise.
  533. *
  534. */
  535. BOOL
  536. SetPrinterSecurityDescriptor(
  537. SECURITY_INFORMATION SecurityInformation,
  538. PSECURITY_DESCRIPTOR pModificationDescriptor,
  539. PSECURITY_DESCRIPTOR *ppObjectsSecurityDescriptor
  540. )
  541. {
  542. HANDLE ClientToken;
  543. DWORD ObjectType = SPOOLER_OBJECT_PRINTER;
  544. BOOL OK = FALSE;
  545. HANDLE hToken;
  546. if( GetTokenHandle( &ClientToken ) )
  547. {
  548. /* SetPrivateObjectSecurity should not be called when we are
  549. * impersonating a client, since it may need to allocate memory:
  550. */
  551. hToken = RevertToPrinterSelf( );
  552. OK = SetPrivateObjectSecurity( SecurityInformation,
  553. pModificationDescriptor,
  554. ppObjectsSecurityDescriptor,
  555. &GenericMapping[ObjectType],
  556. ClientToken );
  557. ImpersonatePrinterClient(hToken);
  558. DBGCHK( !OK, ( "SetPrivateObjectSecurity failed: Error %d", GetLastError() ) );
  559. CloseHandle(ClientToken);
  560. }
  561. return OK;
  562. }
  563. /* CreateDocumentSecurityDescriptor
  564. *
  565. * Creates a default security descriptor for a document by inheritance
  566. * of the access flags in the supplied printer security descriptor.
  567. * The resulting descriptor is allocated from the process' heap
  568. * and should be freed by DeleteDocumentSecurityDescriptor.
  569. *
  570. * Argument: The printer's security descriptor
  571. *
  572. * Return: The document's security descriptor
  573. *
  574. */
  575. PSECURITY_DESCRIPTOR
  576. CreateDocumentSecurityDescriptor(
  577. PSECURITY_DESCRIPTOR pPrinterSecurityDescriptor
  578. )
  579. {
  580. HANDLE ClientToken;
  581. PSECURITY_DESCRIPTOR pPrivateObjectSecurity;
  582. PSECURITY_DESCRIPTOR pDocumentSecurityDescriptor;
  583. PSECURITY_DESCRIPTOR pSD = NULL;
  584. DWORD ObjectType = SPOOLER_OBJECT_DOCUMENT;
  585. BOOL OK = FALSE;
  586. HANDLE hToken;
  587. if( GetTokenHandle( &ClientToken ) )
  588. {
  589. hToken = RevertToPrinterSelf( );
  590. //
  591. // The function CreateDocumentSecurityDescriptor does not preserve
  592. // the last error correctly. If CreatePrivateObjectSecurityEx fails,
  593. // it sets the last error. But after that,
  594. //
  595. OK = BuildJobOwnerSecurityDescriptor(ClientToken, &pSD) &&
  596. CreatePrivateObjectSecurityEx(pPrinterSecurityDescriptor,
  597. pSD,
  598. &pPrivateObjectSecurity,
  599. NULL,
  600. FALSE, // This is not a container
  601. SEF_DACL_AUTO_INHERIT | SEF_SACL_AUTO_INHERIT,
  602. ClientToken,
  603. &GenericMapping[ObjectType] );
  604. DestroyJobOwnerSecurityDescriptor(pSD);
  605. ImpersonatePrinterClient(hToken);
  606. CloseHandle(ClientToken);
  607. DBGCHK( !OK, ( "CreatePrivateObjectSecurity failed: Error %d", GetLastError() ) );
  608. if( !OK )
  609. return NULL;
  610. pDocumentSecurityDescriptor = pPrivateObjectSecurity;
  611. #if DBG
  612. if( MODULE_DEBUG & DBG_SECURITY )
  613. {
  614. BOOL DaclPresent;
  615. PACL pDacl;
  616. BOOL DaclDefaulted = FALSE;
  617. GetSecurityDescriptorDacl( pDocumentSecurityDescriptor,
  618. &DaclPresent,
  619. &pDacl,
  620. &DaclDefaulted );
  621. DBGMSG( DBG_SECURITY, ( "Document security descriptor DACL:\n" ));
  622. DumpAcl( pDacl );
  623. }
  624. #endif /* DBG */
  625. }
  626. else
  627. {
  628. OK = FALSE;
  629. }
  630. return ( OK ? pDocumentSecurityDescriptor : NULL );
  631. }
  632. /*
  633. *
  634. */
  635. BOOL DeletePrinterSecurity(
  636. PINIPRINTER pIniPrinter
  637. )
  638. {
  639. BOOL OK;
  640. OK = DestroyPrivateObjectSecurity( &pIniPrinter->pSecurityDescriptor );
  641. pIniPrinter->pSecurityDescriptor = NULL;
  642. DBGCHK( !OK, ( "DestroyPrivateObjectSecurity failed. Error %d", GetLastError() ) );
  643. return OK;
  644. }
  645. /*
  646. *
  647. */
  648. BOOL DeleteDocumentSecurity(
  649. PINIJOB pIniJob
  650. )
  651. {
  652. BOOL OK;
  653. OK = DestroyPrivateObjectSecurity( &pIniJob->pSecurityDescriptor );
  654. DBGCHK( !OK, ( "DestroyPrivateObjectSecurity failed. Error %d", GetLastError() ) );
  655. OK = ObjectCloseAuditAlarm( szSpooler, pIniJob,
  656. pIniJob->GenerateOnClose );
  657. DBGCHK( !OK, ( "ObjectCloseAuditAlarm failed. Error %d", GetLastError() ) );
  658. return OK;
  659. }
  660. #ifdef OLDSTUFF
  661. /* AllocateLocalSD
  662. *
  663. * Makes a copy of a security descriptor, allocating it out of the local heap.
  664. * The source descriptor MUST be in self-relative format.
  665. *
  666. * Argument
  667. *
  668. * pSourceSD - Pointer to a self-relative security descriptor
  669. *
  670. *
  671. * Returns
  672. *
  673. * A pointer to a locally allocated security descriptor.
  674. *
  675. * If the function fails to allocate the memory, NULL is returned.
  676. *
  677. * Note, if an invalid security descriptor is passed to
  678. * GetSecurityDescriptorLength, the return value is undefined,
  679. * therefore the caller should ensure that the source is valid.
  680. */
  681. PSECURITY_DESCRIPTOR AllocateLocalSD( PSECURITY_DESCRIPTOR pSourceSD )
  682. {
  683. DWORD Length;
  684. PSECURITY_DESCRIPTOR pLocalSD;
  685. Length = GetSecurityDescriptorLength( pSourceSD );
  686. pLocalSD = AllocSplMem( Length );
  687. if( pLocalSD )
  688. {
  689. memcpy( pLocalSD, pSourceSD, Length );
  690. }
  691. return pLocalSD;
  692. }
  693. #endif /* OLDSTUFF */
  694. //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  695. BOOL
  696. BuildPrintObjectProtection(
  697. IN PUCHAR AceType,
  698. IN DWORD AceCount,
  699. IN PSID *AceSid,
  700. IN ACCESS_MASK *AceMask,
  701. IN BYTE *InheritFlags,
  702. IN PSID OwnerSid,
  703. IN PSID GroupSid,
  704. IN PGENERIC_MAPPING GenericMap,
  705. OUT PSECURITY_DESCRIPTOR *ppSecurityDescriptor
  706. )
  707. /*++
  708. Routine Description:
  709. This routine builds a self-relative security descriptor ready
  710. to be applied to one of the print manager objects.
  711. If so indicated, a pointer to the last RID of the SID in the last
  712. ACE of the DACL is returned and a flag set indicating that the RID
  713. must be replaced before the security descriptor is applied to an object.
  714. This is to support USER object protection, which must grant some
  715. access to the user represented by the object.
  716. The SACL of each of these objects will be set to:
  717. Audit
  718. Success | Fail
  719. WORLD
  720. (Write | Delete | WriteDacl | AccessSystemSecurity)
  721. Arguments:
  722. AceType - Array of AceTypes.
  723. Must be ACCESS_ALLOWED_ACE_TYPE or ACCESS_DENIED_ACE_TYPE.
  724. AceCount - The number of ACEs to be included in the DACL.
  725. AceSid - Points to an array of SIDs to be granted access by the DACL.
  726. If the target SAM object is a User object, then the last entry
  727. in this array is expected to be the SID of an account within the
  728. domain with the last RID not yet set. The RID will be set during
  729. actual account creation.
  730. AceMask - Points to an array of accesses to be granted by the DACL.
  731. The n'th entry of this array corresponds to the n'th entry of
  732. the AceSid array. These masks should not include any generic
  733. access types.
  734. InheritFlags - Pointer to an array of inherit flags.
  735. The n'th entry of this array corresponds to the n'th entry of
  736. the AceSid array.
  737. OwnerSid - The SID of the owner to be assigned to the descriptor.
  738. GroupSid - The SID of the group to be assigned to the descriptor.
  739. GenericMap - Points to a generic mapping for the target object type.
  740. ppSecurityDescriptor - Receives a pointer to the security descriptor.
  741. This will be allcated from the process' heap, not the spooler's,
  742. and should therefore be freed with LocalFree().
  743. IN DWORD AceCount,
  744. IN PSID *AceSid,
  745. IN ACCESS_MASK *AceMask,
  746. IN BYTE *InheritFlags,
  747. IN PSID OwnerSid,
  748. IN PSID GroupSid,
  749. IN PGENERIC_MAPPING GenericMap,
  750. OUT PSECURITY_DESCRIPTOR *ppSecurityDescriptor
  751. Return Value:
  752. TBS.
  753. --*/
  754. {
  755. SECURITY_DESCRIPTOR Absolute;
  756. PSECURITY_DESCRIPTOR Relative = NULL;
  757. PACL TmpAcl= NULL;
  758. PACCESS_ALLOWED_ACE TmpAce;
  759. DWORD SDLength;
  760. DWORD DaclLength;
  761. DWORD i;
  762. BOOL bReturn = FALSE;
  763. //
  764. // The approach is to set up an absolute security descriptor that
  765. // looks like what we want and then copy it to make a self-relative
  766. // security descriptor.
  767. //
  768. if (InitializeSecurityDescriptor( &Absolute,
  769. SECURITY_DESCRIPTOR_REVISION1 ) &&
  770. SetSecurityDescriptorOwner( &Absolute, OwnerSid, FALSE ) &&
  771. SetSecurityDescriptorGroup( &Absolute, GroupSid, FALSE ) ) {
  772. //
  773. // Discretionary ACL
  774. //
  775. // Calculate its length,
  776. // Allocate it,
  777. // Initialize it,
  778. // Add each ACE
  779. // Set ACE as InheritOnly if necessary
  780. // Add it to the security descriptor
  781. //
  782. DaclLength = (DWORD)sizeof(ACL);
  783. for (i=0; i<AceCount; i++) {
  784. DaclLength += GetLengthSid( AceSid[i] ) +
  785. (DWORD)sizeof(ACCESS_ALLOWED_ACE) -
  786. (DWORD)sizeof(DWORD); //Subtract out SidStart field length
  787. }
  788. TmpAcl = AllocSplMem( DaclLength );
  789. if (TmpAcl && InitializeAcl( TmpAcl, DaclLength, ACL_REVISION2 )) {
  790. BOOL bLoop = TRUE;
  791. for (i=0; bLoop && i < AceCount; i++)
  792. {
  793. if( AceType[i] == ACCESS_ALLOWED_ACE_TYPE ) {
  794. bLoop = AddAccessAllowedAce ( TmpAcl, ACL_REVISION2, AceMask[i], AceSid[i] );
  795. } else {
  796. bLoop = AddAccessDeniedAce ( TmpAcl, ACL_REVISION2, AceMask[i], AceSid[i] );
  797. }
  798. if (bLoop) {
  799. if (InheritFlags[i] != 0)
  800. {
  801. if ( bLoop = GetAce( TmpAcl, i, (LPVOID *)&TmpAce )) {
  802. TmpAce->Header.AceFlags = InheritFlags[i];
  803. }
  804. }
  805. }
  806. }
  807. if (bLoop) {
  808. #if DBG
  809. DBGMSG( DBG_SECURITY, ( "Server security descriptor DACL:\n" ) );
  810. DumpAcl(TmpAcl);
  811. #endif /* DBG */
  812. if (SetSecurityDescriptorDacl (&Absolute, TRUE, TmpAcl, FALSE )) {
  813. //
  814. // Convert the Security Descriptor to Self-Relative
  815. //
  816. // Get the length needed
  817. // Allocate that much memory
  818. // Copy it
  819. // Free the generated absolute ACLs
  820. //
  821. SDLength = GetSecurityDescriptorLength( &Absolute );
  822. Relative = LocalAlloc( 0, SDLength );
  823. if (Relative) {
  824. bReturn = MakeSelfRelativeSD(&Absolute, Relative, &SDLength );
  825. }
  826. }
  827. }
  828. }
  829. }
  830. if (bReturn) {
  831. *ppSecurityDescriptor = Relative;
  832. } else {
  833. *ppSecurityDescriptor = NULL;
  834. if (Relative) {
  835. LocalFree(Relative);
  836. }
  837. }
  838. if (TmpAcl){
  839. FreeSplMem(TmpAcl);
  840. }
  841. return(bReturn);
  842. }
  843. /*++
  844. Routine Name:
  845. ValidateObjectAccess
  846. Routine Description:
  847. Validates whether the currently impersonated user has access to the given
  848. printer object or not.
  849. Arguments:
  850. ObjectType - SPOOLER_OBJECT_* value, which is an index into the global
  851. mapping for spooler objects.
  852. DesiredAccess - The type of access requested.
  853. ObjectHandle - If ObjectType == SPOOLER_OBJECT_PRINTER, this must be a printer
  854. handle, if SPOOLER_OBJECT_DOCUMENT, a pointer to a INIJOB
  855. structure. For SPOOLER_OBJECT_SERVER this is ignored.
  856. pGrantedAccess - The access that we granted to the client.
  857. pIniSpooler - The inispooler on which the obhect is located.
  858. Return Value:
  859. TRUE if requested access is granted.
  860. --*/
  861. BOOL
  862. ValidateObjectAccess(
  863. IN DWORD ObjectType,
  864. IN ACCESS_MASK DesiredAccess,
  865. IN LPVOID ObjectHandle,
  866. OUT PACCESS_MASK pGrantedAccess,
  867. IN PINISPOOLER pIniSpooler
  868. )
  869. {
  870. BOOL bRet = FALSE;
  871. HANDLE hClientToken = NULL;
  872. bRet = GetTokenHandle(&hClientToken);
  873. if (bRet)
  874. {
  875. bRet = ValidateObjectAccessWithToken(hClientToken, ObjectType, DesiredAccess, ObjectHandle, pGrantedAccess, pIniSpooler);
  876. }
  877. else if (pGrantedAccess)
  878. {
  879. *pGrantedAccess = 0;
  880. }
  881. if (hClientToken)
  882. {
  883. CloseHandle(hClientToken);
  884. }
  885. return bRet;
  886. }
  887. BOOL
  888. ValidateObjectAccessWithToken(
  889. IN HANDLE hClientToken,
  890. IN DWORD ObjectType,
  891. IN ACCESS_MASK DesiredAccess,
  892. IN LPVOID ObjectHandle,
  893. OUT PACCESS_MASK pGrantedAccess,
  894. IN PINISPOOLER pIniSpooler
  895. )
  896. {
  897. LPWSTR pObjectName;
  898. PSECURITY_DESCRIPTOR pSecurityDescriptor;
  899. PSPOOL pSpool = NULL;
  900. PINIPRINTER pIniPrinter;
  901. PINIJOB pIniJob;
  902. BOOL AccessCheckOK;
  903. BOOL OK;
  904. BOOL AccessStatus = TRUE;
  905. ACCESS_MASK MappedDesiredAccess;
  906. DWORD GrantedAccess = 0;
  907. PBOOL pGenerateOnClose;
  908. BYTE PrivilegeSetBuffer[256];
  909. DWORD PrivilegeSetBufferLength = 256;
  910. PPRIVILEGE_SET pPrivilegeSet;
  911. BOOL HackForNoImpersonationToken = FALSE;
  912. DWORD dwRetCode;
  913. PTOKEN_PRIVILEGES pPreviousTokenPrivileges;
  914. DWORD PreviousTokenPrivilegesLength;
  915. //
  916. // Some Print Providers may not require Security
  917. //
  918. if ( (pIniSpooler->SpoolerFlags & SPL_SECURITY_CHECK) == FALSE ) return TRUE;
  919. switch( ObjectType )
  920. {
  921. case SPOOLER_OBJECT_SERVER:
  922. case SPOOLER_OBJECT_XCV:
  923. if( ObjectHandle )
  924. pSpool = ObjectHandle;
  925. ObjectHandle = pIniSpooler;
  926. pObjectName = pIniSpooler->pMachineName;
  927. pSecurityDescriptor = pServerSecurityDescriptor;
  928. pGenerateOnClose = &ServerGenerateOnClose;
  929. break;
  930. case SPOOLER_OBJECT_PRINTER:
  931. pSpool = ObjectHandle;
  932. pIniPrinter = pSpool->pIniPrinter;
  933. pObjectName = pIniPrinter->pName;
  934. pSecurityDescriptor = pIniPrinter->pSecurityDescriptor;
  935. pGenerateOnClose = &pSpool->GenerateOnClose;
  936. break;
  937. case SPOOLER_OBJECT_DOCUMENT:
  938. pIniJob = (PINIJOB)ObjectHandle;
  939. pObjectName = pIniJob->pDocument;
  940. pSecurityDescriptor = pIniJob->pSecurityDescriptor;
  941. pGenerateOnClose = &pIniJob->GenerateOnClose;
  942. break;
  943. }
  944. MapGenericToSpecificAccess( ObjectType, DesiredAccess, &MappedDesiredAccess );
  945. if (MappedDesiredAccess & ACCESS_SYSTEM_SECURITY) {
  946. if (!SetRequiredPrivileges( hClientToken,
  947. &pPreviousTokenPrivileges,
  948. &PreviousTokenPrivilegesLength
  949. )) {
  950. if (pGrantedAccess) {
  951. *pGrantedAccess = 0;
  952. }
  953. return FALSE;
  954. }
  955. }
  956. pPrivilegeSet = (PPRIVILEGE_SET)PrivilegeSetBuffer;
  957. /* Call AccessCheck followed by ObjectOpenAuditAlarm rather than
  958. * AccessCheckAndAuditAlarm, because we may need to enable
  959. * SeSecurityPrivilege in order to check for ACCESS_SYSTEM_SECURITY
  960. * privilege. We must ensure that the security access-checking
  961. * API has the actual token whose security privilege we have enabled.
  962. * AccessCheckAndAuditAlarm is no good for this, because it opens
  963. * the client's token again, which may not have the privilege enabled.
  964. */
  965. AccessCheckOK = AccessCheck( pSecurityDescriptor,
  966. hClientToken,
  967. MappedDesiredAccess,
  968. &GenericMapping[ObjectType],
  969. pPrivilegeSet,
  970. &PrivilegeSetBufferLength,
  971. &GrantedAccess,
  972. &AccessStatus );
  973. if (!AccessCheckOK) {
  974. if (GetLastError() == ERROR_NO_IMPERSONATION_TOKEN) {
  975. DBGMSG(DBG_TRACE, ("No impersonation token. Access will be granted.\n"));
  976. HackForNoImpersonationToken = TRUE;
  977. dwRetCode = ERROR_SUCCESS;
  978. GrantedAccess = MappedDesiredAccess;
  979. } else {
  980. dwRetCode = GetLastError();
  981. }
  982. pPrivilegeSet = NULL;
  983. } else {
  984. if (!AccessStatus) {
  985. dwRetCode = GetLastError();
  986. }
  987. }
  988. OK = ObjectOpenAuditAlarm( szSpooler,
  989. ObjectHandle,
  990. ObjectTypeName[ObjectType],
  991. pObjectName,
  992. pSecurityDescriptor,
  993. hClientToken,
  994. MappedDesiredAccess,
  995. GrantedAccess,
  996. pPrivilegeSet,
  997. FALSE, /* No new object creation */
  998. AccessStatus,
  999. pGenerateOnClose );
  1000. if( MappedDesiredAccess & ACCESS_SYSTEM_SECURITY )
  1001. ResetRequiredPrivileges( hClientToken,
  1002. pPreviousTokenPrivileges,
  1003. PreviousTokenPrivilegesLength );
  1004. if( !pSpool )
  1005. ObjectCloseAuditAlarm( szSpooler, ObjectHandle, *pGenerateOnClose );
  1006. //
  1007. // Allowing power users to install printer drivers or other dlls into the
  1008. // trusted component base is a security hole. We now require that administrators
  1009. // and power users have the load driver privilege present in the token in order
  1010. // to be able to preform administrative tasks on the spooler. See bug 352856
  1011. // for more details.
  1012. //
  1013. if (AccessCheckOK &&
  1014. AccessStatus &&
  1015. ObjectType == SPOOLER_OBJECT_SERVER &&
  1016. GrantedAccess & SERVER_ACCESS_ADMINISTER)
  1017. {
  1018. BOOL bPrivPresent;
  1019. DWORD Attributes;
  1020. dwRetCode = CheckPrivilegePresent(hClientToken,
  1021. &gLoadDriverPrivilegeLuid,
  1022. &bPrivPresent,
  1023. &Attributes);
  1024. if (dwRetCode == ERROR_SUCCESS)
  1025. {
  1026. //
  1027. // The reason why we check if the load driver privilege is present and
  1028. // not present AND enabled is the following. Let's assume you have been
  1029. // granted the privilege to load drivers.
  1030. // When you logon on interactively SeLoadDriverPrivilege is enabled.
  1031. // When you logon on via the secondary logon (runas which calls
  1032. // CreateProcessWithLogonW) then the privilege is disabled. We do not want
  1033. // to have inconsistent behavior regarding administering the spooler server.
  1034. //
  1035. if (!bPrivPresent)
  1036. {
  1037. //
  1038. // The caller has been granted SERVER_ACCESS_ADMINISTER permission but
  1039. // the caller doesn't have the privilege to load drivers. We do not
  1040. // grant the desired access in this case.
  1041. //
  1042. GrantedAccess = 0;
  1043. AccessStatus = FALSE;
  1044. dwRetCode = ERROR_ACCESS_DENIED;
  1045. }
  1046. }
  1047. else
  1048. {
  1049. //
  1050. // We cannot determine if the privilege is held, so we need to fail
  1051. // the AccessCheck function.
  1052. //
  1053. GrantedAccess = 0;
  1054. AccessCheckOK = FALSE;
  1055. dwRetCode = GetLastError();
  1056. }
  1057. }
  1058. if( pGrantedAccess )
  1059. *pGrantedAccess = GrantedAccess;
  1060. //
  1061. // we do the setlasterror here because we may have failed the AccessCheck
  1062. // or we succeeded but are denied access but the ObjectOpenAuditAlarm went
  1063. // thru smoothly and now there is no error code to return on the function
  1064. // so we specify the dwRetCode if we did fail.
  1065. //
  1066. if (!AccessCheckOK || !AccessStatus) {
  1067. SetLastError(dwRetCode);
  1068. }
  1069. return ( ( OK && AccessCheckOK && AccessStatus ) || HackForNoImpersonationToken );
  1070. }
  1071. /* AccessGranted
  1072. *
  1073. * Checks whether the desired access is granted, by comparing the GrantedAccess
  1074. * mask pointed to by pSpool.
  1075. *
  1076. * Parameters
  1077. *
  1078. * ObjectType - SPOOLER_OBJECT_* value, which is an index into the global
  1079. * mapping for spooler objects. This will not be SPOOLER_OBJECT_DOCUMENT,
  1080. * since we don't have document handles. It could potentially be
  1081. * SPOOLER_OBJECT_SERVER.
  1082. *
  1083. * DesiredAccess - The type of access requested.
  1084. *
  1085. * pSpool - A pointer to the SPOOL structure
  1086. *
  1087. * Returns
  1088. *
  1089. * TRUE - Access is granted
  1090. * FALSE - Access is not granted
  1091. */
  1092. BOOL
  1093. AccessGranted(
  1094. DWORD ObjectType,
  1095. ACCESS_MASK DesiredAccess,
  1096. PSPOOL pSpool
  1097. )
  1098. {
  1099. if ( (pSpool->pIniSpooler->SpoolerFlags & SPL_SECURITY_CHECK) == FALSE ) return TRUE;
  1100. MapGenericMask( &DesiredAccess,
  1101. &GenericMapping[ObjectType] );
  1102. return AreAllAccessesGranted( pSpool->GrantedAccess, DesiredAccess );
  1103. }
  1104. // Stolen from windows\base\username.c
  1105. // !!! Must close the handle that is returned
  1106. BOOL
  1107. GetTokenHandle(
  1108. PHANDLE pTokenHandle
  1109. )
  1110. {
  1111. if (!OpenThreadToken(GetCurrentThread(),
  1112. TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  1113. TRUE,
  1114. pTokenHandle)) {
  1115. if (GetLastError() == ERROR_NO_TOKEN) {
  1116. // This means we are not impersonating anybody.
  1117. // Instead, lets get the token out of the process.
  1118. if (!OpenProcessToken(GetCurrentProcess(),
  1119. TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  1120. pTokenHandle)) {
  1121. return FALSE;
  1122. }
  1123. } else
  1124. return FALSE;
  1125. }
  1126. return TRUE;
  1127. }
  1128. VOID MapGenericToSpecificAccess(
  1129. DWORD ObjectType,
  1130. DWORD GenericAccess,
  1131. PDWORD pSpecificAccess
  1132. )
  1133. {
  1134. *pSpecificAccess = GenericAccess;
  1135. MapGenericMask( pSpecificAccess,
  1136. &GenericMapping[ObjectType] );
  1137. }
  1138. /* GetSecurityInformation
  1139. *
  1140. * Fills in the security information with a mask specifying the contents
  1141. * of the security descriptor.
  1142. *
  1143. * Parameters
  1144. *
  1145. * pSecurityDescriptor - A pointer to a security descriptor
  1146. * that the caller wishes to set. This may be NULL.
  1147. *
  1148. * pSecurityInformation - A pointer to a buffer to receive
  1149. * the security information flags.
  1150. *
  1151. *
  1152. * Warning: This is an egregious hack.
  1153. * We need to find out what is being set so we can verify the caller
  1154. * has the required privileges.
  1155. * There's no way an app like Print Manager can tell us what bits
  1156. * of the security descriptor it wants to set.
  1157. *
  1158. * The following flags may be set:
  1159. *
  1160. * OWNER_SECURITY_INFORMATION
  1161. * GROUP_SECURITY_INFORMATION
  1162. * DACL_SECURITY_INFORMATION
  1163. * SACL_SECURITY_INFORMATION
  1164. *
  1165. * Returns
  1166. *
  1167. * TRUE - No errors occurred
  1168. * FALSE - An error occurred
  1169. *
  1170. */
  1171. BOOL
  1172. GetSecurityInformation(
  1173. PSECURITY_DESCRIPTOR pSecurityDescriptor,
  1174. PSECURITY_INFORMATION pSecurityInformation
  1175. )
  1176. {
  1177. SECURITY_INFORMATION SecurityInformation = 0;
  1178. BOOL Defaulted;
  1179. PSID pSidOwner;
  1180. PSID pSidGroup;
  1181. BOOL DaclPresent;
  1182. PACL pDacl;
  1183. BOOL SaclPresent;
  1184. PACL pSacl;
  1185. BOOL rc = TRUE;
  1186. if( pSecurityDescriptor
  1187. && IsValidSecurityDescriptor( pSecurityDescriptor ) )
  1188. {
  1189. if( GetSecurityDescriptorOwner( pSecurityDescriptor, &pSidOwner, &Defaulted )
  1190. && GetSecurityDescriptorGroup( pSecurityDescriptor, &pSidGroup, &Defaulted )
  1191. && GetSecurityDescriptorDacl( pSecurityDescriptor, &DaclPresent, &pDacl, &Defaulted )
  1192. && GetSecurityDescriptorSacl( pSecurityDescriptor, &SaclPresent, &pSacl, &Defaulted ) )
  1193. {
  1194. if( pSidOwner )
  1195. SecurityInformation |= OWNER_SECURITY_INFORMATION;
  1196. if( pSidGroup )
  1197. SecurityInformation |= GROUP_SECURITY_INFORMATION;
  1198. if( DaclPresent )
  1199. SecurityInformation |= DACL_SECURITY_INFORMATION;
  1200. if( SaclPresent )
  1201. SecurityInformation |= SACL_SECURITY_INFORMATION;
  1202. }
  1203. else
  1204. rc = FALSE;
  1205. }else {
  1206. DBGMSG(DBG_TRACE, ("Either NULL pSecurityDescriptor or !IsValidSecurityDescriptor %.8x\n", pSecurityDescriptor));
  1207. rc = FALSE;
  1208. }
  1209. DBGMSG( DBG_TRACE, ("GetSecurityInformation returns %d with SecurityInformation = %08x\n", rc, SecurityInformation) );
  1210. *pSecurityInformation = SecurityInformation;
  1211. return rc;
  1212. }
  1213. /* GetPrivilegeRequired
  1214. *
  1215. * Returns a mask containing the privileges required to set the specified
  1216. * security information.
  1217. *
  1218. * Parameter
  1219. *
  1220. * SecurityInformation - Flags specifying the security information
  1221. * that the caller wishes to set. This may be 0.
  1222. *
  1223. * Returns
  1224. *
  1225. * An access mask specifying the privileges required.
  1226. *
  1227. */
  1228. ACCESS_MASK
  1229. GetPrivilegeRequired(
  1230. SECURITY_INFORMATION SecurityInformation
  1231. )
  1232. {
  1233. ACCESS_MASK PrivilegeRequired = 0;
  1234. if( SecurityInformation & OWNER_SECURITY_INFORMATION )
  1235. PrivilegeRequired |= WRITE_OWNER;
  1236. if( SecurityInformation & GROUP_SECURITY_INFORMATION )
  1237. PrivilegeRequired |= WRITE_OWNER;
  1238. if( SecurityInformation & DACL_SECURITY_INFORMATION )
  1239. PrivilegeRequired |= WRITE_DAC;
  1240. if( SecurityInformation & SACL_SECURITY_INFORMATION )
  1241. PrivilegeRequired |= ACCESS_SYSTEM_SECURITY;
  1242. return PrivilegeRequired;
  1243. }
  1244. /* BuildPartialSecurityDescriptor
  1245. *
  1246. * Creates a copy of the source security descriptor, omitting those
  1247. * parts of the descriptor which the AccessGranted mask doesn't give
  1248. * read access to.
  1249. *
  1250. * Parameters
  1251. *
  1252. * AccessMask - Defines the permissions held by the client.
  1253. * This may include READ_CONTROL or ACCESS_SYSTEM_SECURITY.
  1254. *
  1255. * pSourceSecurityDescriptor - A pointer to the security descriptor
  1256. * upon which the partial security descriptor will be based.
  1257. * Its Owner, Group, DACL and SACL will be copied appropriately,
  1258. *
  1259. * ppPartialSecurityDescriptor - A pointer to a variable which
  1260. * will receive the address of the newly created descriptor.
  1261. * If the AccessMask parameter contains neither READ_CONTROL
  1262. * nor ACCESS_SYSTEM_SECURITY, the descriptor will be empty.
  1263. * The descriptor will be in self-relative format, and must
  1264. * be freed by the caller using FreeSplMem().
  1265. *
  1266. * pPartialSecurityDescriptorLength - A pointer to a variable
  1267. * to receive the length of the security descriptor.
  1268. * This should be passed as the second parameter to FreeSplMem()
  1269. * when the descriptor is freed.
  1270. *
  1271. * Returns
  1272. *
  1273. * TRUE - No error was detected
  1274. * FALSE - An error was detected
  1275. *
  1276. */
  1277. BOOL
  1278. BuildPartialSecurityDescriptor(
  1279. ACCESS_MASK AccessGranted,
  1280. PSECURITY_DESCRIPTOR pSourceSecurityDescriptor,
  1281. PSECURITY_DESCRIPTOR *ppPartialSecurityDescriptor,
  1282. PDWORD pPartialSecurityDescriptorLength
  1283. )
  1284. {
  1285. SECURITY_DESCRIPTOR AbsolutePartialSecurityDescriptor;
  1286. BOOL Defaulted = FALSE;
  1287. PSID pOwnerSid = NULL;
  1288. PSID pGroupSid = NULL;
  1289. BOOL DaclPresent = FALSE;
  1290. PACL pDacl = NULL;
  1291. BOOL SaclPresent = FALSE;
  1292. PACL pSacl = NULL;
  1293. BOOL ErrorOccurred = FALSE;
  1294. DWORD Length = 0;
  1295. PSECURITY_DESCRIPTOR pSelfRelativePartialSecurityDescriptor = NULL;
  1296. /* When we've initialized the security descriptor,
  1297. * it will have no owner, no primary group, no DACL and no SACL:
  1298. */
  1299. if( InitializeSecurityDescriptor( &AbsolutePartialSecurityDescriptor,
  1300. SECURITY_DESCRIPTOR_REVISION1 ) )
  1301. {
  1302. /* If the caller has READ_CONTROL permission,
  1303. * set the Owner, Group and DACL:
  1304. */
  1305. if( AreAllAccessesGranted( AccessGranted, READ_CONTROL ) )
  1306. {
  1307. if( GetSecurityDescriptorOwner( pSourceSecurityDescriptor,
  1308. &pOwnerSid, &Defaulted ) )
  1309. SetSecurityDescriptorOwner( &AbsolutePartialSecurityDescriptor,
  1310. pOwnerSid, Defaulted );
  1311. else
  1312. ErrorOccurred = TRUE;
  1313. if( GetSecurityDescriptorGroup( pSourceSecurityDescriptor,
  1314. &pGroupSid, &Defaulted ) )
  1315. SetSecurityDescriptorGroup( &AbsolutePartialSecurityDescriptor,
  1316. pGroupSid, Defaulted );
  1317. else
  1318. ErrorOccurred = TRUE;
  1319. if( GetSecurityDescriptorDacl( pSourceSecurityDescriptor,
  1320. &DaclPresent, &pDacl, &Defaulted ) )
  1321. SetSecurityDescriptorDacl( &AbsolutePartialSecurityDescriptor,
  1322. DaclPresent, pDacl, Defaulted );
  1323. else
  1324. ErrorOccurred = TRUE;
  1325. }
  1326. /* If the caller has ACCESS_SYSTEM_SECURITY permission,
  1327. * set the SACL:
  1328. */
  1329. if( AreAllAccessesGranted( AccessGranted, ACCESS_SYSTEM_SECURITY ) )
  1330. {
  1331. if( GetSecurityDescriptorSacl( pSourceSecurityDescriptor,
  1332. &SaclPresent, &pSacl, &Defaulted ) )
  1333. SetSecurityDescriptorSacl( &AbsolutePartialSecurityDescriptor,
  1334. SaclPresent, pSacl, Defaulted );
  1335. else
  1336. ErrorOccurred = TRUE;
  1337. }
  1338. if( !ErrorOccurred )
  1339. {
  1340. Length = 0;
  1341. if( !MakeSelfRelativeSD( &AbsolutePartialSecurityDescriptor,
  1342. pSelfRelativePartialSecurityDescriptor,
  1343. &Length ) )
  1344. {
  1345. if( GetLastError( ) == ERROR_INSUFFICIENT_BUFFER )
  1346. {
  1347. pSelfRelativePartialSecurityDescriptor = AllocSplMem( Length );
  1348. if( !pSelfRelativePartialSecurityDescriptor
  1349. || !MakeSelfRelativeSD( &AbsolutePartialSecurityDescriptor,
  1350. pSelfRelativePartialSecurityDescriptor,
  1351. &Length ) )
  1352. {
  1353. ErrorOccurred = TRUE;
  1354. }
  1355. }
  1356. else
  1357. {
  1358. ErrorOccurred = TRUE;
  1359. DBGMSG(DBG_WARNING, ("MakeSelfRelativeSD failed: Error %d\n",
  1360. GetLastError()));
  1361. }
  1362. }
  1363. else
  1364. {
  1365. DBGMSG(DBG_WARNING, ("Expected MakeSelfRelativeSD to fail!\n"));
  1366. }
  1367. }
  1368. }
  1369. else
  1370. ErrorOccurred = TRUE;
  1371. if( !ErrorOccurred )
  1372. {
  1373. *ppPartialSecurityDescriptor = pSelfRelativePartialSecurityDescriptor;
  1374. *pPartialSecurityDescriptorLength = Length;
  1375. }
  1376. return !ErrorOccurred;
  1377. }
  1378. BOOL
  1379. SetRequiredPrivileges(
  1380. IN HANDLE TokenHandle,
  1381. OUT PTOKEN_PRIVILEGES *ppPreviousTokenPrivileges,
  1382. OUT PDWORD pPreviousTokenPrivilegesLength
  1383. )
  1384. /*++
  1385. Routine Description:
  1386. Arguments:
  1387. TokenHandle - A token associated with the current thread or process
  1388. ppPreviousTokenPrivileges - This will be filled with the address of the
  1389. buffer allocated to hold the previously existing privileges for this
  1390. process or thread.
  1391. pPreviousTokenPrivilegesLength - This will be filled with the length of the
  1392. buffer allocated.
  1393. Return Value:
  1394. TRUE if successful.
  1395. --*/
  1396. {
  1397. /* Make enough room for TOKEN_PRIVILEGES with an array of 2 Privileges
  1398. * (there's 1 by default):
  1399. */
  1400. #define PRIV_SECURITY 0
  1401. #define PRIV_COUNT 1
  1402. LUID SecurityValue;
  1403. BYTE TokenPrivilegesBuffer[ sizeof( TOKEN_PRIVILEGES ) +
  1404. ( ( PRIV_COUNT - 1 ) *
  1405. sizeof( LUID_AND_ATTRIBUTES ) ) ];
  1406. PTOKEN_PRIVILEGES pTokenPrivileges;
  1407. DWORD FirstTryBufferLength = 256;
  1408. DWORD BytesNeeded;
  1409. //
  1410. // First, assert Audit privilege
  1411. //
  1412. memset( &SecurityValue, 0, sizeof SecurityValue );
  1413. if( !LookupPrivilegeValue( NULL, SE_SECURITY_NAME, &SecurityValue ) )
  1414. {
  1415. DBGMSG( DBG_WARNING,
  1416. ( "LookupPrivilegeValue failed: Error %d\n", GetLastError( ) ) );
  1417. return FALSE;
  1418. }
  1419. /* Allocate a buffer of a reasonable length to hold the current privileges,
  1420. * so we can restore them later:
  1421. */
  1422. *pPreviousTokenPrivilegesLength = FirstTryBufferLength;
  1423. if( !( *ppPreviousTokenPrivileges = AllocSplMem( FirstTryBufferLength ) ) )
  1424. return FALSE;
  1425. memset( &TokenPrivilegesBuffer, 0, sizeof TokenPrivilegesBuffer );
  1426. pTokenPrivileges = (PTOKEN_PRIVILEGES)&TokenPrivilegesBuffer;
  1427. /*
  1428. * Set up the privilege set we will need
  1429. */
  1430. pTokenPrivileges->PrivilegeCount = PRIV_COUNT;
  1431. pTokenPrivileges->Privileges[PRIV_SECURITY].Luid = SecurityValue;
  1432. pTokenPrivileges->Privileges[PRIV_SECURITY].Attributes = SE_PRIVILEGE_ENABLED;
  1433. if (!AdjustTokenPrivileges( TokenHandle,
  1434. FALSE,
  1435. pTokenPrivileges,
  1436. *pPreviousTokenPrivilegesLength,
  1437. *ppPreviousTokenPrivileges,
  1438. &BytesNeeded )) {
  1439. if( GetLastError() == ERROR_INSUFFICIENT_BUFFER )
  1440. {
  1441. *pPreviousTokenPrivilegesLength = BytesNeeded;
  1442. *ppPreviousTokenPrivileges = ReallocSplMem(
  1443. *ppPreviousTokenPrivileges,
  1444. 0,
  1445. *pPreviousTokenPrivilegesLength );
  1446. if( *ppPreviousTokenPrivileges )
  1447. {
  1448. if (!AdjustTokenPrivileges( TokenHandle,
  1449. FALSE,
  1450. pTokenPrivileges,
  1451. *pPreviousTokenPrivilegesLength,
  1452. *ppPreviousTokenPrivileges,
  1453. &BytesNeeded )) {
  1454. DBGMSG( DBG_WARNING, ("AdjustTokenPrivileges failed: Error %d\n", GetLastError()));
  1455. goto Fail;
  1456. }
  1457. }
  1458. else
  1459. {
  1460. *pPreviousTokenPrivilegesLength = 0;
  1461. goto Fail;
  1462. }
  1463. }
  1464. else
  1465. {
  1466. DBGMSG( DBG_WARNING, ("AdjustTokenPrivileges failed: Error %d\n", GetLastError()));
  1467. goto Fail;
  1468. }
  1469. }
  1470. return TRUE;
  1471. Fail:
  1472. if (*ppPreviousTokenPrivileges) {
  1473. FreeSplMem(*ppPreviousTokenPrivileges);
  1474. }
  1475. return FALSE;
  1476. }
  1477. BOOL
  1478. ResetRequiredPrivileges(
  1479. IN HANDLE TokenHandle,
  1480. IN PTOKEN_PRIVILEGES pPreviousTokenPrivileges,
  1481. IN DWORD PreviousTokenPrivilegesLength
  1482. )
  1483. /*++
  1484. Routine Description:
  1485. Arguments:
  1486. TokenHandle - A token associated with the current thread or process
  1487. pPreviousTokenPrivileges - The address of the buffer holding the previous
  1488. privileges to be reinstated.
  1489. PreviousTokenPrivilegesLength - Length of the buffer for deallocation.
  1490. Return Value:
  1491. TRUE if successful.
  1492. --*/
  1493. {
  1494. BOOL OK;
  1495. OK = AdjustTokenPrivileges ( TokenHandle,
  1496. FALSE,
  1497. pPreviousTokenPrivileges,
  1498. 0,
  1499. NULL,
  1500. NULL );
  1501. FreeSplMem( pPreviousTokenPrivileges );
  1502. return OK;
  1503. }
  1504. /* CreateEverybodySecurityDescriptor
  1505. *
  1506. * Creates a security descriptor giving everyone access
  1507. *
  1508. * Arguments: None
  1509. *
  1510. * Return: The security descriptor returned by BuildPrintObjectProtection.
  1511. *
  1512. */
  1513. #undef MAX_ACE
  1514. #define MAX_ACE 5
  1515. #define DBGCHK( Condition, ErrorInfo ) \
  1516. if( Condition ) DBGMSG( DBG_WARNING, ErrorInfo )
  1517. PSECURITY_DESCRIPTOR
  1518. CreateEverybodySecurityDescriptor(
  1519. VOID
  1520. )
  1521. {
  1522. UCHAR AceType[MAX_ACE];
  1523. PSID AceSid[MAX_ACE]; // Don't expect more than MAX_ACE ACEs in any of these.
  1524. DWORD AceCount;
  1525. //
  1526. // For Code optimization we replace 5 individaul
  1527. // SID_IDENTIFIER_AUTHORITY with an array of
  1528. // SID_IDENTIFIER_AUTHORITYs
  1529. // where
  1530. // SidAuthority[0] = UserSidAuthority
  1531. // SidAuthority[1] = PowerSidAuthority
  1532. // SidAuthority[2] = CreatorSidAuthority
  1533. // SidAuthority[3] = SystemSidAuthority
  1534. // SidAuthority[4] = AdminSidAuthority
  1535. //
  1536. SID_IDENTIFIER_AUTHORITY SidAuthority[MAX_ACE] = {
  1537. SECURITY_NT_AUTHORITY,
  1538. SECURITY_NT_AUTHORITY,
  1539. SECURITY_CREATOR_SID_AUTHORITY,
  1540. SECURITY_NT_AUTHORITY,
  1541. SECURITY_NT_AUTHORITY
  1542. };
  1543. //
  1544. // For code optimization we replace 5 individual Sids with
  1545. // an array of Sids
  1546. // where
  1547. // Sid[0] = UserSid
  1548. // Sid[1] = PowerSid
  1549. // Sid[2] = CreatorSid
  1550. // Sid[3] = SystemSid
  1551. // Sid[4] = AdminSid
  1552. //
  1553. PSID Sids[MAX_ACE] = {NULL,NULL,NULL,NULL,NULL};
  1554. //
  1555. // Access masks corresponding to Sids
  1556. //
  1557. ACCESS_MASK AceMask[MAX_ACE] = {
  1558. (FILE_GENERIC_EXECUTE | SYNCHRONIZE | FILE_GENERIC_WRITE | FILE_GENERIC_READ) &
  1559. ~READ_CONTROL & ~FILE_WRITE_ATTRIBUTES &
  1560. ~FILE_WRITE_EA&~FILE_READ_DATA&~FILE_LIST_DIRECTORY ,
  1561. (FILE_GENERIC_EXECUTE | SYNCHRONIZE | FILE_GENERIC_WRITE | FILE_GENERIC_READ) &
  1562. ~READ_CONTROL & ~FILE_WRITE_ATTRIBUTES &
  1563. ~FILE_WRITE_EA&~FILE_READ_DATA&~FILE_LIST_DIRECTORY ,
  1564. STANDARD_RIGHTS_ALL | FILE_GENERIC_EXECUTE | FILE_GENERIC_WRITE |
  1565. FILE_GENERIC_READ | FILE_ALL_ACCESS ,
  1566. STANDARD_RIGHTS_ALL | FILE_GENERIC_EXECUTE | FILE_GENERIC_WRITE |
  1567. FILE_GENERIC_READ | FILE_ALL_ACCESS ,
  1568. STANDARD_RIGHTS_ALL | FILE_GENERIC_EXECUTE | FILE_GENERIC_WRITE |
  1569. FILE_GENERIC_READ | FILE_ALL_ACCESS ,
  1570. };
  1571. //
  1572. // SubAuthorities leading to the proper Group
  1573. //
  1574. DWORD SubAuthorities[3*MAX_ACE] = {
  1575. 2 , SECURITY_BUILTIN_DOMAIN_RID , DOMAIN_ALIAS_RID_USERS ,
  1576. 2 , SECURITY_BUILTIN_DOMAIN_RID , DOMAIN_ALIAS_RID_POWER_USERS ,
  1577. 1 , SECURITY_CREATOR_OWNER_RID , 0 ,
  1578. 1 , SECURITY_LOCAL_SYSTEM_RID , 0 ,
  1579. 2 , SECURITY_BUILTIN_DOMAIN_RID , DOMAIN_ALIAS_RID_ADMINS
  1580. };
  1581. //
  1582. // CONTAINER_INHERIT_ACE -> This folder and subfolders
  1583. // OBJECT_INHERIT_ACE -> Files
  1584. //
  1585. BYTE InheritFlags[MAX_ACE] = {
  1586. CONTAINER_INHERIT_ACE,
  1587. CONTAINER_INHERIT_ACE,
  1588. CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE,
  1589. CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE,
  1590. CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE
  1591. };
  1592. PSECURITY_DESCRIPTOR ServerSD = NULL;
  1593. //
  1594. // Printer SD
  1595. //
  1596. for(AceCount = 0;
  1597. ( (AceCount < MAX_ACE) &&
  1598. AllocateAndInitializeSid(&SidAuthority[AceCount],
  1599. (BYTE)SubAuthorities[AceCount*3],
  1600. SubAuthorities[AceCount*3+1],
  1601. SubAuthorities[AceCount*3+2],
  1602. 0, 0, 0, 0, 0, 0,
  1603. &Sids[AceCount]));
  1604. AceCount++)
  1605. {
  1606. AceType[AceCount] = ACCESS_ALLOWED_ACE_TYPE;
  1607. AceSid[AceCount] = Sids[AceCount];
  1608. }
  1609. if(AceCount == MAX_ACE)
  1610. {
  1611. if(!BuildPrintObjectProtection( AceType,
  1612. AceCount,
  1613. AceSid,
  1614. AceMask,
  1615. InheritFlags,
  1616. NULL,
  1617. NULL,
  1618. NULL,
  1619. &ServerSD ) )
  1620. {
  1621. DBGMSG( DBG_WARNING,( "Couldn't buidl Print Object protection" ) );
  1622. ServerSD = NULL;
  1623. }
  1624. }
  1625. else
  1626. {
  1627. DBGMSG( DBG_WARNING,( "Couldn't Allocate and initialize SIDs" ) );
  1628. }
  1629. for(AceCount=0;AceCount<MAX_ACE;AceCount++)
  1630. {
  1631. if(Sids[AceCount])
  1632. FreeSid( Sids[AceCount] );
  1633. }
  1634. return ServerSD;
  1635. }
  1636. /* CreateDriversShareSecurityDescriptor
  1637. *
  1638. * Creates a security descriptor for the drivers$ share.
  1639. * This reflects the security descriptor applied to the print server,
  1640. * in that Everyone is given GENERIC_READ | GENERIC_EXECUTE,
  1641. * and everyone with SERVER_ACCESS_ADMINISTER (Administrators,
  1642. * Power Users etc.) is given GENERIC_ALL access to the share,
  1643. *
  1644. * If in future releases we support changes to the print server
  1645. * security descriptor (e.g. allowing the ability to deny
  1646. * SERVER_ACCESS_ENUMERATE), this routine will have to become more
  1647. * sophisticated, as the access to the share will probably need
  1648. * to be modified accordingly.
  1649. *
  1650. * Arguments: None
  1651. *
  1652. * Return: The security descriptor returned by BuildPrintObjectProtection.
  1653. *
  1654. */
  1655. #undef MAX_ACE
  1656. #define MAX_ACE 20
  1657. #define DBGCHK( Condition, ErrorInfo ) \
  1658. if( Condition ) DBGMSG( DBG_WARNING, ErrorInfo )
  1659. PSECURITY_DESCRIPTOR
  1660. CreateDriversShareSecurityDescriptor(
  1661. VOID
  1662. )
  1663. {
  1664. DWORD ObjectType = SPOOLER_OBJECT_SERVER;
  1665. NT_PRODUCT_TYPE NtProductType;
  1666. PSID AceSid[MAX_ACE]; // Don't expect more than MAX_ACE ACEs in any of these.
  1667. ACCESS_MASK AceMask[MAX_ACE]; // Access masks corresponding to Sids
  1668. BYTE InheritFlags[MAX_ACE]; //
  1669. UCHAR AceType[MAX_ACE];
  1670. DWORD AceCount;
  1671. SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
  1672. SID_IDENTIFIER_AUTHORITY WorldSidAuthority = SECURITY_WORLD_SID_AUTHORITY;
  1673. SID_IDENTIFIER_AUTHORITY CreatorSidAuthority = SECURITY_CREATOR_SID_AUTHORITY;
  1674. PSID WorldSid = NULL;
  1675. PSID AdminsAliasSid = NULL;
  1676. PSID PrintOpsAliasSid = NULL;
  1677. PSID SystemOpsAliasSid = NULL;
  1678. PSID PowerUsersAliasSid = NULL;
  1679. PSID CreatorOwnerSid = NULL;
  1680. PSECURITY_DESCRIPTOR pDriversShareSD = NULL;
  1681. BOOL OK;
  1682. //
  1683. // Printer SD
  1684. //
  1685. AceCount = 0;
  1686. /* Creator-Owner SID: */
  1687. OK = AllocateAndInitializeSid( &CreatorSidAuthority, 1,
  1688. SECURITY_CREATOR_OWNER_RID,
  1689. 0, 0, 0, 0, 0, 0, 0,
  1690. &CreatorOwnerSid );
  1691. DBGCHK( !OK, ( "Couldn't Allocate and initialize SID" ) );
  1692. if ( !OK ) {
  1693. goto CleanUp;
  1694. }
  1695. /* World SID */
  1696. OK = AllocateAndInitializeSid( &WorldSidAuthority, 1,
  1697. SECURITY_WORLD_RID,
  1698. 0, 0, 0, 0, 0, 0, 0,
  1699. &WorldSid );
  1700. DBGCHK( !OK, ( "Couldn't Allocate and initialize SID" ) );
  1701. if ( !OK ) {
  1702. goto CleanUp;
  1703. }
  1704. AceType[AceCount] = ACCESS_ALLOWED_ACE_TYPE;
  1705. AceSid[AceCount] = WorldSid;
  1706. AceMask[AceCount] = GENERIC_READ | GENERIC_EXECUTE;
  1707. InheritFlags[AceCount] = 0;
  1708. AceCount++;
  1709. /* Admins alias SID */
  1710. OK = AllocateAndInitializeSid( &NtAuthority, 2,
  1711. SECURITY_BUILTIN_DOMAIN_RID,
  1712. DOMAIN_ALIAS_RID_ADMINS,
  1713. 0, 0, 0, 0, 0, 0,
  1714. &AdminsAliasSid );
  1715. DBGCHK( !OK, ( "Couldn't Allocate and initialize SID" ) );
  1716. if ( !OK ) {
  1717. goto CleanUp;
  1718. }
  1719. AceType[AceCount] = ACCESS_ALLOWED_ACE_TYPE;
  1720. AceSid[AceCount] = AdminsAliasSid;
  1721. AceMask[AceCount] = GENERIC_ALL;
  1722. InheritFlags[AceCount] = 0;
  1723. AceCount++;
  1724. OK = RtlGetNtProductType( &NtProductType );
  1725. DBGCHK( !OK, ( "Couldn't get product type" ) );
  1726. if (NtProductType == NtProductLanManNt) {
  1727. /* Print Ops alias SID */
  1728. OK = AllocateAndInitializeSid( &NtAuthority, 2,
  1729. SECURITY_BUILTIN_DOMAIN_RID,
  1730. DOMAIN_ALIAS_RID_PRINT_OPS,
  1731. 0, 0, 0, 0, 0, 0,
  1732. &PrintOpsAliasSid );
  1733. DBGCHK( !OK, ( "Couldn't Allocate and initialize SID" ) );
  1734. if ( !OK ) {
  1735. goto CleanUp;
  1736. }
  1737. AceType[AceCount] = ACCESS_ALLOWED_ACE_TYPE;
  1738. AceSid[AceCount] = PrintOpsAliasSid;
  1739. AceMask[AceCount] = GENERIC_ALL;
  1740. InheritFlags[AceCount] = 0;
  1741. AceCount++;
  1742. /* System Ops alias SID */
  1743. OK = AllocateAndInitializeSid( &NtAuthority, 2,
  1744. SECURITY_BUILTIN_DOMAIN_RID,
  1745. DOMAIN_ALIAS_RID_SYSTEM_OPS,
  1746. 0, 0, 0, 0, 0, 0,
  1747. &SystemOpsAliasSid );
  1748. DBGCHK( !OK, ( "Couldn't Allocate and initialize SID" ) );
  1749. if ( !OK ) {
  1750. goto CleanUp;
  1751. }
  1752. AceType[AceCount] = ACCESS_ALLOWED_ACE_TYPE;
  1753. AceSid[AceCount] = SystemOpsAliasSid;
  1754. AceMask[AceCount] = GENERIC_ALL;
  1755. InheritFlags[AceCount] = 0;
  1756. AceCount++;
  1757. } else {
  1758. //
  1759. // LanManNT product
  1760. //
  1761. OK = AllocateAndInitializeSid( &NtAuthority, 2,
  1762. SECURITY_BUILTIN_DOMAIN_RID,
  1763. DOMAIN_ALIAS_RID_POWER_USERS,
  1764. 0, 0, 0, 0, 0, 0,
  1765. &PowerUsersAliasSid );
  1766. DBGCHK( !OK, ( "Couldn't Allocate and initialize SID" ) );
  1767. if ( !OK ) {
  1768. goto CleanUp;
  1769. }
  1770. AceType[AceCount] = ACCESS_ALLOWED_ACE_TYPE;
  1771. AceSid[AceCount] = PowerUsersAliasSid;
  1772. AceMask[AceCount] = GENERIC_ALL;
  1773. InheritFlags[AceCount] = 0;
  1774. AceCount++;
  1775. }
  1776. DBGCHK( ( AceCount > MAX_ACE ), ( "ACE count exceeded" ) );
  1777. OK = BuildPrintObjectProtection( AceType,
  1778. AceCount,
  1779. AceSid,
  1780. AceMask,
  1781. InheritFlags,
  1782. AdminsAliasSid,
  1783. AdminsAliasSid,
  1784. &GenericMapping[ObjectType],
  1785. &pDriversShareSD );
  1786. CleanUp:
  1787. if (WorldSid) {
  1788. FreeSid( WorldSid );
  1789. }
  1790. if (AdminsAliasSid) {
  1791. FreeSid( AdminsAliasSid );
  1792. }
  1793. if (CreatorOwnerSid) {
  1794. FreeSid( CreatorOwnerSid );
  1795. }
  1796. if (PrintOpsAliasSid) {
  1797. FreeSid( PrintOpsAliasSid );
  1798. }
  1799. if (SystemOpsAliasSid) {
  1800. FreeSid( SystemOpsAliasSid );
  1801. }
  1802. if (PowerUsersAliasSid) {
  1803. FreeSid( PowerUsersAliasSid );
  1804. }
  1805. return pDriversShareSD;
  1806. }
  1807. #if DBG
  1808. VOID
  1809. DumpAcl(
  1810. IN PACL Acl
  1811. )
  1812. /*++
  1813. Routine Description:
  1814. This routine dumps via (NetpDbgPrint) an Acl for debug purposes. It is
  1815. specialized to dump standard aces.
  1816. Arguments:
  1817. Acl - Supplies the Acl to dump
  1818. Return Value:
  1819. None
  1820. --*/
  1821. {
  1822. DWORD i;
  1823. PSTANDARD_ACE Ace;
  1824. if( MODULE_DEBUG & DBG_SECURITY ) {
  1825. DBGMSG( DBG_SECURITY, ( " DumpAcl @%08lx\n", Acl ));
  1826. //
  1827. // Check if the Acl is null
  1828. //
  1829. if (Acl == NULL) {
  1830. return;
  1831. }
  1832. //
  1833. // Dump the Acl header
  1834. //
  1835. DBGMSG( DBG_SECURITY,
  1836. ( " Revision: %02x, Size: %04x, AceCount: %04x\n",
  1837. Acl->AclRevision, Acl->AclSize, Acl->AceCount ));
  1838. //
  1839. // Now for each Ace we want do dump it
  1840. //
  1841. for (i = 0, Ace = FirstAce(Acl);
  1842. i < Acl->AceCount;
  1843. i++, Ace = NextAce(Ace) ) {
  1844. //
  1845. // print out the ace header
  1846. //
  1847. DBGMSG( DBG_SECURITY, ( " AceHeader: %08lx\n", *(PDWORD)Ace ));
  1848. //
  1849. // special case on the standard ace types
  1850. //
  1851. if ((Ace->Header.AceType == ACCESS_ALLOWED_ACE_TYPE) ||
  1852. (Ace->Header.AceType == ACCESS_DENIED_ACE_TYPE) ||
  1853. (Ace->Header.AceType == SYSTEM_AUDIT_ACE_TYPE) ||
  1854. (Ace->Header.AceType == SYSTEM_ALARM_ACE_TYPE)) {
  1855. //
  1856. // The following array is indexed by ace types and must
  1857. // follow the allowed, denied, audit, alarm seqeuence
  1858. //
  1859. static LPSTR AceTypes[] = { "Access Allowed",
  1860. "Access Denied ",
  1861. "System Audit ",
  1862. "System Alarm "
  1863. };
  1864. DBGMSG( DBG_SECURITY,
  1865. ( " %s Access Mask: %08lx\n",
  1866. AceTypes[Ace->Header.AceType], Ace->Mask ));
  1867. } else {
  1868. DBGMSG( DBG_SECURITY, (" Unknown Ace Type\n" ));
  1869. }
  1870. DBGMSG( DBG_SECURITY,
  1871. ( " AceSize = %d\n AceFlags = ", Ace->Header.AceSize ));
  1872. if (Ace->Header.AceFlags & OBJECT_INHERIT_ACE) {
  1873. DBGMSG( DBG_SECURITY, ( " OBJECT_INHERIT_ACE\n" ));
  1874. DBGMSG( DBG_SECURITY, ( " " ));
  1875. }
  1876. if (Ace->Header.AceFlags & CONTAINER_INHERIT_ACE) {
  1877. DBGMSG( DBG_SECURITY, ( " CONTAINER_INHERIT_ACE\n" ));
  1878. DBGMSG( DBG_SECURITY, ( " " ));
  1879. }
  1880. if (Ace->Header.AceFlags & NO_PROPAGATE_INHERIT_ACE) {
  1881. DBGMSG( DBG_SECURITY, ( " NO_PROPAGATE_INHERIT_ACE\n" ));
  1882. DBGMSG( DBG_SECURITY, ( " " ));
  1883. }
  1884. if (Ace->Header.AceFlags & INHERIT_ONLY_ACE) {
  1885. DBGMSG( DBG_SECURITY, ( " INHERIT_ONLY_ACE\n" ));
  1886. DBGMSG( DBG_SECURITY, ( " " ));
  1887. }
  1888. if (Ace->Header.AceFlags & SUCCESSFUL_ACCESS_ACE_FLAG) {
  1889. DBGMSG( DBG_SECURITY, ( " SUCCESSFUL_ACCESS_ACE_FLAG\n" ));
  1890. DBGMSG( DBG_SECURITY, ( " " ));
  1891. }
  1892. if (Ace->Header.AceFlags & FAILED_ACCESS_ACE_FLAG) {
  1893. DBGMSG( DBG_SECURITY, ( " FAILED_ACCESS_ACE_FLAG\n" ));
  1894. DBGMSG( DBG_SECURITY, ( " " ));
  1895. }
  1896. DBGMSG( DBG_SECURITY, ( "\n" ));
  1897. }
  1898. }
  1899. }
  1900. #endif // if DBG
  1901. /*++
  1902. Routine Name
  1903. BuildJobOwnerSecurityDescriptor
  1904. Routine Description:
  1905. This routine builds a SD that will be passed as CreatorDescriptor argument to
  1906. CreatePrivateObjectSecurityEx. The SD on any new job will be created using
  1907. the SD returned by this function and will inherit from the SD from the print
  1908. queue.
  1909. BuildJobOwnerSecurityDescriptor --> SD Print queue SD
  1910. \ /
  1911. \ / Inheritance
  1912. \ /
  1913. Job SD
  1914. The SD created in this function will have as owner the user from the
  1915. hToken argument. (The user impersonated by the thread from where we have the
  1916. hToken). The ACL grants full access on the job to the local system.
  1917. The reason why we need this special SD is the following. If you remove the
  1918. creatorowner from the print queue SD and no user has manage docs permissions
  1919. CreatePrivateObjectSecurity won't find any inheritable ACEs in the parent.
  1920. Thus it grants full permissions to the owner and to the local system. This
  1921. leads to a random behavior where according to the UI the user should not be
  1922. able to manage his docs, but the SD on the job will grant manage docs rights.
  1923. We don't want that. We want the local system to have full privileges on the job
  1924. and the user who submitted the job should be granted permissions only if:
  1925. - the user has manage doc rights
  1926. - creator owner is present in the print queue SD
  1927. Arguments:
  1928. hToken - impersonation token of the user who creates a new job
  1929. ppSD - pointer to recieve SD
  1930. Return Value:
  1931. Win32 error code
  1932. --*/
  1933. BOOL
  1934. BuildJobOwnerSecurityDescriptor(
  1935. IN HANDLE hToken,
  1936. OUT PSECURITY_DESCRIPTOR *ppSD
  1937. )
  1938. {
  1939. DWORD Error = ERROR_INVALID_PARAMETER;
  1940. if (hToken && ppSD)
  1941. {
  1942. PVOID pUserInfo = NULL;
  1943. DWORD cbUserInfo = 0;
  1944. //
  1945. // Get the owner from the thread token
  1946. //
  1947. Error = GetTokenInformation(hToken,
  1948. TokenUser,
  1949. NULL,
  1950. 0,
  1951. &cbUserInfo) ? ERROR_SUCCESS : GetLastError();
  1952. //
  1953. // Allocate buffer and try getting the owner again
  1954. //
  1955. if (Error == ERROR_INSUFFICIENT_BUFFER)
  1956. {
  1957. if (pUserInfo = AllocSplMem(cbUserInfo))
  1958. {
  1959. Error = GetTokenInformation(hToken,
  1960. TokenUser,
  1961. pUserInfo,
  1962. cbUserInfo,
  1963. &cbUserInfo) ? ERROR_SUCCESS : GetLastError();
  1964. //
  1965. // Build the SD. We grant read control to the owner of the job
  1966. //
  1967. if (Error == ERROR_SUCCESS)
  1968. {
  1969. DWORD ObjectType = SPOOLER_OBJECT_DOCUMENT;
  1970. PSID AceSid[2];
  1971. ACCESS_MASK AceMask[2];
  1972. BYTE InheritFlags[2];
  1973. UCHAR AceType[2];
  1974. DWORD AceCount = 0;
  1975. PSID pUserSid;
  1976. pUserSid = ((((TOKEN_USER *)pUserInfo)->User)).Sid;
  1977. AceType[AceCount] = ACCESS_ALLOWED_ACE_TYPE;
  1978. AceSid[AceCount] = ((((TOKEN_USER *)pUserInfo)->User)).Sid;
  1979. AceMask[AceCount] = JOB_READ;
  1980. InheritFlags[AceCount] = 0;
  1981. AceCount++;
  1982. AceType[AceCount] = ACCESS_ALLOWED_ACE_TYPE;
  1983. AceSid[AceCount] = pLocalSystemSid;
  1984. AceMask[AceCount] = JOB_ALL_ACCESS;
  1985. InheritFlags[AceCount] = 0;
  1986. AceCount++;
  1987. Error = BuildPrintObjectProtection(AceType,
  1988. AceCount,
  1989. AceSid,
  1990. AceMask,
  1991. InheritFlags,
  1992. pUserSid,
  1993. NULL,
  1994. &GenericMapping[ObjectType],
  1995. ppSD) ? ERROR_SUCCESS : GetLastError();
  1996. }
  1997. FreeSplMem(pUserInfo);
  1998. }
  1999. else
  2000. {
  2001. Error = GetLastError();
  2002. }
  2003. }
  2004. }
  2005. SetLastError(Error);
  2006. return Error == ERROR_SUCCESS;
  2007. }
  2008. /*++
  2009. Routine Name
  2010. DestroyJobOwnerSecurityDescriptor
  2011. Routine Description:
  2012. This routine frees a SD allocated by CreatejobOwnerSecurityDescriptor
  2013. Arguments:
  2014. pSD - pointer to SD
  2015. Return Value:
  2016. None
  2017. --*/
  2018. VOID
  2019. DestroyJobOwnerSecurityDescriptor(
  2020. IN PSECURITY_DESCRIPTOR pSD
  2021. )
  2022. {
  2023. if (pSD)
  2024. {
  2025. LocalFree(pSD);
  2026. }
  2027. }
  2028. /*++
  2029. Routine Name
  2030. InitializeSecurityStructures
  2031. Routine Description:
  2032. This routine initializes security structures.
  2033. Arguments:
  2034. None
  2035. Return Value:
  2036. TRUE - function succeeded
  2037. FALSE - function failed, GetLastError() returns the reason
  2038. --*/
  2039. BOOL
  2040. InitializeSecurityStructures(
  2041. VOID
  2042. )
  2043. {
  2044. SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
  2045. return !!CreateServerSecurityDescriptor() &&
  2046. LookupPrivilegeValue(NULL,
  2047. SE_LOAD_DRIVER_NAME,
  2048. &gLoadDriverPrivilegeLuid) &&
  2049. AllocateAndInitializeSid(&NtAuthority,
  2050. 1,
  2051. SECURITY_LOCAL_SYSTEM_RID,
  2052. 0, 0, 0, 0, 0, 0, 0,
  2053. &pLocalSystemSid) &&
  2054. AllocateAndInitializeSid(&NtAuthority,
  2055. 1,
  2056. SECURITY_NETWORK_RID,
  2057. 0, 0, 0, 0, 0, 0, 0,
  2058. &pNetworkLogonSid) &&
  2059. AllocateAndInitializeSid(&NtAuthority,
  2060. 2,
  2061. SECURITY_BUILTIN_DOMAIN_RID,
  2062. DOMAIN_ALIAS_RID_GUESTS,
  2063. 0, 0, 0, 0, 0, 0,
  2064. &pGuestsSid);
  2065. }
  2066. /*++
  2067. Routine Name
  2068. PrincipalIsRemoteGuest
  2069. Routine Description:
  2070. This routine checks whether remote guest is present in a token.
  2071. Remote guest = network + guest
  2072. Arguments:
  2073. hToken - handle to token, NULL is ok (see CheckTokenMemberShip)
  2074. pbRemoteGuest - pointer to receive BOOL. true means remote guest
  2075. Return Value:
  2076. ERROR_SUCCESS - pbRemoteGuest is reliable
  2077. other win32 error code, do not use pbRemoteGuest
  2078. --*/
  2079. DWORD
  2080. PrincipalIsRemoteGuest(
  2081. IN HANDLE hToken,
  2082. OUT BOOL *pbRemoteGuest
  2083. )
  2084. {
  2085. DWORD Error = ERROR_INVALID_PARAMETER;
  2086. if (pbRemoteGuest)
  2087. {
  2088. BOOL bNetwork = FALSE;
  2089. BOOL bGuests = FALSE;
  2090. if (CheckTokenMembership(hToken, pNetworkLogonSid, &bNetwork) &&
  2091. CheckTokenMembership(hToken, pGuestsSid, &bGuests))
  2092. {
  2093. *pbRemoteGuest = bNetwork && bGuests;
  2094. Error = ERROR_SUCCESS;
  2095. }
  2096. else
  2097. {
  2098. *pbRemoteGuest = FALSE;
  2099. Error = GetLastError();
  2100. }
  2101. }
  2102. return Error;
  2103. }
  2104. /*++
  2105. Routine Name
  2106. CheckPrivilegePresent
  2107. Routine Description:
  2108. This routine checks if a certain privilege is present in a token
  2109. Arguments:
  2110. hToken - thread or process token
  2111. pLuid - pointer to luid for the privilege to be searched for
  2112. pbPresent - will be set to true is the privilege is present in the token
  2113. pAttributes - will be set to the attributes of the privilege. It is a mask
  2114. indicating if the privilege is disabled, enabled, enabled by
  2115. default.
  2116. Return Value:
  2117. ERROR_SUCCESS - the function executed successfully and the caller can use
  2118. pbPresent and pAttributes
  2119. other Win32 error
  2120. --*/
  2121. DWORD
  2122. CheckPrivilegePresent(
  2123. IN HANDLE hToken,
  2124. IN PLUID pLuid,
  2125. IN LPBOOL pbPresent,
  2126. IN LPDWORD pAttributes OPTIONAL
  2127. )
  2128. {
  2129. DWORD Error = ERROR_INVALID_PARAMETER;
  2130. PVOID pPrivInfo = NULL;
  2131. DWORD cbPrivInfo = kGuessTokenPrivileges;
  2132. if (pLuid && pbPresent)
  2133. {
  2134. *pbPresent = FALSE;
  2135. pPrivInfo = AllocSplMem(cbPrivInfo);
  2136. Error = pPrivInfo ? ERROR_SUCCESS : GetLastError();
  2137. if (Error == ERROR_SUCCESS)
  2138. {
  2139. Error = GetTokenInformation(hToken,
  2140. TokenPrivileges,
  2141. pPrivInfo,
  2142. cbPrivInfo,
  2143. &cbPrivInfo) ? ERROR_SUCCESS : GetLastError();
  2144. }
  2145. //
  2146. // Reallocate buffer and try getting the privileges
  2147. //
  2148. if (Error == ERROR_INSUFFICIENT_BUFFER)
  2149. {
  2150. FreeSplMem(pPrivInfo);
  2151. pPrivInfo = AllocSplMem(cbPrivInfo);
  2152. Error = pPrivInfo ? ERROR_SUCCESS : GetLastError();
  2153. if (Error == ERROR_SUCCESS)
  2154. {
  2155. Error = GetTokenInformation(hToken,
  2156. TokenPrivileges,
  2157. pPrivInfo,
  2158. cbPrivInfo,
  2159. &cbPrivInfo) ? ERROR_SUCCESS : GetLastError();
  2160. }
  2161. }
  2162. if (Error == ERROR_SUCCESS)
  2163. {
  2164. TOKEN_PRIVILEGES *pTokenPrivileges = (TOKEN_PRIVILEGES *)pPrivInfo;
  2165. DWORD uCount;
  2166. //
  2167. // Search the privilege in the list of privileges present in the token
  2168. //
  2169. for (uCount = 0; uCount < pTokenPrivileges->PrivilegeCount; uCount++)
  2170. {
  2171. if (pTokenPrivileges->Privileges[uCount].Luid.HighPart == pLuid->HighPart &&
  2172. pTokenPrivileges->Privileges[uCount].Luid.LowPart == pLuid->LowPart)
  2173. {
  2174. //
  2175. // We found the privilege
  2176. //
  2177. *pbPresent = TRUE;
  2178. if (pAttributes)
  2179. {
  2180. *pAttributes = pTokenPrivileges->Privileges[uCount].Attributes;
  2181. }
  2182. break;
  2183. }
  2184. }
  2185. }
  2186. FreeSplMem(pPrivInfo);
  2187. }
  2188. return Error;
  2189. }
  2190. /*++
  2191. Routine Name
  2192. CreateSelfRelativeSD
  2193. Routine Description:
  2194. Creates a self relative SD. The function does not modifiy *pAbsoluteSD
  2195. Arguments:
  2196. pAbsoluteSD - pointer to SD in absolute form
  2197. ppRelativeSD - pointer where to receive a pointer to the SD in self relative form.
  2198. The caller needs to free the returned memory using LocalFree
  2199. Return Value:
  2200. ERROR_SUCCESS - *ppRelativeSD points to the SD in relative form. Must be freed with LocalFree
  2201. other Win32 error
  2202. --*/
  2203. DWORD
  2204. CreateSelfRelativeSD(
  2205. IN PSECURITY_DESCRIPTOR pAbsoluteSD,
  2206. OUT PSECURITY_DESCRIPTOR *ppRelativeSD
  2207. )
  2208. {
  2209. DWORD cbNeeded = 0;
  2210. DWORD Error = ERROR_SUCCESS;
  2211. *ppRelativeSD = NULL;
  2212. if (!MakeSelfRelativeSD(pAbsoluteSD, NULL, &cbNeeded) && (Error = GetLastError()) == ERROR_INSUFFICIENT_BUFFER)
  2213. {
  2214. PSECURITY_DESCRIPTOR pSelfRelativeSD = LocalAlloc(LMEM_FIXED, cbNeeded);
  2215. if (pSelfRelativeSD)
  2216. {
  2217. if (MakeSelfRelativeSD(pAbsoluteSD, pSelfRelativeSD, &cbNeeded))
  2218. {
  2219. *ppRelativeSD = pSelfRelativeSD;
  2220. pSelfRelativeSD = NULL;
  2221. Error = ERROR_SUCCESS;
  2222. }
  2223. else
  2224. {
  2225. Error = GetLastError();
  2226. }
  2227. LocalFree(pSelfRelativeSD);
  2228. }
  2229. else
  2230. {
  2231. Error = GetLastError();
  2232. }
  2233. }
  2234. return Error;
  2235. }
  2236. /*++
  2237. Routine Name
  2238. AddEntriesToSecurityDescriptor
  2239. Routine Description:
  2240. Adds ACEs to an existing SD. *ppSecurityDescriptor is assumed to be not null and valid.
  2241. Arguments:
  2242. cCountOfExplicitEntries - number of entries in array
  2243. pListOfExplicitEntries - array of EXPLICIT_ACCESS
  2244. ppSecurityDescriptor - on input, pointer to SD in self relative form, allocated with LocalAlloc
  2245. on output, pointer to SD in self relative form with added ACEs
  2246. Return Value:
  2247. ERROR_SUCCESS - the function freed the original *ppSecurityDescriptor and stored a pointer to
  2248. a SD equivalent to the original + added ACEs. Caller must free it with LocalFree
  2249. other Win32 error - *ppSecurityDescriptor is not modified
  2250. --*/
  2251. DWORD
  2252. AddEntriesToSecurityDescriptor(
  2253. IN ULONG cCountOfExplicitEntries,
  2254. IN PEXPLICIT_ACCESS pListOfExplicitEntries,
  2255. IN OUT PSECURITY_DESCRIPTOR *ppSecurityDescriptor
  2256. )
  2257. {
  2258. DWORD Error = ERROR_SUCCESS;
  2259. SECURITY_DESCRIPTOR AbsoluteSD = {0};
  2260. DWORD AbsoluteSDSize = sizeof(SECURITY_DESCRIPTOR);
  2261. PACL pDacl = NULL;
  2262. DWORD DaclSize = 0;
  2263. PACL pSacl = NULL;
  2264. DWORD SaclSize = 0;
  2265. PSID pOwner = NULL;
  2266. DWORD OwnerSize = 0;
  2267. PSID pGroup = NULL;
  2268. DWORD GroupSize = 0;
  2269. if (!MakeAbsoluteSD(*ppSecurityDescriptor,
  2270. &AbsoluteSD,
  2271. &AbsoluteSDSize,
  2272. pDacl,
  2273. &DaclSize,
  2274. pSacl,
  2275. &SaclSize,
  2276. pOwner,
  2277. &OwnerSize,
  2278. pGroup,
  2279. &GroupSize) && (Error = GetLastError()) == ERROR_INSUFFICIENT_BUFFER)
  2280. {
  2281. if (DaclSize == 0)
  2282. {
  2283. //
  2284. // Nothing to do, return the same SD back to the caller
  2285. //
  2286. Error = ERROR_SUCCESS;
  2287. }
  2288. else
  2289. {
  2290. if (!(pDacl = LocalAlloc(LMEM_FIXED, DaclSize)) ||
  2291. SaclSize > 0 && !(pSacl = LocalAlloc(LMEM_FIXED, SaclSize)) ||
  2292. OwnerSize > 0 && !(pOwner = LocalAlloc(LMEM_FIXED, OwnerSize)) ||
  2293. GroupSize > 0 && !(pGroup = LocalAlloc(LMEM_FIXED, GroupSize)))
  2294. {
  2295. Error = GetLastError();
  2296. }
  2297. else
  2298. {
  2299. if (MakeAbsoluteSD(*ppSecurityDescriptor,
  2300. &AbsoluteSD,
  2301. &AbsoluteSDSize,
  2302. pDacl,
  2303. &DaclSize,
  2304. pSacl,
  2305. &SaclSize,
  2306. pOwner,
  2307. &OwnerSize,
  2308. pGroup,
  2309. &GroupSize))
  2310. {
  2311. PACL pNewDacl = NULL;
  2312. if ((Error = SetEntriesInAcl(cCountOfExplicitEntries,
  2313. pListOfExplicitEntries,
  2314. pDacl,
  2315. &pNewDacl)) == ERROR_SUCCESS)
  2316. {
  2317. if (SetSecurityDescriptorDacl(&AbsoluteSD,
  2318. TRUE,
  2319. pNewDacl,
  2320. TRUE))
  2321. {
  2322. PSECURITY_DESCRIPTOR pTempSD = NULL;
  2323. if ((Error = CreateSelfRelativeSD(&AbsoluteSD, &pTempSD)) == ERROR_SUCCESS)
  2324. {
  2325. LocalFree(*ppSecurityDescriptor);
  2326. *ppSecurityDescriptor = pTempSD;
  2327. }
  2328. }
  2329. else
  2330. {
  2331. Error = GetLastError();
  2332. }
  2333. LocalFree(pNewDacl);
  2334. }
  2335. }
  2336. else
  2337. {
  2338. Error = GetLastError();
  2339. }
  2340. }
  2341. LocalFree(pDacl);
  2342. LocalFree(pSacl);
  2343. LocalFree(pOwner);
  2344. LocalFree(pGroup);
  2345. }
  2346. }
  2347. return Error;
  2348. }
  2349. /*++
  2350. Routine Name
  2351. GrantJobReadPermissionToLocalSystem
  2352. Routine Description:
  2353. Adds an ACE that grants job_read permission to local system on an existing SD
  2354. Arguments:
  2355. ppSecurityDescriptor - on input, pointer to SD in self relative form, allocated with LocalAlloc
  2356. on output, pointer to SD in self relative form with added ACE for local system
  2357. Return Value:
  2358. TRUE - the function freed the original *ppSecurityDescriptor and stored a pointer to
  2359. a SD equivalent to the original + added ACE. Caller must free it with LocalFree
  2360. FALSE - *ppSecurityDescriptor is not modified, use GetLastError
  2361. --*/
  2362. BOOL
  2363. GrantJobReadPermissionToLocalSystem(
  2364. IN OUT PSECURITY_DESCRIPTOR *ppSecurityDescriptor
  2365. )
  2366. {
  2367. DWORD Error;
  2368. EXPLICIT_ACCESS ExplicitAccess[1];
  2369. ExplicitAccess[0].grfAccessMode = GRANT_ACCESS;
  2370. ExplicitAccess[0].grfAccessPermissions = JOB_READ;
  2371. ExplicitAccess[0].grfInheritance = NO_INHERITANCE;
  2372. ExplicitAccess[0].Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
  2373. ExplicitAccess[0].Trustee.pMultipleTrustee = NULL;
  2374. ExplicitAccess[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
  2375. ExplicitAccess[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
  2376. ExplicitAccess[0].Trustee.ptstrName = pLocalSystemSid;
  2377. Error = AddEntriesToSecurityDescriptor(1, ExplicitAccess, ppSecurityDescriptor);
  2378. SetLastError(Error);
  2379. return Error == ERROR_SUCCESS;
  2380. }