Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

388 lines
10 KiB

  1. /*--
  2. Copyright (c) 1996-1997 Microsoft Corporation
  3. Module Name:
  4. dacls.c
  5. Abstract:
  6. Extended version of cacls.exe
  7. Author:
  8. 14-Dec-1996 (macm)
  9. Environment:
  10. User mode only.
  11. Requires ANSI C extensions: slash-slash comments, long external names.
  12. Revision History:
  13. --*/
  14. #include <windows.h>
  15. #include <caclscom.h>
  16. #include <dsysdbg.h>
  17. #include <stdio.h>
  18. #include <aclapi.h>
  19. #define CMD_PRESENT(index, list) ((list)[index].iIndex != -1)
  20. #define NO_INHERIT_ONLY
  21. //
  22. // Enumeration of command tags
  23. //
  24. typedef enum _CMD_TAGS {
  25. CmdTree = 0,
  26. CmdEdit,
  27. CmdContinue,
  28. CmdGrant,
  29. CmdRevoke,
  30. CmdReplace,
  31. CmdDeny,
  32. CmdICont,
  33. CmdIObj,
  34. #ifndef NO_INHERIT_ONLY
  35. CmdIOnly,
  36. #endif
  37. CmdIProp
  38. } CMD_TAGS, *PCMD_TAGS;
  39. VOID
  40. Usage (
  41. IN PCACLS_STR_RIGHTS pStrRights,
  42. IN INT cStrRights,
  43. IN PCACLS_CMDLINE pCmdVals
  44. )
  45. /*++
  46. Routine Description:
  47. Displays the expected usage
  48. Arguments:
  49. Return Value:
  50. VOID
  51. --*/
  52. {
  53. INT i;
  54. printf("Displays or modifies access control lists (ACLs) of files\n\n");
  55. printf("DACLS filename [/T] [/E] [/C] [/G user:perm] [/R user [...]]\n");
  56. printf(" [/P user:perm [...]] [/D user [...]]\n");
  57. printf(" filename Displays ACLs.\n");
  58. printf(" /%s Changes ACLs of specified files in\n", pCmdVals[CmdTree].pszSwitch);
  59. printf(" the current directory and all subdirectories.\n");
  60. printf(" /%s Edit ACL instead of replacing it.\n", pCmdVals[CmdEdit].pszSwitch);
  61. printf(" /%s Continue on access denied errors.\n", pCmdVals[CmdContinue].pszSwitch);
  62. printf(" /%s user:perms Grant specified user access rights .\n", pCmdVals[CmdGrant].pszSwitch);
  63. printf(" /%s user Revoke specified user's access rights (only valid with /E).\n", pCmdVals[CmdRevoke].pszSwitch);
  64. printf(" /%s user:perms Replace specified user's access rights.\n", pCmdVals[CmdReplace].pszSwitch);
  65. printf(" /%s user:perms Deny specified user access.\n", pCmdVals[CmdDeny].pszSwitch);
  66. printf(" /%s Mark the ace as CONTAINER_INHERIT (folder or directory inherit)\n", pCmdVals[CmdICont].pszSwitch);
  67. printf(" /%s Mark the ace as OBJECT_INHERIT\n", pCmdVals[CmdIObj].pszSwitch);
  68. #ifndef NO_INHERIT_ONLY
  69. printf(" /%s Mark the ace as INHERIT_ONLY\n", pCmdVals[CmdIOnly].pszSwitch);
  70. #endif
  71. printf(" /%s Mark the ace as INHERIT_NO_PROPAGATE\n", pCmdVals[CmdIProp].pszSwitch);
  72. printf("The list of supported perms for the Grant and Replace operations are:\n");
  73. for (i = 0; i < cStrRights; i++) {
  74. printf(" %c%c %s\n",
  75. pStrRights[i].szRightsTag[0],
  76. pStrRights[i].szRightsTag[1],
  77. pStrRights[i].pszDisplayTag);
  78. }
  79. printf("\nMultiple perms can be specified per user\n");
  80. printf("Wildcards can be used to specify more that one file in a command.\n");
  81. printf("You can specify more than one user in a command.\n\n");
  82. printf("Example: DACLS c:\\temp /G user1:GRGW user2:SDRC\n");
  83. }
  84. INT
  85. __cdecl main (
  86. int argc,
  87. char *argv[])
  88. /*++
  89. Routine Description:
  90. The main the for this executable
  91. Arguments:
  92. argc - Count of arguments
  93. argv - List of arguments
  94. Return Value:
  95. VOID
  96. --*/
  97. {
  98. DWORD dwErr = 0;
  99. CACLS_STR_RIGHTS pStrRights[] = {
  100. "NA", 0, "No Access",
  101. "GR", GENERIC_READ, "Read",
  102. "GC", GENERIC_WRITE, "Change (write)",
  103. "GF", GENERIC_ALL, "Full control",
  104. "SD", DELETE, "Delete",
  105. "RC", READ_CONTROL, "Read Control",
  106. "WP", WRITE_DAC, "Write DAC",
  107. "WO", WRITE_OWNER, "Write Owner",
  108. "RD", FILE_READ_DATA, "Read Data (on file) / List Directory (on Dir)",
  109. "WD", FILE_WRITE_DATA, "Write Data (on file) / Add File (on Dir)",
  110. "AD", FILE_APPEND_DATA, "Append Data (on file) / Add SubDir (on Dir)",
  111. "FE", FILE_EXECUTE, "Execute (on file) / Traverse (on Dir)",
  112. "DC", FILE_DELETE_CHILD, "Delete Child (on Dir only)",
  113. "RA", FILE_READ_ATTRIBUTES, "Read Attributes",
  114. "WA", FILE_WRITE_ATTRIBUTES, "Write Attributes",
  115. "RE", FILE_READ_EA, "Read Extended Attributes",
  116. "WE", FILE_WRITE_EA, "Write Extended Attributes"
  117. };
  118. INT cStrRights = sizeof(pStrRights) / sizeof(CACLS_STR_RIGHTS);
  119. CACLS_CMDLINE pCmdVals[] = {
  120. "T", -1, FALSE, 0, // CmdTree
  121. "E", -1, FALSE, 0, // CmdEdit
  122. "C", -1, FALSE, 0, // CmdContinue
  123. "G", -1, TRUE, 0, // CmdGrant
  124. "R", -1, TRUE, 0, // CmdRevoke
  125. "P", -1, TRUE, 0, // CmdReplace
  126. "D", -1, TRUE, 0, // CmdDeny
  127. "F", -1, FALSE, 0, // CmdICont
  128. "O", -1, FALSE, 0, // CmdIObj
  129. #ifndef NO_INHERIT_ONLY
  130. "I", -1, FALSE, 0, // CmdIOnly
  131. #endif
  132. "N", -1, FALSE, 0, // CmdIProp
  133. };
  134. INT cCmdVals = sizeof(pCmdVals) / sizeof(CACLS_CMDLINE);
  135. INT i;
  136. PSECURITY_DESCRIPTOR pInitialSD = NULL, pFinalSD;
  137. PACL pOldAcl = NULL, pNewAcl = NULL;
  138. DWORD fInherit = 0;
  139. BOOL fFreeAcl = FALSE;
  140. if (argc < 2) {
  141. Usage(pStrRights, cStrRights, pCmdVals);
  142. return(1);
  143. } else if (argc == 2 && (strcmp(argv[1], "-?") == 0 || strcmp(argv[1], "/?") == 0)) {
  144. Usage(pStrRights, cStrRights, pCmdVals);
  145. return(0);
  146. }
  147. //
  148. // Parse the command line
  149. //
  150. dwErr = ParseCmdline(argv, argc, 2, pCmdVals, cCmdVals);
  151. if (dwErr != ERROR_SUCCESS) {
  152. Usage(pStrRights, cStrRights, pCmdVals);
  153. return(1);
  154. }
  155. //
  156. // Set our inheritance flags
  157. //
  158. if (CMD_PRESENT(CmdICont, pCmdVals)) {
  159. fInherit |= CONTAINER_INHERIT_ACE;
  160. }
  161. if (CMD_PRESENT(CmdIObj, pCmdVals)) {
  162. fInherit |= OBJECT_INHERIT_ACE;
  163. }
  164. #ifndef NO_INHERIT_ONLY
  165. if (CMD_PRESENT(CmdIOnly, pCmdVals)) {
  166. fInherit |= INHERIT_ONLY_ACE;
  167. }
  168. #endif
  169. if (CMD_PRESENT(CmdIProp, pCmdVals)) {
  170. fInherit |= NO_PROPAGATE_INHERIT_ACE;
  171. }
  172. //
  173. // Ok, see if we need to read the existing security
  174. //
  175. if (CMD_PRESENT(CmdEdit, pCmdVals) || argc == 2) {
  176. dwErr = GetNamedSecurityInfoA(argv[1], SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
  177. NULL, NULL, &pOldAcl, NULL, &pInitialSD);
  178. if (dwErr != ERROR_SUCCESS) {
  179. fprintf(stderr, "Failed to read the security off of %s: %lu\n", argv[1], dwErr);
  180. }
  181. }
  182. //
  183. // Either display the existing access or do the sets as requested
  184. //
  185. if (dwErr == ERROR_SUCCESS && argc == 2) {
  186. dwErr = DisplayAcl ( argv[1], pOldAcl, pStrRights, cStrRights );
  187. } else {
  188. //
  189. // Ok, first we do the revokes
  190. //
  191. if (dwErr == ERROR_SUCCESS && CMD_PRESENT(CmdRevoke, pCmdVals)) {
  192. //
  193. // Make sure we've read it first...
  194. //
  195. if (CMD_PRESENT(CmdEdit, pCmdVals)) {
  196. dwErr = ProcessOperation( argv, &pCmdVals[CmdRevoke], REVOKE_ACCESS, pStrRights,
  197. cStrRights, fInherit, pOldAcl, &pNewAcl );
  198. if (dwErr == ERROR_SUCCESS) {
  199. pOldAcl = pNewAcl;
  200. }
  201. } else {
  202. dwErr = ERROR_INVALID_PARAMETER;
  203. }
  204. }
  205. //
  206. // Then the grants
  207. //
  208. if (dwErr == ERROR_SUCCESS && CMD_PRESENT(CmdGrant, pCmdVals)) {
  209. //
  210. // First, see if we need to free the old acl on completion
  211. //
  212. if (pOldAcl == pNewAcl) {
  213. fFreeAcl = TRUE;
  214. }
  215. dwErr = ProcessOperation(argv, &pCmdVals[CmdGrant], GRANT_ACCESS, pStrRights,
  216. cStrRights, 0, pOldAcl, &pNewAcl);
  217. if (dwErr == ERROR_SUCCESS) {
  218. if (fFreeAcl == TRUE) {
  219. LocalFree(pOldAcl);
  220. }
  221. pOldAcl = pNewAcl;
  222. //
  223. // Now set it and optionally propagate it
  224. //
  225. dwErr = SetAndPropagateFileRights(argv[1], pNewAcl, DACL_SECURITY_INFORMATION,
  226. CMD_PRESENT(CmdTree, pCmdVals),
  227. CMD_PRESENT(CmdContinue, pCmdVals), TRUE,
  228. fInherit);
  229. }
  230. }
  231. //
  232. // Finally, the denieds
  233. //
  234. if (dwErr == ERROR_SUCCESS && CMD_PRESENT(CmdDeny, pCmdVals)) {
  235. //
  236. // First, see if we need to free the old acl on completion
  237. //
  238. if (pOldAcl == pNewAcl) {
  239. fFreeAcl = TRUE;
  240. }
  241. dwErr = ProcessOperation(argv, &pCmdVals[CmdDeny], DENY_ACCESS, pStrRights,
  242. cStrRights, 0, pOldAcl, &pNewAcl);
  243. if (dwErr == ERROR_SUCCESS) {
  244. if (fFreeAcl == TRUE) {
  245. LocalFree(pOldAcl);
  246. }
  247. pOldAcl = pNewAcl;
  248. //
  249. // Now set it and optionally propagate it
  250. //
  251. dwErr = SetAndPropagateFileRights(argv[1], pNewAcl, DACL_SECURITY_INFORMATION,
  252. CMD_PRESENT(CmdTree, pCmdVals),
  253. CMD_PRESENT(CmdContinue, pCmdVals), FALSE,
  254. fInherit);
  255. }
  256. }
  257. //
  258. // Finally, do the set if it hasn't already been done
  259. //
  260. if (dwErr == ERROR_SUCCESS && !CMD_PRESENT(CmdGrant, pCmdVals) &&
  261. !CMD_PRESENT(CmdDeny, pCmdVals)) {
  262. dwErr = SetAndPropagateFileRights(argv[1], pNewAcl, DACL_SECURITY_INFORMATION,
  263. CMD_PRESENT(CmdTree, pCmdVals),
  264. CMD_PRESENT(CmdContinue, pCmdVals), FALSE,
  265. fInherit);
  266. }
  267. if (dwErr == ERROR_INVALID_PARAMETER) {
  268. Usage(pStrRights, cStrRights, pCmdVals);
  269. }
  270. LocalFree(pInitialSD);
  271. }
  272. LocalFree(pOldAcl);
  273. if(dwErr == ERROR_SUCCESS) {
  274. printf("The command completed successfully\n");
  275. } else {
  276. printf("The command failed with an error %lu\n", dwErr);
  277. }
  278. return(dwErr == 0 ? 0 : 1);
  279. }