2
Unix SMB/CIFS implementation.
3
SMB NT Security Descriptor / Unix permission conversion.
4
Copyright (C) Jeremy Allison 1994-2000.
5
Copyright (C) Andreas Gruenbacher 2002.
7
This program is free software; you can redistribute it and/or modify
8
it under the terms of the GNU General Public License as published by
9
the Free Software Foundation; either version 2 of the License, or
10
(at your option) any later version.
12
This program is distributed in the hope that it will be useful,
13
but WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
GNU General Public License for more details.
17
You should have received a copy of the GNU General Public License
18
along with this program; if not, write to the Free Software
19
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24
extern struct current_user current_user;
25
extern struct generic_mapping file_generic_mapping;
28
#define DBGC_CLASS DBGC_ACLS
30
/****************************************************************************
31
Data structures representing the internal ACE format.
32
****************************************************************************/
34
enum ace_owner {UID_ACE, GID_ACE, WORLD_ACE};
35
enum ace_attribute {ALLOW_ACE, DENY_ACE}; /* Used for incoming NT ACLS. */
37
typedef union posix_id {
43
typedef struct canon_ace {
44
struct canon_ace *next, *prev;
46
mode_t perms; /* Only use S_I(R|W|X)USR mode bits here. */
48
enum ace_owner owner_type;
49
enum ace_attribute attr;
54
#define ALL_ACE_PERMS (S_IRUSR|S_IWUSR|S_IXUSR)
57
* EA format of user.SAMBA_PAI (Samba_Posix_Acl_Interitance)
60
* | 1 | 1 | 2 | 2 | ....
61
* +------+------+-------------+---------------------+-------------+--------------------+
62
* | vers | flag | num_entries | num_default_entries | ..entries.. | default_entries... |
63
* +------+------+-------------+---------------------+-------------+--------------------+
66
#define PAI_VERSION_OFFSET 0
67
#define PAI_FLAG_OFFSET 1
68
#define PAI_NUM_ENTRIES_OFFSET 2
69
#define PAI_NUM_DEFAULT_ENTRIES_OFFSET 4
70
#define PAI_ENTRIES_BASE 6
73
#define PAI_ACL_FLAG_PROTECTED 0x1
74
#define PAI_ENTRY_LENGTH 5
77
* In memory format of user.SAMBA_PAI attribute.
81
struct pai_entry *next, *prev;
82
enum ace_owner owner_type;
88
unsigned int num_entries;
89
struct pai_entry *entry_list;
90
unsigned int num_def_entries;
91
struct pai_entry *def_entry_list;
94
/************************************************************************
95
Return a uint32 of the pai_entry principal.
96
************************************************************************/
98
static uint32 get_pai_entry_val(struct pai_entry *paie)
100
switch (paie->owner_type) {
102
DEBUG(10,("get_pai_entry_val: uid = %u\n", (unsigned int)paie->unix_ug.uid ));
103
return (uint32)paie->unix_ug.uid;
105
DEBUG(10,("get_pai_entry_val: gid = %u\n", (unsigned int)paie->unix_ug.gid ));
106
return (uint32)paie->unix_ug.gid;
109
DEBUG(10,("get_pai_entry_val: world ace\n"));
114
/************************************************************************
115
Return a uint32 of the entry principal.
116
************************************************************************/
118
static uint32 get_entry_val(canon_ace *ace_entry)
120
switch (ace_entry->owner_type) {
122
DEBUG(10,("get_entry_val: uid = %u\n", (unsigned int)ace_entry->unix_ug.uid ));
123
return (uint32)ace_entry->unix_ug.uid;
125
DEBUG(10,("get_entry_val: gid = %u\n", (unsigned int)ace_entry->unix_ug.gid ));
126
return (uint32)ace_entry->unix_ug.gid;
129
DEBUG(10,("get_entry_val: world ace\n"));
134
/************************************************************************
135
Count the inherited entries.
136
************************************************************************/
138
static unsigned int num_inherited_entries(canon_ace *ace_list)
140
unsigned int num_entries = 0;
142
for (; ace_list; ace_list = ace_list->next)
143
if (ace_list->inherited)
148
/************************************************************************
149
Create the on-disk format. Caller must free.
150
************************************************************************/
152
static char *create_pai_buf(canon_ace *file_ace_list, canon_ace *dir_ace_list, BOOL pai_protected, size_t *store_size)
154
char *pai_buf = NULL;
155
canon_ace *ace_list = NULL;
156
char *entry_offset = NULL;
157
unsigned int num_entries = 0;
158
unsigned int num_def_entries = 0;
160
for (ace_list = file_ace_list; ace_list; ace_list = ace_list->next)
161
if (ace_list->inherited)
164
for (ace_list = dir_ace_list; ace_list; ace_list = ace_list->next)
165
if (ace_list->inherited)
168
DEBUG(10,("create_pai_buf: num_entries = %u, num_def_entries = %u\n", num_entries, num_def_entries ));
170
*store_size = PAI_ENTRIES_BASE + ((num_entries + num_def_entries)*PAI_ENTRY_LENGTH);
172
pai_buf = SMB_MALLOC(*store_size);
177
/* Set up the header. */
178
memset(pai_buf, '\0', PAI_ENTRIES_BASE);
179
SCVAL(pai_buf,PAI_VERSION_OFFSET,PAI_VERSION);
180
SCVAL(pai_buf,PAI_FLAG_OFFSET,(pai_protected ? PAI_ACL_FLAG_PROTECTED : 0));
181
SSVAL(pai_buf,PAI_NUM_ENTRIES_OFFSET,num_entries);
182
SSVAL(pai_buf,PAI_NUM_DEFAULT_ENTRIES_OFFSET,num_def_entries);
184
entry_offset = pai_buf + PAI_ENTRIES_BASE;
186
for (ace_list = file_ace_list; ace_list; ace_list = ace_list->next) {
187
if (ace_list->inherited) {
188
uint8 type_val = (unsigned char)ace_list->owner_type;
189
uint32 entry_val = get_entry_val(ace_list);
191
SCVAL(entry_offset,0,type_val);
192
SIVAL(entry_offset,1,entry_val);
193
entry_offset += PAI_ENTRY_LENGTH;
197
for (ace_list = dir_ace_list; ace_list; ace_list = ace_list->next) {
198
if (ace_list->inherited) {
199
uint8 type_val = (unsigned char)ace_list->owner_type;
200
uint32 entry_val = get_entry_val(ace_list);
202
SCVAL(entry_offset,0,type_val);
203
SIVAL(entry_offset,1,entry_val);
204
entry_offset += PAI_ENTRY_LENGTH;
211
/************************************************************************
212
Store the user.SAMBA_PAI attribute on disk.
213
************************************************************************/
215
static void store_inheritance_attributes(files_struct *fsp, canon_ace *file_ace_list,
216
canon_ace *dir_ace_list, BOOL pai_protected)
222
if (!lp_map_acl_inherit(SNUM(fsp->conn)))
226
* Don't store if this ACL isn't protected and
227
* none of the entries in it are marked as inherited.
230
if (!pai_protected && num_inherited_entries(file_ace_list) == 0 && num_inherited_entries(dir_ace_list) == 0) {
231
/* Instead just remove the attribute if it exists. */
232
if (fsp->fh->fd != -1)
233
SMB_VFS_FREMOVEXATTR(fsp, fsp->fh->fd, SAMBA_POSIX_INHERITANCE_EA_NAME);
235
SMB_VFS_REMOVEXATTR(fsp->conn, fsp->fsp_name, SAMBA_POSIX_INHERITANCE_EA_NAME);
239
pai_buf = create_pai_buf(file_ace_list, dir_ace_list, pai_protected, &store_size);
241
if (fsp->fh->fd != -1)
242
ret = SMB_VFS_FSETXATTR(fsp, fsp->fh->fd, SAMBA_POSIX_INHERITANCE_EA_NAME,
243
pai_buf, store_size, 0);
245
ret = SMB_VFS_SETXATTR(fsp->conn,fsp->fsp_name, SAMBA_POSIX_INHERITANCE_EA_NAME,
246
pai_buf, store_size, 0);
250
DEBUG(10,("store_inheritance_attribute:%s for file %s\n", pai_protected ? " (protected)" : "", fsp->fsp_name));
251
if (ret == -1 && !no_acl_syscall_error(errno))
252
DEBUG(1,("store_inheritance_attribute: Error %s\n", strerror(errno) ));
255
/************************************************************************
256
Delete the in memory inheritance info.
257
************************************************************************/
259
static void free_inherited_info(struct pai_val *pal)
262
struct pai_entry *paie, *paie_next;
263
for (paie = pal->entry_list; paie; paie = paie_next) {
264
paie_next = paie->next;
267
for (paie = pal->def_entry_list; paie; paie = paie_next) {
268
paie_next = paie->next;
275
/************************************************************************
276
Was this ACL protected ?
277
************************************************************************/
279
static BOOL get_protected_flag(struct pai_val *pal)
283
return pal->pai_protected;
286
/************************************************************************
287
Was this ACE inherited ?
288
************************************************************************/
290
static BOOL get_inherited_flag(struct pai_val *pal, canon_ace *ace_entry, BOOL default_ace)
292
struct pai_entry *paie;
297
/* If the entry exists it is inherited. */
298
for (paie = (default_ace ? pal->def_entry_list : pal->entry_list); paie; paie = paie->next) {
299
if (ace_entry->owner_type == paie->owner_type &&
300
get_entry_val(ace_entry) == get_pai_entry_val(paie))
306
/************************************************************************
307
Ensure an attribute just read is valid.
308
************************************************************************/
310
static BOOL check_pai_ok(char *pai_buf, size_t pai_buf_data_size)
313
uint16 num_def_entries;
315
if (pai_buf_data_size < PAI_ENTRIES_BASE) {
316
/* Corrupted - too small. */
320
if (CVAL(pai_buf,PAI_VERSION_OFFSET) != PAI_VERSION)
323
num_entries = SVAL(pai_buf,PAI_NUM_ENTRIES_OFFSET);
324
num_def_entries = SVAL(pai_buf,PAI_NUM_DEFAULT_ENTRIES_OFFSET);
326
/* Check the entry lists match. */
327
/* Each entry is 5 bytes (type plus 4 bytes of uid or gid). */
329
if (((num_entries + num_def_entries)*PAI_ENTRY_LENGTH) + PAI_ENTRIES_BASE != pai_buf_data_size)
336
/************************************************************************
337
Convert to in-memory format.
338
************************************************************************/
340
static struct pai_val *create_pai_val(char *buf, size_t size)
343
struct pai_val *paiv = NULL;
346
if (!check_pai_ok(buf, size))
349
paiv = SMB_MALLOC_P(struct pai_val);
353
memset(paiv, '\0', sizeof(struct pai_val));
355
paiv->pai_protected = (CVAL(buf,PAI_FLAG_OFFSET) == PAI_ACL_FLAG_PROTECTED);
357
paiv->num_entries = SVAL(buf,PAI_NUM_ENTRIES_OFFSET);
358
paiv->num_def_entries = SVAL(buf,PAI_NUM_DEFAULT_ENTRIES_OFFSET);
360
entry_offset = buf + PAI_ENTRIES_BASE;
362
DEBUG(10,("create_pai_val:%s num_entries = %u, num_def_entries = %u\n",
363
paiv->pai_protected ? " (pai_protected)" : "", paiv->num_entries, paiv->num_def_entries ));
365
for (i = 0; i < paiv->num_entries; i++) {
366
struct pai_entry *paie;
368
paie = SMB_MALLOC_P(struct pai_entry);
370
free_inherited_info(paiv);
374
paie->owner_type = (enum ace_owner)CVAL(entry_offset,0);
375
switch( paie->owner_type) {
377
paie->unix_ug.uid = (uid_t)IVAL(entry_offset,1);
378
DEBUG(10,("create_pai_val: uid = %u\n", (unsigned int)paie->unix_ug.uid ));
381
paie->unix_ug.gid = (gid_t)IVAL(entry_offset,1);
382
DEBUG(10,("create_pai_val: gid = %u\n", (unsigned int)paie->unix_ug.gid ));
385
paie->unix_ug.world = -1;
386
DEBUG(10,("create_pai_val: world ace\n"));
389
free_inherited_info(paiv);
392
entry_offset += PAI_ENTRY_LENGTH;
393
DLIST_ADD(paiv->entry_list, paie);
396
for (i = 0; i < paiv->num_def_entries; i++) {
397
struct pai_entry *paie;
399
paie = SMB_MALLOC_P(struct pai_entry);
401
free_inherited_info(paiv);
405
paie->owner_type = (enum ace_owner)CVAL(entry_offset,0);
406
switch( paie->owner_type) {
408
paie->unix_ug.uid = (uid_t)IVAL(entry_offset,1);
409
DEBUG(10,("create_pai_val: (def) uid = %u\n", (unsigned int)paie->unix_ug.uid ));
412
paie->unix_ug.gid = (gid_t)IVAL(entry_offset,1);
413
DEBUG(10,("create_pai_val: (def) gid = %u\n", (unsigned int)paie->unix_ug.gid ));
416
paie->unix_ug.world = -1;
417
DEBUG(10,("create_pai_val: (def) world ace\n"));
420
free_inherited_info(paiv);
423
entry_offset += PAI_ENTRY_LENGTH;
424
DLIST_ADD(paiv->def_entry_list, paie);
430
/************************************************************************
431
Load the user.SAMBA_PAI attribute.
432
************************************************************************/
434
static struct pai_val *load_inherited_info(files_struct *fsp)
437
size_t pai_buf_size = 1024;
438
struct pai_val *paiv = NULL;
441
if (!lp_map_acl_inherit(SNUM(fsp->conn)))
444
if ((pai_buf = SMB_MALLOC(pai_buf_size)) == NULL)
448
if (fsp->fh->fd != -1)
449
ret = SMB_VFS_FGETXATTR(fsp, fsp->fh->fd, SAMBA_POSIX_INHERITANCE_EA_NAME,
450
pai_buf, pai_buf_size);
452
ret = SMB_VFS_GETXATTR(fsp->conn,fsp->fsp_name,SAMBA_POSIX_INHERITANCE_EA_NAME,
453
pai_buf, pai_buf_size);
456
if (errno != ERANGE) {
459
/* Buffer too small - enlarge it. */
462
if (pai_buf_size > 1024*1024) {
463
return NULL; /* Limit malloc to 1mb. */
465
if ((pai_buf = SMB_MALLOC(pai_buf_size)) == NULL)
470
DEBUG(10,("load_inherited_info: ret = %lu for file %s\n", (unsigned long)ret, fsp->fsp_name));
473
/* No attribute or not supported. */
475
if (errno != ENOATTR)
476
DEBUG(10,("load_inherited_info: Error %s\n", strerror(errno) ));
479
DEBUG(10,("load_inherited_info: Error %s\n", strerror(errno) ));
485
paiv = create_pai_val(pai_buf, ret);
487
if (paiv && paiv->pai_protected)
488
DEBUG(10,("load_inherited_info: ACL is protected for file %s\n", fsp->fsp_name));
494
/****************************************************************************
495
Functions to manipulate the internal ACE format.
496
****************************************************************************/
498
/****************************************************************************
499
Count a linked list of canonical ACE entries.
500
****************************************************************************/
502
static size_t count_canon_ace_list( canon_ace *list_head )
507
for (ace = list_head; ace; ace = ace->next)
513
/****************************************************************************
514
Free a linked list of canonical ACE entries.
515
****************************************************************************/
517
static void free_canon_ace_list( canon_ace *list_head )
519
canon_ace *list, *next;
521
for (list = list_head; list; list = next) {
523
DLIST_REMOVE(list_head, list);
528
/****************************************************************************
529
Function to duplicate a canon_ace entry.
530
****************************************************************************/
532
static canon_ace *dup_canon_ace( canon_ace *src_ace)
534
canon_ace *dst_ace = SMB_MALLOC_P(canon_ace);
540
dst_ace->prev = dst_ace->next = NULL;
544
/****************************************************************************
545
Print out a canon ace.
546
****************************************************************************/
548
static void print_canon_ace(canon_ace *pace, int num)
552
dbgtext( "canon_ace index %d. Type = %s ", num, pace->attr == ALLOW_ACE ? "allow" : "deny" );
553
dbgtext( "SID = %s ", sid_to_string( str, &pace->trustee));
554
if (pace->owner_type == UID_ACE) {
555
const char *u_name = uidtoname(pace->unix_ug.uid);
556
dbgtext( "uid %u (%s) ", (unsigned int)pace->unix_ug.uid, u_name );
557
} else if (pace->owner_type == GID_ACE) {
558
char *g_name = gidtoname(pace->unix_ug.gid);
559
dbgtext( "gid %u (%s) ", (unsigned int)pace->unix_ug.gid, g_name );
562
switch (pace->type) {
564
dbgtext( "SMB_ACL_USER ");
566
case SMB_ACL_USER_OBJ:
567
dbgtext( "SMB_ACL_USER_OBJ ");
570
dbgtext( "SMB_ACL_GROUP ");
572
case SMB_ACL_GROUP_OBJ:
573
dbgtext( "SMB_ACL_GROUP_OBJ ");
576
dbgtext( "SMB_ACL_OTHER ");
580
dbgtext( "(inherited) ");
582
dbgtext( "%c", pace->perms & S_IRUSR ? 'r' : '-');
583
dbgtext( "%c", pace->perms & S_IWUSR ? 'w' : '-');
584
dbgtext( "%c\n", pace->perms & S_IXUSR ? 'x' : '-');
587
/****************************************************************************
588
Print out a canon ace list.
589
****************************************************************************/
591
static void print_canon_ace_list(const char *name, canon_ace *ace_list)
595
if( DEBUGLVL( 10 )) {
596
dbgtext( "print_canon_ace_list: %s\n", name );
597
for (;ace_list; ace_list = ace_list->next, count++)
598
print_canon_ace(ace_list, count );
602
/****************************************************************************
603
Map POSIX ACL perms to canon_ace permissions (a mode_t containing only S_(R|W|X)USR bits).
604
****************************************************************************/
606
static mode_t convert_permset_to_mode_t(connection_struct *conn, SMB_ACL_PERMSET_T permset)
610
ret |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? S_IRUSR : 0);
611
ret |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? S_IWUSR : 0);
612
ret |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? S_IXUSR : 0);
617
/****************************************************************************
618
Map generic UNIX permissions to canon_ace permissions (a mode_t containing only S_(R|W|X)USR bits).
619
****************************************************************************/
621
static mode_t unix_perms_to_acl_perms(mode_t mode, int r_mask, int w_mask, int x_mask)
635
/****************************************************************************
636
Map canon_ace permissions (a mode_t containing only S_(R|W|X)USR bits) to
637
an SMB_ACL_PERMSET_T.
638
****************************************************************************/
640
static int map_acl_perms_to_permset(connection_struct *conn, mode_t mode, SMB_ACL_PERMSET_T *p_permset)
642
if (SMB_VFS_SYS_ACL_CLEAR_PERMS(conn, *p_permset) == -1)
644
if (mode & S_IRUSR) {
645
if (SMB_VFS_SYS_ACL_ADD_PERM(conn, *p_permset, SMB_ACL_READ) == -1)
648
if (mode & S_IWUSR) {
649
if (SMB_VFS_SYS_ACL_ADD_PERM(conn, *p_permset, SMB_ACL_WRITE) == -1)
652
if (mode & S_IXUSR) {
653
if (SMB_VFS_SYS_ACL_ADD_PERM(conn, *p_permset, SMB_ACL_EXECUTE) == -1)
658
/****************************************************************************
659
Function to create owner and group SIDs from a SMB_STRUCT_STAT.
660
****************************************************************************/
662
static void create_file_sids(SMB_STRUCT_STAT *psbuf, DOM_SID *powner_sid, DOM_SID *pgroup_sid)
664
uid_to_sid( powner_sid, psbuf->st_uid );
665
gid_to_sid( pgroup_sid, psbuf->st_gid );
668
/****************************************************************************
669
Merge aces with a common sid - if both are allow or deny, OR the permissions together and
670
delete the second one. If the first is deny, mask the permissions off and delete the allow
671
if the permissions become zero, delete the deny if the permissions are non zero.
672
****************************************************************************/
674
static void merge_aces( canon_ace **pp_list_head )
676
canon_ace *list_head = *pp_list_head;
677
canon_ace *curr_ace_outer;
678
canon_ace *curr_ace_outer_next;
681
* First, merge allow entries with identical SIDs, and deny entries
682
* with identical SIDs.
685
for (curr_ace_outer = list_head; curr_ace_outer; curr_ace_outer = curr_ace_outer_next) {
687
canon_ace *curr_ace_next;
689
curr_ace_outer_next = curr_ace_outer->next; /* Save the link in case we delete. */
691
for (curr_ace = curr_ace_outer->next; curr_ace; curr_ace = curr_ace_next) {
693
curr_ace_next = curr_ace->next; /* Save the link in case of delete. */
695
if (sid_equal(&curr_ace->trustee, &curr_ace_outer->trustee) &&
696
(curr_ace->attr == curr_ace_outer->attr)) {
698
if( DEBUGLVL( 10 )) {
699
dbgtext("merge_aces: Merging ACE's\n");
700
print_canon_ace( curr_ace_outer, 0);
701
print_canon_ace( curr_ace, 0);
704
/* Merge two allow or two deny ACE's. */
706
curr_ace_outer->perms |= curr_ace->perms;
707
DLIST_REMOVE(list_head, curr_ace);
709
curr_ace_outer_next = curr_ace_outer->next; /* We may have deleted the link. */
715
* Now go through and mask off allow permissions with deny permissions.
716
* We can delete either the allow or deny here as we know that each SID
717
* appears only once in the list.
720
for (curr_ace_outer = list_head; curr_ace_outer; curr_ace_outer = curr_ace_outer_next) {
722
canon_ace *curr_ace_next;
724
curr_ace_outer_next = curr_ace_outer->next; /* Save the link in case we delete. */
726
for (curr_ace = curr_ace_outer->next; curr_ace; curr_ace = curr_ace_next) {
728
curr_ace_next = curr_ace->next; /* Save the link in case of delete. */
731
* Subtract ACE's with different entries. Due to the ordering constraints
732
* we've put on the ACL, we know the deny must be the first one.
735
if (sid_equal(&curr_ace->trustee, &curr_ace_outer->trustee) &&
736
(curr_ace_outer->attr == DENY_ACE) && (curr_ace->attr == ALLOW_ACE)) {
738
if( DEBUGLVL( 10 )) {
739
dbgtext("merge_aces: Masking ACE's\n");
740
print_canon_ace( curr_ace_outer, 0);
741
print_canon_ace( curr_ace, 0);
744
curr_ace->perms &= ~curr_ace_outer->perms;
746
if (curr_ace->perms == 0) {
749
* The deny overrides the allow. Remove the allow.
752
DLIST_REMOVE(list_head, curr_ace);
754
curr_ace_outer_next = curr_ace_outer->next; /* We may have deleted the link. */
759
* Even after removing permissions, there
760
* are still allow permissions - delete the deny.
761
* It is safe to delete the deny here,
762
* as we are guarenteed by the deny first
763
* ordering that all the deny entries for
764
* this SID have already been merged into one
765
* before we can get to an allow ace.
768
DLIST_REMOVE(list_head, curr_ace_outer);
769
SAFE_FREE(curr_ace_outer);
774
} /* end for curr_ace */
775
} /* end for curr_ace_outer */
777
/* We may have modified the list. */
779
*pp_list_head = list_head;
782
/****************************************************************************
783
Check if we need to return NT4.x compatible ACL entries.
784
****************************************************************************/
786
static BOOL nt4_compatible_acls(void)
788
int compat = lp_acl_compatibility();
790
if (compat == ACL_COMPAT_AUTO) {
791
enum remote_arch_types ra_type = get_remote_arch();
793
/* Automatically adapt to client */
794
return (ra_type <= RA_WINNT);
796
return (compat == ACL_COMPAT_WINNT);
800
/****************************************************************************
801
Map canon_ace perms to permission bits NT.
802
The attr element is not used here - we only process deny entries on set,
803
not get. Deny entries are implicit on get with ace->perms = 0.
804
****************************************************************************/
806
static SEC_ACCESS map_canon_ace_perms(int snum, int *pacl_type, DOM_SID *powner_sid, canon_ace *ace, BOOL directory_ace)
811
*pacl_type = SEC_ACE_TYPE_ACCESS_ALLOWED;
813
if (lp_acl_map_full_control(snum) && ((ace->perms & ALL_ACE_PERMS) == ALL_ACE_PERMS)) {
815
nt_mask = UNIX_DIRECTORY_ACCESS_RWX;
817
nt_mask = UNIX_ACCESS_RWX;
819
} else if ((ace->perms & ALL_ACE_PERMS) == (mode_t)0) {
821
* Windows NT refuses to display ACEs with no permissions in them (but
822
* they are perfectly legal with Windows 2000). If the ACE has empty
823
* permissions we cannot use 0, so we use the otherwise unused
824
* WRITE_OWNER permission, which we ignore when we set an ACL.
825
* We abstract this into a #define of UNIX_ACCESS_NONE to allow this
826
* to be changed in the future.
829
if (nt4_compatible_acls())
830
nt_mask = UNIX_ACCESS_NONE;
835
nt_mask |= ((ace->perms & S_IRUSR) ? UNIX_DIRECTORY_ACCESS_R : 0 );
836
nt_mask |= ((ace->perms & S_IWUSR) ? UNIX_DIRECTORY_ACCESS_W : 0 );
837
nt_mask |= ((ace->perms & S_IXUSR) ? UNIX_DIRECTORY_ACCESS_X : 0 );
839
nt_mask |= ((ace->perms & S_IRUSR) ? UNIX_ACCESS_R : 0 );
840
nt_mask |= ((ace->perms & S_IWUSR) ? UNIX_ACCESS_W : 0 );
841
nt_mask |= ((ace->perms & S_IXUSR) ? UNIX_ACCESS_X : 0 );
845
DEBUG(10,("map_canon_ace_perms: Mapped (UNIX) %x to (NT) %x\n",
846
(unsigned int)ace->perms, (unsigned int)nt_mask ));
848
init_sec_access(&sa,nt_mask);
852
/****************************************************************************
853
Map NT perms to a UNIX mode_t.
854
****************************************************************************/
856
#define FILE_SPECIFIC_READ_BITS (FILE_READ_DATA|FILE_READ_EA|FILE_READ_ATTRIBUTES)
857
#define FILE_SPECIFIC_WRITE_BITS (FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_WRITE_EA|FILE_WRITE_ATTRIBUTES)
858
#define FILE_SPECIFIC_EXECUTE_BITS (FILE_EXECUTE)
860
static mode_t map_nt_perms( SEC_ACCESS sec_access, int type)
866
if(sec_access.mask & GENERIC_ALL_ACCESS)
867
mode = S_IRUSR|S_IWUSR|S_IXUSR;
869
mode |= (sec_access.mask & (GENERIC_READ_ACCESS|FILE_SPECIFIC_READ_BITS)) ? S_IRUSR : 0;
870
mode |= (sec_access.mask & (GENERIC_WRITE_ACCESS|FILE_SPECIFIC_WRITE_BITS)) ? S_IWUSR : 0;
871
mode |= (sec_access.mask & (GENERIC_EXECUTE_ACCESS|FILE_SPECIFIC_EXECUTE_BITS)) ? S_IXUSR : 0;
875
if(sec_access.mask & GENERIC_ALL_ACCESS)
876
mode = S_IRGRP|S_IWGRP|S_IXGRP;
878
mode |= (sec_access.mask & (GENERIC_READ_ACCESS|FILE_SPECIFIC_READ_BITS)) ? S_IRGRP : 0;
879
mode |= (sec_access.mask & (GENERIC_WRITE_ACCESS|FILE_SPECIFIC_WRITE_BITS)) ? S_IWGRP : 0;
880
mode |= (sec_access.mask & (GENERIC_EXECUTE_ACCESS|FILE_SPECIFIC_EXECUTE_BITS)) ? S_IXGRP : 0;
884
if(sec_access.mask & GENERIC_ALL_ACCESS)
885
mode = S_IROTH|S_IWOTH|S_IXOTH;
887
mode |= (sec_access.mask & (GENERIC_READ_ACCESS|FILE_SPECIFIC_READ_BITS)) ? S_IROTH : 0;
888
mode |= (sec_access.mask & (GENERIC_WRITE_ACCESS|FILE_SPECIFIC_WRITE_BITS)) ? S_IWOTH : 0;
889
mode |= (sec_access.mask & (GENERIC_EXECUTE_ACCESS|FILE_SPECIFIC_EXECUTE_BITS)) ? S_IXOTH : 0;
897
/****************************************************************************
898
Unpack a SEC_DESC into a UNIX owner and group.
899
****************************************************************************/
901
static BOOL unpack_nt_owners(int snum, SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *pgrp, uint32 security_info_sent, SEC_DESC *psd)
909
if(security_info_sent == 0) {
910
DEBUG(0,("unpack_nt_owners: no security info sent !\n"));
915
* Validate the owner and group SID's.
918
memset(&owner_sid, '\0', sizeof(owner_sid));
919
memset(&grp_sid, '\0', sizeof(grp_sid));
921
DEBUG(5,("unpack_nt_owners: validating owner_sids.\n"));
924
* Don't immediately fail if the owner sid cannot be validated.
925
* This may be a group chown only set.
928
if (security_info_sent & OWNER_SECURITY_INFORMATION) {
929
sid_copy(&owner_sid, psd->owner_sid);
930
if (!sid_to_uid(&owner_sid, puser)) {
931
if (lp_force_unknown_acl_user(snum)) {
932
/* this allows take ownership to work
934
*puser = current_user.ut.uid;
936
DEBUG(3,("unpack_nt_owners: unable to validate"
937
" owner sid for %s\n",
938
sid_string_static(&owner_sid)));
945
* Don't immediately fail if the group sid cannot be validated.
946
* This may be an owner chown only set.
949
if (security_info_sent & GROUP_SECURITY_INFORMATION) {
950
sid_copy(&grp_sid, psd->grp_sid);
951
if (!sid_to_gid( &grp_sid, pgrp)) {
952
if (lp_force_unknown_acl_user(snum)) {
953
/* this allows take group ownership to work
955
*pgrp = current_user.ut.gid;
957
DEBUG(3,("unpack_nt_owners: unable to validate"
964
DEBUG(5,("unpack_nt_owners: owner_sids validated.\n"));
969
/****************************************************************************
970
Ensure the enforced permissions for this share apply.
971
****************************************************************************/
973
static void apply_default_perms(files_struct *fsp, canon_ace *pace, mode_t type)
975
int snum = SNUM(fsp->conn);
976
mode_t and_bits = (mode_t)0;
977
mode_t or_bits = (mode_t)0;
979
/* Get the initial bits to apply. */
981
if (fsp->is_directory) {
982
and_bits = lp_dir_security_mask(snum);
983
or_bits = lp_force_dir_security_mode(snum);
985
and_bits = lp_security_mask(snum);
986
or_bits = lp_force_security_mode(snum);
989
/* Now bounce them into the S_USR space. */
992
/* Ensure owner has read access. */
993
pace->perms |= S_IRUSR;
994
if (fsp->is_directory)
995
pace->perms |= (S_IWUSR|S_IXUSR);
996
and_bits = unix_perms_to_acl_perms(and_bits, S_IRUSR, S_IWUSR, S_IXUSR);
997
or_bits = unix_perms_to_acl_perms(or_bits, S_IRUSR, S_IWUSR, S_IXUSR);
1000
and_bits = unix_perms_to_acl_perms(and_bits, S_IRGRP, S_IWGRP, S_IXGRP);
1001
or_bits = unix_perms_to_acl_perms(or_bits, S_IRGRP, S_IWGRP, S_IXGRP);
1004
and_bits = unix_perms_to_acl_perms(and_bits, S_IROTH, S_IWOTH, S_IXOTH);
1005
or_bits = unix_perms_to_acl_perms(or_bits, S_IROTH, S_IWOTH, S_IXOTH);
1009
pace->perms = ((pace->perms & and_bits)|or_bits);
1012
/****************************************************************************
1013
Check if a given uid/SID is in a group gid/SID. This is probably very
1014
expensive and will need optimisation. A *lot* of optimisation :-). JRA.
1015
****************************************************************************/
1017
static BOOL uid_entry_in_group( canon_ace *uid_ace, canon_ace *group_ace )
1021
/* "Everyone" always matches every uid. */
1023
if (sid_equal(&group_ace->trustee, &global_sid_World))
1026
/* Assume that the current user is in the current group (force group) */
1028
if (uid_ace->unix_ug.uid == current_user.ut.uid && group_ace->unix_ug.gid == current_user.ut.gid)
1031
fstrcpy(u_name, uidtoname(uid_ace->unix_ug.uid));
1032
return user_in_group_sid(u_name, &group_ace->trustee);
1035
/****************************************************************************
1036
A well formed POSIX file or default ACL has at least 3 entries, a
1037
SMB_ACL_USER_OBJ, SMB_ACL_GROUP_OBJ, SMB_ACL_OTHER_OBJ.
1038
In addition, the owner must always have at least read access.
1039
When using this call on get_acl, the pst struct is valid and contains
1040
the mode of the file. When using this call on set_acl, the pst struct has
1041
been modified to have a mode containing the default for this file or directory
1043
****************************************************************************/
1045
static BOOL ensure_canon_entry_valid(canon_ace **pp_ace,
1047
const DOM_SID *pfile_owner_sid,
1048
const DOM_SID *pfile_grp_sid,
1049
SMB_STRUCT_STAT *pst,
1053
BOOL got_user = False;
1054
BOOL got_grp = False;
1055
BOOL got_other = False;
1056
canon_ace *pace_other = NULL;
1058
for (pace = *pp_ace; pace; pace = pace->next) {
1059
if (pace->type == SMB_ACL_USER_OBJ) {
1062
apply_default_perms(fsp, pace, S_IRUSR);
1065
} else if (pace->type == SMB_ACL_GROUP_OBJ) {
1068
* Ensure create mask/force create mode is respected on set.
1072
apply_default_perms(fsp, pace, S_IRGRP);
1075
} else if (pace->type == SMB_ACL_OTHER) {
1078
* Ensure create mask/force create mode is respected on set.
1082
apply_default_perms(fsp, pace, S_IROTH);
1089
if ((pace = SMB_MALLOC_P(canon_ace)) == NULL) {
1090
DEBUG(0,("ensure_canon_entry_valid: malloc fail.\n"));
1095
pace->type = SMB_ACL_USER_OBJ;
1096
pace->owner_type = UID_ACE;
1097
pace->unix_ug.uid = pst->st_uid;
1098
pace->trustee = *pfile_owner_sid;
1099
pace->attr = ALLOW_ACE;
1102
/* See if the owning user is in any of the other groups in
1103
the ACE. If so, OR in the permissions from that group. */
1105
BOOL group_matched = False;
1106
canon_ace *pace_iter;
1108
for (pace_iter = *pp_ace; pace_iter; pace_iter = pace_iter->next) {
1109
if (pace_iter->type == SMB_ACL_GROUP_OBJ || pace_iter->type == SMB_ACL_GROUP) {
1110
if (uid_entry_in_group(pace, pace_iter)) {
1111
pace->perms |= pace_iter->perms;
1112
group_matched = True;
1117
/* If we only got an "everyone" perm, just use that. */
1118
if (!group_matched) {
1120
pace->perms = pace_other->perms;
1125
apply_default_perms(fsp, pace, S_IRUSR);
1127
pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IRUSR, S_IWUSR, S_IXUSR);
1130
DLIST_ADD(*pp_ace, pace);
1134
if ((pace = SMB_MALLOC_P(canon_ace)) == NULL) {
1135
DEBUG(0,("ensure_canon_entry_valid: malloc fail.\n"));
1140
pace->type = SMB_ACL_GROUP_OBJ;
1141
pace->owner_type = GID_ACE;
1142
pace->unix_ug.uid = pst->st_gid;
1143
pace->trustee = *pfile_grp_sid;
1144
pace->attr = ALLOW_ACE;
1146
/* If we only got an "everyone" perm, just use that. */
1148
pace->perms = pace_other->perms;
1151
apply_default_perms(fsp, pace, S_IRGRP);
1153
pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IRGRP, S_IWGRP, S_IXGRP);
1156
DLIST_ADD(*pp_ace, pace);
1160
if ((pace = SMB_MALLOC_P(canon_ace)) == NULL) {
1161
DEBUG(0,("ensure_canon_entry_valid: malloc fail.\n"));
1166
pace->type = SMB_ACL_OTHER;
1167
pace->owner_type = WORLD_ACE;
1168
pace->unix_ug.world = -1;
1169
pace->trustee = global_sid_World;
1170
pace->attr = ALLOW_ACE;
1173
apply_default_perms(fsp, pace, S_IROTH);
1175
pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IROTH, S_IWOTH, S_IXOTH);
1177
DLIST_ADD(*pp_ace, pace);
1183
/****************************************************************************
1184
Check if a POSIX ACL has the required SMB_ACL_USER_OBJ and SMB_ACL_GROUP_OBJ entries.
1185
If it does not have them, check if there are any entries where the trustee is the
1186
file owner or the owning group, and map these to SMB_ACL_USER_OBJ and SMB_ACL_GROUP_OBJ.
1187
****************************************************************************/
1189
static void check_owning_objs(canon_ace *ace, DOM_SID *pfile_owner_sid, DOM_SID *pfile_grp_sid)
1191
BOOL got_user_obj, got_group_obj;
1192
canon_ace *current_ace;
1195
entries = count_canon_ace_list(ace);
1196
got_user_obj = False;
1197
got_group_obj = False;
1199
for (i=0, current_ace = ace; i < entries; i++, current_ace = current_ace->next) {
1200
if (current_ace->type == SMB_ACL_USER_OBJ)
1201
got_user_obj = True;
1202
else if (current_ace->type == SMB_ACL_GROUP_OBJ)
1203
got_group_obj = True;
1205
if (got_user_obj && got_group_obj) {
1206
DEBUG(10,("check_owning_objs: ACL had owning user/group entries.\n"));
1210
for (i=0, current_ace = ace; i < entries; i++, current_ace = current_ace->next) {
1211
if (!got_user_obj && current_ace->owner_type == UID_ACE &&
1212
sid_equal(¤t_ace->trustee, pfile_owner_sid)) {
1213
current_ace->type = SMB_ACL_USER_OBJ;
1214
got_user_obj = True;
1216
if (!got_group_obj && current_ace->owner_type == GID_ACE &&
1217
sid_equal(¤t_ace->trustee, pfile_grp_sid)) {
1218
current_ace->type = SMB_ACL_GROUP_OBJ;
1219
got_group_obj = True;
1223
DEBUG(10,("check_owning_objs: ACL is missing an owner entry.\n"));
1225
DEBUG(10,("check_owning_objs: ACL is missing an owning group entry.\n"));
1228
/****************************************************************************
1229
Unpack a SEC_DESC into two canonical ace lists.
1230
****************************************************************************/
1232
static BOOL create_canon_ace_lists(files_struct *fsp, SMB_STRUCT_STAT *pst,
1233
DOM_SID *pfile_owner_sid,
1234
DOM_SID *pfile_grp_sid,
1235
canon_ace **ppfile_ace, canon_ace **ppdir_ace,
1238
BOOL all_aces_are_inherit_only = (fsp->is_directory ? True : False);
1239
canon_ace *file_ace = NULL;
1240
canon_ace *dir_ace = NULL;
1241
canon_ace *tmp_ace = NULL;
1242
canon_ace *current_ace = NULL;
1243
BOOL got_dir_allow = False;
1244
BOOL got_file_allow = False;
1251
* Convert the incoming ACL into a more regular form.
1254
for(i = 0; i < dacl->num_aces; i++) {
1255
SEC_ACE *psa = &dacl->ace[i];
1257
if((psa->type != SEC_ACE_TYPE_ACCESS_ALLOWED) && (psa->type != SEC_ACE_TYPE_ACCESS_DENIED)) {
1258
DEBUG(3,("create_canon_ace_lists: unable to set anything but an ALLOW or DENY ACE.\n"));
1262
if (nt4_compatible_acls()) {
1264
* The security mask may be UNIX_ACCESS_NONE which should map into
1265
* no permissions (we overload the WRITE_OWNER bit for this) or it
1266
* should be one of the ALL/EXECUTE/READ/WRITE bits. Arrange for this
1267
* to be so. Any other bits override the UNIX_ACCESS_NONE bit.
1271
* Convert GENERIC bits to specific bits.
1274
se_map_generic(&psa->info.mask, &file_generic_mapping);
1276
psa->info.mask &= (UNIX_ACCESS_NONE|FILE_ALL_ACCESS);
1278
if(psa->info.mask != UNIX_ACCESS_NONE)
1279
psa->info.mask &= ~UNIX_ACCESS_NONE;
1284
* Deal with the fact that NT 4.x re-writes the canonical format
1285
* that we return for default ACLs. If a directory ACE is identical
1286
* to a inherited directory ACE then NT changes the bits so that the
1287
* first ACE is set to OI|IO and the second ACE for this SID is set
1288
* to CI. We need to repair this. JRA.
1291
for(i = 0; i < dacl->num_aces; i++) {
1292
SEC_ACE *psa1 = &dacl->ace[i];
1294
for (j = i + 1; j < dacl->num_aces; j++) {
1295
SEC_ACE *psa2 = &dacl->ace[j];
1297
if (psa1->info.mask != psa2->info.mask)
1300
if (!sid_equal(&psa1->trustee, &psa2->trustee))
1304
* Ok - permission bits and SIDs are equal.
1305
* Check if flags were re-written.
1308
if (psa1->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
1310
psa1->flags |= (psa2->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT));
1311
psa2->flags &= ~(SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT);
1313
} else if (psa2->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
1315
psa2->flags |= (psa1->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT));
1316
psa1->flags &= ~(SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT);
1322
for(i = 0; i < dacl->num_aces; i++) {
1323
SEC_ACE *psa = &dacl->ace[i];
1326
* Ignore non-mappable SIDs (NT Authority, BUILTIN etc).
1329
if (non_mappable_sid(&psa->trustee)) {
1331
DEBUG(10,("create_canon_ace_lists: ignoring non-mappable SID %s\n",
1332
sid_to_string(str, &psa->trustee) ));
1337
* Create a cannon_ace entry representing this NT DACL ACE.
1340
if ((current_ace = SMB_MALLOC_P(canon_ace)) == NULL) {
1341
free_canon_ace_list(file_ace);
1342
free_canon_ace_list(dir_ace);
1343
DEBUG(0,("create_canon_ace_lists: malloc fail.\n"));
1347
ZERO_STRUCTP(current_ace);
1349
sid_copy(¤t_ace->trustee, &psa->trustee);
1352
* Try and work out if the SID is a user or group
1353
* as we need to flag these differently for POSIX.
1354
* Note what kind of a POSIX ACL this should map to.
1357
if( sid_equal(¤t_ace->trustee, &global_sid_World)) {
1358
current_ace->owner_type = WORLD_ACE;
1359
current_ace->unix_ug.world = -1;
1360
current_ace->type = SMB_ACL_OTHER;
1361
} else if (sid_equal(¤t_ace->trustee, &global_sid_Creator_Owner)) {
1362
current_ace->owner_type = UID_ACE;
1363
current_ace->unix_ug.uid = pst->st_uid;
1364
current_ace->type = SMB_ACL_USER_OBJ;
1367
* The Creator Owner entry only specifies inheritable permissions,
1368
* never access permissions. WinNT doesn't always set the ACE to
1369
*INHERIT_ONLY, though.
1372
if (nt4_compatible_acls())
1373
psa->flags |= SEC_ACE_FLAG_INHERIT_ONLY;
1374
} else if (sid_equal(¤t_ace->trustee, &global_sid_Creator_Group)) {
1375
current_ace->owner_type = GID_ACE;
1376
current_ace->unix_ug.gid = pst->st_gid;
1377
current_ace->type = SMB_ACL_GROUP_OBJ;
1380
* The Creator Group entry only specifies inheritable permissions,
1381
* never access permissions. WinNT doesn't always set the ACE to
1382
*INHERIT_ONLY, though.
1384
if (nt4_compatible_acls())
1385
psa->flags |= SEC_ACE_FLAG_INHERIT_ONLY;
1387
} else if (sid_to_uid( ¤t_ace->trustee, ¤t_ace->unix_ug.uid)) {
1388
current_ace->owner_type = UID_ACE;
1389
current_ace->type = SMB_ACL_USER;
1390
} else if (sid_to_gid( ¤t_ace->trustee, ¤t_ace->unix_ug.gid)) {
1391
current_ace->owner_type = GID_ACE;
1392
current_ace->type = SMB_ACL_GROUP;
1396
free_canon_ace_list(file_ace);
1397
free_canon_ace_list(dir_ace);
1398
DEBUG(0,("create_canon_ace_lists: unable to map SID %s to uid or gid.\n",
1399
sid_to_string(str, ¤t_ace->trustee) ));
1400
SAFE_FREE(current_ace);
1405
* Map the given NT permissions into a UNIX mode_t containing only
1406
* S_I(R|W|X)USR bits.
1409
current_ace->perms |= map_nt_perms( psa->info, S_IRUSR);
1410
current_ace->attr = (psa->type == SEC_ACE_TYPE_ACCESS_ALLOWED) ? ALLOW_ACE : DENY_ACE;
1411
current_ace->inherited = ((psa->flags & SEC_ACE_FLAG_INHERITED_ACE) ? True : False);
1414
* Now add the created ace to either the file list, the directory
1415
* list, or both. We *MUST* preserve the order here (hence we use
1416
* DLIST_ADD_END) as NT ACLs are order dependent.
1419
if (fsp->is_directory) {
1422
* We can only add to the default POSIX ACE list if the ACE is
1423
* designed to be inherited by both files and directories.
1426
if ((psa->flags & (SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT)) ==
1427
(SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT)) {
1429
DLIST_ADD_END(dir_ace, current_ace, tmp_ace);
1432
* Note if this was an allow ace. We can't process
1433
* any further deny ace's after this.
1436
if (current_ace->attr == ALLOW_ACE)
1437
got_dir_allow = True;
1439
if ((current_ace->attr == DENY_ACE) && got_dir_allow) {
1440
DEBUG(0,("create_canon_ace_lists: malformed ACL in inheritable ACL ! \
1441
Deny entry after Allow entry. Failing to set on file %s.\n", fsp->fsp_name ));
1442
free_canon_ace_list(file_ace);
1443
free_canon_ace_list(dir_ace);
1447
if( DEBUGLVL( 10 )) {
1448
dbgtext("create_canon_ace_lists: adding dir ACL:\n");
1449
print_canon_ace( current_ace, 0);
1453
* If this is not an inherit only ACE we need to add a duplicate
1457
if (!(psa->flags & SEC_ACE_FLAG_INHERIT_ONLY)) {
1458
canon_ace *dup_ace = dup_canon_ace(current_ace);
1461
DEBUG(0,("create_canon_ace_lists: malloc fail !\n"));
1462
free_canon_ace_list(file_ace);
1463
free_canon_ace_list(dir_ace);
1468
* We must not free current_ace here as its
1469
* pointer is now owned by the dir_ace list.
1471
current_ace = dup_ace;
1474
* We must not free current_ace here as its
1475
* pointer is now owned by the dir_ace list.
1483
* Only add to the file ACL if not inherit only.
1486
if (current_ace && !(psa->flags & SEC_ACE_FLAG_INHERIT_ONLY)) {
1487
DLIST_ADD_END(file_ace, current_ace, tmp_ace);
1490
* Note if this was an allow ace. We can't process
1491
* any further deny ace's after this.
1494
if (current_ace->attr == ALLOW_ACE)
1495
got_file_allow = True;
1497
if ((current_ace->attr == DENY_ACE) && got_file_allow) {
1498
DEBUG(0,("create_canon_ace_lists: malformed ACL in file ACL ! \
1499
Deny entry after Allow entry. Failing to set on file %s.\n", fsp->fsp_name ));
1500
free_canon_ace_list(file_ace);
1501
free_canon_ace_list(dir_ace);
1505
if( DEBUGLVL( 10 )) {
1506
dbgtext("create_canon_ace_lists: adding file ACL:\n");
1507
print_canon_ace( current_ace, 0);
1509
all_aces_are_inherit_only = False;
1511
* We must not free current_ace here as its
1512
* pointer is now owned by the file_ace list.
1518
* Free if ACE was not added.
1521
SAFE_FREE(current_ace);
1524
if (fsp->is_directory && all_aces_are_inherit_only) {
1526
* Windows 2000 is doing one of these weird 'inherit acl'
1527
* traverses to conserve NTFS ACL resources. Just pretend
1528
* there was no DACL sent. JRA.
1531
DEBUG(10,("create_canon_ace_lists: Win2k inherit acl traverse. Ignoring DACL.\n"));
1532
free_canon_ace_list(file_ace);
1533
free_canon_ace_list(dir_ace);
1538
* Check if we have SMB_ACL_USER_OBJ and SMB_ACL_GROUP_OBJ entries in each
1539
* ACL. If we don't have them, check if any SMB_ACL_USER/SMB_ACL_GROUP
1540
* entries can be converted to *_OBJ. Usually we will already have these
1541
* entries in the Default ACL, and the Access ACL will not have them.
1544
check_owning_objs(file_ace, pfile_owner_sid, pfile_grp_sid);
1547
check_owning_objs(dir_ace, pfile_owner_sid, pfile_grp_sid);
1551
*ppfile_ace = file_ace;
1552
*ppdir_ace = dir_ace;
1557
/****************************************************************************
1558
ASCII art time again... JRA :-).
1560
We have 4 cases to process when moving from an NT ACL to a POSIX ACL. Firstly,
1561
we insist the ACL is in canonical form (ie. all DENY entries preceede ALLOW
1562
entries). Secondly, the merge code has ensured that all duplicate SID entries for
1563
allow or deny have been merged, so the same SID can only appear once in the deny
1564
list or once in the allow list.
1566
We then process as follows :
1568
---------------------------------------------------------------------------
1569
First pass - look for a Everyone DENY entry.
1571
If it is deny all (rwx) trunate the list at this point.
1572
Else, walk the list from this point and use the deny permissions of this
1573
entry as a mask on all following allow entries. Finally, delete
1574
the Everyone DENY entry (we have applied it to everything possible).
1576
In addition, in this pass we remove any DENY entries that have
1577
no permissions (ie. they are a DENY nothing).
1578
---------------------------------------------------------------------------
1579
Second pass - only deal with deny user entries.
1581
DENY user1 (perms XXX)
1584
for all following allow group entries where user1 is in group
1585
new_perms |= group_perms;
1587
user1 entry perms = new_perms & ~ XXX;
1589
Convert the deny entry to an allow entry with the new perms and
1590
push to the end of the list. Note if the user was in no groups
1591
this maps to a specific allow nothing entry for this user.
1593
The common case from the NT ACL choser (userX deny all) is
1594
optimised so we don't do the group lookup - we just map to
1595
an allow nothing entry.
1597
What we're doing here is inferring the allow permissions the
1598
person setting the ACE on user1 wanted by looking at the allow
1599
permissions on the groups the user is currently in. This will
1600
be a snapshot, depending on group membership but is the best
1601
we can do and has the advantage of failing closed rather than
1603
---------------------------------------------------------------------------
1604
Third pass - only deal with deny group entries.
1606
DENY group1 (perms XXX)
1608
for all following allow user entries where user is in group1
1609
user entry perms = user entry perms & ~ XXX;
1611
If there is a group Everyone allow entry with permissions YYY,
1612
convert the group1 entry to an allow entry and modify its
1615
new_perms = YYY & ~ XXX
1617
and push to the end of the list.
1619
If there is no group Everyone allow entry then convert the
1620
group1 entry to a allow nothing entry and push to the end of the list.
1622
Note that the common case from the NT ACL choser (groupX deny all)
1623
cannot be optimised here as we need to modify user entries who are
1624
in the group to change them to a deny all also.
1626
What we're doing here is modifying the allow permissions of
1627
user entries (which are more specific in POSIX ACLs) to mask
1628
out the explicit deny set on the group they are in. This will
1629
be a snapshot depending on current group membership but is the
1630
best we can do and has the advantage of failing closed rather
1632
---------------------------------------------------------------------------
1633
Fourth pass - cope with cumulative permissions.
1635
for all allow user entries, if there exists an allow group entry with
1636
more permissive permissions, and the user is in that group, rewrite the
1637
allow user permissions to contain both sets of permissions.
1639
Currently the code for this is #ifdef'ed out as these semantics make
1640
no sense to me. JRA.
1641
---------------------------------------------------------------------------
1643
Note we *MUST* do the deny user pass first as this will convert deny user
1644
entries into allow user entries which can then be processed by the deny
1647
The above algorithm took a *lot* of thinking about - hence this
1648
explaination :-). JRA.
1649
****************************************************************************/
1651
/****************************************************************************
1652
Process a canon_ace list entries. This is very complex code. We need
1653
to go through and remove the "deny" permissions from any allow entry that matches
1654
the id of this entry. We have already refused any NT ACL that wasn't in correct
1655
order (DENY followed by ALLOW). If any allow entry ends up with zero permissions,
1656
we just remove it (to fail safe). We have already removed any duplicate ace
1657
entries. Treat an "Everyone" DENY_ACE as a special case - use it to mask all
1659
****************************************************************************/
1661
static void process_deny_list( canon_ace **pp_ace_list )
1663
canon_ace *ace_list = *pp_ace_list;
1664
canon_ace *curr_ace = NULL;
1665
canon_ace *curr_ace_next = NULL;
1667
/* Pass 1 above - look for an Everyone, deny entry. */
1669
for (curr_ace = ace_list; curr_ace; curr_ace = curr_ace_next) {
1670
canon_ace *allow_ace_p;
1672
curr_ace_next = curr_ace->next; /* So we can't lose the link. */
1674
if (curr_ace->attr != DENY_ACE)
1677
if (curr_ace->perms == (mode_t)0) {
1679
/* Deny nothing entry - delete. */
1681
DLIST_REMOVE(ace_list, curr_ace);
1685
if (!sid_equal(&curr_ace->trustee, &global_sid_World))
1688
/* JRATEST - assert. */
1689
SMB_ASSERT(curr_ace->owner_type == WORLD_ACE);
1691
if (curr_ace->perms == ALL_ACE_PERMS) {
1694
* Optimisation. This is a DENY_ALL to Everyone. Truncate the
1695
* list at this point including this entry.
1698
canon_ace *prev_entry = curr_ace->prev;
1700
free_canon_ace_list( curr_ace );
1702
prev_entry->next = NULL;
1704
/* We deleted the entire list. */
1710
for (allow_ace_p = curr_ace->next; allow_ace_p; allow_ace_p = allow_ace_p->next) {
1713
* Only mask off allow entries.
1716
if (allow_ace_p->attr != ALLOW_ACE)
1719
allow_ace_p->perms &= ~curr_ace->perms;
1723
* Now it's been applied, remove it.
1726
DLIST_REMOVE(ace_list, curr_ace);
1729
/* Pass 2 above - deal with deny user entries. */
1731
for (curr_ace = ace_list; curr_ace; curr_ace = curr_ace_next) {
1732
mode_t new_perms = (mode_t)0;
1733
canon_ace *allow_ace_p;
1736
curr_ace_next = curr_ace->next; /* So we can't lose the link. */
1738
if (curr_ace->attr != DENY_ACE)
1741
if (curr_ace->owner_type != UID_ACE)
1744
if (curr_ace->perms == ALL_ACE_PERMS) {
1747
* Optimisation - this is a deny everything to this user.
1748
* Convert to an allow nothing and push to the end of the list.
1751
curr_ace->attr = ALLOW_ACE;
1752
curr_ace->perms = (mode_t)0;
1753
DLIST_DEMOTE(ace_list, curr_ace, tmp_ace);
1757
for (allow_ace_p = curr_ace->next; allow_ace_p; allow_ace_p = allow_ace_p->next) {
1759
if (allow_ace_p->attr != ALLOW_ACE)
1762
/* We process GID_ACE and WORLD_ACE entries only. */
1764
if (allow_ace_p->owner_type == UID_ACE)
1767
if (uid_entry_in_group( curr_ace, allow_ace_p))
1768
new_perms |= allow_ace_p->perms;
1772
* Convert to a allow entry, modify the perms and push to the end
1776
curr_ace->attr = ALLOW_ACE;
1777
curr_ace->perms = (new_perms & ~curr_ace->perms);
1778
DLIST_DEMOTE(ace_list, curr_ace, tmp_ace);
1781
/* Pass 3 above - deal with deny group entries. */
1783
for (curr_ace = ace_list; curr_ace; curr_ace = curr_ace_next) {
1785
canon_ace *allow_ace_p;
1786
canon_ace *allow_everyone_p = NULL;
1788
curr_ace_next = curr_ace->next; /* So we can't lose the link. */
1790
if (curr_ace->attr != DENY_ACE)
1793
if (curr_ace->owner_type != GID_ACE)
1796
for (allow_ace_p = curr_ace->next; allow_ace_p; allow_ace_p = allow_ace_p->next) {
1798
if (allow_ace_p->attr != ALLOW_ACE)
1801
/* Store a pointer to the Everyone allow, if it exists. */
1802
if (allow_ace_p->owner_type == WORLD_ACE)
1803
allow_everyone_p = allow_ace_p;
1805
/* We process UID_ACE entries only. */
1807
if (allow_ace_p->owner_type != UID_ACE)
1810
/* Mask off the deny group perms. */
1812
if (uid_entry_in_group( allow_ace_p, curr_ace))
1813
allow_ace_p->perms &= ~curr_ace->perms;
1817
* Convert the deny to an allow with the correct perms and
1818
* push to the end of the list.
1821
curr_ace->attr = ALLOW_ACE;
1822
if (allow_everyone_p)
1823
curr_ace->perms = allow_everyone_p->perms & ~curr_ace->perms;
1825
curr_ace->perms = (mode_t)0;
1826
DLIST_DEMOTE(ace_list, curr_ace, tmp_ace);
1830
/* Doing this fourth pass allows Windows semantics to be layered
1831
* on top of POSIX semantics. I'm not sure if this is desirable.
1832
* For example, in W2K ACLs there is no way to say, "Group X no
1833
* access, user Y full access" if user Y is a member of group X.
1834
* This seems completely broken semantics to me.... JRA.
1838
/* Pass 4 above - deal with allow entries. */
1840
for (curr_ace = ace_list; curr_ace; curr_ace = curr_ace_next) {
1841
canon_ace *allow_ace_p;
1843
curr_ace_next = curr_ace->next; /* So we can't lose the link. */
1845
if (curr_ace->attr != ALLOW_ACE)
1848
if (curr_ace->owner_type != UID_ACE)
1851
for (allow_ace_p = ace_list; allow_ace_p; allow_ace_p = allow_ace_p->next) {
1853
if (allow_ace_p->attr != ALLOW_ACE)
1856
/* We process GID_ACE entries only. */
1858
if (allow_ace_p->owner_type != GID_ACE)
1861
/* OR in the group perms. */
1863
if (uid_entry_in_group( curr_ace, allow_ace_p))
1864
curr_ace->perms |= allow_ace_p->perms;
1869
*pp_ace_list = ace_list;
1872
/****************************************************************************
1873
Create a default mode that will be used if a security descriptor entry has
1874
no user/group/world entries.
1875
****************************************************************************/
1877
static mode_t create_default_mode(files_struct *fsp, BOOL interitable_mode)
1879
int snum = SNUM(fsp->conn);
1880
mode_t and_bits = (mode_t)0;
1881
mode_t or_bits = (mode_t)0;
1882
mode_t mode = interitable_mode ? unix_mode( fsp->conn, FILE_ATTRIBUTE_ARCHIVE, fsp->fsp_name, False) : S_IRUSR;
1884
if (fsp->is_directory)
1885
mode |= (S_IWUSR|S_IXUSR);
1888
* Now AND with the create mode/directory mode bits then OR with the
1889
* force create mode/force directory mode bits.
1892
if (fsp->is_directory) {
1893
and_bits = lp_dir_security_mask(snum);
1894
or_bits = lp_force_dir_security_mode(snum);
1896
and_bits = lp_security_mask(snum);
1897
or_bits = lp_force_security_mode(snum);
1900
return ((mode & and_bits)|or_bits);
1903
/****************************************************************************
1904
Unpack a SEC_DESC into two canonical ace lists. We don't depend on this
1906
****************************************************************************/
1908
static BOOL unpack_canon_ace(files_struct *fsp,
1909
SMB_STRUCT_STAT *pst,
1910
DOM_SID *pfile_owner_sid,
1911
DOM_SID *pfile_grp_sid,
1912
canon_ace **ppfile_ace, canon_ace **ppdir_ace,
1913
uint32 security_info_sent, SEC_DESC *psd)
1915
canon_ace *file_ace = NULL;
1916
canon_ace *dir_ace = NULL;
1921
if(security_info_sent == 0) {
1922
DEBUG(0,("unpack_canon_ace: no security info sent !\n"));
1927
* If no DACL then this is a chown only security descriptor.
1930
if(!(security_info_sent & DACL_SECURITY_INFORMATION) || !psd->dacl)
1934
* Now go through the DACL and create the canon_ace lists.
1937
if (!create_canon_ace_lists( fsp, pst, pfile_owner_sid, pfile_grp_sid,
1938
&file_ace, &dir_ace, psd->dacl))
1941
if ((file_ace == NULL) && (dir_ace == NULL)) {
1942
/* W2K traverse DACL set - ignore. */
1947
* Go through the canon_ace list and merge entries
1948
* belonging to identical users of identical allow or deny type.
1949
* We can do this as all deny entries come first, followed by
1950
* all allow entries (we have mandated this before accepting this acl).
1953
print_canon_ace_list( "file ace - before merge", file_ace);
1954
merge_aces( &file_ace );
1956
print_canon_ace_list( "dir ace - before merge", dir_ace);
1957
merge_aces( &dir_ace );
1960
* NT ACLs are order dependent. Go through the acl lists and
1961
* process DENY entries by masking the allow entries.
1964
print_canon_ace_list( "file ace - before deny", file_ace);
1965
process_deny_list( &file_ace);
1967
print_canon_ace_list( "dir ace - before deny", dir_ace);
1968
process_deny_list( &dir_ace);
1971
* A well formed POSIX file or default ACL has at least 3 entries, a
1972
* SMB_ACL_USER_OBJ, SMB_ACL_GROUP_OBJ, SMB_ACL_OTHER_OBJ
1973
* and optionally a mask entry. Ensure this is the case.
1976
print_canon_ace_list( "file ace - before valid", file_ace);
1979
* A default 3 element mode entry for a file should be r-- --- ---.
1980
* A default 3 element mode entry for a directory should be rwx --- ---.
1983
pst->st_mode = create_default_mode(fsp, False);
1985
if (!ensure_canon_entry_valid(&file_ace, fsp, pfile_owner_sid, pfile_grp_sid, pst, True)) {
1986
free_canon_ace_list(file_ace);
1987
free_canon_ace_list(dir_ace);
1991
print_canon_ace_list( "dir ace - before valid", dir_ace);
1994
* A default inheritable 3 element mode entry for a directory should be the
1995
* mode Samba will use to create a file within. Ensure user rwx bits are set if
1999
pst->st_mode = create_default_mode(fsp, True);
2001
if (dir_ace && !ensure_canon_entry_valid(&dir_ace, fsp, pfile_owner_sid, pfile_grp_sid, pst, True)) {
2002
free_canon_ace_list(file_ace);
2003
free_canon_ace_list(dir_ace);
2007
print_canon_ace_list( "file ace - return", file_ace);
2008
print_canon_ace_list( "dir ace - return", dir_ace);
2010
*ppfile_ace = file_ace;
2011
*ppdir_ace = dir_ace;
2016
/******************************************************************************
2017
When returning permissions, try and fit NT display
2018
semantics if possible. Note the the canon_entries here must have been malloced.
2019
The list format should be - first entry = owner, followed by group and other user
2020
entries, last entry = other.
2022
Note that this doesn't exactly match the NT semantics for an ACL. As POSIX entries
2023
are not ordered, and match on the most specific entry rather than walking a list,
2024
then a simple POSIX permission of rw-r--r-- should really map to 5 entries,
2026
Entry 0: owner : deny all except read and write.
2027
Entry 1: owner : allow read and write.
2028
Entry 2: group : deny all except read.
2029
Entry 3: group : allow read.
2030
Entry 4: Everyone : allow read.
2032
But NT cannot display this in their ACL editor !
2033
********************************************************************************/
2035
static void arrange_posix_perms( char *filename, canon_ace **pp_list_head)
2037
canon_ace *list_head = *pp_list_head;
2038
canon_ace *owner_ace = NULL;
2039
canon_ace *other_ace = NULL;
2040
canon_ace *ace = NULL;
2042
for (ace = list_head; ace; ace = ace->next) {
2043
if (ace->type == SMB_ACL_USER_OBJ)
2045
else if (ace->type == SMB_ACL_OTHER) {
2046
/* Last ace - this is "other" */
2051
if (!owner_ace || !other_ace) {
2052
DEBUG(0,("arrange_posix_perms: Invalid POSIX permissions for file %s, missing owner or other.\n",
2058
* The POSIX algorithm applies to owner first, and other last,
2059
* so ensure they are arranged in this order.
2063
DLIST_PROMOTE(list_head, owner_ace);
2067
DLIST_DEMOTE(list_head, other_ace, ace);
2070
/* We have probably changed the head of the list. */
2072
*pp_list_head = list_head;
2075
/****************************************************************************
2076
Create a linked list of canonical ACE entries.
2077
****************************************************************************/
2079
static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_STRUCT_STAT *psbuf,
2080
const DOM_SID *powner, const DOM_SID *pgroup, struct pai_val *pal, SMB_ACL_TYPE_T the_acl_type)
2082
connection_struct *conn = fsp->conn;
2083
mode_t acl_mask = (S_IRUSR|S_IWUSR|S_IXUSR);
2084
canon_ace *list_head = NULL;
2085
canon_ace *ace = NULL;
2086
canon_ace *next_ace = NULL;
2087
int entry_id = SMB_ACL_FIRST_ENTRY;
2088
SMB_ACL_ENTRY_T entry;
2091
while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2092
SMB_ACL_TAG_T tagtype;
2093
SMB_ACL_PERMSET_T permset;
2096
enum ace_owner owner_type;
2099
if (entry_id == SMB_ACL_FIRST_ENTRY)
2100
entry_id = SMB_ACL_NEXT_ENTRY;
2102
/* Is this a MASK entry ? */
2103
if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1)
2106
if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1)
2109
/* Decide which SID to use based on the ACL type. */
2111
case SMB_ACL_USER_OBJ:
2112
/* Get the SID from the owner. */
2113
sid_copy(&sid, powner);
2114
unix_ug.uid = psbuf->st_uid;
2115
owner_type = UID_ACE;
2119
uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2121
DEBUG(0,("canonicalise_acl: Failed to get uid.\n"));
2125
* A SMB_ACL_USER entry for the owner is shadowed by the
2126
* SMB_ACL_USER_OBJ entry and Windows also cannot represent
2127
* that entry, so we ignore it. We also don't create such
2128
* entries out of the blue when setting ACLs, so a get/set
2129
* cycle will drop them.
2131
if (the_acl_type == SMB_ACL_TYPE_ACCESS && *puid == psbuf->st_uid) {
2132
SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2135
uid_to_sid( &sid, *puid);
2136
unix_ug.uid = *puid;
2137
owner_type = UID_ACE;
2138
SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2141
case SMB_ACL_GROUP_OBJ:
2142
/* Get the SID from the owning group. */
2143
sid_copy(&sid, pgroup);
2144
unix_ug.gid = psbuf->st_gid;
2145
owner_type = GID_ACE;
2149
gid_t *pgid = (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2151
DEBUG(0,("canonicalise_acl: Failed to get gid.\n"));
2154
gid_to_sid( &sid, *pgid);
2155
unix_ug.gid = *pgid;
2156
owner_type = GID_ACE;
2157
SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2161
acl_mask = convert_permset_to_mode_t(conn, permset);
2162
continue; /* Don't count the mask as an entry. */
2164
/* Use the Everyone SID */
2165
sid = global_sid_World;
2167
owner_type = WORLD_ACE;
2170
DEBUG(0,("canonicalise_acl: Unknown tagtype %u\n", (unsigned int)tagtype));
2175
* Add this entry to the list.
2178
if ((ace = SMB_MALLOC_P(canon_ace)) == NULL)
2182
ace->type = tagtype;
2183
ace->perms = convert_permset_to_mode_t(conn, permset);
2184
ace->attr = ALLOW_ACE;
2186
ace->unix_ug = unix_ug;
2187
ace->owner_type = owner_type;
2188
ace->inherited = get_inherited_flag(pal, ace, (the_acl_type == SMB_ACL_TYPE_DEFAULT));
2190
DLIST_ADD(list_head, ace);
2194
* This next call will ensure we have at least a user/group/world set.
2197
if (!ensure_canon_entry_valid(&list_head, fsp, powner, pgroup, psbuf, False))
2201
* Now go through the list, masking the permissions with the
2202
* acl_mask. Ensure all DENY Entries are at the start of the list.
2205
DEBUG(10,("canonicalise_acl: %s ace entries before arrange :\n", the_acl_type == SMB_ACL_TYPE_ACCESS ? "Access" : "Default" ));
2207
for ( ace_count = 0, ace = list_head; ace; ace = next_ace, ace_count++) {
2208
next_ace = ace->next;
2210
/* Masks are only applied to entries other than USER_OBJ and OTHER. */
2211
if (ace->type != SMB_ACL_OTHER && ace->type != SMB_ACL_USER_OBJ)
2212
ace->perms &= acl_mask;
2214
if (ace->perms == 0) {
2215
DLIST_PROMOTE(list_head, ace);
2218
if( DEBUGLVL( 10 ) ) {
2219
print_canon_ace(ace, ace_count);
2223
arrange_posix_perms(fsp->fsp_name,&list_head );
2225
print_canon_ace_list( "canonicalise_acl: ace entries after arrange", list_head );
2231
free_canon_ace_list(list_head);
2235
/****************************************************************************
2236
Check if the current user group list contains a given group.
2237
****************************************************************************/
2239
static BOOL current_user_in_group(gid_t gid)
2243
for (i = 0; i < current_user.ut.ngroups; i++) {
2244
if (current_user.ut.groups[i] == gid) {
2252
/****************************************************************************
2253
Should we override a deny ? Check deprecated 'acl group control'
2255
****************************************************************************/
2257
static BOOL acl_group_override(connection_struct *conn, gid_t prim_gid)
2259
if ( (errno == EACCES || errno == EPERM)
2260
&& (lp_acl_group_control(SNUM(conn) || lp_dos_filemode(SNUM(conn))))
2261
&& current_user_in_group(prim_gid) )
2269
/****************************************************************************
2270
Attempt to apply an ACL to a file or directory.
2271
****************************************************************************/
2273
static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL default_ace, gid_t prim_gid, BOOL *pacl_set_support)
2275
connection_struct *conn = fsp->conn;
2277
SMB_ACL_T the_acl = SMB_VFS_SYS_ACL_INIT(conn, (int)count_canon_ace_list(the_ace) + 1);
2280
SMB_ACL_ENTRY_T mask_entry;
2281
BOOL got_mask_entry = False;
2282
SMB_ACL_PERMSET_T mask_permset;
2283
SMB_ACL_TYPE_T the_acl_type = (default_ace ? SMB_ACL_TYPE_DEFAULT : SMB_ACL_TYPE_ACCESS);
2284
BOOL needs_mask = False;
2285
mode_t mask_perms = 0;
2287
#if defined(POSIX_ACL_NEEDS_MASK)
2288
/* HP-UX always wants to have a mask (called "class" there). */
2292
if (the_acl == NULL) {
2294
if (!no_acl_syscall_error(errno)) {
2296
* Only print this error message if we have some kind of ACL
2297
* support that's not working. Otherwise we would always get this.
2299
DEBUG(0,("set_canon_ace_list: Unable to init %s ACL. (%s)\n",
2300
default_ace ? "default" : "file", strerror(errno) ));
2302
*pacl_set_support = False;
2306
if( DEBUGLVL( 10 )) {
2307
dbgtext("set_canon_ace_list: setting ACL:\n");
2308
for (i = 0, p_ace = the_ace; p_ace; p_ace = p_ace->next, i++ ) {
2309
print_canon_ace( p_ace, i);
2313
for (i = 0, p_ace = the_ace; p_ace; p_ace = p_ace->next, i++ ) {
2314
SMB_ACL_ENTRY_T the_entry;
2315
SMB_ACL_PERMSET_T the_permset;
2318
* ACLs only "need" an ACL_MASK entry if there are any named user or
2319
* named group entries. But if there is an ACL_MASK entry, it applies
2320
* to ACL_USER, ACL_GROUP, and ACL_GROUP_OBJ entries. Set the mask
2321
* so that it doesn't deny (i.e., mask off) any permissions.
2324
if (p_ace->type == SMB_ACL_USER || p_ace->type == SMB_ACL_GROUP) {
2326
mask_perms |= p_ace->perms;
2327
} else if (p_ace->type == SMB_ACL_GROUP_OBJ) {
2328
mask_perms |= p_ace->perms;
2332
* Get the entry for this ACE.
2335
if (SMB_VFS_SYS_ACL_CREATE_ENTRY(conn, &the_acl, &the_entry) == -1) {
2336
DEBUG(0,("set_canon_ace_list: Failed to create entry %d. (%s)\n",
2337
i, strerror(errno) ));
2341
if (p_ace->type == SMB_ACL_MASK) {
2342
mask_entry = the_entry;
2343
got_mask_entry = True;
2347
* Ok - we now know the ACL calls should be working, don't
2348
* allow fallback to chmod.
2351
*pacl_set_support = True;
2354
* Initialise the entry from the canon_ace.
2358
* First tell the entry what type of ACE this is.
2361
if (SMB_VFS_SYS_ACL_SET_TAG_TYPE(conn, the_entry, p_ace->type) == -1) {
2362
DEBUG(0,("set_canon_ace_list: Failed to set tag type on entry %d. (%s)\n",
2363
i, strerror(errno) ));
2368
* Only set the qualifier (user or group id) if the entry is a user
2372
if ((p_ace->type == SMB_ACL_USER) || (p_ace->type == SMB_ACL_GROUP)) {
2373
if (SMB_VFS_SYS_ACL_SET_QUALIFIER(conn, the_entry,(void *)&p_ace->unix_ug.uid) == -1) {
2374
DEBUG(0,("set_canon_ace_list: Failed to set qualifier on entry %d. (%s)\n",
2375
i, strerror(errno) ));
2381
* Convert the mode_t perms in the canon_ace to a POSIX permset.
2384
if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, the_entry, &the_permset) == -1) {
2385
DEBUG(0,("set_canon_ace_list: Failed to get permset on entry %d. (%s)\n",
2386
i, strerror(errno) ));
2390
if (map_acl_perms_to_permset(conn, p_ace->perms, &the_permset) == -1) {
2391
DEBUG(0,("set_canon_ace_list: Failed to create permset for mode (%u) on entry %d. (%s)\n",
2392
(unsigned int)p_ace->perms, i, strerror(errno) ));
2397
* ..and apply them to the entry.
2400
if (SMB_VFS_SYS_ACL_SET_PERMSET(conn, the_entry, the_permset) == -1) {
2401
DEBUG(0,("set_canon_ace_list: Failed to add permset on entry %d. (%s)\n",
2402
i, strerror(errno) ));
2407
print_canon_ace( p_ace, i);
2411
if (needs_mask && !got_mask_entry) {
2412
if (SMB_VFS_SYS_ACL_CREATE_ENTRY(conn, &the_acl, &mask_entry) == -1) {
2413
DEBUG(0,("set_canon_ace_list: Failed to create mask entry. (%s)\n", strerror(errno) ));
2417
if (SMB_VFS_SYS_ACL_SET_TAG_TYPE(conn, mask_entry, SMB_ACL_MASK) == -1) {
2418
DEBUG(0,("set_canon_ace_list: Failed to set tag type on mask entry. (%s)\n",strerror(errno) ));
2422
if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, mask_entry, &mask_permset) == -1) {
2423
DEBUG(0,("set_canon_ace_list: Failed to get mask permset. (%s)\n", strerror(errno) ));
2427
if (map_acl_perms_to_permset(conn, S_IRUSR|S_IWUSR|S_IXUSR, &mask_permset) == -1) {
2428
DEBUG(0,("set_canon_ace_list: Failed to create mask permset. (%s)\n", strerror(errno) ));
2432
if (SMB_VFS_SYS_ACL_SET_PERMSET(conn, mask_entry, mask_permset) == -1) {
2433
DEBUG(0,("set_canon_ace_list: Failed to add mask permset. (%s)\n", strerror(errno) ));
2439
* Check if the ACL is valid.
2442
if (SMB_VFS_SYS_ACL_VALID(conn, the_acl) == -1) {
2443
DEBUG(0,("set_canon_ace_list: ACL type (%s) is invalid for set (%s).\n",
2444
the_acl_type == SMB_ACL_TYPE_DEFAULT ? "directory default" : "file",
2450
* Finally apply it to the file or directory.
2453
if(default_ace || fsp->is_directory || fsp->fh->fd == -1) {
2454
if (SMB_VFS_SYS_ACL_SET_FILE(conn, fsp->fsp_name, the_acl_type, the_acl) == -1) {
2456
* Some systems allow all the above calls and only fail with no ACL support
2457
* when attempting to apply the acl. HPUX with HFS is an example of this. JRA.
2459
if (no_acl_syscall_error(errno)) {
2460
*pacl_set_support = False;
2463
if (acl_group_override(conn, prim_gid)) {
2466
DEBUG(5,("set_canon_ace_list: acl group control on and current user in file %s primary group.\n",
2470
sret = SMB_VFS_SYS_ACL_SET_FILE(conn, fsp->fsp_name, the_acl_type, the_acl);
2478
DEBUG(2,("set_canon_ace_list: sys_acl_set_file type %s failed for file %s (%s).\n",
2479
the_acl_type == SMB_ACL_TYPE_DEFAULT ? "directory default" : "file",
2480
fsp->fsp_name, strerror(errno) ));
2485
if (SMB_VFS_SYS_ACL_SET_FD(fsp, fsp->fh->fd, the_acl) == -1) {
2487
* Some systems allow all the above calls and only fail with no ACL support
2488
* when attempting to apply the acl. HPUX with HFS is an example of this. JRA.
2490
if (no_acl_syscall_error(errno)) {
2491
*pacl_set_support = False;
2494
if (acl_group_override(conn, prim_gid)) {
2497
DEBUG(5,("set_canon_ace_list: acl group control on and current user in file %s primary group.\n",
2501
sret = SMB_VFS_SYS_ACL_SET_FD(fsp, fsp->fh->fd, the_acl);
2509
DEBUG(2,("set_canon_ace_list: sys_acl_set_file failed for file %s (%s).\n",
2510
fsp->fsp_name, strerror(errno) ));
2520
if (the_acl != NULL) {
2521
SMB_VFS_SYS_ACL_FREE_ACL(conn, the_acl);
2527
/****************************************************************************
2528
Find a particular canon_ace entry.
2529
****************************************************************************/
2531
static struct canon_ace *canon_ace_entry_for(struct canon_ace *list, SMB_ACL_TAG_T type, posix_id *id)
2534
if (list->type == type && ((type != SMB_ACL_USER && type != SMB_ACL_GROUP) ||
2535
(type == SMB_ACL_USER && id && id->uid == list->unix_ug.uid) ||
2536
(type == SMB_ACL_GROUP && id && id->gid == list->unix_ug.gid)))
2543
/****************************************************************************
2545
****************************************************************************/
2547
SMB_ACL_T free_empty_sys_acl(connection_struct *conn, SMB_ACL_T the_acl)
2549
SMB_ACL_ENTRY_T entry;
2553
if (SMB_VFS_SYS_ACL_GET_ENTRY(conn, the_acl, SMB_ACL_FIRST_ENTRY, &entry) != 1) {
2554
SMB_VFS_SYS_ACL_FREE_ACL(conn, the_acl);
2560
/****************************************************************************
2561
Convert a canon_ace to a generic 3 element permission - if possible.
2562
****************************************************************************/
2564
#define MAP_PERM(p,mask,result) (((p) & (mask)) ? (result) : 0 )
2566
static BOOL convert_canon_ace_to_posix_perms( files_struct *fsp, canon_ace *file_ace_list, mode_t *posix_perms)
2568
int snum = SNUM(fsp->conn);
2569
size_t ace_count = count_canon_ace_list(file_ace_list);
2571
canon_ace *owner_ace = NULL;
2572
canon_ace *group_ace = NULL;
2573
canon_ace *other_ace = NULL;
2577
if (ace_count != 3) {
2578
DEBUG(3,("convert_canon_ace_to_posix_perms: Too many ACE entries for file %s to convert to \
2579
posix perms.\n", fsp->fsp_name ));
2583
for (ace_p = file_ace_list; ace_p; ace_p = ace_p->next) {
2584
if (ace_p->owner_type == UID_ACE)
2586
else if (ace_p->owner_type == GID_ACE)
2588
else if (ace_p->owner_type == WORLD_ACE)
2592
if (!owner_ace || !group_ace || !other_ace) {
2593
DEBUG(3,("convert_canon_ace_to_posix_perms: Can't get standard entries for file %s.\n",
2598
*posix_perms = (mode_t)0;
2600
*posix_perms |= owner_ace->perms;
2601
*posix_perms |= MAP_PERM(group_ace->perms, S_IRUSR, S_IRGRP);
2602
*posix_perms |= MAP_PERM(group_ace->perms, S_IWUSR, S_IWGRP);
2603
*posix_perms |= MAP_PERM(group_ace->perms, S_IXUSR, S_IXGRP);
2604
*posix_perms |= MAP_PERM(other_ace->perms, S_IRUSR, S_IROTH);
2605
*posix_perms |= MAP_PERM(other_ace->perms, S_IWUSR, S_IWOTH);
2606
*posix_perms |= MAP_PERM(other_ace->perms, S_IXUSR, S_IXOTH);
2608
/* The owner must have at least read access. */
2610
*posix_perms |= S_IRUSR;
2611
if (fsp->is_directory)
2612
*posix_perms |= (S_IWUSR|S_IXUSR);
2614
/* If requested apply the masks. */
2616
/* Get the initial bits to apply. */
2618
if (fsp->is_directory) {
2619
and_bits = lp_dir_security_mask(snum);
2620
or_bits = lp_force_dir_security_mode(snum);
2622
and_bits = lp_security_mask(snum);
2623
or_bits = lp_force_security_mode(snum);
2626
*posix_perms = (((*posix_perms) & and_bits)|or_bits);
2628
DEBUG(10,("convert_canon_ace_to_posix_perms: converted u=%o,g=%o,w=%o to perm=0%o for file %s.\n",
2629
(int)owner_ace->perms, (int)group_ace->perms, (int)other_ace->perms, (int)*posix_perms,
2635
/****************************************************************************
2636
Incoming NT ACLs on a directory can be split into a default POSIX acl (CI|OI|IO) and
2637
a normal POSIX acl. Win2k needs these split acls re-merging into one ACL
2638
with CI|OI set so it is inherited and also applies to the directory.
2639
Based on code from "Jim McDonough" <jmcd@us.ibm.com>.
2640
****************************************************************************/
2642
static size_t merge_default_aces( SEC_ACE *nt_ace_list, size_t num_aces)
2646
for (i = 0; i < num_aces; i++) {
2647
for (j = i+1; j < num_aces; j++) {
2648
uint32 i_flags_ni = (nt_ace_list[i].flags & ~SEC_ACE_FLAG_INHERITED_ACE);
2649
uint32 j_flags_ni = (nt_ace_list[j].flags & ~SEC_ACE_FLAG_INHERITED_ACE);
2650
BOOL i_inh = (nt_ace_list[i].flags & SEC_ACE_FLAG_INHERITED_ACE) ? True : False;
2651
BOOL j_inh = (nt_ace_list[j].flags & SEC_ACE_FLAG_INHERITED_ACE) ? True : False;
2653
/* We know the lower number ACE's are file entries. */
2654
if ((nt_ace_list[i].type == nt_ace_list[j].type) &&
2655
(nt_ace_list[i].size == nt_ace_list[j].size) &&
2656
(nt_ace_list[i].info.mask == nt_ace_list[j].info.mask) &&
2657
sid_equal(&nt_ace_list[i].trustee, &nt_ace_list[j].trustee) &&
2659
(i_flags_ni == 0) &&
2660
(j_flags_ni == (SEC_ACE_FLAG_OBJECT_INHERIT|
2661
SEC_ACE_FLAG_CONTAINER_INHERIT|
2662
SEC_ACE_FLAG_INHERIT_ONLY))) {
2664
* W2K wants to have access allowed zero access ACE's
2665
* at the end of the list. If the mask is zero, merge
2666
* the non-inherited ACE onto the inherited ACE.
2669
if (nt_ace_list[i].info.mask == 0) {
2670
nt_ace_list[j].flags = SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT|
2671
(i_inh ? SEC_ACE_FLAG_INHERITED_ACE : 0);
2672
if (num_aces - i - 1 > 0)
2673
memmove(&nt_ace_list[i], &nt_ace_list[i+1], (num_aces-i-1) *
2676
DEBUG(10,("merge_default_aces: Merging zero access ACE %u onto ACE %u.\n",
2677
(unsigned int)i, (unsigned int)j ));
2680
* These are identical except for the flags.
2681
* Merge the inherited ACE onto the non-inherited ACE.
2684
nt_ace_list[i].flags = SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT|
2685
(i_inh ? SEC_ACE_FLAG_INHERITED_ACE : 0);
2686
if (num_aces - j - 1 > 0)
2687
memmove(&nt_ace_list[j], &nt_ace_list[j+1], (num_aces-j-1) *
2690
DEBUG(10,("merge_default_aces: Merging ACE %u onto ACE %u.\n",
2691
(unsigned int)j, (unsigned int)i ));
2701
/****************************************************************************
2702
Reply to query a security descriptor from an fsp. If it succeeds it allocates
2703
the space for the return elements and returns the size needed to return the
2704
security descriptor. This should be the only external function needed for
2705
the UNIX style get ACL.
2706
****************************************************************************/
2708
size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc)
2710
connection_struct *conn = fsp->conn;
2711
SMB_STRUCT_STAT sbuf;
2712
SEC_ACE *nt_ace_list = NULL;
2716
SEC_ACL *psa = NULL;
2717
size_t num_acls = 0;
2718
size_t num_def_acls = 0;
2719
size_t num_aces = 0;
2720
SMB_ACL_T posix_acl = NULL;
2721
SMB_ACL_T def_acl = NULL;
2722
canon_ace *file_ace = NULL;
2723
canon_ace *dir_ace = NULL;
2724
size_t num_profile_acls = 0;
2725
struct pai_val *pal = NULL;
2726
SEC_DESC *psd = NULL;
2730
DEBUG(10,("get_nt_acl: called for file %s\n", fsp->fsp_name ));
2732
if(fsp->is_directory || fsp->fh->fd == -1) {
2734
/* Get the stat struct for the owner info. */
2735
if(SMB_VFS_STAT(fsp->conn,fsp->fsp_name, &sbuf) != 0) {
2739
* Get the ACL from the path.
2742
posix_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_ACCESS);
2745
* If it's a directory get the default POSIX ACL.
2748
if(fsp->is_directory) {
2749
def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
2750
def_acl = free_empty_sys_acl(conn, def_acl);
2755
/* Get the stat struct for the owner info. */
2756
if(SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
2760
* Get the ACL from the fd.
2762
posix_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
2765
DEBUG(5,("get_nt_acl : file ACL %s, directory ACL %s\n",
2766
posix_acl ? "present" : "absent",
2767
def_acl ? "present" : "absent" ));
2769
pal = load_inherited_info(fsp);
2772
* Get the owner, group and world SIDs.
2775
if (lp_profile_acls(SNUM(conn))) {
2776
/* For WXP SP1 the owner must be administrators. */
2777
sid_copy(&owner_sid, &global_sid_Builtin_Administrators);
2778
sid_copy(&group_sid, &global_sid_Builtin_Users);
2779
num_profile_acls = 2;
2781
create_file_sids(&sbuf, &owner_sid, &group_sid);
2784
if ((security_info & DACL_SECURITY_INFORMATION) && !(security_info & PROTECTED_DACL_SECURITY_INFORMATION)) {
2787
* In the optimum case Creator Owner and Creator Group would be used for
2788
* the ACL_USER_OBJ and ACL_GROUP_OBJ entries, respectively, but this
2789
* would lead to usability problems under Windows: The Creator entries
2790
* are only available in browse lists of directories and not for files;
2791
* additionally the identity of the owning group couldn't be determined.
2792
* We therefore use those identities only for Default ACLs.
2795
/* Create the canon_ace lists. */
2796
file_ace = canonicalise_acl( fsp, posix_acl, &sbuf, &owner_sid, &group_sid, pal, SMB_ACL_TYPE_ACCESS );
2798
/* We must have *some* ACLS. */
2800
if (count_canon_ace_list(file_ace) == 0) {
2801
DEBUG(0,("get_nt_acl : No ACLs on file (%s) !\n", fsp->fsp_name ));
2805
if (fsp->is_directory && def_acl) {
2806
dir_ace = canonicalise_acl(fsp, def_acl, &sbuf,
2807
&global_sid_Creator_Owner,
2808
&global_sid_Creator_Group, pal, SMB_ACL_TYPE_DEFAULT );
2812
* Create the NT ACE list from the canonical ace lists.
2820
if (nt4_compatible_acls() && dir_ace) {
2822
* NT 4 chokes if an ACL contains an INHERIT_ONLY entry
2823
* but no non-INHERIT_ONLY entry for one SID. So we only
2824
* remove entries from the Access ACL if the
2825
* corresponding Default ACL entries have also been
2826
* removed. ACEs for CREATOR-OWNER and CREATOR-GROUP
2827
* are exceptions. We can do nothing
2828
* intelligent if the Default ACL contains entries that
2829
* are not also contained in the Access ACL, so this
2830
* case will still fail under NT 4.
2833
ace = canon_ace_entry_for(dir_ace, SMB_ACL_OTHER, NULL);
2834
if (ace && !ace->perms) {
2835
DLIST_REMOVE(dir_ace, ace);
2838
ace = canon_ace_entry_for(file_ace, SMB_ACL_OTHER, NULL);
2839
if (ace && !ace->perms) {
2840
DLIST_REMOVE(file_ace, ace);
2846
* WinNT doesn't usually have Creator Group
2847
* in browse lists, so we send this entry to
2848
* WinNT even if it contains no relevant
2849
* permissions. Once we can add
2850
* Creator Group to browse lists we can
2855
ace = canon_ace_entry_for(dir_ace, SMB_ACL_GROUP_OBJ, NULL);
2856
if (ace && !ace->perms) {
2857
DLIST_REMOVE(dir_ace, ace);
2862
ace = canon_ace_entry_for(file_ace, SMB_ACL_GROUP_OBJ, NULL);
2863
if (ace && !ace->perms) {
2864
DLIST_REMOVE(file_ace, ace);
2869
num_acls = count_canon_ace_list(file_ace);
2870
num_def_acls = count_canon_ace_list(dir_ace);
2872
/* Allocate the ace list. */
2873
if ((nt_ace_list = SMB_MALLOC_ARRAY(SEC_ACE,num_acls + num_profile_acls + num_def_acls)) == NULL) {
2874
DEBUG(0,("get_nt_acl: Unable to malloc space for nt_ace_list.\n"));
2878
memset(nt_ace_list, '\0', (num_acls + num_def_acls) * sizeof(SEC_ACE) );
2881
* Create the NT ACE list from the canonical ace lists.
2886
for (i = 0; i < num_acls; i++, ace = ace->next) {
2889
acc = map_canon_ace_perms(SNUM(conn), &nt_acl_type, &owner_sid, ace, fsp->is_directory);
2890
init_sec_ace(&nt_ace_list[num_aces++], &ace->trustee, nt_acl_type, acc, ace->inherited ? SEC_ACE_FLAG_INHERITED_ACE : 0);
2893
/* The User must have access to a profile share - even if we can't map the SID. */
2894
if (lp_profile_acls(SNUM(conn))) {
2897
init_sec_access(&acc,FILE_GENERIC_ALL);
2898
init_sec_ace(&nt_ace_list[num_aces++], &global_sid_Builtin_Users, SEC_ACE_TYPE_ACCESS_ALLOWED,
2904
for (i = 0; i < num_def_acls; i++, ace = ace->next) {
2907
acc = map_canon_ace_perms(SNUM(conn), &nt_acl_type, &owner_sid, ace, fsp->is_directory);
2908
init_sec_ace(&nt_ace_list[num_aces++], &ace->trustee, nt_acl_type, acc,
2909
SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT|
2910
SEC_ACE_FLAG_INHERIT_ONLY|
2911
(ace->inherited ? SEC_ACE_FLAG_INHERITED_ACE : 0));
2914
/* The User must have access to a profile share - even if we can't map the SID. */
2915
if (lp_profile_acls(SNUM(conn))) {
2918
init_sec_access(&acc,FILE_GENERIC_ALL);
2919
init_sec_ace(&nt_ace_list[num_aces++], &global_sid_Builtin_Users, SEC_ACE_TYPE_ACCESS_ALLOWED, acc,
2920
SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT|
2921
SEC_ACE_FLAG_INHERIT_ONLY|0);
2925
* Merge POSIX default ACLs and normal ACLs into one NT ACE.
2926
* Win2K needs this to get the inheritance correct when replacing ACLs
2927
* on a directory tree. Based on work by Jim @ IBM.
2930
num_aces = merge_default_aces(nt_ace_list, num_aces);
2935
if((psa = make_sec_acl( main_loop_talloc_get(), NT4_ACL_REVISION, num_aces, nt_ace_list)) == NULL) {
2936
DEBUG(0,("get_nt_acl: Unable to malloc space for acl.\n"));
2940
} /* security_info & DACL_SECURITY_INFORMATION */
2942
psd = make_standard_sec_desc( main_loop_talloc_get(),
2943
(security_info & OWNER_SECURITY_INFORMATION) ? &owner_sid : NULL,
2944
(security_info & GROUP_SECURITY_INFORMATION) ? &group_sid : NULL,
2949
DEBUG(0,("get_nt_acl: Unable to malloc space for security descriptor.\n"));
2955
* Windows 2000: The DACL_PROTECTED flag in the security
2956
* descriptor marks the ACL as non-inheriting, i.e., no
2957
* ACEs from higher level directories propagate to this
2958
* ACL. In the POSIX ACL model permissions are only
2959
* inherited at file create time, so ACLs never contain
2960
* any ACEs that are inherited dynamically. The DACL_PROTECTED
2961
* flag doesn't seem to bother Windows NT.
2962
* Always set this if map acl inherit is turned off.
2964
if (get_protected_flag(pal) || !lp_map_acl_inherit(SNUM(conn))) {
2965
psd->type |= SE_DESC_DACL_PROTECTED;
2969
dacl_sort_into_canonical_order(psd->dacl->ace, (unsigned int)psd->dacl->num_aces);
2977
SMB_VFS_SYS_ACL_FREE_ACL(conn, posix_acl);
2980
SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
2982
free_canon_ace_list(file_ace);
2983
free_canon_ace_list(dir_ace);
2984
free_inherited_info(pal);
2985
SAFE_FREE(nt_ace_list);
2990
/****************************************************************************
2991
Try to chown a file. We will be able to chown it under the following conditions.
2993
1) If we have root privileges, then it will just work.
2994
2) If we have SeTakeOwnershipPrivilege we can change the user to the current user.
2995
3) If we have SeRestorePrivilege we can change the user to any other user.
2996
4) If we have write permission to the file and dos_filemodes is set
2997
then allow chown to the currently authenticated user.
2998
****************************************************************************/
3000
static int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid)
3006
if(!CAN_WRITE(conn)) {
3011
/* try the direct way first */
3012
ret = SMB_VFS_CHOWN(conn, fname, uid, gid);
3016
/* Case (2) / (3) */
3017
if (lp_enable_privileges()) {
3019
BOOL has_take_ownership_priv = user_has_privileges(current_user.nt_user_token,
3020
&se_take_ownership);
3021
BOOL has_restore_priv = user_has_privileges(current_user.nt_user_token,
3025
if ( ( has_take_ownership_priv && ( uid == current_user.ut.uid ) ) ||
3027
( has_restore_priv ) ) {
3030
/* Keep the current file gid the same - take ownership doesn't imply group change. */
3031
ret = SMB_VFS_CHOWN(conn, fname, uid, (gid_t)-1);
3038
if (!lp_dos_filemode(SNUM(conn))) {
3042
if (SMB_VFS_STAT(conn,fname,&st)) {
3046
if (!NT_STATUS_IS_OK(open_file_fchmod(conn,fname,&st,&fsp))) {
3050
/* only allow chown to the current user. This is more secure,
3051
and also copes with the case where the SID in a take ownership ACL is
3052
a local SID on the users workstation
3054
uid = current_user.ut.uid;
3057
/* Keep the current file gid the same. */
3058
ret = SMB_VFS_FCHOWN(fsp, fsp->fh->fd, uid, (gid_t)-1);
3061
close_file_fchmod(fsp);
3066
/****************************************************************************
3067
Reply to set a security descriptor on an fsp. security_info_sent is the
3068
description of the following NT ACL.
3069
This should be the only external function needed for the UNIX style set ACL.
3070
****************************************************************************/
3072
BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
3074
connection_struct *conn = fsp->conn;
3075
uid_t user = (uid_t)-1;
3076
gid_t grp = (gid_t)-1;
3077
SMB_STRUCT_STAT sbuf;
3078
DOM_SID file_owner_sid;
3079
DOM_SID file_grp_sid;
3080
canon_ace *file_ace_list = NULL;
3081
canon_ace *dir_ace_list = NULL;
3082
BOOL acl_perms = False;
3083
mode_t orig_mode = (mode_t)0;
3086
BOOL need_chown = False;
3088
DEBUG(10,("set_nt_acl: called for file %s\n", fsp->fsp_name ));
3090
if (!CAN_WRITE(conn)) {
3091
DEBUG(10,("set acl rejected on read-only share\n"));
3096
* Get the current state of the file.
3099
if(fsp->is_directory || fsp->fh->fd == -1) {
3100
if(SMB_VFS_STAT(fsp->conn,fsp->fsp_name, &sbuf) != 0)
3103
if(SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0)
3107
/* Save the original elements we check against. */
3108
orig_mode = sbuf.st_mode;
3109
orig_uid = sbuf.st_uid;
3110
orig_gid = sbuf.st_gid;
3113
* Unpack the user/group/world id's.
3116
if (!unpack_nt_owners( SNUM(conn), &sbuf, &user, &grp, security_info_sent, psd)) {
3121
* Do we need to chown ?
3124
if (((user != (uid_t)-1) && (orig_uid != user)) || (( grp != (gid_t)-1) && (orig_gid != grp))) {
3129
* Chown before setting ACL only if we don't change the user, or
3130
* if we change to the current user, but not if we want to give away
3134
if (need_chown && (user == (uid_t)-1 || user == current_user.ut.uid)) {
3136
DEBUG(3,("set_nt_acl: chown %s. uid = %u, gid = %u.\n",
3137
fsp->fsp_name, (unsigned int)user, (unsigned int)grp ));
3139
if(try_chown( fsp->conn, fsp->fsp_name, user, grp) == -1) {
3140
DEBUG(3,("set_nt_acl: chown %s, %u, %u failed. Error = %s.\n",
3141
fsp->fsp_name, (unsigned int)user, (unsigned int)grp, strerror(errno) ));
3146
* Recheck the current state of the file, which may have changed.
3147
* (suid/sgid bits, for instance)
3150
if(fsp->is_directory) {
3151
if(SMB_VFS_STAT(fsp->conn, fsp->fsp_name, &sbuf) != 0) {
3158
if(fsp->fh->fd == -1)
3159
ret = SMB_VFS_STAT(fsp->conn, fsp->fsp_name, &sbuf);
3161
ret = SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf);
3167
/* Save the original elements we check against. */
3168
orig_mode = sbuf.st_mode;
3169
orig_uid = sbuf.st_uid;
3170
orig_gid = sbuf.st_gid;
3172
/* We did it, don't try again */
3176
create_file_sids(&sbuf, &file_owner_sid, &file_grp_sid);
3178
acl_perms = unpack_canon_ace( fsp, &sbuf, &file_owner_sid, &file_grp_sid,
3179
&file_ace_list, &dir_ace_list, security_info_sent, psd);
3181
/* Ignore W2K traverse DACL set. */
3182
if (file_ace_list || dir_ace_list) {
3185
DEBUG(3,("set_nt_acl: cannot set permissions\n"));
3186
free_canon_ace_list(file_ace_list);
3187
free_canon_ace_list(dir_ace_list);
3192
* Only change security if we got a DACL.
3195
if((security_info_sent & DACL_SECURITY_INFORMATION) && (psd->dacl != NULL)) {
3197
BOOL acl_set_support = False;
3201
* Try using the POSIX ACL set first. Fall back to chmod if
3202
* we have no ACL support on this filesystem.
3205
if (acl_perms && file_ace_list) {
3206
ret = set_canon_ace_list(fsp, file_ace_list, False, sbuf.st_gid, &acl_set_support);
3207
if (acl_set_support && ret == False) {
3208
DEBUG(3,("set_nt_acl: failed to set file acl on file %s (%s).\n", fsp->fsp_name, strerror(errno) ));
3209
free_canon_ace_list(file_ace_list);
3210
free_canon_ace_list(dir_ace_list);
3215
if (acl_perms && acl_set_support && fsp->is_directory) {
3217
if (!set_canon_ace_list(fsp, dir_ace_list, True, sbuf.st_gid, &acl_set_support)) {
3218
DEBUG(3,("set_nt_acl: failed to set default acl on directory %s (%s).\n", fsp->fsp_name, strerror(errno) ));
3219
free_canon_ace_list(file_ace_list);
3220
free_canon_ace_list(dir_ace_list);
3226
* No default ACL - delete one if it exists.
3229
if (SMB_VFS_SYS_ACL_DELETE_DEF_FILE(conn, fsp->fsp_name) == -1) {
3232
if (acl_group_override(conn, sbuf.st_gid)) {
3233
DEBUG(5,("set_nt_acl: acl group control on and "
3234
"current user in file %s primary group. Override delete_def_acl\n",
3238
sret = SMB_VFS_SYS_ACL_DELETE_DEF_FILE(conn, fsp->fsp_name);
3243
DEBUG(3,("set_nt_acl: sys_acl_delete_def_file failed (%s)\n", strerror(errno)));
3244
free_canon_ace_list(file_ace_list);
3245
free_canon_ace_list(dir_ace_list);
3252
if (acl_set_support) {
3253
store_inheritance_attributes(fsp, file_ace_list, dir_ace_list,
3254
(psd->type & SE_DESC_DACL_PROTECTED) ? True : False);
3258
* If we cannot set using POSIX ACLs we fall back to checking if we need to chmod.
3261
if(!acl_set_support && acl_perms) {
3264
if (!convert_canon_ace_to_posix_perms( fsp, file_ace_list, &posix_perms)) {
3265
free_canon_ace_list(file_ace_list);
3266
free_canon_ace_list(dir_ace_list);
3267
DEBUG(3,("set_nt_acl: failed to convert file acl to posix permissions for file %s.\n",
3272
if (orig_mode != posix_perms) {
3274
DEBUG(3,("set_nt_acl: chmod %s. perms = 0%o.\n",
3275
fsp->fsp_name, (unsigned int)posix_perms ));
3277
if(SMB_VFS_CHMOD(conn,fsp->fsp_name, posix_perms) == -1) {
3279
if (acl_group_override(conn, sbuf.st_gid)) {
3280
DEBUG(5,("set_nt_acl: acl group control on and "
3281
"current user in file %s primary group. Override chmod\n",
3285
sret = SMB_VFS_CHMOD(conn,fsp->fsp_name, posix_perms);
3290
DEBUG(3,("set_nt_acl: chmod %s, 0%o failed. Error = %s.\n",
3291
fsp->fsp_name, (unsigned int)posix_perms, strerror(errno) ));
3292
free_canon_ace_list(file_ace_list);
3293
free_canon_ace_list(dir_ace_list);
3301
free_canon_ace_list(file_ace_list);
3302
free_canon_ace_list(dir_ace_list);
3305
/* Any chown pending? */
3308
DEBUG(3,("set_nt_acl: chown %s. uid = %u, gid = %u.\n",
3309
fsp->fsp_name, (unsigned int)user, (unsigned int)grp ));
3311
if(try_chown( fsp->conn, fsp->fsp_name, user, grp) == -1) {
3312
DEBUG(3,("set_nt_acl: chown %s, %u, %u failed. Error = %s.\n",
3313
fsp->fsp_name, (unsigned int)user, (unsigned int)grp, strerror(errno) ));
3321
/****************************************************************************
3322
Get the actual group bits stored on a file with an ACL. Has no effect if
3323
the file has no ACL. Needed in dosmode code where the stat() will return
3324
the mask bits, not the real group bits, for a file with an ACL.
3325
****************************************************************************/
3327
int get_acl_group_bits( connection_struct *conn, const char *fname, mode_t *mode )
3329
int entry_id = SMB_ACL_FIRST_ENTRY;
3330
SMB_ACL_ENTRY_T entry;
3331
SMB_ACL_T posix_acl;
3334
posix_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3335
if (posix_acl == (SMB_ACL_T)NULL)
3338
while (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1) {
3339
SMB_ACL_TAG_T tagtype;
3340
SMB_ACL_PERMSET_T permset;
3343
if (entry_id == SMB_ACL_FIRST_ENTRY)
3344
entry_id = SMB_ACL_NEXT_ENTRY;
3346
if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) ==-1)
3349
if (tagtype == SMB_ACL_GROUP_OBJ) {
3350
if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3353
*mode &= ~(S_IRGRP|S_IWGRP|S_IXGRP);
3354
*mode |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? S_IRGRP : 0);
3355
*mode |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? S_IWGRP : 0);
3356
*mode |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? S_IXGRP : 0);
3362
SMB_VFS_SYS_ACL_FREE_ACL(conn, posix_acl);
3366
/****************************************************************************
3367
Do a chmod by setting the ACL USER_OBJ, GROUP_OBJ and OTHER bits in an ACL
3368
and set the mask to rwx. Needed to preserve complex ACLs set by NT.
3369
****************************************************************************/
3371
static int chmod_acl_internals( connection_struct *conn, SMB_ACL_T posix_acl, mode_t mode)
3373
int entry_id = SMB_ACL_FIRST_ENTRY;
3374
SMB_ACL_ENTRY_T entry;
3375
int num_entries = 0;
3377
while ( SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1) {
3378
SMB_ACL_TAG_T tagtype;
3379
SMB_ACL_PERMSET_T permset;
3383
if (entry_id == SMB_ACL_FIRST_ENTRY)
3384
entry_id = SMB_ACL_NEXT_ENTRY;
3386
if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1)
3389
if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1)
3395
case SMB_ACL_USER_OBJ:
3396
perms = unix_perms_to_acl_perms(mode, S_IRUSR, S_IWUSR, S_IXUSR);
3398
case SMB_ACL_GROUP_OBJ:
3399
perms = unix_perms_to_acl_perms(mode, S_IRGRP, S_IWGRP, S_IXGRP);
3403
* FIXME: The ACL_MASK entry permissions should really be set to
3404
* the union of the permissions of all ACL_USER,
3405
* ACL_GROUP_OBJ, and ACL_GROUP entries. That's what
3406
* acl_calc_mask() does, but Samba ACLs doesn't provide it.
3408
perms = S_IRUSR|S_IWUSR|S_IXUSR;
3411
perms = unix_perms_to_acl_perms(mode, S_IROTH, S_IWOTH, S_IXOTH);
3417
if (map_acl_perms_to_permset(conn, perms, &permset) == -1)
3420
if (SMB_VFS_SYS_ACL_SET_PERMSET(conn, entry, permset) == -1)
3425
* If this is a simple 3 element ACL or no elements then it's a standard
3426
* UNIX permission set. Just use chmod...
3429
if ((num_entries == 3) || (num_entries == 0))
3435
/****************************************************************************
3436
Get the access ACL of FROM, do a chmod by setting the ACL USER_OBJ,
3437
GROUP_OBJ and OTHER bits in an ACL and set the mask to rwx. Set the
3438
resulting ACL on TO. Note that name is in UNIX character set.
3439
****************************************************************************/
3441
static int copy_access_acl(connection_struct *conn, const char *from, const char *to, mode_t mode)
3443
SMB_ACL_T posix_acl = NULL;
3446
if ((posix_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, from, SMB_ACL_TYPE_ACCESS)) == NULL)
3449
if ((ret = chmod_acl_internals(conn, posix_acl, mode)) == -1)
3452
ret = SMB_VFS_SYS_ACL_SET_FILE(conn, to, SMB_ACL_TYPE_ACCESS, posix_acl);
3456
SMB_VFS_SYS_ACL_FREE_ACL(conn, posix_acl);
3460
/****************************************************************************
3461
Do a chmod by setting the ACL USER_OBJ, GROUP_OBJ and OTHER bits in an ACL
3462
and set the mask to rwx. Needed to preserve complex ACLs set by NT.
3463
Note that name is in UNIX character set.
3464
****************************************************************************/
3466
int chmod_acl(connection_struct *conn, const char *name, mode_t mode)
3468
return copy_access_acl(conn, name, name, mode);
3471
/****************************************************************************
3472
If "inherit permissions" is set and the parent directory has no default
3473
ACL but it does have an Access ACL, inherit this Access ACL to file name.
3474
****************************************************************************/
3476
int inherit_access_acl(connection_struct *conn, const char *name, mode_t mode)
3479
pstrcpy(dirname, parent_dirname(name));
3481
if (!lp_inherit_perms(SNUM(conn)) || directory_has_default_acl(conn, dirname))
3484
return copy_access_acl(conn, dirname, name, mode);
3487
/****************************************************************************
3488
Do an fchmod by setting the ACL USER_OBJ, GROUP_OBJ and OTHER bits in an ACL
3489
and set the mask to rwx. Needed to preserve complex ACLs set by NT.
3490
****************************************************************************/
3492
int fchmod_acl(files_struct *fsp, int fd, mode_t mode)
3494
connection_struct *conn = fsp->conn;
3495
SMB_ACL_T posix_acl = NULL;
3498
if ((posix_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fd)) == NULL)
3501
if ((ret = chmod_acl_internals(conn, posix_acl, mode)) == -1)
3504
ret = SMB_VFS_SYS_ACL_SET_FD(fsp, fd, posix_acl);
3508
SMB_VFS_SYS_ACL_FREE_ACL(conn, posix_acl);
3512
/****************************************************************************
3513
Check for an existing default POSIX ACL on a directory.
3514
****************************************************************************/
3516
BOOL directory_has_default_acl(connection_struct *conn, const char *fname)
3518
SMB_ACL_T def_acl = SMB_VFS_SYS_ACL_GET_FILE( conn, fname, SMB_ACL_TYPE_DEFAULT);
3519
BOOL has_acl = False;
3520
SMB_ACL_ENTRY_T entry;
3522
if (def_acl != NULL && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, def_acl, SMB_ACL_FIRST_ENTRY, &entry) == 1)) {
3527
SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3532
/****************************************************************************
3533
Map from wire type to permset.
3534
****************************************************************************/
3536
static BOOL unix_ex_wire_to_permset(connection_struct *conn, unsigned char wire_perm, SMB_ACL_PERMSET_T *p_permset)
3538
if (wire_perm & ~(SMB_POSIX_ACL_READ|SMB_POSIX_ACL_WRITE|SMB_POSIX_ACL_EXECUTE)) {
3542
if (SMB_VFS_SYS_ACL_CLEAR_PERMS(conn, *p_permset) == -1) {
3546
if (wire_perm & SMB_POSIX_ACL_READ) {
3547
if (SMB_VFS_SYS_ACL_ADD_PERM(conn, *p_permset, SMB_ACL_READ) == -1) {
3551
if (wire_perm & SMB_POSIX_ACL_WRITE) {
3552
if (SMB_VFS_SYS_ACL_ADD_PERM(conn, *p_permset, SMB_ACL_WRITE) == -1) {
3556
if (wire_perm & SMB_POSIX_ACL_EXECUTE) {
3557
if (SMB_VFS_SYS_ACL_ADD_PERM(conn, *p_permset, SMB_ACL_EXECUTE) == -1) {
3564
/****************************************************************************
3565
Map from wire type to tagtype.
3566
****************************************************************************/
3568
static BOOL unix_ex_wire_to_tagtype(unsigned char wire_tt, SMB_ACL_TAG_T *p_tt)
3571
case SMB_POSIX_ACL_USER_OBJ:
3572
*p_tt = SMB_ACL_USER_OBJ;
3574
case SMB_POSIX_ACL_USER:
3575
*p_tt = SMB_ACL_USER;
3577
case SMB_POSIX_ACL_GROUP_OBJ:
3578
*p_tt = SMB_ACL_GROUP_OBJ;
3580
case SMB_POSIX_ACL_GROUP:
3581
*p_tt = SMB_ACL_GROUP;
3583
case SMB_POSIX_ACL_MASK:
3584
*p_tt = SMB_ACL_MASK;
3586
case SMB_POSIX_ACL_OTHER:
3587
*p_tt = SMB_ACL_OTHER;
3595
/****************************************************************************
3596
Create a new POSIX acl from wire permissions.
3597
FIXME ! How does the share mask/mode fit into this.... ?
3598
****************************************************************************/
3600
static SMB_ACL_T create_posix_acl_from_wire(connection_struct *conn, uint16 num_acls, const char *pdata)
3603
SMB_ACL_T the_acl = SMB_VFS_SYS_ACL_INIT(conn, num_acls);
3605
if (the_acl == NULL) {
3609
for (i = 0; i < num_acls; i++) {
3610
SMB_ACL_ENTRY_T the_entry;
3611
SMB_ACL_PERMSET_T the_permset;
3612
SMB_ACL_TAG_T tag_type;
3614
if (SMB_VFS_SYS_ACL_CREATE_ENTRY(conn, &the_acl, &the_entry) == -1) {
3615
DEBUG(0,("create_posix_acl_from_wire: Failed to create entry %u. (%s)\n",
3616
i, strerror(errno) ));
3620
if (!unix_ex_wire_to_tagtype(CVAL(pdata,(i*SMB_POSIX_ACL_ENTRY_SIZE)), &tag_type)) {
3621
DEBUG(0,("create_posix_acl_from_wire: invalid wire tagtype %u on entry %u.\n",
3622
CVAL(pdata,(i*SMB_POSIX_ACL_ENTRY_SIZE)), i ));
3626
if (SMB_VFS_SYS_ACL_SET_TAG_TYPE(conn, the_entry, tag_type) == -1) {
3627
DEBUG(0,("create_posix_acl_from_wire: Failed to set tagtype on entry %u. (%s)\n",
3628
i, strerror(errno) ));
3632
/* Get the permset pointer from the new ACL entry. */
3633
if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, the_entry, &the_permset) == -1) {
3634
DEBUG(0,("create_posix_acl_from_wire: Failed to get permset on entry %u. (%s)\n",
3635
i, strerror(errno) ));
3639
/* Map from wire to permissions. */
3640
if (!unix_ex_wire_to_permset(conn, CVAL(pdata,(i*SMB_POSIX_ACL_ENTRY_SIZE)+1), &the_permset)) {
3641
DEBUG(0,("create_posix_acl_from_wire: invalid permset %u on entry %u.\n",
3642
CVAL(pdata,(i*SMB_POSIX_ACL_ENTRY_SIZE) + 1), i ));
3646
/* Now apply to the new ACL entry. */
3647
if (SMB_VFS_SYS_ACL_SET_PERMSET(conn, the_entry, the_permset) == -1) {
3648
DEBUG(0,("create_posix_acl_from_wire: Failed to add permset on entry %u. (%s)\n",
3649
i, strerror(errno) ));
3653
if (tag_type == SMB_ACL_USER) {
3654
uint32 uidval = IVAL(pdata,(i*SMB_POSIX_ACL_ENTRY_SIZE)+2);
3655
uid_t uid = (uid_t)uidval;
3656
if (SMB_VFS_SYS_ACL_SET_QUALIFIER(conn, the_entry,(void *)&uid) == -1) {
3657
DEBUG(0,("create_posix_acl_from_wire: Failed to set uid %u on entry %u. (%s)\n",
3658
(unsigned int)uid, i, strerror(errno) ));
3663
if (tag_type == SMB_ACL_GROUP) {
3664
uint32 gidval = IVAL(pdata,(i*SMB_POSIX_ACL_ENTRY_SIZE)+2);
3665
gid_t gid = (uid_t)gidval;
3666
if (SMB_VFS_SYS_ACL_SET_QUALIFIER(conn, the_entry,(void *)&gid) == -1) {
3667
DEBUG(0,("create_posix_acl_from_wire: Failed to set gid %u on entry %u. (%s)\n",
3668
(unsigned int)gid, i, strerror(errno) ));
3678
if (the_acl != NULL) {
3679
SMB_VFS_SYS_ACL_FREE_ACL(conn, the_acl);
3684
/****************************************************************************
3685
Calls from UNIX extensions - Default POSIX ACL set.
3686
If num_def_acls == 0 and not a directory just return. If it is a directory
3687
and num_def_acls == 0 then remove the default acl. Else set the default acl
3689
****************************************************************************/
3691
BOOL set_unix_posix_default_acl(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf,
3692
uint16 num_def_acls, const char *pdata)
3694
SMB_ACL_T def_acl = NULL;
3696
if (num_def_acls && !S_ISDIR(psbuf->st_mode)) {
3697
DEBUG(5,("set_unix_posix_default_acl: Can't set default ACL on non-directory file %s\n", fname ));
3702
if (!num_def_acls) {
3703
/* Remove the default ACL. */
3704
if (SMB_VFS_SYS_ACL_DELETE_DEF_FILE(conn, fname) == -1) {
3705
DEBUG(5,("set_unix_posix_default_acl: acl_delete_def_file failed on directory %s (%s)\n",
3706
fname, strerror(errno) ));
3712
if ((def_acl = create_posix_acl_from_wire(conn, num_def_acls, pdata)) == NULL) {
3716
if (SMB_VFS_SYS_ACL_SET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT, def_acl) == -1) {
3717
DEBUG(5,("set_unix_posix_default_acl: acl_set_file failed on directory %s (%s)\n",
3718
fname, strerror(errno) ));
3719
SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3723
DEBUG(10,("set_unix_posix_default_acl: set default acl for file %s\n", fname ));
3724
SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3728
/****************************************************************************
3729
Remove an ACL from a file. As we don't have acl_delete_entry() available
3730
we must read the current acl and copy all entries except MASK, USER and GROUP
3731
to a new acl, then set that. This (at least on Linux) causes any ACL to be
3733
FIXME ! How does the share mask/mode fit into this.... ?
3734
****************************************************************************/
3736
static BOOL remove_posix_acl(connection_struct *conn, files_struct *fsp, const char *fname)
3738
SMB_ACL_T file_acl = NULL;
3739
int entry_id = SMB_ACL_FIRST_ENTRY;
3740
SMB_ACL_ENTRY_T entry;
3742
/* Create a new ACL with only 3 entries, u/g/w. */
3743
SMB_ACL_T new_file_acl = SMB_VFS_SYS_ACL_INIT(conn, 3);
3744
SMB_ACL_ENTRY_T user_ent = NULL;
3745
SMB_ACL_ENTRY_T group_ent = NULL;
3746
SMB_ACL_ENTRY_T other_ent = NULL;
3748
if (new_file_acl == NULL) {
3749
DEBUG(5,("remove_posix_acl: failed to init new ACL with 3 entries for file %s.\n", fname));
3753
/* Now create the u/g/w entries. */
3754
if (SMB_VFS_SYS_ACL_CREATE_ENTRY(conn, &new_file_acl, &user_ent) == -1) {
3755
DEBUG(5,("remove_posix_acl: Failed to create user entry for file %s. (%s)\n",
3756
fname, strerror(errno) ));
3759
if (SMB_VFS_SYS_ACL_SET_TAG_TYPE(conn, user_ent, SMB_ACL_USER_OBJ) == -1) {
3760
DEBUG(5,("remove_posix_acl: Failed to set user entry for file %s. (%s)\n",
3761
fname, strerror(errno) ));
3765
if (SMB_VFS_SYS_ACL_CREATE_ENTRY(conn, &new_file_acl, &group_ent) == -1) {
3766
DEBUG(5,("remove_posix_acl: Failed to create group entry for file %s. (%s)\n",
3767
fname, strerror(errno) ));
3770
if (SMB_VFS_SYS_ACL_SET_TAG_TYPE(conn, group_ent, SMB_ACL_GROUP_OBJ) == -1) {
3771
DEBUG(5,("remove_posix_acl: Failed to set group entry for file %s. (%s)\n",
3772
fname, strerror(errno) ));
3776
if (SMB_VFS_SYS_ACL_CREATE_ENTRY(conn, &new_file_acl, &other_ent) == -1) {
3777
DEBUG(5,("remove_posix_acl: Failed to create other entry for file %s. (%s)\n",
3778
fname, strerror(errno) ));
3781
if (SMB_VFS_SYS_ACL_SET_TAG_TYPE(conn, other_ent, SMB_ACL_OTHER) == -1) {
3782
DEBUG(5,("remove_posix_acl: Failed to set other entry for file %s. (%s)\n",
3783
fname, strerror(errno) ));
3787
/* Get the current file ACL. */
3788
if (fsp && fsp->fh->fd != -1) {
3789
file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
3791
file_acl = SMB_VFS_SYS_ACL_GET_FILE( conn, fname, SMB_ACL_TYPE_ACCESS);
3794
if (file_acl == NULL) {
3795
/* This is only returned if an error occurred. Even for a file with
3796
no acl a u/g/w acl should be returned. */
3797
DEBUG(5,("remove_posix_acl: failed to get ACL from file %s (%s).\n",
3798
fname, strerror(errno) ));
3802
while ( SMB_VFS_SYS_ACL_GET_ENTRY(conn, file_acl, entry_id, &entry) == 1) {
3803
SMB_ACL_TAG_T tagtype;
3804
SMB_ACL_PERMSET_T permset;
3807
if (entry_id == SMB_ACL_FIRST_ENTRY)
3808
entry_id = SMB_ACL_NEXT_ENTRY;
3810
if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3811
DEBUG(5,("remove_posix_acl: failed to get tagtype from ACL on file %s (%s).\n",
3812
fname, strerror(errno) ));
3816
if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3817
DEBUG(5,("remove_posix_acl: failed to get permset from ACL on file %s (%s).\n",
3818
fname, strerror(errno) ));
3822
if (tagtype == SMB_ACL_USER_OBJ) {
3823
if (SMB_VFS_SYS_ACL_SET_PERMSET(conn, user_ent, permset) == -1) {
3824
DEBUG(5,("remove_posix_acl: failed to set permset from ACL on file %s (%s).\n",
3825
fname, strerror(errno) ));
3827
} else if (tagtype == SMB_ACL_GROUP_OBJ) {
3828
if (SMB_VFS_SYS_ACL_SET_PERMSET(conn, group_ent, permset) == -1) {
3829
DEBUG(5,("remove_posix_acl: failed to set permset from ACL on file %s (%s).\n",
3830
fname, strerror(errno) ));
3832
} else if (tagtype == SMB_ACL_OTHER) {
3833
if (SMB_VFS_SYS_ACL_SET_PERMSET(conn, other_ent, permset) == -1) {
3834
DEBUG(5,("remove_posix_acl: failed to set permset from ACL on file %s (%s).\n",
3835
fname, strerror(errno) ));
3840
/* Set the new empty file ACL. */
3841
if (fsp && fsp->fh->fd != -1) {
3842
if (SMB_VFS_SYS_ACL_SET_FD(fsp, fsp->fh->fd, new_file_acl) == -1) {
3843
DEBUG(5,("remove_posix_acl: acl_set_file failed on %s (%s)\n",
3844
fname, strerror(errno) ));
3848
if (SMB_VFS_SYS_ACL_SET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS, new_file_acl) == -1) {
3849
DEBUG(5,("remove_posix_acl: acl_set_file failed on %s (%s)\n",
3850
fname, strerror(errno) ));
3860
SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3863
SMB_VFS_SYS_ACL_FREE_ACL(conn, new_file_acl);
3868
/****************************************************************************
3869
Calls from UNIX extensions - POSIX ACL set.
3870
If num_def_acls == 0 then read/modify/write acl after removing all entries
3871
except SMB_ACL_USER_OBJ, SMB_ACL_GROUP_OBJ, SMB_ACL_OTHER.
3872
****************************************************************************/
3874
BOOL set_unix_posix_acl(connection_struct *conn, files_struct *fsp, const char *fname, uint16 num_acls, const char *pdata)
3876
SMB_ACL_T file_acl = NULL;
3879
/* Remove the ACL from the file. */
3880
return remove_posix_acl(conn, fsp, fname);
3883
if ((file_acl = create_posix_acl_from_wire(conn, num_acls, pdata)) == NULL) {
3887
if (fsp && fsp->fh->fd != -1) {
3888
/* The preferred way - use an open fd. */
3889
if (SMB_VFS_SYS_ACL_SET_FD(fsp, fsp->fh->fd, file_acl) == -1) {
3890
DEBUG(5,("set_unix_posix_acl: acl_set_file failed on %s (%s)\n",
3891
fname, strerror(errno) ));
3892
SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3896
if (SMB_VFS_SYS_ACL_SET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS, file_acl) == -1) {
3897
DEBUG(5,("set_unix_posix_acl: acl_set_file failed on %s (%s)\n",
3898
fname, strerror(errno) ));
3899
SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3904
DEBUG(10,("set_unix_posix_acl: set acl for file %s\n", fname ));
3905
SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3909
/****************************************************************************
3910
Check for POSIX group ACLs. If none use stat entry.
3911
Return -1 if no match, 0 if match and denied, 1 if match and allowed.
3912
****************************************************************************/
3914
static int check_posix_acl_group_write(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf)
3916
SMB_ACL_T posix_acl = NULL;
3917
int entry_id = SMB_ACL_FIRST_ENTRY;
3918
SMB_ACL_ENTRY_T entry;
3920
BOOL seen_mask = False;
3921
BOOL seen_owning_group = False;
3925
if ((posix_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS)) == NULL) {
3929
/* First ensure the group mask allows group read. */
3930
/* Also check any user entries (these take preference over group). */
3932
while ( SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1) {
3933
SMB_ACL_TAG_T tagtype;
3934
SMB_ACL_PERMSET_T permset;
3935
int have_write = -1;
3938
if (entry_id == SMB_ACL_FIRST_ENTRY)
3939
entry_id = SMB_ACL_NEXT_ENTRY;
3941
if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3945
if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3949
have_write = SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE);
3950
if (have_write == -1) {
3955
* Solaris returns 2 for this if write is available.
3956
* canonicalize to 0 or 1.
3958
have_write = (have_write ? 1 : 0);
3964
/* We don't have any group or explicit user write permission. */
3965
ret = -1; /* Allow caller to check "other" permissions. */
3966
DEBUG(10,("check_posix_acl_group_write: file %s \
3967
refusing write due to mask.\n", fname));
3973
/* Check against current_user.ut.uid. */
3974
uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3978
if (current_user.ut.uid == *puid) {
3979
/* We have a uid match but we must ensure we have seen the acl mask. */
3981
DEBUG(10,("check_posix_acl_group_write: file %s \
3982
match on user %u -> %s.\n", fname, (unsigned int)*puid, ret ? "can write" : "cannot write"));
3994
/* If ret is anything other than -1 we matched on a user entry. */
3999
/* Next check all group entries. */
4000
entry_id = SMB_ACL_FIRST_ENTRY;
4001
while ( SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1) {
4002
SMB_ACL_TAG_T tagtype;
4003
SMB_ACL_PERMSET_T permset;
4004
int have_write = -1;
4007
if (entry_id == SMB_ACL_FIRST_ENTRY)
4008
entry_id = SMB_ACL_NEXT_ENTRY;
4010
if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
4014
if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
4018
have_write = SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE);
4019
if (have_write == -1) {
4024
* Solaris returns 2 for this if write is available.
4025
* canonicalize to 0 or 1.
4027
have_write = (have_write ? 1 : 0);
4031
case SMB_ACL_GROUP_OBJ:
4035
if (tagtype == SMB_ACL_GROUP) {
4036
pgid = (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
4038
seen_owning_group = True;
4039
pgid = &psbuf->st_gid;
4046
* Does it match the current effective group
4047
* or supplementary groups ?
4049
for (cu_gid = get_current_user_gid_first(&i); cu_gid != (gid_t)-1;
4050
cu_gid = get_current_user_gid_next(&i)) {
4051
if (cu_gid == *pgid) {
4053
DEBUG(10,("check_posix_acl_group_write: file %s \
4054
match on group %u -> can write.\n", fname, (unsigned int)cu_gid ));
4056
/* If we don't have write permission this entry doesn't
4057
terminate the enumeration of the entries. */
4061
/* But does terminate the group iteration. */
4072
/* If ret is -1 here we didn't match on the user entry or
4073
supplemental group entries. */
4075
DEBUG(10,("check_posix_acl_group_write: ret = %d before check_stat:\n", ret));
4080
* We only check the S_IWGRP permissions if we haven't already
4081
* seen an owning group SMB_ACL_GROUP_OBJ ace entry. If there is an
4082
* SMB_ACL_GROUP_OBJ ace entry then the group bits in st_gid are
4083
* the same as the SMB_ACL_MASK bits, not the SMB_ACL_GROUP_OBJ
4084
* bits. Thanks to Marc Cousin <mcousin@sigma.fr> for pointing
4088
if (!seen_owning_group) {
4089
/* Do we match on the owning group entry ? */
4091
* Does it match the current effective group
4092
* or supplementary groups ?
4094
for (cu_gid = get_current_user_gid_first(&i); cu_gid != (gid_t)-1;
4095
cu_gid = get_current_user_gid_next(&i)) {
4096
if (cu_gid == psbuf->st_gid) {
4097
ret = (psbuf->st_mode & S_IWGRP) ? 1 : 0;
4098
DEBUG(10,("check_posix_acl_group_write: file %s \
4099
match on owning group %u -> %s.\n", fname, (unsigned int)psbuf->st_gid, ret ? "can write" : "cannot write"));
4104
if (cu_gid == (gid_t)-1) {
4105
DEBUG(10,("check_posix_acl_group_write: file %s \
4106
failed to match on user or group in token (ret = %d).\n", fname, ret ));
4113
SMB_VFS_SYS_ACL_FREE_ACL(conn, posix_acl);
4116
DEBUG(10,("check_posix_acl_group_write: file %s returning (ret = %d).\n", fname, ret ));
4120
/****************************************************************************
4121
Actually emulate the in-kernel access checking for delete access. We need
4122
this to successfully return ACCESS_DENIED on a file open for delete access.
4123
****************************************************************************/
4125
BOOL can_delete_file_in_directory(connection_struct *conn, const char *fname)
4127
SMB_STRUCT_STAT sbuf;
4131
if (!CAN_WRITE(conn)) {
4135
/* Get the parent directory permission mask and owners. */
4136
pstrcpy(dname, parent_dirname(fname));
4137
if(SMB_VFS_STAT(conn, dname, &sbuf) != 0) {
4140
if (!S_ISDIR(sbuf.st_mode)) {
4143
if (current_user.ut.uid == 0 || conn->admin_user) {
4144
/* I'm sorry sir, I didn't know you were root... */
4148
/* Check primary owner write access. */
4149
if (current_user.ut.uid == sbuf.st_uid) {
4150
return (sbuf.st_mode & S_IWUSR) ? True : False;
4154
/* sticky bit means delete only by owner or root. */
4155
if (sbuf.st_mode & S_ISVTX) {
4156
SMB_STRUCT_STAT sbuf_file;
4157
if(SMB_VFS_STAT(conn, fname, &sbuf_file) != 0) {
4161
* Patch from SATOH Fumiyasu <fumiyas@miraclelinux.com>
4162
* for bug #3348. Don't assume owning sticky bit
4163
* directory means write access allowed.
4165
if (current_user.ut.uid != sbuf_file.st_uid) {
4171
/* Check group or explicit user acl entry write access. */
4172
ret = check_posix_acl_group_write(conn, dname, &sbuf);
4173
if (ret == 0 || ret == 1) {
4174
return ret ? True : False;
4177
/* Finally check other write access. */
4178
return (sbuf.st_mode & S_IWOTH) ? True : False;
4181
/****************************************************************************
4182
Actually emulate the in-kernel access checking for write access. We need
4183
this to successfully check for ability to write for dos filetimes.
4184
Note this doesn't take into account share write permissions.
4185
****************************************************************************/
4187
BOOL can_write_to_file(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf)
4191
if (current_user.ut.uid == 0 || conn->admin_user) {
4192
/* I'm sorry sir, I didn't know you were root... */
4196
if (!VALID_STAT(*psbuf)) {
4197
/* Get the file permission mask and owners. */
4198
if(SMB_VFS_STAT(conn, fname, psbuf) != 0) {
4203
/* Check primary owner write access. */
4204
if (current_user.ut.uid == psbuf->st_uid) {
4205
return (psbuf->st_mode & S_IWUSR) ? True : False;
4208
/* Check group or explicit user acl entry write access. */
4209
ret = check_posix_acl_group_write(conn, fname, psbuf);
4210
if (ret == 0 || ret == 1) {
4211
return ret ? True : False;
4214
/* Finally check other write access. */
4215
return (psbuf->st_mode & S_IWOTH) ? True : False;
4218
/********************************************************************
4219
Pull the NT ACL from a file on disk or the OpenEventlog() access
4220
check. Caller is responsible for freeing the returned security
4221
descriptor via TALLOC_FREE(). This is designed for dealing with
4222
user space access checks in smbd outside of the VFS. For example,
4223
checking access rights in OpenEventlog().
4225
Assume we are dealing with files (for now)
4226
********************************************************************/
4228
SEC_DESC* get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fname)
4230
SEC_DESC *psd, *ret_sd;
4231
connection_struct conn;
4233
struct fd_handle fh;
4237
ZERO_STRUCT( conn );
4239
if ( !(conn.mem_ctx = talloc_init( "novfs_get_nt_acl" )) ) {
4240
DEBUG(0,("get_nt_acl_no_snum: talloc() failed!\n"));
4244
if (!(conn.params = TALLOC_P(conn.mem_ctx, struct share_params))) {
4245
DEBUG(0,("get_nt_acl_no_snum: talloc() failed!\n"));
4246
TALLOC_FREE(conn.mem_ctx);
4250
conn.params->service = -1;
4252
pstrcpy( path, "/" );
4253
set_conn_connectpath(&conn, path);
4255
if (!smbd_vfs_init(&conn)) {
4256
DEBUG(0,("get_nt_acl_no_snum: Unable to create a fake connection struct!\n"));
4257
conn_free_internal( &conn );
4261
ZERO_STRUCT( finfo );
4268
pstrcpy( filename, fname );
4269
finfo.fsp_name = filename;
4271
if (get_nt_acl( &finfo, DACL_SECURITY_INFORMATION, &psd ) == 0) {
4272
DEBUG(0,("get_nt_acl_no_snum: get_nt_acl returned zero.\n"));
4273
conn_free_internal( &conn );
4277
ret_sd = dup_sec_desc( ctx, psd );
4279
conn_free_internal( &conn );