[PATCH] smbcacls added support for a -I flag
Matthew McGillis
matthew at mcgillis.org
Mon Apr 26 12:05:24 MDT 2010
Added support for a -I flag which provides the equivelant functionality of
setting or unsetting the windows file properity check box:
"Allow inheritable permissions from the parent to propagate to this object
and all child objects. Include these with entries explicitly defined here."
Hopefully this patch will address all the issues identified by Volker.
Regards
Matthew
---
source3/utils/smbcacls.c | 259 ++++++++++++++++++++++++++++++++++------------
1 files changed, 194 insertions(+), 65 deletions(-)
diff --git a/source3/utils/smbcacls.c b/source3/utils/smbcacls.c
index e1e37ae..be6e697 100644
--- a/source3/utils/smbcacls.c
+++ b/source3/utils/smbcacls.c
@@ -36,7 +36,7 @@ static int numeric;
static int sddl;
enum acl_mode {SMB_ACL_SET, SMB_ACL_DELETE, SMB_ACL_MODIFY, SMB_ACL_ADD };
-enum chown_mode {REQUEST_NONE, REQUEST_CHOWN, REQUEST_CHGRP};
+enum chown_mode {REQUEST_NONE, REQUEST_CHOWN, REQUEST_CHGRP, REQUEST_INHERIT};
enum exit_values {EXIT_OK, EXIT_FAILED, EXIT_PARSE_ERROR};
struct perm_value {
@@ -659,42 +659,113 @@ static void sec_desc_print(struct cli_state *cli, FILE *f, SEC_DESC *sd)
}
/*****************************************************
-dump the acls for a file
+get fileinfo for filename
*******************************************************/
-static int cacl_dump(struct cli_state *cli, char *filename)
+static uint16 get_fileinfo(struct cli_state *cli, char *filename)
+{
+ uint16_t fnum = (uint16_t)-1;
+ uint16 mode;
+
+ /* The desired access below is the only one I could find that works
+ with NT4, W2KP and Samba */
+
+ if (!NT_STATUS_IS_OK(cli_ntcreate(cli, filename, 0, CREATE_ACCESS_READ,
+ 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
+ FILE_OPEN, 0x0, 0x0, &fnum))) {
+ printf("Failed to open %s: %s\n", filename, cli_errstr(cli));
+ }
+
+ if (!cli_qfileinfo(cli, fnum, &mode, NULL, NULL, NULL,
+ NULL, NULL, NULL)) {
+ printf("Failed to file info %s: %s\n", filename,
+ cli_errstr(cli));
+ }
+
+ cli_close(cli, fnum);
+
+ return mode;
+}
+
+/*****************************************************
+get sec desc for filename
+*******************************************************/
+static SEC_DESC *get_secdesc(struct cli_state *cli, char *filename)
{
- int result = EXIT_FAILED;
uint16_t fnum = (uint16_t)-1;
SEC_DESC *sd;
- if (test_args)
- return EXIT_OK;
+ /* The desired access below is the only one I could find that works
+ with NT4, W2KP and Samba */
- if (!NT_STATUS_IS_OK(cli_ntcreate(cli, filename, 0, CREATE_ACCESS_READ, 0,
- FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0x0, 0x0, &fnum))) {
+ if (!NT_STATUS_IS_OK(cli_ntcreate(cli, filename, 0, CREATE_ACCESS_READ,
+ 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
+ FILE_OPEN, 0x0, 0x0, &fnum))) {
printf("Failed to open %s: %s\n", filename, cli_errstr(cli));
- goto done;
+ return NULL;
}
sd = cli_query_secdesc(cli, fnum, talloc_tos());
+ cli_close(cli, fnum);
+
if (!sd) {
- printf("ERROR: secdesc query failed: %s\n", cli_errstr(cli));
- goto done;
+ printf("Failed to get security descriptor\n");
+ return NULL;
}
+ return sd;
+}
- if (sddl) {
- printf("%s\n", sddl_encode(talloc_tos(), sd,
- get_global_sam_sid()));
- } else {
- sec_desc_print(cli, stdout, sd);
- }
+/*****************************************************
+set sec desc for filename
+*******************************************************/
+static bool set_secdesc(struct cli_state *cli, char *filename, SEC_DESC *sd)
+{
+ uint16_t fnum = (uint16_t)-1;
+ bool result=true;
+
+ /* The desired access below is the only one I could find that works
+ with NT4, W2KP and Samba */
- result = EXIT_OK;
+ if (!NT_STATUS_IS_OK(cli_ntcreate(cli, filename, 0,
+ WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS,
+ 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
+ FILE_OPEN, 0x0, 0x0, &fnum))) {
+ printf("Failed to open %s: %s\n", filename, cli_errstr(cli));
+ return false;
+ }
-done:
- if (fnum != (uint16_t)-1)
+ if (!cli_set_secdesc(cli, fnum, sd)) {
+ printf("ERROR: security description set failed: %s\n",
+ cli_errstr(cli));
cli_close(cli, fnum);
+ result=false;
+ }
+
+ cli_close(cli, fnum);
+ return result;
+}
+
+/*****************************************************
+dump the acls for a file
+*******************************************************/
+static int cacl_dump(struct cli_state *cli, char *filename)
+{
+ int result = EXIT_FAILED;
+ SEC_DESC *sd;
+
+ if (test_args)
+ return EXIT_OK;
+
+ sd = get_secdesc(cli, filename);
+
+ if (sd) {
+ if (sddl) {
+ printf("%s\n", sddl_encode(talloc_tos(), sd, get_global_sam_sid()));
+ } else {
+ sec_desc_print(cli, stdout, sd);
+ }
+ result = EXIT_OK;
+ }
return result;
}
@@ -705,28 +776,19 @@ because the NT docs say this can't be done :-). JRA.
*******************************************************/
static int owner_set(struct cli_state *cli, enum chown_mode change_mode,
- const char *filename, const char *new_username)
+ char *filename, const char *new_username)
{
uint16_t fnum;
DOM_SID sid;
SEC_DESC *sd, *old;
size_t sd_size;
- if (!NT_STATUS_IS_OK(cli_ntcreate(cli, filename, 0, CREATE_ACCESS_READ, 0,
- FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0x0, 0x0, &fnum))) {
- printf("Failed to open %s: %s\n", filename, cli_errstr(cli));
- return EXIT_FAILED;
- }
-
if (!StringToSid(cli, &sid, new_username))
return EXIT_PARSE_ERROR;
- old = cli_query_secdesc(cli, fnum, talloc_tos());
-
- cli_close(cli, fnum);
+ old = get_secdesc(cli, filename);
if (!old) {
- printf("owner_set: Failed to query old descriptor\n");
return EXIT_FAILED;
}
@@ -735,20 +797,10 @@ static int owner_set(struct cli_state *cli, enum chown_mode change_mode,
(change_mode == REQUEST_CHGRP) ? &sid : NULL,
NULL, NULL, &sd_size);
- if (!NT_STATUS_IS_OK(cli_ntcreate(cli, filename, 0, WRITE_OWNER_ACCESS, 0,
- FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0x0, 0x0, &fnum))) {
- printf("Failed to open %s: %s\n", filename, cli_errstr(cli));
- return EXIT_FAILED;
- }
-
- if (!cli_set_secdesc(cli, fnum, sd)) {
- printf("ERROR: secdesc set failed: %s\n", cli_errstr(cli));
- cli_close(cli, fnum);
+ if (!set_secdesc(cli, filename, sd)) {
return EXIT_FAILED;
}
- cli_close(cli, fnum);
-
return EXIT_OK;
}
@@ -821,7 +873,6 @@ set the ACLs on a file given an ascii description
static int cacl_set(struct cli_state *cli, char *filename,
char *the_acl, enum acl_mode mode)
{
- uint16_t fnum;
SEC_DESC *sd, *old;
uint32 i, j;
size_t sd_size;
@@ -836,24 +887,12 @@ static int cacl_set(struct cli_state *cli, char *filename,
if (!sd) return EXIT_PARSE_ERROR;
if (test_args) return EXIT_OK;
- /* The desired access below is the only one I could find that works
- with NT4, W2KP and Samba */
-
- if (!NT_STATUS_IS_OK(cli_ntcreate(cli, filename, 0, CREATE_ACCESS_READ, 0,
- FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0x0, 0x0, &fnum))) {
- printf("cacl_set failed to open %s: %s\n", filename, cli_errstr(cli));
- return EXIT_FAILED;
- }
-
- old = cli_query_secdesc(cli, fnum, talloc_tos());
+ old = get_secdesc(cli, filename);
if (!old) {
- printf("calc_set: Failed to query old descriptor\n");
return EXIT_FAILED;
}
- cli_close(cli, fnum);
-
/* the logic here is rather more complex than I would like */
switch (mode) {
case SMB_ACL_DELETE:
@@ -939,20 +978,102 @@ static int cacl_set(struct cli_state *cli, char *filename,
old->owner_sid, old->group_sid,
NULL, old->dacl, &sd_size);
- if (!NT_STATUS_IS_OK(cli_ntcreate(cli, filename, 0, WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS, 0,
- FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0x0, 0x0, &fnum))) {
- printf("cacl_set failed to open %s: %s\n", filename, cli_errstr(cli));
+ if (!set_secdesc(cli, filename, sd)) {
+ result = EXIT_FAILED;
+ }
+
+ return result;
+}
+
+/*****************************************************
+set the inherit on a file
+*******************************************************/
+
+static int inherit(struct cli_state *cli, char *filename, const char *type)
+{
+ uint16_t fnum;
+ SEC_DESC *old,*sd;
+ uint32 i, j;
+ size_t sd_size;
+ int result = EXIT_OK;
+
+ old = get_secdesc(cli, filename);
+
+ if (!old) {
return EXIT_FAILED;
}
- if (!cli_set_secdesc(cli, fnum, sd)) {
- printf("ERROR: secdesc set failed: %s\n", cli_errstr(cli));
- result = EXIT_FAILED;
+ uint32 oldattr = get_fileinfo(cli,filename);
+
+ if (strcmp(type,"allow")==0) {
+ char *parentname;
+ SEC_DESC *parent;
+
+ old->type=old->type & (~SEC_DESC_DACL_PROTECTED);
+
+ /* look at parent and copy in all its inheritable ACL's. */
+ string_replace(filename, '\\', '/');
+ if (!parent_dirname(talloc_tos(),filename,&parentname,NULL)) {
+ return EXIT_FAILED;
+ }
+ string_replace(filename, '/', '\\');
+ string_replace(parentname, '/', '\\');
+ parent = get_secdesc(cli,parentname);
+ for (i=0;i<parent->dacl->num_aces;i++) {
+ SEC_ACE *ace=&parent->dacl->aces[i];
+ if ((oldattr & aDIR) == aDIR) {
+ if ((ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) ==
+ SEC_ACE_FLAG_CONTAINER_INHERIT) {
+ add_ace(&old->dacl, ace);
+ }
+ } else {
+ if ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) ==
+ SEC_ACE_FLAG_OBJECT_INHERIT) {
+ add_ace(&old->dacl, ace);
+ }
+ }
+ }
+ } else if (strcmp(type,"remove")==0) {
+ old->type=old->type | SEC_DESC_DACL_PROTECTED;
+
+ /* remove all inherited ACL's. */
+ if (old->dacl) {
+ SEC_ACL *temp=old->dacl;
+ old->dacl=make_sec_acl(talloc_tos(), 3, 0, NULL);
+ int i;
+ for (i=temp->num_aces-1;i>=0;i--) {
+ SEC_ACE *ace=&temp->aces[i];
+ /* Remove all ace with INHERITED flag set */
+ if ((ace->flags & SEC_ACE_FLAG_INHERITED_ACE) !=
+ SEC_ACE_FLAG_INHERITED_ACE) {
+ add_ace(&old->dacl,ace);
+ }
+ }
+ }
+ } else if (strcmp(type,"copy")==0) {
+ old->type=old->type | SEC_DESC_DACL_PROTECTED;
+
+ /* convert all inherited ACL's to non inherated ACL's. */
+ if (old->dacl) {
+ int i;
+ for (i=0;i<old->dacl->num_aces;i++) {
+ SEC_ACE *ace=&old->dacl->aces[i];
+ /* Remove INHERITED FLAG from all aces */
+ ace->flags=ace->flags&(~SEC_ACE_FLAG_INHERITED_ACE);
+ }
+ }
}
- /* Clean up */
+ /* Denied ACE entries must come before allowed ones */
+ sort_acl(old->dacl);
- cli_close(cli, fnum);
+ sd = make_sec_desc(talloc_tos(),old->revision, old->type,
+ old->owner_sid, old->group_sid,
+ NULL, old->dacl, &sd_size);
+
+ if (!set_secdesc(cli, filename, sd)) {
+ result = EXIT_FAILED;
+ }
return result;
}
@@ -1034,6 +1155,7 @@ static struct cli_state *connect_one(struct user_auth_info *auth_info,
{ "set", 'S', POPT_ARG_STRING, NULL, 'S', "Set acls", "ACLS" },
{ "chown", 'C', POPT_ARG_STRING, NULL, 'C', "Change ownership of a file", "USERNAME" },
{ "chgrp", 'G', POPT_ARG_STRING, NULL, 'G', "Change group ownership of a file", "GROUPNAME" },
+ { "inherit", 'I', POPT_ARG_STRING, NULL, 'I', "Inherit allow|remove|copy" },
{ "numeric", 0, POPT_ARG_NONE, &numeric, 1, "Don't resolve sids or masks to names" },
{ "sddl", 0, POPT_ARG_NONE, &sddl, 1, "Output and input acls in sddl format" },
{ "test-args", 't', POPT_ARG_NONE, &test_args, 1, "Test arguments"},
@@ -1106,6 +1228,11 @@ static struct cli_state *connect_one(struct user_auth_info *auth_info,
owner_username = poptGetOptArg(pc);
change_mode = REQUEST_CHGRP;
break;
+
+ case 'I':
+ owner_username = poptGetOptArg(pc);
+ change_mode = REQUEST_INHERIT;
+ break;
}
}
@@ -1166,7 +1293,9 @@ static struct cli_state *connect_one(struct user_auth_info *auth_info,
/* Perform requested action */
- if (change_mode != REQUEST_NONE) {
+ if (change_mode == REQUEST_INHERIT) {
+ result = inherit(cli, filename, owner_username);
+ } else if (change_mode != REQUEST_NONE) {
result = owner_set(cli, change_mode, filename, owner_username);
} else if (the_acl) {
result = cacl_set(cli, filename, the_acl, mode);
--
1.6.2.5
More information about the samba-technical
mailing list