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.

1120 lines
31 KiB

  1. /*++
  2. Copyright (c) 1997-1999 Microsoft Corporation
  3. Module Name:
  4. wmisecur.c
  5. Abstract:
  6. Wmi security tool
  7. Author:
  8. 16-Jan-1997 AlanWar
  9. Revision History:
  10. 5-20-2002 DamianH: Added new parameter so that the SD is printed
  11. in SDDL format (querysddl). Fix ChangePrivs so that the privilege
  12. is actually disabled.
  13. --*/
  14. #define INITGUID
  15. #include <nt.h>
  16. #include <ntrtl.h>
  17. #include <nturtl.h>
  18. #include <windows.h>
  19. #include <ole2.h>
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <aclapi.h>
  23. #include <sddl.h> // For ConvertSecurityDescriptorToStringSecurityDescriptor
  24. #include <tchar.h> // For TCHAR
  25. #include "wmium.h"
  26. #include "wmiumkm.h"
  27. void EditGuidSecurity(
  28. LPTSTR GuidString,
  29. LPGUID Guid
  30. );
  31. #define SE_WMIGUID_OBJECT 11
  32. #define WMI_SECURITY_REGSTR "SYSTEM\\CurrentControlSet\\Control\\WMI\\Security"
  33. #define WmipAllocEvent() CreateEvent(NULL, FALSE, FALSE, NULL)
  34. #define WmipFreeEvent(EventHandle) CloseHandle(EventHandle)
  35. HANDLE WmipKMHandle;
  36. ULONG PrintSecurityString(LPSTR Guid, BOOL fPrintSDDL);
  37. ULONG ChangePrivs(
  38. BOOLEAN Enable
  39. )
  40. {
  41. HANDLE Token;
  42. PTOKEN_PRIVILEGES NewPrivileges;
  43. PBYTE pbOldPriv;
  44. BYTE OldPriv[2048];
  45. ULONG cbNeeded;
  46. LUID LuidPrivilege;
  47. ULONG Status;
  48. if (OpenProcessToken( GetCurrentProcess(),
  49. TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  50. &Token))
  51. {
  52. cbNeeded = 0;
  53. //
  54. // Initialize the privilege adjustment structure
  55. //
  56. LookupPrivilegeValue( NULL, SE_SECURITY_NAME, &LuidPrivilege );
  57. NewPrivileges = (PTOKEN_PRIVILEGES)malloc( sizeof(TOKEN_PRIVILEGES) +
  58. sizeof(LUID_AND_ATTRIBUTES)
  59. );
  60. if (NewPrivileges != NULL)
  61. {
  62. NewPrivileges->PrivilegeCount = 1;
  63. NewPrivileges->Privileges[0].Luid = LuidPrivilege;
  64. NewPrivileges->Privileges[0].Attributes = Enable ?
  65. SE_PRIVILEGE_ENABLED : 0;
  66. //
  67. // Enable the privilege
  68. //
  69. pbOldPriv = OldPriv;
  70. if (AdjustTokenPrivileges( Token,
  71. FALSE,
  72. NewPrivileges,
  73. sizeof( OldPriv ),
  74. (PTOKEN_PRIVILEGES)pbOldPriv,
  75. &cbNeeded
  76. ))
  77. {
  78. CloseHandle(Token);
  79. if (OpenProcessToken( GetCurrentProcess(),
  80. TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  81. &Token))
  82. {
  83. printf("token is %p\n", Token);
  84. }
  85. Status = ERROR_SUCCESS;
  86. } else {
  87. Status = GetLastError();
  88. free( NewPrivileges );
  89. NewPrivileges = NULL;
  90. }
  91. } else {
  92. Status = ERROR_NOT_ENOUGH_MEMORY;
  93. }
  94. CloseHandle( Token );
  95. } else {
  96. Status = GetLastError();
  97. }
  98. return(Status);
  99. }
  100. ULONG WmipSendWmiKMRequest(
  101. ULONG Ioctl,
  102. PVOID Buffer,
  103. ULONG InBufferSize,
  104. ULONG MaxBufferSize,
  105. ULONG *ReturnSize
  106. )
  107. /*+++
  108. Routine Description:
  109. This routine does the work of sending WMI requests to the WMI kernel
  110. mode device. Any retry errors returned by the WMI device are handled
  111. in this routine.
  112. Arguments:
  113. Ioctl is the IOCTL code to send to the WMI device
  114. Buffer is the input and output buffer for the call to the WMI device
  115. InBufferSize is the size of the buffer passed to the device
  116. MaxBufferSize is the maximum number of bytes that can be written
  117. into the buffer
  118. *ReturnSize on return has the actual number of bytes written in buffer
  119. Return Value:
  120. ERROR_SUCCESS or an error code
  121. ---*/
  122. {
  123. OVERLAPPED Overlapped;
  124. ULONG Status;
  125. BOOL IoctlSuccess;
  126. if (WmipKMHandle == NULL)
  127. {
  128. //
  129. // If device is not open for then open it now. The
  130. // handle is closed in the process detach dll callout (DlllMain)
  131. WmipKMHandle = CreateFile(WMIDataDeviceName,
  132. GENERIC_READ | GENERIC_WRITE,
  133. 0,
  134. NULL,
  135. OPEN_EXISTING,
  136. FILE_ATTRIBUTE_NORMAL |
  137. FILE_FLAG_OVERLAPPED,
  138. NULL);
  139. if (WmipKMHandle == (HANDLE)-1)
  140. {
  141. WmipKMHandle = NULL;
  142. return(GetLastError());
  143. }
  144. }
  145. Overlapped.hEvent = WmipAllocEvent();
  146. if (Overlapped.hEvent == NULL)
  147. {
  148. return(ERROR_NOT_ENOUGH_MEMORY);
  149. }
  150. do
  151. {
  152. IoctlSuccess = DeviceIoControl(WmipKMHandle,
  153. Ioctl,
  154. Buffer,
  155. InBufferSize,
  156. Buffer,
  157. MaxBufferSize,
  158. ReturnSize,
  159. &Overlapped);
  160. if (GetLastError() == ERROR_IO_PENDING)
  161. {
  162. IoctlSuccess = GetOverlappedResult(WmipKMHandle,
  163. &Overlapped,
  164. ReturnSize,
  165. TRUE);
  166. }
  167. if (! IoctlSuccess)
  168. {
  169. Status = GetLastError();
  170. } else {
  171. Status = ERROR_SUCCESS;
  172. }
  173. } while (Status == ERROR_WMI_TRY_AGAIN);
  174. WmipFreeEvent(Overlapped.hEvent);
  175. return(Status);
  176. }
  177. #ifdef SET_SECURITY_BY_HANDLE
  178. ULONG WmipOpenKernelGuid(
  179. LPGUID Guid,
  180. ACCESS_MASK DesiredAccess,
  181. PHANDLE Handle
  182. )
  183. {
  184. WMIOPENGUIDBLOCK WmiOpenGuidBlock;
  185. ULONG ReturnSize;
  186. ULONG Status;
  187. WmiOpenGuidBlock.Guid = *Guid;
  188. WmiOpenGuidBlock.DesiredAccess = DesiredAccess;
  189. Status = WmipSendWmiKMRequest(IOCTL_WMI_OPEN_GUID,
  190. (PVOID)&WmiOpenGuidBlock,
  191. sizeof(WMIOPENGUIDBLOCK),
  192. sizeof(WMIOPENGUIDBLOCK),
  193. &ReturnSize);
  194. if (Status == ERROR_SUCCESS)
  195. {
  196. *Handle = WmiOpenGuidBlock.Handle;
  197. } else {
  198. *Handle = NULL;
  199. }
  200. return(Status);
  201. }
  202. #endif
  203. ULONG SetWmiGuidSecurityInfo(
  204. LPGUID Guid,
  205. SECURITY_INFORMATION SecurityInformation,
  206. PSID OwnerSid,
  207. PSID GroupSid,
  208. PACL Dacl,
  209. PACL Sacl
  210. )
  211. {
  212. HANDLE Handle;
  213. ULONG Status;
  214. #ifdef SET_SECURITY_BY_HANDLE
  215. Status = WmipOpenKernelGuid(Guid,
  216. WRITE_DAC | WRITE_OWNER,
  217. &Handle);
  218. if (Status == ERROR_SUCCESS)
  219. {
  220. Status = SetSecurityInfo(Handle,
  221. SE_KERNEL_OBJECT,
  222. SecurityInformation,
  223. OwnerSid,
  224. GroupSid,
  225. Dacl,
  226. Sacl);
  227. CloseHandle(Handle);
  228. }
  229. #else
  230. PCHAR GuidName;
  231. Status = UuidToString(Guid,
  232. &GuidName);
  233. if (Status == ERROR_SUCCESS)
  234. {
  235. Status = SetNamedSecurityInfo(GuidName,
  236. SE_WMIGUID_OBJECT,
  237. SecurityInformation,
  238. OwnerSid,
  239. GroupSid,
  240. Dacl,
  241. Sacl);
  242. RpcStringFree(&GuidName);
  243. }
  244. #endif
  245. return(Status);
  246. }
  247. ULONG GetWmiGuidSecurityInfo(
  248. LPGUID Guid,
  249. SECURITY_INFORMATION SecurityInformation,
  250. PSID *OwnerSid,
  251. PSID *GroupSid,
  252. PACL *Dacl,
  253. PACL *Sacl,
  254. PSECURITY_DESCRIPTOR *Sd
  255. )
  256. {
  257. HANDLE Handle;
  258. ULONG Status;
  259. #ifdef SET_SECURITY_BY_HANDLE
  260. Status = WmipOpenKernelGuid(Guid,
  261. READ_CONTROL,
  262. &Handle);
  263. if (Status == ERROR_SUCCESS)
  264. {
  265. Status = GetSecurityInfo(Handle,
  266. SE_KERNEL_OBJECT,
  267. SecurityInformation,
  268. OwnerSid,
  269. GroupSid,
  270. Dacl,
  271. Sacl,
  272. Sd);
  273. CloseHandle(Handle);
  274. }
  275. #else
  276. PCHAR GuidName;
  277. Status = UuidToString(Guid,
  278. &GuidName);
  279. if (Status == ERROR_SUCCESS)
  280. {
  281. Status = GetNamedSecurityInfo(GuidName,
  282. SE_WMIGUID_OBJECT,
  283. SecurityInformation,
  284. OwnerSid,
  285. GroupSid,
  286. Dacl,
  287. Sacl,
  288. Sd);
  289. RpcStringFree(&GuidName);
  290. }
  291. #endif
  292. return(Status);
  293. }
  294. //
  295. // The routines below were blantenly stolen without remorse from the ole
  296. // sources in \nt\private\ole32\com\class\compapi.cxx. They are copied here
  297. // so that WMI doesn't need to load in ole32 only to convert a guid string
  298. // into its binary representation.
  299. //
  300. //+-------------------------------------------------------------------------
  301. //
  302. // Function: HexStringToDword (private)
  303. //
  304. // Synopsis: scan lpsz for a number of hex digits (at most 8); update lpsz
  305. // return value in Value; check for chDelim;
  306. //
  307. // Arguments: [lpsz] - the hex string to convert
  308. // [Value] - the returned value
  309. // [cDigits] - count of digits
  310. //
  311. // Returns: TRUE for success
  312. //
  313. //--------------------------------------------------------------------------
  314. BOOL HexStringToDword(LPCSTR lpsz, DWORD * RetValue,
  315. int cDigits, WCHAR chDelim)
  316. {
  317. int Count;
  318. DWORD Value;
  319. Value = 0;
  320. for (Count = 0; Count < cDigits; Count++, lpsz++)
  321. {
  322. if (*lpsz >= '0' && *lpsz <= '9')
  323. Value = (Value << 4) + *lpsz - '0';
  324. else if (*lpsz >= 'A' && *lpsz <= 'F')
  325. Value = (Value << 4) + *lpsz - 'A' + 10;
  326. else if (*lpsz >= 'a' && *lpsz <= 'f')
  327. Value = (Value << 4) + *lpsz - 'a' + 10;
  328. else
  329. return(FALSE);
  330. }
  331. *RetValue = Value;
  332. if (chDelim != 0)
  333. return *lpsz++ == chDelim;
  334. else
  335. return TRUE;
  336. }
  337. //+-------------------------------------------------------------------------
  338. //
  339. // Function: wUUIDFromString (internal)
  340. //
  341. // Synopsis: Parse UUID such as 00000000-0000-0000-0000-000000000000
  342. //
  343. // Arguments: [lpsz] - Supplies the UUID string to convert
  344. // [pguid] - Returns the GUID.
  345. //
  346. // Returns: TRUE if successful
  347. //
  348. //--------------------------------------------------------------------------
  349. BOOL wUUIDFromString(LPCSTR lpsz, LPGUID pguid)
  350. {
  351. DWORD dw;
  352. if (!HexStringToDword(lpsz, &pguid->Data1, sizeof(DWORD)*2, '-'))
  353. return FALSE;
  354. lpsz += sizeof(DWORD)*2 + 1;
  355. if (!HexStringToDword(lpsz, &dw, sizeof(WORD)*2, '-'))
  356. return FALSE;
  357. lpsz += sizeof(WORD)*2 + 1;
  358. pguid->Data2 = (WORD)dw;
  359. if (!HexStringToDword(lpsz, &dw, sizeof(WORD)*2, '-'))
  360. return FALSE;
  361. lpsz += sizeof(WORD)*2 + 1;
  362. pguid->Data3 = (WORD)dw;
  363. if (!HexStringToDword(lpsz, &dw, sizeof(BYTE)*2, 0))
  364. return FALSE;
  365. lpsz += sizeof(BYTE)*2;
  366. pguid->Data4[0] = (BYTE)dw;
  367. if (!HexStringToDword(lpsz, &dw, sizeof(BYTE)*2, '-'))
  368. return FALSE;
  369. lpsz += sizeof(BYTE)*2+1;
  370. pguid->Data4[1] = (BYTE)dw;
  371. if (!HexStringToDword(lpsz, &dw, sizeof(BYTE)*2, 0))
  372. return FALSE;
  373. lpsz += sizeof(BYTE)*2;
  374. pguid->Data4[2] = (BYTE)dw;
  375. if (!HexStringToDword(lpsz, &dw, sizeof(BYTE)*2, 0))
  376. return FALSE;
  377. lpsz += sizeof(BYTE)*2;
  378. pguid->Data4[3] = (BYTE)dw;
  379. if (!HexStringToDword(lpsz, &dw, sizeof(BYTE)*2, 0))
  380. return FALSE;
  381. lpsz += sizeof(BYTE)*2;
  382. pguid->Data4[4] = (BYTE)dw;
  383. if (!HexStringToDword(lpsz, &dw, sizeof(BYTE)*2, 0))
  384. return FALSE;
  385. lpsz += sizeof(BYTE)*2;
  386. pguid->Data4[5] = (BYTE)dw;
  387. if (!HexStringToDword(lpsz, &dw, sizeof(BYTE)*2, 0))
  388. return FALSE;
  389. lpsz += sizeof(BYTE)*2;
  390. pguid->Data4[6] = (BYTE)dw;
  391. if (!HexStringToDword(lpsz, &dw, sizeof(BYTE)*2, 0))
  392. return FALSE;
  393. lpsz += sizeof(BYTE)*2;
  394. pguid->Data4[7] = (BYTE)dw;
  395. return TRUE;
  396. }
  397. //+-------------------------------------------------------------------------
  398. //
  399. // Function: wGUIDFromString (internal)
  400. //
  401. // Synopsis: Parse GUID such as {00000000-0000-0000-0000-000000000000}
  402. //
  403. // Arguments: [lpsz] - the guid string to convert
  404. // [pguid] - guid to return
  405. //
  406. // Returns: TRUE if successful
  407. //
  408. //--------------------------------------------------------------------------
  409. BOOL wGUIDFromString(LPCSTR lpsz, LPGUID pguid)
  410. {
  411. DWORD dw;
  412. if (*lpsz == '{' )
  413. lpsz++;
  414. if(wUUIDFromString(lpsz, pguid) != TRUE)
  415. return FALSE;
  416. lpsz +=36;
  417. if (*lpsz == '}' )
  418. lpsz++;
  419. if (*lpsz != '\0') // check for zero terminated string - test bug #18307
  420. {
  421. return FALSE;
  422. }
  423. return TRUE;
  424. }
  425. ULONG RemoveWmiSD(
  426. LPGUID Guid
  427. )
  428. {
  429. CHAR GuidName[MAX_PATH];
  430. HKEY RegistryKey;
  431. ULONG Status;
  432. Status = RegOpenKey(HKEY_LOCAL_MACHINE,
  433. "System\\CurrentControlSet\\Control\\Wmi\\Security",
  434. &RegistryKey);
  435. if (Status != ERROR_SUCCESS)
  436. {
  437. printf("RegOpenKey returned %d\n", Status);
  438. return(Status);
  439. }
  440. if (Guid != NULL)
  441. {
  442. wsprintf(GuidName, "%08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x",
  443. Guid->Data1, Guid->Data2,
  444. Guid->Data3,
  445. Guid->Data4[0], Guid->Data4[1],
  446. Guid->Data4[2], Guid->Data4[3],
  447. Guid->Data4[4], Guid->Data4[5],
  448. Guid->Data4[6], Guid->Data4[7]);
  449. } else {
  450. strcpy(GuidName, "00000000-0000-0000-0000000000000000");
  451. }
  452. RegDeleteValue(RegistryKey,
  453. GuidName);
  454. RegCloseKey(RegistryKey);
  455. return(ERROR_SUCCESS);
  456. }
  457. void Usage(
  458. void
  459. )
  460. {
  461. printf("wmisecur <guid> [query | querysddl | edit | owner | group | dacl | adacl] [parameters]\n");
  462. printf(" wmisecur <guid> query\n");
  463. printf(" queries and prints the security string appropriate for inclusion in INF file\n\n");
  464. printf(" wmisecur <guid> querysddl\n");
  465. printf(" queries and prints the security string as SDDL\n\n");
  466. printf(" wmisecur <guid> querysddl\n");
  467. printf(" queries and prints the security descriptor in SDDL format\n\n");
  468. printf(" wmisecur <guid> edit\n");
  469. printf(" opens a security descriptor property sheet for editing the DACL of the guid\n\n");
  470. printf(" wmisecur <guid> owner <account name>\n");
  471. printf(" sets owner of guid to be <account name>\n\n");
  472. printf(" wmisecur <guid> group <account name>\n");
  473. printf(" sets group of guid to be <account name>\n\n");
  474. printf(" wmisecur <guid> dacl <account name> [allow | deny] <right1> <right2> ....\n");
  475. printf(" resets dacl to assign <right1>, <right2>, ... to <account name>\n\n");
  476. printf(" wmisecur <guid> adacl <account name> [allow | deny] <right1> <right2> ....\n");
  477. printf(" appends ace to dacl,<right1>, <right2>, ... assigned to <account name>\n\n");
  478. printf(" Rights: WMIGUID_QUERY\n");
  479. printf(" WMIGUID_SET\n");
  480. printf(" WMIGUID_NOTIFICATION\n");
  481. printf(" WMIGUID_READ_DESCRIPTION\n");
  482. printf(" WMIGUID_EXECUTE\n");
  483. printf(" TRACELOG_CREATE_REALTIME\n");
  484. printf(" TRACELOG_CREATE_ONDISK\n");
  485. printf(" TRACELOG_GUID_ENABLE\n");
  486. printf(" TRACELOG_ACCESS_KERNEL_LOGGER\n");
  487. printf(" TRACELOG_CREATE_INPROC\n");
  488. printf(" TRACELOG_ACCESS_REALTIME\n");
  489. printf(" READ_CONTROL\n");
  490. printf(" WRITE_DAC\n");
  491. printf(" WRITE_OWNER\n");
  492. printf(" DELETE\n");
  493. printf(" SYNCHRONIZE\n");
  494. printf(" ALL (all wmi specific rights)\n");
  495. printf(" ALLRIGHTS (STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL)\n");
  496. printf(" Examples:\n");
  497. printf(" wmisecur 78ebc105-4cf9-11d2-ba4a-00a0c9062910 edit\n\n");
  498. printf(" wmisecur 78ebc105-4cf9-11d2-ba4a-00a0c9062910 query\n");
  499. }
  500. typedef enum
  501. {
  502. SetOwner,
  503. SetGroup,
  504. ResetDacl,
  505. AppendDacl,
  506. CopyDacl,
  507. QueryGuid,
  508. EditGuid,
  509. ResetSACL,
  510. CopySACL,
  511. AppendSACL,
  512. QueryGuidSDDL
  513. } OPERATION;
  514. typedef enum
  515. {
  516. Allow,
  517. Deny
  518. } ALLOWORDENY;
  519. ULONG SetOwnerOrGroup(
  520. OPERATION Operation,
  521. LPGUID Guid,
  522. PSID Sid
  523. )
  524. {
  525. ULONG Status;
  526. if (Operation == SetOwner)
  527. {
  528. Status = SetWmiGuidSecurityInfo(Guid,
  529. OWNER_SECURITY_INFORMATION,
  530. Sid,
  531. NULL,
  532. NULL,
  533. NULL);
  534. } else {
  535. Status = SetWmiGuidSecurityInfo(Guid,
  536. GROUP_SECURITY_INFORMATION,
  537. NULL,
  538. Sid,
  539. NULL,
  540. NULL);
  541. }
  542. return(Status);
  543. }
  544. ULONG ResetOrAppendDacl(
  545. OPERATION Operation,
  546. LPGUID Guid,
  547. PSID Sid,
  548. ALLOWORDENY AllowOrDeny,
  549. ULONG Rights
  550. )
  551. {
  552. ULONG Status;
  553. PSECURITY_DESCRIPTOR OldSD;
  554. PACL OldDacl, NewDacl;
  555. UCHAR NewDaclBuffer[512];
  556. NewDacl = (PACL)NewDaclBuffer;
  557. if ((Operation == AppendDacl) || (Operation == CopyDacl))
  558. {
  559. Status = GetWmiGuidSecurityInfo(Guid,
  560. DACL_SECURITY_INFORMATION,
  561. NULL,
  562. NULL,
  563. &OldDacl,
  564. NULL,
  565. &OldSD);
  566. if (Status != ERROR_SUCCESS)
  567. {
  568. return(Status);
  569. }
  570. memcpy(NewDacl, OldDacl, OldDacl->AclSize);
  571. LocalFree(OldSD);
  572. NewDacl->AclSize = sizeof(NewDaclBuffer);
  573. } else {
  574. RtlCreateAcl(NewDacl,
  575. sizeof(NewDaclBuffer),
  576. ACL_REVISION);
  577. }
  578. if (Operation != CopyDacl)
  579. {
  580. if (AllowOrDeny == Deny)
  581. {
  582. if (! AddAccessDeniedAce(NewDacl,
  583. ACL_REVISION,
  584. Rights,
  585. Sid))
  586. {
  587. return(GetLastError());
  588. }
  589. } else {
  590. if (! AddAccessAllowedAce(NewDacl,
  591. ACL_REVISION,
  592. Rights,
  593. Sid))
  594. {
  595. return(GetLastError());
  596. }
  597. }
  598. }
  599. Status = SetWmiGuidSecurityInfo(Guid,
  600. DACL_SECURITY_INFORMATION,
  601. NULL,
  602. NULL,
  603. NewDacl,
  604. NULL);
  605. return(Status);
  606. }
  607. ULONG ResetOrAppendSacl(
  608. OPERATION Operation,
  609. LPGUID Guid,
  610. PSID Sid,
  611. ALLOWORDENY AllowOrDeny,
  612. ULONG Rights
  613. )
  614. {
  615. ULONG Status;
  616. PSECURITY_DESCRIPTOR OldSD;
  617. PACL OldDacl, NewDacl;
  618. UCHAR NewDaclBuffer[512];
  619. Status = ChangePrivs(TRUE);
  620. if (Status == ERROR_SUCCESS)
  621. {
  622. NewDacl = (PACL)NewDaclBuffer;
  623. if ((Operation == AppendSACL) || (Operation == CopySACL))
  624. {
  625. Status = GetWmiGuidSecurityInfo(Guid,
  626. SACL_SECURITY_INFORMATION,
  627. NULL,
  628. NULL,
  629. NULL,
  630. &OldDacl,
  631. &OldSD);
  632. if (Status != ERROR_SUCCESS)
  633. {
  634. return(Status);
  635. }
  636. memcpy(NewDacl, OldDacl, OldDacl->AclSize);
  637. LocalFree(OldSD);
  638. NewDacl->AclSize = sizeof(NewDaclBuffer);
  639. } else {
  640. RtlCreateAcl(NewDacl,
  641. sizeof(NewDaclBuffer),
  642. ACL_REVISION);
  643. }
  644. if (Operation != CopySACL)
  645. {
  646. if (AllowOrDeny == Deny)
  647. {
  648. if (! AddAccessDeniedAce(NewDacl,
  649. ACL_REVISION,
  650. Rights,
  651. Sid))
  652. {
  653. return(GetLastError());
  654. }
  655. } else {
  656. if (! AddAccessAllowedAce(NewDacl,
  657. ACL_REVISION,
  658. Rights,
  659. Sid))
  660. {
  661. return(GetLastError());
  662. }
  663. }
  664. }
  665. Status = SetWmiGuidSecurityInfo(Guid,
  666. SACL_SECURITY_INFORMATION,
  667. NULL,
  668. NULL,
  669. NULL,
  670. NewDacl);
  671. ChangePrivs(FALSE);
  672. }
  673. return(Status);
  674. }
  675. BOOLEAN RightNameToDWord(
  676. PCHAR RightName,
  677. PDWORD RightDWord
  678. )
  679. {
  680. *RightDWord = 0;
  681. if (_stricmp(RightName, "WMIGUID_QUERY") == 0)
  682. {
  683. *RightDWord = WMIGUID_QUERY;
  684. } else if (_stricmp(RightName, "WMIGUID_SET") == 0) {
  685. *RightDWord = WMIGUID_SET;
  686. } else if (_stricmp(RightName, "WMIGUID_NOTIFICATION") == 0) {
  687. *RightDWord = WMIGUID_NOTIFICATION;
  688. } else if (_stricmp(RightName, "WMIGUID_READ_DESCRIPTION") == 0) {
  689. *RightDWord = WMIGUID_READ_DESCRIPTION;
  690. } else if (_stricmp(RightName, "WMIGUID_EXECUTE") == 0) {
  691. *RightDWord = WMIGUID_EXECUTE;
  692. } else if (_stricmp(RightName, "TRACELOG_CREATE_REALTIME") == 0) {
  693. *RightDWord = TRACELOG_CREATE_REALTIME;
  694. } else if (_stricmp(RightName, "TRACELOG_CREATE_ONDISK") == 0) {
  695. *RightDWord = TRACELOG_CREATE_ONDISK;
  696. } else if (_stricmp(RightName, "TRACELOG_GUID_ENABLE") == 0) {
  697. *RightDWord = TRACELOG_GUID_ENABLE;
  698. } else if (_stricmp(RightName, "TRACELOG_ACCESS_KERNEL_LOGGER") == 0) {
  699. *RightDWord = TRACELOG_ACCESS_KERNEL_LOGGER;
  700. } else if (_stricmp(RightName, "TRACELOG_CREATE_INPROC") == 0) {
  701. *RightDWord = TRACELOG_CREATE_INPROC;
  702. } else if (_stricmp(RightName, "TRACELOG_ACCESS_REALTIME") == 0) {
  703. *RightDWord = TRACELOG_ACCESS_REALTIME;
  704. } else if (_stricmp(RightName, "READ_CONTROL") == 0) {
  705. *RightDWord = READ_CONTROL;
  706. } else if (_stricmp(RightName, "WRITE_DAC") == 0) {
  707. *RightDWord = WRITE_DAC;
  708. } else if (_stricmp(RightName, "WRITE_OWNER") == 0) {
  709. *RightDWord = WRITE_OWNER;
  710. } else if (_stricmp(RightName, "WRITE_DAC") == 0) {
  711. *RightDWord = WRITE_DAC;
  712. } else if (_stricmp(RightName, "DELETE") == 0) {
  713. *RightDWord = DELETE;
  714. } else if (_stricmp(RightName, "SYNCHRONIZE") == 0) {
  715. *RightDWord = SYNCHRONIZE;
  716. } else if (_stricmp(RightName, "ALL") == 0) {
  717. *RightDWord = WMIGUID_ALL_ACCESS;
  718. } else if (_stricmp(RightName, "ALLRIGHTS") == 0) {
  719. *RightDWord = STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL;
  720. } else {
  721. return(FALSE);
  722. }
  723. return(TRUE);
  724. }
  725. int __cdecl main(int argc, char *argv[])
  726. {
  727. int i;
  728. ALLOWORDENY AllowOrDeny;
  729. OPERATION Operation;
  730. DWORD Rights;
  731. DWORD NewRight;
  732. PSID Sid;
  733. UCHAR SidBuffer[512];
  734. ULONG SidLength;
  735. GUID Guid;
  736. CHAR ReferencedDomain[512];
  737. SID_NAME_USE SidNameUse;
  738. ULONG ReferencedDomainSize;
  739. ULONG Status;
  740. if (argc <= 2)
  741. {
  742. Usage();
  743. return(0);
  744. }
  745. if (_stricmp(argv[2], "owner") == 0)
  746. {
  747. Operation = SetOwner;
  748. } else if (_stricmp(argv[2], "group") == 0) {
  749. Operation = SetGroup;
  750. } else if (_stricmp(argv[2], "dacl") == 0) {
  751. Operation = ResetDacl;
  752. } else if (_stricmp(argv[2], "adacl") == 0) {
  753. Operation = AppendDacl;
  754. } else if (_stricmp(argv[2], "copy") == 0) {
  755. Operation = CopyDacl;
  756. } else if (_stricmp(argv[2], "query") == 0) {
  757. Operation = QueryGuid;
  758. } else if (_stricmp(argv[2], "edit") == 0) {
  759. Operation = EditGuid;
  760. } else if (_stricmp(argv[2], "sacl") == 0) {
  761. Operation = ResetSACL;
  762. } else if (_stricmp(argv[2], "asacl") == 0) {
  763. Operation = AppendSACL;
  764. } else if (_stricmp(argv[2], "csacl") == 0) {
  765. Operation = CopySACL;
  766. } else if (_stricmp(argv[2], "querysddl") == 0) {
  767. Operation = QueryGuidSDDL;
  768. } else {
  769. Usage();
  770. return(0);
  771. }
  772. //
  773. // Parse the guid parameter
  774. if (! wUUIDFromString(argv[1], &Guid))
  775. {
  776. printf("Bad guid %s\n", argv[1]);
  777. return(0);
  778. }
  779. if (Operation == EditGuid)
  780. {
  781. Status = ChangePrivs(TRUE);
  782. if (Status == ERROR_SUCCESS)
  783. {
  784. EditGuidSecurity(argv[1], &Guid);
  785. }
  786. ChangePrivs(FALSE);
  787. return(0);
  788. }
  789. if (Operation == QueryGuid)
  790. {
  791. if (PrintSecurityString(argv[1],FALSE))
  792. printf("Cannot find security set for given guid\n");
  793. return 0;
  794. }
  795. if (Operation == QueryGuidSDDL)
  796. {
  797. DWORD dwErr=ERROR_SUCCESS;
  798. dwErr=PrintSecurityString(argv[1],TRUE);
  799. if (ERROR_SUCCESS!=dwErr) {
  800. printf("Cannot find security set for given guid (error: 0x%08X )\n",
  801. dwErr);
  802. }
  803. return 0;
  804. }
  805. if (Operation == CopyDacl)
  806. {
  807. Status = ResetOrAppendDacl(Operation, &Guid, NULL, Allow, 0);
  808. printf("Status is %d\n", Status);
  809. return(Status);
  810. }
  811. if (Operation == CopySACL)
  812. {
  813. Status = ResetOrAppendSacl(Operation, &Guid, NULL, Allow, 0);
  814. printf("Status is %d\n", Status);
  815. return(Status);
  816. }
  817. if (_stricmp(argv[3], "LocalSystem") == 0)
  818. {
  819. //
  820. // This is a special SID we need to build by hand
  821. //
  822. //
  823. // Create SID for LocalSystem dynamically
  824. //
  825. Sid = (PSID)malloc(RtlLengthRequiredSid( 1 ));
  826. if (Sid != NULL)
  827. {
  828. SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
  829. RtlInitializeSid( Sid, &NtAuthority, 1);
  830. *(RtlSubAuthoritySid( Sid, 0 )) = SECURITY_LOCAL_SYSTEM_RID;
  831. } else {
  832. printf("Not enougfh memory for local system sid\n");
  833. return(ERROR_NOT_ENOUGH_MEMORY);
  834. }
  835. } else {
  836. //
  837. // Parse the account name parameter
  838. Sid = (PSID)SidBuffer;
  839. SidLength = sizeof(SidBuffer);
  840. ReferencedDomainSize = sizeof(ReferencedDomain);
  841. if (! LookupAccountName(NULL,
  842. argv[3],
  843. Sid,
  844. &SidLength,
  845. ReferencedDomain,
  846. &ReferencedDomainSize,
  847. &SidNameUse))
  848. {
  849. printf("Error %d looking up account %s\n", GetLastError(), argv[3]);
  850. return(0);
  851. }
  852. }
  853. if ((Operation == SetOwner) ||
  854. (Operation == SetGroup))
  855. {
  856. Status = SetOwnerOrGroup(Operation, &Guid, Sid);
  857. printf("Status is %d\n", Status);
  858. if (Status == 0) {
  859. PrintSecurityString(argv[1],FALSE);
  860. }
  861. } else {
  862. if (argc < 4)
  863. {
  864. Usage();
  865. return(0);
  866. }
  867. if (_stricmp(argv[4], "allow") == 0)
  868. {
  869. AllowOrDeny = Allow;
  870. } else if (_stricmp(argv[4], "deny") == 0) {
  871. AllowOrDeny = Deny;
  872. } else {
  873. Usage();
  874. return(0);
  875. }
  876. Rights = 0;
  877. for (i = 5; i < argc; i++)
  878. {
  879. if (! RightNameToDWord(argv[i], &NewRight))
  880. {
  881. printf("Invalid right %s\n", argv[i]);
  882. return(0);
  883. }
  884. Rights |= NewRight;
  885. }
  886. if ((Operation == AppendDacl) || (Operation == ResetDacl))
  887. {
  888. Status = ResetOrAppendDacl(Operation, &Guid, Sid, AllowOrDeny, Rights);
  889. } else {
  890. Status = ResetOrAppendSacl(Operation, &Guid, Sid, AllowOrDeny, Rights);
  891. }
  892. printf("Status is %d\n", Status);
  893. if (Status == 0) {
  894. PrintSecurityString(argv[1],FALSE);
  895. }
  896. }
  897. }
  898. ULONG
  899. PrintSecurityString(LPSTR GuidStr, BOOL fPrintSDDL)
  900. {
  901. ULONG status;
  902. HKEY hKey;
  903. UCHAR buffer[1024]={0};
  904. ULONG size, i;
  905. LPTSTR pszSD=NULL;
  906. status = RegOpenKeyEx(
  907. HKEY_LOCAL_MACHINE,
  908. WMI_SECURITY_REGSTR,
  909. 0L,
  910. KEY_QUERY_VALUE,
  911. &hKey);
  912. if (status != ERROR_SUCCESS)
  913. return status;
  914. size = 1024;
  915. status = RegQueryValueEx(
  916. hKey,
  917. GuidStr,
  918. NULL,
  919. NULL,
  920. buffer,
  921. &size);
  922. if (status != ERROR_SUCCESS) {
  923. RegCloseKey(hKey);
  924. return status;
  925. }
  926. printf("\nHKLM,\"%s\",\"%s\",0x00030003,\\\n",
  927. WMI_SECURITY_REGSTR, GuidStr);
  928. if (!fPrintSDDL) {
  929. for (i=0; i<size; i++) {
  930. if ((i%16) == 0) {
  931. if (i>0)
  932. printf(",\\\n");
  933. printf(" ");
  934. printf("%02x", buffer[i]);
  935. }
  936. else
  937. printf(",%02x", buffer[i]);
  938. }
  939. printf("\n");
  940. }
  941. else {
  942. if (ConvertSecurityDescriptorToStringSecurityDescriptor(
  943. (PSECURITY_DESCRIPTOR)buffer,
  944. SDDL_REVISION_1,
  945. OWNER_SECURITY_INFORMATION |
  946. GROUP_SECURITY_INFORMATION |
  947. DACL_SECURITY_INFORMATION |
  948. SACL_SECURITY_INFORMATION,
  949. &pszSD,
  950. NULL)) {
  951. _tprintf(_T("SD: %s"),
  952. pszSD);
  953. LocalFree(pszSD);
  954. }
  955. else {
  956. _tprintf(_T("ConvertSecurityDescriptorToStringSecurityDescriptor failed (%d)"),
  957. GetLastError());
  958. return GetLastError();
  959. }
  960. }
  961. RegCloseKey(hKey);
  962. return ERROR_SUCCESS;
  963. }