s3: include smbd/smbd.h where needed.
[kai/samba-autobuild/.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
29 extern const struct generic_mapping file_generic_mapping;
30
31 #undef  DBGC_CLASS
32 #define DBGC_CLASS DBGC_ACLS
33
34 /****************************************************************************
35  Data structures representing the internal ACE format.
36 ****************************************************************************/
37
38 enum ace_owner {UID_ACE, GID_ACE, WORLD_ACE};
39 enum ace_attribute {ALLOW_ACE, DENY_ACE}; /* Used for incoming NT ACLS. */
40
41 typedef union posix_id {
42                 uid_t uid;
43                 gid_t gid;
44                 int world;
45 } posix_id;
46
47 typedef struct canon_ace {
48         struct canon_ace *next, *prev;
49         SMB_ACL_TAG_T type;
50         mode_t perms; /* Only use S_I(R|W|X)USR mode bits here. */
51         struct dom_sid trustee;
52         enum ace_owner owner_type;
53         enum ace_attribute attr;
54         posix_id unix_ug;
55         uint8_t ace_flags; /* From windows ACE entry. */
56 } canon_ace;
57
58 #define ALL_ACE_PERMS (S_IRUSR|S_IWUSR|S_IXUSR)
59
60 /*
61  * EA format of user.SAMBA_PAI (Samba_Posix_Acl_Interitance)
62  * attribute on disk - version 1.
63  * All values are little endian.
64  *
65  * |  1   |  1   |   2         |         2           |  ....
66  * +------+------+-------------+---------------------+-------------+--------------------+
67  * | vers | flag | num_entries | num_default_entries | ..entries.. | default_entries... |
68  * +------+------+-------------+---------------------+-------------+--------------------+
69  *
70  * Entry format is :
71  *
72  * |  1   |       4           |
73  * +------+-------------------+
74  * | value|  uid/gid or world |
75  * | type |  value            |
76  * +------+-------------------+
77  *
78  * Version 2 format. Stores extra Windows metadata about an ACL.
79  *
80  * |  1   |  2       |   2         |         2           |  ....
81  * +------+----------+-------------+---------------------+-------------+--------------------+
82  * | vers | ace      | num_entries | num_default_entries | ..entries.. | default_entries... |
83  * |   2  |  type    |             |                     |             |                    |
84  * +------+----------+-------------+---------------------+-------------+--------------------+
85  *
86  * Entry format is :
87  *
88  * |  1   |  1   |       4           |
89  * +------+------+-------------------+
90  * | ace  | value|  uid/gid or world |
91  * | flag | type |  value            |
92  * +------+-------------------+------+
93  *
94  */
95
96 #define PAI_VERSION_OFFSET                      0
97
98 #define PAI_V1_FLAG_OFFSET                      1
99 #define PAI_V1_NUM_ENTRIES_OFFSET               2
100 #define PAI_V1_NUM_DEFAULT_ENTRIES_OFFSET       4
101 #define PAI_V1_ENTRIES_BASE                     6
102 #define PAI_V1_ACL_FLAG_PROTECTED               0x1
103 #define PAI_V1_ENTRY_LENGTH                     5
104
105 #define PAI_V1_VERSION                          1
106
107 #define PAI_V2_TYPE_OFFSET                      1
108 #define PAI_V2_NUM_ENTRIES_OFFSET               3
109 #define PAI_V2_NUM_DEFAULT_ENTRIES_OFFSET       5
110 #define PAI_V2_ENTRIES_BASE                     7
111 #define PAI_V2_ENTRY_LENGTH                     6
112
113 #define PAI_V2_VERSION                          2
114
115 /*
116  * In memory format of user.SAMBA_PAI attribute.
117  */
118
119 struct pai_entry {
120         struct pai_entry *next, *prev;
121         uint8_t ace_flags;
122         enum ace_owner owner_type;
123         posix_id unix_ug;
124 };
125
126 struct pai_val {
127         uint16_t sd_type;
128         unsigned int num_entries;
129         struct pai_entry *entry_list;
130         unsigned int num_def_entries;
131         struct pai_entry *def_entry_list;
132 };
133
134 /************************************************************************
135  Return a uint32 of the pai_entry principal.
136 ************************************************************************/
137
138 static uint32_t get_pai_entry_val(struct pai_entry *paie)
139 {
140         switch (paie->owner_type) {
141                 case UID_ACE:
142                         DEBUG(10,("get_pai_entry_val: uid = %u\n", (unsigned int)paie->unix_ug.uid ));
143                         return (uint32_t)paie->unix_ug.uid;
144                 case GID_ACE:
145                         DEBUG(10,("get_pai_entry_val: gid = %u\n", (unsigned int)paie->unix_ug.gid ));
146                         return (uint32_t)paie->unix_ug.gid;
147                 case WORLD_ACE:
148                 default:
149                         DEBUG(10,("get_pai_entry_val: world ace\n"));
150                         return (uint32_t)-1;
151         }
152 }
153
154 /************************************************************************
155  Return a uint32 of the entry principal.
156 ************************************************************************/
157
158 static uint32_t get_entry_val(canon_ace *ace_entry)
159 {
160         switch (ace_entry->owner_type) {
161                 case UID_ACE:
162                         DEBUG(10,("get_entry_val: uid = %u\n", (unsigned int)ace_entry->unix_ug.uid ));
163                         return (uint32_t)ace_entry->unix_ug.uid;
164                 case GID_ACE:
165                         DEBUG(10,("get_entry_val: gid = %u\n", (unsigned int)ace_entry->unix_ug.gid ));
166                         return (uint32_t)ace_entry->unix_ug.gid;
167                 case WORLD_ACE:
168                 default:
169                         DEBUG(10,("get_entry_val: world ace\n"));
170                         return (uint32_t)-1;
171         }
172 }
173
174 /************************************************************************
175  Create the on-disk format (always v2 now). Caller must free.
176 ************************************************************************/
177
178 static char *create_pai_buf_v2(canon_ace *file_ace_list,
179                                 canon_ace *dir_ace_list,
180                                 uint16_t sd_type,
181                                 size_t *store_size)
182 {
183         char *pai_buf = NULL;
184         canon_ace *ace_list = NULL;
185         char *entry_offset = NULL;
186         unsigned int num_entries = 0;
187         unsigned int num_def_entries = 0;
188         unsigned int i;
189
190         for (ace_list = file_ace_list; ace_list; ace_list = ace_list->next) {
191                 num_entries++;
192         }
193
194         for (ace_list = dir_ace_list; ace_list; ace_list = ace_list->next) {
195                 num_def_entries++;
196         }
197
198         DEBUG(10,("create_pai_buf_v2: num_entries = %u, num_def_entries = %u\n", num_entries, num_def_entries ));
199
200         *store_size = PAI_V2_ENTRIES_BASE +
201                 ((num_entries + num_def_entries)*PAI_V2_ENTRY_LENGTH);
202
203         pai_buf = (char *)SMB_MALLOC(*store_size);
204         if (!pai_buf) {
205                 return NULL;
206         }
207
208         /* Set up the header. */
209         memset(pai_buf, '\0', PAI_V2_ENTRIES_BASE);
210         SCVAL(pai_buf,PAI_VERSION_OFFSET,PAI_V2_VERSION);
211         SSVAL(pai_buf,PAI_V2_TYPE_OFFSET, sd_type);
212         SSVAL(pai_buf,PAI_V2_NUM_ENTRIES_OFFSET,num_entries);
213         SSVAL(pai_buf,PAI_V2_NUM_DEFAULT_ENTRIES_OFFSET,num_def_entries);
214
215         DEBUG(10,("create_pai_buf_v2: sd_type = 0x%x\n",
216                         (unsigned int)sd_type ));
217
218         entry_offset = pai_buf + PAI_V2_ENTRIES_BASE;
219
220         i = 0;
221         for (ace_list = file_ace_list; ace_list; ace_list = ace_list->next) {
222                 uint8_t type_val = (uint8_t)ace_list->owner_type;
223                 uint32_t entry_val = get_entry_val(ace_list);
224
225                 SCVAL(entry_offset,0,ace_list->ace_flags);
226                 SCVAL(entry_offset,1,type_val);
227                 SIVAL(entry_offset,2,entry_val);
228                 DEBUG(10,("create_pai_buf_v2: entry %u [0x%x] [0x%x] [0x%x]\n",
229                         i,
230                         (unsigned int)ace_list->ace_flags,
231                         (unsigned int)type_val,
232                         (unsigned int)entry_val ));
233                 i++;
234                 entry_offset += PAI_V2_ENTRY_LENGTH;
235         }
236
237         for (ace_list = dir_ace_list; ace_list; ace_list = ace_list->next) {
238                 uint8_t type_val = (uint8_t)ace_list->owner_type;
239                 uint32_t entry_val = get_entry_val(ace_list);
240
241                 SCVAL(entry_offset,0,ace_list->ace_flags);
242                 SCVAL(entry_offset,1,type_val);
243                 SIVAL(entry_offset,2,entry_val);
244                 DEBUG(10,("create_pai_buf_v2: entry %u [0x%x] [0x%x] [0x%x]\n",
245                         i,
246                         (unsigned int)ace_list->ace_flags,
247                         (unsigned int)type_val,
248                         (unsigned int)entry_val ));
249                 i++;
250                 entry_offset += PAI_V2_ENTRY_LENGTH;
251         }
252
253         return pai_buf;
254 }
255
256 /************************************************************************
257  Store the user.SAMBA_PAI attribute on disk.
258 ************************************************************************/
259
260 static void store_inheritance_attributes(files_struct *fsp,
261                                         canon_ace *file_ace_list,
262                                         canon_ace *dir_ace_list,
263                                         uint16_t sd_type)
264 {
265         int ret;
266         size_t store_size;
267         char *pai_buf;
268
269         if (!lp_map_acl_inherit(SNUM(fsp->conn))) {
270                 return;
271         }
272
273         pai_buf = create_pai_buf_v2(file_ace_list, dir_ace_list,
274                                 sd_type, &store_size);
275
276         if (fsp->fh->fd != -1) {
277                 ret = SMB_VFS_FSETXATTR(fsp, SAMBA_POSIX_INHERITANCE_EA_NAME,
278                                 pai_buf, store_size, 0);
279         } else {
280                 ret = SMB_VFS_SETXATTR(fsp->conn, fsp->fsp_name->base_name,
281                                        SAMBA_POSIX_INHERITANCE_EA_NAME,
282                                        pai_buf, store_size, 0);
283         }
284
285         SAFE_FREE(pai_buf);
286
287         DEBUG(10,("store_inheritance_attribute: type 0x%x for file %s\n",
288                 (unsigned int)sd_type,
289                 fsp_str_dbg(fsp)));
290
291         if (ret == -1 && !no_acl_syscall_error(errno)) {
292                 DEBUG(1,("store_inheritance_attribute: Error %s\n", strerror(errno) ));
293         }
294 }
295
296 /************************************************************************
297  Delete the in memory inheritance info.
298 ************************************************************************/
299
300 static void free_inherited_info(struct pai_val *pal)
301 {
302         if (pal) {
303                 struct pai_entry *paie, *paie_next;
304                 for (paie = pal->entry_list; paie; paie = paie_next) {
305                         paie_next = paie->next;
306                         SAFE_FREE(paie);
307                 }
308                 for (paie = pal->def_entry_list; paie; paie = paie_next) {
309                         paie_next = paie->next;
310                         SAFE_FREE(paie);
311                 }
312                 SAFE_FREE(pal);
313         }
314 }
315
316 /************************************************************************
317  Get any stored ACE flags.
318 ************************************************************************/
319
320 static uint16_t get_pai_flags(struct pai_val *pal, canon_ace *ace_entry, bool default_ace)
321 {
322         struct pai_entry *paie;
323
324         if (!pal) {
325                 return 0;
326         }
327
328         /* If the entry exists it is inherited. */
329         for (paie = (default_ace ? pal->def_entry_list : pal->entry_list); paie; paie = paie->next) {
330                 if (ace_entry->owner_type == paie->owner_type &&
331                                 get_entry_val(ace_entry) == get_pai_entry_val(paie))
332                         return paie->ace_flags;
333         }
334         return 0;
335 }
336
337 /************************************************************************
338  Ensure an attribute just read is valid - v1.
339 ************************************************************************/
340
341 static bool check_pai_ok_v1(const char *pai_buf, size_t pai_buf_data_size)
342 {
343         uint16 num_entries;
344         uint16 num_def_entries;
345
346         if (pai_buf_data_size < PAI_V1_ENTRIES_BASE) {
347                 /* Corrupted - too small. */
348                 return false;
349         }
350
351         if (CVAL(pai_buf,PAI_VERSION_OFFSET) != PAI_V1_VERSION) {
352                 return false;
353         }
354
355         num_entries = SVAL(pai_buf,PAI_V1_NUM_ENTRIES_OFFSET);
356         num_def_entries = SVAL(pai_buf,PAI_V1_NUM_DEFAULT_ENTRIES_OFFSET);
357
358         /* Check the entry lists match. */
359         /* Each entry is 5 bytes (type plus 4 bytes of uid or gid). */
360
361         if (((num_entries + num_def_entries)*PAI_V1_ENTRY_LENGTH) +
362                         PAI_V1_ENTRIES_BASE != pai_buf_data_size) {
363                 return false;
364         }
365
366         return true;
367 }
368
369 /************************************************************************
370  Ensure an attribute just read is valid - v2.
371 ************************************************************************/
372
373 static bool check_pai_ok_v2(const char *pai_buf, size_t pai_buf_data_size)
374 {
375         uint16 num_entries;
376         uint16 num_def_entries;
377
378         if (pai_buf_data_size < PAI_V2_ENTRIES_BASE) {
379                 /* Corrupted - too small. */
380                 return false;
381         }
382
383         if (CVAL(pai_buf,PAI_VERSION_OFFSET) != PAI_V2_VERSION) {
384                 return false;
385         }
386
387         num_entries = SVAL(pai_buf,PAI_V2_NUM_ENTRIES_OFFSET);
388         num_def_entries = SVAL(pai_buf,PAI_V2_NUM_DEFAULT_ENTRIES_OFFSET);
389
390         /* Check the entry lists match. */
391         /* Each entry is 6 bytes (flags + type + 4 bytes of uid or gid). */
392
393         if (((num_entries + num_def_entries)*PAI_V2_ENTRY_LENGTH) +
394                         PAI_V2_ENTRIES_BASE != pai_buf_data_size) {
395                 return false;
396         }
397
398         return true;
399 }
400
401 /************************************************************************
402  Decode the owner.
403 ************************************************************************/
404
405 static bool get_pai_owner_type(struct pai_entry *paie, const char *entry_offset)
406 {
407         paie->owner_type = (enum ace_owner)CVAL(entry_offset,0);
408         switch( paie->owner_type) {
409                 case UID_ACE:
410                         paie->unix_ug.uid = (uid_t)IVAL(entry_offset,1);
411                         DEBUG(10,("get_pai_owner_type: uid = %u\n",
412                                 (unsigned int)paie->unix_ug.uid ));
413                         break;
414                 case GID_ACE:
415                         paie->unix_ug.gid = (gid_t)IVAL(entry_offset,1);
416                         DEBUG(10,("get_pai_owner_type: gid = %u\n",
417                                 (unsigned int)paie->unix_ug.gid ));
418                         break;
419                 case WORLD_ACE:
420                         paie->unix_ug.world = -1;
421                         DEBUG(10,("get_pai_owner_type: world ace\n"));
422                         break;
423                 default:
424                         DEBUG(10,("get_pai_owner_type: unknown type %u\n",
425                                 (unsigned int)paie->owner_type ));
426                         return false;
427         }
428         return true;
429 }
430
431 /************************************************************************
432  Process v2 entries.
433 ************************************************************************/
434
435 static const char *create_pai_v1_entries(struct pai_val *paiv,
436                                 const char *entry_offset,
437                                 bool def_entry)
438 {
439         int i;
440
441         for (i = 0; i < paiv->num_entries; i++) {
442                 struct pai_entry *paie = SMB_MALLOC_P(struct pai_entry);
443                 if (!paie) {
444                         return NULL;
445                 }
446
447                 paie->ace_flags = SEC_ACE_FLAG_INHERITED_ACE;
448                 if (!get_pai_owner_type(paie, entry_offset)) {
449                         SAFE_FREE(paie);
450                         return NULL;
451                 }
452
453                 if (!def_entry) {
454                         DLIST_ADD(paiv->entry_list, paie);
455                 } else {
456                         DLIST_ADD(paiv->def_entry_list, paie);
457                 }
458                 entry_offset += PAI_V1_ENTRY_LENGTH;
459         }
460         return entry_offset;
461 }
462
463 /************************************************************************
464  Convert to in-memory format from version 1.
465 ************************************************************************/
466
467 static struct pai_val *create_pai_val_v1(const char *buf, size_t size)
468 {
469         const char *entry_offset;
470         struct pai_val *paiv = NULL;
471
472         if (!check_pai_ok_v1(buf, size)) {
473                 return NULL;
474         }
475
476         paiv = SMB_MALLOC_P(struct pai_val);
477         if (!paiv) {
478                 return NULL;
479         }
480
481         memset(paiv, '\0', sizeof(struct pai_val));
482
483         paiv->sd_type = (CVAL(buf,PAI_V1_FLAG_OFFSET) == PAI_V1_ACL_FLAG_PROTECTED) ?
484                         SEC_DESC_DACL_PROTECTED : 0;
485
486         paiv->num_entries = SVAL(buf,PAI_V1_NUM_ENTRIES_OFFSET);
487         paiv->num_def_entries = SVAL(buf,PAI_V1_NUM_DEFAULT_ENTRIES_OFFSET);
488
489         entry_offset = buf + PAI_V1_ENTRIES_BASE;
490
491         DEBUG(10,("create_pai_val: num_entries = %u, num_def_entries = %u\n",
492                         paiv->num_entries, paiv->num_def_entries ));
493
494         entry_offset = create_pai_v1_entries(paiv, entry_offset, false);
495         if (entry_offset == NULL) {
496                 free_inherited_info(paiv);
497                 return NULL;
498         }
499         entry_offset = create_pai_v1_entries(paiv, entry_offset, true);
500         if (entry_offset == NULL) {
501                 free_inherited_info(paiv);
502                 return NULL;
503         }
504
505         return paiv;
506 }
507
508 /************************************************************************
509  Process v2 entries.
510 ************************************************************************/
511
512 static const char *create_pai_v2_entries(struct pai_val *paiv,
513                                 unsigned int num_entries,
514                                 const char *entry_offset,
515                                 bool def_entry)
516 {
517         unsigned int i;
518
519         for (i = 0; i < num_entries; i++) {
520                 struct pai_entry *paie = SMB_MALLOC_P(struct pai_entry);
521                 if (!paie) {
522                         return NULL;
523                 }
524
525                 paie->ace_flags = CVAL(entry_offset,0);
526
527                 if (!get_pai_owner_type(paie, entry_offset+1)) {
528                         SAFE_FREE(paie);
529                         return NULL;
530                 }
531                 if (!def_entry) {
532                         DLIST_ADD(paiv->entry_list, paie);
533                 } else {
534                         DLIST_ADD(paiv->def_entry_list, paie);
535                 }
536                 entry_offset += PAI_V2_ENTRY_LENGTH;
537         }
538         return entry_offset;
539 }
540
541 /************************************************************************
542  Convert to in-memory format from version 2.
543 ************************************************************************/
544
545 static struct pai_val *create_pai_val_v2(const char *buf, size_t size)
546 {
547         const char *entry_offset;
548         struct pai_val *paiv = NULL;
549
550         if (!check_pai_ok_v2(buf, size)) {
551                 return NULL;
552         }
553
554         paiv = SMB_MALLOC_P(struct pai_val);
555         if (!paiv) {
556                 return NULL;
557         }
558
559         memset(paiv, '\0', sizeof(struct pai_val));
560
561         paiv->sd_type = SVAL(buf,PAI_V2_TYPE_OFFSET);
562
563         paiv->num_entries = SVAL(buf,PAI_V2_NUM_ENTRIES_OFFSET);
564         paiv->num_def_entries = SVAL(buf,PAI_V2_NUM_DEFAULT_ENTRIES_OFFSET);
565
566         entry_offset = buf + PAI_V2_ENTRIES_BASE;
567
568         DEBUG(10,("create_pai_val_v2: sd_type = 0x%x num_entries = %u, num_def_entries = %u\n",
569                         (unsigned int)paiv->sd_type,
570                         paiv->num_entries, paiv->num_def_entries ));
571
572         entry_offset = create_pai_v2_entries(paiv, paiv->num_entries,
573                                 entry_offset, false);
574         if (entry_offset == NULL) {
575                 free_inherited_info(paiv);
576                 return NULL;
577         }
578         entry_offset = create_pai_v2_entries(paiv, paiv->num_def_entries,
579                                 entry_offset, true);
580         if (entry_offset == NULL) {
581                 free_inherited_info(paiv);
582                 return NULL;
583         }
584
585         return paiv;
586 }
587
588 /************************************************************************
589  Convert to in-memory format - from either version 1 or 2.
590 ************************************************************************/
591
592 static struct pai_val *create_pai_val(const char *buf, size_t size)
593 {
594         if (size < 1) {
595                 return NULL;
596         }
597         if (CVAL(buf,PAI_VERSION_OFFSET) == PAI_V1_VERSION) {
598                 return create_pai_val_v1(buf, size);
599         } else if (CVAL(buf,PAI_VERSION_OFFSET) == PAI_V2_VERSION) {
600                 return create_pai_val_v2(buf, size);
601         } else {
602                 return NULL;
603         }
604 }
605
606 /************************************************************************
607  Load the user.SAMBA_PAI attribute.
608 ************************************************************************/
609
610 static struct pai_val *fload_inherited_info(files_struct *fsp)
611 {
612         char *pai_buf;
613         size_t pai_buf_size = 1024;
614         struct pai_val *paiv = NULL;
615         ssize_t ret;
616
617         if (!lp_map_acl_inherit(SNUM(fsp->conn))) {
618                 return NULL;
619         }
620
621         if ((pai_buf = (char *)SMB_MALLOC(pai_buf_size)) == NULL) {
622                 return NULL;
623         }
624
625         do {
626                 if (fsp->fh->fd != -1) {
627                         ret = SMB_VFS_FGETXATTR(fsp, SAMBA_POSIX_INHERITANCE_EA_NAME,
628                                         pai_buf, pai_buf_size);
629                 } else {
630                         ret = SMB_VFS_GETXATTR(fsp->conn,
631                                                fsp->fsp_name->base_name,
632                                                SAMBA_POSIX_INHERITANCE_EA_NAME,
633                                                pai_buf, pai_buf_size);
634                 }
635
636                 if (ret == -1) {
637                         if (errno != ERANGE) {
638                                 break;
639                         }
640                         /* Buffer too small - enlarge it. */
641                         pai_buf_size *= 2;
642                         SAFE_FREE(pai_buf);
643                         if (pai_buf_size > 1024*1024) {
644                                 return NULL; /* Limit malloc to 1mb. */
645                         }
646                         if ((pai_buf = (char *)SMB_MALLOC(pai_buf_size)) == NULL)
647                                 return NULL;
648                 }
649         } while (ret == -1);
650
651         DEBUG(10,("load_inherited_info: ret = %lu for file %s\n",
652                   (unsigned long)ret, fsp_str_dbg(fsp)));
653
654         if (ret == -1) {
655                 /* No attribute or not supported. */
656 #if defined(ENOATTR)
657                 if (errno != ENOATTR)
658                         DEBUG(10,("load_inherited_info: Error %s\n", strerror(errno) ));
659 #else
660                 if (errno != ENOSYS)
661                         DEBUG(10,("load_inherited_info: Error %s\n", strerror(errno) ));
662 #endif
663                 SAFE_FREE(pai_buf);
664                 return NULL;
665         }
666
667         paiv = create_pai_val(pai_buf, ret);
668
669         if (paiv) {
670                 DEBUG(10,("load_inherited_info: ACL type is 0x%x for file %s\n",
671                           (unsigned int)paiv->sd_type, fsp_str_dbg(fsp)));
672         }
673
674         SAFE_FREE(pai_buf);
675         return paiv;
676 }
677
678 /************************************************************************
679  Load the user.SAMBA_PAI attribute.
680 ************************************************************************/
681
682 static struct pai_val *load_inherited_info(const struct connection_struct *conn,
683                                            const char *fname)
684 {
685         char *pai_buf;
686         size_t pai_buf_size = 1024;
687         struct pai_val *paiv = NULL;
688         ssize_t ret;
689
690         if (!lp_map_acl_inherit(SNUM(conn))) {
691                 return NULL;
692         }
693
694         if ((pai_buf = (char *)SMB_MALLOC(pai_buf_size)) == NULL) {
695                 return NULL;
696         }
697
698         do {
699                 ret = SMB_VFS_GETXATTR(conn, fname,
700                                        SAMBA_POSIX_INHERITANCE_EA_NAME,
701                                        pai_buf, pai_buf_size);
702
703                 if (ret == -1) {
704                         if (errno != ERANGE) {
705                                 break;
706                         }
707                         /* Buffer too small - enlarge it. */
708                         pai_buf_size *= 2;
709                         SAFE_FREE(pai_buf);
710                         if (pai_buf_size > 1024*1024) {
711                                 return NULL; /* Limit malloc to 1mb. */
712                         }
713                         if ((pai_buf = (char *)SMB_MALLOC(pai_buf_size)) == NULL)
714                                 return NULL;
715                 }
716         } while (ret == -1);
717
718         DEBUG(10,("load_inherited_info: ret = %lu for file %s\n", (unsigned long)ret, fname));
719
720         if (ret == -1) {
721                 /* No attribute or not supported. */
722 #if defined(ENOATTR)
723                 if (errno != ENOATTR)
724                         DEBUG(10,("load_inherited_info: Error %s\n", strerror(errno) ));
725 #else
726                 if (errno != ENOSYS)
727                         DEBUG(10,("load_inherited_info: Error %s\n", strerror(errno) ));
728 #endif
729                 SAFE_FREE(pai_buf);
730                 return NULL;
731         }
732
733         paiv = create_pai_val(pai_buf, ret);
734
735         if (paiv) {
736                 DEBUG(10,("load_inherited_info: ACL type 0x%x for file %s\n",
737                         (unsigned int)paiv->sd_type,
738                         fname));
739         }
740
741         SAFE_FREE(pai_buf);
742         return paiv;
743 }
744
745 /****************************************************************************
746  Functions to manipulate the internal ACE format.
747 ****************************************************************************/
748
749 /****************************************************************************
750  Count a linked list of canonical ACE entries.
751 ****************************************************************************/
752
753 static size_t count_canon_ace_list( canon_ace *l_head )
754 {
755         size_t count = 0;
756         canon_ace *ace;
757
758         for (ace = l_head; ace; ace = ace->next)
759                 count++;
760
761         return count;
762 }
763
764 /****************************************************************************
765  Free a linked list of canonical ACE entries.
766 ****************************************************************************/
767
768 static void free_canon_ace_list( canon_ace *l_head )
769 {
770         canon_ace *list, *next;
771
772         for (list = l_head; list; list = next) {
773                 next = list->next;
774                 DLIST_REMOVE(l_head, list);
775                 SAFE_FREE(list);
776         }
777 }
778
779 /****************************************************************************
780  Function to duplicate a canon_ace entry.
781 ****************************************************************************/
782
783 static canon_ace *dup_canon_ace( canon_ace *src_ace)
784 {
785         canon_ace *dst_ace = SMB_MALLOC_P(canon_ace);
786
787         if (dst_ace == NULL)
788                 return NULL;
789
790         *dst_ace = *src_ace;
791         dst_ace->prev = dst_ace->next = NULL;
792         return dst_ace;
793 }
794
795 /****************************************************************************
796  Print out a canon ace.
797 ****************************************************************************/
798
799 static void print_canon_ace(canon_ace *pace, int num)
800 {
801         dbgtext( "canon_ace index %d. Type = %s ", num, pace->attr == ALLOW_ACE ? "allow" : "deny" );
802         dbgtext( "SID = %s ", sid_string_dbg(&pace->trustee));
803         if (pace->owner_type == UID_ACE) {
804                 const char *u_name = uidtoname(pace->unix_ug.uid);
805                 dbgtext( "uid %u (%s) ", (unsigned int)pace->unix_ug.uid, u_name );
806         } else if (pace->owner_type == GID_ACE) {
807                 char *g_name = gidtoname(pace->unix_ug.gid);
808                 dbgtext( "gid %u (%s) ", (unsigned int)pace->unix_ug.gid, g_name );
809         } else
810                 dbgtext( "other ");
811         switch (pace->type) {
812                 case SMB_ACL_USER:
813                         dbgtext( "SMB_ACL_USER ");
814                         break;
815                 case SMB_ACL_USER_OBJ:
816                         dbgtext( "SMB_ACL_USER_OBJ ");
817                         break;
818                 case SMB_ACL_GROUP:
819                         dbgtext( "SMB_ACL_GROUP ");
820                         break;
821                 case SMB_ACL_GROUP_OBJ:
822                         dbgtext( "SMB_ACL_GROUP_OBJ ");
823                         break;
824                 case SMB_ACL_OTHER:
825                         dbgtext( "SMB_ACL_OTHER ");
826                         break;
827                 default:
828                         dbgtext( "MASK " );
829                         break;
830         }
831
832         dbgtext( "ace_flags = 0x%x ", (unsigned int)pace->ace_flags);
833         dbgtext( "perms ");
834         dbgtext( "%c", pace->perms & S_IRUSR ? 'r' : '-');
835         dbgtext( "%c", pace->perms & S_IWUSR ? 'w' : '-');
836         dbgtext( "%c\n", pace->perms & S_IXUSR ? 'x' : '-');
837 }
838
839 /****************************************************************************
840  Print out a canon ace list.
841 ****************************************************************************/
842
843 static void print_canon_ace_list(const char *name, canon_ace *ace_list)
844 {
845         int count = 0;
846
847         if( DEBUGLVL( 10 )) {
848                 dbgtext( "print_canon_ace_list: %s\n", name );
849                 for (;ace_list; ace_list = ace_list->next, count++)
850                         print_canon_ace(ace_list, count );
851         }
852 }
853
854 /****************************************************************************
855  Map POSIX ACL perms to canon_ace permissions (a mode_t containing only S_(R|W|X)USR bits).
856 ****************************************************************************/
857
858 static mode_t convert_permset_to_mode_t(connection_struct *conn, SMB_ACL_PERMSET_T permset)
859 {
860         mode_t ret = 0;
861
862         ret |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? S_IRUSR : 0);
863         ret |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? S_IWUSR : 0);
864         ret |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? S_IXUSR : 0);
865
866         return ret;
867 }
868
869 /****************************************************************************
870  Map generic UNIX permissions to canon_ace permissions (a mode_t containing only S_(R|W|X)USR bits).
871 ****************************************************************************/
872
873 static mode_t unix_perms_to_acl_perms(mode_t mode, int r_mask, int w_mask, int x_mask)
874 {
875         mode_t ret = 0;
876
877         if (mode & r_mask)
878                 ret |= S_IRUSR;
879         if (mode & w_mask)
880                 ret |= S_IWUSR;
881         if (mode & x_mask)
882                 ret |= S_IXUSR;
883
884         return ret;
885 }
886
887 /****************************************************************************
888  Map canon_ace permissions (a mode_t containing only S_(R|W|X)USR bits) to
889  an SMB_ACL_PERMSET_T.
890 ****************************************************************************/
891
892 static int map_acl_perms_to_permset(connection_struct *conn, mode_t mode, SMB_ACL_PERMSET_T *p_permset)
893 {
894         if (SMB_VFS_SYS_ACL_CLEAR_PERMS(conn, *p_permset) ==  -1)
895                 return -1;
896         if (mode & S_IRUSR) {
897                 if (SMB_VFS_SYS_ACL_ADD_PERM(conn, *p_permset, SMB_ACL_READ) == -1)
898                         return -1;
899         }
900         if (mode & S_IWUSR) {
901                 if (SMB_VFS_SYS_ACL_ADD_PERM(conn, *p_permset, SMB_ACL_WRITE) == -1)
902                         return -1;
903         }
904         if (mode & S_IXUSR) {
905                 if (SMB_VFS_SYS_ACL_ADD_PERM(conn, *p_permset, SMB_ACL_EXECUTE) == -1)
906                         return -1;
907         }
908         return 0;
909 }
910
911 /****************************************************************************
912  Function to create owner and group SIDs from a SMB_STRUCT_STAT.
913 ****************************************************************************/
914
915 void create_file_sids(const SMB_STRUCT_STAT *psbuf, struct dom_sid *powner_sid, struct dom_sid *pgroup_sid)
916 {
917         uid_to_sid( powner_sid, psbuf->st_ex_uid );
918         gid_to_sid( pgroup_sid, psbuf->st_ex_gid );
919 }
920
921 /****************************************************************************
922  Merge aces with a common sid - if both are allow or deny, OR the permissions together and
923  delete the second one. If the first is deny, mask the permissions off and delete the allow
924  if the permissions become zero, delete the deny if the permissions are non zero.
925 ****************************************************************************/
926
927 static void merge_aces( canon_ace **pp_list_head, bool dir_acl)
928 {
929         canon_ace *l_head = *pp_list_head;
930         canon_ace *curr_ace_outer;
931         canon_ace *curr_ace_outer_next;
932
933         /*
934          * First, merge allow entries with identical SIDs, and deny entries
935          * with identical SIDs.
936          */
937
938         for (curr_ace_outer = l_head; curr_ace_outer; curr_ace_outer = curr_ace_outer_next) {
939                 canon_ace *curr_ace;
940                 canon_ace *curr_ace_next;
941
942                 curr_ace_outer_next = curr_ace_outer->next; /* Save the link in case we delete. */
943
944                 for (curr_ace = curr_ace_outer->next; curr_ace; curr_ace = curr_ace_next) {
945                         bool can_merge = false;
946
947                         curr_ace_next = curr_ace->next; /* Save the link in case of delete. */
948
949                         /* For file ACLs we can merge if the SIDs and ALLOW/DENY
950                          * types are the same. For directory acls we must also
951                          * ensure the POSIX ACL types are the same. */
952
953                         if (!dir_acl) {
954                                 can_merge = (dom_sid_equal(&curr_ace->trustee, &curr_ace_outer->trustee) &&
955                                                 (curr_ace->attr == curr_ace_outer->attr));
956                         } else {
957                                 can_merge = (dom_sid_equal(&curr_ace->trustee, &curr_ace_outer->trustee) &&
958                                                 (curr_ace->type == curr_ace_outer->type) &&
959                                                 (curr_ace->attr == curr_ace_outer->attr));
960                         }
961
962                         if (can_merge) {
963                                 if( DEBUGLVL( 10 )) {
964                                         dbgtext("merge_aces: Merging ACE's\n");
965                                         print_canon_ace( curr_ace_outer, 0);
966                                         print_canon_ace( curr_ace, 0);
967                                 }
968
969                                 /* Merge two allow or two deny ACE's. */
970
971                                 /* Theoretically we shouldn't merge a dir ACE if
972                                  * one ACE has the CI flag set, and the other
973                                  * ACE has the OI flag set, but this is rare
974                                  * enough we can ignore it. */
975
976                                 curr_ace_outer->perms |= curr_ace->perms;
977                                 curr_ace_outer->ace_flags |= curr_ace->ace_flags;
978                                 DLIST_REMOVE(l_head, curr_ace);
979                                 SAFE_FREE(curr_ace);
980                                 curr_ace_outer_next = curr_ace_outer->next; /* We may have deleted the link. */
981                         }
982                 }
983         }
984
985         /*
986          * Now go through and mask off allow permissions with deny permissions.
987          * We can delete either the allow or deny here as we know that each SID
988          * appears only once in the list.
989          */
990
991         for (curr_ace_outer = l_head; curr_ace_outer; curr_ace_outer = curr_ace_outer_next) {
992                 canon_ace *curr_ace;
993                 canon_ace *curr_ace_next;
994
995                 curr_ace_outer_next = curr_ace_outer->next; /* Save the link in case we delete. */
996
997                 for (curr_ace = curr_ace_outer->next; curr_ace; curr_ace = curr_ace_next) {
998
999                         curr_ace_next = curr_ace->next; /* Save the link in case of delete. */
1000
1001                         /*
1002                          * Subtract ACE's with different entries. Due to the ordering constraints
1003                          * we've put on the ACL, we know the deny must be the first one.
1004                          */
1005
1006                         if (dom_sid_equal(&curr_ace->trustee, &curr_ace_outer->trustee) &&
1007                                 (curr_ace_outer->attr == DENY_ACE) && (curr_ace->attr == ALLOW_ACE)) {
1008
1009                                 if( DEBUGLVL( 10 )) {
1010                                         dbgtext("merge_aces: Masking ACE's\n");
1011                                         print_canon_ace( curr_ace_outer, 0);
1012                                         print_canon_ace( curr_ace, 0);
1013                                 }
1014
1015                                 curr_ace->perms &= ~curr_ace_outer->perms;
1016
1017                                 if (curr_ace->perms == 0) {
1018
1019                                         /*
1020                                          * The deny overrides the allow. Remove the allow.
1021                                          */
1022
1023                                         DLIST_REMOVE(l_head, curr_ace);
1024                                         SAFE_FREE(curr_ace);
1025                                         curr_ace_outer_next = curr_ace_outer->next; /* We may have deleted the link. */
1026
1027                                 } else {
1028
1029                                         /*
1030                                          * Even after removing permissions, there
1031                                          * are still allow permissions - delete the deny.
1032                                          * It is safe to delete the deny here,
1033                                          * as we are guarenteed by the deny first
1034                                          * ordering that all the deny entries for
1035                                          * this SID have already been merged into one
1036                                          * before we can get to an allow ace.
1037                                          */
1038
1039                                         DLIST_REMOVE(l_head, curr_ace_outer);
1040                                         SAFE_FREE(curr_ace_outer);
1041                                         break;
1042                                 }
1043                         }
1044
1045                 } /* end for curr_ace */
1046         } /* end for curr_ace_outer */
1047
1048         /* We may have modified the list. */
1049
1050         *pp_list_head = l_head;
1051 }
1052
1053 /****************************************************************************
1054  Check if we need to return NT4.x compatible ACL entries.
1055 ****************************************************************************/
1056
1057 bool nt4_compatible_acls(void)
1058 {
1059         int compat = lp_acl_compatibility();
1060
1061         if (compat == ACL_COMPAT_AUTO) {
1062                 enum remote_arch_types ra_type = get_remote_arch();
1063
1064                 /* Automatically adapt to client */
1065                 return (ra_type <= RA_WINNT);
1066         } else
1067                 return (compat == ACL_COMPAT_WINNT);
1068 }
1069
1070
1071 /****************************************************************************
1072  Map canon_ace perms to permission bits NT.
1073  The attr element is not used here - we only process deny entries on set,
1074  not get. Deny entries are implicit on get with ace->perms = 0.
1075 ****************************************************************************/
1076
1077 uint32_t map_canon_ace_perms(int snum,
1078                                 enum security_ace_type *pacl_type,
1079                                 mode_t perms,
1080                                 bool directory_ace)
1081 {
1082         uint32_t nt_mask = 0;
1083
1084         *pacl_type = SEC_ACE_TYPE_ACCESS_ALLOWED;
1085
1086         if (lp_acl_map_full_control(snum) && ((perms & ALL_ACE_PERMS) == ALL_ACE_PERMS)) {
1087                 if (directory_ace) {
1088                         nt_mask = UNIX_DIRECTORY_ACCESS_RWX;
1089                 } else {
1090                         nt_mask = (UNIX_ACCESS_RWX & ~DELETE_ACCESS);
1091                 }
1092         } else if ((perms & ALL_ACE_PERMS) == (mode_t)0) {
1093                 /*
1094                  * Windows NT refuses to display ACEs with no permissions in them (but
1095                  * they are perfectly legal with Windows 2000). If the ACE has empty
1096                  * permissions we cannot use 0, so we use the otherwise unused
1097                  * WRITE_OWNER permission, which we ignore when we set an ACL.
1098                  * We abstract this into a #define of UNIX_ACCESS_NONE to allow this
1099                  * to be changed in the future.
1100                  */
1101
1102                 if (nt4_compatible_acls())
1103                         nt_mask = UNIX_ACCESS_NONE;
1104                 else
1105                         nt_mask = 0;
1106         } else {
1107                 if (directory_ace) {
1108                         nt_mask |= ((perms & S_IRUSR) ? UNIX_DIRECTORY_ACCESS_R : 0 );
1109                         nt_mask |= ((perms & S_IWUSR) ? UNIX_DIRECTORY_ACCESS_W : 0 );
1110                         nt_mask |= ((perms & S_IXUSR) ? UNIX_DIRECTORY_ACCESS_X : 0 );
1111                 } else {
1112                         nt_mask |= ((perms & S_IRUSR) ? UNIX_ACCESS_R : 0 );
1113                         nt_mask |= ((perms & S_IWUSR) ? UNIX_ACCESS_W : 0 );
1114                         nt_mask |= ((perms & S_IXUSR) ? UNIX_ACCESS_X : 0 );
1115                 }
1116         }
1117
1118         if ((perms & S_IWUSR) && lp_dos_filemode(snum)) {
1119                 nt_mask |= (SEC_STD_WRITE_DAC|SEC_STD_WRITE_OWNER|DELETE_ACCESS);
1120         }
1121
1122         DEBUG(10,("map_canon_ace_perms: Mapped (UNIX) %x to (NT) %x\n",
1123                         (unsigned int)perms, (unsigned int)nt_mask ));
1124
1125         return nt_mask;
1126 }
1127
1128 /****************************************************************************
1129  Map NT perms to a UNIX mode_t.
1130 ****************************************************************************/
1131
1132 #define FILE_SPECIFIC_READ_BITS (FILE_READ_DATA|FILE_READ_EA|FILE_READ_ATTRIBUTES)
1133 #define FILE_SPECIFIC_WRITE_BITS (FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_WRITE_EA|FILE_WRITE_ATTRIBUTES)
1134 #define FILE_SPECIFIC_EXECUTE_BITS (FILE_EXECUTE)
1135
1136 static mode_t map_nt_perms( uint32 *mask, int type)
1137 {
1138         mode_t mode = 0;
1139
1140         switch(type) {
1141         case S_IRUSR:
1142                 if((*mask) & GENERIC_ALL_ACCESS)
1143                         mode = S_IRUSR|S_IWUSR|S_IXUSR;
1144                 else {
1145                         mode |= ((*mask) & (GENERIC_READ_ACCESS|FILE_SPECIFIC_READ_BITS)) ? S_IRUSR : 0;
1146                         mode |= ((*mask) & (GENERIC_WRITE_ACCESS|FILE_SPECIFIC_WRITE_BITS)) ? S_IWUSR : 0;
1147                         mode |= ((*mask) & (GENERIC_EXECUTE_ACCESS|FILE_SPECIFIC_EXECUTE_BITS)) ? S_IXUSR : 0;
1148                 }
1149                 break;
1150         case S_IRGRP:
1151                 if((*mask) & GENERIC_ALL_ACCESS)
1152                         mode = S_IRGRP|S_IWGRP|S_IXGRP;
1153                 else {
1154                         mode |= ((*mask) & (GENERIC_READ_ACCESS|FILE_SPECIFIC_READ_BITS)) ? S_IRGRP : 0;
1155                         mode |= ((*mask) & (GENERIC_WRITE_ACCESS|FILE_SPECIFIC_WRITE_BITS)) ? S_IWGRP : 0;
1156                         mode |= ((*mask) & (GENERIC_EXECUTE_ACCESS|FILE_SPECIFIC_EXECUTE_BITS)) ? S_IXGRP : 0;
1157                 }
1158                 break;
1159         case S_IROTH:
1160                 if((*mask) & GENERIC_ALL_ACCESS)
1161                         mode = S_IROTH|S_IWOTH|S_IXOTH;
1162                 else {
1163                         mode |= ((*mask) & (GENERIC_READ_ACCESS|FILE_SPECIFIC_READ_BITS)) ? S_IROTH : 0;
1164                         mode |= ((*mask) & (GENERIC_WRITE_ACCESS|FILE_SPECIFIC_WRITE_BITS)) ? S_IWOTH : 0;
1165                         mode |= ((*mask) & (GENERIC_EXECUTE_ACCESS|FILE_SPECIFIC_EXECUTE_BITS)) ? S_IXOTH : 0;
1166                 }
1167                 break;
1168         }
1169
1170         return mode;
1171 }
1172
1173 /****************************************************************************
1174  Unpack a struct security_descriptor into a UNIX owner and group.
1175 ****************************************************************************/
1176
1177 NTSTATUS unpack_nt_owners(struct connection_struct *conn,
1178                         uid_t *puser, gid_t *pgrp,
1179                         uint32 security_info_sent, const struct
1180                         security_descriptor *psd)
1181 {
1182         struct dom_sid owner_sid;
1183         struct dom_sid grp_sid;
1184
1185         *puser = (uid_t)-1;
1186         *pgrp = (gid_t)-1;
1187
1188         if(security_info_sent == 0) {
1189                 DEBUG(0,("unpack_nt_owners: no security info sent !\n"));
1190                 return NT_STATUS_OK;
1191         }
1192
1193         /*
1194          * Validate the owner and group SID's.
1195          */
1196
1197         memset(&owner_sid, '\0', sizeof(owner_sid));
1198         memset(&grp_sid, '\0', sizeof(grp_sid));
1199
1200         DEBUG(5,("unpack_nt_owners: validating owner_sids.\n"));
1201
1202         /*
1203          * Don't immediately fail if the owner sid cannot be validated.
1204          * This may be a group chown only set.
1205          */
1206
1207         if (security_info_sent & SECINFO_OWNER) {
1208                 sid_copy(&owner_sid, psd->owner_sid);
1209                 if (!sid_to_uid(&owner_sid, puser)) {
1210                         if (lp_force_unknown_acl_user(SNUM(conn))) {
1211                                 /* this allows take ownership to work
1212                                  * reasonably */
1213                                 *puser = get_current_uid(conn);
1214                         } else {
1215                                 DEBUG(3,("unpack_nt_owners: unable to validate"
1216                                          " owner sid for %s\n",
1217                                          sid_string_dbg(&owner_sid)));
1218                                 return NT_STATUS_INVALID_OWNER;
1219                         }
1220                 }
1221                 DEBUG(3,("unpack_nt_owners: owner sid mapped to uid %u\n",
1222                          (unsigned int)*puser ));
1223         }
1224
1225         /*
1226          * Don't immediately fail if the group sid cannot be validated.
1227          * This may be an owner chown only set.
1228          */
1229
1230         if (security_info_sent & SECINFO_GROUP) {
1231                 sid_copy(&grp_sid, psd->group_sid);
1232                 if (!sid_to_gid( &grp_sid, pgrp)) {
1233                         if (lp_force_unknown_acl_user(SNUM(conn))) {
1234                                 /* this allows take group ownership to work
1235                                  * reasonably */
1236                                 *pgrp = get_current_gid(conn);
1237                         } else {
1238                                 DEBUG(3,("unpack_nt_owners: unable to validate"
1239                                          " group sid.\n"));
1240                                 return NT_STATUS_INVALID_OWNER;
1241                         }
1242                 }
1243                 DEBUG(3,("unpack_nt_owners: group sid mapped to gid %u\n",
1244                          (unsigned int)*pgrp));
1245         }
1246
1247         DEBUG(5,("unpack_nt_owners: owner_sids validated.\n"));
1248
1249         return NT_STATUS_OK;
1250 }
1251
1252 /****************************************************************************
1253  Ensure the enforced permissions for this share apply.
1254 ****************************************************************************/
1255
1256 static void apply_default_perms(const struct share_params *params,
1257                                 const bool is_directory, canon_ace *pace,
1258                                 mode_t type)
1259 {
1260         mode_t and_bits = (mode_t)0;
1261         mode_t or_bits = (mode_t)0;
1262
1263         /* Get the initial bits to apply. */
1264
1265         if (is_directory) {
1266                 and_bits = lp_dir_security_mask(params->service);
1267                 or_bits = lp_force_dir_security_mode(params->service);
1268         } else {
1269                 and_bits = lp_security_mask(params->service);
1270                 or_bits = lp_force_security_mode(params->service);
1271         }
1272
1273         /* Now bounce them into the S_USR space. */     
1274         switch(type) {
1275         case S_IRUSR:
1276                 /* Ensure owner has read access. */
1277                 pace->perms |= S_IRUSR;
1278                 if (is_directory)
1279                         pace->perms |= (S_IWUSR|S_IXUSR);
1280                 and_bits = unix_perms_to_acl_perms(and_bits, S_IRUSR, S_IWUSR, S_IXUSR);
1281                 or_bits = unix_perms_to_acl_perms(or_bits, S_IRUSR, S_IWUSR, S_IXUSR);
1282                 break;
1283         case S_IRGRP:
1284                 and_bits = unix_perms_to_acl_perms(and_bits, S_IRGRP, S_IWGRP, S_IXGRP);
1285                 or_bits = unix_perms_to_acl_perms(or_bits, S_IRGRP, S_IWGRP, S_IXGRP);
1286                 break;
1287         case S_IROTH:
1288                 and_bits = unix_perms_to_acl_perms(and_bits, S_IROTH, S_IWOTH, S_IXOTH);
1289                 or_bits = unix_perms_to_acl_perms(or_bits, S_IROTH, S_IWOTH, S_IXOTH);
1290                 break;
1291         }
1292
1293         pace->perms = ((pace->perms & and_bits)|or_bits);
1294 }
1295
1296 /****************************************************************************
1297  Check if a given uid/SID is in a group gid/SID. This is probably very
1298  expensive and will need optimisation. A *lot* of optimisation :-). JRA.
1299 ****************************************************************************/
1300
1301 static bool uid_entry_in_group(connection_struct *conn, canon_ace *uid_ace, canon_ace *group_ace )
1302 {
1303         const char *u_name = NULL;
1304
1305         /* "Everyone" always matches every uid. */
1306
1307         if (dom_sid_equal(&group_ace->trustee, &global_sid_World))
1308                 return True;
1309
1310         /*
1311          * if it's the current user, we already have the unix token
1312          * and don't need to do the complex user_in_group_sid() call
1313          */
1314         if (uid_ace->unix_ug.uid == get_current_uid(conn)) {
1315                 const struct security_unix_token *curr_utok = NULL;
1316                 size_t i;
1317
1318                 if (group_ace->unix_ug.gid == get_current_gid(conn)) {
1319                         return True;
1320                 }
1321
1322                 curr_utok = get_current_utok(conn);
1323                 for (i=0; i < curr_utok->ngroups; i++) {
1324                         if (group_ace->unix_ug.gid == curr_utok->groups[i]) {
1325                                 return True;
1326                         }
1327                 }
1328         }
1329
1330         /* u_name talloc'ed off tos. */
1331         u_name = uidtoname(uid_ace->unix_ug.uid);
1332         if (!u_name) {
1333                 return False;
1334         }
1335
1336         /*
1337          * user_in_group_sid() uses create_token_from_username()
1338          * which creates an artificial NT token given just a username,
1339          * so this is not reliable for users from foreign domains
1340          * exported by winbindd!
1341          */
1342         return user_in_group_sid(u_name, &group_ace->trustee);
1343 }
1344
1345 /****************************************************************************
1346  A well formed POSIX file or default ACL has at least 3 entries, a 
1347  SMB_ACL_USER_OBJ, SMB_ACL_GROUP_OBJ, SMB_ACL_OTHER_OBJ.
1348  In addition, the owner must always have at least read access.
1349  When using this call on get_acl, the pst struct is valid and contains
1350  the mode of the file. When using this call on set_acl, the pst struct has
1351  been modified to have a mode containing the default for this file or directory
1352  type.
1353 ****************************************************************************/
1354
1355 static bool ensure_canon_entry_valid(connection_struct *conn, canon_ace **pp_ace,
1356                                      const struct share_params *params,
1357                                      const bool is_directory,
1358                                                         const struct dom_sid *pfile_owner_sid,
1359                                                         const struct dom_sid *pfile_grp_sid,
1360                                                         const SMB_STRUCT_STAT *pst,
1361                                                         bool setting_acl)
1362 {
1363         canon_ace *pace;
1364         bool got_user = False;
1365         bool got_grp = False;
1366         bool got_other = False;
1367         canon_ace *pace_other = NULL;
1368
1369         for (pace = *pp_ace; pace; pace = pace->next) {
1370                 if (pace->type == SMB_ACL_USER_OBJ) {
1371
1372                         if (setting_acl)
1373                                 apply_default_perms(params, is_directory, pace, S_IRUSR);
1374                         got_user = True;
1375
1376                 } else if (pace->type == SMB_ACL_GROUP_OBJ) {
1377
1378                         /*
1379                          * Ensure create mask/force create mode is respected on set.
1380                          */
1381
1382                         if (setting_acl)
1383                                 apply_default_perms(params, is_directory, pace, S_IRGRP);
1384                         got_grp = True;
1385
1386                 } else if (pace->type == SMB_ACL_OTHER) {
1387
1388                         /*
1389                          * Ensure create mask/force create mode is respected on set.
1390                          */
1391
1392                         if (setting_acl)
1393                                 apply_default_perms(params, is_directory, pace, S_IROTH);
1394                         got_other = True;
1395                         pace_other = pace;
1396                 }
1397         }
1398
1399         if (!got_user) {
1400                 if ((pace = SMB_MALLOC_P(canon_ace)) == NULL) {
1401                         DEBUG(0,("ensure_canon_entry_valid: malloc fail.\n"));
1402                         return False;
1403                 }
1404
1405                 ZERO_STRUCTP(pace);
1406                 pace->type = SMB_ACL_USER_OBJ;
1407                 pace->owner_type = UID_ACE;
1408                 pace->unix_ug.uid = pst->st_ex_uid;
1409                 pace->trustee = *pfile_owner_sid;
1410                 pace->attr = ALLOW_ACE;
1411
1412                 if (setting_acl) {
1413                         /* See if the owning user is in any of the other groups in
1414                            the ACE. If so, OR in the permissions from that group. */
1415
1416                         bool group_matched = False;
1417                         canon_ace *pace_iter;
1418
1419                         for (pace_iter = *pp_ace; pace_iter; pace_iter = pace_iter->next) {
1420                                 if (pace_iter->type == SMB_ACL_GROUP_OBJ || pace_iter->type == SMB_ACL_GROUP) {
1421                                         if (uid_entry_in_group(conn, pace, pace_iter)) {
1422                                                 pace->perms |= pace_iter->perms;
1423                                                 group_matched = True;
1424                                         }
1425                                 }
1426                         }
1427
1428                         /* If we only got an "everyone" perm, just use that. */
1429                         if (!group_matched) {
1430                                 if (got_other)
1431                                         pace->perms = pace_other->perms;
1432                                 else
1433                                         pace->perms = 0;
1434                         }
1435
1436                         apply_default_perms(params, is_directory, pace, S_IRUSR);
1437                 } else {
1438                         pace->perms = unix_perms_to_acl_perms(pst->st_ex_mode, S_IRUSR, S_IWUSR, S_IXUSR);
1439                 }
1440
1441                 DLIST_ADD(*pp_ace, pace);
1442         }
1443
1444         if (!got_grp) {
1445                 if ((pace = SMB_MALLOC_P(canon_ace)) == NULL) {
1446                         DEBUG(0,("ensure_canon_entry_valid: malloc fail.\n"));
1447                         return False;
1448                 }
1449
1450                 ZERO_STRUCTP(pace);
1451                 pace->type = SMB_ACL_GROUP_OBJ;
1452                 pace->owner_type = GID_ACE;
1453                 pace->unix_ug.uid = pst->st_ex_gid;
1454                 pace->trustee = *pfile_grp_sid;
1455                 pace->attr = ALLOW_ACE;
1456                 if (setting_acl) {
1457                         /* If we only got an "everyone" perm, just use that. */
1458                         if (got_other)
1459                                 pace->perms = pace_other->perms;
1460                         else
1461                                 pace->perms = 0;
1462                         apply_default_perms(params, is_directory, pace, S_IRGRP);
1463                 } else {
1464                         pace->perms = unix_perms_to_acl_perms(pst->st_ex_mode, S_IRGRP, S_IWGRP, S_IXGRP);
1465                 }
1466
1467                 DLIST_ADD(*pp_ace, pace);
1468         }
1469
1470         if (!got_other) {
1471                 if ((pace = SMB_MALLOC_P(canon_ace)) == NULL) {
1472                         DEBUG(0,("ensure_canon_entry_valid: malloc fail.\n"));
1473                         return False;
1474                 }
1475
1476                 ZERO_STRUCTP(pace);
1477                 pace->type = SMB_ACL_OTHER;
1478                 pace->owner_type = WORLD_ACE;
1479                 pace->unix_ug.world = -1;
1480                 pace->trustee = global_sid_World;
1481                 pace->attr = ALLOW_ACE;
1482                 if (setting_acl) {
1483                         pace->perms = 0;
1484                         apply_default_perms(params, is_directory, pace, S_IROTH);
1485                 } else
1486                         pace->perms = unix_perms_to_acl_perms(pst->st_ex_mode, S_IROTH, S_IWOTH, S_IXOTH);
1487
1488                 DLIST_ADD(*pp_ace, pace);
1489         }
1490
1491         return True;
1492 }
1493
1494 /****************************************************************************
1495  Check if a POSIX ACL has the required SMB_ACL_USER_OBJ and SMB_ACL_GROUP_OBJ entries.
1496  If it does not have them, check if there are any entries where the trustee is the
1497  file owner or the owning group, and map these to SMB_ACL_USER_OBJ and SMB_ACL_GROUP_OBJ.
1498 ****************************************************************************/
1499
1500 static void check_owning_objs(canon_ace *ace, struct dom_sid *pfile_owner_sid, struct dom_sid *pfile_grp_sid)
1501 {
1502         bool got_user_obj, got_group_obj;
1503         canon_ace *current_ace;
1504         int i, entries;
1505
1506         entries = count_canon_ace_list(ace);
1507         got_user_obj = False;
1508         got_group_obj = False;
1509
1510         for (i=0, current_ace = ace; i < entries; i++, current_ace = current_ace->next) {
1511                 if (current_ace->type == SMB_ACL_USER_OBJ)
1512                         got_user_obj = True;
1513                 else if (current_ace->type == SMB_ACL_GROUP_OBJ)
1514                         got_group_obj = True;
1515         }
1516         if (got_user_obj && got_group_obj) {
1517                 DEBUG(10,("check_owning_objs: ACL had owning user/group entries.\n"));
1518                 return;
1519         }
1520
1521         for (i=0, current_ace = ace; i < entries; i++, current_ace = current_ace->next) {
1522                 if (!got_user_obj && current_ace->owner_type == UID_ACE &&
1523                                 dom_sid_equal(&current_ace->trustee, pfile_owner_sid)) {
1524                         current_ace->type = SMB_ACL_USER_OBJ;
1525                         got_user_obj = True;
1526                 }
1527                 if (!got_group_obj && current_ace->owner_type == GID_ACE &&
1528                                 dom_sid_equal(&current_ace->trustee, pfile_grp_sid)) {
1529                         current_ace->type = SMB_ACL_GROUP_OBJ;
1530                         got_group_obj = True;
1531                 }
1532         }
1533         if (!got_user_obj)
1534                 DEBUG(10,("check_owning_objs: ACL is missing an owner entry.\n"));
1535         if (!got_group_obj)
1536                 DEBUG(10,("check_owning_objs: ACL is missing an owning group entry.\n"));
1537 }
1538
1539 /****************************************************************************
1540  If an ACE entry is SMB_ACL_USER_OBJ and not CREATOR_OWNER, map to SMB_ACL_USER.
1541  If an ACE entry is SMB_ACL_GROUP_OBJ and not CREATOR_GROUP, map to SMB_ACL_GROUP
1542 ****************************************************************************/
1543
1544 static bool dup_owning_ace(canon_ace *dir_ace, canon_ace *ace)
1545 {
1546         /* dir ace must be followings.
1547            SMB_ACL_USER_OBJ : trustee(CREATOR_OWNER) -> Posix ACL d:u::perm
1548            SMB_ACL_USER     : not trustee    -> Posix ACL u:user:perm
1549            SMB_ACL_USER_OBJ : trustee -> convert to SMB_ACL_USER : trustee
1550            Posix ACL u:trustee:perm
1551
1552            SMB_ACL_GROUP_OBJ: trustee(CREATOR_GROUP) -> Posix ACL d:g::perm
1553            SMB_ACL_GROUP    : not trustee   -> Posix ACL g:group:perm
1554            SMB_ACL_GROUP_OBJ: trustee -> convert to SMB_ACL_GROUP : trustee
1555            Posix ACL g:trustee:perm
1556         */
1557
1558         if (ace->type == SMB_ACL_USER_OBJ &&
1559                         !(dom_sid_equal(&ace->trustee, &global_sid_Creator_Owner))) {
1560                 canon_ace *dup_ace = dup_canon_ace(ace);
1561
1562                 if (dup_ace == NULL) {
1563                         return false;
1564                 }
1565                 dup_ace->type = SMB_ACL_USER;
1566                 DLIST_ADD_END(dir_ace, dup_ace, canon_ace *);
1567         }
1568
1569         if (ace->type == SMB_ACL_GROUP_OBJ &&
1570                         !(dom_sid_equal(&ace->trustee, &global_sid_Creator_Group))) {
1571                 canon_ace *dup_ace = dup_canon_ace(ace);
1572
1573                 if (dup_ace == NULL) {
1574                         return false;
1575                 }
1576                 dup_ace->type = SMB_ACL_GROUP;
1577                 DLIST_ADD_END(dir_ace, dup_ace, canon_ace *);
1578         }
1579
1580         return true;
1581 }
1582
1583 /****************************************************************************
1584  Unpack a struct security_descriptor into two canonical ace lists.
1585 ****************************************************************************/
1586
1587 static bool create_canon_ace_lists(files_struct *fsp,
1588                                         const SMB_STRUCT_STAT *pst,
1589                                         struct dom_sid *pfile_owner_sid,
1590                                         struct dom_sid *pfile_grp_sid,
1591                                         canon_ace **ppfile_ace,
1592                                         canon_ace **ppdir_ace,
1593                                         const struct security_acl *dacl)
1594 {
1595         bool all_aces_are_inherit_only = (fsp->is_directory ? True : False);
1596         canon_ace *file_ace = NULL;
1597         canon_ace *dir_ace = NULL;
1598         canon_ace *current_ace = NULL;
1599         bool got_dir_allow = False;
1600         bool got_file_allow = False;
1601         int i, j;
1602
1603         *ppfile_ace = NULL;
1604         *ppdir_ace = NULL;
1605
1606         /*
1607          * Convert the incoming ACL into a more regular form.
1608          */
1609
1610         for(i = 0; i < dacl->num_aces; i++) {
1611                 struct security_ace *psa = &dacl->aces[i];
1612
1613                 if((psa->type != SEC_ACE_TYPE_ACCESS_ALLOWED) && (psa->type != SEC_ACE_TYPE_ACCESS_DENIED)) {
1614                         DEBUG(3,("create_canon_ace_lists: unable to set anything but an ALLOW or DENY ACE.\n"));
1615                         return False;
1616                 }
1617
1618                 if (nt4_compatible_acls()) {
1619                         /*
1620                          * The security mask may be UNIX_ACCESS_NONE which should map into
1621                          * no permissions (we overload the WRITE_OWNER bit for this) or it
1622                          * should be one of the ALL/EXECUTE/READ/WRITE bits. Arrange for this
1623                          * to be so. Any other bits override the UNIX_ACCESS_NONE bit.
1624                          */
1625
1626                         /*
1627                          * Convert GENERIC bits to specific bits.
1628                          */
1629  
1630                         se_map_generic(&psa->access_mask, &file_generic_mapping);
1631
1632                         psa->access_mask &= (UNIX_ACCESS_NONE|FILE_ALL_ACCESS);
1633
1634                         if(psa->access_mask != UNIX_ACCESS_NONE)
1635                                 psa->access_mask &= ~UNIX_ACCESS_NONE;
1636                 }
1637         }
1638
1639         /*
1640          * Deal with the fact that NT 4.x re-writes the canonical format
1641          * that we return for default ACLs. If a directory ACE is identical
1642          * to a inherited directory ACE then NT changes the bits so that the
1643          * first ACE is set to OI|IO and the second ACE for this SID is set
1644          * to CI. We need to repair this. JRA.
1645          */
1646
1647         for(i = 0; i < dacl->num_aces; i++) {
1648                 struct security_ace *psa1 = &dacl->aces[i];
1649
1650                 for (j = i + 1; j < dacl->num_aces; j++) {
1651                         struct security_ace *psa2 = &dacl->aces[j];
1652
1653                         if (psa1->access_mask != psa2->access_mask)
1654                                 continue;
1655
1656                         if (!dom_sid_equal(&psa1->trustee, &psa2->trustee))
1657                                 continue;
1658
1659                         /*
1660                          * Ok - permission bits and SIDs are equal.
1661                          * Check if flags were re-written.
1662                          */
1663
1664                         if (psa1->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
1665
1666                                 psa1->flags |= (psa2->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT));
1667                                 psa2->flags &= ~(SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT);
1668
1669                         } else if (psa2->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
1670
1671                                 psa2->flags |= (psa1->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT));
1672                                 psa1->flags &= ~(SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT);
1673
1674                         }
1675                 }
1676         }
1677
1678         for(i = 0; i < dacl->num_aces; i++) {
1679                 struct security_ace *psa = &dacl->aces[i];
1680
1681                 /*
1682                  * Create a canon_ace entry representing this NT DACL ACE.
1683                  */
1684
1685                 if ((current_ace = SMB_MALLOC_P(canon_ace)) == NULL) {
1686                         free_canon_ace_list(file_ace);
1687                         free_canon_ace_list(dir_ace);
1688                         DEBUG(0,("create_canon_ace_lists: malloc fail.\n"));
1689                         return False;
1690                 }
1691
1692                 ZERO_STRUCTP(current_ace);
1693
1694                 sid_copy(&current_ace->trustee, &psa->trustee);
1695
1696                 /*
1697                  * Try and work out if the SID is a user or group
1698                  * as we need to flag these differently for POSIX.
1699                  * Note what kind of a POSIX ACL this should map to.
1700                  */
1701
1702                 if( dom_sid_equal(&current_ace->trustee, &global_sid_World)) {
1703                         current_ace->owner_type = WORLD_ACE;
1704                         current_ace->unix_ug.world = -1;
1705                         current_ace->type = SMB_ACL_OTHER;
1706                 } else if (dom_sid_equal(&current_ace->trustee, &global_sid_Creator_Owner)) {
1707                         current_ace->owner_type = UID_ACE;
1708                         current_ace->unix_ug.uid = pst->st_ex_uid;
1709                         current_ace->type = SMB_ACL_USER_OBJ;
1710
1711                         /*
1712                          * The Creator Owner entry only specifies inheritable permissions,
1713                          * never access permissions. WinNT doesn't always set the ACE to
1714                          * INHERIT_ONLY, though.
1715                          */
1716
1717                         psa->flags |= SEC_ACE_FLAG_INHERIT_ONLY;
1718
1719                 } else if (dom_sid_equal(&current_ace->trustee, &global_sid_Creator_Group)) {
1720                         current_ace->owner_type = GID_ACE;
1721                         current_ace->unix_ug.gid = pst->st_ex_gid;
1722                         current_ace->type = SMB_ACL_GROUP_OBJ;
1723
1724                         /*
1725                          * The Creator Group entry only specifies inheritable permissions,
1726                          * never access permissions. WinNT doesn't always set the ACE to
1727                          * INHERIT_ONLY, though.
1728                          */
1729                         psa->flags |= SEC_ACE_FLAG_INHERIT_ONLY;
1730
1731                 } else if (sid_to_uid( &current_ace->trustee, &current_ace->unix_ug.uid)) {
1732                         current_ace->owner_type = UID_ACE;
1733                         /* If it's the owning user, this is a user_obj, not
1734                          * a user. */
1735                         if (current_ace->unix_ug.uid == pst->st_ex_uid) {
1736                                 current_ace->type = SMB_ACL_USER_OBJ;
1737                         } else {
1738                                 current_ace->type = SMB_ACL_USER;
1739                         }
1740                 } else if (sid_to_gid( &current_ace->trustee, &current_ace->unix_ug.gid)) {
1741                         current_ace->owner_type = GID_ACE;
1742                         /* If it's the primary group, this is a group_obj, not
1743                          * a group. */
1744                         if (current_ace->unix_ug.gid == pst->st_ex_gid) {
1745                                 current_ace->type = SMB_ACL_GROUP_OBJ;
1746                         } else {
1747                                 current_ace->type = SMB_ACL_GROUP;
1748                         }
1749                 } else {
1750                         /*
1751                          * Silently ignore map failures in non-mappable SIDs (NT Authority, BUILTIN etc).
1752                          */
1753
1754                         if (non_mappable_sid(&psa->trustee)) {
1755                                 DEBUG(10, ("create_canon_ace_lists: ignoring "
1756                                            "non-mappable SID %s\n",
1757                                            sid_string_dbg(&psa->trustee)));
1758                                 SAFE_FREE(current_ace);
1759                                 continue;
1760                         }
1761
1762                         if (lp_force_unknown_acl_user(SNUM(fsp->conn))) {
1763                                 DEBUG(10, ("create_canon_ace_lists: ignoring "
1764                                         "unknown or foreign SID %s\n",
1765                                         sid_string_dbg(&psa->trustee)));
1766                                 SAFE_FREE(current_ace);
1767                                 continue;
1768                         }
1769
1770                         free_canon_ace_list(file_ace);
1771                         free_canon_ace_list(dir_ace);
1772                         DEBUG(0, ("create_canon_ace_lists: unable to map SID "
1773                                   "%s to uid or gid.\n",
1774                                   sid_string_dbg(&current_ace->trustee)));
1775                         SAFE_FREE(current_ace);
1776                         return False;
1777                 }
1778
1779                 /*
1780                  * Map the given NT permissions into a UNIX mode_t containing only
1781                  * S_I(R|W|X)USR bits.
1782                  */
1783
1784                 current_ace->perms |= map_nt_perms( &psa->access_mask, S_IRUSR);
1785                 current_ace->attr = (psa->type == SEC_ACE_TYPE_ACCESS_ALLOWED) ? ALLOW_ACE : DENY_ACE;
1786
1787                 /* Store the ace_flag. */
1788                 current_ace->ace_flags = psa->flags;
1789
1790                 /*
1791                  * Now add the created ace to either the file list, the directory
1792                  * list, or both. We *MUST* preserve the order here (hence we use
1793                  * DLIST_ADD_END) as NT ACLs are order dependent.
1794                  */
1795
1796                 if (fsp->is_directory) {
1797
1798                         /*
1799                          * We can only add to the default POSIX ACE list if the ACE is
1800                          * designed to be inherited by both files and directories.
1801                          */
1802
1803                         if ((psa->flags & (SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT)) ==
1804                                 (SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT)) {
1805
1806                                 DLIST_ADD_END(dir_ace, current_ace, canon_ace *);
1807
1808                                 /*
1809                                  * Note if this was an allow ace. We can't process
1810                                  * any further deny ace's after this.
1811                                  */
1812
1813                                 if (current_ace->attr == ALLOW_ACE)
1814                                         got_dir_allow = True;
1815
1816                                 if ((current_ace->attr == DENY_ACE) && got_dir_allow) {
1817                                         DEBUG(0,("create_canon_ace_lists: "
1818                                                  "malformed ACL in "
1819                                                  "inheritable ACL! Deny entry "
1820                                                  "after Allow entry. Failing "
1821                                                  "to set on file %s.\n",
1822                                                  fsp_str_dbg(fsp)));
1823                                         free_canon_ace_list(file_ace);
1824                                         free_canon_ace_list(dir_ace);
1825                                         return False;
1826                                 }       
1827
1828                                 if( DEBUGLVL( 10 )) {
1829                                         dbgtext("create_canon_ace_lists: adding dir ACL:\n");
1830                                         print_canon_ace( current_ace, 0);
1831                                 }
1832
1833                                 /*
1834                                  * We have a lossy mapping: directory ACE entries
1835                                  * CREATOR_OWNER ------\
1836                                  *     (map to)         +---> SMB_ACL_USER_OBJ
1837                                  * owning sid    ------/
1838                                  *
1839                                  * CREATOR_GROUP ------\
1840                                  *     (map to)         +---> SMB_ACL_GROUP_OBJ
1841                                  * primary group sid --/
1842                                  *
1843                                  * on set. And on read of a directory ACL
1844                                  *
1845                                  * SMB_ACL_USER_OBJ ----> CREATOR_OWNER
1846                                  * SMB_ACL_GROUP_OBJ ---> CREATOR_GROUP.
1847                                  *
1848                                  * Deal with this on set by duplicating
1849                                  * owning sid and primary group sid ACE
1850                                  * entries into the directory ACL.
1851                                  * Fix from Tsukasa Hamano <hamano@osstech.co.jp>.
1852                                  */
1853
1854                                 if (!dup_owning_ace(dir_ace, current_ace)) {
1855                                         DEBUG(0,("create_canon_ace_lists: malloc fail !\n"));
1856                                         free_canon_ace_list(file_ace);
1857                                         free_canon_ace_list(dir_ace);
1858                                         return false;
1859                                 }
1860
1861                                 /*
1862                                  * If this is not an inherit only ACE we need to add a duplicate
1863                                  * to the file acl.
1864                                  */
1865
1866                                 if (!(psa->flags & SEC_ACE_FLAG_INHERIT_ONLY)) {
1867                                         canon_ace *dup_ace = dup_canon_ace(current_ace);
1868
1869                                         if (!dup_ace) {
1870                                                 DEBUG(0,("create_canon_ace_lists: malloc fail !\n"));
1871                                                 free_canon_ace_list(file_ace);
1872                                                 free_canon_ace_list(dir_ace);
1873                                                 return False;
1874                                         }
1875
1876                                         /*
1877                                          * We must not free current_ace here as its
1878                                          * pointer is now owned by the dir_ace list.
1879                                          */
1880                                         current_ace = dup_ace;
1881                                         /* We've essentially split this ace into two,
1882                                          * and added the ace with inheritance request
1883                                          * bits to the directory ACL. Drop those bits for
1884                                          * the ACE we're adding to the file list. */
1885                                         current_ace->ace_flags &= ~(SEC_ACE_FLAG_OBJECT_INHERIT|
1886                                                                 SEC_ACE_FLAG_CONTAINER_INHERIT|
1887                                                                 SEC_ACE_FLAG_INHERIT_ONLY);
1888                                 } else {
1889                                         /*
1890                                          * We must not free current_ace here as its
1891                                          * pointer is now owned by the dir_ace list.
1892                                          */
1893                                         current_ace = NULL;
1894                                 }
1895                         }
1896                 }
1897
1898                 /*
1899                  * Only add to the file ACL if not inherit only.
1900                  */
1901
1902                 if (current_ace && !(psa->flags & SEC_ACE_FLAG_INHERIT_ONLY)) {
1903                         DLIST_ADD_END(file_ace, current_ace, canon_ace *);
1904
1905                         /*
1906                          * Note if this was an allow ace. We can't process
1907                          * any further deny ace's after this.
1908                          */
1909
1910                         if (current_ace->attr == ALLOW_ACE)
1911                                 got_file_allow = True;
1912
1913                         if ((current_ace->attr == DENY_ACE) && got_file_allow) {
1914                                 DEBUG(0,("create_canon_ace_lists: malformed "
1915                                          "ACL in file ACL ! Deny entry after "
1916                                          "Allow entry. Failing to set on file "
1917                                          "%s.\n", fsp_str_dbg(fsp)));
1918                                 free_canon_ace_list(file_ace);
1919                                 free_canon_ace_list(dir_ace);
1920                                 return False;
1921                         }       
1922
1923                         if( DEBUGLVL( 10 )) {
1924                                 dbgtext("create_canon_ace_lists: adding file ACL:\n");
1925                                 print_canon_ace( current_ace, 0);
1926                         }
1927                         all_aces_are_inherit_only = False;
1928                         /*
1929                          * We must not free current_ace here as its
1930                          * pointer is now owned by the file_ace list.
1931                          */
1932                         current_ace = NULL;
1933                 }
1934
1935                 /*
1936                  * Free if ACE was not added.
1937                  */
1938
1939                 SAFE_FREE(current_ace);
1940         }
1941
1942         if (fsp->is_directory && all_aces_are_inherit_only) {
1943                 /*
1944                  * Windows 2000 is doing one of these weird 'inherit acl'
1945                  * traverses to conserve NTFS ACL resources. Just pretend
1946                  * there was no DACL sent. JRA.
1947                  */
1948
1949                 DEBUG(10,("create_canon_ace_lists: Win2k inherit acl traverse. Ignoring DACL.\n"));
1950                 free_canon_ace_list(file_ace);
1951                 free_canon_ace_list(dir_ace);
1952                 file_ace = NULL;
1953                 dir_ace = NULL;
1954         } else {
1955                 /*
1956                  * Check if we have SMB_ACL_USER_OBJ and SMB_ACL_GROUP_OBJ entries in each
1957                  * ACL. If we don't have them, check if any SMB_ACL_USER/SMB_ACL_GROUP
1958                  * entries can be converted to *_OBJ. Usually we will already have these
1959                  * entries in the Default ACL, and the Access ACL will not have them.
1960                  */
1961                 if (file_ace) {
1962                         check_owning_objs(file_ace, pfile_owner_sid, pfile_grp_sid);
1963                 }
1964                 if (dir_ace) {
1965                         check_owning_objs(dir_ace, pfile_owner_sid, pfile_grp_sid);
1966                 }
1967         }
1968
1969         *ppfile_ace = file_ace;
1970         *ppdir_ace = dir_ace;
1971
1972         return True;
1973 }
1974
1975 /****************************************************************************
1976  ASCII art time again... JRA :-).
1977
1978  We have 4 cases to process when moving from an NT ACL to a POSIX ACL. Firstly,
1979  we insist the ACL is in canonical form (ie. all DENY entries preceede ALLOW
1980  entries). Secondly, the merge code has ensured that all duplicate SID entries for
1981  allow or deny have been merged, so the same SID can only appear once in the deny
1982  list or once in the allow list.
1983
1984  We then process as follows :
1985
1986  ---------------------------------------------------------------------------
1987  First pass - look for a Everyone DENY entry.
1988
1989  If it is deny all (rwx) trunate the list at this point.
1990  Else, walk the list from this point and use the deny permissions of this
1991  entry as a mask on all following allow entries. Finally, delete
1992  the Everyone DENY entry (we have applied it to everything possible).
1993
1994  In addition, in this pass we remove any DENY entries that have 
1995  no permissions (ie. they are a DENY nothing).
1996  ---------------------------------------------------------------------------
1997  Second pass - only deal with deny user entries.
1998
1999  DENY user1 (perms XXX)
2000
2001  new_perms = 0
2002  for all following allow group entries where user1 is in group
2003         new_perms |= group_perms;
2004
2005  user1 entry perms = new_perms & ~ XXX;
2006
2007  Convert the deny entry to an allow entry with the new perms and
2008  push to the end of the list. Note if the user was in no groups
2009  this maps to a specific allow nothing entry for this user.
2010
2011  The common case from the NT ACL choser (userX deny all) is
2012  optimised so we don't do the group lookup - we just map to
2013  an allow nothing entry.
2014
2015  What we're doing here is inferring the allow permissions the
2016  person setting the ACE on user1 wanted by looking at the allow
2017  permissions on the groups the user is currently in. This will
2018  be a snapshot, depending on group membership but is the best
2019  we can do and has the advantage of failing closed rather than
2020  open.
2021  ---------------------------------------------------------------------------
2022  Third pass - only deal with deny group entries.
2023
2024  DENY group1 (perms XXX)
2025
2026  for all following allow user entries where user is in group1
2027    user entry perms = user entry perms & ~ XXX;
2028
2029  If there is a group Everyone allow entry with permissions YYY,
2030  convert the group1 entry to an allow entry and modify its
2031  permissions to be :
2032
2033  new_perms = YYY & ~ XXX
2034
2035  and push to the end of the list.
2036
2037  If there is no group Everyone allow entry then convert the
2038  group1 entry to a allow nothing entry and push to the end of the list.
2039
2040  Note that the common case from the NT ACL choser (groupX deny all)
2041  cannot be optimised here as we need to modify user entries who are
2042  in the group to change them to a deny all also.
2043
2044  What we're doing here is modifying the allow permissions of
2045  user entries (which are more specific in POSIX ACLs) to mask
2046  out the explicit deny set on the group they are in. This will
2047  be a snapshot depending on current group membership but is the
2048  best we can do and has the advantage of failing closed rather
2049  than open.
2050  ---------------------------------------------------------------------------
2051  Fourth pass - cope with cumulative permissions.
2052
2053  for all allow user entries, if there exists an allow group entry with
2054  more permissive permissions, and the user is in that group, rewrite the
2055  allow user permissions to contain both sets of permissions.
2056
2057  Currently the code for this is #ifdef'ed out as these semantics make
2058  no sense to me. JRA.
2059  ---------------------------------------------------------------------------
2060
2061  Note we *MUST* do the deny user pass first as this will convert deny user
2062  entries into allow user entries which can then be processed by the deny
2063  group pass.
2064
2065  The above algorithm took a *lot* of thinking about - hence this
2066  explaination :-). JRA.
2067 ****************************************************************************/
2068
2069 /****************************************************************************
2070  Process a canon_ace list entries. This is very complex code. We need
2071  to go through and remove the "deny" permissions from any allow entry that matches
2072  the id of this entry. We have already refused any NT ACL that wasn't in correct
2073  order (DENY followed by ALLOW). If any allow entry ends up with zero permissions,
2074  we just remove it (to fail safe). We have already removed any duplicate ace
2075  entries. Treat an "Everyone" DENY_ACE as a special case - use it to mask all
2076  allow entries.
2077 ****************************************************************************/
2078
2079 static void process_deny_list(connection_struct *conn, canon_ace **pp_ace_list )
2080 {
2081         canon_ace *ace_list = *pp_ace_list;
2082         canon_ace *curr_ace = NULL;
2083         canon_ace *curr_ace_next = NULL;
2084
2085         /* Pass 1 above - look for an Everyone, deny entry. */
2086
2087         for (curr_ace = ace_list; curr_ace; curr_ace = curr_ace_next) {
2088                 canon_ace *allow_ace_p;
2089
2090                 curr_ace_next = curr_ace->next; /* So we can't lose the link. */
2091
2092                 if (curr_ace->attr != DENY_ACE)
2093                         continue;
2094
2095                 if (curr_ace->perms == (mode_t)0) {
2096
2097                         /* Deny nothing entry - delete. */
2098
2099                         DLIST_REMOVE(ace_list, curr_ace);
2100                         continue;
2101                 }
2102
2103                 if (!dom_sid_equal(&curr_ace->trustee, &global_sid_World))
2104                         continue;
2105
2106                 /* JRATEST - assert. */
2107                 SMB_ASSERT(curr_ace->owner_type == WORLD_ACE);
2108
2109                 if (curr_ace->perms == ALL_ACE_PERMS) {
2110
2111                         /*
2112                          * Optimisation. This is a DENY_ALL to Everyone. Truncate the
2113                          * list at this point including this entry.
2114                          */
2115
2116                         canon_ace *prev_entry = DLIST_PREV(curr_ace);
2117
2118                         free_canon_ace_list( curr_ace );
2119                         if (prev_entry)
2120                                 DLIST_REMOVE(ace_list, prev_entry);
2121                         else {
2122                                 /* We deleted the entire list. */
2123                                 ace_list = NULL;
2124                         }
2125                         break;
2126                 }
2127
2128                 for (allow_ace_p = curr_ace->next; allow_ace_p; allow_ace_p = allow_ace_p->next) {
2129
2130                         /* 
2131                          * Only mask off allow entries.
2132                          */
2133
2134                         if (allow_ace_p->attr != ALLOW_ACE)
2135                                 continue;
2136
2137                         allow_ace_p->perms &= ~curr_ace->perms;
2138                 }
2139
2140                 /*
2141                  * Now it's been applied, remove it.
2142                  */
2143
2144                 DLIST_REMOVE(ace_list, curr_ace);
2145         }
2146
2147         /* Pass 2 above - deal with deny user entries. */
2148
2149         for (curr_ace = ace_list; curr_ace; curr_ace = curr_ace_next) {
2150                 mode_t new_perms = (mode_t)0;
2151                 canon_ace *allow_ace_p;
2152
2153                 curr_ace_next = curr_ace->next; /* So we can't lose the link. */
2154
2155                 if (curr_ace->attr != DENY_ACE)
2156                         continue;
2157
2158                 if (curr_ace->owner_type != UID_ACE)
2159                         continue;
2160
2161                 if (curr_ace->perms == ALL_ACE_PERMS) {
2162
2163                         /*
2164                          * Optimisation - this is a deny everything to this user.
2165                          * Convert to an allow nothing and push to the end of the list.
2166                          */
2167
2168                         curr_ace->attr = ALLOW_ACE;
2169                         curr_ace->perms = (mode_t)0;
2170                         DLIST_DEMOTE(ace_list, curr_ace, canon_ace *);
2171                         continue;
2172                 }
2173
2174                 for (allow_ace_p = curr_ace->next; allow_ace_p; allow_ace_p = allow_ace_p->next) {
2175
2176                         if (allow_ace_p->attr != ALLOW_ACE)
2177                                 continue;
2178
2179                         /* We process GID_ACE and WORLD_ACE entries only. */
2180
2181                         if (allow_ace_p->owner_type == UID_ACE)
2182                                 continue;
2183
2184                         if (uid_entry_in_group(conn, curr_ace, allow_ace_p))
2185                                 new_perms |= allow_ace_p->perms;
2186                 }
2187
2188                 /*
2189                  * Convert to a allow entry, modify the perms and push to the end
2190                  * of the list.
2191                  */
2192
2193                 curr_ace->attr = ALLOW_ACE;
2194                 curr_ace->perms = (new_perms & ~curr_ace->perms);
2195                 DLIST_DEMOTE(ace_list, curr_ace, canon_ace *);
2196         }
2197
2198         /* Pass 3 above - deal with deny group entries. */
2199
2200         for (curr_ace = ace_list; curr_ace; curr_ace = curr_ace_next) {
2201                 canon_ace *allow_ace_p;
2202                 canon_ace *allow_everyone_p = NULL;
2203
2204                 curr_ace_next = curr_ace->next; /* So we can't lose the link. */
2205
2206                 if (curr_ace->attr != DENY_ACE)
2207                         continue;
2208
2209                 if (curr_ace->owner_type != GID_ACE)
2210                         continue;
2211
2212                 for (allow_ace_p = curr_ace->next; allow_ace_p; allow_ace_p = allow_ace_p->next) {
2213
2214                         if (allow_ace_p->attr != ALLOW_ACE)
2215                                 continue;
2216
2217                         /* Store a pointer to the Everyone allow, if it exists. */
2218                         if (allow_ace_p->owner_type == WORLD_ACE)
2219                                 allow_everyone_p = allow_ace_p;
2220
2221                         /* We process UID_ACE entries only. */
2222
2223                         if (allow_ace_p->owner_type != UID_ACE)
2224                                 continue;
2225
2226                         /* Mask off the deny group perms. */
2227
2228                         if (uid_entry_in_group(conn, allow_ace_p, curr_ace))
2229                                 allow_ace_p->perms &= ~curr_ace->perms;
2230                 }
2231
2232                 /*
2233                  * Convert the deny to an allow with the correct perms and
2234                  * push to the end of the list.
2235                  */
2236
2237                 curr_ace->attr = ALLOW_ACE;
2238                 if (allow_everyone_p)
2239                         curr_ace->perms = allow_everyone_p->perms & ~curr_ace->perms;
2240                 else
2241                         curr_ace->perms = (mode_t)0;
2242                 DLIST_DEMOTE(ace_list, curr_ace, canon_ace *);
2243         }
2244
2245         /* Doing this fourth pass allows Windows semantics to be layered
2246          * on top of POSIX semantics. I'm not sure if this is desirable.
2247          * For example, in W2K ACLs there is no way to say, "Group X no
2248          * access, user Y full access" if user Y is a member of group X.
2249          * This seems completely broken semantics to me.... JRA.
2250          */
2251
2252 #if 0
2253         /* Pass 4 above - deal with allow entries. */
2254
2255         for (curr_ace = ace_list; curr_ace; curr_ace = curr_ace_next) {
2256                 canon_ace *allow_ace_p;
2257
2258                 curr_ace_next = curr_ace->next; /* So we can't lose the link. */
2259
2260                 if (curr_ace->attr != ALLOW_ACE)
2261                         continue;
2262
2263                 if (curr_ace->owner_type != UID_ACE)
2264                         continue;
2265
2266                 for (allow_ace_p = ace_list; allow_ace_p; allow_ace_p = allow_ace_p->next) {
2267
2268                         if (allow_ace_p->attr != ALLOW_ACE)
2269                                 continue;
2270
2271                         /* We process GID_ACE entries only. */
2272
2273                         if (allow_ace_p->owner_type != GID_ACE)
2274                                 continue;
2275
2276                         /* OR in the group perms. */
2277
2278                         if (uid_entry_in_group(conn, curr_ace, allow_ace_p))
2279                                 curr_ace->perms |= allow_ace_p->perms;
2280                 }
2281         }
2282 #endif
2283
2284         *pp_ace_list = ace_list;
2285 }
2286
2287 /****************************************************************************
2288  Create a default mode that will be used if a security descriptor entry has
2289  no user/group/world entries.
2290 ****************************************************************************/
2291
2292 static mode_t create_default_mode(files_struct *fsp, bool interitable_mode)
2293 {
2294         int snum = SNUM(fsp->conn);
2295         mode_t and_bits = (mode_t)0;
2296         mode_t or_bits = (mode_t)0;
2297         mode_t mode;
2298
2299         if (interitable_mode) {
2300                 mode = unix_mode(fsp->conn, FILE_ATTRIBUTE_ARCHIVE,
2301                                  fsp->fsp_name, NULL);
2302         } else {
2303                 mode = S_IRUSR;
2304         }
2305
2306         if (fsp->is_directory)
2307                 mode |= (S_IWUSR|S_IXUSR);
2308
2309         /*
2310          * Now AND with the create mode/directory mode bits then OR with the
2311          * force create mode/force directory mode bits.
2312          */
2313
2314         if (fsp->is_directory) {
2315                 and_bits = lp_dir_security_mask(snum);
2316                 or_bits = lp_force_dir_security_mode(snum);
2317         } else {
2318                 and_bits = lp_security_mask(snum);
2319                 or_bits = lp_force_security_mode(snum);
2320         }
2321
2322         return ((mode & and_bits)|or_bits);
2323 }
2324
2325 /****************************************************************************
2326  Unpack a struct security_descriptor into two canonical ace lists. We don't depend on this
2327  succeeding.
2328 ****************************************************************************/
2329
2330 static bool unpack_canon_ace(files_struct *fsp,
2331                                 const SMB_STRUCT_STAT *pst,
2332                                 struct dom_sid *pfile_owner_sid,
2333                                 struct dom_sid *pfile_grp_sid,
2334                                 canon_ace **ppfile_ace,
2335                                 canon_ace **ppdir_ace,
2336                                 uint32 security_info_sent,
2337                                 const struct security_descriptor *psd)
2338 {
2339         SMB_STRUCT_STAT st;
2340         canon_ace *file_ace = NULL;
2341         canon_ace *dir_ace = NULL;
2342
2343         *ppfile_ace = NULL;
2344         *ppdir_ace = NULL;
2345
2346         if(security_info_sent == 0) {
2347                 DEBUG(0,("unpack_canon_ace: no security info sent !\n"));
2348                 return False;
2349         }
2350
2351         /*
2352          * If no DACL then this is a chown only security descriptor.
2353          */
2354
2355         if(!(security_info_sent & SECINFO_DACL) || !psd->dacl)
2356                 return True;
2357
2358         /*
2359          * Now go through the DACL and create the canon_ace lists.
2360          */
2361
2362         if (!create_canon_ace_lists( fsp, pst, pfile_owner_sid, pfile_grp_sid,
2363                                                                 &file_ace, &dir_ace, psd->dacl))
2364                 return False;
2365
2366         if ((file_ace == NULL) && (dir_ace == NULL)) {
2367                 /* W2K traverse DACL set - ignore. */
2368                 return True;
2369         }
2370
2371         /*
2372          * Go through the canon_ace list and merge entries
2373          * belonging to identical users of identical allow or deny type.
2374          * We can do this as all deny entries come first, followed by
2375          * all allow entries (we have mandated this before accepting this acl).
2376          */
2377
2378         print_canon_ace_list( "file ace - before merge", file_ace);
2379         merge_aces( &file_ace, false);
2380
2381         print_canon_ace_list( "dir ace - before merge", dir_ace);
2382         merge_aces( &dir_ace, true);
2383
2384         /*
2385          * NT ACLs are order dependent. Go through the acl lists and
2386          * process DENY entries by masking the allow entries.
2387          */
2388
2389         print_canon_ace_list( "file ace - before deny", file_ace);
2390         process_deny_list(fsp->conn, &file_ace);
2391
2392         print_canon_ace_list( "dir ace - before deny", dir_ace);
2393         process_deny_list(fsp->conn, &dir_ace);
2394
2395         /*
2396          * A well formed POSIX file or default ACL has at least 3 entries, a 
2397          * SMB_ACL_USER_OBJ, SMB_ACL_GROUP_OBJ, SMB_ACL_OTHER_OBJ
2398          * and optionally a mask entry. Ensure this is the case.
2399          */
2400
2401         print_canon_ace_list( "file ace - before valid", file_ace);
2402
2403         st = *pst;
2404
2405         /*
2406          * A default 3 element mode entry for a file should be r-- --- ---.
2407          * A default 3 element mode entry for a directory should be rwx --- ---.
2408          */
2409
2410         st.st_ex_mode = create_default_mode(fsp, False);
2411
2412         if (!ensure_canon_entry_valid(fsp->conn, &file_ace, fsp->conn->params,
2413                         fsp->is_directory, pfile_owner_sid, pfile_grp_sid, &st, True)) {
2414                 free_canon_ace_list(file_ace);
2415                 free_canon_ace_list(dir_ace);
2416                 return False;
2417         }
2418
2419         print_canon_ace_list( "dir ace - before valid", dir_ace);
2420
2421         /*
2422          * A default inheritable 3 element mode entry for a directory should be the
2423          * mode Samba will use to create a file within. Ensure user rwx bits are set if
2424          * it's a directory.
2425          */
2426
2427         st.st_ex_mode = create_default_mode(fsp, True);
2428
2429         if (dir_ace && !ensure_canon_entry_valid(fsp->conn, &dir_ace, fsp->conn->params,
2430                         fsp->is_directory, pfile_owner_sid, pfile_grp_sid, &st, True)) {
2431                 free_canon_ace_list(file_ace);
2432                 free_canon_ace_list(dir_ace);
2433                 return False;
2434         }
2435
2436         print_canon_ace_list( "file ace - return", file_ace);
2437         print_canon_ace_list( "dir ace - return", dir_ace);
2438
2439         *ppfile_ace = file_ace;
2440         *ppdir_ace = dir_ace;
2441         return True;
2442
2443 }
2444
2445 /******************************************************************************
2446  When returning permissions, try and fit NT display
2447  semantics if possible. Note the the canon_entries here must have been malloced.
2448  The list format should be - first entry = owner, followed by group and other user
2449  entries, last entry = other.
2450
2451  Note that this doesn't exactly match the NT semantics for an ACL. As POSIX entries
2452  are not ordered, and match on the most specific entry rather than walking a list,
2453  then a simple POSIX permission of rw-r--r-- should really map to 5 entries,
2454
2455  Entry 0: owner : deny all except read and write.
2456  Entry 1: owner : allow read and write.
2457  Entry 2: group : deny all except read.
2458  Entry 3: group : allow read.
2459  Entry 4: Everyone : allow read.
2460
2461  But NT cannot display this in their ACL editor !
2462 ********************************************************************************/
2463
2464 static void arrange_posix_perms(const char *filename, canon_ace **pp_list_head)
2465 {
2466         canon_ace *l_head = *pp_list_head;
2467         canon_ace *owner_ace = NULL;
2468         canon_ace *other_ace = NULL;
2469         canon_ace *ace = NULL;
2470
2471         for (ace = l_head; ace; ace = ace->next) {
2472                 if (ace->type == SMB_ACL_USER_OBJ)
2473                         owner_ace = ace;
2474                 else if (ace->type == SMB_ACL_OTHER) {
2475                         /* Last ace - this is "other" */
2476                         other_ace = ace;
2477                 }
2478         }
2479
2480         if (!owner_ace || !other_ace) {
2481                 DEBUG(0,("arrange_posix_perms: Invalid POSIX permissions for file %s, missing owner or other.\n",
2482                         filename ));
2483                 return;
2484         }
2485
2486         /*
2487          * The POSIX algorithm applies to owner first, and other last,
2488          * so ensure they are arranged in this order.
2489          */
2490
2491         if (owner_ace) {
2492                 DLIST_PROMOTE(l_head, owner_ace);
2493         }
2494
2495         if (other_ace) {
2496                 DLIST_DEMOTE(l_head, other_ace, canon_ace *);
2497         }
2498
2499         /* We have probably changed the head of the list. */
2500
2501         *pp_list_head = l_head;
2502 }
2503
2504 /****************************************************************************
2505  Create a linked list of canonical ACE entries.
2506 ****************************************************************************/
2507
2508 static canon_ace *canonicalise_acl(struct connection_struct *conn,
2509                                    const char *fname, SMB_ACL_T posix_acl,
2510                                    const SMB_STRUCT_STAT *psbuf,
2511                                    const struct dom_sid *powner, const struct dom_sid *pgroup, struct pai_val *pal, SMB_ACL_TYPE_T the_acl_type)
2512 {
2513         mode_t acl_mask = (S_IRUSR|S_IWUSR|S_IXUSR);
2514         canon_ace *l_head = NULL;
2515         canon_ace *ace = NULL;
2516         canon_ace *next_ace = NULL;
2517         int entry_id = SMB_ACL_FIRST_ENTRY;
2518         SMB_ACL_ENTRY_T entry;
2519         size_t ace_count;
2520
2521         while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2522                 SMB_ACL_TAG_T tagtype;
2523                 SMB_ACL_PERMSET_T permset;
2524                 struct dom_sid sid;
2525                 posix_id unix_ug;
2526                 enum ace_owner owner_type;
2527
2528                 entry_id = SMB_ACL_NEXT_ENTRY;
2529
2530                 /* Is this a MASK entry ? */
2531                 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1)
2532                         continue;
2533
2534                 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1)
2535                         continue;
2536
2537                 /* Decide which SID to use based on the ACL type. */
2538                 switch(tagtype) {
2539                         case SMB_ACL_USER_OBJ:
2540                                 /* Get the SID from the owner. */
2541                                 sid_copy(&sid, powner);
2542                                 unix_ug.uid = psbuf->st_ex_uid;
2543                                 owner_type = UID_ACE;
2544                                 break;
2545                         case SMB_ACL_USER:
2546                                 {
2547                                         uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2548                                         if (puid == NULL) {
2549                                                 DEBUG(0,("canonicalise_acl: Failed to get uid.\n"));
2550                                                 continue;
2551                                         }
2552                                         uid_to_sid( &sid, *puid);
2553                                         unix_ug.uid = *puid;
2554                                         owner_type = UID_ACE;
2555                                         SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2556                                         break;
2557                                 }
2558                         case SMB_ACL_GROUP_OBJ:
2559                                 /* Get the SID from the owning group. */
2560                                 sid_copy(&sid, pgroup);
2561                                 unix_ug.gid = psbuf->st_ex_gid;
2562                                 owner_type = GID_ACE;
2563                                 break;
2564                         case SMB_ACL_GROUP:
2565                                 {
2566                                         gid_t *pgid = (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2567                                         if (pgid == NULL) {
2568                                                 DEBUG(0,("canonicalise_acl: Failed to get gid.\n"));
2569                                                 continue;
2570                                         }
2571                                         gid_to_sid( &sid, *pgid);
2572                                         unix_ug.gid = *pgid;
2573                                         owner_type = GID_ACE;
2574                                         SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2575                                         break;
2576                                 }
2577                         case SMB_ACL_MASK:
2578                                 acl_mask = convert_permset_to_mode_t(conn, permset);
2579                                 continue; /* Don't count the mask as an entry. */
2580                         case SMB_ACL_OTHER:
2581                                 /* Use the Everyone SID */
2582                                 sid = global_sid_World;
2583                                 unix_ug.world = -1;
2584                                 owner_type = WORLD_ACE;
2585                                 break;
2586                         default:
2587                                 DEBUG(0,("canonicalise_acl: Unknown tagtype %u\n", (unsigned int)tagtype));
2588                                 continue;
2589                 }
2590
2591                 /*
2592                  * Add this entry to the list.
2593                  */
2594
2595                 if ((ace = SMB_MALLOC_P(canon_ace)) == NULL)
2596                         goto fail;
2597
2598                 ZERO_STRUCTP(ace);
2599                 ace->type = tagtype;
2600                 ace->perms = convert_permset_to_mode_t(conn, permset);
2601                 ace->attr = ALLOW_ACE;
2602                 ace->trustee = sid;
2603                 ace->unix_ug = unix_ug;
2604                 ace->owner_type = owner_type;
2605                 ace->ace_flags = get_pai_flags(pal, ace, (the_acl_type == SMB_ACL_TYPE_DEFAULT));
2606
2607                 DLIST_ADD(l_head, ace);
2608         }
2609
2610         /*
2611          * This next call will ensure we have at least a user/group/world set.
2612          */
2613
2614         if (!ensure_canon_entry_valid(conn, &l_head, conn->params,
2615                                       S_ISDIR(psbuf->st_ex_mode), powner, pgroup,
2616                                       psbuf, False))
2617                 goto fail;
2618
2619         /*
2620          * Now go through the list, masking the permissions with the
2621          * acl_mask. Ensure all DENY Entries are at the start of the list.
2622          */
2623
2624         DEBUG(10,("canonicalise_acl: %s ace entries before arrange :\n", the_acl_type == SMB_ACL_TYPE_ACCESS ? "Access" : "Default" ));
2625
2626         for ( ace_count = 0, ace = l_head; ace; ace = next_ace, ace_count++) {
2627                 next_ace = ace->next;
2628
2629                 /* Masks are only applied to entries other than USER_OBJ and OTHER. */
2630                 if (ace->type != SMB_ACL_OTHER && ace->type != SMB_ACL_USER_OBJ)
2631                         ace->perms &= acl_mask;
2632
2633                 if (ace->perms == 0) {
2634                         DLIST_PROMOTE(l_head, ace);
2635                 }
2636
2637                 if( DEBUGLVL( 10 ) ) {
2638                         print_canon_ace(ace, ace_count);
2639                 }
2640         }
2641
2642         arrange_posix_perms(fname,&l_head );
2643
2644         print_canon_ace_list( "canonicalise_acl: ace entries after arrange", l_head );
2645
2646         return l_head;
2647
2648   fail:
2649
2650         free_canon_ace_list(l_head);
2651         return NULL;
2652 }
2653
2654 /****************************************************************************
2655  Check if the current user group list contains a given group.
2656 ****************************************************************************/
2657
2658 static bool current_user_in_group(connection_struct *conn, gid_t gid)
2659 {
2660         int i;
2661         const struct security_unix_token *utok = get_current_utok(conn);
2662
2663         for (i = 0; i < utok->ngroups; i++) {
2664                 if (utok->groups[i] == gid) {
2665                         return True;
2666                 }
2667         }
2668
2669         return False;
2670 }
2671
2672 /****************************************************************************
2673  Should we override a deny ? Check 'acl group control' and 'dos filemode'.
2674 ****************************************************************************/
2675
2676 static bool acl_group_override(connection_struct *conn,
2677                                const struct smb_filename *smb_fname)
2678 {
2679         if ((errno != EPERM) && (errno != EACCES)) {
2680                 return false;
2681         }
2682
2683         /* file primary group == user primary or supplementary group */
2684         if (lp_acl_group_control(SNUM(conn)) &&
2685             current_user_in_group(conn, smb_fname->st.st_ex_gid)) {
2686                 return true;
2687         }
2688
2689         /* user has writeable permission */
2690         if (lp_dos_filemode(SNUM(conn)) &&
2691             can_write_to_file(conn, smb_fname)) {
2692                 return true;
2693         }
2694
2695         return false;
2696 }
2697
2698 /****************************************************************************
2699  Attempt to apply an ACL to a file or directory.
2700 ****************************************************************************/
2701
2702 static bool set_canon_ace_list(files_struct *fsp,
2703                                 canon_ace *the_ace,
2704                                 bool default_ace,
2705                                 const SMB_STRUCT_STAT *psbuf,
2706                                 bool *pacl_set_support)
2707 {
2708         connection_struct *conn = fsp->conn;
2709         bool ret = False;
2710         SMB_ACL_T the_acl = SMB_VFS_SYS_ACL_INIT(conn, (int)count_canon_ace_list(the_ace) + 1);
2711         canon_ace *p_ace;
2712         int i;
2713         SMB_ACL_ENTRY_T mask_entry;
2714         bool got_mask_entry = False;
2715         SMB_ACL_PERMSET_T mask_permset;
2716         SMB_ACL_TYPE_T the_acl_type = (default_ace ? SMB_ACL_TYPE_DEFAULT : SMB_ACL_TYPE_ACCESS);
2717         bool needs_mask = False;
2718         mode_t mask_perms = 0;
2719
2720         /* Use the psbuf that was passed in. */
2721         if (psbuf != &fsp->fsp_name->st) {
2722                 fsp->fsp_name->st = *psbuf;
2723         }
2724
2725 #if defined(POSIX_ACL_NEEDS_MASK)
2726         /* HP-UX always wants to have a mask (called "class" there). */
2727         needs_mask = True;
2728 #endif
2729
2730         if (the_acl == NULL) {
2731
2732                 if (!no_acl_syscall_error(errno)) {
2733                         /*
2734                          * Only print this error message if we have some kind of ACL
2735                          * support that's not working. Otherwise we would always get this.
2736                          */
2737                         DEBUG(0,("set_canon_ace_list: Unable to init %s ACL. (%s)\n",
2738                                 default_ace ? "default" : "file", strerror(errno) ));
2739                 }
2740                 *pacl_set_support = False;
2741                 goto fail;
2742         }
2743
2744         if( DEBUGLVL( 10 )) {
2745                 dbgtext("set_canon_ace_list: setting ACL:\n");
2746                 for (i = 0, p_ace = the_ace; p_ace; p_ace = p_ace->next, i++ ) {
2747                         print_canon_ace( p_ace, i);
2748                 }
2749         }
2750
2751         for (i = 0, p_ace = the_ace; p_ace; p_ace = p_ace->next, i++ ) {
2752                 SMB_ACL_ENTRY_T the_entry;
2753                 SMB_ACL_PERMSET_T the_permset;
2754
2755                 /*
2756                  * ACLs only "need" an ACL_MASK entry if there are any named user or
2757                  * named group entries. But if there is an ACL_MASK entry, it applies
2758                  * to ACL_USER, ACL_GROUP, and ACL_GROUP_OBJ entries. Set the mask
2759                  * so that it doesn't deny (i.e., mask off) any permissions.
2760                  */
2761
2762                 if (p_ace->type == SMB_ACL_USER || p_ace->type == SMB_ACL_GROUP) {
2763                         needs_mask = True;
2764                         mask_perms |= p_ace->perms;
2765                 } else if (p_ace->type == SMB_ACL_GROUP_OBJ) {
2766                         mask_perms |= p_ace->perms;
2767                 }
2768
2769                 /*
2770                  * Get the entry for this ACE.
2771                  */
2772
2773                 if (SMB_VFS_SYS_ACL_CREATE_ENTRY(conn, &the_acl, &the_entry) == -1) {
2774                         DEBUG(0,("set_canon_ace_list: Failed to create entry %d. (%s)\n",
2775                                 i, strerror(errno) ));
2776                         goto fail;
2777                 }
2778
2779                 if (p_ace->type == SMB_ACL_MASK) {
2780                         mask_entry = the_entry;
2781                         got_mask_entry = True;
2782                 }
2783
2784                 /*
2785                  * Ok - we now know the ACL calls should be working, don't
2786                  * allow fallback to chmod.
2787                  */
2788
2789                 *pacl_set_support = True;
2790
2791                 /*
2792                  * Initialise the entry from the canon_ace.
2793                  */
2794
2795                 /*
2796                  * First tell the entry what type of ACE this is.
2797                  */
2798
2799                 if (SMB_VFS_SYS_ACL_SET_TAG_TYPE(conn, the_entry, p_ace->type) == -1) {
2800                         DEBUG(0,("set_canon_ace_list: Failed to set tag type on entry %d. (%s)\n",
2801                                 i, strerror(errno) ));
2802                         goto fail;
2803                 }
2804
2805                 /*
2806                  * Only set the qualifier (user or group id) if the entry is a user
2807                  * or group id ACE.
2808                  */
2809
2810                 if ((p_ace->type == SMB_ACL_USER) || (p_ace->type == SMB_ACL_GROUP)) {
2811                         if (SMB_VFS_SYS_ACL_SET_QUALIFIER(conn, the_entry,(void *)&p_ace->unix_ug.uid) == -1) {
2812                                 DEBUG(0,("set_canon_ace_list: Failed to set qualifier on entry %d. (%s)\n",
2813                                         i, strerror(errno) ));
2814                                 goto fail;
2815                         }
2816                 }
2817
2818                 /*
2819                  * Convert the mode_t perms in the canon_ace to a POSIX permset.
2820                  */
2821
2822                 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, the_entry, &the_permset) == -1) {
2823                         DEBUG(0,("set_canon_ace_list: Failed to get permset on entry %d. (%s)\n",
2824                                 i, strerror(errno) ));
2825                         goto fail;
2826                 }
2827
2828                 if (map_acl_perms_to_permset(conn, p_ace->perms, &the_permset) == -1) {
2829                         DEBUG(0,("set_canon_ace_list: Failed to create permset for mode (%u) on entry %d. (%s)\n",
2830                                 (unsigned int)p_ace->perms, i, strerror(errno) ));
2831                         goto fail;
2832                 }
2833
2834                 /*
2835                  * ..and apply them to the entry.
2836                  */
2837
2838                 if (SMB_VFS_SYS_ACL_SET_PERMSET(conn, the_entry, the_permset) == -1) {
2839                         DEBUG(0,("set_canon_ace_list: Failed to add permset on entry %d. (%s)\n",
2840                                 i, strerror(errno) ));
2841                         goto fail;
2842                 }
2843
2844                 if( DEBUGLVL( 10 ))
2845                         print_canon_ace( p_ace, i);
2846
2847         }
2848
2849         if (needs_mask && !got_mask_entry) {
2850                 if (SMB_VFS_SYS_ACL_CREATE_ENTRY(conn, &the_acl, &mask_entry) == -1) {
2851                         DEBUG(0,("set_canon_ace_list: Failed to create mask entry. (%s)\n", strerror(errno) ));
2852                         goto fail;
2853                 }
2854
2855                 if (SMB_VFS_SYS_ACL_SET_TAG_TYPE(conn, mask_entry, SMB_ACL_MASK) == -1) {
2856                         DEBUG(0,("set_canon_ace_list: Failed to set tag type on mask entry. (%s)\n",strerror(errno) ));
2857                         goto fail;
2858                 }
2859
2860                 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, mask_entry, &mask_permset) == -1) {
2861                         DEBUG(0,("set_canon_ace_list: Failed to get mask permset. (%s)\n", strerror(errno) ));
2862                         goto fail;
2863                 }
2864
2865                 if (map_acl_perms_to_permset(conn, S_IRUSR|S_IWUSR|S_IXUSR, &mask_permset) == -1) {
2866                         DEBUG(0,("set_canon_ace_list: Failed to create mask permset. (%s)\n", strerror(errno) ));
2867                         goto fail;
2868                 }
2869
2870                 if (SMB_VFS_SYS_ACL_SET_PERMSET(conn, mask_entry, mask_permset) == -1) {
2871                         DEBUG(0,("set_canon_ace_list: Failed to add mask permset. (%s)\n", strerror(errno) ));
2872                         goto fail;
2873                 }
2874         }
2875
2876         /*
2877          * Finally apply it to the file or directory.
2878          */
2879
2880         if(default_ace || fsp->is_directory || fsp->fh->fd == -1) {
2881                 if (SMB_VFS_SYS_ACL_SET_FILE(conn, fsp->fsp_name->base_name,
2882                                              the_acl_type, the_acl) == -1) {
2883                         /*
2884                          * Some systems allow all the above calls and only fail with no ACL support
2885                          * when attempting to apply the acl. HPUX with HFS is an example of this. JRA.
2886                          */
2887                         if (no_acl_syscall_error(errno)) {
2888                                 *pacl_set_support = False;
2889                         }
2890
2891                         if (acl_group_override(conn, fsp->fsp_name)) {
2892                                 int sret;
2893
2894                                 DEBUG(5,("set_canon_ace_list: acl group "
2895                                          "control on and current user in file "
2896                                          "%s primary group.\n",
2897                                          fsp_str_dbg(fsp)));
2898
2899                                 become_root();
2900                                 sret = SMB_VFS_SYS_ACL_SET_FILE(conn,
2901                                     fsp->fsp_name->base_name, the_acl_type,
2902                                     the_acl);
2903                                 unbecome_root();
2904                                 if (sret == 0) {
2905                                         ret = True;     
2906                                 }
2907                         }
2908
2909                         if (ret == False) {
2910                                 DEBUG(2,("set_canon_ace_list: "
2911                                          "sys_acl_set_file type %s failed for "
2912                                          "file %s (%s).\n",
2913                                          the_acl_type == SMB_ACL_TYPE_DEFAULT ?
2914                                          "directory default" : "file",
2915                                          fsp_str_dbg(fsp), strerror(errno)));
2916                                 goto fail;
2917                         }
2918                 }
2919         } else {
2920                 if (SMB_VFS_SYS_ACL_SET_FD(fsp, the_acl) == -1) {
2921                         /*
2922                          * Some systems allow all the above calls and only fail with no ACL support
2923                          * when attempting to apply the acl. HPUX with HFS is an example of this. JRA.
2924                          */
2925                         if (no_acl_syscall_error(errno)) {
2926                                 *pacl_set_support = False;
2927                         }
2928
2929                         if (acl_group_override(conn, fsp->fsp_name)) {
2930                                 int sret;
2931
2932                                 DEBUG(5,("set_canon_ace_list: acl group "
2933                                          "control on and current user in file "
2934                                          "%s primary group.\n",
2935                                          fsp_str_dbg(fsp)));
2936
2937                                 become_root();
2938                                 sret = SMB_VFS_SYS_ACL_SET_FD(fsp, the_acl);
2939                                 unbecome_root();
2940                                 if (sret == 0) {
2941                                         ret = True;
2942                                 }
2943                         }
2944
2945                         if (ret == False) {
2946                                 DEBUG(2,("set_canon_ace_list: "
2947                                          "sys_acl_set_file failed for file %s "
2948                                          "(%s).\n",
2949                                          fsp_str_dbg(fsp), strerror(errno)));
2950                                 goto fail;
2951                         }
2952                 }
2953         }
2954
2955         ret = True;
2956
2957   fail:
2958
2959         if (the_acl != NULL) {
2960                 SMB_VFS_SYS_ACL_FREE_ACL(conn, the_acl);