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