~ubuntu-branches/ubuntu/vivid/samba/vivid

« back to all changes in this revision

Viewing changes to source3/utils/smbcacls.c

  • Committer: Package Import Robot
  • Author(s): Chuck Short
  • Date: 2011-12-21 13:18:04 UTC
  • mfrom: (0.39.21 sid)
  • Revision ID: package-import@ubuntu.com-20111221131804-xtlr39wx6njehxxr
Tags: 2:3.6.1-3ubuntu1
* Merge from Debian testing.  Remaining changes:
  + debian/patches/VERSION.patch:
    - set SAMBA_VERSION_SUFFIX to Ubuntu.
  + debian/patches/error-trans.fix-276472:
    - Add the translation of Unix Error code -ENOTSUP to NT Error Code
    - NT_STATUS_NOT_SUPPORTED to prevent the Permission denied error.
  + debian/smb.conf:
    - add "(Samba, Ubuntu)" to server string.
    - comment out the default [homes] share, and add a comment about
      "valid users = %S" to show users how to restrict access to
      \\server\username to only username.
    - Set 'usershare allow guests', so that usershare admins are 
      allowed to create public shares in addition to authenticated
      ones.
    - add map to guest = Bad user, maps bad username to guest access.
  + debian/samba-common.config:
    - Do not change priority to high if dhclient3 is installed.
    - Use priority medium instead of high for the workgroup question.
  + debian/control:
    - Don't build against or suggest ctdb.
    - Add dependency on samba-common-bin to samba.
  + Add ufw integration:
    - Created debian/samba.ufw.profile
    - debian/rules, debian/samba.dirs, debian/samba.files: install
      profile
    - debian/control: have samba suggest ufw
  + Add apport hook:
    - Created debian/source_samba.py.
    - debian/rules, debian/samba.dirs, debian/samba-common-bin.files: install
  + Switch to upstart:
    - Add debian/samba.{nmbd,smbd}.upstart.
  + debian/samba.logrotate, debian/samba-common.dhcp, debian/samba.if-up:
    - Make them upstart compatible
  + debian/samba.postinst: 
    - Avoid scary pdbedit warnings on first import.
  + debian/samba-common.postinst: Add more informative error message for
    the case where smb.conf was manually deleted
  + debian/patches/fix-debuglevel-name-conflict.patch: don't use 'debug_level'
    as a global variable name in an NSS module 
  + Dropped:
    - debian/patches/error-trans.fix-276472
    - debian/patches/fix-debuglevel-name-conflict.patch

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* 
 
1
/*
2
2
   Unix SMB/CIFS implementation.
3
3
   ACL get/set utility
4
 
   
 
4
 
5
5
   Copyright (C) Andrew Tridgell 2000
6
6
   Copyright (C) Tim Potter      2000
7
7
   Copyright (C) Jeremy Allison  2000
8
8
   Copyright (C) Jelmer Vernooij 2003
9
 
   
 
9
 
10
10
   This program is free software; you can redistribute it and/or modify
11
11
   it under the terms of the GNU General Public License as published by
12
12
   the Free Software Foundation; either version 3 of the License, or
13
13
   (at your option) any later version.
14
 
   
 
14
 
15
15
   This program is distributed in the hope that it will be useful,
16
16
   but WITHOUT ANY WARRANTY; without even the implied warranty of
17
17
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
18
   GNU General Public License for more details.
19
 
   
 
19
 
20
20
   You should have received a copy of the GNU General Public License
21
21
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
22
22
*/
23
23
 
24
24
#include "includes.h"
25
 
 
26
 
extern bool AllowDebugChange;
 
25
#include "popt_common.h"
 
26
#include "rpc_client/cli_pipe.h"
 
27
#include "../librpc/gen_ndr/ndr_lsa.h"
 
28
#include "rpc_client/cli_lsarpc.h"
 
29
#include "../libcli/security/security.h"
 
30
#include "libsmb/libsmb.h"
 
31
#include "libsmb/clirap.h"
 
32
#include "passdb/machine_sid.h"
27
33
 
28
34
static int test_args;
29
35
 
33
39
   than going via LSA calls to resolve them */
34
40
static int numeric;
35
41
 
 
42
static int sddl;
 
43
 
36
44
enum acl_mode {SMB_ACL_SET, SMB_ACL_DELETE, SMB_ACL_MODIFY, SMB_ACL_ADD };
37
 
enum chown_mode {REQUEST_NONE, REQUEST_CHOWN, REQUEST_CHGRP};
 
45
enum chown_mode {REQUEST_NONE, REQUEST_CHOWN, REQUEST_CHGRP, REQUEST_INHERIT};
38
46
enum exit_values {EXIT_OK, EXIT_FAILED, EXIT_PARSE_ERROR};
39
47
 
40
48
struct perm_value {
64
72
/* Open cli connection and policy handle */
65
73
 
66
74
static NTSTATUS cli_lsa_lookup_sid(struct cli_state *cli,
67
 
                                   const DOM_SID *sid,
 
75
                                   const struct dom_sid *sid,
68
76
                                   TALLOC_CTX *mem_ctx,
69
77
                                   enum lsa_SidType *type,
70
78
                                   char **domain, char **name)
117
125
static NTSTATUS cli_lsa_lookup_name(struct cli_state *cli,
118
126
                                    const char *name,
119
127
                                    enum lsa_SidType *type,
120
 
                                    DOM_SID *sid)
 
128
                                    struct dom_sid *sid)
121
129
{
122
130
        uint16 orig_cnum = cli->cnum;
123
131
        struct rpc_pipe_client *p;
124
132
        struct policy_handle handle;
125
133
        NTSTATUS status;
126
134
        TALLOC_CTX *frame = talloc_stackframe();
127
 
        DOM_SID *sids;
 
135
        struct dom_sid *sids;
128
136
        enum lsa_SidType *types;
129
137
 
130
138
        status = cli_tcon_andx(cli, "IPC$", "?????", "", 0);
163
171
}
164
172
 
165
173
/* convert a SID to a string, either numeric or username/group */
166
 
static void SidToString(struct cli_state *cli, fstring str, const DOM_SID *sid)
 
174
static void SidToString(struct cli_state *cli, fstring str, const struct dom_sid *sid)
167
175
{
168
176
        char *domain = NULL;
169
177
        char *name = NULL;
192
200
}
193
201
 
194
202
/* convert a string to a SID, either numeric or username/group */
195
 
static bool StringToSid(struct cli_state *cli, DOM_SID *sid, const char *str)
 
203
static bool StringToSid(struct cli_state *cli, struct dom_sid *sid, const char *str)
196
204
{
197
205
        enum lsa_SidType type;
198
206
 
199
 
        if (strncmp(str, "S-", 2) == 0) {
200
 
                return string_to_sid(sid, str);
 
207
        if (string_to_sid(sid, str)) {
 
208
                return true;
201
209
        }
202
210
 
203
211
        return NT_STATUS_IS_OK(cli_lsa_lookup_name(cli, str, &type, sid));
264
272
}
265
273
 
266
274
/* print an ACE on a FILE, using either numeric or ascii representation */
267
 
static void print_ace(struct cli_state *cli, FILE *f, SEC_ACE *ace)
 
275
static void print_ace(struct cli_state *cli, FILE *f, struct security_ace *ace)
268
276
{
269
277
        const struct perm_value *v;
270
278
        fstring sidstr;
352
360
                        return false;
353
361
                }
354
362
 
355
 
                if (*p != '|' && *p != '\0') {
 
363
                switch (*p) {
 
364
                case '|':
 
365
                        p++;
 
366
                case '\0':
 
367
                        continue;
 
368
                default:
356
369
                        return false;
357
370
                }
358
371
        }
360
373
}
361
374
 
362
375
/* parse an ACE in the same format as print_ace() */
363
 
static bool parse_ace(struct cli_state *cli, SEC_ACE *ace,
 
376
static bool parse_ace(struct cli_state *cli, struct security_ace *ace,
364
377
                      const char *orig_str)
365
378
{
366
379
        char *p;
369
382
        unsigned int atype = 0;
370
383
        unsigned int aflags = 0;
371
384
        unsigned int amask = 0;
372
 
        DOM_SID sid;
 
385
        struct dom_sid sid;
373
386
        uint32_t mask;
374
387
        const struct perm_value *v;
375
388
        char *str = SMB_STRDUP(orig_str);
526
539
        return True;
527
540
}
528
541
 
529
 
/* add an ACE to a list of ACEs in a SEC_ACL */
530
 
static bool add_ace(SEC_ACL **the_acl, SEC_ACE *ace)
 
542
/* add an ACE to a list of ACEs in a struct security_acl */
 
543
static bool add_ace(struct security_acl **the_acl, struct security_ace *ace)
531
544
{
532
 
        SEC_ACL *new_ace;
533
 
        SEC_ACE *aces;
 
545
        struct security_acl *new_ace;
 
546
        struct security_ace *aces;
534
547
        if (! *the_acl) {
535
548
                return (((*the_acl) = make_sec_acl(talloc_tos(), 3, 1, ace))
536
549
                        != NULL);
537
550
        }
538
551
 
539
 
        if (!(aces = SMB_CALLOC_ARRAY(SEC_ACE, 1+(*the_acl)->num_aces))) {
 
552
        if (!(aces = SMB_CALLOC_ARRAY(struct security_ace, 1+(*the_acl)->num_aces))) {
540
553
                return False;
541
554
        }
542
 
        memcpy(aces, (*the_acl)->aces, (*the_acl)->num_aces * sizeof(SEC_ACE));
543
 
        memcpy(aces+(*the_acl)->num_aces, ace, sizeof(SEC_ACE));
 
555
        memcpy(aces, (*the_acl)->aces, (*the_acl)->num_aces * sizeof(struct
 
556
        security_ace));
 
557
        memcpy(aces+(*the_acl)->num_aces, ace, sizeof(struct security_ace));
544
558
        new_ace = make_sec_acl(talloc_tos(),(*the_acl)->revision,1+(*the_acl)->num_aces, aces);
545
559
        SAFE_FREE(aces);
546
560
        (*the_acl) = new_ace;
548
562
}
549
563
 
550
564
/* parse a ascii version of a security descriptor */
551
 
static SEC_DESC *sec_desc_parse(TALLOC_CTX *ctx, struct cli_state *cli, char *str)
 
565
static struct security_descriptor *sec_desc_parse(TALLOC_CTX *ctx, struct cli_state *cli, char *str)
552
566
{
553
567
        const char *p = str;
554
568
        char *tok;
555
 
        SEC_DESC *ret = NULL;
 
569
        struct security_descriptor *ret = NULL;
556
570
        size_t sd_size;
557
 
        DOM_SID *grp_sid=NULL, *owner_sid=NULL;
558
 
        SEC_ACL *dacl=NULL;
 
571
        struct dom_sid *grp_sid=NULL, *owner_sid=NULL;
 
572
        struct security_acl *dacl=NULL;
559
573
        int revision=1;
560
574
 
561
575
        while (next_token_talloc(ctx, &p, &tok, "\t,\r\n")) {
569
583
                                printf("Only specify owner once\n");
570
584
                                goto done;
571
585
                        }
572
 
                        owner_sid = SMB_CALLOC_ARRAY(DOM_SID, 1);
 
586
                        owner_sid = SMB_CALLOC_ARRAY(struct dom_sid, 1);
573
587
                        if (!owner_sid ||
574
588
                            !StringToSid(cli, owner_sid, tok+6)) {
575
589
                                printf("Failed to parse owner sid\n");
583
597
                                printf("Only specify group once\n");
584
598
                                goto done;
585
599
                        }
586
 
                        grp_sid = SMB_CALLOC_ARRAY(DOM_SID, 1);
 
600
                        grp_sid = SMB_CALLOC_ARRAY(struct dom_sid, 1);
587
601
                        if (!grp_sid ||
588
602
                            !StringToSid(cli, grp_sid, tok+6)) {
589
603
                                printf("Failed to parse group sid\n");
593
607
                }
594
608
 
595
609
                if (strncmp(tok,"ACL:", 4) == 0) {
596
 
                        SEC_ACE ace;
 
610
                        struct security_ace ace;
597
611
                        if (!parse_ace(cli, &ace, tok+4)) {
598
612
                                goto done;
599
613
                        }
620
634
 
621
635
 
622
636
/* print a ascii version of a security descriptor on a FILE handle */
623
 
static void sec_desc_print(struct cli_state *cli, FILE *f, SEC_DESC *sd)
 
637
static void sec_desc_print(struct cli_state *cli, FILE *f, struct security_descriptor *sd)
624
638
{
625
639
        fstring sidstr;
626
640
        uint32 i;
648
662
 
649
663
        /* Print aces */
650
664
        for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
651
 
                SEC_ACE *ace = &sd->dacl->aces[i];
 
665
                struct security_ace *ace = &sd->dacl->aces[i];
652
666
                fprintf(f, "ACL:");
653
667
                print_ace(cli, f, ace);
654
668
                fprintf(f, "\n");
656
670
 
657
671
}
658
672
 
659
 
/***************************************************** 
 
673
/*****************************************************
 
674
get fileinfo for filename
 
675
*******************************************************/
 
676
static uint16 get_fileinfo(struct cli_state *cli, const char *filename)
 
677
{
 
678
        uint16_t fnum = (uint16_t)-1;
 
679
        uint16 mode = 0;
 
680
        NTSTATUS status;
 
681
 
 
682
        /* The desired access below is the only one I could find that works
 
683
           with NT4, W2KP and Samba */
 
684
 
 
685
        status = cli_ntcreate(cli, filename, 0, CREATE_ACCESS_READ,
 
686
                              0, FILE_SHARE_READ|FILE_SHARE_WRITE,
 
687
                              FILE_OPEN, 0x0, 0x0, &fnum);
 
688
        if (!NT_STATUS_IS_OK(status)) {
 
689
                printf("Failed to open %s: %s\n", filename, nt_errstr(status));
 
690
                return 0;
 
691
        }
 
692
 
 
693
        status = cli_qfileinfo_basic(cli, fnum, &mode, NULL, NULL, NULL,
 
694
                                     NULL, NULL, NULL);
 
695
        if (!NT_STATUS_IS_OK(status)) {
 
696
                printf("Failed to file info %s: %s\n", filename,
 
697
                       nt_errstr(status));
 
698
        }
 
699
 
 
700
        cli_close(cli, fnum);
 
701
 
 
702
        return mode;
 
703
}
 
704
 
 
705
/*****************************************************
 
706
get sec desc for filename
 
707
*******************************************************/
 
708
static struct security_descriptor *get_secdesc(struct cli_state *cli, const char *filename)
 
709
{
 
710
        uint16_t fnum = (uint16_t)-1;
 
711
        struct security_descriptor *sd;
 
712
        NTSTATUS status;
 
713
 
 
714
        /* The desired access below is the only one I could find that works
 
715
           with NT4, W2KP and Samba */
 
716
 
 
717
        status = cli_ntcreate(cli, filename, 0, CREATE_ACCESS_READ,
 
718
                              0, FILE_SHARE_READ|FILE_SHARE_WRITE,
 
719
                              FILE_OPEN, 0x0, 0x0, &fnum);
 
720
        if (!NT_STATUS_IS_OK(status)) {
 
721
                printf("Failed to open %s: %s\n", filename, nt_errstr(status));
 
722
                return NULL;
 
723
        }
 
724
 
 
725
        sd = cli_query_secdesc(cli, fnum, talloc_tos());
 
726
 
 
727
        cli_close(cli, fnum);
 
728
 
 
729
        if (!sd) {
 
730
                printf("Failed to get security descriptor\n");
 
731
                return NULL;
 
732
        }
 
733
        return sd;
 
734
}
 
735
 
 
736
/*****************************************************
 
737
set sec desc for filename
 
738
*******************************************************/
 
739
static bool set_secdesc(struct cli_state *cli, const char *filename,
 
740
                        struct security_descriptor *sd)
 
741
{
 
742
        uint16_t fnum = (uint16_t)-1;
 
743
        bool result=true;
 
744
        NTSTATUS status;
 
745
 
 
746
        /* The desired access below is the only one I could find that works
 
747
           with NT4, W2KP and Samba */
 
748
 
 
749
        status = cli_ntcreate(cli, filename, 0,
 
750
                              WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS,
 
751
                              0, FILE_SHARE_READ|FILE_SHARE_WRITE,
 
752
                              FILE_OPEN, 0x0, 0x0, &fnum);
 
753
        if (!NT_STATUS_IS_OK(status)) {
 
754
                printf("Failed to open %s: %s\n", filename, nt_errstr(status));
 
755
                return false;
 
756
        }
 
757
 
 
758
        status = cli_set_secdesc(cli, fnum, sd);
 
759
        if (!NT_STATUS_IS_OK(status)) {
 
760
                printf("ERROR: security description set failed: %s\n",
 
761
                       nt_errstr(status));
 
762
                result=false;
 
763
        }
 
764
 
 
765
        cli_close(cli, fnum);
 
766
        return result;
 
767
}
 
768
 
 
769
/*****************************************************
660
770
dump the acls for a file
661
771
*******************************************************/
662
 
static int cacl_dump(struct cli_state *cli, char *filename)
 
772
static int cacl_dump(struct cli_state *cli, const char *filename)
663
773
{
664
774
        int result = EXIT_FAILED;
665
 
        uint16_t fnum = (uint16_t)-1;
666
 
        SEC_DESC *sd;
 
775
        struct security_descriptor *sd;
667
776
 
668
 
        if (test_args) 
 
777
        if (test_args)
669
778
                return EXIT_OK;
670
779
 
671
 
        if (!NT_STATUS_IS_OK(cli_ntcreate(cli, filename, 0, CREATE_ACCESS_READ, 0,
672
 
                                FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0x0, 0x0, &fnum))) {
673
 
                printf("Failed to open %s: %s\n", filename, cli_errstr(cli));
674
 
                goto done;
675
 
        }
676
 
 
677
 
        sd = cli_query_secdesc(cli, fnum, talloc_tos());
678
 
 
679
 
        if (!sd) {
680
 
                printf("ERROR: secdesc query failed: %s\n", cli_errstr(cli));
681
 
                goto done;
682
 
        }
683
 
 
684
 
        sec_desc_print(cli, stdout, sd);
685
 
 
686
 
        result = EXIT_OK;
687
 
 
688
 
done:
689
 
        if (fnum != (uint16_t)-1)
690
 
                cli_close(cli, fnum);
 
780
        sd = get_secdesc(cli, filename);
 
781
 
 
782
        if (sd) {
 
783
                if (sddl) {
 
784
                        printf("%s\n", sddl_encode(talloc_tos(), sd,
 
785
                                           get_global_sam_sid()));
 
786
                } else {
 
787
                        sec_desc_print(cli, stdout, sd);
 
788
                }
 
789
                result = EXIT_OK;
 
790
        }
691
791
 
692
792
        return result;
693
793
}
700
800
static int owner_set(struct cli_state *cli, enum chown_mode change_mode, 
701
801
                        const char *filename, const char *new_username)
702
802
{
703
 
        uint16_t fnum;
704
 
        DOM_SID sid;
705
 
        SEC_DESC *sd, *old;
 
803
        struct dom_sid sid;
 
804
        struct security_descriptor *sd, *old;
706
805
        size_t sd_size;
707
806
 
708
 
        if (!NT_STATUS_IS_OK(cli_ntcreate(cli, filename, 0, CREATE_ACCESS_READ, 0,
709
 
                                FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0x0, 0x0, &fnum))) {
710
 
                printf("Failed to open %s: %s\n", filename, cli_errstr(cli));
711
 
                return EXIT_FAILED;
712
 
        }
713
 
 
714
807
        if (!StringToSid(cli, &sid, new_username))
715
808
                return EXIT_PARSE_ERROR;
716
809
 
717
 
        old = cli_query_secdesc(cli, fnum, talloc_tos());
718
 
 
719
 
        cli_close(cli, fnum);
 
810
        old = get_secdesc(cli, filename);
720
811
 
721
812
        if (!old) {
722
 
                printf("owner_set: Failed to query old descriptor\n");
723
813
                return EXIT_FAILED;
724
814
        }
725
815
 
728
818
                                (change_mode == REQUEST_CHGRP) ? &sid : NULL,
729
819
                           NULL, NULL, &sd_size);
730
820
 
731
 
        if (!NT_STATUS_IS_OK(cli_ntcreate(cli, filename, 0, WRITE_OWNER_ACCESS, 0,
732
 
                        FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0x0, 0x0, &fnum))) {
733
 
                printf("Failed to open %s: %s\n", filename, cli_errstr(cli));
734
 
                return EXIT_FAILED;
735
 
        }
736
 
 
737
 
        if (!cli_set_secdesc(cli, fnum, sd)) {
738
 
                printf("ERROR: secdesc set failed: %s\n", cli_errstr(cli));
739
 
                cli_close(cli, fnum);
740
 
                return EXIT_FAILED;
741
 
        }
742
 
 
743
 
        cli_close(cli, fnum);
 
821
        if (!set_secdesc(cli, filename, sd)) {
 
822
                return EXIT_FAILED;
 
823
        }
744
824
 
745
825
        return EXIT_OK;
746
826
}
754
834
   canonical order is specified as "Explicit Deny, Explicit Allow,
755
835
   Inherited ACEs unchanged" */
756
836
 
757
 
static int ace_compare(SEC_ACE *ace1, SEC_ACE *ace2)
 
837
static int ace_compare(struct security_ace *ace1, struct security_ace *ace2)
758
838
{
759
839
        if (sec_ace_equal(ace1, ace2))
760
840
                return 0;
772
852
        if (ace1->type != ace2->type)
773
853
                return ace2->type - ace1->type;
774
854
 
775
 
        if (sid_compare(&ace1->trustee, &ace2->trustee))
776
 
                return sid_compare(&ace1->trustee, &ace2->trustee);
 
855
        if (dom_sid_compare(&ace1->trustee, &ace2->trustee))
 
856
                return dom_sid_compare(&ace1->trustee, &ace2->trustee);
777
857
 
778
858
        if (ace1->flags != ace2->flags)
779
859
                return ace1->flags - ace2->flags;
784
864
        if (ace1->size != ace2->size)
785
865
                return ace1->size - ace2->size;
786
866
 
787
 
        return memcmp(ace1, ace2, sizeof(SEC_ACE));
 
867
        return memcmp(ace1, ace2, sizeof(struct security_ace));
788
868
}
789
869
 
790
 
static void sort_acl(SEC_ACL *the_acl)
 
870
static void sort_acl(struct security_acl *the_acl)
791
871
{
792
872
        uint32 i;
793
873
        if (!the_acl) return;
794
874
 
795
 
        qsort(the_acl->aces, the_acl->num_aces, sizeof(the_acl->aces[0]), QSORT_CAST ace_compare);
 
875
        TYPESAFE_QSORT(the_acl->aces, the_acl->num_aces, ace_compare);
796
876
 
797
877
        for (i=1;i<the_acl->num_aces;) {
798
878
                if (sec_ace_equal(&the_acl->aces[i-1], &the_acl->aces[i])) {
811
891
set the ACLs on a file given an ascii description
812
892
*******************************************************/
813
893
 
814
 
static int cacl_set(struct cli_state *cli, char *filename, 
 
894
static int cacl_set(struct cli_state *cli, const char *filename,
815
895
                    char *the_acl, enum acl_mode mode)
816
896
{
817
 
        uint16_t fnum;
818
 
        SEC_DESC *sd, *old;
 
897
        struct security_descriptor *sd, *old;
819
898
        uint32 i, j;
820
899
        size_t sd_size;
821
900
        int result = EXIT_OK;
822
901
 
823
 
        sd = sec_desc_parse(talloc_tos(), cli, the_acl);
 
902
        if (sddl) {
 
903
                sd = sddl_decode(talloc_tos(), the_acl, get_global_sam_sid());
 
904
        } else {
 
905
                sd = sec_desc_parse(talloc_tos(), cli, the_acl);
 
906
        }
824
907
 
825
908
        if (!sd) return EXIT_PARSE_ERROR;
826
909
        if (test_args) return EXIT_OK;
827
910
 
828
 
        /* The desired access below is the only one I could find that works
829
 
           with NT4, W2KP and Samba */
830
 
 
831
 
        if (!NT_STATUS_IS_OK(cli_ntcreate(cli, filename, 0, CREATE_ACCESS_READ, 0,
832
 
                                FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0x0, 0x0, &fnum))) {
833
 
                printf("cacl_set failed to open %s: %s\n", filename, cli_errstr(cli));
834
 
                return EXIT_FAILED;
835
 
        }
836
 
 
837
 
        old = cli_query_secdesc(cli, fnum, talloc_tos());
 
911
        old = get_secdesc(cli, filename);
838
912
 
839
913
        if (!old) {
840
 
                printf("calc_set: Failed to query old descriptor\n");
841
914
                return EXIT_FAILED;
842
915
        }
843
916
 
844
 
        cli_close(cli, fnum);
845
 
 
846
917
        /* the logic here is rather more complex than I would like */
847
918
        switch (mode) {
848
919
        case SMB_ACL_DELETE:
875
946
                        bool found = False;
876
947
 
877
948
                        for (j=0;old->dacl && j<old->dacl->num_aces;j++) {
878
 
                                if (sid_equal(&sd->dacl->aces[i].trustee,
 
949
                                if (dom_sid_equal(&sd->dacl->aces[i].trustee,
879
950
                                              &old->dacl->aces[j].trustee)) {
880
951
                                        old->dacl->aces[j] = sd->dacl->aces[i];
881
952
                                        found = True;
928
999
                           old->owner_sid, old->group_sid,
929
1000
                           NULL, old->dacl, &sd_size);
930
1001
 
931
 
        if (!NT_STATUS_IS_OK(cli_ntcreate(cli, filename, 0, WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS, 0,
932
 
                        FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0x0, 0x0, &fnum))) {
933
 
                printf("cacl_set failed to open %s: %s\n", filename, cli_errstr(cli));
 
1002
        if (!set_secdesc(cli, filename, sd)) {
 
1003
                result = EXIT_FAILED;
 
1004
        }
 
1005
 
 
1006
        return result;
 
1007
}
 
1008
 
 
1009
/*****************************************************
 
1010
set the inherit on a file
 
1011
*******************************************************/
 
1012
static int inherit(struct cli_state *cli, const char *filename,
 
1013
                   const char *type)
 
1014
{
 
1015
        struct security_descriptor *old,*sd;
 
1016
        uint32 oldattr;
 
1017
        size_t sd_size;
 
1018
        int result = EXIT_OK;
 
1019
 
 
1020
        old = get_secdesc(cli, filename);
 
1021
 
 
1022
        if (!old) {
934
1023
                return EXIT_FAILED;
935
1024
        }
936
1025
 
937
 
        if (!cli_set_secdesc(cli, fnum, sd)) {
938
 
                printf("ERROR: secdesc set failed: %s\n", cli_errstr(cli));
 
1026
        oldattr = get_fileinfo(cli,filename);
 
1027
 
 
1028
        if (strcmp(type,"allow")==0) {
 
1029
                if ((old->type & SEC_DESC_DACL_PROTECTED) ==
 
1030
                    SEC_DESC_DACL_PROTECTED) {
 
1031
                        int i;
 
1032
                        char *parentname,*temp;
 
1033
                        struct security_descriptor *parent;
 
1034
                        temp = talloc_strdup(talloc_tos(), filename);
 
1035
 
 
1036
                        old->type=old->type & (~SEC_DESC_DACL_PROTECTED);
 
1037
 
 
1038
                        /* look at parent and copy in all its inheritable ACL's. */
 
1039
                        string_replace(temp, '\\', '/');
 
1040
                        if (!parent_dirname(talloc_tos(),temp,&parentname,NULL)) {
 
1041
                                return EXIT_FAILED;
 
1042
                        }
 
1043
                        string_replace(parentname, '/', '\\');
 
1044
                        parent = get_secdesc(cli,parentname);
 
1045
                        if (parent == NULL) {
 
1046
                                return EXIT_FAILED;
 
1047
                        }
 
1048
                        for (i=0;i<parent->dacl->num_aces;i++) {
 
1049
                                struct security_ace *ace=&parent->dacl->aces[i];
 
1050
                                /* Add inherited flag to all aces */
 
1051
                                ace->flags=ace->flags|
 
1052
                                           SEC_ACE_FLAG_INHERITED_ACE;
 
1053
                                if ((oldattr & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY) {
 
1054
                                        if ((ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) ==
 
1055
                                            SEC_ACE_FLAG_CONTAINER_INHERIT) {
 
1056
                                                add_ace(&old->dacl, ace);
 
1057
                                        }
 
1058
                                } else {
 
1059
                                        if ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) ==
 
1060
                                            SEC_ACE_FLAG_OBJECT_INHERIT) {
 
1061
                                                /* clear flags for files */
 
1062
                                                ace->flags=0;
 
1063
                                                add_ace(&old->dacl, ace);
 
1064
                                        }
 
1065
                                }
 
1066
                        }
 
1067
                } else {
 
1068
                        printf("Already set to inheritable permissions.\n");
 
1069
                        return EXIT_FAILED;
 
1070
                }
 
1071
        } else if (strcmp(type,"remove")==0) {
 
1072
                if ((old->type & SEC_DESC_DACL_PROTECTED) !=
 
1073
                    SEC_DESC_DACL_PROTECTED) {
 
1074
                        old->type=old->type | SEC_DESC_DACL_PROTECTED;
 
1075
 
 
1076
                        /* remove all inherited ACL's. */
 
1077
                        if (old->dacl) {
 
1078
                                int i;
 
1079
                                struct security_acl *temp=old->dacl;
 
1080
                                old->dacl=make_sec_acl(talloc_tos(), 3, 0, NULL);
 
1081
                                for (i=temp->num_aces-1;i>=0;i--) {
 
1082
                                        struct security_ace *ace=&temp->aces[i];
 
1083
                                        /* Remove all ace with INHERITED flag set */
 
1084
                                        if ((ace->flags & SEC_ACE_FLAG_INHERITED_ACE) !=
 
1085
                                            SEC_ACE_FLAG_INHERITED_ACE) {
 
1086
                                                add_ace(&old->dacl,ace);
 
1087
                                        }
 
1088
                                }
 
1089
                        }
 
1090
                } else {
 
1091
                        printf("Already set to no inheritable permissions.\n");
 
1092
                        return EXIT_FAILED;
 
1093
                }
 
1094
        } else if (strcmp(type,"copy")==0) {
 
1095
                if ((old->type & SEC_DESC_DACL_PROTECTED) !=
 
1096
                    SEC_DESC_DACL_PROTECTED) {
 
1097
                        old->type=old->type | SEC_DESC_DACL_PROTECTED;
 
1098
 
 
1099
                        /* convert all inherited ACL's to non inherated ACL's. */
 
1100
                        if (old->dacl) {
 
1101
                                int i;
 
1102
                                for (i=0;i<old->dacl->num_aces;i++) {
 
1103
                                        struct security_ace *ace=&old->dacl->aces[i];
 
1104
                                        /* Remove INHERITED FLAG from all aces */
 
1105
                                        ace->flags=ace->flags&(~SEC_ACE_FLAG_INHERITED_ACE);
 
1106
                                }
 
1107
                        }
 
1108
                } else {
 
1109
                        printf("Already set to no inheritable permissions.\n");
 
1110
                        return EXIT_FAILED;
 
1111
                }
 
1112
        }
 
1113
 
 
1114
        /* Denied ACE entries must come before allowed ones */
 
1115
        sort_acl(old->dacl);
 
1116
 
 
1117
        sd = make_sec_desc(talloc_tos(),old->revision, old->type,
 
1118
                           old->owner_sid, old->group_sid,
 
1119
                           NULL, old->dacl, &sd_size);
 
1120
 
 
1121
        if (!set_secdesc(cli, filename, sd)) {
939
1122
                result = EXIT_FAILED;
940
1123
        }
941
1124
 
942
 
        /* Clean up */
943
 
 
944
 
        cli_close(cli, fnum);
945
 
 
946
1125
        return result;
947
1126
}
948
1127
 
949
 
 
950
1128
/*****************************************************
951
1129
 Return a connection to a server.
952
1130
*******************************************************/
979
1157
                                lp_workgroup(),
980
1158
                                get_cmdline_auth_info_password(auth_info),
981
1159
                                flags,
982
 
                                get_cmdline_auth_info_signing_state(auth_info),
983
 
                                NULL);
 
1160
                                get_cmdline_auth_info_signing_state(auth_info));
984
1161
        if (!NT_STATUS_IS_OK(nt_status)) {
985
1162
                DEBUG(0,("cli_full_connection failed! (%s)\n", nt_errstr(nt_status)));
986
1163
                return NULL;
1023
1200
                { "set", 'S', POPT_ARG_STRING, NULL, 'S', "Set acls", "ACLS" },
1024
1201
                { "chown", 'C', POPT_ARG_STRING, NULL, 'C', "Change ownership of a file", "USERNAME" },
1025
1202
                { "chgrp", 'G', POPT_ARG_STRING, NULL, 'G', "Change group ownership of a file", "GROUPNAME" },
 
1203
                { "inherit", 'I', POPT_ARG_STRING, NULL, 'I', "Inherit allow|remove|copy" },
1026
1204
                { "numeric", 0, POPT_ARG_NONE, &numeric, 1, "Don't resolve sids or masks to names" },
 
1205
                { "sddl", 0, POPT_ARG_NONE, &sddl, 1, "Output and input acls in sddl format" },
1027
1206
                { "test-args", 't', POPT_ARG_NONE, &test_args, 1, "Test arguments"},
1028
1207
                POPT_COMMON_SAMBA
1029
1208
                POPT_COMMON_CONNECTION
1039
1218
 
1040
1219
        load_case_tables();
1041
1220
 
1042
 
 
1043
1221
        /* set default debug level to 1 regardless of what smb.conf sets */
1044
 
        setup_logging( "smbcacls", True );
1045
 
        DEBUGLEVEL_CLASS[DBGC_ALL] = 1;
1046
 
        dbf = x_stderr;
1047
 
        x_setbuf( x_stderr, NULL );
1048
 
        AllowDebugChange = false;
 
1222
        setup_logging( "smbcacls", DEBUG_STDERR);
 
1223
        lp_set_cmdline("log level", "1");
1049
1224
 
1050
1225
        setlinebuf(stdout);
1051
1226
 
1094
1269
                        owner_username = poptGetOptArg(pc);
1095
1270
                        change_mode = REQUEST_CHGRP;
1096
1271
                        break;
 
1272
 
 
1273
                case 'I':
 
1274
                        owner_username = poptGetOptArg(pc);
 
1275
                        change_mode = REQUEST_INHERIT;
 
1276
                        break;
1097
1277
                }
1098
1278
        }
1099
1279
 
1154
1334
 
1155
1335
        /* Perform requested action */
1156
1336
 
1157
 
        if (change_mode != REQUEST_NONE) {
 
1337
        if (change_mode == REQUEST_INHERIT) {
 
1338
                result = inherit(cli, filename, owner_username);
 
1339
        } else if (change_mode != REQUEST_NONE) {
1158
1340
                result = owner_set(cli, change_mode, filename, owner_username);
1159
1341
        } else if (the_acl) {
1160
1342
                result = cacl_set(cli, filename, the_acl, mode);