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