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