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.

868 lines
25 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. --*/
  11. #define INITGUID
  12. #include <nt.h>
  13. #include <ntrtl.h>
  14. #include <nturtl.h>
  15. #include <windows.h>
  16. #include <ole2.h>
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <aclapi.h>
  20. #include "wmium.h"
  21. #include "wmiumkm.h"
  22. #define SE_WMIGUID_OBJECT 11
  23. #define WMI_SECURITY_REGSTR "SYSTEM\\CurrentControlSet\\Control\\WMI\\Security"
  24. #define WmipAllocEvent() CreateEvent(NULL, FALSE, FALSE, NULL)
  25. #define WmipFreeEvent(EventHandle) CloseHandle(EventHandle)
  26. HANDLE WmipKMHandle;
  27. ULONG PrintSecurityString(LPSTR Guid);
  28. ULONG WmipSendWmiKMRequest(
  29. ULONG Ioctl,
  30. PVOID Buffer,
  31. ULONG InBufferSize,
  32. ULONG MaxBufferSize,
  33. ULONG *ReturnSize
  34. )
  35. /*+++
  36. Routine Description:
  37. This routine does the work of sending WMI requests to the WMI kernel
  38. mode device. Any retry errors returned by the WMI device are handled
  39. in this routine.
  40. Arguments:
  41. Ioctl is the IOCTL code to send to the WMI device
  42. Buffer is the input and output buffer for the call to the WMI device
  43. InBufferSize is the size of the buffer passed to the device
  44. MaxBufferSize is the maximum number of bytes that can be written
  45. into the buffer
  46. *ReturnSize on return has the actual number of bytes written in buffer
  47. Return Value:
  48. ERROR_SUCCESS or an error code
  49. ---*/
  50. {
  51. OVERLAPPED Overlapped;
  52. ULONG Status;
  53. BOOL IoctlSuccess;
  54. if (WmipKMHandle == NULL)
  55. {
  56. //
  57. // If device is not open for then open it now. The
  58. // handle is closed in the process detach dll callout (DlllMain)
  59. WmipKMHandle = CreateFile(WMIDataDeviceName,
  60. GENERIC_READ | GENERIC_WRITE,
  61. 0,
  62. NULL,
  63. OPEN_EXISTING,
  64. FILE_ATTRIBUTE_NORMAL |
  65. FILE_FLAG_OVERLAPPED,
  66. NULL);
  67. if (WmipKMHandle == (HANDLE)-1)
  68. {
  69. WmipKMHandle = NULL;
  70. return(GetLastError());
  71. }
  72. }
  73. Overlapped.hEvent = WmipAllocEvent();
  74. if (Overlapped.hEvent == NULL)
  75. {
  76. return(ERROR_NOT_ENOUGH_MEMORY);
  77. }
  78. do
  79. {
  80. IoctlSuccess = DeviceIoControl(WmipKMHandle,
  81. Ioctl,
  82. Buffer,
  83. InBufferSize,
  84. Buffer,
  85. MaxBufferSize,
  86. ReturnSize,
  87. &Overlapped);
  88. if (GetLastError() == ERROR_IO_PENDING)
  89. {
  90. IoctlSuccess = GetOverlappedResult(WmipKMHandle,
  91. &Overlapped,
  92. ReturnSize,
  93. TRUE);
  94. }
  95. if (! IoctlSuccess)
  96. {
  97. Status = GetLastError();
  98. } else {
  99. Status = ERROR_SUCCESS;
  100. }
  101. } while (Status == ERROR_WMI_TRY_AGAIN);
  102. WmipFreeEvent(Overlapped.hEvent);
  103. return(Status);
  104. }
  105. #ifdef SET_SECURITY_BY_HANDLE
  106. ULONG WmipOpenKernelGuid(
  107. LPGUID Guid,
  108. ACCESS_MASK DesiredAccess,
  109. PHANDLE Handle
  110. )
  111. {
  112. WMIOPENGUIDBLOCK WmiOpenGuidBlock;
  113. ULONG ReturnSize;
  114. ULONG Status;
  115. WmiOpenGuidBlock.Guid = *Guid;
  116. WmiOpenGuidBlock.DesiredAccess = DesiredAccess;
  117. Status = WmipSendWmiKMRequest(IOCTL_WMI_OPEN_GUID,
  118. (PVOID)&WmiOpenGuidBlock,
  119. sizeof(WMIOPENGUIDBLOCK),
  120. sizeof(WMIOPENGUIDBLOCK),
  121. &ReturnSize);
  122. if (Status == ERROR_SUCCESS)
  123. {
  124. *Handle = WmiOpenGuidBlock.Handle;
  125. } else {
  126. *Handle = NULL;
  127. }
  128. return(Status);
  129. }
  130. #endif
  131. ULONG SetWmiGuidSecurityInfo(
  132. LPGUID Guid,
  133. SECURITY_INFORMATION SecurityInformation,
  134. PSID OwnerSid,
  135. PSID GroupSid,
  136. PACL Dacl,
  137. PACL Sacl
  138. )
  139. {
  140. HANDLE Handle;
  141. ULONG Status;
  142. #ifdef SET_SECURITY_BY_HANDLE
  143. Status = WmipOpenKernelGuid(Guid,
  144. WRITE_DAC | WRITE_OWNER,
  145. &Handle);
  146. if (Status == ERROR_SUCCESS)
  147. {
  148. Status = SetSecurityInfo(Handle,
  149. SE_KERNEL_OBJECT,
  150. SecurityInformation,
  151. OwnerSid,
  152. GroupSid,
  153. Dacl,
  154. Sacl);
  155. CloseHandle(Handle);
  156. }
  157. #else
  158. PCHAR GuidName;
  159. Status = UuidToString(Guid,
  160. &GuidName);
  161. if (Status == ERROR_SUCCESS)
  162. {
  163. Status = SetNamedSecurityInfo(GuidName,
  164. SE_WMIGUID_OBJECT,
  165. SecurityInformation,
  166. OwnerSid,
  167. GroupSid,
  168. Dacl,
  169. Sacl);
  170. RpcStringFree(&GuidName);
  171. }
  172. #endif
  173. return(Status);
  174. }
  175. ULONG GetWmiGuidSecurityInfo(
  176. LPGUID Guid,
  177. SECURITY_INFORMATION SecurityInformation,
  178. PSID *OwnerSid,
  179. PSID *GroupSid,
  180. PACL *Dacl,
  181. PACL *Sacl,
  182. PSECURITY_DESCRIPTOR *Sd
  183. )
  184. {
  185. HANDLE Handle;
  186. ULONG Status;
  187. #ifdef SET_SECURITY_BY_HANDLE
  188. Status = WmipOpenKernelGuid(Guid,
  189. READ_CONTROL,
  190. &Handle);
  191. if (Status == ERROR_SUCCESS)
  192. {
  193. Status = GetSecurityInfo(Handle,
  194. SE_KERNEL_OBJECT,
  195. SecurityInformation,
  196. OwnerSid,
  197. GroupSid,
  198. Dacl,
  199. Sacl,
  200. Sd);
  201. CloseHandle(Handle);
  202. }
  203. #else
  204. PCHAR GuidName;
  205. Status = UuidToString(Guid,
  206. &GuidName);
  207. if (Status == ERROR_SUCCESS)
  208. {
  209. Status = GetNamedSecurityInfo(GuidName,
  210. SE_WMIGUID_OBJECT,
  211. SecurityInformation,
  212. OwnerSid,
  213. GroupSid,
  214. Dacl,
  215. Sacl,
  216. Sd);
  217. RpcStringFree(&GuidName);
  218. }
  219. #endif
  220. return(Status);
  221. }
  222. //
  223. // The routines below were blantenly stolen without remorse from the ole
  224. // sources in \nt\private\ole32\com\class\compapi.cxx. They are copied here
  225. // so that WMI doesn't need to load in ole32 only to convert a guid string
  226. // into its binary representation.
  227. //
  228. //+-------------------------------------------------------------------------
  229. //
  230. // Function: HexStringToDword (private)
  231. //
  232. // Synopsis: scan lpsz for a number of hex digits (at most 8); update lpsz
  233. // return value in Value; check for chDelim;
  234. //
  235. // Arguments: [lpsz] - the hex string to convert
  236. // [Value] - the returned value
  237. // [cDigits] - count of digits
  238. //
  239. // Returns: TRUE for success
  240. //
  241. //--------------------------------------------------------------------------
  242. BOOL HexStringToDword(LPCSTR lpsz, DWORD * RetValue,
  243. int cDigits, WCHAR chDelim)
  244. {
  245. int Count;
  246. DWORD Value;
  247. Value = 0;
  248. for (Count = 0; Count < cDigits; Count++, lpsz++)
  249. {
  250. if (*lpsz >= '0' && *lpsz <= '9')
  251. Value = (Value << 4) + *lpsz - '0';
  252. else if (*lpsz >= 'A' && *lpsz <= 'F')
  253. Value = (Value << 4) + *lpsz - 'A' + 10;
  254. else if (*lpsz >= 'a' && *lpsz <= 'f')
  255. Value = (Value << 4) + *lpsz - 'a' + 10;
  256. else
  257. return(FALSE);
  258. }
  259. *RetValue = Value;
  260. if (chDelim != 0)
  261. return *lpsz++ == chDelim;
  262. else
  263. return TRUE;
  264. }
  265. //+-------------------------------------------------------------------------
  266. //
  267. // Function: wUUIDFromString (internal)
  268. //
  269. // Synopsis: Parse UUID such as 00000000-0000-0000-0000-000000000000
  270. //
  271. // Arguments: [lpsz] - Supplies the UUID string to convert
  272. // [pguid] - Returns the GUID.
  273. //
  274. // Returns: TRUE if successful
  275. //
  276. //--------------------------------------------------------------------------
  277. BOOL wUUIDFromString(LPCSTR lpsz, LPGUID pguid)
  278. {
  279. DWORD dw;
  280. if (!HexStringToDword(lpsz, &pguid->Data1, sizeof(DWORD)*2, '-'))
  281. return FALSE;
  282. lpsz += sizeof(DWORD)*2 + 1;
  283. if (!HexStringToDword(lpsz, &dw, sizeof(WORD)*2, '-'))
  284. return FALSE;
  285. lpsz += sizeof(WORD)*2 + 1;
  286. pguid->Data2 = (WORD)dw;
  287. if (!HexStringToDword(lpsz, &dw, sizeof(WORD)*2, '-'))
  288. return FALSE;
  289. lpsz += sizeof(WORD)*2 + 1;
  290. pguid->Data3 = (WORD)dw;
  291. if (!HexStringToDword(lpsz, &dw, sizeof(BYTE)*2, 0))
  292. return FALSE;
  293. lpsz += sizeof(BYTE)*2;
  294. pguid->Data4[0] = (BYTE)dw;
  295. if (!HexStringToDword(lpsz, &dw, sizeof(BYTE)*2, '-'))
  296. return FALSE;
  297. lpsz += sizeof(BYTE)*2+1;
  298. pguid->Data4[1] = (BYTE)dw;
  299. if (!HexStringToDword(lpsz, &dw, sizeof(BYTE)*2, 0))
  300. return FALSE;
  301. lpsz += sizeof(BYTE)*2;
  302. pguid->Data4[2] = (BYTE)dw;
  303. if (!HexStringToDword(lpsz, &dw, sizeof(BYTE)*2, 0))
  304. return FALSE;
  305. lpsz += sizeof(BYTE)*2;
  306. pguid->Data4[3] = (BYTE)dw;
  307. if (!HexStringToDword(lpsz, &dw, sizeof(BYTE)*2, 0))
  308. return FALSE;
  309. lpsz += sizeof(BYTE)*2;
  310. pguid->Data4[4] = (BYTE)dw;
  311. if (!HexStringToDword(lpsz, &dw, sizeof(BYTE)*2, 0))
  312. return FALSE;
  313. lpsz += sizeof(BYTE)*2;
  314. pguid->Data4[5] = (BYTE)dw;
  315. if (!HexStringToDword(lpsz, &dw, sizeof(BYTE)*2, 0))
  316. return FALSE;
  317. lpsz += sizeof(BYTE)*2;
  318. pguid->Data4[6] = (BYTE)dw;
  319. if (!HexStringToDword(lpsz, &dw, sizeof(BYTE)*2, 0))
  320. return FALSE;
  321. lpsz += sizeof(BYTE)*2;
  322. pguid->Data4[7] = (BYTE)dw;
  323. return TRUE;
  324. }
  325. //+-------------------------------------------------------------------------
  326. //
  327. // Function: wGUIDFromString (internal)
  328. //
  329. // Synopsis: Parse GUID such as {00000000-0000-0000-0000-000000000000}
  330. //
  331. // Arguments: [lpsz] - the guid string to convert
  332. // [pguid] - guid to return
  333. //
  334. // Returns: TRUE if successful
  335. //
  336. //--------------------------------------------------------------------------
  337. BOOL wGUIDFromString(LPCSTR lpsz, LPGUID pguid)
  338. {
  339. DWORD dw;
  340. if (*lpsz == '{' )
  341. lpsz++;
  342. if(wUUIDFromString(lpsz, pguid) != TRUE)
  343. return FALSE;
  344. lpsz +=36;
  345. if (*lpsz == '}' )
  346. lpsz++;
  347. if (*lpsz != '\0') // check for zero terminated string - test bug #18307
  348. {
  349. return FALSE;
  350. }
  351. return TRUE;
  352. }
  353. ULONG RemoveWmiSD(
  354. LPGUID Guid
  355. )
  356. {
  357. CHAR GuidName[35];
  358. HKEY RegistryKey;
  359. ULONG Status;
  360. Status = RegOpenKey(HKEY_LOCAL_MACHINE,
  361. "System\\CurrentControlSet\\Control\\Wmi\\Security",
  362. &RegistryKey);
  363. if (Status != ERROR_SUCCESS)
  364. {
  365. printf("RegOpenKey returned %d\n", Status);
  366. return(Status);
  367. }
  368. if (Guid != NULL)
  369. {
  370. wsprintf(GuidName, "%08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x",
  371. Guid->Data1, Guid->Data2,
  372. Guid->Data3,
  373. Guid->Data4[0], Guid->Data4[1],
  374. Guid->Data4[2], Guid->Data4[3],
  375. Guid->Data4[4], Guid->Data4[5],
  376. Guid->Data4[6], Guid->Data4[7]);
  377. } else {
  378. strcpy(GuidName, "00000000-0000-0000-0000000000000000");
  379. }
  380. RegDeleteValue(RegistryKey,
  381. GuidName);
  382. RegCloseKey(RegistryKey);
  383. return(ERROR_SUCCESS);
  384. }
  385. void Usage(
  386. void
  387. )
  388. {
  389. printf("wmisecur <guid> [owner | group | dacl | adacl] [parameters]\n");
  390. printf(" wmisecur <guid> owner <account name>\n");
  391. printf(" sets owner of guid to be <account name>\n\n");
  392. printf(" wmisecur <guid> group <account name>\n");
  393. printf(" sets group of guid to be <account name>\n\n");
  394. printf(" wmisecur <guid> dacl <account name> [allow | deny] <right1> <right2> ....\n");
  395. printf(" resets dacl to assign <right1>, <right2>, ... to <account name>\n\n");
  396. printf(" wmisecur <guid> adacl <account name> [allow | deny] <right1> <right2> ....\n");
  397. printf(" appends ace to dacl,<right1>, <right2>, ... assigned to <account name>\n\n");
  398. printf(" wmisecur <guid> query\n");
  399. printf(" queries and prints the security string\n\n");
  400. printf(" Rights: WMIGUID_QUERY\n");
  401. printf(" WMIGUID_SET\n");
  402. printf(" WMIGUID_NOTIFICATION\n");
  403. printf(" WMIGUID_READ_DESCRIPTION\n");
  404. printf(" WMIGUID_EXECUTE\n");
  405. printf(" TRACELOG_CREATE_REALTIME\n");
  406. printf(" TRACELOG_CREATE_ONDISK\n");
  407. printf(" TRACELOG_GUID_ENABLE\n");
  408. printf(" TRACELOG_ACCESS_KERNEL_LOGGER\n");
  409. printf(" TRACELOG_CREATE_INPROC\n");
  410. printf(" TRACELOG_ACCESS_REALTIME\n");
  411. printf(" READ_CONTROL\n");
  412. printf(" WRITE_DAC\n");
  413. printf(" WRITE_OWNER\n");
  414. printf(" DELETE\n");
  415. printf(" SYNCHRONIZE\n");
  416. printf(" ALL (all wmi specific rights)\n");
  417. printf(" ALLRIGHTS (STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL)\n");
  418. }
  419. typedef enum
  420. {
  421. SetOwner,
  422. SetGroup,
  423. ResetDacl,
  424. AppendDacl,
  425. CopyDacl,
  426. QueryGuid
  427. } OPERATION;
  428. typedef enum
  429. {
  430. Allow,
  431. Deny
  432. } ALLOWORDENY;
  433. ULONG SetOwnerOrGroup(
  434. OPERATION Operation,
  435. LPGUID Guid,
  436. PSID Sid
  437. )
  438. {
  439. ULONG Status;
  440. if (Operation == SetOwner)
  441. {
  442. Status = SetWmiGuidSecurityInfo(Guid,
  443. OWNER_SECURITY_INFORMATION,
  444. Sid,
  445. NULL,
  446. NULL,
  447. NULL);
  448. } else {
  449. Status = SetWmiGuidSecurityInfo(Guid,
  450. GROUP_SECURITY_INFORMATION,
  451. NULL,
  452. Sid,
  453. NULL,
  454. NULL);
  455. }
  456. return(Status);
  457. }
  458. ULONG ResetOrAppendDacl(
  459. OPERATION Operation,
  460. LPGUID Guid,
  461. PSID Sid,
  462. ALLOWORDENY AllowOrDeny,
  463. ULONG Rights
  464. )
  465. {
  466. ULONG Status;
  467. PSECURITY_DESCRIPTOR OldSD;
  468. PACL OldDacl, NewDacl;
  469. UCHAR NewDaclBuffer[512];
  470. NewDacl = (PACL)NewDaclBuffer;
  471. if ((Operation == AppendDacl) || (Operation == CopyDacl))
  472. {
  473. Status = GetWmiGuidSecurityInfo(Guid,
  474. DACL_SECURITY_INFORMATION,
  475. NULL,
  476. NULL,
  477. &OldDacl,
  478. NULL,
  479. &OldSD);
  480. if (Status != ERROR_SUCCESS)
  481. {
  482. return(Status);
  483. }
  484. memcpy(NewDacl, OldDacl, OldDacl->AclSize);
  485. LocalFree(OldSD);
  486. NewDacl->AclSize = sizeof(NewDaclBuffer);
  487. } else {
  488. RtlCreateAcl(NewDacl,
  489. sizeof(NewDaclBuffer),
  490. ACL_REVISION);
  491. }
  492. if (Operation != CopyDacl)
  493. {
  494. if (AllowOrDeny == Deny)
  495. {
  496. if (! AddAccessDeniedAce(NewDacl,
  497. ACL_REVISION,
  498. Rights,
  499. Sid))
  500. {
  501. return(GetLastError());
  502. }
  503. } else {
  504. if (! AddAccessAllowedAce(NewDacl,
  505. ACL_REVISION,
  506. Rights,
  507. Sid))
  508. {
  509. return(GetLastError());
  510. }
  511. }
  512. }
  513. Status = SetWmiGuidSecurityInfo(Guid,
  514. DACL_SECURITY_INFORMATION,
  515. NULL,
  516. NULL,
  517. NewDacl,
  518. NULL);
  519. return(Status);
  520. }
  521. BOOLEAN RightNameToDWord(
  522. PCHAR RightName,
  523. PDWORD RightDWord
  524. )
  525. {
  526. *RightDWord = 0;
  527. if (_stricmp(RightName, "WMIGUID_QUERY") == 0)
  528. {
  529. *RightDWord = WMIGUID_QUERY;
  530. } else if (_stricmp(RightName, "WMIGUID_SET") == 0) {
  531. *RightDWord = WMIGUID_SET;
  532. } else if (_stricmp(RightName, "WMIGUID_NOTIFICATION") == 0) {
  533. *RightDWord = WMIGUID_NOTIFICATION;
  534. } else if (_stricmp(RightName, "WMIGUID_READ_DESCRIPTION") == 0) {
  535. *RightDWord = WMIGUID_READ_DESCRIPTION;
  536. } else if (_stricmp(RightName, "WMIGUID_EXECUTE") == 0) {
  537. *RightDWord = WMIGUID_EXECUTE;
  538. } else if (_stricmp(RightName, "TRACELOG_CREATE_REALTIME") == 0) {
  539. *RightDWord = TRACELOG_CREATE_REALTIME;
  540. } else if (_stricmp(RightName, "TRACELOG_CREATE_ONDISK") == 0) {
  541. *RightDWord = TRACELOG_CREATE_ONDISK;
  542. } else if (_stricmp(RightName, "TRACELOG_GUID_ENABLE") == 0) {
  543. *RightDWord = TRACELOG_GUID_ENABLE;
  544. } else if (_stricmp(RightName, "TRACELOG_ACCESS_KERNEL_LOGGER") == 0) {
  545. *RightDWord = TRACELOG_ACCESS_KERNEL_LOGGER;
  546. } else if (_stricmp(RightName, "TRACELOG_CREATE_INPROC") == 0) {
  547. *RightDWord = TRACELOG_CREATE_INPROC;
  548. } else if (_stricmp(RightName, "TRACELOG_ACCESS_REALTIME") == 0) {
  549. *RightDWord = TRACELOG_ACCESS_REALTIME;
  550. } else if (_stricmp(RightName, "READ_CONTROL") == 0) {
  551. *RightDWord = READ_CONTROL;
  552. } else if (_stricmp(RightName, "WRITE_DAC") == 0) {
  553. *RightDWord = WRITE_DAC;
  554. } else if (_stricmp(RightName, "WRITE_OWNER") == 0) {
  555. *RightDWord = WRITE_OWNER;
  556. } else if (_stricmp(RightName, "WRITE_DAC") == 0) {
  557. *RightDWord = WRITE_DAC;
  558. } else if (_stricmp(RightName, "DELETE") == 0) {
  559. *RightDWord = DELETE;
  560. } else if (_stricmp(RightName, "SYNCHRONIZE") == 0) {
  561. *RightDWord = SYNCHRONIZE;
  562. } else if (_stricmp(RightName, "ALL") == 0) {
  563. *RightDWord = WMIGUID_ALL_ACCESS;
  564. } else if (_stricmp(RightName, "ALLRIGHTS") == 0) {
  565. *RightDWord = STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL;
  566. } else {
  567. return(FALSE);
  568. }
  569. return(TRUE);
  570. }
  571. int __cdecl main(int argc, char *argv[])
  572. {
  573. int i;
  574. ALLOWORDENY AllowOrDeny;
  575. OPERATION Operation;
  576. DWORD Rights;
  577. DWORD NewRight;
  578. PSID Sid;
  579. UCHAR SidBuffer[512];
  580. ULONG SidLength;
  581. GUID Guid;
  582. CHAR ReferencedDomain[512];
  583. SID_NAME_USE SidNameUse;
  584. ULONG ReferencedDomainSize;
  585. ULONG Status;
  586. if (argc < 2)
  587. {
  588. Usage();
  589. return(0);
  590. }
  591. if (_stricmp(argv[2], "owner") == 0)
  592. {
  593. Operation = SetOwner;
  594. } else if (_stricmp(argv[2], "group") == 0) {
  595. Operation = SetGroup;
  596. } else if (_stricmp(argv[2], "dacl") == 0) {
  597. Operation = ResetDacl;
  598. } else if (_stricmp(argv[2], "adacl") == 0) {
  599. Operation = AppendDacl;
  600. } else if (_stricmp(argv[2], "copy") == 0) {
  601. Operation = CopyDacl;
  602. } else if (_stricmp(argv[2], "query") == 0) {
  603. Operation = QueryGuid;
  604. } else {
  605. Usage();
  606. return(0);
  607. }
  608. //
  609. // Parse the guid parameter
  610. if (! wUUIDFromString(argv[1], &Guid))
  611. {
  612. printf("Bad guid %s\n", argv[1]);
  613. return(0);
  614. }
  615. if (Operation == QueryGuid)
  616. {
  617. if (PrintSecurityString(argv[1]))
  618. printf("Cannot find security set for given guid\n");
  619. return 0;
  620. }
  621. if (Operation == CopyDacl)
  622. {
  623. Status = ResetOrAppendDacl(Operation, &Guid, NULL, Allow, 0);
  624. printf("Status is %d\n", Status);
  625. return(Status);
  626. }
  627. if (_stricmp(argv[3], "LocalSystem") == 0)
  628. {
  629. //
  630. // This is a special SID we need to build by hand
  631. //
  632. //
  633. // Create SID for LocalSystem dynamically
  634. //
  635. Sid = (PSID)malloc(RtlLengthRequiredSid( 1 ));
  636. if (Sid != NULL)
  637. {
  638. SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
  639. RtlInitializeSid( Sid, &NtAuthority, 1);
  640. *(RtlSubAuthoritySid( Sid, 0 )) = SECURITY_LOCAL_SYSTEM_RID;
  641. } else {
  642. printf("Not enougfh memory for local system sid\n");
  643. return(ERROR_NOT_ENOUGH_MEMORY);
  644. }
  645. } else {
  646. //
  647. // Parse the account name parameter
  648. Sid = (PSID)SidBuffer;
  649. SidLength = sizeof(SidBuffer);
  650. ReferencedDomainSize = sizeof(ReferencedDomain);
  651. if (! LookupAccountName(NULL,
  652. argv[3],
  653. Sid,
  654. &SidLength,
  655. ReferencedDomain,
  656. &ReferencedDomainSize,
  657. &SidNameUse))
  658. {
  659. printf("Error %d looking up account %s\n", GetLastError(), argv[3]);
  660. return(0);
  661. }
  662. }
  663. if ((Operation == SetOwner) ||
  664. (Operation == SetGroup))
  665. {
  666. Status = SetOwnerOrGroup(Operation, &Guid, Sid);
  667. printf("Status is %d\n", Status);
  668. if (Status == 0) {
  669. PrintSecurityString(argv[1]);
  670. }
  671. } else {
  672. if (argc < 4)
  673. {
  674. Usage();
  675. return(0);
  676. }
  677. if (_stricmp(argv[4], "allow") == 0)
  678. {
  679. AllowOrDeny = Allow;
  680. } else if (_stricmp(argv[4], "deny") == 0) {
  681. AllowOrDeny = Deny;
  682. } else {
  683. Usage();
  684. return(0);
  685. }
  686. Rights = 0;
  687. for (i = 5; i < argc; i++)
  688. {
  689. if (! RightNameToDWord(argv[i], &NewRight))
  690. {
  691. printf("Invalid right %s\n", argv[i]);
  692. return(0);
  693. }
  694. Rights |= NewRight;
  695. }
  696. Status = ResetOrAppendDacl(Operation, &Guid, Sid, AllowOrDeny, Rights);
  697. printf("Status is %d\n", Status);
  698. if (Status == 0) {
  699. PrintSecurityString(argv[1]);
  700. }
  701. }
  702. }
  703. ULONG
  704. PrintSecurityString(LPSTR GuidStr)
  705. {
  706. ULONG status;
  707. HKEY hKey;
  708. UCHAR buffer[1024];
  709. ULONG size, i;
  710. status = RegOpenKeyEx(
  711. HKEY_LOCAL_MACHINE,
  712. WMI_SECURITY_REGSTR,
  713. 0L,
  714. KEY_QUERY_VALUE,
  715. &hKey);
  716. if (status != ERROR_SUCCESS)
  717. return status;
  718. size = 1024;
  719. status = RegQueryValueEx(
  720. hKey,
  721. GuidStr,
  722. NULL,
  723. NULL,
  724. buffer,
  725. &size);
  726. if (status != ERROR_SUCCESS) {
  727. RegCloseKey(hKey);
  728. return status;
  729. }
  730. printf("\nHKLM,\"%s\",\"%s\",0x00030003,\\\n",
  731. WMI_SECURITY_REGSTR, GuidStr);
  732. for (i=0; i<size; i++) {
  733. if ((i%16) == 0) {
  734. if (i>0)
  735. printf(",\\\n");
  736. printf(" ");
  737. printf("%02x", buffer[i]);
  738. }
  739. else
  740. printf(",%02x", buffer[i]);
  741. }
  742. printf("\n");
  743. RegCloseKey(hKey);
  744. return ERROR_SUCCESS;
  745. }