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