s3-utils/smbcacls.c: replace cli_query_secdesc_old()
[samba.git] / source3 / utils / smbcacls.c
index f7f12722158548cfc2f5876e6168cb900bb6ba1a..18f76c47239219ab372e02b211e38543b03f2169 100644 (file)
@@ -1,27 +1,35 @@
-/* 
+/*
    Unix SMB/CIFS implementation.
    ACL get/set utility
    Unix SMB/CIFS implementation.
    ACL get/set utility
-   
+
    Copyright (C) Andrew Tridgell 2000
    Copyright (C) Tim Potter      2000
    Copyright (C) Jeremy Allison  2000
    Copyright (C) Jelmer Vernooij 2003
    Copyright (C) Andrew Tridgell 2000
    Copyright (C) Tim Potter      2000
    Copyright (C) Jeremy Allison  2000
    Copyright (C) Jelmer Vernooij 2003
-   
+
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
-   
+
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
-   
+
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
+#include "popt_common.h"
+#include "rpc_client/cli_pipe.h"
+#include "../librpc/gen_ndr/ndr_lsa.h"
+#include "rpc_client/cli_lsarpc.h"
+#include "../libcli/security/security.h"
+#include "libsmb/libsmb.h"
+#include "libsmb/clirap.h"
+#include "passdb/machine_sid.h"
 
 static int test_args;
 
 
 static int test_args;
 
@@ -31,8 +39,10 @@ static int test_args;
    than going via LSA calls to resolve them */
 static int numeric;
 
    than going via LSA calls to resolve them */
 static int numeric;
 
+static int sddl;
+
 enum acl_mode {SMB_ACL_SET, SMB_ACL_DELETE, SMB_ACL_MODIFY, SMB_ACL_ADD };
 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 {
 enum exit_values {EXIT_OK, EXIT_FAILED, EXIT_PARSE_ERROR};
 
 struct perm_value {
@@ -62,13 +72,13 @@ static const struct perm_value standard_values[] = {
 /* Open cli connection and policy handle */
 
 static NTSTATUS cli_lsa_lookup_sid(struct cli_state *cli,
 /* Open cli connection and policy handle */
 
 static NTSTATUS cli_lsa_lookup_sid(struct cli_state *cli,
-                                  const DOM_SID *sid,
+                                  const struct dom_sid *sid,
                                   TALLOC_CTX *mem_ctx,
                                   enum lsa_SidType *type,
                                   char **domain, char **name)
 {
                                   TALLOC_CTX *mem_ctx,
                                   enum lsa_SidType *type,
                                   char **domain, char **name)
 {
-       uint16 orig_cnum = cli->cnum;
-       struct rpc_pipe_client *p;
+       uint16 orig_cnum = cli_state_get_tid(cli);
+       struct rpc_pipe_client *p = NULL;
        struct policy_handle handle;
        NTSTATUS status;
        TALLOC_CTX *frame = talloc_stackframe();
        struct policy_handle handle;
        NTSTATUS status;
        TALLOC_CTX *frame = talloc_stackframe();
@@ -76,8 +86,9 @@ static NTSTATUS cli_lsa_lookup_sid(struct cli_state *cli,
        char **domains;
        char **names;
 
        char **domains;
        char **names;
 
-       if (!cli_send_tconX(cli, "IPC$", "?????", "", 0)) {
-               return cli_nt_error(cli);
+       status = cli_tcon_andx(cli, "IPC$", "?????", "", 0);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
        }
 
        status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
        }
 
        status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
@@ -106,7 +117,7 @@ static NTSTATUS cli_lsa_lookup_sid(struct cli_state *cli,
  fail:
        TALLOC_FREE(p);
        cli_tdis(cli);
  fail:
        TALLOC_FREE(p);
        cli_tdis(cli);
-       cli->cnum = orig_cnum;
+       cli_state_set_tid(cli, orig_cnum);
        TALLOC_FREE(frame);
        return status;
 }
        TALLOC_FREE(frame);
        return status;
 }
@@ -114,18 +125,19 @@ static NTSTATUS cli_lsa_lookup_sid(struct cli_state *cli,
 static NTSTATUS cli_lsa_lookup_name(struct cli_state *cli,
                                    const char *name,
                                    enum lsa_SidType *type,
 static NTSTATUS cli_lsa_lookup_name(struct cli_state *cli,
                                    const char *name,
                                    enum lsa_SidType *type,
-                                   DOM_SID *sid)
+                                   struct dom_sid *sid)
 {
 {
-       uint16 orig_cnum = cli->cnum;
+       uint16 orig_cnum = cli_state_get_tid(cli);
        struct rpc_pipe_client *p;
        struct policy_handle handle;
        NTSTATUS status;
        TALLOC_CTX *frame = talloc_stackframe();
        struct rpc_pipe_client *p;
        struct policy_handle handle;
        NTSTATUS status;
        TALLOC_CTX *frame = talloc_stackframe();
-       DOM_SID *sids;
+       struct dom_sid *sids;
        enum lsa_SidType *types;
 
        enum lsa_SidType *types;
 
-       if (!cli_send_tconX(cli, "IPC$", "?????", "", 0)) {
-               return cli_nt_error(cli);
+       status = cli_tcon_andx(cli, "IPC$", "?????", "", 0);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
        }
 
        status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
        }
 
        status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
@@ -153,13 +165,13 @@ static NTSTATUS cli_lsa_lookup_name(struct cli_state *cli,
  fail:
        TALLOC_FREE(p);
        cli_tdis(cli);
  fail:
        TALLOC_FREE(p);
        cli_tdis(cli);
-       cli->cnum = orig_cnum;
+       cli_state_set_tid(cli, orig_cnum);
        TALLOC_FREE(frame);
        return status;
 }
 
 /* convert a SID to a string, either numeric or username/group */
        TALLOC_FREE(frame);
        return status;
 }
 
 /* convert a SID to a string, either numeric or username/group */
-static void SidToString(struct cli_state *cli, fstring str, const DOM_SID *sid)
+static void SidToString(struct cli_state *cli, fstring str, const struct dom_sid *sid)
 {
        char *domain = NULL;
        char *name = NULL;
 {
        char *domain = NULL;
        char *name = NULL;
@@ -188,12 +200,12 @@ static void SidToString(struct cli_state *cli, fstring str, const DOM_SID *sid)
 }
 
 /* convert a string to a SID, either numeric or username/group */
 }
 
 /* convert a string to a SID, either numeric or username/group */
-static bool StringToSid(struct cli_state *cli, DOM_SID *sid, const char *str)
+static bool StringToSid(struct cli_state *cli, struct dom_sid *sid, const char *str)
 {
        enum lsa_SidType type;
 
 {
        enum lsa_SidType type;
 
-       if (strncmp(str, "S-", 2) == 0) {
-               return string_to_sid(sid, str);
+       if (string_to_sid(sid, str)) {
+               return true;
        }
 
        return NT_STATUS_IS_OK(cli_lsa_lookup_name(cli, str, &type, sid));
        }
 
        return NT_STATUS_IS_OK(cli_lsa_lookup_name(cli, str, &type, sid));
@@ -260,7 +272,7 @@ static void print_ace_flags(FILE *f, uint8_t flags)
 }
 
 /* print an ACE on a FILE, using either numeric or ascii representation */
 }
 
 /* print an ACE on a FILE, using either numeric or ascii representation */
-static void print_ace(struct cli_state *cli, FILE *f, SEC_ACE *ace)
+static void print_ace(struct cli_state *cli, FILE *f, struct security_ace *ace)
 {
        const struct perm_value *v;
        fstring sidstr;
 {
        const struct perm_value *v;
        fstring sidstr;
@@ -348,7 +360,12 @@ static bool parse_ace_flags(const char *str, unsigned int *pflags)
                        return false;
                }
 
                        return false;
                }
 
-               if (*p != '|' && *p != '\0') {
+               switch (*p) {
+               case '|':
+                       p++;
+               case '\0':
+                       continue;
+               default:
                        return false;
                }
        }
                        return false;
                }
        }
@@ -356,7 +373,7 @@ static bool parse_ace_flags(const char *str, unsigned int *pflags)
 }
 
 /* parse an ACE in the same format as print_ace() */
 }
 
 /* parse an ACE in the same format as print_ace() */
-static bool parse_ace(struct cli_state *cli, SEC_ACE *ace,
+static bool parse_ace(struct cli_state *cli, struct security_ace *ace,
                      const char *orig_str)
 {
        char *p;
                      const char *orig_str)
 {
        char *p;
@@ -365,7 +382,7 @@ static bool parse_ace(struct cli_state *cli, SEC_ACE *ace,
        unsigned int atype = 0;
        unsigned int aflags = 0;
        unsigned int amask = 0;
        unsigned int atype = 0;
        unsigned int aflags = 0;
        unsigned int amask = 0;
-       DOM_SID sid;
+       struct dom_sid sid;
        uint32_t mask;
        const struct perm_value *v;
        char *str = SMB_STRDUP(orig_str);
        uint32_t mask;
        const struct perm_value *v;
        char *str = SMB_STRDUP(orig_str);
@@ -522,21 +539,22 @@ static bool parse_ace(struct cli_state *cli, SEC_ACE *ace,
        return True;
 }
 
        return True;
 }
 
-/* add an ACE to a list of ACEs in a SEC_ACL */
-static bool add_ace(SEC_ACL **the_acl, SEC_ACE *ace)
+/* add an ACE to a list of ACEs in a struct security_acl */
+static bool add_ace(struct security_acl **the_acl, struct security_ace *ace)
 {
 {
-       SEC_ACL *new_ace;
-       SEC_ACE *aces;
+       struct security_acl *new_ace;
+       struct security_ace *aces;
        if (! *the_acl) {
                return (((*the_acl) = make_sec_acl(talloc_tos(), 3, 1, ace))
                        != NULL);
        }
 
        if (! *the_acl) {
                return (((*the_acl) = make_sec_acl(talloc_tos(), 3, 1, ace))
                        != NULL);
        }
 
-       if (!(aces = SMB_CALLOC_ARRAY(SEC_ACE, 1+(*the_acl)->num_aces))) {
+       if (!(aces = SMB_CALLOC_ARRAY(struct security_ace, 1+(*the_acl)->num_aces))) {
                return False;
        }
                return False;
        }
-       memcpy(aces, (*the_acl)->aces, (*the_acl)->num_aces * sizeof(SEC_ACE));
-       memcpy(aces+(*the_acl)->num_aces, ace, sizeof(SEC_ACE));
+       memcpy(aces, (*the_acl)->aces, (*the_acl)->num_aces * sizeof(struct
+       security_ace));
+       memcpy(aces+(*the_acl)->num_aces, ace, sizeof(struct security_ace));
        new_ace = make_sec_acl(talloc_tos(),(*the_acl)->revision,1+(*the_acl)->num_aces, aces);
        SAFE_FREE(aces);
        (*the_acl) = new_ace;
        new_ace = make_sec_acl(talloc_tos(),(*the_acl)->revision,1+(*the_acl)->num_aces, aces);
        SAFE_FREE(aces);
        (*the_acl) = new_ace;
@@ -544,14 +562,14 @@ static bool add_ace(SEC_ACL **the_acl, SEC_ACE *ace)
 }
 
 /* parse a ascii version of a security descriptor */
 }
 
 /* parse a ascii version of a security descriptor */
-static SEC_DESC *sec_desc_parse(TALLOC_CTX *ctx, struct cli_state *cli, char *str)
+static struct security_descriptor *sec_desc_parse(TALLOC_CTX *ctx, struct cli_state *cli, char *str)
 {
        const char *p = str;
        char *tok;
 {
        const char *p = str;
        char *tok;
-       SEC_DESC *ret = NULL;
+       struct security_descriptor *ret = NULL;
        size_t sd_size;
        size_t sd_size;
-       DOM_SID *grp_sid=NULL, *owner_sid=NULL;
-       SEC_ACL *dacl=NULL;
+       struct dom_sid *grp_sid=NULL, *owner_sid=NULL;
+       struct security_acl *dacl=NULL;
        int revision=1;
 
        while (next_token_talloc(ctx, &p, &tok, "\t,\r\n")) {
        int revision=1;
 
        while (next_token_talloc(ctx, &p, &tok, "\t,\r\n")) {
@@ -565,7 +583,7 @@ static SEC_DESC *sec_desc_parse(TALLOC_CTX *ctx, struct cli_state *cli, char *st
                                printf("Only specify owner once\n");
                                goto done;
                        }
                                printf("Only specify owner once\n");
                                goto done;
                        }
-                       owner_sid = SMB_CALLOC_ARRAY(DOM_SID, 1);
+                       owner_sid = SMB_CALLOC_ARRAY(struct dom_sid, 1);
                        if (!owner_sid ||
                            !StringToSid(cli, owner_sid, tok+6)) {
                                printf("Failed to parse owner sid\n");
                        if (!owner_sid ||
                            !StringToSid(cli, owner_sid, tok+6)) {
                                printf("Failed to parse owner sid\n");
@@ -579,7 +597,7 @@ static SEC_DESC *sec_desc_parse(TALLOC_CTX *ctx, struct cli_state *cli, char *st
                                printf("Only specify group once\n");
                                goto done;
                        }
                                printf("Only specify group once\n");
                                goto done;
                        }
-                       grp_sid = SMB_CALLOC_ARRAY(DOM_SID, 1);
+                       grp_sid = SMB_CALLOC_ARRAY(struct dom_sid, 1);
                        if (!grp_sid ||
                            !StringToSid(cli, grp_sid, tok+6)) {
                                printf("Failed to parse group sid\n");
                        if (!grp_sid ||
                            !StringToSid(cli, grp_sid, tok+6)) {
                                printf("Failed to parse group sid\n");
@@ -589,7 +607,7 @@ static SEC_DESC *sec_desc_parse(TALLOC_CTX *ctx, struct cli_state *cli, char *st
                }
 
                if (strncmp(tok,"ACL:", 4) == 0) {
                }
 
                if (strncmp(tok,"ACL:", 4) == 0) {
-                       SEC_ACE ace;
+                       struct security_ace ace;
                        if (!parse_ace(cli, &ace, tok+4)) {
                                goto done;
                        }
                        if (!parse_ace(cli, &ace, tok+4)) {
                                goto done;
                        }
@@ -616,7 +634,7 @@ static SEC_DESC *sec_desc_parse(TALLOC_CTX *ctx, struct cli_state *cli, char *st
 
 
 /* print a ascii version of a security descriptor on a FILE handle */
 
 
 /* print a ascii version of a security descriptor on a FILE handle */
-static void sec_desc_print(struct cli_state *cli, FILE *f, SEC_DESC *sd)
+static void sec_desc_print(struct cli_state *cli, FILE *f, struct security_descriptor *sd)
 {
        fstring sidstr;
        uint32 i;
 {
        fstring sidstr;
        uint32 i;
@@ -644,7 +662,7 @@ static void sec_desc_print(struct cli_state *cli, FILE *f, SEC_DESC *sd)
 
        /* Print aces */
        for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
 
        /* Print aces */
        for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
-               SEC_ACE *ace = &sd->dacl->aces[i];
+               struct security_ace *ace = &sd->dacl->aces[i];
                fprintf(f, "ACL:");
                print_ace(cli, f, ace);
                fprintf(f, "\n");
                fprintf(f, "ACL:");
                print_ace(cli, f, ace);
                fprintf(f, "\n");
@@ -652,39 +670,125 @@ 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, const char *filename)
 {
 {
-       int result = EXIT_FAILED;
-       int fnum = -1;
-       SEC_DESC *sd;
+       uint16_t fnum = (uint16_t)-1;
+       uint16 mode = 0;
+       NTSTATUS status;
 
 
-       if (test_args) 
-               return EXIT_OK;
+       /* The desired access below is the only one I could find that works
+          with NT4, W2KP and Samba */
+
+       status = 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(status)) {
+               printf("Failed to open %s: %s\n", filename, nt_errstr(status));
+               return 0;
+       }
 
 
-       fnum = cli_nt_create(cli, filename, CREATE_ACCESS_READ);
+       status = cli_qfileinfo_basic(cli, fnum, &mode, NULL, NULL, NULL,
+                                    NULL, NULL, NULL);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("Failed to file info %s: %s\n", filename,
+                      nt_errstr(status));
+        }
 
 
-       if (fnum == -1) {
-               printf("Failed to open %s: %s\n", filename, cli_errstr(cli));
-               goto done;
+       cli_close(cli, fnum);
+
+        return mode;
+}
+
+/*****************************************************
+get sec desc for filename
+*******************************************************/
+static struct security_descriptor *get_secdesc(struct cli_state *cli, const char *filename)
+{
+       uint16_t fnum = (uint16_t)-1;
+       struct security_descriptor *sd;
+       NTSTATUS status;
+
+       /* The desired access below is the only one I could find that works
+          with NT4, W2KP and Samba */
+
+       status = 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(status)) {
+               printf("Failed to open %s: %s\n", filename, nt_errstr(status));
+               return NULL;
        }
 
        }
 
-       sd = cli_query_secdesc(cli, fnum, talloc_tos());
+       status = cli_query_secdesc(cli, fnum, talloc_tos(), &sd);
 
 
-       if (!sd) {
-               printf("ERROR: secdesc query failed: %s\n", cli_errstr(cli));
-               goto done;
+       cli_close(cli, fnum);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("Failed to get security descriptor: %s\n",
+                      nt_errstr(status));
+               return NULL;
+       }
+        return sd;
+}
+
+/*****************************************************
+set sec desc for filename
+*******************************************************/
+static bool set_secdesc(struct cli_state *cli, const char *filename,
+                        struct security_descriptor *sd)
+{
+       uint16_t fnum = (uint16_t)-1;
+        bool result=true;
+       NTSTATUS status;
+
+       /* The desired access below is the only one I could find that works
+          with NT4, W2KP and Samba */
+
+       status = cli_ntcreate(cli, filename, 0,
+                             WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS,
+                             0, FILE_SHARE_READ|FILE_SHARE_WRITE,
+                             FILE_OPEN, 0x0, 0x0, &fnum);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("Failed to open %s: %s\n", filename, nt_errstr(status));
+               return false;
        }
 
        }
 
-       sec_desc_print(cli, stdout, sd);
+       status = cli_set_secdesc(cli, fnum, sd);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf("ERROR: security description set failed: %s\n",
+                       nt_errstr(status));
+               result=false;
+       }
+
+       cli_close(cli, fnum);
+       return result;
+}
+
+/*****************************************************
+dump the acls for a file
+*******************************************************/
+static int cacl_dump(struct cli_state *cli, const char *filename)
+{
+       int result = EXIT_FAILED;
+       struct security_descriptor *sd;
 
 
-       result = EXIT_OK;
+       if (test_args)
+               return EXIT_OK;
 
 
-done:
-       if (fnum != -1)
-               cli_close(cli, fnum);
+       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;
 }
 
        return result;
 }
@@ -697,27 +801,16 @@ 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)
 {
 static int owner_set(struct cli_state *cli, enum chown_mode change_mode, 
                        const char *filename, const char *new_username)
 {
-       int fnum;
-       DOM_SID sid;
-       SEC_DESC *sd, *old;
+       struct dom_sid sid;
+       struct security_descriptor *sd, *old;
        size_t sd_size;
 
        size_t sd_size;
 
-       fnum = cli_nt_create(cli, filename, CREATE_ACCESS_READ);
-
-       if (fnum == -1) {
-               printf("Failed to open %s: %s\n", filename, cli_errstr(cli));
-               return EXIT_FAILED;
-       }
-
        if (!StringToSid(cli, &sid, new_username))
                return EXIT_PARSE_ERROR;
 
        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) {
 
        if (!old) {
-               printf("owner_set: Failed to query old descriptor\n");
                return EXIT_FAILED;
        }
 
                return EXIT_FAILED;
        }
 
@@ -726,21 +819,10 @@ static int owner_set(struct cli_state *cli, enum chown_mode change_mode,
                                (change_mode == REQUEST_CHGRP) ? &sid : NULL,
                           NULL, NULL, &sd_size);
 
                                (change_mode == REQUEST_CHGRP) ? &sid : NULL,
                           NULL, NULL, &sd_size);
 
-       fnum = cli_nt_create(cli, filename, WRITE_OWNER_ACCESS);
-
-       if (fnum == -1) {
-               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;
        }
 
                return EXIT_FAILED;
        }
 
-       cli_close(cli, fnum);
-
        return EXIT_OK;
 }
 
        return EXIT_OK;
 }
 
@@ -753,7 +835,7 @@ static int owner_set(struct cli_state *cli, enum chown_mode change_mode,
    canonical order is specified as "Explicit Deny, Explicit Allow,
    Inherited ACEs unchanged" */
 
    canonical order is specified as "Explicit Deny, Explicit Allow,
    Inherited ACEs unchanged" */
 
-static int ace_compare(SEC_ACE *ace1, SEC_ACE *ace2)
+static int ace_compare(struct security_ace *ace1, struct security_ace *ace2)
 {
        if (sec_ace_equal(ace1, ace2))
                return 0;
 {
        if (sec_ace_equal(ace1, ace2))
                return 0;
@@ -771,8 +853,8 @@ static int ace_compare(SEC_ACE *ace1, SEC_ACE *ace2)
        if (ace1->type != ace2->type)
                return ace2->type - ace1->type;
 
        if (ace1->type != ace2->type)
                return ace2->type - ace1->type;
 
-       if (sid_compare(&ace1->trustee, &ace2->trustee))
-               return sid_compare(&ace1->trustee, &ace2->trustee);
+       if (dom_sid_compare(&ace1->trustee, &ace2->trustee))
+               return dom_sid_compare(&ace1->trustee, &ace2->trustee);
 
        if (ace1->flags != ace2->flags)
                return ace1->flags - ace2->flags;
 
        if (ace1->flags != ace2->flags)
                return ace1->flags - ace2->flags;
@@ -783,15 +865,15 @@ static int ace_compare(SEC_ACE *ace1, SEC_ACE *ace2)
        if (ace1->size != ace2->size)
                return ace1->size - ace2->size;
 
        if (ace1->size != ace2->size)
                return ace1->size - ace2->size;
 
-       return memcmp(ace1, ace2, sizeof(SEC_ACE));
+       return memcmp(ace1, ace2, sizeof(struct security_ace));
 }
 
 }
 
-static void sort_acl(SEC_ACL *the_acl)
+static void sort_acl(struct security_acl *the_acl)
 {
        uint32 i;
        if (!the_acl) return;
 
 {
        uint32 i;
        if (!the_acl) return;
 
-       qsort(the_acl->aces, the_acl->num_aces, sizeof(the_acl->aces[0]), QSORT_CAST ace_compare);
+       TYPESAFE_QSORT(the_acl->aces, the_acl->num_aces, ace_compare);
 
        for (i=1;i<the_acl->num_aces;) {
                if (sec_ace_equal(&the_acl->aces[i-1], &the_acl->aces[i])) {
 
        for (i=1;i<the_acl->num_aces;) {
                if (sec_ace_equal(&the_acl->aces[i-1], &the_acl->aces[i])) {
@@ -810,39 +892,29 @@ static void sort_acl(SEC_ACL *the_acl)
 set the ACLs on a file given an ascii description
 *******************************************************/
 
 set the ACLs on a file given an ascii description
 *******************************************************/
 
-static int cacl_set(struct cli_state *cli, char *filename, 
+static int cacl_set(struct cli_state *cli, const char *filename,
                    char *the_acl, enum acl_mode mode)
 {
                    char *the_acl, enum acl_mode mode)
 {
-       int fnum;
-       SEC_DESC *sd, *old;
+       struct security_descriptor *sd, *old;
        uint32 i, j;
        size_t sd_size;
        int result = EXIT_OK;
 
        uint32 i, j;
        size_t sd_size;
        int result = EXIT_OK;
 
-       sd = sec_desc_parse(talloc_tos(), cli, the_acl);
+       if (sddl) {
+               sd = sddl_decode(talloc_tos(), the_acl, get_global_sam_sid());
+       } else {
+               sd = sec_desc_parse(talloc_tos(), cli, the_acl);
+       }
 
        if (!sd) return EXIT_PARSE_ERROR;
        if (test_args) return EXIT_OK;
 
 
        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 */
-
-       fnum = cli_nt_create(cli, filename, CREATE_ACCESS_READ);
-
-       if (fnum == -1) {
-               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) {
 
        if (!old) {
-               printf("calc_set: Failed to query old descriptor\n");
                return EXIT_FAILED;
        }
 
                return EXIT_FAILED;
        }
 
-       cli_close(cli, fnum);
-
        /* the logic here is rather more complex than I would like */
        switch (mode) {
        case SMB_ACL_DELETE:
        /* the logic here is rather more complex than I would like */
        switch (mode) {
        case SMB_ACL_DELETE:
@@ -875,7 +947,7 @@ static int cacl_set(struct cli_state *cli, char *filename,
                        bool found = False;
 
                        for (j=0;old->dacl && j<old->dacl->num_aces;j++) {
                        bool found = False;
 
                        for (j=0;old->dacl && j<old->dacl->num_aces;j++) {
-                               if (sid_equal(&sd->dacl->aces[i].trustee,
+                               if (dom_sid_equal(&sd->dacl->aces[i].trustee,
                                              &old->dacl->aces[j].trustee)) {
                                        old->dacl->aces[j] = sd->dacl->aces[i];
                                        found = True;
                                              &old->dacl->aces[j].trustee)) {
                                        old->dacl->aces[j] = sd->dacl->aces[i];
                                        found = True;
@@ -928,73 +1000,171 @@ static int cacl_set(struct cli_state *cli, char *filename,
                           old->owner_sid, old->group_sid,
                           NULL, old->dacl, &sd_size);
 
                           old->owner_sid, old->group_sid,
                           NULL, old->dacl, &sd_size);
 
-       fnum = cli_nt_create(cli, filename, WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS);
+       if (!set_secdesc(cli, filename, sd)) {
+               result = EXIT_FAILED;
+       }
+
+       return result;
+}
+
+/*****************************************************
+set the inherit on a file
+*******************************************************/
+static int inherit(struct cli_state *cli, const char *filename,
+                   const char *type)
+{
+       struct security_descriptor *old,*sd;
+       uint32 oldattr;
+       size_t sd_size;
+       int result = EXIT_OK;
+
+       old = get_secdesc(cli, filename);
 
 
-       if (fnum == -1) {
-               printf("cacl_set failed to open %s: %s\n", filename, cli_errstr(cli));
+       if (!old) {
                return EXIT_FAILED;
        }
 
                return EXIT_FAILED;
        }
 
-       if (!cli_set_secdesc(cli, fnum, sd)) {
-               printf("ERROR: secdesc set failed: %s\n", cli_errstr(cli));
-               result = EXIT_FAILED;
+        oldattr = get_fileinfo(cli,filename);
+
+       if (strcmp(type,"allow")==0) {
+               if ((old->type & SEC_DESC_DACL_PROTECTED) ==
+                    SEC_DESC_DACL_PROTECTED) {
+                       int i;
+                       char *parentname,*temp;
+                       struct security_descriptor *parent;
+                       temp = talloc_strdup(talloc_tos(), filename);
+
+                       old->type=old->type & (~SEC_DESC_DACL_PROTECTED);
+
+                       /* look at parent and copy in all its inheritable ACL's. */
+                       string_replace(temp, '\\', '/');
+                       if (!parent_dirname(talloc_tos(),temp,&parentname,NULL)) {
+                               return EXIT_FAILED;
+                       }
+                       string_replace(parentname, '/', '\\');
+                       parent = get_secdesc(cli,parentname);
+                       if (parent == NULL) {
+                               return EXIT_FAILED;
+                       }
+                       for (i=0;i<parent->dacl->num_aces;i++) {
+                               struct security_ace *ace=&parent->dacl->aces[i];
+                               /* Add inherited flag to all aces */
+                               ace->flags=ace->flags|
+                                          SEC_ACE_FLAG_INHERITED_ACE;
+                               if ((oldattr & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY) {
+                                       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) {
+                                               /* clear flags for files */
+                                               ace->flags=0;
+                                               add_ace(&old->dacl, ace);
+                                       }
+                               }
+                       }
+                } else {
+                       printf("Already set to inheritable permissions.\n");
+                       return EXIT_FAILED;
+                }
+       } else if (strcmp(type,"remove")==0) {
+               if ((old->type & SEC_DESC_DACL_PROTECTED) !=
+                    SEC_DESC_DACL_PROTECTED) {
+                       old->type=old->type | SEC_DESC_DACL_PROTECTED;
+
+                       /* remove all inherited ACL's. */
+                       if (old->dacl) {
+                               int i;
+                               struct security_acl *temp=old->dacl;
+                               old->dacl=make_sec_acl(talloc_tos(), 3, 0, NULL);
+                               for (i=temp->num_aces-1;i>=0;i--) {
+                                       struct security_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 {
+                       printf("Already set to no inheritable permissions.\n");
+                       return EXIT_FAILED;
+                }
+       } else if (strcmp(type,"copy")==0) {
+               if ((old->type & SEC_DESC_DACL_PROTECTED) !=
+                    SEC_DESC_DACL_PROTECTED) {
+                       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++) {
+                                       struct security_ace *ace=&old->dacl->aces[i];
+                                       /* Remove INHERITED FLAG from all aces */
+                                       ace->flags=ace->flags&(~SEC_ACE_FLAG_INHERITED_ACE);
+                               }
+                       }
+                } else {
+                       printf("Already set to no inheritable permissions.\n");
+                       return EXIT_FAILED;
+                }
        }
 
        }
 
-       /* Clean up */
+       /* Denied ACE entries must come before allowed ones */
+       sort_acl(old->dacl);
+
+       sd = make_sec_desc(talloc_tos(),old->revision, old->type,
+                          old->owner_sid, old->group_sid,
+                          NULL, old->dacl, &sd_size);
 
 
-       cli_close(cli, fnum);
+       if (!set_secdesc(cli, filename, sd)) {
+               result = EXIT_FAILED;
+       }
 
        return result;
 }
 
 
        return result;
 }
 
-
 /*****************************************************
  Return a connection to a server.
 *******************************************************/
 /*****************************************************
  Return a connection to a server.
 *******************************************************/
-static struct cli_state *connect_one(const char *server, const char *share)
+static struct cli_state *connect_one(struct user_auth_info *auth_info,
+                                    const char *server, const char *share)
 {
        struct cli_state *c = NULL;
 {
        struct cli_state *c = NULL;
-       struct sockaddr_storage ss;
        NTSTATUS nt_status;
        uint32_t flags = 0;
 
        NTSTATUS nt_status;
        uint32_t flags = 0;
 
-       zero_sockaddr(&ss);
-
-       if (get_cmdline_auth_info_use_kerberos()) {
+       if (get_cmdline_auth_info_use_kerberos(auth_info)) {
                flags |= CLI_FULL_CONNECTION_USE_KERBEROS |
                         CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS;
        }
 
                flags |= CLI_FULL_CONNECTION_USE_KERBEROS |
                         CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS;
        }
 
-       if (get_cmdline_auth_info_use_machine_account() &&
-           !set_cmdline_auth_info_machine_account_creds()) {
+       if (get_cmdline_auth_info_use_machine_account(auth_info) &&
+           !set_cmdline_auth_info_machine_account_creds(auth_info)) {
                return NULL;
        }
 
                return NULL;
        }
 
-       if (!get_cmdline_auth_info_got_pass()) {
-               char *pass = getpass("Password: ");
-               if (pass) {
-                       set_cmdline_auth_info_password(pass);
-               }
-       }
+       set_cmdline_auth_info_getpass(auth_info);
 
 
-       nt_status = cli_full_connection(&c, global_myname(), server, 
-                               &ss, 0,
+       nt_status = cli_full_connection(&c, lp_netbios_name(), server,
+                               NULL, 0,
                                share, "?????",
                                share, "?????",
-                               get_cmdline_auth_info_username(),
+                               get_cmdline_auth_info_username(auth_info),
                                lp_workgroup(),
                                lp_workgroup(),
-                               get_cmdline_auth_info_password(),
+                               get_cmdline_auth_info_password(auth_info),
                                flags,
                                flags,
-                               get_cmdline_auth_info_signing_state(),
-                               NULL);
+                               get_cmdline_auth_info_signing_state(auth_info));
        if (!NT_STATUS_IS_OK(nt_status)) {
                DEBUG(0,("cli_full_connection failed! (%s)\n", nt_errstr(nt_status)));
                return NULL;
        }
 
        if (!NT_STATUS_IS_OK(nt_status)) {
                DEBUG(0,("cli_full_connection failed! (%s)\n", nt_errstr(nt_status)));
                return NULL;
        }
 
-       if (get_cmdline_auth_info_smb_encrypt()) {
+       if (get_cmdline_auth_info_smb_encrypt(auth_info)) {
                nt_status = cli_cm_force_encryption(c,
                nt_status = cli_cm_force_encryption(c,
-                                       get_cmdline_auth_info_username(),
-                                       get_cmdline_auth_info_password(),
+                                       get_cmdline_auth_info_username(auth_info),
+                                       get_cmdline_auth_info_password(auth_info),
                                        lp_workgroup(),
                                        share);
                 if (!NT_STATUS_IS_OK(nt_status)) {
                                        lp_workgroup(),
                                        share);
                 if (!NT_STATUS_IS_OK(nt_status)) {
@@ -1028,7 +1198,9 @@ static struct cli_state *connect_one(const char *server, const char *share)
                { "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" },
                { "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" },
                { "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"},
                POPT_COMMON_SAMBA
                POPT_COMMON_CONNECTION
                { "test-args", 't', POPT_ARG_NONE, &test_args, 1, "Test arguments"},
                POPT_COMMON_SAMBA
                POPT_COMMON_CONNECTION
@@ -1040,21 +1212,25 @@ static struct cli_state *connect_one(const char *server, const char *share)
        TALLOC_CTX *frame = talloc_stackframe();
        const char *owner_username = "";
        char *server;
        TALLOC_CTX *frame = talloc_stackframe();
        const char *owner_username = "";
        char *server;
+       struct user_auth_info *auth_info;
 
        load_case_tables();
 
 
        load_case_tables();
 
-
        /* set default debug level to 1 regardless of what smb.conf sets */
        /* set default debug level to 1 regardless of what smb.conf sets */
-       setup_logging( "smbcacls", True );
-       DEBUGLEVEL_CLASS[DBGC_ALL] = 1;
-       dbf = x_stderr;
-       x_setbuf( x_stderr, NULL );
+       setup_logging( "smbcacls", DEBUG_STDERR);
+       lp_set_cmdline("log level", "1");
 
        setlinebuf(stdout);
 
        lp_load(get_dyn_CONFIGFILE(),True,False,False,True);
        load_interfaces();
 
 
        setlinebuf(stdout);
 
        lp_load(get_dyn_CONFIGFILE(),True,False,False,True);
        load_interfaces();
 
+       auth_info = user_auth_info_init(frame);
+       if (auth_info == NULL) {
+               exit(1);
+       }
+       popt_common_set_auth_info(auth_info);
+
        pc = poptGetContext("smbcacls", argc, argv, long_options, 0);
 
        poptSetOtherOptionHelp(pc, "//server1/share1 filename\nACLs look like: "
        pc = poptGetContext("smbcacls", argc, argv, long_options, 0);
 
        poptSetOtherOptionHelp(pc, "//server1/share1 filename\nACLs look like: "
@@ -1091,6 +1267,11 @@ static struct cli_state *connect_one(const char *server, const char *share)
                        owner_username = poptGetOptArg(pc);
                        change_mode = REQUEST_CHGRP;
                        break;
                        owner_username = poptGetOptArg(pc);
                        change_mode = REQUEST_CHGRP;
                        break;
+
+               case 'I':
+                       owner_username = poptGetOptArg(pc);
+                       change_mode = REQUEST_INHERIT;
+                       break;
                }
        }
 
                }
        }
 
@@ -1131,7 +1312,7 @@ static struct cli_state *connect_one(const char *server, const char *share)
        share++;
 
        if (!test_args) {
        share++;
 
        if (!test_args) {
-               cli = connect_one(server, share);
+               cli = connect_one(auth_info, server, share);
                if (!cli) {
                        exit(EXIT_FAILED);
                }
                if (!cli) {
                        exit(EXIT_FAILED);
                }
@@ -1151,7 +1332,9 @@ static struct cli_state *connect_one(const char *server, const char *share)
 
        /* Perform requested action */
 
 
        /* 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);
                result = owner_set(cli, change_mode, filename, owner_username);
        } else if (the_acl) {
                result = cacl_set(cli, filename, the_acl, mode);