fuzzing: fix fuzz_stable_sort_r_unstable comparison
[samba.git] / source3 / smbd / posix_acls.c
1 /*
2    Unix SMB/CIFS implementation.
3    SMB NT Security Descriptor / Unix permission conversion.
4    Copyright (C) Jeremy Allison 1994-2009.
5    Copyright (C) Andreas Gruenbacher 2002.
6    Copyright (C) Simo Sorce <idra@samba.org> 2009.
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "smbd/smbd.h"
24 #include "system/filesys.h"
25 #include "../libcli/security/security.h"
26 #include "trans2.h"
27 #include "passdb/lookup_sid.h"
28 #include "auth.h"
29 #include "../librpc/gen_ndr/idmap.h"
30 #include "../librpc/gen_ndr/ndr_smb_acl.h"
31 #include "lib/param/loadparm.h"
32
33 extern const struct generic_mapping file_generic_mapping;
34
35 #undef  DBGC_CLASS
36 #define DBGC_CLASS DBGC_ACLS
37
38 /****************************************************************************
39  Data structures representing the internal ACE format.
40 ****************************************************************************/
41
42 enum ace_owner {UID_ACE, GID_ACE, WORLD_ACE};
43 enum ace_attribute {ALLOW_ACE, DENY_ACE}; /* Used for incoming NT ACLS. */
44
45 typedef struct canon_ace {
46         struct canon_ace *next, *prev;
47         SMB_ACL_TAG_T type;
48         mode_t perms; /* Only use S_I(R|W|X)USR mode bits here. */
49         struct dom_sid trustee;
50         enum ace_owner owner_type;
51         enum ace_attribute attr;
52         struct unixid unix_ug;
53         uint8_t ace_flags; /* From windows ACE entry. */
54 } canon_ace;
55
56 #define ALL_ACE_PERMS (S_IRUSR|S_IWUSR|S_IXUSR)
57
58 /*
59  * EA format of user.SAMBA_PAI (Samba_Posix_Acl_Interitance)
60  * attribute on disk - version 1.
61  * All values are little endian.
62  *
63  * |  1   |  1   |   2         |         2           |  ....
64  * +------+------+-------------+---------------------+-------------+--------------------+
65  * | vers | flag | num_entries | num_default_entries | ..entries.. | default_entries... |
66  * +------+------+-------------+---------------------+-------------+--------------------+
67  *
68  * Entry format is :
69  *
70  * |  1   |       4           |
71  * +------+-------------------+
72  * | value|  uid/gid or world |
73  * | type |  value            |
74  * +------+-------------------+
75  *
76  * Version 2 format. Stores extra Windows metadata about an ACL.
77  *
78  * |  1   |  2       |   2         |         2           |  ....
79  * +------+----------+-------------+---------------------+-------------+--------------------+
80  * | vers | ace      | num_entries | num_default_entries | ..entries.. | default_entries... |
81  * |   2  |  type    |             |                     |             |                    |
82  * +------+----------+-------------+---------------------+-------------+--------------------+
83  *
84  * Entry format is :
85  *
86  * |  1   |  1   |       4           |
87  * +------+------+-------------------+
88  * | ace  | value|  uid/gid or world |
89  * | flag | type |  value            |
90  * +------+-------------------+------+
91  *
92  */
93
94 #define PAI_VERSION_OFFSET                      0
95
96 #define PAI_V1_FLAG_OFFSET                      1
97 #define PAI_V1_NUM_ENTRIES_OFFSET               2
98 #define PAI_V1_NUM_DEFAULT_ENTRIES_OFFSET       4
99 #define PAI_V1_ENTRIES_BASE                     6
100 #define PAI_V1_ACL_FLAG_PROTECTED               0x1
101 #define PAI_V1_ENTRY_LENGTH                     5
102
103 #define PAI_V1_VERSION                          1
104
105 #define PAI_V2_TYPE_OFFSET                      1
106 #define PAI_V2_NUM_ENTRIES_OFFSET               3
107 #define PAI_V2_NUM_DEFAULT_ENTRIES_OFFSET       5
108 #define PAI_V2_ENTRIES_BASE                     7
109 #define PAI_V2_ENTRY_LENGTH                     6
110
111 #define PAI_V2_VERSION                          2
112
113 /*
114  * In memory format of user.SAMBA_PAI attribute.
115  */
116
117 struct pai_entry {
118         struct pai_entry *next, *prev;
119         uint8_t ace_flags;
120         enum ace_owner owner_type;
121         struct unixid unix_ug;
122 };
123
124 struct pai_val {
125         uint16_t sd_type;
126         unsigned int num_entries;
127         struct pai_entry *entry_list;
128         unsigned int num_def_entries;
129         struct pai_entry *def_entry_list;
130 };
131
132 /************************************************************************
133  Return a uint32_t of the pai_entry principal.
134 ************************************************************************/
135
136 static uint32_t get_pai_entry_val(struct pai_entry *paie)
137 {
138         switch (paie->owner_type) {
139                 case UID_ACE:
140                         DEBUG(10,("get_pai_entry_val: uid = %u\n", (unsigned int)paie->unix_ug.id ));
141                         return (uint32_t)paie->unix_ug.id;
142                 case GID_ACE:
143                         DEBUG(10,("get_pai_entry_val: gid = %u\n", (unsigned int)paie->unix_ug.id ));
144                         return (uint32_t)paie->unix_ug.id;
145                 case WORLD_ACE:
146                 default:
147                         DEBUG(10,("get_pai_entry_val: world ace\n"));
148                         return (uint32_t)-1;
149         }
150 }
151
152 /************************************************************************
153  Return a uint32_t of the entry principal.
154 ************************************************************************/
155
156 static uint32_t get_entry_val(canon_ace *ace_entry)
157 {
158         switch (ace_entry->owner_type) {
159                 case UID_ACE:
160                         DEBUG(10,("get_entry_val: uid = %u\n", (unsigned int)ace_entry->unix_ug.id ));
161                         return (uint32_t)ace_entry->unix_ug.id;
162                 case GID_ACE:
163                         DEBUG(10,("get_entry_val: gid = %u\n", (unsigned int)ace_entry->unix_ug.id ));
164                         return (uint32_t)ace_entry->unix_ug.id;
165                 case WORLD_ACE:
166                 default:
167                         DEBUG(10,("get_entry_val: world ace\n"));
168                         return (uint32_t)-1;
169         }
170 }
171
172 /************************************************************************
173  Create the on-disk format (always v2 now). Caller must free.
174 ************************************************************************/
175
176 static char *create_pai_buf_v2(canon_ace *file_ace_list,
177                                 canon_ace *dir_ace_list,
178                                 uint16_t sd_type,
179                                 size_t *store_size)
180 {
181         char *pai_buf = NULL;
182         canon_ace *ace_list = NULL;
183         char *entry_offset = NULL;
184         unsigned int num_entries = 0;
185         unsigned int num_def_entries = 0;
186         unsigned int i;
187
188         for (ace_list = file_ace_list; ace_list; ace_list = ace_list->next) {
189                 num_entries++;
190         }
191
192         for (ace_list = dir_ace_list; ace_list; ace_list = ace_list->next) {
193                 num_def_entries++;
194         }
195
196         DEBUG(10,("create_pai_buf_v2: num_entries = %u, num_def_entries = %u\n", num_entries, num_def_entries ));
197
198         *store_size = PAI_V2_ENTRIES_BASE +
199                 ((num_entries + num_def_entries)*PAI_V2_ENTRY_LENGTH);
200
201         pai_buf = talloc_array(talloc_tos(), char, *store_size);
202         if (!pai_buf) {
203                 return NULL;
204         }
205
206         /* Set up the header. */
207         memset(pai_buf, '\0', PAI_V2_ENTRIES_BASE);
208         SCVAL(pai_buf,PAI_VERSION_OFFSET,PAI_V2_VERSION);
209         SSVAL(pai_buf,PAI_V2_TYPE_OFFSET, sd_type);
210         SSVAL(pai_buf,PAI_V2_NUM_ENTRIES_OFFSET,num_entries);
211         SSVAL(pai_buf,PAI_V2_NUM_DEFAULT_ENTRIES_OFFSET,num_def_entries);
212
213         DEBUG(10,("create_pai_buf_v2: sd_type = 0x%x\n",
214                         (unsigned int)sd_type ));
215
216         entry_offset = pai_buf + PAI_V2_ENTRIES_BASE;
217
218         i = 0;
219         for (ace_list = file_ace_list; ace_list; ace_list = ace_list->next) {
220                 uint8_t type_val = (uint8_t)ace_list->owner_type;
221                 uint32_t entry_val = get_entry_val(ace_list);
222
223                 SCVAL(entry_offset,0,ace_list->ace_flags);
224                 SCVAL(entry_offset,1,type_val);
225                 SIVAL(entry_offset,2,entry_val);
226                 DEBUG(10,("create_pai_buf_v2: entry %u [0x%x] [0x%x] [0x%x]\n",
227                         i,
228                         (unsigned int)ace_list->ace_flags,
229                         (unsigned int)type_val,
230                         (unsigned int)entry_val ));
231                 i++;
232                 entry_offset += PAI_V2_ENTRY_LENGTH;
233         }
234
235         for (ace_list = dir_ace_list; ace_list; ace_list = ace_list->next) {
236                 uint8_t type_val = (uint8_t)ace_list->owner_type;
237                 uint32_t entry_val = get_entry_val(ace_list);
238
239                 SCVAL(entry_offset,0,ace_list->ace_flags);
240                 SCVAL(entry_offset,1,type_val);
241                 SIVAL(entry_offset,2,entry_val);
242                 DEBUG(10,("create_pai_buf_v2: entry %u [0x%x] [0x%x] [0x%x]\n",
243                         i,
244                         (unsigned int)ace_list->ace_flags,
245                         (unsigned int)type_val,
246                         (unsigned int)entry_val ));
247                 i++;
248                 entry_offset += PAI_V2_ENTRY_LENGTH;
249         }
250
251         return pai_buf;
252 }
253
254 /************************************************************************
255  Store the user.SAMBA_PAI attribute on disk.
256 ************************************************************************/
257
258 static void store_inheritance_attributes(files_struct *fsp,
259                                         canon_ace *file_ace_list,
260                                         canon_ace *dir_ace_list,
261                                         uint16_t sd_type)
262 {
263         int ret;
264         size_t store_size;
265         char *pai_buf;
266
267         if (!lp_map_acl_inherit(SNUM(fsp->conn))) {
268                 return;
269         }
270
271         pai_buf = create_pai_buf_v2(file_ace_list, dir_ace_list,
272                                 sd_type, &store_size);
273
274         ret = SMB_VFS_FSETXATTR(fsp, SAMBA_POSIX_INHERITANCE_EA_NAME,
275                                 pai_buf, store_size, 0);
276
277         TALLOC_FREE(pai_buf);
278
279         DEBUG(10,("store_inheritance_attribute: type 0x%x for file %s\n",
280                 (unsigned int)sd_type,
281                 fsp_str_dbg(fsp)));
282
283         if (ret == -1 && !no_acl_syscall_error(errno)) {
284                 DEBUG(1,("store_inheritance_attribute: Error %s\n", strerror(errno) ));
285         }
286 }
287
288 /************************************************************************
289  Delete the in memory inheritance info.
290 ************************************************************************/
291
292 static void free_inherited_info(struct pai_val *pal)
293 {
294         if (pal) {
295                 struct pai_entry *paie, *paie_next;
296                 for (paie = pal->entry_list; paie; paie = paie_next) {
297                         paie_next = paie->next;
298                         TALLOC_FREE(paie);
299                 }
300                 for (paie = pal->def_entry_list; paie; paie = paie_next) {
301                         paie_next = paie->next;
302                         TALLOC_FREE(paie);
303                 }
304                 TALLOC_FREE(pal);
305         }
306 }
307
308 /************************************************************************
309  Get any stored ACE flags.
310 ************************************************************************/
311
312 static uint16_t get_pai_flags(struct pai_val *pal, canon_ace *ace_entry, bool default_ace)
313 {
314         struct pai_entry *paie;
315
316         if (!pal) {
317                 return 0;
318         }
319
320         /* If the entry exists it is inherited. */
321         for (paie = (default_ace ? pal->def_entry_list : pal->entry_list); paie; paie = paie->next) {
322                 if (ace_entry->owner_type == paie->owner_type &&
323                                 get_entry_val(ace_entry) == get_pai_entry_val(paie))
324                         return paie->ace_flags;
325         }
326         return 0;
327 }
328
329 /************************************************************************
330  Ensure an attribute just read is valid - v1.
331 ************************************************************************/
332
333 static bool check_pai_ok_v1(const char *pai_buf, size_t pai_buf_data_size)
334 {
335         uint16_t num_entries;
336         uint16_t num_def_entries;
337
338         if (pai_buf_data_size < PAI_V1_ENTRIES_BASE) {
339                 /* Corrupted - too small. */
340                 return false;
341         }
342
343         if (CVAL(pai_buf,PAI_VERSION_OFFSET) != PAI_V1_VERSION) {
344                 return false;
345         }
346
347         num_entries = SVAL(pai_buf,PAI_V1_NUM_ENTRIES_OFFSET);
348         num_def_entries = SVAL(pai_buf,PAI_V1_NUM_DEFAULT_ENTRIES_OFFSET);
349
350         /* Check the entry lists match. */
351         /* Each entry is 5 bytes (type plus 4 bytes of uid or gid). */
352
353         if (((num_entries + num_def_entries)*PAI_V1_ENTRY_LENGTH) +
354                         PAI_V1_ENTRIES_BASE != pai_buf_data_size) {
355                 return false;
356         }
357
358         return true;
359 }
360
361 /************************************************************************
362  Ensure an attribute just read is valid - v2.
363 ************************************************************************/
364
365 static bool check_pai_ok_v2(const char *pai_buf, size_t pai_buf_data_size)
366 {
367         uint16_t num_entries;
368         uint16_t num_def_entries;
369
370         if (pai_buf_data_size < PAI_V2_ENTRIES_BASE) {
371                 /* Corrupted - too small. */
372                 return false;
373         }
374
375         if (CVAL(pai_buf,PAI_VERSION_OFFSET) != PAI_V2_VERSION) {
376                 return false;
377         }
378
379         num_entries = SVAL(pai_buf,PAI_V2_NUM_ENTRIES_OFFSET);
380         num_def_entries = SVAL(pai_buf,PAI_V2_NUM_DEFAULT_ENTRIES_OFFSET);
381
382         /* Check the entry lists match. */
383         /* Each entry is 6 bytes (flags + type + 4 bytes of uid or gid). */
384
385         if (((num_entries + num_def_entries)*PAI_V2_ENTRY_LENGTH) +
386                         PAI_V2_ENTRIES_BASE != pai_buf_data_size) {
387                 return false;
388         }
389
390         return true;
391 }
392
393 /************************************************************************
394  Decode the owner.
395 ************************************************************************/
396
397 static bool get_pai_owner_type(struct pai_entry *paie, const char *entry_offset)
398 {
399         paie->owner_type = (enum ace_owner)CVAL(entry_offset,0);
400         switch( paie->owner_type) {
401                 case UID_ACE:
402                         paie->unix_ug.type = ID_TYPE_UID;
403                         paie->unix_ug.id = (uid_t)IVAL(entry_offset,1);
404                         DEBUG(10,("get_pai_owner_type: uid = %u\n",
405                                 (unsigned int)paie->unix_ug.id ));
406                         break;
407                 case GID_ACE:
408                         paie->unix_ug.type = ID_TYPE_GID;
409                         paie->unix_ug.id = (gid_t)IVAL(entry_offset,1);
410                         DEBUG(10,("get_pai_owner_type: gid = %u\n",
411                                 (unsigned int)paie->unix_ug.id ));
412                         break;
413                 case WORLD_ACE:
414                         paie->unix_ug.type = ID_TYPE_NOT_SPECIFIED;
415                         paie->unix_ug.id = -1;
416                         DEBUG(10,("get_pai_owner_type: world ace\n"));
417                         break;
418                 default:
419                         DEBUG(10,("get_pai_owner_type: unknown type %u\n",
420                                 (unsigned int)paie->owner_type ));
421                         return false;
422         }
423         return true;
424 }
425
426 /************************************************************************
427  Process v2 entries.
428 ************************************************************************/
429
430 static const char *create_pai_v1_entries(struct pai_val *paiv,
431                                 const char *entry_offset,
432                                 bool def_entry)
433 {
434         unsigned int i;
435
436         for (i = 0; i < paiv->num_entries; i++) {
437                 struct pai_entry *paie = talloc(talloc_tos(), struct pai_entry);
438                 if (!paie) {
439                         return NULL;
440                 }
441
442                 paie->ace_flags = SEC_ACE_FLAG_INHERITED_ACE;
443                 if (!get_pai_owner_type(paie, entry_offset)) {
444                         TALLOC_FREE(paie);
445                         return NULL;
446                 }
447
448                 if (!def_entry) {
449                         DLIST_ADD(paiv->entry_list, paie);
450                 } else {
451                         DLIST_ADD(paiv->def_entry_list, paie);
452                 }
453                 entry_offset += PAI_V1_ENTRY_LENGTH;
454         }
455         return entry_offset;
456 }
457
458 /************************************************************************
459  Convert to in-memory format from version 1.
460 ************************************************************************/
461
462 static struct pai_val *create_pai_val_v1(const char *buf, size_t size)
463 {
464         const char *entry_offset;
465         struct pai_val *paiv = NULL;
466
467         if (!check_pai_ok_v1(buf, size)) {
468                 return NULL;
469         }
470
471         paiv = talloc(talloc_tos(), struct pai_val);
472         if (!paiv) {
473                 return NULL;
474         }
475
476         memset(paiv, '\0', sizeof(struct pai_val));
477
478         paiv->sd_type = (CVAL(buf,PAI_V1_FLAG_OFFSET) == PAI_V1_ACL_FLAG_PROTECTED) ?
479                         SEC_DESC_DACL_PROTECTED : 0;
480
481         paiv->num_entries = SVAL(buf,PAI_V1_NUM_ENTRIES_OFFSET);
482         paiv->num_def_entries = SVAL(buf,PAI_V1_NUM_DEFAULT_ENTRIES_OFFSET);
483
484         entry_offset = buf + PAI_V1_ENTRIES_BASE;
485
486         DEBUG(10,("create_pai_val: num_entries = %u, num_def_entries = %u\n",
487                         paiv->num_entries, paiv->num_def_entries ));
488
489         entry_offset = create_pai_v1_entries(paiv, entry_offset, false);
490         if (entry_offset == NULL) {
491                 free_inherited_info(paiv);
492                 return NULL;
493         }
494         entry_offset = create_pai_v1_entries(paiv, entry_offset, true);
495         if (entry_offset == NULL) {
496                 free_inherited_info(paiv);
497                 return NULL;
498         }
499
500         return paiv;
501 }
502
503 /************************************************************************
504  Process v2 entries.
505 ************************************************************************/
506
507 static const char *create_pai_v2_entries(struct pai_val *paiv,
508                                 unsigned int num_entries,
509                                 const char *entry_offset,
510                                 bool def_entry)
511 {
512         unsigned int i;
513
514         for (i = 0; i < num_entries; i++) {
515                 struct pai_entry *paie = talloc(talloc_tos(), struct pai_entry);
516                 if (!paie) {
517                         return NULL;
518                 }
519
520                 paie->ace_flags = CVAL(entry_offset,0);
521
522                 if (!get_pai_owner_type(paie, entry_offset+1)) {
523                         TALLOC_FREE(paie);
524                         return NULL;
525                 }
526                 if (!def_entry) {
527                         DLIST_ADD(paiv->entry_list, paie);
528                 } else {
529                         DLIST_ADD(paiv->def_entry_list, paie);
530                 }
531                 entry_offset += PAI_V2_ENTRY_LENGTH;
532         }
533         return entry_offset;
534 }
535
536 /************************************************************************
537  Convert to in-memory format from version 2.
538 ************************************************************************/
539
540 static struct pai_val *create_pai_val_v2(const char *buf, size_t size)
541 {
542         const char *entry_offset;
543         struct pai_val *paiv = NULL;
544
545         if (!check_pai_ok_v2(buf, size)) {
546                 return NULL;
547         }
548
549         paiv = talloc(talloc_tos(), struct pai_val);
550         if (!paiv) {
551                 return NULL;
552         }
553
554         memset(paiv, '\0', sizeof(struct pai_val));
555
556         paiv->sd_type = SVAL(buf,PAI_V2_TYPE_OFFSET);
557
558         paiv->num_entries = SVAL(buf,PAI_V2_NUM_ENTRIES_OFFSET);
559         paiv->num_def_entries = SVAL(buf,PAI_V2_NUM_DEFAULT_ENTRIES_OFFSET);
560
561         entry_offset = buf + PAI_V2_ENTRIES_BASE;
562
563         DEBUG(10,("create_pai_val_v2: sd_type = 0x%x num_entries = %u, num_def_entries = %u\n",
564                         (unsigned int)paiv->sd_type,
565                         paiv->num_entries, paiv->num_def_entries ));
566
567         entry_offset = create_pai_v2_entries(paiv, paiv->num_entries,
568                                 entry_offset, false);
569         if (entry_offset == NULL) {
570                 free_inherited_info(paiv);
571                 return NULL;
572         }
573         entry_offset = create_pai_v2_entries(paiv, paiv->num_def_entries,
574                                 entry_offset, true);
575         if (entry_offset == NULL) {
576                 free_inherited_info(paiv);
577                 return NULL;
578         }
579
580         return paiv;
581 }
582
583 /************************************************************************
584  Convert to in-memory format - from either version 1 or 2.
585 ************************************************************************/
586
587 static struct pai_val *create_pai_val(const char *buf, size_t size)
588 {
589         if (size < 1) {
590                 return NULL;
591         }
592         if (CVAL(buf,PAI_VERSION_OFFSET) == PAI_V1_VERSION) {
593                 return create_pai_val_v1(buf, size);
594         } else if (CVAL(buf,PAI_VERSION_OFFSET) == PAI_V2_VERSION) {
595                 return create_pai_val_v2(buf, size);
596         } else {
597                 return NULL;
598         }
599 }
600
601 /************************************************************************
602  Load the user.SAMBA_PAI attribute.
603 ************************************************************************/
604
605 static struct pai_val *fload_inherited_info(files_struct *fsp)
606 {
607         char *pai_buf;
608         size_t pai_buf_size = 1024;
609         struct pai_val *paiv = NULL;
610         ssize_t ret;
611
612         if (!lp_map_acl_inherit(SNUM(fsp->conn))) {
613                 return NULL;
614         }
615
616         if ((pai_buf = talloc_array(talloc_tos(), char, pai_buf_size)) == NULL) {
617                 return NULL;
618         }
619
620         do {
621                 ret = SMB_VFS_FGETXATTR(fsp, SAMBA_POSIX_INHERITANCE_EA_NAME,
622                                         pai_buf, pai_buf_size);
623                 if (ret == -1) {
624                         if (errno != ERANGE) {
625                                 break;
626                         }
627                         /* Buffer too small - enlarge it. */
628                         pai_buf_size *= 2;
629                         TALLOC_FREE(pai_buf);
630                         if (pai_buf_size > 1024*1024) {
631                                 return NULL; /* Limit malloc to 1mb. */
632                         }
633                         if ((pai_buf = talloc_array(talloc_tos(), char, pai_buf_size)) == NULL)
634                                 return NULL;
635                 }
636         } while (ret == -1);
637
638         DEBUG(10,("load_inherited_info: ret = %lu for file %s\n",
639                   (unsigned long)ret, fsp_str_dbg(fsp)));
640
641         if (ret == -1) {
642                 /* No attribute or not supported. */
643 #if defined(ENOATTR)
644                 if (errno != ENOATTR)
645                         DEBUG(10,("load_inherited_info: Error %s\n", strerror(errno) ));
646 #else
647                 if (errno != ENOSYS)
648                         DEBUG(10,("load_inherited_info: Error %s\n", strerror(errno) ));
649 #endif
650                 TALLOC_FREE(pai_buf);
651                 return NULL;
652         }
653
654         paiv = create_pai_val(pai_buf, ret);
655
656         if (paiv) {
657                 DEBUG(10,("load_inherited_info: ACL type is 0x%x for file %s\n",
658                           (unsigned int)paiv->sd_type, fsp_str_dbg(fsp)));
659         }
660
661         TALLOC_FREE(pai_buf);
662         return paiv;
663 }
664
665 /****************************************************************************
666  Functions to manipulate the internal ACE format.
667 ****************************************************************************/
668
669 /****************************************************************************
670  Count a linked list of canonical ACE entries.
671 ****************************************************************************/
672
673 static size_t count_canon_ace_list( canon_ace *l_head )
674 {
675         size_t count = 0;
676         canon_ace *ace;
677
678         for (ace = l_head; ace; ace = ace->next)
679                 count++;
680
681         return count;
682 }
683
684 /****************************************************************************
685  Free a linked list of canonical ACE entries.
686 ****************************************************************************/
687
688 static void free_canon_ace_list( canon_ace *l_head )
689 {
690         canon_ace *list, *next;
691
692         for (list = l_head; list; list = next) {
693                 next = list->next;
694                 DLIST_REMOVE(l_head, list);
695                 TALLOC_FREE(list);
696         }
697 }
698
699 /****************************************************************************
700  Function to duplicate a canon_ace entry.
701 ****************************************************************************/
702
703 static canon_ace *dup_canon_ace( canon_ace *src_ace)
704 {
705         canon_ace *dst_ace = talloc(talloc_tos(), canon_ace);
706
707         if (dst_ace == NULL)
708                 return NULL;
709
710         *dst_ace = *src_ace;
711         dst_ace->prev = dst_ace->next = NULL;
712         return dst_ace;
713 }
714
715 /****************************************************************************
716  Print out a canon ace.
717 ****************************************************************************/
718
719 static void print_canon_ace(canon_ace *pace, int num)
720 {
721         struct dom_sid_buf buf;
722         dbgtext( "canon_ace index %d. Type = %s ", num, pace->attr == ALLOW_ACE ? "allow" : "deny" );
723         dbgtext( "SID = %s ", dom_sid_str_buf(&pace->trustee, &buf));
724         if (pace->owner_type == UID_ACE) {
725                 dbgtext( "uid %u ", (unsigned int)pace->unix_ug.id);
726         } else if (pace->owner_type == GID_ACE) {
727                 dbgtext( "gid %u ", (unsigned int)pace->unix_ug.id);
728         } else
729                 dbgtext( "other ");
730         switch (pace->type) {
731                 case SMB_ACL_USER:
732                         dbgtext( "SMB_ACL_USER ");
733                         break;
734                 case SMB_ACL_USER_OBJ:
735                         dbgtext( "SMB_ACL_USER_OBJ ");
736                         break;
737                 case SMB_ACL_GROUP:
738                         dbgtext( "SMB_ACL_GROUP ");
739                         break;
740                 case SMB_ACL_GROUP_OBJ:
741                         dbgtext( "SMB_ACL_GROUP_OBJ ");
742                         break;
743                 case SMB_ACL_OTHER:
744                         dbgtext( "SMB_ACL_OTHER ");
745                         break;
746                 default:
747                         dbgtext( "MASK " );
748                         break;
749         }
750
751         dbgtext( "ace_flags = 0x%x ", (unsigned int)pace->ace_flags);
752         dbgtext( "perms ");
753         dbgtext( "%c", pace->perms & S_IRUSR ? 'r' : '-');
754         dbgtext( "%c", pace->perms & S_IWUSR ? 'w' : '-');
755         dbgtext( "%c\n", pace->perms & S_IXUSR ? 'x' : '-');
756 }
757
758 /****************************************************************************
759  Print out a canon ace list.
760 ****************************************************************************/
761
762 static void print_canon_ace_list(const char *name, canon_ace *ace_list)
763 {
764         int count = 0;
765
766         if( DEBUGLVL( 10 )) {
767                 dbgtext( "print_canon_ace_list: %s\n", name );
768                 for (;ace_list; ace_list = ace_list->next, count++)
769                         print_canon_ace(ace_list, count );
770         }
771 }
772
773 /****************************************************************************
774  Map POSIX ACL perms to canon_ace permissions (a mode_t containing only S_(R|W|X)USR bits).
775 ****************************************************************************/
776
777 static mode_t convert_permset_to_mode_t(SMB_ACL_PERMSET_T permset)
778 {
779         mode_t ret = 0;
780
781         ret |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? S_IRUSR : 0);
782         ret |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? S_IWUSR : 0);
783         ret |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? S_IXUSR : 0);
784
785         return ret;
786 }
787
788 /****************************************************************************
789  Map generic UNIX permissions to canon_ace permissions (a mode_t containing only S_(R|W|X)USR bits).
790 ****************************************************************************/
791
792 mode_t unix_perms_to_acl_perms(mode_t mode, int r_mask, int w_mask, int x_mask)
793 {
794         mode_t ret = 0;
795
796         if (mode & r_mask)
797                 ret |= S_IRUSR;
798         if (mode & w_mask)
799                 ret |= S_IWUSR;
800         if (mode & x_mask)
801                 ret |= S_IXUSR;
802
803         return ret;
804 }
805
806 /****************************************************************************
807  Map canon_ace permissions (a mode_t containing only S_(R|W|X)USR bits) to
808  an SMB_ACL_PERMSET_T.
809 ****************************************************************************/
810
811 int map_acl_perms_to_permset(mode_t mode, SMB_ACL_PERMSET_T *p_permset)
812 {
813         if (sys_acl_clear_perms(*p_permset) ==  -1)
814                 return -1;
815         if (mode & S_IRUSR) {
816                 if (sys_acl_add_perm(*p_permset, SMB_ACL_READ) == -1)
817                         return -1;
818         }
819         if (mode & S_IWUSR) {
820                 if (sys_acl_add_perm(*p_permset, SMB_ACL_WRITE) == -1)
821                         return -1;
822         }
823         if (mode & S_IXUSR) {
824                 if (sys_acl_add_perm(*p_permset, SMB_ACL_EXECUTE) == -1)
825                         return -1;
826         }
827         return 0;
828 }
829
830 /****************************************************************************
831  Function to create owner and group SIDs from a SMB_STRUCT_STAT.
832 ****************************************************************************/
833
834 static void create_file_sids(const SMB_STRUCT_STAT *psbuf,
835                              struct dom_sid *powner_sid,
836                              struct dom_sid *pgroup_sid)
837 {
838         uid_to_sid( powner_sid, psbuf->st_ex_uid );
839         gid_to_sid( pgroup_sid, psbuf->st_ex_gid );
840 }
841
842 /****************************************************************************
843  Merge aces with a common UID or GID - if both are allow or deny, OR the permissions together and
844  delete the second one. If the first is deny, mask the permissions off and delete the allow
845  if the permissions become zero, delete the deny if the permissions are non zero.
846 ****************************************************************************/
847
848 static void merge_aces( canon_ace **pp_list_head, bool dir_acl)
849 {
850         canon_ace *l_head = *pp_list_head;
851         canon_ace *curr_ace_outer;
852         canon_ace *curr_ace_outer_next;
853
854         /*
855          * First, merge allow entries with identical SIDs, and deny entries
856          * with identical SIDs.
857          */
858
859         for (curr_ace_outer = l_head; curr_ace_outer; curr_ace_outer = curr_ace_outer_next) {
860                 canon_ace *curr_ace;
861                 canon_ace *curr_ace_next;
862
863                 curr_ace_outer_next = curr_ace_outer->next; /* Save the link in case we delete. */
864
865                 for (curr_ace = curr_ace_outer->next; curr_ace; curr_ace = curr_ace_next) {
866                         bool can_merge = false;
867
868                         curr_ace_next = curr_ace->next; /* Save the link in case of delete. */
869
870                         /* For file ACLs we can merge if the SIDs and ALLOW/DENY
871                          * types are the same. For directory acls we must also
872                          * ensure the POSIX ACL types are the same.
873                          *
874                          * For the IDMAP_BOTH case, we must not merge
875                          * the UID and GID ACE values for same SID
876                          */
877
878                         if (!dir_acl) {
879                                 can_merge = (curr_ace->unix_ug.id == curr_ace_outer->unix_ug.id &&
880                                              curr_ace->owner_type == curr_ace_outer->owner_type &&
881                                              (curr_ace->attr == curr_ace_outer->attr));
882                         } else {
883                                 can_merge = (curr_ace->unix_ug.id == curr_ace_outer->unix_ug.id &&
884                                              curr_ace->owner_type == curr_ace_outer->owner_type &&
885                                              (curr_ace->type == curr_ace_outer->type) &&
886                                              (curr_ace->attr == curr_ace_outer->attr));
887                         }
888
889                         if (can_merge) {
890                                 if( DEBUGLVL( 10 )) {
891                                         dbgtext("merge_aces: Merging ACE's\n");
892                                         print_canon_ace( curr_ace_outer, 0);
893                                         print_canon_ace( curr_ace, 0);
894                                 }
895
896                                 /* Merge two allow or two deny ACE's. */
897
898                                 /* Theoretically we shouldn't merge a dir ACE if
899                                  * one ACE has the CI flag set, and the other
900                                  * ACE has the OI flag set, but this is rare
901                                  * enough we can ignore it. */
902
903                                 curr_ace_outer->perms |= curr_ace->perms;
904                                 curr_ace_outer->ace_flags |= curr_ace->ace_flags;
905                                 DLIST_REMOVE(l_head, curr_ace);
906                                 TALLOC_FREE(curr_ace);
907                                 curr_ace_outer_next = curr_ace_outer->next; /* We may have deleted the link. */
908                         }
909                 }
910         }
911
912         /*
913          * Now go through and mask off allow permissions with deny permissions.
914          * We can delete either the allow or deny here as we know that each SID
915          * appears only once in the list.
916          */
917
918         for (curr_ace_outer = l_head; curr_ace_outer; curr_ace_outer = curr_ace_outer_next) {
919                 canon_ace *curr_ace;
920                 canon_ace *curr_ace_next;
921
922                 curr_ace_outer_next = curr_ace_outer->next; /* Save the link in case we delete. */
923
924                 for (curr_ace = curr_ace_outer->next; curr_ace; curr_ace = curr_ace_next) {
925
926                         curr_ace_next = curr_ace->next; /* Save the link in case of delete. */
927
928                         /*
929                          * Subtract ACE's with different entries. Due to the ordering constraints
930                          * we've put on the ACL, we know the deny must be the first one.
931                          */
932
933                         if (curr_ace->unix_ug.id == curr_ace_outer->unix_ug.id &&
934                             (curr_ace->owner_type == curr_ace_outer->owner_type) &&
935                             (curr_ace_outer->attr == DENY_ACE) && (curr_ace->attr == ALLOW_ACE)) {
936
937                                 if( DEBUGLVL( 10 )) {
938                                         dbgtext("merge_aces: Masking ACE's\n");
939                                         print_canon_ace( curr_ace_outer, 0);
940                                         print_canon_ace( curr_ace, 0);
941                                 }
942
943                                 curr_ace->perms &= ~curr_ace_outer->perms;
944
945                                 if (curr_ace->perms == 0) {
946
947                                         /*
948                                          * The deny overrides the allow. Remove the allow.
949                                          */
950
951                                         DLIST_REMOVE(l_head, curr_ace);
952                                         TALLOC_FREE(curr_ace);
953                                         curr_ace_outer_next = curr_ace_outer->next; /* We may have deleted the link. */
954
955                                 } else {
956
957                                         /*
958                                          * Even after removing permissions, there
959                                          * are still allow permissions - delete the deny.
960                                          * It is safe to delete the deny here,
961                                          * as we are guaranteed by the deny first
962                                          * ordering that all the deny entries for
963                                          * this SID have already been merged into one
964                                          * before we can get to an allow ace.
965                                          */
966
967                                         DLIST_REMOVE(l_head, curr_ace_outer);
968                                         TALLOC_FREE(curr_ace_outer);
969                                         break;
970                                 }
971                         }
972
973                 } /* end for curr_ace */
974         } /* end for curr_ace_outer */
975
976         /* We may have modified the list. */
977
978         *pp_list_head = l_head;
979 }
980
981 /****************************************************************************
982  Map canon_ace perms to permission bits NT.
983  The attr element is not used here - we only process deny entries on set,
984  not get. Deny entries are implicit on get with ace->perms = 0.
985 ****************************************************************************/
986
987 uint32_t map_canon_ace_perms(int snum,
988                                 enum security_ace_type *pacl_type,
989                                 mode_t perms,
990                                 bool directory_ace)
991 {
992         uint32_t nt_mask = 0;
993
994         *pacl_type = SEC_ACE_TYPE_ACCESS_ALLOWED;
995
996         if (lp_acl_map_full_control(snum) && ((perms & ALL_ACE_PERMS) == ALL_ACE_PERMS)) {
997                 if (directory_ace) {
998                         nt_mask = UNIX_DIRECTORY_ACCESS_RWX;
999                 } else {
1000                         nt_mask = (UNIX_ACCESS_RWX & ~DELETE_ACCESS);
1001                 }
1002         } else if ((perms & ALL_ACE_PERMS) == (mode_t)0) {
1003                 /*
1004                  * Windows NT refuses to display ACEs with no permissions in them (but
1005                  * they are perfectly legal with Windows 2000). If the ACE has empty
1006                  * permissions we cannot use 0, so we use the otherwise unused
1007                  * WRITE_OWNER permission, which we ignore when we set an ACL.
1008                  * We abstract this into a #define of UNIX_ACCESS_NONE to allow this
1009                  * to be changed in the future.
1010                  */
1011
1012                 nt_mask = 0;
1013         } else {
1014                 if (directory_ace) {
1015                         nt_mask |= ((perms & S_IRUSR) ? UNIX_DIRECTORY_ACCESS_R : 0 );
1016                         nt_mask |= ((perms & S_IWUSR) ? UNIX_DIRECTORY_ACCESS_W : 0 );
1017                         nt_mask |= ((perms & S_IXUSR) ? UNIX_DIRECTORY_ACCESS_X : 0 );
1018                 } else {
1019                         nt_mask |= ((perms & S_IRUSR) ? UNIX_ACCESS_R : 0 );
1020                         nt_mask |= ((perms & S_IWUSR) ? UNIX_ACCESS_W : 0 );
1021                         nt_mask |= ((perms & S_IXUSR) ? UNIX_ACCESS_X : 0 );
1022                 }
1023         }
1024
1025         if ((perms & S_IWUSR) && lp_dos_filemode(snum)) {
1026                 nt_mask |= (SEC_STD_WRITE_DAC|SEC_STD_WRITE_OWNER|DELETE_ACCESS);
1027         }
1028
1029         DEBUG(10,("map_canon_ace_perms: Mapped (UNIX) %x to (NT) %x\n",
1030                         (unsigned int)perms, (unsigned int)nt_mask ));
1031
1032         return nt_mask;
1033 }
1034
1035 /****************************************************************************
1036  Map NT perms to a UNIX mode_t.
1037 ****************************************************************************/
1038
1039 #define FILE_SPECIFIC_READ_BITS (FILE_READ_DATA|FILE_READ_EA)
1040 #define FILE_SPECIFIC_WRITE_BITS (FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_WRITE_EA)
1041 #define FILE_SPECIFIC_EXECUTE_BITS (FILE_EXECUTE)
1042
1043 static mode_t map_nt_perms( uint32_t *mask, int type)
1044 {
1045         mode_t mode = 0;
1046
1047         switch(type) {
1048         case S_IRUSR:
1049                 if((*mask) & GENERIC_ALL_ACCESS)
1050                         mode = S_IRUSR|S_IWUSR|S_IXUSR;
1051                 else {
1052                         mode |= ((*mask) & (GENERIC_READ_ACCESS|FILE_SPECIFIC_READ_BITS)) ? S_IRUSR : 0;
1053                         mode |= ((*mask) & (GENERIC_WRITE_ACCESS|FILE_SPECIFIC_WRITE_BITS)) ? S_IWUSR : 0;
1054                         mode |= ((*mask) & (GENERIC_EXECUTE_ACCESS|FILE_SPECIFIC_EXECUTE_BITS)) ? S_IXUSR : 0;
1055                 }
1056                 break;
1057         case S_IRGRP:
1058                 if((*mask) & GENERIC_ALL_ACCESS)
1059                         mode = S_IRGRP|S_IWGRP|S_IXGRP;
1060                 else {
1061                         mode |= ((*mask) & (GENERIC_READ_ACCESS|FILE_SPECIFIC_READ_BITS)) ? S_IRGRP : 0;
1062                         mode |= ((*mask) & (GENERIC_WRITE_ACCESS|FILE_SPECIFIC_WRITE_BITS)) ? S_IWGRP : 0;
1063                         mode |= ((*mask) & (GENERIC_EXECUTE_ACCESS|FILE_SPECIFIC_EXECUTE_BITS)) ? S_IXGRP : 0;
1064                 }
1065                 break;
1066         case S_IROTH:
1067                 if((*mask) & GENERIC_ALL_ACCESS)
1068                         mode = S_IROTH|S_IWOTH|S_IXOTH;
1069                 else {
1070                         mode |= ((*mask) & (GENERIC_READ_ACCESS|FILE_SPECIFIC_READ_BITS)) ? S_IROTH : 0;
1071                         mode |= ((*mask) & (GENERIC_WRITE_ACCESS|FILE_SPECIFIC_WRITE_BITS)) ? S_IWOTH : 0;
1072                         mode |= ((*mask) & (GENERIC_EXECUTE_ACCESS|FILE_SPECIFIC_EXECUTE_BITS)) ? S_IXOTH : 0;
1073                 }
1074                 break;
1075         }
1076
1077         return mode;
1078 }
1079
1080 /****************************************************************************
1081  Unpack a struct security_descriptor into a UNIX owner and group.
1082 ****************************************************************************/
1083
1084 static NTSTATUS unpack_nt_owners(struct connection_struct *conn,
1085                                  uid_t *puser, gid_t *pgrp,
1086                                  uint32_t security_info_sent,
1087                                  const struct security_descriptor *psd)
1088 {
1089         *puser = (uid_t)-1;
1090         *pgrp = (gid_t)-1;
1091
1092         if(security_info_sent == 0) {
1093                 DEBUG(0,("unpack_nt_owners: no security info sent !\n"));
1094                 return NT_STATUS_OK;
1095         }
1096
1097         /*
1098          * Validate the owner and group SID's.
1099          */
1100
1101         DEBUG(5,("unpack_nt_owners: validating owner_sids.\n"));
1102
1103         /*
1104          * Don't immediately fail if the owner sid cannot be validated.
1105          * This may be a group chown only set.
1106          */
1107
1108         if (security_info_sent & SECINFO_OWNER) {
1109                 if (!sid_to_uid(psd->owner_sid, puser)) {
1110                         if (lp_force_unknown_acl_user(SNUM(conn))) {
1111                                 /* this allows take ownership to work
1112                                  * reasonably */
1113                                 *puser = get_current_uid(conn);
1114                         } else {
1115                                 struct dom_sid_buf buf;
1116                                 DBG_NOTICE("unable to validate"
1117                                            " owner sid for %s\n",
1118                                            dom_sid_str_buf(psd->owner_sid,
1119                                                            &buf));
1120                                 return NT_STATUS_INVALID_OWNER;
1121                         }
1122                 }
1123                 DEBUG(3,("unpack_nt_owners: owner sid mapped to uid %u\n",
1124                          (unsigned int)*puser ));
1125         }
1126
1127         /*
1128          * Don't immediately fail if the group sid cannot be validated.
1129          * This may be an owner chown only set.
1130          */
1131
1132         if (security_info_sent & SECINFO_GROUP) {
1133                 if (!sid_to_gid(psd->group_sid, pgrp)) {
1134                         if (lp_force_unknown_acl_user(SNUM(conn))) {
1135                                 /* this allows take group ownership to work
1136                                  * reasonably */
1137                                 *pgrp = get_current_gid(conn);
1138                         } else {
1139                                 DEBUG(3,("unpack_nt_owners: unable to validate"
1140                                          " group sid.\n"));
1141                                 return NT_STATUS_INVALID_OWNER;
1142                         }
1143                 }
1144                 DEBUG(3,("unpack_nt_owners: group sid mapped to gid %u\n",
1145                          (unsigned int)*pgrp));
1146         }
1147
1148         DEBUG(5,("unpack_nt_owners: owner_sids validated.\n"));
1149
1150         return NT_STATUS_OK;
1151 }
1152
1153
1154 static void trim_ace_perms(canon_ace *pace)
1155 {
1156         pace->perms = pace->perms & (S_IXUSR|S_IWUSR|S_IRUSR);
1157 }
1158
1159 static void ensure_minimal_owner_ace_perms(const bool is_directory,
1160                                            canon_ace *pace)
1161 {
1162         pace->perms |= S_IRUSR;
1163         if (is_directory) {
1164                 pace->perms |= (S_IWUSR|S_IXUSR);
1165         }
1166 }
1167
1168 /****************************************************************************
1169  Check if a given uid/SID is in a group gid/SID. This is probably very
1170  expensive and will need optimisation. A *lot* of optimisation :-). JRA.
1171 ****************************************************************************/
1172
1173 static bool uid_entry_in_group(connection_struct *conn, canon_ace *uid_ace, canon_ace *group_ace )
1174 {
1175         bool is_sid = false;
1176         bool has_sid = false;
1177         struct security_token *security_token = NULL;
1178
1179         /* "Everyone" always matches every uid. */
1180
1181         if (dom_sid_equal(&group_ace->trustee, &global_sid_World))
1182                 return True;
1183
1184         security_token = conn->session_info->security_token;
1185         /* security_token should not be NULL */
1186         SMB_ASSERT(security_token);
1187         is_sid = security_token_is_sid(security_token,
1188                                        &uid_ace->trustee);
1189         if (is_sid) {
1190                 has_sid = security_token_has_sid(security_token,
1191                                                  &group_ace->trustee);
1192
1193                 if (has_sid) {
1194                         return true;
1195                 }
1196         }
1197
1198         /*
1199          * if it's the current user, we already have the unix token
1200          * and don't need to do the complex user_in_group_sid() call
1201          */
1202         if (uid_ace->unix_ug.id == get_current_uid(conn)) {
1203                 const struct security_unix_token *curr_utok = NULL;
1204                 size_t i;
1205
1206                 if (group_ace->unix_ug.id == get_current_gid(conn)) {
1207                         return True;
1208                 }
1209
1210                 curr_utok = get_current_utok(conn);
1211                 for (i=0; i < curr_utok->ngroups; i++) {
1212                         if (group_ace->unix_ug.id == curr_utok->groups[i]) {
1213                                 return True;
1214                         }
1215                 }
1216         }
1217
1218         /*
1219          * user_in_group_sid() uses create_token_from_sid()
1220          * which creates an artificial NT token given just a username,
1221          * so this is not reliable for users from foreign domains
1222          * exported by winbindd!
1223          */
1224         return user_sid_in_group_sid(&uid_ace->trustee, &group_ace->trustee);
1225 }
1226
1227 /****************************************************************************
1228  A well formed POSIX file or default ACL has at least 3 entries, a
1229  SMB_ACL_USER_OBJ, SMB_ACL_GROUP_OBJ, SMB_ACL_OTHER_OBJ.
1230  In addition, the owner must always have at least read access.
1231  When using this call on get_acl, the pst struct is valid and contains
1232  the mode of the file.
1233 ****************************************************************************/
1234
1235 static bool ensure_canon_entry_valid_on_get(connection_struct *conn,
1236                                         canon_ace **pp_ace,
1237                                         const struct dom_sid *pfile_owner_sid,
1238                                         const struct dom_sid *pfile_grp_sid,
1239                                         const SMB_STRUCT_STAT *pst)
1240 {
1241         canon_ace *pace;
1242         bool got_user = false;
1243         bool got_group = false;
1244         bool got_other = false;
1245
1246         for (pace = *pp_ace; pace; pace = pace->next) {
1247                 if (pace->type == SMB_ACL_USER_OBJ) {
1248                         got_user = true;
1249                 } else if (pace->type == SMB_ACL_GROUP_OBJ) {
1250                         got_group = true;
1251                 } else if (pace->type == SMB_ACL_OTHER) {
1252                         got_other = true;
1253                 }
1254         }
1255
1256         if (!got_user) {
1257                 if ((pace = talloc(talloc_tos(), canon_ace)) == NULL) {
1258                         DEBUG(0,("malloc fail.\n"));
1259                         return false;
1260                 }
1261
1262                 ZERO_STRUCTP(pace);
1263                 pace->type = SMB_ACL_USER_OBJ;
1264                 pace->owner_type = UID_ACE;
1265                 pace->unix_ug.type = ID_TYPE_UID;
1266                 pace->unix_ug.id = pst->st_ex_uid;
1267                 pace->trustee = *pfile_owner_sid;
1268                 pace->attr = ALLOW_ACE;
1269                 pace->perms = unix_perms_to_acl_perms(pst->st_ex_mode, S_IRUSR, S_IWUSR, S_IXUSR);
1270                 DLIST_ADD(*pp_ace, pace);
1271         }
1272
1273         if (!got_group) {
1274                 if ((pace = talloc(talloc_tos(), canon_ace)) == NULL) {
1275                         DEBUG(0,("malloc fail.\n"));
1276                         return false;
1277                 }
1278
1279                 ZERO_STRUCTP(pace);
1280                 pace->type = SMB_ACL_GROUP_OBJ;
1281                 pace->owner_type = GID_ACE;
1282                 pace->unix_ug.type = ID_TYPE_GID;
1283                 pace->unix_ug.id = pst->st_ex_gid;
1284                 pace->trustee = *pfile_grp_sid;
1285                 pace->attr = ALLOW_ACE;
1286                 pace->perms = unix_perms_to_acl_perms(pst->st_ex_mode, S_IRGRP, S_IWGRP, S_IXGRP);
1287                 DLIST_ADD(*pp_ace, pace);
1288         }
1289
1290         if (!got_other) {
1291                 if ((pace = talloc(talloc_tos(), canon_ace)) == NULL) {
1292                         DEBUG(0,("malloc fail.\n"));
1293                         return false;
1294                 }
1295
1296                 ZERO_STRUCTP(pace);
1297                 pace->type = SMB_ACL_OTHER;
1298                 pace->owner_type = WORLD_ACE;
1299                 pace->unix_ug.type = ID_TYPE_NOT_SPECIFIED;
1300                 pace->unix_ug.id = -1;
1301                 pace->trustee = global_sid_World;
1302                 pace->attr = ALLOW_ACE;
1303                 pace->perms = unix_perms_to_acl_perms(pst->st_ex_mode, S_IROTH, S_IWOTH, S_IXOTH);
1304                 DLIST_ADD(*pp_ace, pace);
1305         }
1306
1307         return true;
1308 }
1309
1310 /****************************************************************************
1311  A well formed POSIX file or default ACL has at least 3 entries, a
1312  SMB_ACL_USER_OBJ, SMB_ACL_GROUP_OBJ, SMB_ACL_OTHER_OBJ.
1313  In addition, the owner must always have at least read access.
1314  When using this call on set_acl, the pst struct has
1315  been modified to have a mode containing the default for this file or directory
1316  type.
1317 ****************************************************************************/
1318
1319 static bool ensure_canon_entry_valid_on_set(connection_struct *conn,
1320                                         canon_ace **pp_ace,
1321                                         bool is_default_acl,
1322                                         const struct share_params *params,
1323                                         const bool is_directory,
1324                                         const struct dom_sid *pfile_owner_sid,
1325                                         const struct dom_sid *pfile_grp_sid,
1326                                         const SMB_STRUCT_STAT *pst)
1327 {
1328         canon_ace *pace;
1329         canon_ace *pace_user = NULL;
1330         canon_ace *pace_group = NULL;
1331         canon_ace *pace_other = NULL;
1332         bool got_duplicate_user = false;
1333         bool got_duplicate_group = false;
1334
1335         for (pace = *pp_ace; pace; pace = pace->next) {
1336                 trim_ace_perms(pace);
1337                 if (pace->type == SMB_ACL_USER_OBJ) {
1338                         ensure_minimal_owner_ace_perms(is_directory, pace);
1339                         pace_user = pace;
1340                 } else if (pace->type == SMB_ACL_GROUP_OBJ) {
1341                         pace_group = pace;
1342                 } else if (pace->type == SMB_ACL_OTHER) {
1343                         pace_other = pace;
1344                 }
1345         }
1346
1347         if (!pace_user) {
1348                 canon_ace *pace_iter;
1349
1350                 if ((pace = talloc(talloc_tos(), canon_ace)) == NULL) {
1351                         DEBUG(0,("talloc fail.\n"));
1352                         return false;
1353                 }
1354
1355                 ZERO_STRUCTP(pace);
1356                 pace->type = SMB_ACL_USER_OBJ;
1357                 pace->owner_type = UID_ACE;
1358                 pace->unix_ug.type = ID_TYPE_UID;
1359                 pace->unix_ug.id = pst->st_ex_uid;
1360                 pace->trustee = *pfile_owner_sid;
1361                 pace->attr = ALLOW_ACE;
1362                 /* Start with existing user permissions, principle of least
1363                    surprises for the user. */
1364                 pace->perms = unix_perms_to_acl_perms(pst->st_ex_mode, S_IRUSR, S_IWUSR, S_IXUSR);
1365
1366                 /* See if the owning user is in any of the other groups in
1367                    the ACE, or if there's a matching user entry (by uid
1368                    or in the case of ID_TYPE_BOTH by SID).
1369                    If so, OR in the permissions from that entry. */
1370
1371
1372                 for (pace_iter = *pp_ace; pace_iter; pace_iter = pace_iter->next) {
1373                         if (pace_iter->type == SMB_ACL_USER &&
1374                                         pace_iter->unix_ug.id == pace->unix_ug.id) {
1375                                 pace->perms |= pace_iter->perms;
1376                         } else if (pace_iter->type == SMB_ACL_GROUP_OBJ || pace_iter->type == SMB_ACL_GROUP) {
1377                                 if (dom_sid_equal(&pace->trustee, &pace_iter->trustee)) {
1378                                         pace->perms |= pace_iter->perms;
1379                                 } else if (uid_entry_in_group(conn, pace, pace_iter)) {
1380                                         pace->perms |= pace_iter->perms;
1381                                 }
1382                         }
1383                 }
1384
1385                 if (pace->perms == 0) {
1386                         /* If we only got an "everyone" perm, just use that. */
1387                         if (pace_other)
1388                                 pace->perms = pace_other->perms;
1389                 }
1390
1391                 /*
1392                  * Ensure we have default parameters for the
1393                  * user (owner) even on default ACLs.
1394                  */
1395                 ensure_minimal_owner_ace_perms(is_directory, pace);
1396
1397                 DLIST_ADD(*pp_ace, pace);
1398                 pace_user = pace;
1399         }
1400
1401         if (!pace_group) {
1402                 if ((pace = talloc(talloc_tos(), canon_ace)) == NULL) {
1403                         DEBUG(0,("talloc fail.\n"));
1404                         return false;
1405                 }
1406
1407                 ZERO_STRUCTP(pace);
1408                 pace->type = SMB_ACL_GROUP_OBJ;
1409                 pace->owner_type = GID_ACE;
1410                 pace->unix_ug.type = ID_TYPE_GID;
1411                 pace->unix_ug.id = pst->st_ex_gid;
1412                 pace->trustee = *pfile_grp_sid;
1413                 pace->attr = ALLOW_ACE;
1414
1415                 /* If we only got an "everyone" perm, just use that. */
1416                 if (pace_other) {
1417                         pace->perms = pace_other->perms;
1418                 } else {
1419                         pace->perms = 0;
1420                 }
1421
1422                 DLIST_ADD(*pp_ace, pace);
1423                 pace_group = pace;
1424         }
1425
1426         if (!pace_other) {
1427                 if ((pace = talloc(talloc_tos(), canon_ace)) == NULL) {
1428                         DEBUG(0,("talloc fail.\n"));
1429                         return false;
1430                 }
1431
1432                 ZERO_STRUCTP(pace);
1433                 pace->type = SMB_ACL_OTHER;
1434                 pace->owner_type = WORLD_ACE;
1435                 pace->unix_ug.type = ID_TYPE_NOT_SPECIFIED;
1436                 pace->unix_ug.id = -1;
1437                 pace->trustee = global_sid_World;
1438                 pace->attr = ALLOW_ACE;
1439                 pace->perms = 0;
1440
1441                 DLIST_ADD(*pp_ace, pace);
1442                 pace_other = pace;
1443         }
1444
1445         /* Ensure when setting a POSIX ACL, that the uid for a
1446            SMB_ACL_USER_OBJ ACE (the owner ACE entry) has a duplicate
1447            permission entry as an SMB_ACL_USER, and a gid for a
1448            SMB_ACL_GROUP_OBJ ACE (the primary group ACE entry) also has
1449            a duplicate permission entry as an SMB_ACL_GROUP. If not,
1450            then if the ownership or group ownership of this file or
1451            directory gets changed, the user or group can lose their
1452            access. */
1453
1454         for (pace = *pp_ace; pace; pace = pace->next) {
1455                 if (pace->type == SMB_ACL_USER &&
1456                                 pace->unix_ug.id == pace_user->unix_ug.id) {
1457                         /* Already got one. */
1458                         got_duplicate_user = true;
1459                 } else if (pace->type == SMB_ACL_GROUP &&
1460                                 pace->unix_ug.id == pace_group->unix_ug.id) {
1461                         /* Already got one. */
1462                         got_duplicate_group = true;
1463                 } else if ((pace->type == SMB_ACL_GROUP)
1464                            && (dom_sid_equal(&pace->trustee, &pace_user->trustee))) {
1465                         /* If the SID owning the file appears
1466                          * in a group entry, then we have
1467                          * enough duplication, they will still
1468                          * have access */
1469                         got_duplicate_user = true;
1470                 }
1471         }
1472
1473         /* If the SID is equal for the user and group that we need
1474            to add the duplicate for, add only the group */
1475         if (!got_duplicate_user && !got_duplicate_group
1476                         && dom_sid_equal(&pace_group->trustee,
1477                                         &pace_user->trustee)) {
1478                 /* Add a duplicate SMB_ACL_GROUP entry, this
1479                  * will cover the owning SID as well, as it
1480                  * will always be mapped to both a uid and
1481                  * gid. */
1482
1483                 if ((pace = talloc(talloc_tos(), canon_ace)) == NULL) {
1484                         DEBUG(0,("talloc fail.\n"));
1485                         return false;
1486                 }
1487
1488                 ZERO_STRUCTP(pace);
1489                 pace->type = SMB_ACL_GROUP;;
1490                 pace->owner_type = GID_ACE;
1491                 pace->unix_ug.type = ID_TYPE_GID;
1492                 pace->unix_ug.id = pace_group->unix_ug.id;
1493                 pace->trustee = pace_group->trustee;
1494                 pace->attr = pace_group->attr;
1495                 pace->perms = pace_group->perms;
1496
1497                 DLIST_ADD(*pp_ace, pace);
1498
1499                 /* We're done here, make sure the
1500                    statements below are not executed. */
1501                 got_duplicate_user = true;
1502                 got_duplicate_group = true;
1503         }
1504
1505         if (!got_duplicate_user) {
1506                 /* Add a duplicate SMB_ACL_USER entry. */
1507                 if ((pace = talloc(talloc_tos(), canon_ace)) == NULL) {
1508                         DEBUG(0,("talloc fail.\n"));
1509                         return false;
1510                 }
1511
1512                 ZERO_STRUCTP(pace);
1513                 pace->type = SMB_ACL_USER;;
1514                 pace->owner_type = UID_ACE;
1515                 pace->unix_ug.type = ID_TYPE_UID;
1516                 pace->unix_ug.id = pace_user->unix_ug.id;
1517                 pace->trustee = pace_user->trustee;
1518                 pace->attr = pace_user->attr;
1519                 pace->perms = pace_user->perms;
1520
1521                 DLIST_ADD(*pp_ace, pace);
1522
1523                 got_duplicate_user = true;
1524         }
1525
1526         if (!got_duplicate_group) {
1527                 /* Add a duplicate SMB_ACL_GROUP entry. */
1528                 if ((pace = talloc(talloc_tos(), canon_ace)) == NULL) {
1529                         DEBUG(0,("talloc fail.\n"));
1530                         return false;
1531                 }
1532
1533                 ZERO_STRUCTP(pace);
1534                 pace->type = SMB_ACL_GROUP;;
1535                 pace->owner_type = GID_ACE;
1536                 pace->unix_ug.type = ID_TYPE_GID;
1537                 pace->unix_ug.id = pace_group->unix_ug.id;
1538                 pace->trustee = pace_group->trustee;
1539                 pace->attr = pace_group->attr;
1540                 pace->perms = pace_group->perms;
1541
1542                 DLIST_ADD(*pp_ace, pace);
1543
1544                 got_duplicate_group = true;
1545         }
1546
1547         return true;
1548 }
1549
1550 /****************************************************************************
1551  Check if a POSIX ACL has the required SMB_ACL_USER_OBJ and SMB_ACL_GROUP_OBJ entries.
1552  If it does not have them, check if there are any entries where the trustee is the
1553  file owner or the owning group, and map these to SMB_ACL_USER_OBJ and SMB_ACL_GROUP_OBJ.
1554  Note we must not do this to default directory ACLs.
1555 ****************************************************************************/
1556
1557 static void check_owning_objs(canon_ace *ace, struct dom_sid *pfile_owner_sid, struct dom_sid *pfile_grp_sid)
1558 {
1559         bool got_user_obj, got_group_obj;
1560         canon_ace *current_ace;
1561         int i, entries;
1562
1563         entries = count_canon_ace_list(ace);
1564         got_user_obj = False;
1565         got_group_obj = False;
1566
1567         for (i=0, current_ace = ace; i < entries; i++, current_ace = current_ace->next) {
1568                 if (current_ace->type == SMB_ACL_USER_OBJ)
1569                         got_user_obj = True;
1570                 else if (current_ace->type == SMB_ACL_GROUP_OBJ)
1571                         got_group_obj = True;
1572         }
1573         if (got_user_obj && got_group_obj) {
1574                 DEBUG(10,("check_owning_objs: ACL had owning user/group entries.\n"));
1575                 return;
1576         }
1577
1578         for (i=0, current_ace = ace; i < entries; i++, current_ace = current_ace->next) {
1579                 if (!got_user_obj && current_ace->owner_type == UID_ACE &&
1580                                 dom_sid_equal(&current_ace->trustee, pfile_owner_sid)) {
1581                         current_ace->type = SMB_ACL_USER_OBJ;
1582                         got_user_obj = True;
1583                 }
1584                 if (!got_group_obj && current_ace->owner_type == GID_ACE &&
1585                                 dom_sid_equal(&current_ace->trustee, pfile_grp_sid)) {
1586                         current_ace->type = SMB_ACL_GROUP_OBJ;
1587                         got_group_obj = True;
1588                 }
1589         }
1590         if (!got_user_obj)
1591                 DEBUG(10,("check_owning_objs: ACL is missing an owner entry.\n"));
1592         if (!got_group_obj)
1593                 DEBUG(10,("check_owning_objs: ACL is missing an owning group entry.\n"));
1594 }
1595
1596 static bool add_current_ace_to_acl(files_struct *fsp, struct security_ace *psa,
1597                                    canon_ace **file_ace, canon_ace **dir_ace,
1598                                    bool *got_file_allow, bool *got_dir_allow,
1599                                    bool *all_aces_are_inherit_only,
1600                                    canon_ace *current_ace)
1601 {
1602
1603         /*
1604          * Map the given NT permissions into a UNIX mode_t containing only
1605          * S_I(R|W|X)USR bits.
1606          */
1607
1608         current_ace->perms |= map_nt_perms( &psa->access_mask, S_IRUSR);
1609         current_ace->attr = (psa->type == SEC_ACE_TYPE_ACCESS_ALLOWED) ? ALLOW_ACE : DENY_ACE;
1610
1611         /* Store the ace_flag. */
1612         current_ace->ace_flags = psa->flags;
1613
1614         /*
1615          * Now add the created ace to either the file list, the directory
1616          * list, or both. We *MUST* preserve the order here (hence we use
1617          * DLIST_ADD_END) as NT ACLs are order dependent.
1618          */
1619
1620         if (fsp->fsp_flags.is_directory) {
1621
1622                 /*
1623                  * We can only add to the default POSIX ACE list if the ACE is
1624                  * designed to be inherited by both files and directories.
1625                  */
1626
1627                 if ((psa->flags & (SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT)) ==
1628                     (SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT)) {
1629
1630                         canon_ace *current_dir_ace = current_ace;
1631                         DLIST_ADD_END(*dir_ace, current_ace);
1632
1633                         /*
1634                          * Note if this was an allow ace. We can't process
1635                          * any further deny ace's after this.
1636                          */
1637
1638                         if (current_ace->attr == ALLOW_ACE)
1639                                 *got_dir_allow = True;
1640
1641                         if ((current_ace->attr == DENY_ACE) && *got_dir_allow) {
1642                                 DEBUG(0,("add_current_ace_to_acl: "
1643                                          "malformed ACL in "
1644                                          "inheritable ACL! Deny entry "
1645                                          "after Allow entry. Failing "
1646                                          "to set on file %s.\n",
1647                                          fsp_str_dbg(fsp)));
1648                                 return False;
1649                         }
1650
1651                         if( DEBUGLVL( 10 )) {
1652                                 dbgtext("add_current_ace_to_acl: adding dir ACL:\n");
1653                                 print_canon_ace( current_ace, 0);
1654                         }
1655
1656                         /*
1657                          * If this is not an inherit only ACE we need to add a duplicate
1658                          * to the file acl.
1659                          */
1660
1661                         if (!(psa->flags & SEC_ACE_FLAG_INHERIT_ONLY)) {
1662                                 canon_ace *dup_ace = dup_canon_ace(current_ace);
1663
1664                                 if (!dup_ace) {
1665                                         DEBUG(0,("add_current_ace_to_acl: malloc fail !\n"));
1666                                         return False;
1667                                 }
1668
1669                                 /*
1670                                  * We must not free current_ace here as its
1671                                  * pointer is now owned by the dir_ace list.
1672                                  */
1673                                 current_ace = dup_ace;
1674                                 /* We've essentially split this ace into two,
1675                                  * and added the ace with inheritance request
1676                                  * bits to the directory ACL. Drop those bits for
1677                                  * the ACE we're adding to the file list. */
1678                                 current_ace->ace_flags &= ~(SEC_ACE_FLAG_OBJECT_INHERIT|
1679                                                             SEC_ACE_FLAG_CONTAINER_INHERIT|
1680                                                             SEC_ACE_FLAG_INHERIT_ONLY);
1681                         } else {
1682                                 /*
1683                                  * We must not free current_ace here as its
1684                                  * pointer is now owned by the dir_ace list.
1685                                  */
1686                                 current_ace = NULL;
1687                         }
1688
1689                         /*
1690                          * current_ace is now either owned by file_ace
1691                          * or is NULL. We can safely operate on current_dir_ace
1692                          * to treat mapping for default acl entries differently
1693                          * than access acl entries.
1694                          */
1695
1696                         if (current_dir_ace->owner_type == UID_ACE) {
1697                                 /*
1698                                  * We already decided above this is a uid,
1699                                  * for default acls ace's only CREATOR_OWNER
1700                                  * maps to ACL_USER_OBJ. All other uid
1701                                  * ace's are ACL_USER.
1702                                  */
1703                                 if (dom_sid_equal(&current_dir_ace->trustee,
1704                                                   &global_sid_Creator_Owner)) {
1705                                         current_dir_ace->type = SMB_ACL_USER_OBJ;
1706                                 } else {
1707                                         current_dir_ace->type = SMB_ACL_USER;
1708                                 }
1709                         }
1710
1711                         if (current_dir_ace->owner_type == GID_ACE) {
1712                                 /*
1713                                  * We already decided above this is a gid,
1714                                  * for default acls ace's only CREATOR_GROUP
1715                                  * maps to ACL_GROUP_OBJ. All other uid
1716                                  * ace's are ACL_GROUP.
1717                                  */
1718                                 if (dom_sid_equal(&current_dir_ace->trustee,
1719                                                   &global_sid_Creator_Group)) {
1720                                         current_dir_ace->type = SMB_ACL_GROUP_OBJ;
1721                                 } else {
1722                                         current_dir_ace->type = SMB_ACL_GROUP;
1723                                 }
1724                         }
1725                 }
1726         }
1727
1728         /*
1729          * Only add to the file ACL if not inherit only.
1730          */
1731
1732         if (current_ace && !(psa->flags & SEC_ACE_FLAG_INHERIT_ONLY)) {
1733                 DLIST_ADD_END(*file_ace, current_ace);
1734
1735                 /*
1736                  * Note if this was an allow ace. We can't process
1737                  * any further deny ace's after this.
1738                  */
1739
1740                 if (current_ace->attr == ALLOW_ACE)
1741                         *got_file_allow = True;
1742
1743                 if ((current_ace->attr == DENY_ACE) && *got_file_allow) {
1744                         DEBUG(0,("add_current_ace_to_acl: malformed "
1745                                  "ACL in file ACL ! Deny entry after "
1746                                  "Allow entry. Failing to set on file "
1747                                  "%s.\n", fsp_str_dbg(fsp)));
1748                         return False;
1749                 }
1750
1751                 if( DEBUGLVL( 10 )) {
1752                         dbgtext("add_current_ace_to_acl: adding file ACL:\n");
1753                         print_canon_ace( current_ace, 0);
1754                 }
1755                 *all_aces_are_inherit_only = False;
1756                 /*
1757                  * We must not free current_ace here as its
1758                  * pointer is now owned by the file_ace list.
1759                  */
1760                 current_ace = NULL;
1761         }
1762
1763         /*
1764          * Free if ACE was not added.
1765          */
1766
1767         TALLOC_FREE(current_ace);
1768         return true;
1769 }
1770
1771 /****************************************************************************
1772  Unpack a struct security_descriptor into two canonical ace lists.
1773 ****************************************************************************/
1774
1775 static bool create_canon_ace_lists(files_struct *fsp,
1776                                         const SMB_STRUCT_STAT *pst,
1777                                         struct dom_sid *pfile_owner_sid,
1778                                         struct dom_sid *pfile_grp_sid,
1779                                         canon_ace **ppfile_ace,
1780                                         canon_ace **ppdir_ace,
1781                                         const struct security_acl *dacl)
1782 {
1783         bool all_aces_are_inherit_only = (fsp->fsp_flags.is_directory);
1784         canon_ace *file_ace = NULL;
1785         canon_ace *dir_ace = NULL;
1786         canon_ace *current_ace = NULL;
1787         bool got_dir_allow = False;
1788         bool got_file_allow = False;
1789         uint32_t i, j;
1790
1791         *ppfile_ace = NULL;
1792         *ppdir_ace = NULL;
1793
1794         /*
1795          * Convert the incoming ACL into a more regular form.
1796          */
1797
1798         for(i = 0; i < dacl->num_aces; i++) {
1799                 struct security_ace *psa = &dacl->aces[i];
1800
1801                 if((psa->type != SEC_ACE_TYPE_ACCESS_ALLOWED) && (psa->type != SEC_ACE_TYPE_ACCESS_DENIED)) {
1802                         DEBUG(3,("create_canon_ace_lists: unable to set anything but an ALLOW or DENY ACE.\n"));
1803                         return False;
1804                 }
1805         }
1806
1807         /*
1808          * Deal with the fact that NT 4.x re-writes the canonical format
1809          * that we return for default ACLs. If a directory ACE is identical
1810          * to a inherited directory ACE then NT changes the bits so that the
1811          * first ACE is set to OI|IO and the second ACE for this SID is set
1812          * to CI. We need to repair this. JRA.
1813          */
1814
1815         for(i = 0; i < dacl->num_aces; i++) {
1816                 struct security_ace *psa1 = &dacl->aces[i];
1817
1818                 for (j = i + 1; j < dacl->num_aces; j++) {
1819                         struct security_ace *psa2 = &dacl->aces[j];
1820
1821                         if (psa1->access_mask != psa2->access_mask)
1822                                 continue;
1823
1824                         if (!dom_sid_equal(&psa1->trustee, &psa2->trustee))
1825                                 continue;
1826
1827                         /*
1828                          * Ok - permission bits and SIDs are equal.
1829                          * Check if flags were re-written.
1830                          */
1831
1832                         if (psa1->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
1833
1834                                 psa1->flags |= (psa2->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT));
1835                                 psa2->flags &= ~(SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT);
1836
1837                         } else if (psa2->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
1838
1839                                 psa2->flags |= (psa1->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT));
1840                                 psa1->flags &= ~(SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT);
1841
1842                         }
1843                 }
1844         }
1845
1846         for(i = 0; i < dacl->num_aces; i++) {
1847                 struct security_ace *psa = &dacl->aces[i];
1848
1849                 /*
1850                  * Create a canon_ace entry representing this NT DACL ACE.
1851                  */
1852
1853                 if ((current_ace = talloc(talloc_tos(), canon_ace)) == NULL) {
1854                         free_canon_ace_list(file_ace);
1855                         free_canon_ace_list(dir_ace);
1856                         DEBUG(0,("create_canon_ace_lists: malloc fail.\n"));
1857                         return False;
1858                 }
1859
1860                 ZERO_STRUCTP(current_ace);
1861
1862                 sid_copy(&current_ace->trustee, &psa->trustee);
1863
1864                 /*
1865                  * Try and work out if the SID is a user or group
1866                  * as we need to flag these differently for POSIX.
1867                  * Note what kind of a POSIX ACL this should map to.
1868                  */
1869
1870                 if( dom_sid_equal(&current_ace->trustee, &global_sid_World)) {
1871                         current_ace->owner_type = WORLD_ACE;
1872                         current_ace->unix_ug.type = ID_TYPE_NOT_SPECIFIED;
1873                         current_ace->unix_ug.id = -1;
1874                         current_ace->type = SMB_ACL_OTHER;
1875                 } else if (dom_sid_equal(&current_ace->trustee, &global_sid_Creator_Owner)) {
1876                         current_ace->owner_type = UID_ACE;
1877                         current_ace->unix_ug.type = ID_TYPE_UID;
1878                         current_ace->unix_ug.id = pst->st_ex_uid;
1879                         current_ace->type = SMB_ACL_USER_OBJ;
1880
1881                         /*
1882                          * The Creator Owner entry only specifies inheritable permissions,
1883                          * never access permissions. WinNT doesn't always set the ACE to
1884                          * INHERIT_ONLY, though.
1885                          */
1886
1887                         psa->flags |= SEC_ACE_FLAG_INHERIT_ONLY;
1888
1889                 } else if (dom_sid_equal(&current_ace->trustee, &global_sid_Creator_Group)) {
1890                         current_ace->owner_type = GID_ACE;
1891                         current_ace->unix_ug.type = ID_TYPE_GID;
1892                         current_ace->unix_ug.id = pst->st_ex_gid;
1893                         current_ace->type = SMB_ACL_GROUP_OBJ;
1894
1895                         /*
1896                          * The Creator Group entry only specifies inheritable permissions,
1897                          * never access permissions. WinNT doesn't always set the ACE to
1898                          * INHERIT_ONLY, though.
1899                          */
1900                         psa->flags |= SEC_ACE_FLAG_INHERIT_ONLY;
1901
1902                 } else {
1903                         struct unixid unixid;
1904
1905                         if (!sids_to_unixids(&current_ace->trustee, 1, &unixid)) {
1906                                 struct dom_sid_buf buf;
1907                                 free_canon_ace_list(file_ace);
1908                                 free_canon_ace_list(dir_ace);
1909                                 TALLOC_FREE(current_ace);
1910                                 DBG_ERR("sids_to_unixids failed for %s "
1911                                         "(allocation failure)\n",
1912                                         dom_sid_str_buf(&current_ace->trustee,
1913                                                         &buf));
1914                                 return false;
1915                         }
1916
1917                         if (unixid.type == ID_TYPE_BOTH) {
1918                                 /*
1919                                  * We must add both a user and group
1920                                  * entry POSIX_ACL.
1921                                  * This is due to the fact that in POSIX
1922                                  * user entries are more specific than
1923                                  * groups.
1924                                  */
1925                                 current_ace->owner_type = UID_ACE;
1926                                 current_ace->unix_ug.type = ID_TYPE_UID;
1927                                 current_ace->unix_ug.id = unixid.id;
1928                                 current_ace->type =
1929                                         (unixid.id == pst->st_ex_uid) ?
1930                                                 SMB_ACL_USER_OBJ :
1931                                                 SMB_ACL_USER;
1932
1933                                 /* Add the user object to the posix ACL,
1934                                    and proceed to the group mapping
1935                                    below. This handles the talloc_free
1936                                    of current_ace if not added for some
1937                                    reason */
1938                                 if (!add_current_ace_to_acl(fsp,
1939                                                 psa,
1940                                                 &file_ace,
1941                                                 &dir_ace,
1942                                                 &got_file_allow,
1943                                                 &got_dir_allow,
1944                                                 &all_aces_are_inherit_only,
1945                                                 current_ace)) {
1946                                         free_canon_ace_list(file_ace);
1947                                         free_canon_ace_list(dir_ace);
1948                                         return false;
1949                                 }
1950
1951                                 if ((current_ace = talloc(talloc_tos(),
1952                                                 canon_ace)) == NULL) {
1953                                         free_canon_ace_list(file_ace);
1954                                         free_canon_ace_list(dir_ace);
1955                                         DEBUG(0,("create_canon_ace_lists: "
1956                                                 "malloc fail.\n"));
1957                                         return False;
1958                                 }
1959
1960                                 ZERO_STRUCTP(current_ace);
1961
1962                                 sid_copy(&current_ace->trustee, &psa->trustee);
1963
1964                                 current_ace->unix_ug.type = ID_TYPE_GID;
1965                                 current_ace->unix_ug.id = unixid.id;
1966                                 current_ace->owner_type = GID_ACE;
1967                                 /* If it's the primary group, this is a
1968                                    group_obj, not a group. */
1969                                 if (current_ace->unix_ug.id == pst->st_ex_gid) {
1970                                         current_ace->type = SMB_ACL_GROUP_OBJ;
1971                                 } else {
1972                                         current_ace->type = SMB_ACL_GROUP;
1973                                 }
1974
1975                         } else if (unixid.type == ID_TYPE_UID) {
1976                                 current_ace->owner_type = UID_ACE;
1977                                 current_ace->unix_ug.type = ID_TYPE_UID;
1978                                 current_ace->unix_ug.id = unixid.id;
1979                                 /* If it's the owning user, this is a user_obj,
1980                                    not a user. */
1981                                 if (current_ace->unix_ug.id == pst->st_ex_uid) {
1982                                         current_ace->type = SMB_ACL_USER_OBJ;
1983                                 } else {
1984                                         current_ace->type = SMB_ACL_USER;
1985                                 }
1986                         } else if (unixid.type == ID_TYPE_GID) {
1987                                 current_ace->unix_ug.type = ID_TYPE_GID;
1988                                 current_ace->unix_ug.id = unixid.id;
1989                                 current_ace->owner_type = GID_ACE;
1990                                 /* If it's the primary group, this is a
1991                                    group_obj, not a group. */
1992                                 if (current_ace->unix_ug.id == pst->st_ex_gid) {
1993                                         current_ace->type = SMB_ACL_GROUP_OBJ;
1994                                 } else {
1995                                         current_ace->type = SMB_ACL_GROUP;
1996                                 }
1997                         } else {
1998                                 struct dom_sid_buf buf;
1999                                 /*
2000                                  * Silently ignore map failures in non-mappable SIDs (NT Authority, BUILTIN etc).
2001                                  */
2002
2003                                 if (non_mappable_sid(&psa->trustee)) {
2004                                         DBG_DEBUG("ignoring "
2005                                                   "non-mappable SID %s\n",
2006                                                   dom_sid_str_buf(
2007                                                           &psa->trustee,
2008                                                           &buf));
2009                                         TALLOC_FREE(current_ace);
2010                                         continue;
2011                                 }
2012
2013                                 if (lp_force_unknown_acl_user(SNUM(fsp->conn))) {
2014                                         DBG_DEBUG("ignoring unknown or "
2015                                                   "foreign SID %s\n",
2016                                                   dom_sid_str_buf(
2017                                                           &psa->trustee,
2018                                                           &buf));
2019                                         TALLOC_FREE(current_ace);
2020                                         continue;
2021                                 }
2022
2023                                 free_canon_ace_list(file_ace);
2024                                 free_canon_ace_list(dir_ace);
2025                                 DBG_ERR("unable to map SID %s to uid or "
2026                                         "gid.\n",
2027                                         dom_sid_str_buf(&current_ace->trustee,
2028                                                         &buf));
2029                                 TALLOC_FREE(current_ace);
2030                                 return false;
2031                         }
2032                 }
2033
2034                 /* handles the talloc_free of current_ace if not added for some reason */
2035                 if (!add_current_ace_to_acl(fsp, psa, &file_ace, &dir_ace,
2036                                             &got_file_allow, &got_dir_allow,
2037                                             &all_aces_are_inherit_only, current_ace)) {
2038                         free_canon_ace_list(file_ace);
2039                         free_canon_ace_list(dir_ace);
2040                         return false;
2041                 }
2042         }
2043
2044         if (fsp->fsp_flags.is_directory && all_aces_are_inherit_only) {
2045                 /*
2046                  * Windows 2000 is doing one of these weird 'inherit acl'
2047                  * traverses to conserve NTFS ACL resources. Just pretend
2048                  * there was no DACL sent. JRA.
2049                  */
2050
2051                 DEBUG(10,("create_canon_ace_lists: Win2k inherit acl traverse. Ignoring DACL.\n"));
2052                 free_canon_ace_list(file_ace);
2053                 free_canon_ace_list(dir_ace);
2054                 file_ace = NULL;
2055                 dir_ace = NULL;
2056         } else {
2057                 /*
2058                  * Check if we have SMB_ACL_USER_OBJ and SMB_ACL_GROUP_OBJ entries in
2059                  * the file ACL. If we don't have them, check if any SMB_ACL_USER/SMB_ACL_GROUP
2060                  * entries can be converted to *_OBJ. Don't do this for the default
2061                  * ACL, we will create them separately for this if needed inside
2062                  * ensure_canon_entry_valid_on_set().
2063                  */
2064                 if (file_ace) {
2065                         check_owning_objs(file_ace, pfile_owner_sid, pfile_grp_sid);
2066                 }
2067         }
2068
2069         *ppfile_ace = file_ace;
2070         *ppdir_ace = dir_ace;
2071
2072         return True;
2073 }
2074
2075 /****************************************************************************
2076  ASCII art time again... JRA :-).
2077
2078  We have 4 cases to process when moving from an NT ACL to a POSIX ACL. Firstly,
2079  we insist the ACL is in canonical form (ie. all DENY entries precede ALLOW
2080  entries). Secondly, the merge code has ensured that all duplicate SID entries for
2081  allow or deny have been merged, so the same SID can only appear once in the deny
2082  list or once in the allow list.
2083
2084  We then process as follows :
2085
2086  ---------------------------------------------------------------------------
2087  First pass - look for a Everyone DENY entry.
2088
2089  If it is deny all (rwx) trunate the list at this point.
2090  Else, walk the list from this point and use the deny permissions of this
2091  entry as a mask on all following allow entries. Finally, delete
2092  the Everyone DENY entry (we have applied it to everything possible).
2093
2094  In addition, in this pass we remove any DENY entries that have 
2095  no permissions (ie. they are a DENY nothing).
2096  ---------------------------------------------------------------------------
2097  Second pass - only deal with deny user entries.
2098
2099  DENY user1 (perms XXX)
2100
2101  new_perms = 0
2102  for all following allow group entries where user1 is in group
2103         new_perms |= group_perms;
2104
2105  user1 entry perms = new_perms & ~ XXX;
2106
2107  Convert the deny entry to an allow entry with the new perms and
2108  push to the end of the list. Note if the user was in no groups
2109  this maps to a specific allow nothing entry for this user.
2110
2111  The common case from the NT ACL chooser (userX deny all) is
2112  optimised so we don't do the group lookup - we just map to
2113  an allow nothing entry.
2114
2115  What we're doing here is inferring the allow permissions the
2116  person setting the ACE on user1 wanted by looking at the allow
2117  permissions on the groups the user is currently in. This will
2118  be a snapshot, depending on group membership but is the best
2119  we can do and has the advantage of failing closed rather than
2120  open.
2121  ---------------------------------------------------------------------------
2122  Third pass - only deal with deny group entries.
2123
2124  DENY group1 (perms XXX)
2125
2126  for all following allow user entries where user is in group1
2127    user entry perms = user entry perms & ~ XXX;
2128
2129  If there is a group Everyone allow entry with permissions YYY,
2130  convert the group1 entry to an allow entry and modify its
2131  permissions to be :
2132
2133  new_perms = YYY & ~ XXX
2134
2135  and push to the end of the list.
2136
2137  If there is no group Everyone allow entry then convert the
2138  group1 entry to a allow nothing entry and push to the end of the list.
2139
2140  Note that the common case from the NT ACL chooser (groupX deny all)
2141  cannot be optimised here as we need to modify user entries who are
2142  in the group to change them to a deny all also.
2143
2144  What we're doing here is modifying the allow permissions of
2145  user entries (which are more specific in POSIX ACLs) to mask
2146  out the explicit deny set on the group they are in. This will
2147  be a snapshot depending on current group membership but is the
2148  best we can do and has the advantage of failing closed rather
2149  than open.
2150  ---------------------------------------------------------------------------
2151  Fourth pass - cope with cumulative permissions.
2152
2153  for all allow user entries, if there exists an allow group entry with
2154  more permissive permissions, and the user is in that group, rewrite the
2155  allow user permissions to contain both sets of permissions.
2156
2157  Currently the code for this is #ifdef'ed out as these semantics make
2158  no sense to me. JRA.
2159  ---------------------------------------------------------------------------
2160
2161  Note we *MUST* do the deny user pass first as this will convert deny user
2162  entries into allow user entries which can then be processed by the deny
2163  group pass.
2164
2165  The above algorithm took a *lot* of thinking about - hence this
2166  explanation :-). JRA.
2167 ****************************************************************************/
2168
2169 /****************************************************************************
2170  Process a canon_ace list entries. This is very complex code. We need
2171  to go through and remove the "deny" permissions from any allow entry that matches
2172  the id of this entry. We have already refused any NT ACL that wasn't in correct
2173  order (DENY followed by ALLOW). If any allow entry ends up with zero permissions,
2174  we just remove it (to fail safe). We have already removed any duplicate ace
2175  entries. Treat an "Everyone" DENY_ACE as a special case - use it to mask all
2176  allow entries.
2177 ****************************************************************************/
2178
2179 static void process_deny_list(connection_struct *conn, canon_ace **pp_ace_list )
2180 {
2181         canon_ace *ace_list = *pp_ace_list;
2182         canon_ace *curr_ace = NULL;
2183         canon_ace *curr_ace_next = NULL;
2184
2185         /* Pass 1 above - look for an Everyone, deny entry. */
2186
2187         for (curr_ace = ace_list; curr_ace; curr_ace = curr_ace_next) {
2188                 canon_ace *allow_ace_p;
2189
2190                 curr_ace_next = curr_ace->next; /* So we can't lose the link. */
2191
2192                 if (curr_ace->attr != DENY_ACE)
2193                         continue;
2194
2195                 if (curr_ace->perms == (mode_t)0) {
2196
2197                         /* Deny nothing entry - delete. */
2198
2199                         DLIST_REMOVE(ace_list, curr_ace);
2200                         continue;
2201                 }
2202
2203                 if (!dom_sid_equal(&curr_ace->trustee, &global_sid_World))
2204                         continue;
2205
2206                 /* JRATEST - assert. */
2207                 SMB_ASSERT(curr_ace->owner_type == WORLD_ACE);
2208
2209                 if (curr_ace->perms == ALL_ACE_PERMS) {
2210
2211                         /*
2212                          * Optimisation. This is a DENY_ALL to Everyone. Truncate the
2213                          * list at this point including this entry.
2214                          */
2215
2216                         canon_ace *prev_entry = DLIST_PREV(curr_ace);
2217
2218                         free_canon_ace_list( curr_ace );
2219                         if (prev_entry)
2220                                 DLIST_REMOVE(ace_list, prev_entry);
2221                         else {
2222                                 /* We deleted the entire list. */
2223                                 ace_list = NULL;
2224                         }
2225                         break;
2226                 }
2227
2228                 for (allow_ace_p = curr_ace->next; allow_ace_p; allow_ace_p = allow_ace_p->next) {
2229
2230                         /* 
2231                          * Only mask off allow entries.
2232                          */
2233
2234                         if (allow_ace_p->attr != ALLOW_ACE)
2235                                 continue;
2236
2237                         allow_ace_p->perms &= ~curr_ace->perms;
2238                 }
2239
2240                 /*
2241                  * Now it's been applied, remove it.
2242                  */
2243
2244                 DLIST_REMOVE(ace_list, curr_ace);
2245         }
2246
2247         /* Pass 2 above - deal with deny user entries. */
2248
2249         for (curr_ace = ace_list; curr_ace; curr_ace = curr_ace_next) {
2250                 mode_t new_perms = (mode_t)0;
2251                 canon_ace *allow_ace_p;
2252
2253                 curr_ace_next = curr_ace->next; /* So we can't lose the link. */
2254
2255                 if (curr_ace->attr != DENY_ACE)
2256                         continue;
2257
2258                 if (curr_ace->owner_type != UID_ACE)
2259                         continue;
2260
2261                 if (curr_ace->perms == ALL_ACE_PERMS) {
2262
2263                         /*
2264                          * Optimisation - this is a deny everything to this user.
2265                          * Convert to an allow nothing and push to the end of the list.
2266                          */
2267
2268                         curr_ace->attr = ALLOW_ACE;
2269                         curr_ace->perms = (mode_t)0;
2270                         DLIST_DEMOTE(ace_list, curr_ace);
2271                         continue;
2272                 }
2273
2274                 for (allow_ace_p = curr_ace->next; allow_ace_p; allow_ace_p = allow_ace_p->next) {
2275
2276                         if (allow_ace_p->attr != ALLOW_ACE)
2277                                 continue;
2278
2279                         /* We process GID_ACE and WORLD_ACE entries only. */
2280
2281                         if (allow_ace_p->owner_type == UID_ACE)
2282                                 continue;
2283
2284                         if (uid_entry_in_group(conn, curr_ace, allow_ace_p))
2285                                 new_perms |= allow_ace_p->perms;
2286                 }
2287
2288                 /*
2289                  * Convert to a allow entry, modify the perms and push to the end
2290                  * of the list.
2291                  */
2292
2293                 curr_ace->attr = ALLOW_ACE;
2294                 curr_ace->perms = (new_perms & ~curr_ace->perms);
2295                 DLIST_DEMOTE(ace_list, curr_ace);
2296         }
2297
2298         /* Pass 3 above - deal with deny group entries. */
2299
2300         for (curr_ace = ace_list; curr_ace; curr_ace = curr_ace_next) {
2301                 canon_ace *allow_ace_p;
2302                 canon_ace *allow_everyone_p = NULL;
2303
2304                 curr_ace_next = curr_ace->next; /* So we can't lose the link. */
2305
2306                 if (curr_ace->attr != DENY_ACE)
2307                         continue;
2308
2309                 if (curr_ace->owner_type != GID_ACE)
2310                         continue;
2311
2312                 for (allow_ace_p = curr_ace->next; allow_ace_p; allow_ace_p = allow_ace_p->next) {
2313
2314                         if (allow_ace_p->attr != ALLOW_ACE)
2315                                 continue;
2316
2317                         /* Store a pointer to the Everyone allow, if it exists. */
2318                         if (allow_ace_p->owner_type == WORLD_ACE)
2319                                 allow_everyone_p = allow_ace_p;
2320
2321                         /* We process UID_ACE entries only. */
2322
2323                         if (allow_ace_p->owner_type != UID_ACE)
2324                                 continue;
2325
2326                         /* Mask off the deny group perms. */
2327
2328                         if (uid_entry_in_group(conn, allow_ace_p, curr_ace))
2329                                 allow_ace_p->perms &= ~curr_ace->perms;
2330                 }
2331
2332                 /*
2333                  * Convert the deny to an allow with the correct perms and
2334                  * push to the end of the list.
2335                  */
2336
2337                 curr_ace->attr = ALLOW_ACE;
2338                 if (allow_everyone_p)
2339                         curr_ace->perms = allow_everyone_p->perms & ~curr_ace->perms;
2340                 else
2341                         curr_ace->perms = (mode_t)0;
2342                 DLIST_DEMOTE(ace_list, curr_ace);
2343         }
2344
2345         /* Doing this fourth pass allows Windows semantics to be layered
2346          * on top of POSIX semantics. I'm not sure if this is desirable.
2347          * For example, in W2K ACLs there is no way to say, "Group X no
2348          * access, user Y full access" if user Y is a member of group X.
2349          * This seems completely broken semantics to me.... JRA.
2350          */
2351
2352 #if 0
2353         /* Pass 4 above - deal with allow entries. */
2354
2355         for (curr_ace = ace_list; curr_ace; curr_ace = curr_ace_next) {
2356                 canon_ace *allow_ace_p;
2357
2358                 curr_ace_next = curr_ace->next; /* So we can't lose the link. */
2359
2360                 if (curr_ace->attr != ALLOW_ACE)
2361                         continue;
2362
2363                 if (curr_ace->owner_type != UID_ACE)
2364                         continue;
2365
2366                 for (allow_ace_p = ace_list; allow_ace_p; allow_ace_p = allow_ace_p->next) {
2367
2368                         if (allow_ace_p->attr != ALLOW_ACE)
2369                                 continue;
2370
2371                         /* We process GID_ACE entries only. */
2372
2373                         if (allow_ace_p->owner_type != GID_ACE)
2374                                 continue;
2375
2376                         /* OR in the group perms. */
2377
2378                         if (uid_entry_in_group(conn, curr_ace, allow_ace_p))
2379                                 curr_ace->perms |= allow_ace_p->perms;
2380                 }
2381         }
2382 #endif
2383
2384         *pp_ace_list = ace_list;
2385 }
2386
2387 /****************************************************************************
2388  Unpack a struct security_descriptor into two canonical ace lists. We don't depend on this
2389  succeeding.
2390 ****************************************************************************/
2391
2392 static bool unpack_canon_ace(files_struct *fsp,
2393                                 const SMB_STRUCT_STAT *pst,
2394                                 struct dom_sid *pfile_owner_sid,
2395                                 struct dom_sid *pfile_grp_sid,
2396                                 canon_ace **ppfile_ace,
2397                                 canon_ace **ppdir_ace,
2398                                 uint32_t security_info_sent,
2399                                 const struct security_descriptor *psd)
2400 {
2401         canon_ace *file_ace = NULL;
2402         canon_ace *dir_ace = NULL;
2403         bool ok;
2404
2405         *ppfile_ace = NULL;
2406         *ppdir_ace = NULL;
2407
2408         if(security_info_sent == 0) {
2409                 DEBUG(0,("unpack_canon_ace: no security info sent !\n"));
2410                 return False;
2411         }
2412
2413         /*
2414          * If no DACL then this is a chown only security descriptor.
2415          */
2416
2417         if(!(security_info_sent & SECINFO_DACL) || !psd->dacl)
2418                 return True;
2419
2420         /*
2421          * Now go through the DACL and create the canon_ace lists.
2422          */
2423
2424         if (!create_canon_ace_lists(fsp, pst, pfile_owner_sid, pfile_grp_sid,
2425                                     &file_ace, &dir_ace, psd->dacl)) {
2426                 return False;
2427         }
2428
2429         if ((file_ace == NULL) && (dir_ace == NULL)) {
2430                 /* W2K traverse DACL set - ignore. */
2431                 return True;
2432         }
2433
2434         /*
2435          * Go through the canon_ace list and merge entries
2436          * belonging to identical users of identical allow or deny type.
2437          * We can do this as all deny entries come first, followed by
2438          * all allow entries (we have mandated this before accepting this acl).
2439          */
2440
2441         print_canon_ace_list( "file ace - before merge", file_ace);
2442         merge_aces( &file_ace, false);
2443
2444         print_canon_ace_list( "dir ace - before merge", dir_ace);
2445         merge_aces( &dir_ace, true);
2446
2447         /*
2448          * NT ACLs are order dependent. Go through the acl lists and
2449          * process DENY entries by masking the allow entries.
2450          */
2451
2452         print_canon_ace_list( "file ace - before deny", file_ace);
2453         process_deny_list(fsp->conn, &file_ace);
2454
2455         print_canon_ace_list( "dir ace - before deny", dir_ace);
2456         process_deny_list(fsp->conn, &dir_ace);
2457
2458         /*
2459          * A well formed POSIX file or default ACL has at least 3 entries, a 
2460          * SMB_ACL_USER_OBJ, SMB_ACL_GROUP_OBJ, SMB_ACL_OTHER_OBJ
2461          * and optionally a mask entry. Ensure this is the case.
2462          */
2463
2464         print_canon_ace_list( "file ace - before valid", file_ace);
2465
2466         ok = ensure_canon_entry_valid_on_set(
2467                 fsp->conn,
2468                 &file_ace,
2469                 false,
2470                 fsp->conn->params,
2471                 fsp->fsp_flags.is_directory,
2472                 pfile_owner_sid,
2473                 pfile_grp_sid,
2474                 pst);
2475         if (!ok) {
2476                 free_canon_ace_list(file_ace);
2477                 free_canon_ace_list(dir_ace);
2478                 return False;
2479         }
2480
2481         print_canon_ace_list( "dir ace - before valid", dir_ace);
2482
2483         if (dir_ace != NULL) {
2484                 ok = ensure_canon_entry_valid_on_set(
2485                         fsp->conn,
2486                         &dir_ace,
2487                         true,
2488                         fsp->conn->params,
2489                         fsp->fsp_flags.is_directory,
2490                         pfile_owner_sid,
2491                         pfile_grp_sid,
2492                         pst);
2493                 if (!ok) {
2494                         free_canon_ace_list(file_ace);
2495                         free_canon_ace_list(dir_ace);
2496                         return False;
2497                 }
2498         }
2499
2500         print_canon_ace_list( "file ace - return", file_ace);
2501         print_canon_ace_list( "dir ace - return", dir_ace);
2502
2503         *ppfile_ace = file_ace;
2504         *ppdir_ace = dir_ace;
2505         return True;
2506
2507 }
2508
2509 /******************************************************************************
2510  When returning permissions, try and fit NT display
2511  semantics if possible. Note the the canon_entries here must have been malloced.
2512  The list format should be - first entry = owner, followed by group and other user
2513  entries, last entry = other.
2514
2515  Note that this doesn't exactly match the NT semantics for an ACL. As POSIX entries
2516  are not ordered, and match on the most specific entry rather than walking a list,
2517  then a simple POSIX permission of rw-r--r-- should really map to 5 entries,
2518
2519  Entry 0: owner : deny all except read and write.
2520  Entry 1: owner : allow read and write.
2521  Entry 2: group : deny all except read.
2522  Entry 3: group : allow read.
2523  Entry 4: Everyone : allow read.
2524
2525  But NT cannot display this in their ACL editor !
2526 ********************************************************************************/
2527
2528 static void arrange_posix_perms(const char *filename, canon_ace **pp_list_head)
2529 {
2530         canon_ace *l_head = *pp_list_head;
2531         canon_ace *owner_ace = NULL;
2532         canon_ace *other_ace = NULL;
2533         canon_ace *ace = NULL;
2534
2535         for (ace = l_head; ace; ace = ace->next) {
2536                 if (ace->type == SMB_ACL_USER_OBJ)
2537                         owner_ace = ace;
2538                 else if (ace->type == SMB_ACL_OTHER) {
2539                         /* Last ace - this is "other" */
2540                         other_ace = ace;
2541                 }
2542         }
2543
2544         if (!owner_ace || !other_ace) {
2545                 DEBUG(0,("arrange_posix_perms: Invalid POSIX permissions for file %s, missing owner or other.\n",
2546                         filename ));
2547                 return;
2548         }
2549
2550         /*
2551          * The POSIX algorithm applies to owner first, and other last,
2552          * so ensure they are arranged in this order.
2553          */
2554
2555         if (owner_ace) {
2556                 DLIST_PROMOTE(l_head, owner_ace);
2557         }
2558
2559         if (other_ace) {
2560                 DLIST_DEMOTE(l_head, other_ace);
2561         }
2562
2563         /* We have probably changed the head of the list. */
2564
2565         *pp_list_head = l_head;
2566 }
2567
2568 /****************************************************************************
2569  Create a linked list of canonical ACE entries.
2570 ****************************************************************************/
2571
2572 static canon_ace *canonicalise_acl(struct connection_struct *conn,
2573                                    const char *fname, SMB_ACL_T posix_acl,
2574                                    const SMB_STRUCT_STAT *psbuf,
2575                                    const struct dom_sid *powner, const struct dom_sid *pgroup, struct pai_val *pal, SMB_ACL_TYPE_T the_acl_type)
2576 {
2577         mode_t acl_mask = (S_IRUSR|S_IWUSR|S_IXUSR);
2578         canon_ace *l_head = NULL;
2579         canon_ace *ace = NULL;
2580         canon_ace *next_ace = NULL;
2581         int entry_id = SMB_ACL_FIRST_ENTRY;
2582         bool is_default_acl = (the_acl_type == SMB_ACL_TYPE_DEFAULT);
2583         SMB_ACL_ENTRY_T entry;
2584         size_t ace_count;
2585
2586         while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
2587                 SMB_ACL_TAG_T tagtype;
2588                 SMB_ACL_PERMSET_T permset;
2589                 struct dom_sid sid;
2590                 struct unixid unix_ug;
2591                 enum ace_owner owner_type;
2592
2593                 entry_id = SMB_ACL_NEXT_ENTRY;
2594
2595                 if (sys_acl_get_tag_type(entry, &tagtype) == -1)
2596                         continue;
2597
2598                 if (sys_acl_get_permset(entry, &permset) == -1)
2599                         continue;
2600
2601                 /* Decide which SID to use based on the ACL type. */
2602                 switch(tagtype) {
2603                         case SMB_ACL_USER_OBJ:
2604                                 /* Get the SID from the owner. */
2605                                 sid_copy(&sid, powner);
2606                                 unix_ug.type = ID_TYPE_UID;
2607                                 unix_ug.id = psbuf->st_ex_uid;
2608                                 owner_type = UID_ACE;
2609                                 break;
2610                         case SMB_ACL_USER:
2611                                 {
2612                                         uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
2613                                         if (puid == NULL) {
2614                                                 DEBUG(0,("canonicalise_acl: Failed to get uid.\n"));
2615                                                 continue;
2616                                         }
2617                                         uid_to_sid( &sid, *puid);
2618                                         unix_ug.type = ID_TYPE_UID;
2619                                         unix_ug.id = *puid;
2620                                         owner_type = UID_ACE;
2621                                         break;
2622                                 }
2623                         case SMB_ACL_GROUP_OBJ:
2624                                 /* Get the SID from the owning group. */
2625                                 sid_copy(&sid, pgroup);
2626                                 unix_ug.type = ID_TYPE_GID;
2627                                 unix_ug.id = psbuf->st_ex_gid;
2628                                 owner_type = GID_ACE;
2629                                 break;
2630                         case SMB_ACL_GROUP:
2631                                 {
2632                                         gid_t *pgid = (gid_t *)sys_acl_get_qualifier(entry);
2633                                         if (pgid == NULL) {
2634                                                 DEBUG(0,("canonicalise_acl: Failed to get gid.\n"));
2635                                                 continue;
2636                                         }
2637                                         gid_to_sid( &sid, *pgid);
2638                                         unix_ug.type = ID_TYPE_GID;
2639                                         unix_ug.id = *pgid;
2640                                         owner_type = GID_ACE;
2641                                         break;
2642                                 }
2643                         case SMB_ACL_MASK:
2644                                 acl_mask = convert_permset_to_mode_t(permset);
2645                                 continue; /* Don't count the mask as an entry. */
2646                         case SMB_ACL_OTHER:
2647                                 /* Use the Everyone SID */
2648                                 sid = global_sid_World;
2649                                 unix_ug.type = ID_TYPE_NOT_SPECIFIED;
2650                                 unix_ug.id = -1;
2651                                 owner_type = WORLD_ACE;
2652                                 break;
2653                         default:
2654                                 DEBUG(0,("canonicalise_acl: Unknown tagtype %u\n", (unsigned int)tagtype));
2655                                 continue;
2656                 }
2657
2658                 /*
2659                  * Add this entry to the list.
2660                  */
2661
2662                 if ((ace = talloc(talloc_tos(), canon_ace)) == NULL)
2663                         goto fail;
2664
2665                 *ace = (canon_ace) {
2666                         .type = tagtype,
2667                         .perms = convert_permset_to_mode_t(permset),
2668                         .attr = ALLOW_ACE,
2669                         .trustee = sid,
2670                         .unix_ug = unix_ug,
2671                         .owner_type = owner_type
2672                 };
2673                 ace->ace_flags = get_pai_flags(pal, ace, is_default_acl);
2674
2675                 DLIST_ADD(l_head, ace);
2676         }
2677
2678         /*
2679          * This next call will ensure we have at least a user/group/world set.
2680          */
2681
2682         if (!ensure_canon_entry_valid_on_get(conn, &l_head,
2683                                       powner, pgroup,
2684                                       psbuf))
2685                 goto fail;
2686
2687         /*
2688          * Now go through the list, masking the permissions with the
2689          * acl_mask. Ensure all DENY Entries are at the start of the list.
2690          */
2691
2692         DEBUG(10,("canonicalise_acl: %s ace entries before arrange :\n", is_default_acl ?  "Default" : "Access"));
2693
2694         for ( ace_count = 0, ace = l_head; ace; ace = next_ace, ace_count++) {
2695                 next_ace = ace->next;
2696
2697                 /* Masks are only applied to entries other than USER_OBJ and OTHER. */
2698                 if (ace->type != SMB_ACL_OTHER && ace->type != SMB_ACL_USER_OBJ)
2699                         ace->perms &= acl_mask;
2700
2701                 if (ace->perms == 0) {
2702                         DLIST_PROMOTE(l_head, ace);
2703                 }
2704
2705                 if( DEBUGLVL( 10 ) ) {
2706                         print_canon_ace(ace, ace_count);
2707                 }
2708         }
2709
2710         arrange_posix_perms(fname,&l_head );
2711
2712         print_canon_ace_list( "canonicalise_acl: ace entries after arrange", l_head );
2713
2714         return l_head;
2715
2716   fail:
2717
2718         free_canon_ace_list(l_head);
2719         return NULL;
2720 }
2721
2722 /****************************************************************************
2723  Check if the current user group list contains a given group.
2724 ****************************************************************************/
2725
2726 bool current_user_in_group(connection_struct *conn, gid_t gid)
2727 {
2728         uint32_t i;
2729         const struct security_unix_token *utok = get_current_utok(conn);
2730
2731         for (i = 0; i < utok->ngroups; i++) {
2732                 if (utok->groups[i] == gid) {
2733                         return True;
2734                 }
2735         }
2736
2737         return False;
2738 }
2739
2740 /****************************************************************************
2741  Should we override a deny ? Check 'acl group control' and 'dos filemode'.
2742 ****************************************************************************/
2743
2744 static bool acl_group_override_fsp(files_struct *fsp)
2745 {
2746         if ((errno != EPERM) && (errno != EACCES)) {
2747                 return false;
2748         }
2749
2750         /* file primary group == user primary or supplementary group */
2751         if (lp_acl_group_control(SNUM(fsp->conn)) &&
2752             current_user_in_group(fsp->conn, fsp->fsp_name->st.st_ex_gid)) {
2753                 return true;
2754         }
2755
2756         /* user has writeable permission */
2757         if (lp_dos_filemode(SNUM(fsp->conn)) && can_write_to_fsp(fsp)) {
2758                 return true;
2759         }
2760
2761         return false;
2762 }
2763
2764 /****************************************************************************
2765  Attempt to apply an ACL to a file or directory.
2766 ****************************************************************************/
2767
2768 static bool set_canon_ace_list(files_struct *fsp,
2769                                 canon_ace *the_ace,
2770                                 bool default_ace,
2771                                 const SMB_STRUCT_STAT *psbuf,
2772                                 bool *pacl_set_support)
2773 {
2774         bool ret = False;
2775         SMB_ACL_T the_acl = sys_acl_init(talloc_tos());
2776         canon_ace *p_ace;
2777         int i;
2778         SMB_ACL_ENTRY_T mask_entry;
2779         bool got_mask_entry = False;
2780         SMB_ACL_PERMSET_T mask_permset;
2781         SMB_ACL_TYPE_T the_acl_type = (default_ace ? SMB_ACL_TYPE_DEFAULT : SMB_ACL_TYPE_ACCESS);
2782         bool needs_mask = False;
2783         int sret;
2784
2785         /* Use the psbuf that was passed in. */
2786         if (psbuf != &fsp->fsp_name->st) {
2787                 fsp->fsp_name->st = *psbuf;
2788         }
2789
2790 #if defined(POSIX_ACL_NEEDS_MASK)
2791         /* HP-UX always wants to have a mask (called "class" there). */
2792         needs_mask = True;
2793 #endif
2794
2795         if (the_acl == NULL) {
2796                 DEBUG(0, ("sys_acl_init failed to allocate an ACL\n"));
2797                 return false;
2798         }
2799
2800         if( DEBUGLVL( 10 )) {
2801                 dbgtext("set_canon_ace_list: setting ACL:\n");
2802                 for (i = 0, p_ace = the_ace; p_ace; p_ace = p_ace->next, i++ ) {
2803                         print_canon_ace( p_ace, i);
2804                 }
2805         }
2806
2807         for (i = 0, p_ace = the_ace; p_ace; p_ace = p_ace->next, i++ ) {
2808                 SMB_ACL_ENTRY_T the_entry;
2809                 SMB_ACL_PERMSET_T the_permset;
2810
2811                 /*
2812                  * ACLs only "need" an ACL_MASK entry if there are any named user or
2813                  * named group entries. But if there is an ACL_MASK entry, it applies
2814                  * to ACL_USER, ACL_GROUP, and ACL_GROUP_OBJ entries. Set the mask
2815                  * so that it doesn't deny (i.e., mask off) any permissions.
2816                  */
2817
2818                 if (p_ace->type == SMB_ACL_USER || p_ace->type == SMB_ACL_GROUP) {
2819                         needs_mask = True;
2820                 }
2821
2822                 /*
2823                  * Get the entry for this ACE.
2824                  */
2825
2826                 if (sys_acl_create_entry(&the_acl, &the_entry) == -1) {
2827                         DEBUG(0,("set_canon_ace_list: Failed to create entry %d. (%s)\n",
2828                                 i, strerror(errno) ));
2829                         goto fail;
2830                 }
2831
2832                 if (p_ace->type == SMB_ACL_MASK) {
2833                         mask_entry = the_entry;
2834                         got_mask_entry = True;
2835                 }
2836
2837                 /*
2838                  * Ok - we now know the ACL calls should be working, don't
2839                  * allow fallback to chmod.
2840                  */
2841
2842                 *pacl_set_support = True;
2843
2844                 /*
2845                  * Initialise the entry from the canon_ace.
2846                  */
2847
2848                 /*
2849                  * First tell the entry what type of ACE this is.
2850                  */
2851
2852                 if (sys_acl_set_tag_type(the_entry, p_ace->type) == -1) {
2853                         DEBUG(0,("set_canon_ace_list: Failed to set tag type on entry %d. (%s)\n",
2854                                 i, strerror(errno) ));
2855                         goto fail;
2856                 }
2857
2858                 /*
2859                  * Only set the qualifier (user or group id) if the entry is a user
2860                  * or group id ACE.
2861                  */
2862
2863                 if ((p_ace->type == SMB_ACL_USER) || (p_ace->type == SMB_ACL_GROUP)) {
2864                         if (sys_acl_set_qualifier(the_entry,(void *)&p_ace->unix_ug.id) == -1) {
2865                                 DEBUG(0,("set_canon_ace_list: Failed to set qualifier on entry %d. (%s)\n",
2866                                         i, strerror(errno) ));
2867                                 goto fail;
2868                         }
2869                 }
2870
2871                 /*
2872                  * Convert the mode_t perms in the canon_ace to a POSIX permset.
2873                  */
2874
2875                 if (sys_acl_get_permset(the_entry, &the_permset) == -1) {
2876                         DEBUG(0,("set_canon_ace_list: Failed to get permset on entry %d. (%s)\n",
2877                                 i, strerror(errno) ));
2878                         goto fail;
2879                 }
2880
2881                 if (map_acl_perms_to_permset(p_ace->perms, &the_permset) == -1) {
2882                         DEBUG(0,("set_canon_ace_list: Failed to create permset for mode (%u) on entry %d. (%s)\n",
2883                                 (unsigned int)p_ace->perms, i, strerror(errno) ));
2884                         goto fail;
2885                 }
2886
2887                 /*
2888                  * ..and apply them to the entry.
2889                  */
2890
2891                 if (sys_acl_set_permset(the_entry, the_permset) == -1) {
2892                         DEBUG(0,("set_canon_ace_list: Failed to add permset on entry %d. (%s)\n",
2893                                 i, strerror(errno) ));
2894                         goto fail;
2895                 }
2896
2897                 if( DEBUGLVL( 10 ))
2898                         print_canon_ace( p_ace, i);
2899
2900         }
2901
2902         if (needs_mask && !got_mask_entry) {
2903                 if (sys_acl_create_entry(&the_acl, &mask_entry) == -1) {
2904                         DEBUG(0,("set_canon_ace_list: Failed to create mask entry. (%s)\n", strerror(errno) ));
2905                         goto fail;
2906                 }
2907
2908                 if (sys_acl_set_tag_type(mask_entry, SMB_ACL_MASK) == -1) {
2909                         DEBUG(0,("set_canon_ace_list: Failed to set tag type on mask entry. (%s)\n",strerror(errno) ));
2910                         goto fail;
2911                 }
2912
2913                 if (sys_acl_get_permset(mask_entry, &mask_permset) == -1) {
2914                         DEBUG(0,("set_canon_ace_list: Failed to get mask permset. (%s)\n", strerror(errno) ));
2915                         goto fail;
2916                 }
2917
2918                 if (map_acl_perms_to_permset(S_IRUSR|S_IWUSR|S_IXUSR, &mask_permset) == -1) {
2919                         DEBUG(0,("set_canon_ace_list: Failed to create mask permset. (%s)\n", strerror(errno) ));
2920                         goto fail;
2921                 }
2922
2923                 if (sys_acl_set_permset(mask_entry, mask_permset) == -1) {
2924                         DEBUG(0,("set_canon_ace_list: Failed to add mask permset. (%s)\n", strerror(errno) ));
2925                         goto fail;
2926                 }
2927         }
2928
2929         /*
2930          * Finally apply it to the file or directory.
2931          */
2932         sret = SMB_VFS_SYS_ACL_SET_FD(fsp, the_acl_type, the_acl);
2933         if (sret == -1) {
2934                 /*
2935                  * Some systems allow all the above calls and only fail with no ACL support
2936                  * when attempting to apply the acl. HPUX with HFS is an example of this. JRA.
2937                  */
2938                 if (no_acl_syscall_error(errno)) {
2939                         *pacl_set_support = false;
2940                 }
2941
2942                 if (acl_group_override_fsp(fsp)) {
2943                         DBG_DEBUG("acl group control on and current user in "
2944                                   "file [%s] primary group.\n",
2945                                   fsp_str_dbg(fsp));
2946
2947                         become_root();
2948                         sret = SMB_VFS_SYS_ACL_SET_FD(fsp,
2949                                                       the_acl_type,
2950                                                       the_acl);
2951                         unbecome_root();
2952                         if (sret == 0) {
2953                                 ret = true;
2954                         }
2955                 }
2956
2957                 if (ret == false) {
2958                         DBG_WARNING("sys_acl_set_file on file [%s]: (%s)\n",
2959                                     fsp_str_dbg(fsp), strerror(errno));
2960                         goto fail;
2961                 }
2962         }
2963
2964         ret = True;
2965
2966   fail:
2967
2968         if (the_acl != NULL) {
2969                 TALLOC_FREE(the_acl);
2970         }
2971
2972         return ret;
2973 }
2974
2975 /****************************************************************************
2976  
2977 ****************************************************************************/
2978
2979 SMB_ACL_T free_empty_sys_acl(connection_struct *conn, SMB_ACL_T the_acl)
2980 {
2981         SMB_ACL_ENTRY_T entry;
2982
2983         if (!the_acl)
2984                 return NULL;
2985         if (sys_acl_get_entry(the_acl, SMB_ACL_FIRST_ENTRY, &entry) != 1) {
2986                 TALLOC_FREE(the_acl);
2987                 return NULL;
2988         }
2989         return the_acl;
2990 }
2991
2992 /****************************************************************************
2993  Convert a canon_ace to a generic 3 element permission - if possible.
2994 ****************************************************************************/
2995
2996 #define MAP_PERM(p,mask,result) (((p) & (mask)) ? (result) : 0 )
2997
2998 static bool convert_canon_ace_to_posix_perms( files_struct *fsp, canon_ace *file_ace_list, mode_t *posix_perms)
2999 {
3000         size_t ace_count = count_canon_ace_list(file_ace_list);
3001         canon_ace *ace_p;
3002         canon_ace *owner_ace = NULL;
3003         canon_ace *group_ace = NULL;
3004         canon_ace *other_ace = NULL;
3005
3006         if (ace_count > 5) {
3007                 DEBUG(3,("convert_canon_ace_to_posix_perms: Too many ACE "
3008                          "entries for file %s to convert to posix perms.\n",
3009                          fsp_str_dbg(fsp)));
3010                 return False;
3011         }
3012
3013         for (ace_p = file_ace_list; ace_p; ace_p = ace_p->next) {
3014                 if (ace_p->owner_type == UID_ACE)
3015                         owner_ace = ace_p;
3016                 else if (ace_p->owner_type == GID_ACE)
3017                         group_ace = ace_p;
3018                 else if (ace_p->owner_type == WORLD_ACE)
3019                         other_ace = ace_p;
3020         }
3021
3022         if (!owner_ace || !group_ace || !other_ace) {
3023                 DEBUG(3,("convert_canon_ace_to_posix_perms: Can't get "
3024                          "standard entries for file %s.\n", fsp_str_dbg(fsp)));
3025                 return False;
3026         }
3027
3028         /*
3029          * Ensure all ACE entries are owner, group or other.
3030          * We can't set if there are any other SIDs.
3031          */
3032         for (ace_p = file_ace_list; ace_p; ace_p = ace_p->next) {
3033                 if (ace_p == owner_ace || ace_p == group_ace ||
3034                                 ace_p == other_ace) {
3035                         continue;
3036                 }
3037                 if (ace_p->owner_type == UID_ACE) {
3038                         if (ace_p->unix_ug.id != owner_ace->unix_ug.id) {
3039                                 DEBUG(3,("Invalid uid %u in ACE for file %s.\n",
3040                                         (unsigned int)ace_p->unix_ug.id,
3041                                         fsp_str_dbg(fsp)));
3042                                 return false;
3043                         }
3044                 } else if (ace_p->owner_type == GID_ACE) {
3045                         if (ace_p->unix_ug.id != group_ace->unix_ug.id) {
3046                                 DEBUG(3,("Invalid gid %u in ACE for file %s.\n",
3047                                         (unsigned int)ace_p->unix_ug.id,
3048                                         fsp_str_dbg(fsp)));
3049                                 return false;
3050                         }
3051                 } else {
3052                         /*
3053                          * There should be no duplicate WORLD_ACE entries.
3054                          */
3055
3056                         DEBUG(3,("Invalid type %u, uid %u in "
3057                                 "ACE for file %s.\n",
3058                                 (unsigned int)ace_p->owner_type,
3059                                 (unsigned int)ace_p->unix_ug.id,
3060                                 fsp_str_dbg(fsp)));
3061                         return false;
3062                 }
3063         }
3064
3065         *posix_perms = (mode_t)0;
3066
3067         *posix_perms |= owner_ace->perms;
3068         *posix_perms |= MAP_PERM(group_ace->perms, S_IRUSR, S_IRGRP);
3069         *posix_perms |= MAP_PERM(group_ace->perms, S_IWUSR, S_IWGRP);
3070         *posix_perms |= MAP_PERM(group_ace->perms, S_IXUSR, S_IXGRP);
3071         *posix_perms |= MAP_PERM(other_ace->perms, S_IRUSR, S_IROTH);
3072         *posix_perms |= MAP_PERM(other_ace->perms, S_IWUSR, S_IWOTH);
3073         *posix_perms |= MAP_PERM(other_ace->perms, S_IXUSR, S_IXOTH);
3074
3075         /* The owner must have at least read access. */
3076
3077         *posix_perms |= S_IRUSR;
3078         if (fsp->fsp_flags.is_directory)
3079                 *posix_perms |= (S_IWUSR|S_IXUSR);
3080
3081         DEBUG(10,("convert_canon_ace_to_posix_perms: converted u=%o,g=%o,w=%o "
3082                   "to perm=0%o for file %s.\n", (int)owner_ace->perms,
3083                   (int)group_ace->perms, (int)other_ace->perms,
3084                   (int)*posix_perms, fsp_str_dbg(fsp)));
3085
3086         return True;
3087 }
3088
3089 /****************************************************************************
3090   Incoming NT ACLs on a directory can be split into a default POSIX acl (CI|OI|IO) and
3091   a normal POSIX acl. Win2k needs these split acls re-merging into one ACL
3092   with CI|OI set so it is inherited and also applies to the directory.
3093   Based on code from "Jim McDonough" <jmcd@us.ibm.com>.
3094 ****************************************************************************/
3095
3096 static size_t merge_default_aces( struct security_ace *nt_ace_list, size_t num_aces)
3097 {
3098         size_t i, j;
3099
3100         for (i = 0; i < num_aces; i++) {
3101                 for (j = i+1; j < num_aces; j++) {
3102                         uint32_t i_flags_ni = (nt_ace_list[i].flags & ~SEC_ACE_FLAG_INHERITED_ACE);
3103                         uint32_t j_flags_ni = (nt_ace_list[j].flags & ~SEC_ACE_FLAG_INHERITED_ACE);
3104                         bool i_inh = (nt_ace_list[i].flags & SEC_ACE_FLAG_INHERITED_ACE) ? True : False;
3105                         bool j_inh = (nt_ace_list[j].flags & SEC_ACE_FLAG_INHERITED_ACE) ? True : False;
3106
3107                         /* We know the lower number ACE's are file entries. */
3108                         if ((nt_ace_list[i].type == nt_ace_list[j].type) &&
3109                                 (nt_ace_list[i].size == nt_ace_list[j].size) &&
3110                                 (nt_ace_list[i].access_mask == nt_ace_list[j].access_mask) &&
3111                                 dom_sid_equal(&nt_ace_list[i].trustee, &nt_ace_list[j].trustee) &&
3112                                 (i_inh == j_inh) &&
3113                                 (i_flags_ni == 0) &&
3114                                 (j_flags_ni == (SEC_ACE_FLAG_OBJECT_INHERIT|
3115                                                   SEC_ACE_FLAG_CONTAINER_INHERIT|
3116                                                   SEC_ACE_FLAG_INHERIT_ONLY))) {
3117                                 /*
3118                                  * W2K wants to have access allowed zero access ACE's
3119                                  * at the end of the list. If the mask is zero, merge
3120                                  * the non-inherited ACE onto the inherited ACE.
3121                                  */
3122
3123                                 if (nt_ace_list[i].access_mask == 0) {
3124                                         nt_ace_list[j].flags = SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT|
3125                                                                 (i_inh ? SEC_ACE_FLAG_INHERITED_ACE : 0);
3126                                         ARRAY_DEL_ELEMENT(nt_ace_list, i, num_aces);
3127
3128                                         DEBUG(10,("merge_default_aces: Merging zero access ACE %u onto ACE %u.\n",
3129                                                 (unsigned int)i, (unsigned int)j ));
3130
3131                                         /*
3132                                          * If we remove the i'th element, we
3133                                          * should decrement i so that we don't
3134                                          * skip over the succeeding element.
3135                                         */
3136                                         i--;
3137                                         num_aces--;
3138                                         break;
3139                                 } else {
3140                                         /*
3141                                          * These are identical except for the flags.
3142                                          * Merge the inherited ACE onto the non-inherited ACE.
3143                                          */
3144
3145                                         nt_ace_list[i].flags = SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT|
3146                                                                 (i_inh ? SEC_ACE_FLAG_INHERITED_ACE : 0);
3147                                         ARRAY_DEL_ELEMENT(nt_ace_list, j, num_aces);
3148
3149                                         DEBUG(10,("merge_default_aces: Merging ACE %u onto ACE %u.\n",
3150                                                 (unsigned int)j, (unsigned int)i ));
3151
3152                                         /*
3153                                          * If we remove the j'th element, we
3154                                          * should decrement j and continue
3155                                          * around the loop, so as not to skip
3156                                          * subsequent elements.
3157                                          */
3158                                         j--;
3159                                         num_aces--;
3160                                 }
3161                         }
3162                 }
3163         }
3164
3165         return num_aces;
3166 }
3167
3168
3169 /****************************************************************************
3170  Reply to query a security descriptor from an fsp. If it succeeds it allocates
3171  the space for the return elements and returns the size needed to return the
3172  security descriptor. This should be the only external function needed for
3173  the UNIX style get ACL.
3174 ****************************************************************************/
3175
3176 static NTSTATUS posix_get_nt_acl_common(struct connection_struct *conn,
3177                                       const char *name,
3178                                       const SMB_STRUCT_STAT *sbuf,
3179                                       struct pai_val *pal,
3180                                       SMB_ACL_T posix_acl,
3181                                       SMB_ACL_T def_acl,
3182                                       uint32_t security_info,
3183                                       TALLOC_CTX *mem_ctx,
3184                                       struct security_descriptor **ppdesc)
3185 {
3186         struct dom_sid owner_sid;
3187         struct dom_sid group_sid;
3188         size_t sd_size = 0;
3189         struct security_acl *psa = NULL;
3190         size_t num_acls = 0;
3191         size_t num_def_acls = 0;
3192         size_t num_aces = 0;
3193         canon_ace *file_ace = NULL;
3194         canon_ace *dir_ace = NULL;
3195         struct security_ace *nt_ace_list = NULL;
3196         struct security_descriptor *psd = NULL;
3197
3198         /*
3199          * Get the owner, group and world SIDs.
3200          */
3201
3202         create_file_sids(sbuf, &owner_sid, &group_sid);
3203
3204         if (security_info & SECINFO_DACL) {
3205
3206                 /*
3207                  * In the optimum case Creator Owner and Creator Group would be used for
3208                  * the ACL_USER_OBJ and ACL_GROUP_OBJ entries, respectively, but this
3209                  * would lead to usability problems under Windows: The Creator entries
3210                  * are only available in browse lists of directories and not for files;
3211                  * additionally the identity of the owning group couldn't be determined.
3212                  * We therefore use those identities only for Default ACLs.
3213                  */
3214
3215                 /* Create the canon_ace lists. */
3216                 file_ace = canonicalise_acl(conn, name, posix_acl, sbuf,
3217                                             &owner_sid, &group_sid, pal,
3218                                             SMB_ACL_TYPE_ACCESS);
3219
3220                 /* We must have *some* ACLS. */
3221
3222                 if (count_canon_ace_list(file_ace) == 0) {
3223                         DEBUG(0,("get_nt_acl : No ACLs on file (%s) !\n", name));
3224                         goto done;
3225                 }
3226
3227                 if (S_ISDIR(sbuf->st_ex_mode) && def_acl) {
3228                         dir_ace = canonicalise_acl(conn, name, def_acl,
3229                                                    sbuf,
3230                                                    &global_sid_Creator_Owner,
3231                                                    &global_sid_Creator_Group,
3232                                                    pal, SMB_ACL_TYPE_DEFAULT);
3233                 }
3234
3235                 /*
3236                  * Create the NT ACE list from the canonical ace lists.
3237                  */
3238
3239                 {
3240                         canon_ace *ace;
3241                         enum security_ace_type nt_acl_type;
3242
3243                         num_acls = count_canon_ace_list(file_ace);
3244                         num_def_acls = count_canon_ace_list(dir_ace);
3245
3246                         nt_ace_list = talloc_zero_array(
3247                                 talloc_tos(), struct security_ace,
3248                                 num_acls + num_def_acls);
3249
3250                         if (nt_ace_list == NULL) {
3251                                 DEBUG(0,("get_nt_acl: Unable to malloc space for nt_ace_list.\n"));
3252                                 goto done;
3253                         }
3254
3255                         /*
3256                          * Create the NT ACE list from the canonical ace lists.
3257                          */
3258
3259                         for (ace = file_ace; ace != NULL; ace = ace->next) {
3260                                 uint32_t acc = map_canon_ace_perms(SNUM(conn),
3261                                                 &nt_acl_type,
3262                                                 ace->perms,
3263                                                 S_ISDIR(sbuf->st_ex_mode));
3264                                 init_sec_ace(&nt_ace_list[num_aces++],
3265                                         &ace->trustee,
3266                                         nt_acl_type,
3267                                         acc,
3268                                         ace->ace_flags);
3269                         }
3270
3271                         for (ace = dir_ace; ace != NULL; ace = ace->next) {
3272                                 uint32_t acc = map_canon_ace_perms(SNUM(conn),
3273                                                 &nt_acl_type,
3274                                                 ace->perms,
3275                                                 S_ISDIR(sbuf->st_ex_mode));
3276                                 init_sec_ace(&nt_ace_list[num_aces++],
3277                                         &ace->trustee,
3278                                         nt_acl_type,
3279                                         acc,
3280                                         ace->ace_flags |
3281                                         SEC_ACE_FLAG_OBJECT_INHERIT|
3282                                         SEC_ACE_FLAG_CONTAINER_INHERIT|
3283                                         SEC_ACE_FLAG_INHERIT_ONLY);
3284                         }
3285
3286                         /*
3287                          * Merge POSIX default ACLs and normal ACLs into one NT ACE.
3288                          * Win2K needs this to get the inheritance correct when replacing ACLs
3289                          * on a directory tree. Based on work by Jim @ IBM.
3290                          */
3291
3292                         num_aces = merge_default_aces(nt_ace_list, num_aces);
3293                 }
3294
3295                 if (num_aces) {
3296                         if((psa = make_sec_acl( talloc_tos(), NT4_ACL_REVISION, num_aces, nt_ace_list)) == NULL) {
3297                                 DEBUG(0,("get_nt_acl: Unable to malloc space for acl.\n"));
3298                                 goto done;
3299                         }
3300                 }
3301         } /* security_info & SECINFO_DACL */
3302
3303         psd = make_standard_sec_desc(mem_ctx,
3304                         (security_info & SECINFO_OWNER) ? &owner_sid : NULL,
3305                         (security_info & SECINFO_GROUP) ? &group_sid : NULL,
3306                         psa,
3307                         &sd_size);
3308
3309         if(!psd) {
3310                 DEBUG(0,("get_nt_acl: Unable to malloc space for security descriptor.\n"));
3311                 sd_size = 0;
3312                 goto done;
3313         }
3314
3315         /*
3316          * Windows 2000: The DACL_PROTECTED flag in the security
3317          * descriptor marks the ACL as non-inheriting, i.e., no
3318          * ACEs from higher level directories propagate to this
3319          * ACL. In the POSIX ACL model permissions are only
3320          * inherited at file create time, so ACLs never contain
3321          * any ACEs that are inherited dynamically. The DACL_PROTECTED
3322          * flag doesn't seem to bother Windows NT.
3323          * Always set this if map acl inherit is turned off.
3324          */
3325         if (pal == NULL || !lp_map_acl_inherit(SNUM(conn))) {
3326                 psd->type |= SEC_DESC_DACL_PROTECTED;
3327         } else {
3328                 psd->type |= pal->sd_type;
3329         }
3330
3331         if (psd->dacl) {
3332                 dacl_sort_into_canonical_order(psd->dacl->aces, (unsigned int)psd->dacl->num_aces);
3333         }
3334
3335         *ppdesc = psd;
3336
3337  done:
3338
3339         if (posix_acl) {
3340                 TALLOC_FREE(posix_acl);
3341         }
3342         if (def_acl) {
3343                 TALLOC_FREE(def_acl);
3344         }
3345         free_canon_ace_list(file_ace);
3346         free_canon_ace_list(dir_ace);
3347         free_inherited_info(pal);
3348         TALLOC_FREE(nt_ace_list);
3349
3350         return NT_STATUS_OK;
3351 }
3352
3353 NTSTATUS posix_fget_nt_acl(struct files_struct *fsp, uint32_t security_info,
3354                            TALLOC_CTX *mem_ctx,
3355                            struct security_descriptor **ppdesc)
3356 {
3357         SMB_STRUCT_STAT sbuf;
3358         SMB_ACL_T posix_acl = NULL;
3359         SMB_ACL_T def_acl = NULL;
3360         struct pai_val *pal;
3361         TALLOC_CTX *frame = talloc_stackframe();
3362         NTSTATUS status;
3363
3364         *ppdesc = NULL;
3365
3366         DEBUG(10,("posix_fget_nt_acl: called for file %s\n",
3367                   fsp_str_dbg(fsp)));
3368
3369         /* Get the stat struct for the owner info. */
3370         if(SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
3371                 TALLOC_FREE(frame);
3372                 return map_nt_error_from_unix(errno);
3373         }
3374
3375         /* Get the ACL from the fd. */
3376         posix_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
3377                                            SMB_ACL_TYPE_ACCESS,
3378                                            frame);
3379
3380         /* If it's a directory get the default POSIX ACL. */
3381         if(fsp->fsp_flags.is_directory) {
3382                 def_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
3383                                                  SMB_ACL_TYPE_DEFAULT,
3384                                                  frame);
3385                 def_acl = free_empty_sys_acl(fsp->conn, def_acl);
3386         }
3387
3388         pal = fload_inherited_info(fsp);
3389
3390         status = posix_get_nt_acl_common(fsp->conn, fsp->fsp_name->base_name,
3391                                          &sbuf, pal, posix_acl, def_acl,
3392                                          security_info, mem_ctx, ppdesc);
3393         TALLOC_FREE(frame);
3394         return status;
3395 }
3396
3397 /****************************************************************************
3398  Try to chown a file. We will be able to chown it under the following conditions.
3399
3400   1) If we have root privileges, then it will just work.
3401   2) If we have SeRestorePrivilege we can change the user + group to any other user. 
3402   3) If we have SeTakeOwnershipPrivilege we can change the user to the current user.
3403   4) If we have write permission to the file and dos_filemodes is set
3404      then allow chown to the currently authenticated user.
3405 ****************************************************************************/
3406
3407 static NTSTATUS try_chown(files_struct *fsp, uid_t uid, gid_t gid)
3408 {
3409         NTSTATUS status;
3410         int ret;
3411
3412         if(!CAN_WRITE(fsp->conn)) {
3413                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
3414         }
3415
3416         /* Case (1). */
3417         ret = SMB_VFS_FCHOWN(fsp, uid, gid);
3418         if (ret == 0) {
3419                 return NT_STATUS_OK;
3420         }
3421
3422         /* Case (2) / (3) */
3423         if (lp_enable_privileges()) {
3424                 bool has_take_ownership_priv = security_token_has_privilege(
3425                                                 get_current_nttok(fsp->conn),
3426                                                 SEC_PRIV_TAKE_OWNERSHIP);
3427                 bool has_restore_priv = security_token_has_privilege(
3428                                                 get_current_nttok(fsp->conn),
3429                                                 SEC_PRIV_RESTORE);
3430
3431                 if (has_restore_priv) {
3432                         ; /* Case (2) */
3433                 } else if (has_take_ownership_priv) {
3434                         /* Case (3) */
3435                         if (uid == get_current_uid(fsp->conn)) {
3436                                 gid = (gid_t)-1;
3437                         } else {
3438                                 has_take_ownership_priv = false;
3439                         }
3440                 }
3441
3442                 if (has_take_ownership_priv || has_restore_priv) {
3443                         status = NT_STATUS_OK;
3444                         become_root();
3445                         ret = SMB_VFS_FCHOWN(fsp, uid, gid);
3446                         if (ret != 0) {
3447                                 status = map_nt_error_from_unix(errno);
3448                         }
3449                         unbecome_root();
3450                         return status;
3451                 }
3452         }
3453
3454         /* Case (4). */
3455         /* If "dos filemode" isn't set, we're done. */
3456         if (!lp_dos_filemode(SNUM(fsp->conn))) {
3457                 return NT_STATUS_ACCESS_DENIED;
3458         }
3459         /*
3460          * If we have a writable handle, obviously we
3461          * can write to the file.
3462          */
3463         if (!fsp->fsp_flags.can_write) {
3464                 /*
3465                  * If we don't have a writable handle, we
3466                  * need to read the ACL on the file to
3467                  * see if we can write to it.
3468                  */
3469                 if (!can_write_to_fsp(fsp)) {
3470                         return NT_STATUS_ACCESS_DENIED;
3471                 }
3472         }
3473
3474         /* only allow chown to the current user. This is more secure,
3475            and also copes with the case where the SID in a take ownership ACL is
3476            a local SID on the users workstation
3477         */
3478         if (uid != get_current_uid(fsp->conn)) {
3479                 return NT_STATUS_INVALID_OWNER;
3480         }
3481
3482         status = NT_STATUS_OK;
3483         become_root();
3484         /* Keep the current file gid the same. */
3485         ret = SMB_VFS_FCHOWN(fsp, uid, (gid_t)-1);
3486         if (ret != 0) {
3487                 status = map_nt_error_from_unix(errno);
3488         }
3489         unbecome_root();
3490
3491         return status;
3492 }
3493
3494 /*
3495  * Check whether a chown is needed and if so, attempt the chown
3496  * A returned error indicates that the chown failed.
3497  * NT_STATUS_OK with did_chown == false indicates that the chown was skipped.
3498  * NT_STATUS_OK with did_chown == true indicates that the chown succeeded
3499  */
3500 NTSTATUS chown_if_needed(files_struct *fsp, uint32_t security_info_sent,
3501                          const struct security_descriptor *psd,
3502                          bool *did_chown)
3503 {
3504         NTSTATUS status;
3505         uid_t uid = (uid_t)-1;
3506         gid_t gid = (gid_t)-1;
3507
3508         status = unpack_nt_owners(fsp->conn, &uid, &gid, security_info_sent, psd);
3509         if (!NT_STATUS_IS_OK(status)) {
3510                 return status;
3511         }
3512
3513         if (((uid == (uid_t)-1) || (fsp->fsp_name->st.st_ex_uid == uid)) &&
3514             ((gid == (gid_t)-1) || (fsp->fsp_name->st.st_ex_gid == gid))) {
3515                 /*
3516                  * Skip chown
3517                  */
3518                 *did_chown = false;
3519                 return NT_STATUS_OK;
3520         }
3521
3522         DBG_NOTICE("chown %s. uid = %u, gid = %u.\n",
3523                    fsp_str_dbg(fsp), (unsigned int) uid, (unsigned int)gid);
3524
3525         status = try_chown(fsp, uid, gid);
3526         if (!NT_STATUS_IS_OK(status)) {
3527                 DBG_INFO("chown %s, %u, %u failed. Error = %s.\n",
3528                          fsp_str_dbg(fsp), (unsigned int) uid,
3529                          (unsigned int)gid, nt_errstr(status));
3530                 return status;
3531         }
3532
3533         /*
3534          * Recheck the current state of the file, which may have changed.
3535          * (owner and suid/sgid bits, for instance)
3536          */
3537
3538         status = vfs_stat_fsp(fsp);
3539         if (!NT_STATUS_IS_OK(status)) {
3540                 return status;
3541         }
3542
3543         *did_chown = true;
3544         return NT_STATUS_OK;
3545 }
3546
3547 /****************************************************************************
3548  Reply to set a security descriptor on an fsp. security_info_sent is the
3549  description of the following NT ACL.
3550  This should be the only external function needed for the UNIX style set ACL.
3551  We make a copy of psd_orig as internal functions modify the elements inside
3552  it, even though it's a const pointer.
3553 ****************************************************************************/
3554
3555 NTSTATUS set_nt_acl(files_struct *fsp, uint32_t security_info_sent, const struct security_descriptor *psd_orig)
3556 {
3557         connection_struct *conn = fsp->conn;
3558         struct dom_sid file_owner_sid;
3559         struct dom_sid file_grp_sid;
3560         canon_ace *file_ace_list = NULL;
3561         canon_ace *dir_ace_list = NULL;
3562         bool acl_perms = False;
3563         mode_t orig_mode = (mode_t)0;
3564         NTSTATUS status;
3565         bool set_acl_as_root = false;
3566         bool acl_set_support = false;
3567         bool ret = false;
3568         struct security_descriptor *psd = NULL;
3569
3570         DEBUG(10,("set_nt_acl: called for file %s\n",
3571                   fsp_str_dbg(fsp)));
3572
3573         if (!CAN_WRITE(conn)) {
3574                 DEBUG(10,("set acl rejected on read-only share\n"));
3575                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
3576         }
3577
3578         if (psd_orig == NULL) {
3579                 return NT_STATUS_INVALID_PARAMETER;
3580         }
3581
3582         /*
3583          * MS NFS mode, here's the deal: the client merely wants to
3584          * modify the mode, but roundtripping get_acl/set/acl would
3585          * add additional POSIX ACEs.  So in case we get a request
3586          * containing a MS NFS mode SID, we do nothing here.
3587          */
3588         if (security_descriptor_with_ms_nfs(psd_orig)) {
3589                 return NT_STATUS_OK;
3590         }
3591
3592         psd = security_descriptor_copy(talloc_tos(), psd_orig);
3593         if (psd == NULL) {
3594                 return NT_STATUS_NO_MEMORY;
3595         }
3596
3597         /*
3598          * Get the current state of the file.
3599          */
3600
3601         status = vfs_stat_fsp(fsp);
3602         if (!NT_STATUS_IS_OK(status)) {
3603                 return status;
3604         }
3605
3606         /* Save the original element we check against. */
3607         orig_mode = fsp->fsp_name->st.st_ex_mode;
3608
3609         /*
3610          * Unpack the user/group/world id's.
3611          */
3612
3613         /* POSIX can't cope with missing owner/group. */
3614         if ((security_info_sent & SECINFO_OWNER) && (psd->owner_sid == NULL)) {
3615                 security_info_sent &= ~SECINFO_OWNER;
3616         }
3617         if ((security_info_sent & SECINFO_GROUP) && (psd->group_sid == NULL)) {
3618                 security_info_sent &= ~SECINFO_GROUP;
3619         }
3620
3621         /* If UNIX owner is inherited and Windows isn't, then
3622          * setting the UNIX owner based on Windows owner conflicts
3623          * with the inheritance rule
3624          */
3625         if (lp_inherit_owner(SNUM(conn)) == INHERIT_OWNER_UNIX_ONLY) {
3626                 security_info_sent &= ~SECINFO_OWNER;
3627         }
3628
3629         /*
3630          * Do we need to chown ? If so this must be done first as the incoming
3631          * CREATOR_OWNER acl will be relative to the *new* owner, not the old.
3632          * Noticed by Simo.
3633          *
3634          * If we successfully chowned, we know we must be able to set
3635          * the acl, so do it as root (set_acl_as_root).
3636          */
3637         status = chown_if_needed(fsp, security_info_sent, psd, &set_acl_as_root);
3638         if (!NT_STATUS_IS_OK(status)) {
3639                 return status;
3640         }
3641
3642         create_file_sids(&fsp->fsp_name->st, &file_owner_sid, &file_grp_sid);
3643
3644         if((security_info_sent & SECINFO_DACL) &&
3645                         (psd->type & SEC_DESC_DACL_PRESENT) &&
3646                         (psd->dacl == NULL)) {
3647                 struct security_ace ace[3];
3648
3649                 /* We can't have NULL DACL in POSIX.
3650                    Use owner/group/Everyone -> full access. */
3651
3652                 init_sec_ace(&ace[0],
3653                                 &file_owner_sid,
3654                                 SEC_ACE_TYPE_ACCESS_ALLOWED,
3655                                 GENERIC_ALL_ACCESS,
3656                                 0);
3657                 init_sec_ace(&ace[1],
3658                                 &file_grp_sid,
3659                                 SEC_ACE_TYPE_ACCESS_ALLOWED,
3660                                 GENERIC_ALL_ACCESS,
3661                                 0);
3662                 init_sec_ace(&ace[2],
3663                                 &global_sid_World,
3664                                 SEC_ACE_TYPE_ACCESS_ALLOWED,
3665                                 GENERIC_ALL_ACCESS,
3666                                 0);
3667                 psd->dacl = make_sec_acl(talloc_tos(),
3668                                         NT4_ACL_REVISION,
3669                                         3,
3670                                         ace);
3671                 if (psd->dacl == NULL) {
3672                         return NT_STATUS_NO_MEMORY;
3673                 }
3674                 security_acl_map_generic(psd->dacl, &file_generic_mapping);
3675         }
3676
3677         acl_perms = unpack_canon_ace(fsp, &fsp->fsp_name->st, &file_owner_sid,
3678                                      &file_grp_sid, &file_ace_list,
3679                                      &dir_ace_list, security_info_sent, psd);
3680
3681         /* Ignore W2K traverse DACL set. */
3682         if (!file_ace_list && !dir_ace_list) {
3683                 return NT_STATUS_OK;
3684         }
3685
3686         if (!acl_perms) {
3687                 DEBUG(3,("set_nt_acl: cannot set permissions\n"));
3688                 free_canon_ace_list(file_ace_list);
3689                 free_canon_ace_list(dir_ace_list);
3690                 return NT_STATUS_ACCESS_DENIED;
3691         }
3692
3693         /*
3694          * Only change security if we got a DACL.
3695          */
3696
3697         if(!(security_info_sent & SECINFO_DACL) || (psd->dacl == NULL)) {
3698                 free_canon_ace_list(file_ace_list);
3699                 free_canon_ace_list(dir_ace_list);
3700                 return NT_STATUS_OK;
3701         }
3702
3703         /*
3704          * Try using the POSIX ACL set first. Fall back to chmod if
3705          * we have no ACL support on this filesystem.
3706          */
3707
3708         if (acl_perms && file_ace_list) {
3709                 if (set_acl_as_root) {
3710                         become_root();
3711                 }
3712                 ret = set_canon_ace_list(fsp, file_ace_list, false,
3713                                          &fsp->fsp_name->st, &acl_set_support);
3714                 if (set_acl_as_root) {
3715                         unbecome_root();
3716                 }
3717                 if (acl_set_support && ret == false) {
3718                         DEBUG(3,("set_nt_acl: failed to set file acl on file "
3719                                  "%s (%s).\n", fsp_str_dbg(fsp),
3720                                  strerror(errno)));
3721                         free_canon_ace_list(file_ace_list);
3722                         free_canon_ace_list(dir_ace_list);
3723                         return map_nt_error_from_unix(errno);
3724                 }
3725         }
3726
3727         if (acl_perms && acl_set_support && fsp->fsp_flags.is_directory) {
3728                 if (dir_ace_list) {
3729                         if (set_acl_as_root) {
3730                                 become_root();
3731                         }
3732                         ret = set_canon_ace_list(fsp, dir_ace_list, true,
3733                                                  &fsp->fsp_name->st,
3734                                                  &acl_set_support);
3735                         if (set_acl_as_root) {
3736                                 unbecome_root();
3737                         }
3738                         if (ret == false) {
3739                                 DEBUG(3,("set_nt_acl: failed to set default "
3740                                          "acl on directory %s (%s).\n",
3741                                          fsp_str_dbg(fsp), strerror(errno)));
3742                                 free_canon_ace_list(file_ace_list);
3743                                 free_canon_ace_list(dir_ace_list);
3744                                 return map_nt_error_from_unix(errno);
3745                         }
3746                 } else {
3747                         int sret = -1;
3748
3749                         /*
3750                          * No default ACL - delete one if it exists.
3751                          */
3752
3753                         if (set_acl_as_root) {
3754                                 become_root();
3755                         }
3756                         sret = SMB_VFS_SYS_ACL_DELETE_DEF_FD(fsp);
3757                         if (set_acl_as_root) {
3758                                 unbecome_root();
3759                         }
3760                         if (sret == -1) {
3761                                 if (acl_group_override_fsp(fsp)) {
3762                                         DEBUG(5,("set_nt_acl: acl group "
3763                                                  "control on and current user "
3764                                                  "in file %s primary group. "
3765                                                  "Override delete_def_acl\n",
3766                                                  fsp_str_dbg(fsp)));
3767
3768                                         become_root();
3769                                         sret =
3770                                             SMB_VFS_SYS_ACL_DELETE_DEF_FD(fsp);
3771                                         unbecome_root();
3772                                 }
3773
3774                                 if (sret == -1) {
3775                                         DBG_NOTICE("sys_acl_delete_def_fd for "
3776                                                 "directory %s failed (%s)\n",
3777                                                 fsp_str_dbg(fsp),
3778                                                 strerror(errno));
3779                                         free_canon_ace_list(file_ace_list);
3780                                         free_canon_ace_list(dir_ace_list);
3781                                         return map_nt_error_from_unix(errno);
3782                                 }
3783                         }
3784                 }
3785         }
3786
3787         if (acl_set_support) {
3788                 if (set_acl_as_root) {
3789                         become_root();
3790                 }
3791                 store_inheritance_attributes(fsp,
3792                                 file_ace_list,
3793                                 dir_ace_list,
3794                                 psd->type);
3795                 if (set_acl_as_root) {
3796                         unbecome_root();
3797                 }
3798         }
3799
3800         /*
3801          * If we cannot set using POSIX ACLs we fall back to checking if we need to chmod.
3802          */
3803
3804         if(!acl_set_support && acl_perms) {
3805                 mode_t posix_perms;
3806
3807                 if (!convert_canon_ace_to_posix_perms( fsp, file_ace_list, &posix_perms)) {
3808                         free_canon_ace_list(file_ace_list);
3809                         free_canon_ace_list(dir_ace_list);
3810                         DEBUG(3,("set_nt_acl: failed to convert file acl to "
3811                                  "posix permissions for file %s.\n",
3812                                  fsp_str_dbg(fsp)));
3813                         return NT_STATUS_ACCESS_DENIED;
3814                 }
3815
3816                 if (orig_mode != posix_perms) {
3817                         int sret = -1;
3818
3819                         DEBUG(3,("set_nt_acl: chmod %s. perms = 0%o.\n",
3820                                  fsp_str_dbg(fsp), (unsigned int)posix_perms));
3821
3822                         if (set_acl_as_root) {
3823                                 become_root();
3824                         }
3825                         sret = SMB_VFS_FCHMOD(fsp, posix_perms);
3826                         if (set_acl_as_root) {
3827                                 unbecome_root();
3828                         }
3829                         if(sret == -1) {
3830                                 if (acl_group_override_fsp(fsp)) {
3831                                         DEBUG(5,("set_nt_acl: acl group "
3832                                                  "control on and current user "
3833                                                  "in file %s primary group. "
3834                                                  "Override chmod\n",
3835                                                  fsp_str_dbg(fsp)));
3836
3837                                         become_root();
3838                                         sret = SMB_VFS_FCHMOD(fsp, posix_perms);
3839                                         unbecome_root();
3840                                 }
3841
3842                                 if (sret == -1) {
3843                                         DEBUG(3,("set_nt_acl: chmod %s, 0%o "
3844                                                  "failed. Error = %s.\n",
3845                                                  fsp_str_dbg(fsp),
3846                                                  (unsigned int)posix_perms,
3847                                                  strerror(errno)));
3848                                         free_canon_ace_list(file_ace_list);
3849                                         free_canon_ace_list(dir_ace_list);
3850                                         return map_nt_error_from_unix(errno);
3851                                 }
3852                         }
3853                 }
3854         }
3855
3856         free_canon_ace_list(file_ace_list);
3857         free_canon_ace_list(dir_ace_list);
3858
3859         /* Ensure the stat struct in the fsp is correct. */
3860         status = vfs_stat_fsp(fsp);
3861
3862         return NT_STATUS_OK;
3863 }
3864
3865 /****************************************************************************
3866  Get the actual group bits stored on a file with an ACL. Has no effect if
3867  the file has no ACL. Needed in dosmode code where the stat() will return
3868  the mask bits, not the real group bits, for a file with an ACL.
3869 ****************************************************************************/
3870
3871 int get_acl_group_bits(connection_struct *conn,
3872                        struct files_struct *fsp,
3873                        mode_t *mode )
3874 {
3875         int entry_id = SMB_ACL_FIRST_ENTRY;
3876         SMB_ACL_ENTRY_T entry;
3877         SMB_ACL_T posix_acl;
3878         int result = -1;
3879
3880         posix_acl = SMB_VFS_SYS_ACL_GET_FD(metadata_fsp(fsp),
3881                                            SMB_ACL_TYPE_ACCESS,
3882                                            talloc_tos());
3883         if (posix_acl == (SMB_ACL_T)NULL)
3884                 return -1;
3885
3886         while (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1) {
3887                 SMB_ACL_TAG_T tagtype;
3888                 SMB_ACL_PERMSET_T permset;
3889
3890                 entry_id = SMB_ACL_NEXT_ENTRY;
3891
3892                 if (sys_acl_get_tag_type(entry, &tagtype) ==-1)
3893                         break;
3894
3895                 if (tagtype == SMB_ACL_GROUP_OBJ) {
3896                         if (sys_acl_get_permset(entry, &permset) == -1) {
3897                                 break;
3898                         } else {
3899                                 *mode &= ~(S_IRGRP|S_IWGRP|S_IXGRP);
3900                                 *mode |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? S_IRGRP : 0);
3901                                 *mode |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? S_IWGRP : 0);
3902                                 *mode |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? S_IXGRP : 0);
3903                                 result = 0;
3904                                 break;
3905                         }
3906                 }
3907         }
3908         TALLOC_FREE(posix_acl);
3909         return result;
3910 }
3911
3912 /****************************************************************************
3913  Do a chmod by setting the ACL USER_OBJ, GROUP_OBJ and OTHER bits in an ACL
3914  and set the mask to rwx. Needed to preserve complex ACLs set by NT.
3915 ****************************************************************************/
3916
3917 static int chmod_acl_internals(SMB_ACL_T posix_acl, mode_t mode)
3918 {
3919         int entry_id = SMB_ACL_FIRST_ENTRY;
3920         SMB_ACL_ENTRY_T entry;
3921         int num_entries = 0;
3922
3923         while ( sys_acl_get_entry(posix_acl, entry_id, &entry) == 1) {
3924                 SMB_ACL_TAG_T tagtype;
3925                 SMB_ACL_PERMSET_T permset;
3926                 mode_t perms;
3927
3928                 entry_id = SMB_ACL_NEXT_ENTRY;
3929
3930                 if (sys_acl_get_tag_type(entry, &tagtype) == -1)
3931                         return -1;
3932
3933                 if (sys_acl_get_permset(entry, &permset) == -1)
3934                         return -1;
3935
3936                 num_entries++;
3937
3938                 switch(tagtype) {
3939                         case SMB_ACL_USER_OBJ:
3940                                 perms = unix_perms_to_acl_perms(mode, S_IRUSR, S_IWUSR, S_IXUSR);
3941                                 break;
3942                         case SMB_ACL_GROUP_OBJ:
3943                                 perms = unix_perms_to_acl_perms(mode, S_IRGRP, S_IWGRP, S_IXGRP);
3944                                 break;
3945                         case SMB_ACL_MASK:
3946                                 /*
3947                                  * FIXME: The ACL_MASK entry permissions should really be set to
3948                                  * the union of the permissions of all ACL_USER,
3949                                  * ACL_GROUP_OBJ, and ACL_GROUP entries. That's what
3950                                  * acl_calc_mask() does, but Samba ACLs doesn't provide it.
3951                                  */
3952                                 perms = S_IRUSR|S_IWUSR|S_IXUSR;
3953                                 break;
3954                         case SMB_ACL_OTHER:
3955                                 perms = unix_perms_to_acl_perms(mode, S_IROTH, S_IWOTH, S_IXOTH);
3956                                 break;
3957                         default:
3958                                 continue;
3959                 }
3960
3961                 if (map_acl_perms_to_permset(perms, &permset) == -1)
3962                         return -1;
3963
3964                 if (sys_acl_set_permset(entry, permset) == -1)
3965                         return -1;
3966         }
3967
3968         /*
3969          * If this is a simple 3 element ACL or no elements then it's a standard
3970          * UNIX permission set. Just use chmod...       
3971          */
3972
3973         if ((num_entries == 3) || (num_entries == 0))
3974                 return -1;
3975
3976         return 0;
3977 }
3978
3979 /****************************************************************************
3980  Get the access ACL of FROM, do a chmod by setting the ACL USER_OBJ,
3981  GROUP_OBJ and OTHER bits in an ACL and set the mask to rwx. Set the
3982  resulting ACL on TO.  Note that name is in UNIX character set.
3983 ****************************************************************************/
3984
3985 static int copy_access_posix_acl(struct files_struct *from,
3986                                  struct files_struct *to,
3987                                  mode_t mode)
3988 {
3989         SMB_ACL_T posix_acl = NULL;
3990         int ret = -1;
3991
3992         posix_acl = SMB_VFS_SYS_ACL_GET_FD(
3993                 from, SMB_ACL_TYPE_ACCESS, talloc_tos());
3994         if (posix_acl == NULL) {
3995                 return -1;
3996         }
3997
3998         ret = chmod_acl_internals(posix_acl, mode);
3999         if (ret == -1) {
4000                 goto done;
4001         }
4002
4003         ret = SMB_VFS_SYS_ACL_SET_FD(to, SMB_ACL_TYPE_ACCESS, posix_acl);
4004
4005  done:
4006
4007         TALLOC_FREE(posix_acl);
4008         return ret;
4009 }
4010
4011 /****************************************************************************
4012  Check for an existing default POSIX ACL on a directory.
4013 ****************************************************************************/
4014
4015 static bool directory_has_default_posix_acl(struct files_struct *dirfsp)
4016 {
4017         SMB_ACL_T def_acl = SMB_VFS_SYS_ACL_GET_FD(
4018                 dirfsp, SMB_ACL_TYPE_DEFAULT, talloc_tos());
4019         bool has_acl = False;
4020         SMB_ACL_ENTRY_T entry;
4021
4022         if (def_acl != NULL && (sys_acl_get_entry(def_acl, SMB_ACL_FIRST_ENTRY, &entry) == 1)) {
4023                 has_acl = True;
4024         }
4025
4026         if (def_acl) {
4027                 TALLOC_FREE(def_acl);
4028         }
4029         return has_acl;
4030 }
4031
4032 /****************************************************************************
4033  If the parent directory has no default ACL but it does have an Access ACL,
4034  inherit this Access ACL to file name.
4035 ****************************************************************************/
4036
4037 int inherit_access_posix_acl(connection_struct *conn,
4038                              struct files_struct *inherit_from_dirfsp,
4039                              const struct smb_filename *smb_fname,
4040                              mode_t mode)
4041 {
4042         int ret;
4043
4044         if (directory_has_default_posix_acl(inherit_from_dirfsp))
4045                 return 0;
4046
4047         ret = copy_access_posix_acl(
4048                 inherit_from_dirfsp, smb_fname->fsp, mode);
4049         return ret;
4050 }
4051
4052 /****************************************************************************
4053  Map from wire type to permset.
4054 ****************************************************************************/
4055
4056 static bool unix_ex_wire_to_permset(connection_struct *conn, unsigned char wire_perm, SMB_ACL_PERMSET_T *p_permset)
4057 {
4058         if (wire_perm & ~(SMB_POSIX_ACL_READ|SMB_POSIX_ACL_WRITE|SMB_POSIX_ACL_EXECUTE)) {
4059                 return False;
4060         }
4061
4062         if (sys_acl_clear_perms(*p_permset) ==  -1) {
4063                 return False;
4064         }
4065
4066         if (wire_perm & SMB_POSIX_ACL_READ) {
4067                 if (sys_acl_add_perm(*p_permset, SMB_ACL_READ) == -1) {
4068                         return False;
4069                 }
4070         }
4071         if (wire_perm & SMB_POSIX_ACL_WRITE) {
4072                 if (sys_acl_add_perm(*p_permset, SMB_ACL_WRITE) == -1) {
4073                         return False;
4074                 }
4075         }
4076         if (wire_perm & SMB_POSIX_ACL_EXECUTE) {
4077                 if (sys_acl_add_perm(*p_permset, SMB_ACL_EXECUTE) == -1) {
4078                         return False;
4079                 }
4080         }
4081         return True;
4082 }
4083
4084 /****************************************************************************
4085  Map from wire type to tagtype.
4086 ****************************************************************************/
4087
4088 static bool unix_ex_wire_to_tagtype(unsigned char wire_tt, SMB_ACL_TAG_T *p_tt)
4089 {
4090         switch (wire_tt) {
4091                 case SMB_POSIX_ACL_USER_OBJ:
4092                         *p_tt = SMB_ACL_USER_OBJ;
4093                         break;
4094                 case SMB_POSIX_ACL_USER:
4095                         *p_tt = SMB_ACL_USER;
4096                         break;
4097                 case SMB_POSIX_ACL_GROUP_OBJ:
4098                         *p_tt = SMB_ACL_GROUP_OBJ;
4099                         break;
4100                 case SMB_POSIX_ACL_GROUP:
4101                         *p_tt = SMB_ACL_GROUP;
4102                         break;
4103                 case SMB_POSIX_ACL_MASK:
4104                         *p_tt = SMB_ACL_MASK;
4105                         break;
4106                 case SMB_POSIX_ACL_OTHER:
4107                         *p_tt = SMB_ACL_OTHER;
4108                         break;
4109                 default:
4110                         return False;
4111         }
4112         return True;
4113 }
4114
4115 /****************************************************************************
4116  Create a new POSIX acl from wire permissions.
4117  FIXME ! How does the share mask/mode fit into this.... ?
4118 ****************************************************************************/
4119
4120 static SMB_ACL_T create_posix_acl_from_wire(connection_struct *conn,
4121                                             uint16_t num_acls,
4122                                             const char *pdata,
4123                                             TALLOC_CTX *mem_ctx)
4124 {
4125         unsigned int i;
4126         SMB_ACL_T the_acl = sys_acl_init(mem_ctx);
4127
4128         if (the_acl == NULL) {
4129                 return NULL;
4130         }
4131
4132         for (i = 0; i < num_acls; i++) {
4133                 SMB_ACL_ENTRY_T the_entry;
4134                 SMB_ACL_PERMSET_T the_permset;
4135                 SMB_ACL_TAG_T tag_type;
4136
4137                 if (sys_acl_create_entry(&the_acl, &the_entry) == -1) {
4138                         DEBUG(0,("create_posix_acl_from_wire: Failed to create entry %u. (%s)\n",
4139                                 i, strerror(errno) ));
4140                         goto fail;
4141                 }
4142
4143                 if (!unix_ex_wire_to_tagtype(CVAL(pdata,(i*SMB_POSIX_ACL_ENTRY_SIZE)), &tag_type)) {
4144                         DEBUG(0,("create_posix_acl_from_wire: invalid wire tagtype %u on entry %u.\n",
4145                                 CVAL(pdata,(i*SMB_POSIX_ACL_ENTRY_SIZE)), i ));
4146                         goto fail;
4147                 }
4148
4149                 if (sys_acl_set_tag_type(the_entry, tag_type) == -1) {
4150                         DEBUG(0,("create_posix_acl_from_wire: Failed to set tagtype on entry %u. (%s)\n",
4151                                 i, strerror(errno) ));
4152                         goto fail;
4153                 }
4154
4155                 /* Get the permset pointer from the new ACL entry. */
4156                 if (sys_acl_get_permset(the_entry, &the_permset) == -1) {
4157                         DEBUG(0,("create_posix_acl_from_wire: Failed to get permset on entry %u. (%s)\n",
4158                                 i, strerror(errno) ));
4159                         goto fail;
4160                 }
4161
4162                 /* Map from wire to permissions. */
4163                 if (!unix_ex_wire_to_permset(conn, CVAL(pdata,(i*SMB_POSIX_ACL_ENTRY_SIZE)+1), &the_permset)) {
4164                         DEBUG(0,("create_posix_acl_from_wire: invalid permset %u on entry %u.\n",
4165                                 CVAL(pdata,(i*SMB_POSIX_ACL_ENTRY_SIZE) + 1), i ));
4166                         goto fail;
4167                 }
4168
4169                 /* Now apply to the new ACL entry. */
4170                 if (sys_acl_set_permset(the_entry, the_permset) == -1) {
4171                         DEBUG(0,("create_posix_acl_from_wire: Failed to add permset on entry %u. (%s)\n",
4172                                 i, strerror(errno) ));
4173                         goto fail;
4174                 }
4175
4176                 if (tag_type == SMB_ACL_USER) {
4177                         uint32_t uidval = IVAL(pdata,(i*SMB_POSIX_ACL_ENTRY_SIZE)+2);
4178                         uid_t uid = (uid_t)uidval;
4179                         if (sys_acl_set_qualifier(the_entry,(void *)&uid) == -1) {
4180                                 DEBUG(0,("create_posix_acl_from_wire: Failed to set uid %u on entry %u. (%s)\n",
4181                                         (unsigned int)uid, i, strerror(errno) ));
4182                                 goto fail;
4183                         }
4184                 }
4185
4186                 if (tag_type == SMB_ACL_GROUP) {
4187                         uint32_t gidval = IVAL(pdata,(i*SMB_POSIX_ACL_ENTRY_SIZE)+2);
4188                         gid_t gid = (uid_t)gidval;
4189                         if (sys_acl_set_qualifier(the_entry,(void *)&gid) == -1) {
4190                                 DEBUG(0,("create_posix_acl_from_wire: Failed to set gid %u on entry %u. (%s)\n",
4191                                         (unsigned int)gid, i, strerror(errno) ));
4192                                 goto fail;
4193                         }
4194                 }
4195         }
4196
4197         return the_acl;
4198
4199  fail:
4200
4201         if (the_acl != NULL) {
4202                 TALLOC_FREE(the_acl);
4203         }
4204         return NULL;
4205 }
4206
4207 /****************************************************************************
4208  Calls from UNIX extensions - Default POSIX ACL set.
4209  If num_def_acls == 0 and not a directory just return. If it is a directory
4210  and num_def_acls == 0 then remove the default acl. Else set the default acl
4211  on the directory.
4212 ****************************************************************************/
4213
4214 NTSTATUS set_unix_posix_default_acl(connection_struct *conn,
4215                                 files_struct *fsp,
4216                                 uint16_t num_def_acls,
4217                                 const char *pdata)
4218 {
4219         SMB_ACL_T def_acl = NULL;
4220         NTSTATUS status;
4221         int ret;
4222
4223         if (!fsp->fsp_flags.is_directory) {
4224                 return NT_STATUS_INVALID_HANDLE;
4225         }
4226
4227         if (!num_def_acls) {
4228                 /* Remove the default ACL. */
4229                 ret = SMB_VFS_SYS_ACL_DELETE_DEF_FD(fsp);
4230                 if (ret == -1) {
4231                         status = map_nt_error_from_unix(errno);
4232                         DBG_INFO("acl_delete_def_fd failed on "
4233                                 "directory %s (%s)\n",
4234                                 fsp_str_dbg(fsp),
4235                                 strerror(errno));
4236                         return status;
4237                 }
4238                 return NT_STATUS_OK;
4239         }
4240
4241         def_acl = create_posix_acl_from_wire(conn,
4242                                         num_def_acls,
4243                                         pdata,
4244                                         talloc_tos());
4245         if (def_acl == NULL) {
4246                 return map_nt_error_from_unix(errno);
4247         }
4248
4249         ret = SMB_VFS_SYS_ACL_SET_FD(fsp,
4250                                      SMB_ACL_TYPE_DEFAULT,
4251                                      def_acl);
4252         if (ret == -1) {
4253                 status = map_nt_error_from_unix(errno);
4254                 DBG_INFO("acl_set_file failed on directory %s (%s)\n",
4255                         fsp_str_dbg(fsp),
4256                         strerror(errno));
4257                 TALLOC_FREE(def_acl);
4258                 return status;
4259         }
4260
4261         DBG_DEBUG("set default acl for file %s\n",
4262                 fsp_str_dbg(fsp));
4263         TALLOC_FREE(def_acl);
4264         return NT_STATUS_OK;
4265 }
4266
4267 /****************************************************************************
4268  Remove an ACL from a file. As we don't have acl_delete_entry() available
4269  we must read the current acl and copy all entries except MASK, USER and GROUP
4270  to a new acl, then set that. This (at least on Linux) causes any ACL to be
4271  removed.
4272  FIXME ! How does the share mask/mode fit into this.... ?
4273 ****************************************************************************/
4274
4275 static NTSTATUS remove_posix_acl(connection_struct *conn,
4276                         files_struct *fsp)
4277 {
4278         SMB_ACL_T file_acl = NULL;
4279         int entry_id = SMB_ACL_FIRST_ENTRY;
4280         SMB_ACL_ENTRY_T entry;
4281         /* Create a new ACL with only 3 entries, u/g/w. */
4282         SMB_ACL_T new_file_acl = NULL;
4283         SMB_ACL_ENTRY_T user_ent = NULL;
4284         SMB_ACL_ENTRY_T group_ent = NULL;
4285         SMB_ACL_ENTRY_T other_ent = NULL;
4286         NTSTATUS status;
4287         int ret;
4288
4289         new_file_acl = sys_acl_init(talloc_tos());
4290         if (new_file_acl == NULL) {
4291                 status = map_nt_error_from_unix(errno);
4292                 DBG_INFO("failed to init new ACL with 3 entries "
4293                         "for file %s %s.\n",
4294                         fsp_str_dbg(fsp),
4295                         strerror(errno));
4296                 goto done;
4297         }
4298
4299         /* Now create the u/g/w entries. */
4300         ret = sys_acl_create_entry(&new_file_acl, &user_ent);
4301         if (ret == -1) {
4302                 status = map_nt_error_from_unix(errno);
4303                 DBG_INFO("Failed to create user entry for file %s. (%s)\n",
4304                         fsp_str_dbg(fsp),
4305                         strerror(errno));
4306                 goto done;
4307         }
4308         ret = sys_acl_set_tag_type(user_ent, SMB_ACL_USER_OBJ);
4309         if (ret == -1) {
4310                 status = map_nt_error_from_unix(errno);
4311                 DBG_INFO("Failed to set user entry for file %s. (%s)\n",
4312                         fsp_str_dbg(fsp),
4313                         strerror(errno));
4314                 goto done;
4315         }
4316
4317         ret = sys_acl_create_entry(&new_file_acl, &group_ent);
4318         if (ret == -1) {
4319                 status = map_nt_error_from_unix(errno);
4320                 DBG_INFO("Failed to create group entry for file %s. (%s)\n",
4321                         fsp_str_dbg(fsp),
4322                         strerror(errno));
4323                 goto done;
4324         }
4325         ret = sys_acl_set_tag_type(group_ent, SMB_ACL_GROUP_OBJ);
4326         if (ret == -1) {
4327                 status = map_nt_error_from_unix(errno);
4328                 DBG_INFO("Failed to set group entry for file %s. (%s)\n",
4329                         fsp_str_dbg(fsp),
4330                         strerror(errno));
4331                 goto done;
4332         }
4333
4334         ret = sys_acl_create_entry(&new_file_acl, &other_ent);
4335         if (ret == -1) {
4336                 status = map_nt_error_from_unix(errno);
4337                 DBG_INFO("Failed to create other entry for file %s. (%s)\n",
4338                         fsp_str_dbg(fsp),
4339                         strerror(errno));
4340                 goto done;
4341         }
4342         ret = sys_acl_set_tag_type(other_ent, SMB_ACL_OTHER);
4343         if (ret == -1) {
4344                 status = map_nt_error_from_unix(errno);
4345                 DBG_INFO("Failed to set other entry for file %s. (%s)\n",
4346                         fsp_str_dbg(fsp),
4347                         strerror(errno));
4348                 goto done;
4349         }
4350
4351         /* Get the current file ACL. */
4352         file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
4353                                           SMB_ACL_TYPE_ACCESS,
4354                                           talloc_tos());
4355
4356         if (file_acl == NULL) {
4357                 status = map_nt_error_from_unix(errno);
4358                 /* This is only returned if an error occurred. Even for a file with
4359                    no acl a u/g/w acl should be returned. */
4360                 DBG_INFO("failed to get ACL from file %s (%s).\n",
4361                         fsp_str_dbg(fsp),
4362                         strerror(errno));
4363                 goto done;
4364         }
4365
4366         while ( sys_acl_get_entry(file_acl, entry_id, &entry) == 1) {
4367                 SMB_ACL_TAG_T tagtype;
4368                 SMB_ACL_PERMSET_T permset;
4369
4370                 entry_id = SMB_ACL_NEXT_ENTRY;
4371
4372                 ret = sys_acl_get_tag_type(entry, &tagtype);
4373                 if (ret == -1) {
4374                         status = map_nt_error_from_unix(errno);
4375                         DBG_INFO("failed to get tagtype from ACL "
4376                                 "on file %s (%s).\n",
4377                                 fsp_str_dbg(fsp),
4378                                 strerror(errno));
4379                         goto done;
4380                 }
4381
4382                 ret = sys_acl_get_permset(entry, &permset);
4383                 if (ret == -1) {
4384                         status = map_nt_error_from_unix(errno);
4385                         DBG_INFO("failed to get permset from ACL "
4386                                 "on file %s (%s).\n",
4387                                 fsp_str_dbg(fsp),
4388                                 strerror(errno));
4389                         goto done;
4390                 }
4391
4392                 if (tagtype == SMB_ACL_USER_OBJ) {
4393                         ret = sys_acl_set_permset(user_ent, permset);
4394                         if (ret == -1) {
4395                                 status = map_nt_error_from_unix(errno);
4396                                 DBG_INFO("failed to set permset from ACL "
4397                                         "on file %s (%s).\n",
4398                                         fsp_str_dbg(fsp),
4399                                         strerror(errno));
4400                                 goto done;
4401                         }
4402                 } else if (tagtype == SMB_ACL_GROUP_OBJ) {
4403                         ret = sys_acl_set_permset(group_ent, permset);
4404                         if (ret == -1) {
4405                                 status = map_nt_error_from_unix(errno);
4406                                 DBG_INFO("failed to set permset from ACL "
4407                                         "on file %s (%s).\n",
4408                                         fsp_str_dbg(fsp),
4409                                         strerror(errno));
4410                                 goto done;
4411                         }
4412                 } else if (tagtype == SMB_ACL_OTHER) {
4413                         ret = sys_acl_set_permset(other_ent, permset);
4414                         if (ret == -1) {
4415                                 status = map_nt_error_from_unix(errno);
4416                                 DBG_INFO("failed to set permset from ACL "
4417                                         "on file %s (%s).\n",
4418                                         fsp_str_dbg(fsp),
4419                                         strerror(errno));
4420                                 goto done;
4421                         }
4422                 }
4423         }
4424
4425         /* Set the new empty file ACL. */
4426         ret = SMB_VFS_SYS_ACL_SET_FD(fsp, SMB_ACL_TYPE_ACCESS, new_file_acl);
4427         if (ret == -1) {
4428                 status = map_nt_error_from_unix(errno);
4429                 DBG_INFO("acl_set_file failed on %s (%s)\n",
4430                         fsp_str_dbg(fsp),
4431                         strerror(errno));
4432                 goto done;
4433         }
4434
4435         status = NT_STATUS_OK;
4436
4437  done:
4438
4439         TALLOC_FREE(file_acl);
4440         TALLOC_FREE(new_file_acl);
4441         return status;
4442 }
4443
4444 /****************************************************************************
4445  Calls from UNIX extensions - POSIX ACL set.
4446  If num_def_acls == 0 then read/modify/write acl after removing all entries
4447  except SMB_ACL_USER_OBJ, SMB_ACL_GROUP_OBJ, SMB_ACL_OTHER.
4448 ****************************************************************************/
4449
4450 NTSTATUS set_unix_posix_acl(connection_struct *conn,
4451                         files_struct *fsp,
4452                         uint16_t num_acls,
4453                         const char *pdata)
4454 {
4455         SMB_ACL_T file_acl = NULL;
4456         int ret;
4457         NTSTATUS status;
4458
4459         if (!num_acls) {
4460                 /* Remove the ACL from the file. */
4461                 return remove_posix_acl(conn, fsp);
4462         }
4463
4464         file_acl = create_posix_acl_from_wire(conn,
4465                                         num_acls,
4466                                         pdata,
4467                                         talloc_tos());
4468         if (file_acl == NULL) {
4469                 return map_nt_error_from_unix(errno);
4470         }
4471
4472         ret = SMB_VFS_SYS_ACL_SET_FD(fsp, SMB_ACL_TYPE_ACCESS, file_acl);
4473         if (ret == -1) {
4474                 status = map_nt_error_from_unix(errno);
4475                 DBG_INFO("acl_set_file failed on %s (%s)\n",
4476                         fsp_str_dbg(fsp),
4477                         strerror(errno));
4478                 TALLOC_FREE(file_acl);
4479                 return status;
4480         }
4481
4482         DBG_DEBUG("set acl for file %s\n",
4483                 fsp_str_dbg(fsp));
4484
4485         TALLOC_FREE(file_acl);
4486         return NT_STATUS_OK;
4487 }
4488
4489 int posix_sys_acl_blob_get_file(vfs_handle_struct *handle,
4490                                 const struct smb_filename *smb_fname_in,
4491                                 TALLOC_CTX *mem_ctx,
4492                                 char **blob_description,
4493                                 DATA_BLOB *blob)
4494 {
4495         int ret;
4496         TALLOC_CTX *frame = talloc_stackframe();
4497         /* Initialise this to zero, in a portable way */
4498         struct smb_acl_wrapper acl_wrapper = {
4499                 0
4500         };
4501         struct smb_filename *smb_fname = cp_smb_filename_nostream(frame,
4502                                                 smb_fname_in);
4503         if (smb_fname == NULL) {
4504                 TALLOC_FREE(frame);
4505                 errno = ENOMEM;
4506                 return -1;
4507         }
4508
4509         ret = smb_vfs_call_stat(handle, smb_fname);
4510         if (ret == -1) {
4511                 TALLOC_FREE(frame);
4512                 return -1;
4513         }
4514
4515         acl_wrapper.owner = smb_fname->st.st_ex_uid;
4516         acl_wrapper.group = smb_fname->st.st_ex_gid;
4517         acl_wrapper.mode = smb_fname->st.st_ex_mode;
4518
4519         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_struct_blob(blob, mem_ctx,
4520                                                           &acl_wrapper,
4521                                                           (ndr_push_flags_fn_t)ndr_push_smb_acl_wrapper))) {
4522                 errno = EINVAL;
4523                 TALLOC_FREE(frame);
4524                 return -1;
4525         }
4526
4527         *blob_description = talloc_strdup(mem_ctx, "posix_acl");
4528         if (!*blob_description) {
4529                 errno = EINVAL;
4530                 TALLOC_FREE(frame);
4531                 return -1;
4532         }
4533
4534         TALLOC_FREE(frame);
4535         return 0;
4536 }
4537
4538 int posix_sys_acl_blob_get_fd(vfs_handle_struct *handle,
4539                               files_struct *fsp,
4540                               TALLOC_CTX *mem_ctx,
4541                               char **blob_description,
4542                               DATA_BLOB *blob)
4543 {
4544         SMB_STRUCT_STAT sbuf;
4545         TALLOC_CTX *frame;
4546         struct smb_acl_wrapper acl_wrapper = { 0 };
4547         int ret;
4548
4549         frame = talloc_stackframe();
4550
4551         acl_wrapper.access_acl = smb_vfs_call_sys_acl_get_fd(handle,
4552                                         fsp,
4553                                         SMB_ACL_TYPE_ACCESS,
4554                                         frame);
4555
4556         if (fsp->fsp_flags.is_directory) {
4557                 acl_wrapper.default_acl = smb_vfs_call_sys_acl_get_fd(handle,
4558                                                 fsp,
4559                                                 SMB_ACL_TYPE_DEFAULT,
4560                                                 frame);
4561         }
4562
4563         ret = smb_vfs_call_fstat(handle, fsp, &sbuf);
4564         if (ret == -1) {
4565                 TALLOC_FREE(frame);
4566                 return -1;
4567         }
4568
4569         acl_wrapper.owner = sbuf.st_ex_uid;
4570         acl_wrapper.group = sbuf.st_ex_gid;
4571         acl_wrapper.mode = sbuf.st_ex_mode;
4572
4573         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_push_struct_blob(blob, mem_ctx,
4574                                                           &acl_wrapper,
4575                                                           (ndr_push_flags_fn_t)ndr_push_smb_acl_wrapper))) {
4576                 errno = EINVAL;
4577                 TALLOC_FREE(frame);
4578                 return -1;
4579         }
4580
4581         *blob_description = talloc_strdup(mem_ctx, "posix_acl");
4582         if (!*blob_description) {
4583                 errno = EINVAL;
4584                 TALLOC_FREE(frame);
4585                 return -1;
4586         }
4587
4588         TALLOC_FREE(frame);
4589         return 0;
4590 }
4591
4592 static NTSTATUS make_default_acl_posix(TALLOC_CTX *ctx,
4593                                        const char *name,
4594                                        const SMB_STRUCT_STAT *psbuf,
4595                                        struct security_descriptor **ppdesc)
4596 {
4597         struct dom_sid owner_sid, group_sid;
4598         size_t size = 0;
4599         struct security_ace aces[4];
4600         uint32_t access_mask = 0;
4601         mode_t mode = psbuf->st_ex_mode;
4602         struct security_acl *new_dacl = NULL;
4603         int idx = 0;
4604
4605         DBG_DEBUG("file %s mode = 0%o\n",name, (int)mode);
4606
4607         uid_to_sid(&owner_sid, psbuf->st_ex_uid);
4608         gid_to_sid(&group_sid, psbuf->st_ex_gid);
4609
4610         /*
4611          We provide up to 4 ACEs
4612                 - Owner
4613                 - Group
4614                 - Everyone
4615                 - NT System
4616         */
4617
4618         if (mode & S_IRUSR) {
4619                 if (mode & S_IWUSR) {
4620                         access_mask |= SEC_RIGHTS_FILE_ALL;
4621                 } else {
4622                         access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
4623                 }
4624         }
4625         if (mode & S_IWUSR) {
4626                 access_mask |= SEC_RIGHTS_FILE_WRITE | SEC_STD_DELETE;
4627         }
4628
4629         init_sec_ace(&aces[idx],
4630                         &owner_sid,
4631                         SEC_ACE_TYPE_ACCESS_ALLOWED,
4632                         access_mask,
4633                         0);
4634         idx++;
4635
4636         access_mask = 0;
4637         if (mode & S_IRGRP) {
4638                 access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
4639         }
4640         if (mode & S_IWGRP) {
4641                 /* note that delete is not granted - this matches posix behaviour */
4642                 access_mask |= SEC_RIGHTS_FILE_WRITE;
4643         }
4644         if (access_mask) {
4645                 init_sec_ace(&aces[idx],
4646                         &group_sid,
4647                         SEC_ACE_TYPE_ACCESS_ALLOWED,
4648                         access_mask,
4649                         0);
4650                 idx++;
4651         }
4652
4653         access_mask = 0;
4654         if (mode & S_IROTH) {
4655                 access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
4656         }
4657         if (mode & S_IWOTH) {
4658                 access_mask |= SEC_RIGHTS_FILE_WRITE;
4659         }
4660         if (access_mask) {
4661                 init_sec_ace(&aces[idx],
4662                         &global_sid_World,
4663                         SEC_ACE_TYPE_ACCESS_ALLOWED,
4664                         access_mask,
4665                         0);
4666                 idx++;
4667         }
4668
4669         init_sec_ace(&aces[idx],
4670                         &global_sid_System,
4671                         SEC_ACE_TYPE_ACCESS_ALLOWED,
4672                         SEC_RIGHTS_FILE_ALL,
4673                         0);
4674         idx++;
4675
4676         new_dacl = make_sec_acl(ctx,
4677                         NT4_ACL_REVISION,
4678                         idx,
4679                         aces);
4680
4681         if (!new_dacl) {
4682                 return NT_STATUS_NO_MEMORY;
4683         }
4684
4685         *ppdesc = make_sec_desc(ctx,
4686                         SECURITY_DESCRIPTOR_REVISION_1,
4687                         SEC_DESC_SELF_RELATIVE|SEC_DESC_DACL_PRESENT,
4688                         &owner_sid,
4689                         &group_sid,
4690                         NULL,
4691                         new_dacl,
4692                         &size);
4693         if (!*ppdesc) {
4694                 return NT_STATUS_NO_MEMORY;
4695         }
4696         return NT_STATUS_OK;
4697 }
4698
4699 static NTSTATUS make_default_acl_windows(TALLOC_CTX *ctx,
4700                                          const char *name,
4701                                          const SMB_STRUCT_STAT *psbuf,
4702                                          struct security_descriptor **ppdesc)
4703 {
4704         struct dom_sid owner_sid, group_sid;
4705         size_t size = 0;
4706         struct security_ace aces[4];
4707         uint32_t access_mask = 0;
4708         mode_t mode = psbuf->st_ex_mode;
4709         struct security_acl *new_dacl = NULL;
4710         int idx = 0;
4711
4712         DBG_DEBUG("file [%s] mode [0%o]\n", name, (int)mode);
4713
4714         uid_to_sid(&owner_sid, psbuf->st_ex_uid);
4715         gid_to_sid(&group_sid, psbuf->st_ex_gid);
4716
4717         /*
4718          * We provide 2 ACEs:
4719          * - Owner
4720          * - NT System
4721          */
4722
4723         if (mode & S_IRUSR) {
4724                 if (mode & S_IWUSR) {
4725                         access_mask |= SEC_RIGHTS_FILE_ALL;
4726                 } else {
4727                         access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
4728                 }
4729         }
4730         if (mode & S_IWUSR) {
4731                 access_mask |= SEC_RIGHTS_FILE_WRITE | SEC_STD_DELETE;
4732         }
4733
4734         init_sec_ace(&aces[idx],
4735                      &owner_sid,
4736                      SEC_ACE_TYPE_ACCESS_ALLOWED,
4737                      access_mask,
4738                      0);
4739         idx++;
4740
4741         init_sec_ace(&aces[idx],
4742                      &global_sid_System,
4743                      SEC_ACE_TYPE_ACCESS_ALLOWED,
4744                      SEC_RIGHTS_FILE_ALL,
4745                      0);
4746         idx++;
4747
4748         new_dacl = make_sec_acl(ctx,
4749                                 NT4_ACL_REVISION,
4750                                 idx,
4751                                 aces);
4752
4753         if (!new_dacl) {
4754                 return NT_STATUS_NO_MEMORY;
4755         }
4756
4757         *ppdesc = make_sec_desc(ctx,
4758                                 SECURITY_DESCRIPTOR_REVISION_1,
4759                                 SEC_DESC_SELF_RELATIVE|SEC_DESC_DACL_PRESENT,
4760                                 &owner_sid,
4761                                 &group_sid,
4762                                 NULL,
4763                                 new_dacl,
4764                                 &size);
4765         if (!*ppdesc) {
4766                 return NT_STATUS_NO_MEMORY;
4767         }
4768         return NT_STATUS_OK;
4769 }
4770
4771 static NTSTATUS make_default_acl_everyone(TALLOC_CTX *ctx,
4772                                           const char *name,
4773                                           const SMB_STRUCT_STAT *psbuf,
4774                                           struct security_descriptor **ppdesc)
4775 {
4776         struct dom_sid owner_sid, group_sid;
4777         size_t size = 0;
4778         struct security_ace aces[1];
4779         mode_t mode = psbuf->st_ex_mode;
4780         struct security_acl *new_dacl = NULL;
4781         int idx = 0;
4782
4783         DBG_DEBUG("file [%s] mode [0%o]\n", name, (int)mode);
4784
4785         uid_to_sid(&owner_sid, psbuf->st_ex_uid);
4786         gid_to_sid(&group_sid, psbuf->st_ex_gid);
4787
4788         /*
4789          * We provide one ACEs: full access for everyone
4790          */
4791
4792         init_sec_ace(&aces[idx],
4793                      &global_sid_World,
4794                      SEC_ACE_TYPE_ACCESS_ALLOWED,
4795                      SEC_RIGHTS_FILE_ALL,
4796                      0);
4797         idx++;
4798
4799         new_dacl = make_sec_acl(ctx,
4800                                 NT4_ACL_REVISION,
4801                                 idx,
4802                                 aces);
4803
4804         if (!new_dacl) {
4805                 return NT_STATUS_NO_MEMORY;
4806         }
4807
4808         *ppdesc = make_sec_desc(ctx,
4809                                 SECURITY_DESCRIPTOR_REVISION_1,
4810                                 SEC_DESC_SELF_RELATIVE|SEC_DESC_DACL_PRESENT,
4811                                 &owner_sid,
4812                                 &group_sid,
4813                                 NULL,
4814                                 new_dacl,
4815                                 &size);
4816         if (!*ppdesc) {
4817                 return NT_STATUS_NO_MEMORY;
4818         }
4819         return NT_STATUS_OK;
4820 }
4821
4822 static const struct enum_list default_acl_style_list[] = {
4823         {DEFAULT_ACL_POSIX,     "posix"},
4824         {DEFAULT_ACL_WINDOWS,   "windows"},
4825         {DEFAULT_ACL_EVERYONE,  "everyone"},
4826 };
4827
4828 const struct enum_list *get_default_acl_style_list(void)
4829 {
4830         return default_acl_style_list;
4831 }
4832
4833 NTSTATUS make_default_filesystem_acl(
4834         TALLOC_CTX *ctx,
4835         enum default_acl_style acl_style,
4836         const char *name,
4837         const SMB_STRUCT_STAT *psbuf,
4838         struct security_descriptor **ppdesc)
4839 {
4840         NTSTATUS status;
4841
4842         switch (acl_style) {
4843         case DEFAULT_ACL_POSIX:
4844                 status =  make_default_acl_posix(ctx, name, psbuf, ppdesc);
4845                 break;
4846
4847         case DEFAULT_ACL_WINDOWS:
4848                 status =  make_default_acl_windows(ctx, name, psbuf, ppdesc);
4849                 break;
4850
4851         case DEFAULT_ACL_EVERYONE:
4852                 status =  make_default_acl_everyone(ctx, name, psbuf, ppdesc);
4853                 break;
4854
4855         default:
4856                 DBG_ERR("unknown acl style %d\n", acl_style);
4857                 status = NT_STATUS_INTERNAL_ERROR;
4858                 break;
4859         }
4860
4861         return status;
4862 }