summaryrefslogtreecommitdiff
path: root/source3/utils
diff options
context:
space:
mode:
Diffstat (limited to 'source3/utils')
-rw-r--r--source3/utils/smbcacls.c130
1 files changed, 118 insertions, 12 deletions
diff --git a/source3/utils/smbcacls.c b/source3/utils/smbcacls.c
index f18899d01d..8a88469999 100644
--- a/source3/utils/smbcacls.c
+++ b/source3/utils/smbcacls.c
@@ -32,6 +32,9 @@ static int got_pass;
than going via LSA calls to resolve them */
static int numeric;
+enum acl_mode {ACL_SET, ACL_DELETE, ACL_MODIFY, ACL_ADD};
+
+
/* convert a SID to a string, either numeric or username/group */
static void SidToString(fstring str, DOM_SID *sid)
{
@@ -79,7 +82,7 @@ static void print_ace(FILE *f, SEC_ACE *ace)
perm = "C";
} else if (ace->info.mask == 0x001200a9) {
perm = "R";
- } else if (ace->info.mask == 0x00000000) {
+ } else if (ace->info.mask == 0x00080000) {
perm = "N";
} else {
perm = "?";
@@ -275,12 +278,14 @@ static void cacl_dump(struct cli_state *cli, char *filename)
/*****************************************************
set the ACLs on a file given an ascii description
*******************************************************/
-static void cacl_set(struct cli_state *cli, char *filename, char *set_acl)
+static void cacl_set(struct cli_state *cli, char *filename,
+ char *acl, enum acl_mode mode)
{
int fnum;
- SEC_DESC *sd;
+ SEC_DESC *sd, *old;
+ int i, j;
- sd = sec_desc_parse(set_acl);
+ sd = sec_desc_parse(acl);
if (!sd) {
printf("Failed to parse security descriptor\n");
return;
@@ -292,14 +297,89 @@ static void cacl_set(struct cli_state *cli, char *filename, char *set_acl)
return;
}
- /* sec_desc_print(stdout, sd); */
+ old = cli_query_secdesc(cli, fnum);
+
+ /* the logic here is rather more complex than I would like */
+ switch (mode) {
+ case ACL_DELETE:
+ for (i=0;sd->dacl && i<sd->dacl->num_aces;i++) {
+ for (j=0;old->dacl && j<old->dacl->num_aces;j++) {
+ if (sec_ace_equal(&sd->dacl->ace[i],
+ &old->dacl->ace[j])) {
+ if (j == old->dacl->num_aces-1) {
+ free(old->dacl->ace);
+ old->dacl->ace=NULL;
+ free(old->dacl);
+ old->dacl = NULL;
+ } else {
+ old->dacl->ace[j] = old->dacl->ace[j+1];
+ old->dacl->num_aces--;
+ }
+ j--;
+ }
+ }
+ }
+ for (i=0;sd->sacl && i<sd->sacl->num_aces;i++) {
+ for (j=0;old->sacl && j<old->sacl->num_aces;j++) {
+ if (sec_ace_equal(&sd->sacl->ace[i],
+ &old->sacl->ace[j])) {
+ if (j == old->sacl->num_aces-1) {
+ free(old->sacl->ace);
+ old->sacl->ace=NULL;
+ free(old->sacl);
+ old->sacl = NULL;
+ } else {
+ old->sacl->ace[j] = old->sacl->ace[j+1];
+ old->sacl->num_aces--;
+ }
+ j--;
+ }
+ }
+ }
+ break;
+
+ case ACL_MODIFY:
+ for (i=0;sd->dacl && i<sd->dacl->num_aces;i++) {
+ for (j=0;old->dacl && j<old->dacl->num_aces;j++) {
+ if (sid_equal(&sd->dacl->ace[i].sid,
+ &old->dacl->ace[j].sid)) {
+ old->dacl->ace[j] = sd->dacl->ace[i];
+ }
+ }
+ }
+ for (i=0;sd->sacl && i<sd->sacl->num_aces;i++) {
+ for (j=0;old->sacl && j<old->sacl->num_aces;j++) {
+ if (sid_equal(&sd->sacl->ace[i].sid,
+ &old->sacl->ace[j].sid)) {
+ old->sacl->ace[j] = sd->sacl->ace[i];
+ }
+ }
+ }
+ break;
+
+ case ACL_ADD:
+ for (i=0;sd->dacl && i<sd->dacl->num_aces;i++) {
+ add_ace(&old->dacl, &sd->dacl->ace[i]);
+ }
+ for (i=0;sd->sacl && i<sd->sacl->num_aces;i++) {
+ add_ace(&old->sacl, &sd->sacl->ace[i]);
+ }
+ break;
+
+ case ACL_SET:
+ free_sec_desc(&old);
+ old = sd;
+ break;
+
+ }
- if (!cli_set_secdesc(cli, fnum, sd)) {
+ if (!cli_set_secdesc(cli, fnum, old)) {
printf("ERROR: secdesc set failed\n");
return;
}
free_sec_desc(&sd);
+ free_sec_desc(&old);
cli_close(cli, fnum);
}
@@ -393,7 +473,16 @@ static void usage(void)
{
printf(
"Usage:\n\
- smbcacls //server1/share1 filename\n\n");
+ smbcacls //server1/share1 filename [options]\n\n\
+\n\
+ -D <acls> delete an acl\n\
+ -M <acls> modify an acl\n\
+ -A <acls> add an acl\n\
+ -S <acls> set acls\n\
+\n\
+ an acl is of the form SID:type/flags/mask\n\
+ you can string acls together with spaces, commas or newlines\n\
+");
}
/****************************************************************************
@@ -411,7 +500,8 @@ static void usage(void)
int seed;
static pstring servicesf = CONFIGFILE;
struct cli_state *cli;
- char *set_acl = NULL;
+ enum acl_mode mode;
+ char *acl = NULL;
setlinebuf(stdout);
@@ -444,7 +534,7 @@ static void usage(void)
seed = time(NULL);
- while ((opt = getopt(argc, argv, "U:nhS:")) != EOF) {
+ while ((opt = getopt(argc, argv, "U:nhS:D:A:M:")) != EOF) {
switch (opt) {
case 'U':
pstrcpy(username,optarg);
@@ -457,7 +547,23 @@ static void usage(void)
break;
case 'S':
- set_acl = optarg;
+ acl = optarg;
+ mode = ACL_SET;
+ break;
+
+ case 'D':
+ acl = optarg;
+ mode = ACL_DELETE;
+ break;
+
+ case 'M':
+ acl = optarg;
+ mode = ACL_MODIFY;
+ break;
+
+ case 'A':
+ acl = optarg;
+ mode = ACL_ADD;
break;
case 'n':
@@ -479,8 +585,8 @@ static void usage(void)
cli = connect_one(share);
if (!cli) exit(1);
- if (set_acl) {
- cacl_set(cli, filename, set_acl);
+ if (acl) {
+ cacl_set(cli, filename, acl, mode);
} else {
cacl_dump(cli, filename);
}