vfs_acl_common: check for ignore_system_acls before fetching filesystem ACL
[Samba.git] / source3 / modules / vfs_acl_common.c
blob15002ec5c5ada2c448fcb3b5022b81f1162bd7c3
1 /*
2 * Store Windows ACLs in data store - common functions.
3 * #included into modules/vfs_acl_xattr.c and modules/vfs_acl_tdb.c
5 * Copyright (C) Volker Lendecke, 2008
6 * Copyright (C) Jeremy Allison, 2009
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.
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.
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/>.
22 #include "smbd/smbd.h"
23 #include "system/filesys.h"
24 #include "../libcli/security/security.h"
25 #include "../librpc/gen_ndr/ndr_security.h"
26 #include "../lib/util/bitmap.h"
27 #include "passdb/lookup_sid.h"
29 static NTSTATUS create_acl_blob(const struct security_descriptor *psd,
30 DATA_BLOB *pblob,
31 uint16_t hash_type,
32 uint8_t hash[XATTR_SD_HASH_SIZE]);
34 static NTSTATUS get_acl_blob(TALLOC_CTX *ctx,
35 vfs_handle_struct *handle,
36 files_struct *fsp,
37 const char *name,
38 DATA_BLOB *pblob);
40 static NTSTATUS store_acl_blob_fsp(vfs_handle_struct *handle,
41 files_struct *fsp,
42 DATA_BLOB *pblob);
44 #define HASH_SECURITY_INFO (SECINFO_OWNER | \
45 SECINFO_GROUP | \
46 SECINFO_DACL | \
47 SECINFO_SACL)
49 struct acl_common_config {
50 bool ignore_system_acls;
53 static bool init_acl_common_config(vfs_handle_struct *handle)
55 struct acl_common_config *config = NULL;
57 config = talloc_zero(handle->conn, struct acl_common_config);
58 if (config == NULL) {
59 DBG_ERR("talloc_zero() failed\n");
60 errno = ENOMEM;
61 return false;
64 config->ignore_system_acls = lp_parm_bool(SNUM(handle->conn),
65 ACL_MODULE_NAME,
66 "ignore system acls",
67 false);
69 SMB_VFS_HANDLE_SET_DATA(handle, config, NULL,
70 struct acl_common_config,
71 return false);
73 return true;
77 /*******************************************************************
78 Hash a security descriptor.
79 *******************************************************************/
81 static NTSTATUS hash_blob_sha256(DATA_BLOB blob,
82 uint8_t *hash)
84 SHA256_CTX tctx;
86 memset(hash, '\0', XATTR_SD_HASH_SIZE);
88 samba_SHA256_Init(&tctx);
89 samba_SHA256_Update(&tctx, blob.data, blob.length);
90 samba_SHA256_Final(hash, &tctx);
92 return NT_STATUS_OK;
95 /*******************************************************************
96 Hash a security descriptor.
97 *******************************************************************/
99 static NTSTATUS hash_sd_sha256(struct security_descriptor *psd,
100 uint8_t *hash)
102 DATA_BLOB blob;
103 NTSTATUS status;
105 memset(hash, '\0', XATTR_SD_HASH_SIZE);
106 status = create_acl_blob(psd, &blob, XATTR_SD_HASH_TYPE_SHA256, hash);
107 if (!NT_STATUS_IS_OK(status)) {
108 return status;
110 return hash_blob_sha256(blob, hash);
113 /*******************************************************************
114 Parse out a struct security_descriptor from a DATA_BLOB.
115 *******************************************************************/
117 static NTSTATUS parse_acl_blob(const DATA_BLOB *pblob,
118 TALLOC_CTX *mem_ctx,
119 struct security_descriptor **ppdesc,
120 uint16_t *p_hash_type,
121 uint16_t *p_version,
122 uint8_t hash[XATTR_SD_HASH_SIZE],
123 uint8_t sys_acl_hash[XATTR_SD_HASH_SIZE])
125 struct xattr_NTACL xacl;
126 enum ndr_err_code ndr_err;
127 size_t sd_size;
128 TALLOC_CTX *frame = talloc_stackframe();
130 ndr_err = ndr_pull_struct_blob(pblob, frame, &xacl,
131 (ndr_pull_flags_fn_t)ndr_pull_xattr_NTACL);
133 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
134 DEBUG(5, ("parse_acl_blob: ndr_pull_xattr_NTACL failed: %s\n",
135 ndr_errstr(ndr_err)));
136 TALLOC_FREE(frame);
137 return ndr_map_error2ntstatus(ndr_err);
140 *p_version = xacl.version;
142 switch (xacl.version) {
143 case 1:
144 *ppdesc = make_sec_desc(mem_ctx, SD_REVISION,
145 xacl.info.sd->type | SEC_DESC_SELF_RELATIVE,
146 xacl.info.sd->owner_sid,
147 xacl.info.sd->group_sid,
148 xacl.info.sd->sacl,
149 xacl.info.sd->dacl,
150 &sd_size);
151 /* No hash - null out. */
152 *p_hash_type = XATTR_SD_HASH_TYPE_NONE;
153 memset(hash, '\0', XATTR_SD_HASH_SIZE);
154 break;
155 case 2:
156 *ppdesc = make_sec_desc(mem_ctx, SD_REVISION,
157 xacl.info.sd_hs2->sd->type | SEC_DESC_SELF_RELATIVE,
158 xacl.info.sd_hs2->sd->owner_sid,
159 xacl.info.sd_hs2->sd->group_sid,
160 xacl.info.sd_hs2->sd->sacl,
161 xacl.info.sd_hs2->sd->dacl,
162 &sd_size);
163 /* No hash - null out. */
164 *p_hash_type = XATTR_SD_HASH_TYPE_NONE;
165 memset(hash, '\0', XATTR_SD_HASH_SIZE);
166 break;
167 case 3:
168 *ppdesc = make_sec_desc(mem_ctx, SD_REVISION,
169 xacl.info.sd_hs3->sd->type | SEC_DESC_SELF_RELATIVE,
170 xacl.info.sd_hs3->sd->owner_sid,
171 xacl.info.sd_hs3->sd->group_sid,
172 xacl.info.sd_hs3->sd->sacl,
173 xacl.info.sd_hs3->sd->dacl,
174 &sd_size);
175 *p_hash_type = xacl.info.sd_hs3->hash_type;
176 /* Current version 3 (if no sys acl hash available). */
177 memcpy(hash, xacl.info.sd_hs3->hash, XATTR_SD_HASH_SIZE);
178 break;
179 case 4:
180 *ppdesc = make_sec_desc(mem_ctx, SD_REVISION,
181 xacl.info.sd_hs4->sd->type | SEC_DESC_SELF_RELATIVE,
182 xacl.info.sd_hs4->sd->owner_sid,
183 xacl.info.sd_hs4->sd->group_sid,
184 xacl.info.sd_hs4->sd->sacl,
185 xacl.info.sd_hs4->sd->dacl,
186 &sd_size);
187 *p_hash_type = xacl.info.sd_hs4->hash_type;
188 /* Current version 4. */
189 memcpy(hash, xacl.info.sd_hs4->hash, XATTR_SD_HASH_SIZE);
190 memcpy(sys_acl_hash, xacl.info.sd_hs4->sys_acl_hash, XATTR_SD_HASH_SIZE);
191 break;
192 default:
193 TALLOC_FREE(frame);
194 return NT_STATUS_REVISION_MISMATCH;
197 TALLOC_FREE(frame);
199 return (*ppdesc != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
202 /*******************************************************************
203 Create a DATA_BLOB from a hash of the security descriptor storead at
204 the system layer and the NT ACL we wish to preserve
205 *******************************************************************/
207 static NTSTATUS create_acl_blob(const struct security_descriptor *psd,
208 DATA_BLOB *pblob,
209 uint16_t hash_type,
210 uint8_t hash[XATTR_SD_HASH_SIZE])
212 struct xattr_NTACL xacl;
213 struct security_descriptor_hash_v3 sd_hs3;
214 enum ndr_err_code ndr_err;
215 TALLOC_CTX *ctx = talloc_tos();
217 ZERO_STRUCT(xacl);
218 ZERO_STRUCT(sd_hs3);
220 xacl.version = 3;
221 xacl.info.sd_hs3 = &sd_hs3;
222 xacl.info.sd_hs3->sd = discard_const_p(struct security_descriptor, psd);
223 xacl.info.sd_hs3->hash_type = hash_type;
224 memcpy(&xacl.info.sd_hs3->hash[0], hash, XATTR_SD_HASH_SIZE);
226 ndr_err = ndr_push_struct_blob(
227 pblob, ctx, &xacl,
228 (ndr_push_flags_fn_t)ndr_push_xattr_NTACL);
230 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
231 DEBUG(5, ("create_acl_blob: ndr_push_xattr_NTACL failed: %s\n",
232 ndr_errstr(ndr_err)));
233 return ndr_map_error2ntstatus(ndr_err);
236 return NT_STATUS_OK;
239 /*******************************************************************
240 Create a DATA_BLOB from a hash of the security descriptors
241 (system and NT) stored at the system layer and the NT ACL we wish
242 to preserve.
243 *******************************************************************/
245 static NTSTATUS create_sys_acl_blob(const struct security_descriptor *psd,
246 DATA_BLOB *pblob,
247 uint16_t hash_type,
248 uint8_t hash[XATTR_SD_HASH_SIZE],
249 const char *description,
250 uint8_t sys_acl_hash[XATTR_SD_HASH_SIZE])
252 struct xattr_NTACL xacl;
253 struct security_descriptor_hash_v4 sd_hs4;
254 enum ndr_err_code ndr_err;
255 TALLOC_CTX *ctx = talloc_tos();
256 NTTIME nttime_now;
257 struct timeval now = timeval_current();
258 nttime_now = timeval_to_nttime(&now);
260 ZERO_STRUCT(xacl);
261 ZERO_STRUCT(sd_hs4);
263 xacl.version = 4;
264 xacl.info.sd_hs4 = &sd_hs4;
265 xacl.info.sd_hs4->sd = discard_const_p(struct security_descriptor, psd);
266 xacl.info.sd_hs4->hash_type = hash_type;
267 memcpy(&xacl.info.sd_hs4->hash[0], hash, XATTR_SD_HASH_SIZE);
268 xacl.info.sd_hs4->description = description;
269 xacl.info.sd_hs4->time = nttime_now;
270 memcpy(&xacl.info.sd_hs4->sys_acl_hash[0], sys_acl_hash, XATTR_SD_HASH_SIZE);
272 ndr_err = ndr_push_struct_blob(
273 pblob, ctx, &xacl,
274 (ndr_push_flags_fn_t)ndr_push_xattr_NTACL);
276 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
277 DEBUG(5, ("create_acl_blob: ndr_push_xattr_NTACL failed: %s\n",
278 ndr_errstr(ndr_err)));
279 return ndr_map_error2ntstatus(ndr_err);
282 return NT_STATUS_OK;
285 /*******************************************************************
286 Add in 3 inheritable components for a non-inheritable directory ACL.
287 CREATOR_OWNER/CREATOR_GROUP/WORLD.
288 *******************************************************************/
290 static NTSTATUS add_directory_inheritable_components(vfs_handle_struct *handle,
291 const char *name,
292 SMB_STRUCT_STAT *psbuf,
293 struct security_descriptor *psd)
295 struct connection_struct *conn = handle->conn;
296 int num_aces = (psd->dacl ? psd->dacl->num_aces : 0);
297 struct smb_filename smb_fname;
298 enum security_ace_type acltype;
299 uint32_t access_mask;
300 mode_t dir_mode;
301 mode_t file_mode;
302 mode_t mode;
303 struct security_ace *new_ace_list;
305 if (psd->dacl) {
306 new_ace_list = talloc_zero_array(psd->dacl,
307 struct security_ace,
308 num_aces + 3);
309 } else {
311 * make_sec_acl() at the bottom of this function
312 * dupliates new_ace_list
314 new_ace_list = talloc_zero_array(talloc_tos(),
315 struct security_ace,
316 num_aces + 3);
319 if (new_ace_list == NULL) {
320 return NT_STATUS_NO_MEMORY;
323 /* Fake a quick smb_filename. */
324 ZERO_STRUCT(smb_fname);
325 smb_fname.st = *psbuf;
326 smb_fname.base_name = discard_const_p(char, name);
328 dir_mode = unix_mode(conn,
329 FILE_ATTRIBUTE_DIRECTORY, &smb_fname, NULL);
330 file_mode = unix_mode(conn,
331 FILE_ATTRIBUTE_ARCHIVE, &smb_fname, NULL);
333 mode = dir_mode | file_mode;
335 DEBUG(10, ("add_directory_inheritable_components: directory %s, "
336 "mode = 0%o\n",
337 name,
338 (unsigned int)mode ));
340 if (num_aces) {
341 memcpy(new_ace_list, psd->dacl->aces,
342 num_aces * sizeof(struct security_ace));
344 access_mask = map_canon_ace_perms(SNUM(conn), &acltype,
345 mode & 0700, false);
347 init_sec_ace(&new_ace_list[num_aces],
348 &global_sid_Creator_Owner,
349 acltype,
350 access_mask,
351 SEC_ACE_FLAG_CONTAINER_INHERIT|
352 SEC_ACE_FLAG_OBJECT_INHERIT|
353 SEC_ACE_FLAG_INHERIT_ONLY);
354 access_mask = map_canon_ace_perms(SNUM(conn), &acltype,
355 (mode << 3) & 0700, false);
356 init_sec_ace(&new_ace_list[num_aces+1],
357 &global_sid_Creator_Group,
358 acltype,
359 access_mask,
360 SEC_ACE_FLAG_CONTAINER_INHERIT|
361 SEC_ACE_FLAG_OBJECT_INHERIT|
362 SEC_ACE_FLAG_INHERIT_ONLY);
363 access_mask = map_canon_ace_perms(SNUM(conn), &acltype,
364 (mode << 6) & 0700, false);
365 init_sec_ace(&new_ace_list[num_aces+2],
366 &global_sid_World,
367 acltype,
368 access_mask,
369 SEC_ACE_FLAG_CONTAINER_INHERIT|
370 SEC_ACE_FLAG_OBJECT_INHERIT|
371 SEC_ACE_FLAG_INHERIT_ONLY);
372 if (psd->dacl) {
373 psd->dacl->aces = new_ace_list;
374 psd->dacl->num_aces += 3;
375 psd->dacl->size += new_ace_list[num_aces].size +
376 new_ace_list[num_aces+1].size +
377 new_ace_list[num_aces+2].size;
378 } else {
379 psd->dacl = make_sec_acl(psd,
380 NT4_ACL_REVISION,
382 new_ace_list);
383 if (psd->dacl == NULL) {
384 return NT_STATUS_NO_MEMORY;
387 return NT_STATUS_OK;
390 static NTSTATUS make_default_filesystem_acl(TALLOC_CTX *ctx,
391 const char *name,
392 SMB_STRUCT_STAT *psbuf,
393 struct security_descriptor **ppdesc)
395 struct dom_sid owner_sid, group_sid;
396 size_t size = 0;
397 struct security_ace aces[4];
398 uint32_t access_mask = 0;
399 mode_t mode = psbuf->st_ex_mode;
400 struct security_acl *new_dacl = NULL;
401 int idx = 0;
403 DEBUG(10,("make_default_filesystem_acl: file %s mode = 0%o\n",
404 name, (int)mode ));
406 uid_to_sid(&owner_sid, psbuf->st_ex_uid);
407 gid_to_sid(&group_sid, psbuf->st_ex_gid);
410 We provide up to 4 ACEs
411 - Owner
412 - Group
413 - Everyone
414 - NT System
417 if (mode & S_IRUSR) {
418 if (mode & S_IWUSR) {
419 access_mask |= SEC_RIGHTS_FILE_ALL;
420 } else {
421 access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
424 if (mode & S_IWUSR) {
425 access_mask |= SEC_RIGHTS_FILE_WRITE | SEC_STD_DELETE;
428 init_sec_ace(&aces[idx],
429 &owner_sid,
430 SEC_ACE_TYPE_ACCESS_ALLOWED,
431 access_mask,
433 idx++;
435 access_mask = 0;
436 if (mode & S_IRGRP) {
437 access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
439 if (mode & S_IWGRP) {
440 /* note that delete is not granted - this matches posix behaviour */
441 access_mask |= SEC_RIGHTS_FILE_WRITE;
443 if (access_mask) {
444 init_sec_ace(&aces[idx],
445 &group_sid,
446 SEC_ACE_TYPE_ACCESS_ALLOWED,
447 access_mask,
449 idx++;
452 access_mask = 0;
453 if (mode & S_IROTH) {
454 access_mask |= SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
456 if (mode & S_IWOTH) {
457 access_mask |= SEC_RIGHTS_FILE_WRITE;
459 if (access_mask) {
460 init_sec_ace(&aces[idx],
461 &global_sid_World,
462 SEC_ACE_TYPE_ACCESS_ALLOWED,
463 access_mask,
465 idx++;
468 init_sec_ace(&aces[idx],
469 &global_sid_System,
470 SEC_ACE_TYPE_ACCESS_ALLOWED,
471 SEC_RIGHTS_FILE_ALL,
473 idx++;
475 new_dacl = make_sec_acl(ctx,
476 NT4_ACL_REVISION,
477 idx,
478 aces);
480 if (!new_dacl) {
481 return NT_STATUS_NO_MEMORY;
484 *ppdesc = make_sec_desc(ctx,
485 SECURITY_DESCRIPTOR_REVISION_1,
486 SEC_DESC_SELF_RELATIVE|SEC_DESC_DACL_PRESENT,
487 &owner_sid,
488 &group_sid,
489 NULL,
490 new_dacl,
491 &size);
492 if (!*ppdesc) {
493 return NT_STATUS_NO_MEMORY;
495 return NT_STATUS_OK;
499 * Validate an ACL blob
501 * This validates an ACL blob against the underlying filesystem ACL. If this
502 * function returns NT_STATUS_OK ppsd can be
504 * 1. the ACL from the blob (psd_from_fs=false), or
505 * 2. the ACL from the fs (psd_from_fs=true), or
506 * 3. NULL (!)
508 * If the return value is anything else then NT_STATUS_OK, ppsd is set to NULL
509 * and psd_from_fs set to false.
511 * Returning the underlying filesystem ACL in case no. 2 is really just an
512 * optimisation, because some validations have to fetch the filesytem ACL as
513 * part of the validation, so we already have it available and callers might
514 * need it as well.
516 static NTSTATUS validate_nt_acl_blob(TALLOC_CTX *mem_ctx,
517 vfs_handle_struct *handle,
518 files_struct *fsp,
519 const char *name,
520 const DATA_BLOB *blob,
521 struct security_descriptor **ppsd,
522 bool *psd_is_from_fs)
524 NTSTATUS status;
525 uint16_t hash_type = XATTR_SD_HASH_TYPE_NONE;
526 uint16_t xattr_version = 0;
527 uint8_t hash[XATTR_SD_HASH_SIZE];
528 uint8_t sys_acl_hash[XATTR_SD_HASH_SIZE];
529 uint8_t hash_tmp[XATTR_SD_HASH_SIZE];
530 uint8_t sys_acl_hash_tmp[XATTR_SD_HASH_SIZE];
531 struct security_descriptor *psd = NULL;
532 struct security_descriptor *psd_blob = NULL;
533 struct security_descriptor *psd_fs = NULL;
534 char *sys_acl_blob_description = NULL;
535 DATA_BLOB sys_acl_blob = { 0 };
536 struct acl_common_config *config = NULL;
538 *ppsd = NULL;
539 *psd_is_from_fs = false;
541 SMB_VFS_HANDLE_GET_DATA(handle, config,
542 struct acl_common_config,
543 return NT_STATUS_UNSUCCESSFUL);
545 status = parse_acl_blob(blob,
546 mem_ctx,
547 &psd_blob,
548 &hash_type,
549 &xattr_version,
550 &hash[0],
551 &sys_acl_hash[0]);
553 if (!NT_STATUS_IS_OK(status)) {
554 DBG_DEBUG("parse_acl_blob returned %s\n", nt_errstr(status));
555 goto fail;
558 /* determine which type of xattr we got */
559 switch (xattr_version) {
560 case 1:
561 case 2:
562 /* These xattr types are unilatteral, they do not
563 * require confirmation of the hash. In particular,
564 * the NTVFS file server uses version 1, but
565 * 'samba-tool ntacl' can set these as well */
566 *ppsd = psd_blob;
567 return NT_STATUS_OK;
568 case 3:
569 case 4:
570 if (config->ignore_system_acls) {
571 *ppsd = psd_blob;
572 return NT_STATUS_OK;
575 break;
576 default:
577 DBG_DEBUG("ACL blob revision mismatch (%u) for file %s\n",
578 (unsigned int)hash_type, name);
579 TALLOC_FREE(psd_blob);
580 return NT_STATUS_OK;
583 /* determine which type of xattr we got */
584 if (hash_type != XATTR_SD_HASH_TYPE_SHA256) {
585 DBG_DEBUG("ACL blob hash type (%u) unexpected for file %s\n",
586 (unsigned int)hash_type, name);
587 TALLOC_FREE(psd_blob);
588 return NT_STATUS_OK;
591 /* determine which type of xattr we got */
592 switch (xattr_version) {
593 case 4:
595 int ret;
596 if (fsp) {
597 /* Get the full underlying sd, then hash. */
598 ret = SMB_VFS_NEXT_SYS_ACL_BLOB_GET_FD(handle,
599 fsp,
600 mem_ctx,
601 &sys_acl_blob_description,
602 &sys_acl_blob);
603 } else {
604 /* Get the full underlying sd, then hash. */
605 ret = SMB_VFS_NEXT_SYS_ACL_BLOB_GET_FILE(handle,
606 name,
607 mem_ctx,
608 &sys_acl_blob_description,
609 &sys_acl_blob);
612 /* If we fail to get the ACL blob (for some reason) then this
613 * is not fatal, we just work based on the NT ACL only */
614 if (ret == 0) {
615 status = hash_blob_sha256(sys_acl_blob, sys_acl_hash_tmp);
616 if (!NT_STATUS_IS_OK(status)) {
617 goto fail;
620 TALLOC_FREE(sys_acl_blob_description);
621 TALLOC_FREE(sys_acl_blob.data);
623 if (memcmp(&sys_acl_hash[0], &sys_acl_hash_tmp[0],
624 XATTR_SD_HASH_SIZE) == 0) {
625 /* Hash matches, return blob sd. */
626 DBG_DEBUG("blob hash matches for file %s\n",
627 name);
628 *ppsd = psd_blob;
629 return NT_STATUS_OK;
633 /* Otherwise, fall though and see if the NT ACL hash matches */
635 case 3:
636 /* Get the full underlying sd for the hash
637 or to return as backup. */
638 if (fsp) {
639 status = SMB_VFS_NEXT_FGET_NT_ACL(handle,
640 fsp,
641 HASH_SECURITY_INFO,
642 mem_ctx,
643 &psd_fs);
644 } else {
645 status = SMB_VFS_NEXT_GET_NT_ACL(handle,
646 name,
647 HASH_SECURITY_INFO,
648 mem_ctx,
649 &psd_fs);
652 if (!NT_STATUS_IS_OK(status)) {
653 DBG_DEBUG("get_next_acl for file %s returned %s\n",
654 name, nt_errstr(status));
655 goto fail;
658 status = hash_sd_sha256(psd_fs, hash_tmp);
659 if (!NT_STATUS_IS_OK(status)) {
660 TALLOC_FREE(psd_blob);
661 *ppsd = psd_fs;
662 *psd_is_from_fs = true;
663 return NT_STATUS_OK;
666 if (memcmp(&hash[0], &hash_tmp[0], XATTR_SD_HASH_SIZE) == 0) {
667 /* Hash matches, return blob sd. */
668 DBG_DEBUG("blob hash matches for file %s\n", name);
669 *ppsd = psd_blob;
670 return NT_STATUS_OK;
673 /* Hash doesn't match, return underlying sd. */
674 DBG_DEBUG("blob hash does not match for file %s - returning "
675 "file system SD mapping.\n", name);
677 if (DEBUGLEVEL >= 10) {
678 DBG_DEBUG("acl for blob hash for %s is:\n", name);
679 NDR_PRINT_DEBUG(security_descriptor, psd_fs);
682 TALLOC_FREE(psd_blob);
683 *ppsd = psd_fs;
684 *psd_is_from_fs = true;
687 return NT_STATUS_OK;
689 fail:
690 TALLOC_FREE(psd);
691 TALLOC_FREE(psd_blob);
692 TALLOC_FREE(psd_fs);
693 TALLOC_FREE(sys_acl_blob_description);
694 TALLOC_FREE(sys_acl_blob.data);
695 return status;
698 static NTSTATUS stat_fsp_or_name(vfs_handle_struct *handle,
699 files_struct *fsp,
700 const char *name,
701 SMB_STRUCT_STAT *sbuf,
702 SMB_STRUCT_STAT **psbuf)
704 NTSTATUS status;
705 int ret;
707 if (fsp) {
708 status = vfs_stat_fsp(fsp);
709 if (!NT_STATUS_IS_OK(status)) {
710 return status;
712 *psbuf = &fsp->fsp_name->st;
713 } else {
715 * https://bugzilla.samba.org/show_bug.cgi?id=11249
717 * We are currently guaranteed that 'name' here is a
718 * smb_fname->base_name, which *cannot* contain a stream name
719 * (':'). vfs_stat_smb_fname() splits a name into a base name +
720 * stream name, which when we get here we know we've already
721 * done. So we have to call the stat or lstat VFS calls
722 * directly here. Else, a base_name that contains a ':' (from a
723 * demangled name) will get split again.
725 * FIXME.
726 * This uglyness will go away once smb_fname is fully plumbed
727 * through the VFS.
729 ret = vfs_stat_smb_basename(handle->conn,
730 name,
731 sbuf);
732 if (ret == -1) {
733 return map_nt_error_from_unix(errno);
737 return NT_STATUS_OK;
740 /*******************************************************************
741 Pull a DATA_BLOB from an xattr given a pathname.
742 If the hash doesn't match, or doesn't exist - return the underlying
743 filesystem sd.
744 *******************************************************************/
746 static NTSTATUS get_nt_acl_internal(vfs_handle_struct *handle,
747 files_struct *fsp,
748 const char *name,
749 uint32_t security_info,
750 TALLOC_CTX *mem_ctx,
751 struct security_descriptor **ppdesc)
753 DATA_BLOB blob = data_blob_null;
754 NTSTATUS status;
755 struct security_descriptor *psd = NULL;
756 bool psd_is_from_fs = false;
757 struct acl_common_config *config = NULL;
759 SMB_VFS_HANDLE_GET_DATA(handle, config,
760 struct acl_common_config,
761 return NT_STATUS_UNSUCCESSFUL);
763 if (fsp && name == NULL) {
764 name = fsp->fsp_name->base_name;
767 DEBUG(10, ("get_nt_acl_internal: name=%s\n", name));
769 status = get_acl_blob(mem_ctx, handle, fsp, name, &blob);
770 if (NT_STATUS_IS_OK(status)) {
771 status = validate_nt_acl_blob(mem_ctx,
772 handle,
773 fsp,
774 name,
775 &blob,
776 &psd,
777 &psd_is_from_fs);
778 TALLOC_FREE(blob.data);
779 if (!NT_STATUS_IS_OK(status)) {
780 DBG_DEBUG("ACL validation for [%s] failed\n",
781 name);
782 goto fail;
786 if (psd == NULL) {
787 /* Get the full underlying sd, as we failed to get the
788 * blob for the hash, or the revision/hash type wasn't
789 * known */
791 if (config->ignore_system_acls) {
792 SMB_STRUCT_STAT sbuf;
793 SMB_STRUCT_STAT *psbuf = &sbuf;
795 status = stat_fsp_or_name(handle, fsp, name,
796 &sbuf, &psbuf);
797 if (!NT_STATUS_IS_OK(status)) {
798 goto fail;
801 status = make_default_filesystem_acl(
802 mem_ctx,
803 name,
804 psbuf,
805 &psd);
806 if (!NT_STATUS_IS_OK(status)) {
807 goto fail;
809 } else {
810 if (fsp) {
811 status = SMB_VFS_NEXT_FGET_NT_ACL(handle,
812 fsp,
813 security_info,
814 mem_ctx,
815 &psd);
816 } else {
817 status = SMB_VFS_NEXT_GET_NT_ACL(handle,
818 name,
819 security_info,
820 mem_ctx,
821 &psd);
824 if (!NT_STATUS_IS_OK(status)) {
825 DBG_DEBUG("get_next_acl for file %s "
826 "returned %s\n", name,
827 nt_errstr(status));
828 goto fail;
831 psd_is_from_fs = true;
835 if (psd_is_from_fs) {
836 SMB_STRUCT_STAT sbuf;
837 SMB_STRUCT_STAT *psbuf = &sbuf;
838 bool is_directory = false;
841 * We're returning the underlying ACL from the
842 * filesystem. If it's a directory, and has no
843 * inheritable ACE entries we have to fake them.
846 status = stat_fsp_or_name(handle, fsp, name,
847 &sbuf, &psbuf);
848 if (!NT_STATUS_IS_OK(status)) {
849 goto fail;
852 is_directory = S_ISDIR(psbuf->st_ex_mode);
854 if (is_directory && !sd_has_inheritable_components(psd, true)) {
855 status = add_directory_inheritable_components(
856 handle,
857 name,
858 psbuf,
859 psd);
860 if (!NT_STATUS_IS_OK(status)) {
861 goto fail;
866 * The underlying POSIX module always sets the
867 * ~SEC_DESC_DACL_PROTECTED bit, as ACLs can't be inherited in
868 * this way under POSIX. Remove it for Windows-style ACLs.
870 psd->type &= ~SEC_DESC_DACL_PROTECTED;
873 if (!(security_info & SECINFO_OWNER)) {
874 psd->owner_sid = NULL;
876 if (!(security_info & SECINFO_GROUP)) {
877 psd->group_sid = NULL;
879 if (!(security_info & SECINFO_DACL)) {
880 psd->type &= ~SEC_DESC_DACL_PRESENT;
881 psd->dacl = NULL;
883 if (!(security_info & SECINFO_SACL)) {
884 psd->type &= ~SEC_DESC_SACL_PRESENT;
885 psd->sacl = NULL;
888 if (DEBUGLEVEL >= 10) {
889 DEBUG(10,("get_nt_acl_internal: returning acl for %s is:\n",
890 name));
891 NDR_PRINT_DEBUG(security_descriptor, psd);
894 *ppdesc = psd;
896 return NT_STATUS_OK;
898 fail:
899 TALLOC_FREE(psd);
900 return status;
903 /*********************************************************************
904 Fetch a security descriptor given an fsp.
905 *********************************************************************/
907 static NTSTATUS fget_nt_acl_common(vfs_handle_struct *handle,
908 files_struct *fsp,
909 uint32_t security_info,
910 TALLOC_CTX *mem_ctx,
911 struct security_descriptor **ppdesc)
913 return get_nt_acl_internal(handle, fsp,
914 NULL, security_info, mem_ctx, ppdesc);
917 /*********************************************************************
918 Fetch a security descriptor given a pathname.
919 *********************************************************************/
921 static NTSTATUS get_nt_acl_common(vfs_handle_struct *handle,
922 const char *name,
923 uint32_t security_info,
924 TALLOC_CTX *mem_ctx,
925 struct security_descriptor **ppdesc)
927 return get_nt_acl_internal(handle, NULL,
928 name, security_info, mem_ctx, ppdesc);
931 /*********************************************************************
932 Set the underlying ACL (e.g. POSIX ACLS, POSIX owner, etc)
933 *********************************************************************/
934 static NTSTATUS set_underlying_acl(vfs_handle_struct *handle, files_struct *fsp,
935 struct security_descriptor *psd,
936 uint32_t security_info_sent,
937 bool chown_needed)
939 NTSTATUS status =
940 SMB_VFS_NEXT_FSET_NT_ACL(handle, fsp, security_info_sent, psd);
941 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
942 return status;
945 /* We got access denied here. If we're already root,
946 or we didn't need to do a chown, or the fsp isn't
947 open with WRITE_OWNER access, just return. */
948 if (get_current_uid(handle->conn) == 0 || chown_needed == false ||
949 !(fsp->access_mask & SEC_STD_WRITE_OWNER)) {
950 return NT_STATUS_ACCESS_DENIED;
953 DEBUG(10, ("fset_nt_acl_common: overriding chown on file %s "
954 "for sid %s\n",
955 fsp_str_dbg(fsp), sid_string_tos(psd->owner_sid)));
957 /* Ok, we failed to chown and we have
958 SEC_STD_WRITE_OWNER access - override. */
959 become_root();
960 status = SMB_VFS_NEXT_FSET_NT_ACL(handle, fsp, security_info_sent, psd);
961 unbecome_root();
963 return status;
966 /*********************************************************************
967 Store a v3 security descriptor
968 *********************************************************************/
969 static NTSTATUS store_v3_blob(vfs_handle_struct *handle, files_struct *fsp,
970 struct security_descriptor *psd,
971 struct security_descriptor *pdesc_next,
972 uint8_t hash[XATTR_SD_HASH_SIZE])
974 NTSTATUS status;
975 DATA_BLOB blob;
977 if (DEBUGLEVEL >= 10) {
978 DEBUG(10, ("fset_nt_acl_xattr: storing xattr sd for file %s\n",
979 fsp_str_dbg(fsp)));
980 NDR_PRINT_DEBUG(
981 security_descriptor,
982 discard_const_p(struct security_descriptor, psd));
984 if (pdesc_next != NULL) {
985 DEBUG(10, ("fset_nt_acl_xattr: storing has in xattr sd "
986 "based on \n"));
987 NDR_PRINT_DEBUG(
988 security_descriptor,
989 discard_const_p(struct security_descriptor,
990 pdesc_next));
991 } else {
992 DEBUG(10,
993 ("fset_nt_acl_xattr: ignoring underlying sd\n"));
996 status = create_acl_blob(psd, &blob, XATTR_SD_HASH_TYPE_SHA256, hash);
997 if (!NT_STATUS_IS_OK(status)) {
998 DEBUG(10, ("fset_nt_acl_xattr: create_acl_blob failed\n"));
999 return status;
1002 status = store_acl_blob_fsp(handle, fsp, &blob);
1003 return status;
1006 /*********************************************************************
1007 Store a security descriptor given an fsp.
1008 *********************************************************************/
1010 static NTSTATUS fset_nt_acl_common(vfs_handle_struct *handle, files_struct *fsp,
1011 uint32_t security_info_sent, const struct security_descriptor *orig_psd)
1013 NTSTATUS status;
1014 int ret;
1015 DATA_BLOB blob, sys_acl_blob;
1016 struct security_descriptor *pdesc_next = NULL;
1017 struct security_descriptor *psd = NULL;
1018 uint8_t hash[XATTR_SD_HASH_SIZE];
1019 uint8_t sys_acl_hash[XATTR_SD_HASH_SIZE];
1020 bool chown_needed = false;
1021 char *sys_acl_description;
1022 TALLOC_CTX *frame = talloc_stackframe();
1023 bool ignore_file_system_acl = lp_parm_bool(
1024 SNUM(handle->conn), ACL_MODULE_NAME, "ignore system acls", false);
1026 if (DEBUGLEVEL >= 10) {
1027 DEBUG(10,("fset_nt_acl_xattr: incoming sd for file %s\n",
1028 fsp_str_dbg(fsp)));
1029 NDR_PRINT_DEBUG(security_descriptor,
1030 discard_const_p(struct security_descriptor, orig_psd));
1033 status = get_nt_acl_internal(handle, fsp,
1034 NULL,
1035 SECINFO_OWNER|SECINFO_GROUP|SECINFO_DACL|SECINFO_SACL,
1036 frame,
1037 &psd);
1039 if (!NT_STATUS_IS_OK(status)) {
1040 TALLOC_FREE(frame);
1041 return status;
1044 psd->revision = orig_psd->revision;
1045 /* All our SD's are self relative. */
1046 psd->type = orig_psd->type | SEC_DESC_SELF_RELATIVE;
1048 if ((security_info_sent & SECINFO_OWNER) && (orig_psd->owner_sid != NULL)) {
1049 if (!dom_sid_equal(orig_psd->owner_sid, psd->owner_sid)) {
1050 /* We're changing the owner. */
1051 chown_needed = true;
1053 psd->owner_sid = orig_psd->owner_sid;
1055 if ((security_info_sent & SECINFO_GROUP) && (orig_psd->group_sid != NULL)) {
1056 if (!dom_sid_equal(orig_psd->group_sid, psd->group_sid)) {
1057 /* We're changing the group. */
1058 chown_needed = true;
1060 psd->group_sid = orig_psd->group_sid;
1062 if (security_info_sent & SECINFO_DACL) {
1063 if (security_descriptor_with_ms_nfs(orig_psd)) {
1065 * If the sd contains a MS NFS SID, do
1066 * nothing, it's a chmod() request from OS X
1067 * with AAPL context.
1069 TALLOC_FREE(frame);
1070 return NT_STATUS_OK;
1072 psd->dacl = orig_psd->dacl;
1073 psd->type |= SEC_DESC_DACL_PRESENT;
1075 if (security_info_sent & SECINFO_SACL) {
1076 psd->sacl = orig_psd->sacl;
1077 psd->type |= SEC_DESC_SACL_PRESENT;
1080 if (ignore_file_system_acl) {
1081 if (chown_needed) {
1082 /* send only ownership stuff to lower layer */
1083 security_info_sent &= (SECINFO_OWNER | SECINFO_GROUP);
1084 status = set_underlying_acl(handle, fsp, psd,
1085 security_info_sent, true);
1086 if (!NT_STATUS_IS_OK(status)) {
1087 TALLOC_FREE(frame);
1088 return status;
1091 ZERO_ARRAY(hash);
1092 status = store_v3_blob(handle, fsp, psd, NULL, hash);
1094 TALLOC_FREE(frame);
1095 return status;
1098 status = set_underlying_acl(handle, fsp, psd, security_info_sent,
1099 chown_needed);
1100 if (!NT_STATUS_IS_OK(status)) {
1101 TALLOC_FREE(frame);
1102 return status;
1105 /* Get the full underlying sd, then hash. */
1106 status = SMB_VFS_NEXT_FGET_NT_ACL(handle,
1107 fsp,
1108 HASH_SECURITY_INFO,
1109 frame,
1110 &pdesc_next);
1112 if (!NT_STATUS_IS_OK(status)) {
1113 TALLOC_FREE(frame);
1114 return status;
1117 status = hash_sd_sha256(pdesc_next, hash);
1118 if (!NT_STATUS_IS_OK(status)) {
1119 TALLOC_FREE(frame);
1120 return status;
1123 /* Get the full underlying sd, then hash. */
1124 ret = SMB_VFS_NEXT_SYS_ACL_BLOB_GET_FD(handle,
1125 fsp,
1126 frame,
1127 &sys_acl_description,
1128 &sys_acl_blob);
1130 /* If we fail to get the ACL blob (for some reason) then this
1131 * is not fatal, we just work based on the NT ACL only */
1132 if (ret != 0) {
1133 status = store_v3_blob(handle, fsp, psd, pdesc_next, hash);
1135 TALLOC_FREE(frame);
1136 return status;
1139 status = hash_blob_sha256(sys_acl_blob, sys_acl_hash);
1140 if (!NT_STATUS_IS_OK(status)) {
1141 TALLOC_FREE(frame);
1142 return status;
1145 if (DEBUGLEVEL >= 10) {
1146 DEBUG(10,("fset_nt_acl_xattr: storing xattr sd for file %s based on system ACL\n",
1147 fsp_str_dbg(fsp)));
1148 NDR_PRINT_DEBUG(security_descriptor,
1149 discard_const_p(struct security_descriptor, psd));
1151 DEBUG(10,("fset_nt_acl_xattr: storing hash in xattr sd based on system ACL and:\n"));
1152 NDR_PRINT_DEBUG(security_descriptor,
1153 discard_const_p(struct security_descriptor, pdesc_next));
1156 /* We store hashes of both the sys ACL blob and the NT
1157 * security desciptor mapped from that ACL so as to improve
1158 * our chances against some inadvertant change breaking the
1159 * hash used */
1160 status = create_sys_acl_blob(psd, &blob, XATTR_SD_HASH_TYPE_SHA256, hash,
1161 sys_acl_description, sys_acl_hash);
1162 if (!NT_STATUS_IS_OK(status)) {
1163 DEBUG(10, ("fset_nt_acl_xattr: create_sys_acl_blob failed\n"));
1164 TALLOC_FREE(frame);
1165 return status;
1168 status = store_acl_blob_fsp(handle, fsp, &blob);
1170 TALLOC_FREE(frame);
1171 return status;
1174 static int acl_common_remove_object(vfs_handle_struct *handle,
1175 const char *path,
1176 bool is_directory)
1178 connection_struct *conn = handle->conn;
1179 struct file_id id;
1180 files_struct *fsp = NULL;
1181 int ret = 0;
1182 char *parent_dir = NULL;
1183 const char *final_component = NULL;
1184 struct smb_filename local_fname;
1185 int saved_errno = 0;
1186 char *saved_dir = NULL;
1188 saved_dir = vfs_GetWd(talloc_tos(),conn);
1189 if (!saved_dir) {
1190 saved_errno = errno;
1191 goto out;
1194 if (!parent_dirname(talloc_tos(), path,
1195 &parent_dir, &final_component)) {
1196 saved_errno = ENOMEM;
1197 goto out;
1200 DEBUG(10,("acl_common_remove_object: removing %s %s/%s\n",
1201 is_directory ? "directory" : "file",
1202 parent_dir, final_component ));
1204 /* cd into the parent dir to pin it. */
1205 ret = vfs_ChDir(conn, parent_dir);
1206 if (ret == -1) {
1207 saved_errno = errno;
1208 goto out;
1211 ZERO_STRUCT(local_fname);
1212 local_fname.base_name = discard_const_p(char, final_component);
1214 /* Must use lstat here. */
1215 ret = SMB_VFS_LSTAT(conn, &local_fname);
1216 if (ret == -1) {
1217 saved_errno = errno;
1218 goto out;
1221 /* Ensure we have this file open with DELETE access. */
1222 id = vfs_file_id_from_sbuf(conn, &local_fname.st);
1223 for (fsp = file_find_di_first(conn->sconn, id); fsp;
1224 fsp = file_find_di_next(fsp)) {
1225 if (fsp->access_mask & DELETE_ACCESS &&
1226 fsp->delete_on_close) {
1227 /* We did open this for delete,
1228 * allow the delete as root.
1230 break;
1234 if (!fsp) {
1235 DEBUG(10,("acl_common_remove_object: %s %s/%s "
1236 "not an open file\n",
1237 is_directory ? "directory" : "file",
1238 parent_dir, final_component ));
1239 saved_errno = EACCES;
1240 goto out;
1243 become_root();
1244 if (is_directory) {
1245 ret = SMB_VFS_NEXT_RMDIR(handle, final_component);
1246 } else {
1247 ret = SMB_VFS_NEXT_UNLINK(handle, &local_fname);
1249 unbecome_root();
1251 if (ret == -1) {
1252 saved_errno = errno;
1255 out:
1257 TALLOC_FREE(parent_dir);
1259 if (saved_dir) {
1260 vfs_ChDir(conn, saved_dir);
1262 if (saved_errno) {
1263 errno = saved_errno;
1265 return ret;
1268 static int rmdir_acl_common(struct vfs_handle_struct *handle,
1269 const char *path)
1271 int ret;
1273 /* Try the normal rmdir first. */
1274 ret = SMB_VFS_NEXT_RMDIR(handle, path);
1275 if (ret == 0) {
1276 return 0;
1278 if (errno == EACCES || errno == EPERM) {
1279 /* Failed due to access denied,
1280 see if we need to root override. */
1281 return acl_common_remove_object(handle,
1282 path,
1283 true);
1286 DEBUG(10,("rmdir_acl_common: unlink of %s failed %s\n",
1287 path,
1288 strerror(errno) ));
1289 return -1;
1292 static int unlink_acl_common(struct vfs_handle_struct *handle,
1293 const struct smb_filename *smb_fname)
1295 int ret;
1297 /* Try the normal unlink first. */
1298 ret = SMB_VFS_NEXT_UNLINK(handle, smb_fname);
1299 if (ret == 0) {
1300 return 0;
1302 if (errno == EACCES || errno == EPERM) {
1303 /* Failed due to access denied,
1304 see if we need to root override. */
1306 /* Don't do anything fancy for streams. */
1307 if (smb_fname->stream_name) {
1308 return -1;
1310 return acl_common_remove_object(handle,
1311 smb_fname->base_name,
1312 false);
1315 DEBUG(10,("unlink_acl_common: unlink of %s failed %s\n",
1316 smb_fname->base_name,
1317 strerror(errno) ));
1318 return -1;
1321 static int chmod_acl_module_common(struct vfs_handle_struct *handle,
1322 const char *path, mode_t mode)
1324 if (lp_posix_pathnames()) {
1325 /* Only allow this on POSIX pathnames. */
1326 return SMB_VFS_NEXT_CHMOD(handle, path, mode);
1328 return 0;
1331 static int fchmod_acl_module_common(struct vfs_handle_struct *handle,
1332 struct files_struct *fsp, mode_t mode)
1334 if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
1335 /* Only allow this on POSIX opens. */
1336 return SMB_VFS_NEXT_FCHMOD(handle, fsp, mode);
1338 return 0;
1341 static int chmod_acl_acl_module_common(struct vfs_handle_struct *handle,
1342 const char *name, mode_t mode)
1344 if (lp_posix_pathnames()) {
1345 /* Only allow this on POSIX pathnames. */
1346 return SMB_VFS_NEXT_CHMOD_ACL(handle, name, mode);
1348 return 0;
1351 static int fchmod_acl_acl_module_common(struct vfs_handle_struct *handle,
1352 struct files_struct *fsp, mode_t mode)
1354 if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
1355 /* Only allow this on POSIX opens. */
1356 return SMB_VFS_NEXT_FCHMOD_ACL(handle, fsp, mode);
1358 return 0;