2
2
Unix SMB/CIFS implementation.
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
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.
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.
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/>.
24
24
#include "includes.h"
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"
28
34
static int test_args;
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)
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))
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))) {
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
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);
546
560
(*the_acl) = new_ace;
659
/*****************************************************
673
/*****************************************************
674
get fileinfo for filename
675
*******************************************************/
676
static uint16 get_fileinfo(struct cli_state *cli, const char *filename)
678
uint16_t fnum = (uint16_t)-1;
682
/* The desired access below is the only one I could find that works
683
with NT4, W2KP and Samba */
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));
693
status = cli_qfileinfo_basic(cli, fnum, &mode, NULL, NULL, NULL,
695
if (!NT_STATUS_IS_OK(status)) {
696
printf("Failed to file info %s: %s\n", filename,
700
cli_close(cli, fnum);
705
/*****************************************************
706
get sec desc for filename
707
*******************************************************/
708
static struct security_descriptor *get_secdesc(struct cli_state *cli, const char *filename)
710
uint16_t fnum = (uint16_t)-1;
711
struct security_descriptor *sd;
714
/* The desired access below is the only one I could find that works
715
with NT4, W2KP and Samba */
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));
725
sd = cli_query_secdesc(cli, fnum, talloc_tos());
727
cli_close(cli, fnum);
730
printf("Failed to get security descriptor\n");
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)
742
uint16_t fnum = (uint16_t)-1;
746
/* The desired access below is the only one I could find that works
747
with NT4, W2KP and Samba */
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));
758
status = cli_set_secdesc(cli, fnum, sd);
759
if (!NT_STATUS_IS_OK(status)) {
760
printf("ERROR: security description set failed: %s\n",
765
cli_close(cli, fnum);
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)
664
774
int result = EXIT_FAILED;
665
uint16_t fnum = (uint16_t)-1;
775
struct security_descriptor *sd;
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));
677
sd = cli_query_secdesc(cli, fnum, talloc_tos());
680
printf("ERROR: secdesc query failed: %s\n", cli_errstr(cli));
684
sec_desc_print(cli, stdout, sd);
689
if (fnum != (uint16_t)-1)
690
cli_close(cli, fnum);
780
sd = get_secdesc(cli, filename);
784
printf("%s\n", sddl_encode(talloc_tos(), sd,
785
get_global_sam_sid()));
787
sec_desc_print(cli, stdout, sd);
700
800
static int owner_set(struct cli_state *cli, enum chown_mode change_mode,
701
801
const char *filename, const char *new_username)
804
struct security_descriptor *sd, *old;
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));
714
807
if (!StringToSid(cli, &sid, new_username))
715
808
return EXIT_PARSE_ERROR;
717
old = cli_query_secdesc(cli, fnum, talloc_tos());
719
cli_close(cli, fnum);
810
old = get_secdesc(cli, filename);
722
printf("owner_set: Failed to query old descriptor\n");
723
813
return EXIT_FAILED;
811
891
set the ACLs on a file given an ascii description
812
892
*******************************************************/
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)
897
struct security_descriptor *sd, *old;
821
900
int result = EXIT_OK;
823
sd = sec_desc_parse(talloc_tos(), cli, the_acl);
903
sd = sddl_decode(talloc_tos(), the_acl, get_global_sam_sid());
905
sd = sec_desc_parse(talloc_tos(), cli, the_acl);
825
908
if (!sd) return EXIT_PARSE_ERROR;
826
909
if (test_args) return EXIT_OK;
828
/* The desired access below is the only one I could find that works
829
with NT4, W2KP and Samba */
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));
837
old = cli_query_secdesc(cli, fnum, talloc_tos());
911
old = get_secdesc(cli, filename);
840
printf("calc_set: Failed to query old descriptor\n");
841
914
return EXIT_FAILED;
844
cli_close(cli, fnum);
846
917
/* the logic here is rather more complex than I would like */
848
919
case SMB_ACL_DELETE:
928
999
old->owner_sid, old->group_sid,
929
1000
NULL, old->dacl, &sd_size);
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;
1009
/*****************************************************
1010
set the inherit on a file
1011
*******************************************************/
1012
static int inherit(struct cli_state *cli, const char *filename,
1015
struct security_descriptor *old,*sd;
1018
int result = EXIT_OK;
1020
old = get_secdesc(cli, filename);
934
1023
return EXIT_FAILED;
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);
1028
if (strcmp(type,"allow")==0) {
1029
if ((old->type & SEC_DESC_DACL_PROTECTED) ==
1030
SEC_DESC_DACL_PROTECTED) {
1032
char *parentname,*temp;
1033
struct security_descriptor *parent;
1034
temp = talloc_strdup(talloc_tos(), filename);
1036
old->type=old->type & (~SEC_DESC_DACL_PROTECTED);
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)) {
1043
string_replace(parentname, '/', '\\');
1044
parent = get_secdesc(cli,parentname);
1045
if (parent == NULL) {
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);
1059
if ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) ==
1060
SEC_ACE_FLAG_OBJECT_INHERIT) {
1061
/* clear flags for files */
1063
add_ace(&old->dacl, ace);
1068
printf("Already set to inheritable permissions.\n");
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;
1076
/* remove all inherited ACL's. */
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);
1091
printf("Already set to no inheritable permissions.\n");
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;
1099
/* convert all inherited ACL's to non inherated ACL's. */
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);
1109
printf("Already set to no inheritable permissions.\n");
1114
/* Denied ACE entries must come before allowed ones */
1115
sort_acl(old->dacl);
1117
sd = make_sec_desc(talloc_tos(),old->revision, old->type,
1118
old->owner_sid, old->group_sid,
1119
NULL, old->dacl, &sd_size);
1121
if (!set_secdesc(cli, filename, sd)) {
939
1122
result = EXIT_FAILED;
944
cli_close(cli, fnum);
950
1128
/*****************************************************
951
1129
Return a connection to a server.
952
1130
*******************************************************/
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