[s3]vfs_acl_tdb: fix the build.
[Samba/gebeck_regimport.git] / source3 / modules / vfs_acl_tdb.c
blob202c1a84698334278bb8df0f90cdd59111da11ae
1 /*
2 * Store Windows ACLs in xattrs, or a tdb if configured that way.
4 * Copyright (C) Volker Lendecke, 2008
5 * Copyright (C) Jeremy Allison, 2008
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see <http://www.gnu.org/licenses/>.
21 /* NOTE: This is an experimental module, not yet finished. JRA. */
23 #include "includes.h"
24 #include "librpc/gen_ndr/xattr.h"
25 #include "librpc/gen_ndr/ndr_xattr.h"
27 #undef DBGC_CLASS
28 #define DBGC_CLASS DBGC_VFS
30 static unsigned int ref_count;
31 static struct db_context *acl_db;
33 /*******************************************************************
34 Open acl_db if not already open, increment ref count.
35 *******************************************************************/
37 static bool acl_tdb_init(struct db_context **pp_db)
39 const char *dbname;
41 if (acl_db) {
42 *pp_db = acl_db;
43 ref_count++;
44 return true;
47 dbname = lock_path("file_ntacls.tdb");
49 if (dbname == NULL) {
50 errno = ENOSYS;
51 return false;
54 become_root();
55 *pp_db = db_open(NULL, dbname, 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
56 unbecome_root();
58 if (*pp_db == NULL) {
59 #if defined(ENOTSUP)
60 errno = ENOTSUP;
61 #else
62 errno = ENOSYS;
63 #endif
64 return false;
67 ref_count++;
68 return true;
71 /*******************************************************************
72 Lower ref count and close acl_db if zero.
73 *******************************************************************/
75 static void free_acl_xattr_data(void **pptr)
77 struct db_context **pp_db = (struct db_context **)pptr;
79 ref_count--;
80 if (ref_count == 0) {
81 TALLOC_FREE(*pp_db);
82 acl_db = NULL;
86 /*******************************************************************
87 Fetch_lock the tdb acl record for a file
88 *******************************************************************/
90 static struct db_record *acl_xattr_tdb_lock(TALLOC_CTX *mem_ctx,
91 struct db_context *db,
92 const struct file_id *id)
94 uint8 id_buf[16];
95 push_file_id_16((char *)id_buf, id);
96 return db->fetch_locked(db,
97 mem_ctx,
98 make_tdb_data(id_buf,
99 sizeof(id_buf)));
102 /*******************************************************************
103 Parse out a struct security_descriptor from a DATA_BLOB.
104 *******************************************************************/
106 static NTSTATUS parse_acl_blob(const DATA_BLOB *pblob,
107 uint32 security_info,
108 struct security_descriptor **ppdesc)
110 TALLOC_CTX *ctx = talloc_tos();
111 struct xattr_NTACL xacl;
112 enum ndr_err_code ndr_err;
113 size_t sd_size;
115 ndr_err = ndr_pull_struct_blob(pblob, ctx, NULL, &xacl,
116 (ndr_pull_flags_fn_t)ndr_pull_xattr_NTACL);
118 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
119 DEBUG(5, ("parse_acl_blob: ndr_pull_xattr_NTACL failed: %s\n",
120 ndr_errstr(ndr_err)));
121 return ndr_map_error2ntstatus(ndr_err);;
124 if (xacl.version != 2) {
125 return NT_STATUS_REVISION_MISMATCH;
128 *ppdesc = make_sec_desc(ctx, SEC_DESC_REVISION, xacl.info.sd_ts->sd->type | SEC_DESC_SELF_RELATIVE,
129 (security_info & OWNER_SECURITY_INFORMATION)
130 ? xacl.info.sd_ts->sd->owner_sid : NULL,
131 (security_info & GROUP_SECURITY_INFORMATION)
132 ? xacl.info.sd_ts->sd->group_sid : NULL,
133 (security_info & SACL_SECURITY_INFORMATION)
134 ? xacl.info.sd_ts->sd->sacl : NULL,
135 (security_info & DACL_SECURITY_INFORMATION)
136 ? xacl.info.sd_ts->sd->dacl : NULL,
137 &sd_size);
139 TALLOC_FREE(xacl.info.sd);
141 return (*ppdesc != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
144 /*******************************************************************
145 Pull a security descriptor into a DATA_BLOB from a tdb store.
146 *******************************************************************/
148 static NTSTATUS get_acl_blob(TALLOC_CTX *ctx,
149 vfs_handle_struct *handle,
150 files_struct *fsp,
151 const char *name,
152 DATA_BLOB *pblob)
154 uint8 id_buf[16];
155 TDB_DATA data;
156 struct file_id id;
157 struct db_context *db;
158 SMB_STRUCT_STAT sbuf;
160 SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context,
161 return NT_STATUS_INTERNAL_DB_CORRUPTION);
163 if (fsp && fsp->fh->fd != -1) {
164 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
165 return map_nt_error_from_unix(errno);
167 } else {
168 if (SMB_VFS_STAT(handle->conn, name, &sbuf) == -1) {
169 return map_nt_error_from_unix(errno);
172 id = vfs_file_id_from_sbuf(handle->conn, &sbuf);
174 push_file_id_16((char *)id_buf, &id);
176 if (db->fetch(db,
177 ctx,
178 make_tdb_data(id_buf, sizeof(id_buf)),
179 &data) == -1) {
180 return NT_STATUS_INTERNAL_DB_CORRUPTION;
183 pblob->data = data.dptr;
184 pblob->length = data.dsize;
186 DEBUG(10,("get_acl_blob: returned %u bytes from file %s\n",
187 (unsigned int)data.dsize, name ));
189 if (pblob->length == 0 || pblob->data == NULL) {
190 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
192 return NT_STATUS_OK;
195 /*******************************************************************
196 Create a DATA_BLOB from a security descriptor.
197 *******************************************************************/
199 static NTSTATUS create_acl_blob(const struct security_descriptor *psd, DATA_BLOB *pblob)
201 struct xattr_NTACL xacl;
202 struct security_descriptor_timestamp sd_ts;
203 enum ndr_err_code ndr_err;
204 TALLOC_CTX *ctx = talloc_tos();
205 struct timespec curr = timespec_current();
207 ZERO_STRUCT(xacl);
208 ZERO_STRUCT(sd_ts);
210 /* Horrid hack as setting an xattr changes the ctime
211 * on Linux. This gives a race of 1 second during
212 * which we would not see a POSIX ACL set.
214 curr.tv_sec += 1;
216 xacl.version = 2;
217 xacl.info.sd_ts = &sd_ts;
218 xacl.info.sd_ts->sd = CONST_DISCARD(struct security_descriptor *, psd);
219 unix_timespec_to_nt_time(&xacl.info.sd_ts->last_changed, curr);
221 DEBUG(10, ("create_acl_blob: timestamp stored as %s\n",
222 timestring(ctx, curr.tv_sec) ));
224 ndr_err = ndr_push_struct_blob(
225 pblob, ctx, NULL, &xacl,
226 (ndr_push_flags_fn_t)ndr_push_xattr_NTACL);
228 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
229 DEBUG(5, ("create_acl_blob: ndr_push_xattr_NTACL failed: %s\n",
230 ndr_errstr(ndr_err)));
231 return ndr_map_error2ntstatus(ndr_err);;
234 return NT_STATUS_OK;
237 /*******************************************************************
238 Store a DATA_BLOB into a tdb record given an fsp pointer.
239 *******************************************************************/
241 static NTSTATUS store_acl_blob_fsp(vfs_handle_struct *handle,
242 files_struct *fsp,
243 DATA_BLOB *pblob)
245 uint8 id_buf[16];
246 struct file_id id;
247 SMB_STRUCT_STAT sbuf;
248 TDB_DATA data;
249 struct db_context *db;
250 struct db_record *rec;
252 DEBUG(10,("store_acl_blob_fsp: storing blob length %u on file %s\n",
253 (unsigned int)pblob->length, fsp->fsp_name));
255 SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context,
256 return NT_STATUS_INTERNAL_DB_CORRUPTION);
258 if (fsp->fh->fd != -1) {
259 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
260 return map_nt_error_from_unix(errno);
262 } else {
263 if (SMB_VFS_STAT(handle->conn, fsp->fsp_name, &sbuf) == -1) {
264 return map_nt_error_from_unix(errno);
267 id = vfs_file_id_from_sbuf(handle->conn, &sbuf);
269 push_file_id_16((char *)id_buf, &id);
270 rec = db->fetch_locked(db, talloc_tos(),
271 make_tdb_data(id_buf,
272 sizeof(id_buf)));
273 if (rec == NULL) {
274 DEBUG(0, ("store_acl_blob_fsp_tdb: fetch_lock failed\n"));
275 return NT_STATUS_INTERNAL_DB_CORRUPTION;
277 data.dptr = pblob->data;
278 data.dsize = pblob->length;
279 return rec->store(rec, data, 0);
282 /*******************************************************************
283 Store a DATA_BLOB into a tdb record given a pathname.
284 *******************************************************************/
286 static NTSTATUS store_acl_blob_pathname(vfs_handle_struct *handle,
287 const char *fname,
288 DATA_BLOB *pblob)
290 uint8 id_buf[16];
291 struct file_id id;
292 TDB_DATA data;
293 SMB_STRUCT_STAT sbuf;
294 struct db_context *db;
295 struct db_record *rec;
297 DEBUG(10,("store_acl_blob_pathname: storing blob "
298 "length %u on file %s\n",
299 (unsigned int)pblob->length, fname));
301 SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context,
302 return NT_STATUS_INTERNAL_DB_CORRUPTION);
304 if (SMB_VFS_STAT(handle->conn, fname, &sbuf) == -1) {
305 return map_nt_error_from_unix(errno);
308 id = vfs_file_id_from_sbuf(handle->conn, &sbuf);
309 push_file_id_16((char *)id_buf, &id);
311 rec = db->fetch_locked(db, talloc_tos(),
312 make_tdb_data(id_buf,
313 sizeof(id_buf)));
314 if (rec == NULL) {
315 DEBUG(0, ("store_acl_blob_pathname_tdb: fetch_lock failed\n"));
316 return NT_STATUS_INTERNAL_DB_CORRUPTION;
318 data.dptr = pblob->data;
319 data.dsize = pblob->length;
320 return rec->store(rec, data, 0);
323 /*******************************************************************
324 Store a DATA_BLOB into an xattr given a pathname.
325 *******************************************************************/
327 static NTSTATUS get_nt_acl_xattr_internal(vfs_handle_struct *handle,
328 files_struct *fsp,
329 const char *name,
330 uint32 security_info,
331 struct security_descriptor **ppdesc)
333 TALLOC_CTX *ctx = talloc_tos();
334 DATA_BLOB blob;
335 NTSTATUS status;
337 if (fsp && name == NULL) {
338 name = fsp->fsp_name;
341 DEBUG(10, ("get_nt_acl_xattr_internal: name=%s\n", name));
343 status = get_acl_blob(ctx, handle, fsp, name, &blob);
344 if (!NT_STATUS_IS_OK(status)) {
345 DEBUG(10, ("get_acl_blob returned %s\n", nt_errstr(status)));
346 return status;
349 status = parse_acl_blob(&blob, security_info, ppdesc);
350 if (!NT_STATUS_IS_OK(status)) {
351 DEBUG(10, ("parse_acl_blob returned %s\n",
352 nt_errstr(status)));
353 return status;
356 TALLOC_FREE(blob.data);
357 return status;
360 /*********************************************************************
361 Create a default security descriptor for a file in case no inheritance
362 exists. All permissions to the owner and SYSTEM.
363 *********************************************************************/
365 static struct security_descriptor *default_file_sd(TALLOC_CTX *mem_ctx,
366 SMB_STRUCT_STAT *psbuf)
368 struct dom_sid owner_sid, group_sid;
369 size_t sd_size;
370 struct security_ace *pace = NULL;
371 struct security_acl *pacl = NULL;
373 uid_to_sid(&owner_sid, psbuf->st_uid);
374 gid_to_sid(&group_sid, psbuf->st_gid);
376 pace = TALLOC_ARRAY(mem_ctx, struct security_ace, 2);
377 if (!pace) {
378 return NULL;
381 init_sec_ace(&pace[0], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
382 SEC_RIGHTS_FILE_ALL, 0);
383 init_sec_ace(&pace[1], &global_sid_System, SEC_ACE_TYPE_ACCESS_ALLOWED,
384 SEC_RIGHTS_FILE_ALL, 0);
386 pacl = make_sec_acl(mem_ctx,
387 NT4_ACL_REVISION,
389 pace);
390 if (!pacl) {
391 return NULL;
393 return make_sec_desc(mem_ctx,
394 SECURITY_DESCRIPTOR_REVISION_1,
395 SEC_DESC_SELF_RELATIVE|SEC_DESC_DACL_PRESENT,
396 &owner_sid,
397 &group_sid,
398 NULL,
399 pacl,
400 &sd_size);
403 /*********************************************************************
404 *********************************************************************/
406 static NTSTATUS inherit_new_acl(vfs_handle_struct *handle,
407 const char *fname,
408 files_struct *fsp,
409 bool container)
411 TALLOC_CTX *ctx = talloc_tos();
412 NTSTATUS status;
413 struct security_descriptor *parent_desc = NULL;
414 struct security_descriptor *psd = NULL;
415 DATA_BLOB blob;
416 size_t size;
417 char *parent_name;
419 if (!parent_dirname_talloc(ctx,
420 fname,
421 &parent_name,
422 NULL)) {
423 return NT_STATUS_NO_MEMORY;
426 DEBUG(10,("inherit_new_acl: check directory %s\n",
427 parent_name));
429 status = get_nt_acl_xattr_internal(handle,
430 NULL,
431 parent_name,
432 (OWNER_SECURITY_INFORMATION |
433 GROUP_SECURITY_INFORMATION |
434 DACL_SECURITY_INFORMATION),
435 &parent_desc);
436 if (NT_STATUS_IS_OK(status)) {
437 /* Create an inherited descriptor from the parent. */
439 if (DEBUGLEVEL >= 10) {
440 DEBUG(10,("inherit_new_acl: parent acl is:\n"));
441 NDR_PRINT_DEBUG(security_descriptor, parent_desc);
444 status = se_create_child_secdesc(ctx,
445 &psd,
446 &size,
447 parent_desc,
448 &handle->conn->server_info->ptok->user_sids[PRIMARY_USER_SID_INDEX],
449 &handle->conn->server_info->ptok->user_sids[PRIMARY_GROUP_SID_INDEX],
450 container);
451 if (!NT_STATUS_IS_OK(status)) {
452 return status;
455 if (DEBUGLEVEL >= 10) {
456 DEBUG(10,("inherit_new_acl: child acl is:\n"));
457 NDR_PRINT_DEBUG(security_descriptor, psd);
460 } else {
461 DEBUG(10,("inherit_new_acl: directory %s failed "
462 "to get acl %s\n",
463 parent_name,
464 nt_errstr(status) ));
467 if (!psd || psd->dacl == NULL) {
468 SMB_STRUCT_STAT sbuf;
469 int ret;
471 TALLOC_FREE(psd);
472 if (fsp && !fsp->is_directory && fsp->fh->fd != -1) {
473 ret = SMB_VFS_FSTAT(fsp, &sbuf);
474 } else {
475 ret = SMB_VFS_STAT(handle->conn,fname, &sbuf);
477 if (ret == -1) {
478 return map_nt_error_from_unix(errno);
480 psd = default_file_sd(ctx, &sbuf);
481 if (!psd) {
482 return NT_STATUS_NO_MEMORY;
485 if (DEBUGLEVEL >= 10) {
486 DEBUG(10,("inherit_new_acl: default acl is:\n"));
487 NDR_PRINT_DEBUG(security_descriptor, psd);
491 status = create_acl_blob(psd, &blob);
492 if (!NT_STATUS_IS_OK(status)) {
493 return status;
495 if (fsp) {
496 return store_acl_blob_fsp(handle, fsp, &blob);
497 } else {
498 return store_acl_blob_pathname(handle, fname, &blob);
502 /*********************************************************************
503 Check ACL on open. For new files inherit from parent directory.
504 *********************************************************************/
506 static int open_acl_xattr(vfs_handle_struct *handle,
507 const char *fname,
508 files_struct *fsp,
509 int flags,
510 mode_t mode)
512 uint32_t access_granted = 0;
513 struct security_descriptor *pdesc = NULL;
514 bool file_existed = true;
515 NTSTATUS status = get_nt_acl_xattr_internal(handle,
516 NULL,
517 fname,
518 (OWNER_SECURITY_INFORMATION |
519 GROUP_SECURITY_INFORMATION |
520 DACL_SECURITY_INFORMATION),
521 &pdesc);
522 if (NT_STATUS_IS_OK(status)) {
523 /* See if we can access it. */
524 status = smb1_file_se_access_check(pdesc,
525 handle->conn->server_info->ptok,
526 fsp->access_mask,
527 &access_granted);
528 if (!NT_STATUS_IS_OK(status)) {
529 DEBUG(10,("open_acl_xattr: file %s open "
530 "refused with error %s\n",
531 fname,
532 nt_errstr(status) ));
533 errno = map_errno_from_nt_status(status);
534 return -1;
536 } else if (NT_STATUS_EQUAL(status,NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
537 file_existed = false;
540 DEBUG(10,("open_acl_xattr: get_nt_acl_attr_internal for "
541 "file %s returned %s\n",
542 fname,
543 nt_errstr(status) ));
545 fsp->fh->fd = SMB_VFS_NEXT_OPEN(handle, fname, fsp, flags, mode);
547 if (!file_existed && fsp->fh->fd != -1) {
548 /* File was created. Inherit from parent directory. */
549 string_set(&fsp->fsp_name, fname);
550 inherit_new_acl(handle, fname, fsp, false);
553 return fsp->fh->fd;
556 /*********************************************************************
557 On unlink we need to delete the tdb record (if using tdb).
558 *********************************************************************/
560 static int unlink_acl_xattr(vfs_handle_struct *handle, const char *path)
562 SMB_STRUCT_STAT sbuf;
563 struct file_id id;
564 struct db_context *db;
565 struct db_record *rec;
566 int ret;
568 SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1);
570 if (SMB_VFS_STAT(handle->conn, path, &sbuf) == -1) {
571 return -1;
574 ret = SMB_VFS_NEXT_UNLINK(handle, path);
576 if (ret == -1) {
577 return -1;
580 id = vfs_file_id_from_sbuf(handle->conn, &sbuf);
582 rec = acl_xattr_tdb_lock(talloc_tos(), db, &id);
585 * If rec == NULL there's not much we can do about it
588 if (rec == NULL) {
589 DEBUG(10,("unlink_acl_xattr: path %s rec == NULL\n",
590 path ));
591 TALLOC_FREE(rec);
592 return 0;
595 rec->delete_rec(rec);
596 TALLOC_FREE(rec);
598 return 0;
601 /*********************************************************************
602 Store an inherited SD on mkdir.
603 *********************************************************************/
605 static int mkdir_acl_xattr(vfs_handle_struct *handle, const char *path, mode_t mode)
607 int ret = SMB_VFS_NEXT_MKDIR(handle, path, mode);
609 if (ret == -1) {
610 return ret;
612 /* New directory - inherit from parent. */
613 inherit_new_acl(handle, path, NULL, true);
614 return ret;
617 /*********************************************************************
618 On rmdir we need to delete the tdb record (if using tdb).
619 *********************************************************************/
621 static int rmdir_acl_xattr(vfs_handle_struct *handle, const char *path)
623 SMB_STRUCT_STAT sbuf;
624 struct file_id id;
625 struct db_context *db;
626 struct db_record *rec;
627 int ret;
629 SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1);
631 if (SMB_VFS_STAT(handle->conn, path, &sbuf) == -1) {
632 return -1;
635 ret = SMB_VFS_NEXT_RMDIR(handle, path);
637 if (ret == -1) {
638 return -1;
641 id = vfs_file_id_from_sbuf(handle->conn, &sbuf);
643 rec = acl_xattr_tdb_lock(talloc_tos(), db, &id);
646 * If rec == NULL there's not much we can do about it
649 if (rec == NULL) {
650 DEBUG(10,("rmdir_acl_xattr: path %s rec == NULL\n",
651 path ));
652 TALLOC_FREE(rec);
653 return 0;
656 rec->delete_rec(rec);
657 TALLOC_FREE(rec);
659 return 0;
662 /*********************************************************************
663 Fetch a security descriptor given an fsp.
664 *********************************************************************/
666 static NTSTATUS fget_nt_acl_xattr(vfs_handle_struct *handle, files_struct *fsp,
667 uint32 security_info, struct security_descriptor **ppdesc)
669 NTSTATUS status = get_nt_acl_xattr_internal(handle, fsp,
670 NULL, security_info, ppdesc);
671 if (NT_STATUS_IS_OK(status)) {
672 if (DEBUGLEVEL >= 10) {
673 DEBUG(10,("fget_nt_acl_xattr: returning xattr sd for file %s\n",
674 fsp->fsp_name));
675 NDR_PRINT_DEBUG(security_descriptor, *ppdesc);
677 return NT_STATUS_OK;
680 DEBUG(10,("fget_nt_acl_xattr: failed to get xattr sd for file %s, Error %s\n",
681 fsp->fsp_name,
682 nt_errstr(status) ));
684 return SMB_VFS_NEXT_FGET_NT_ACL(handle, fsp,
685 security_info, ppdesc);
688 /*********************************************************************
689 Fetch a security descriptor given a pathname.
690 *********************************************************************/
692 static NTSTATUS get_nt_acl_xattr(vfs_handle_struct *handle,
693 const char *name, uint32 security_info, struct security_descriptor **ppdesc)
695 NTSTATUS status = get_nt_acl_xattr_internal(handle, NULL,
696 name, security_info, ppdesc);
697 if (NT_STATUS_IS_OK(status)) {
698 if (DEBUGLEVEL >= 10) {
699 DEBUG(10,("get_nt_acl_xattr: returning xattr sd for file %s\n",
700 name));
701 NDR_PRINT_DEBUG(security_descriptor, *ppdesc);
703 return NT_STATUS_OK;
706 DEBUG(10,("get_nt_acl_xattr: failed to get xattr sd for file %s, Error %s\n",
707 name,
708 nt_errstr(status) ));
710 return SMB_VFS_NEXT_GET_NT_ACL(handle, name,
711 security_info, ppdesc);
714 /*********************************************************************
715 Store a security descriptor given an fsp.
716 *********************************************************************/
718 static NTSTATUS fset_nt_acl_xattr(vfs_handle_struct *handle, files_struct *fsp,
719 uint32 security_info_sent, const struct security_descriptor *psd)
721 NTSTATUS status;
722 DATA_BLOB blob;
724 if (DEBUGLEVEL >= 10) {
725 DEBUG(10,("fset_nt_acl_xattr: incoming sd for file %s\n",
726 fsp->fsp_name));
727 NDR_PRINT_DEBUG(security_descriptor,
728 CONST_DISCARD(struct security_descriptor *,psd));
731 status = SMB_VFS_NEXT_FSET_NT_ACL(handle, fsp, security_info_sent, psd);
732 if (!NT_STATUS_IS_OK(status)) {
733 return status;
736 /* Ensure owner and group are set. */
737 if (!psd->owner_sid || !psd->group_sid) {
738 int ret;
739 SMB_STRUCT_STAT sbuf;
740 DOM_SID owner_sid, group_sid;
741 struct security_descriptor *nc_psd = dup_sec_desc(talloc_tos(), psd);
743 if (!nc_psd) {
744 return NT_STATUS_OK;
746 if (fsp->is_directory || fsp->fh->fd == -1) {
747 ret = SMB_VFS_STAT(fsp->conn,fsp->fsp_name, &sbuf);
748 } else {
749 ret = SMB_VFS_FSTAT(fsp, &sbuf);
751 if (ret == -1) {
752 /* Lower level acl set succeeded,
753 * so still return OK. */
754 return NT_STATUS_OK;
756 create_file_sids(&sbuf, &owner_sid, &group_sid);
757 /* This is safe as nc_psd is discarded at fn exit. */
758 nc_psd->owner_sid = &owner_sid;
759 nc_psd->group_sid = &group_sid;
760 security_info_sent |= (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION);
761 psd = nc_psd;
764 if ((security_info_sent & DACL_SECURITY_INFORMATION) &&
765 psd->dacl != NULL &&
766 (psd->type & (SE_DESC_DACL_AUTO_INHERITED|
767 SE_DESC_DACL_AUTO_INHERIT_REQ))==
768 (SE_DESC_DACL_AUTO_INHERITED|
769 SE_DESC_DACL_AUTO_INHERIT_REQ) ) {
770 struct security_descriptor *new_psd = NULL;
771 status = append_parent_acl(fsp, psd, &new_psd);
772 if (!NT_STATUS_IS_OK(status)) {
773 /* Lower level acl set succeeded,
774 * so still return OK. */
775 return NT_STATUS_OK;
777 psd = new_psd;
780 if (DEBUGLEVEL >= 10) {
781 DEBUG(10,("fset_nt_acl_xattr: storing xattr sd for file %s\n",
782 fsp->fsp_name));
783 NDR_PRINT_DEBUG(security_descriptor,
784 CONST_DISCARD(struct security_descriptor *,psd));
786 create_acl_blob(psd, &blob);
787 store_acl_blob_fsp(handle, fsp, &blob);
789 return NT_STATUS_OK;
792 /*******************************************************************
793 Handle opening the storage tdb if so configured.
794 *******************************************************************/
796 static int connect_acl_xattr(struct vfs_handle_struct *handle,
797 const char *service,
798 const char *user)
800 struct db_context *db;
801 int res;
803 res = SMB_VFS_NEXT_CONNECT(handle, service, user);
804 if (res < 0) {
805 return res;
808 if (!acl_tdb_init(&db)) {
809 SMB_VFS_NEXT_DISCONNECT(handle);
810 return -1;
813 SMB_VFS_HANDLE_SET_DATA(handle, db, free_acl_xattr_data,
814 struct db_context, return -1);
816 return 0;
819 /* VFS operations structure */
821 static vfs_op_tuple skel_op_tuples[] =
823 {SMB_VFS_OP(connect_acl_xattr), SMB_VFS_OP_CONNECT, SMB_VFS_LAYER_TRANSPARENT},
825 {SMB_VFS_OP(mkdir_acl_xattr), SMB_VFS_OP_MKDIR, SMB_VFS_LAYER_TRANSPARENT},
826 {SMB_VFS_OP(rmdir_acl_xattr), SMB_VFS_OP_RMDIR, SMB_VFS_LAYER_TRANSPARENT},
828 {SMB_VFS_OP(open_acl_xattr), SMB_VFS_OP_OPEN, SMB_VFS_LAYER_TRANSPARENT},
829 {SMB_VFS_OP(unlink_acl_xattr), SMB_VFS_OP_UNLINK, SMB_VFS_LAYER_TRANSPARENT},
831 /* NT File ACL operations */
833 {SMB_VFS_OP(fget_nt_acl_xattr),SMB_VFS_OP_FGET_NT_ACL,SMB_VFS_LAYER_TRANSPARENT},
834 {SMB_VFS_OP(get_nt_acl_xattr), SMB_VFS_OP_GET_NT_ACL, SMB_VFS_LAYER_TRANSPARENT},
835 {SMB_VFS_OP(fset_nt_acl_xattr),SMB_VFS_OP_FSET_NT_ACL,SMB_VFS_LAYER_TRANSPARENT},
837 {SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP}
840 NTSTATUS vfs_acl_xattr_init(void)
842 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "acl_tdb", skel_op_tuples);