2 * Store Windows ACLs in a tdb.
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. */
24 #include "librpc/gen_ndr/xattr.h"
25 #include "librpc/gen_ndr/ndr_xattr.h"
26 #include "../lib/crypto/crypto.h"
29 #define DBGC_CLASS DBGC_VFS
31 static unsigned int ref_count;
32 static struct db_context *acl_db;
34 /*******************************************************************
35 Open acl_db if not already open, increment ref count.
36 *******************************************************************/
38 static bool acl_tdb_init(struct db_context **pp_db)
48 dbname = state_path("file_ntacls.tdb");
56 *pp_db = db_open(NULL, dbname, 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
74 /*******************************************************************
75 Lower ref count and close acl_db if zero.
76 *******************************************************************/
78 static void free_acl_tdb_data(void **pptr)
80 struct db_context **pp_db = (struct db_context **)pptr;
89 /*******************************************************************
90 Fetch_lock the tdb acl record for a file
91 *******************************************************************/
93 static struct db_record *acl_tdb_lock(TALLOC_CTX *mem_ctx,
94 struct db_context *db,
95 const struct file_id *id)
99 /* For backwards compatibility only store the dev/inode. */
100 push_file_id_16((char *)id_buf, id);
101 return db->fetch_locked(db,
103 make_tdb_data(id_buf,
107 /*******************************************************************
108 Delete the tdb acl record for a file
109 *******************************************************************/
111 static NTSTATUS acl_tdb_delete(vfs_handle_struct *handle,
112 struct db_context *db,
113 SMB_STRUCT_STAT *psbuf)
116 struct file_id id = vfs_file_id_from_sbuf(handle->conn, psbuf);
117 struct db_record *rec = acl_tdb_lock(talloc_tos(), db, &id);
120 * If rec == NULL there's not much we can do about it
124 DEBUG(10,("acl_tdb_delete: rec == NULL\n"));
129 status = rec->delete_rec(rec);
134 /*******************************************************************
135 Pull a security descriptor into a DATA_BLOB from a tdb store.
136 *******************************************************************/
138 NTSTATUS get_acl_blob(TALLOC_CTX *ctx,
139 vfs_handle_struct *handle,
147 struct db_context *db;
149 SMB_STRUCT_STAT sbuf;
151 SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context,
152 return NT_STATUS_INTERNAL_DB_CORRUPTION);
154 if (fsp && fsp->fh->fd != -1) {
155 ret = SMB_VFS_FSTAT(fsp, &sbuf);
157 if (fsp && fsp->posix_open) {
158 ret = vfs_lstat_smb_fname(handle->conn, name, &sbuf);
160 ret = vfs_stat_smb_fname(handle->conn, name, &sbuf);
165 return map_nt_error_from_unix(errno);
168 id = vfs_file_id_from_sbuf(handle->conn, &sbuf);
170 /* For backwards compatibility only store the dev/inode. */
171 push_file_id_16((char *)id_buf, &id);
175 make_tdb_data(id_buf, sizeof(id_buf)),
177 return NT_STATUS_INTERNAL_DB_CORRUPTION;
180 pblob->data = data.dptr;
181 pblob->length = data.dsize;
183 DEBUG(10,("get_acl_blob: returned %u bytes from file %s\n",
184 (unsigned int)data.dsize, name ));
186 if (pblob->length == 0 || pblob->data == NULL) {
187 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
192 /*******************************************************************
193 Store a DATA_BLOB into a tdb record given an fsp pointer.
194 *******************************************************************/
196 NTSTATUS store_acl_blob_fsp(vfs_handle_struct *handle,
203 struct db_context *db;
204 struct db_record *rec;
207 DEBUG(10,("store_acl_blob_fsp: storing blob length %u on file %s\n",
208 (unsigned int)pblob->length, fsp_str_dbg(fsp)));
210 SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context,
211 return NT_STATUS_INTERNAL_DB_CORRUPTION);
213 if (fsp->fh->fd != -1) {
214 ret = SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st);
216 if (fsp->posix_open) {
217 ret = SMB_VFS_LSTAT(handle->conn, fsp->fsp_name);
219 ret = SMB_VFS_STAT(handle->conn, fsp->fsp_name);
224 return map_nt_error_from_unix(errno);
227 id = vfs_file_id_from_sbuf(handle->conn, &fsp->fsp_name->st);
229 /* For backwards compatibility only store the dev/inode. */
230 push_file_id_16((char *)id_buf, &id);
231 rec = db->fetch_locked(db, talloc_tos(),
232 make_tdb_data(id_buf,
235 DEBUG(0, ("store_acl_blob_fsp_tdb: fetch_lock failed\n"));
236 return NT_STATUS_INTERNAL_DB_CORRUPTION;
238 data.dptr = pblob->data;
239 data.dsize = pblob->length;
240 return rec->store(rec, data, 0);
243 /*******************************************************************
244 Store a DATA_BLOB into a tdb record given a pathname.
245 *******************************************************************/
247 NTSTATUS store_acl_blob_pathname(vfs_handle_struct *handle,
254 SMB_STRUCT_STAT sbuf;
255 struct db_context *db;
256 struct db_record *rec;
259 DEBUG(10,("store_acl_blob_pathname: storing blob "
260 "length %u on file %s\n",
261 (unsigned int)pblob->length, fname));
263 SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context,
264 return NT_STATUS_INTERNAL_DB_CORRUPTION);
266 if (lp_posix_pathnames()) {
267 ret = vfs_lstat_smb_fname(handle->conn, fname, &sbuf);
269 ret = vfs_stat_smb_fname(handle->conn, fname, &sbuf);
273 return map_nt_error_from_unix(errno);
276 id = vfs_file_id_from_sbuf(handle->conn, &sbuf);
278 /* For backwards compatibility only store the dev/inode. */
279 push_file_id_16((char *)id_buf, &id);
281 rec = db->fetch_locked(db, talloc_tos(),
282 make_tdb_data(id_buf,
285 DEBUG(0, ("store_acl_blob_pathname_tdb: fetch_lock failed\n"));
286 return NT_STATUS_INTERNAL_DB_CORRUPTION;
288 data.dptr = pblob->data;
289 data.dsize = pblob->length;
290 return rec->store(rec, data, 0);
293 /*********************************************************************
294 On unlink we need to delete the tdb record (if using tdb).
295 *********************************************************************/
297 static int unlink_acl_tdb(vfs_handle_struct *handle,
298 const struct smb_filename *smb_fname)
300 struct smb_filename *smb_fname_tmp = NULL;
301 struct db_context *db;
305 SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1);
307 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
308 if (!NT_STATUS_IS_OK(status)) {
309 errno = map_errno_from_nt_status(status);
313 if (lp_posix_pathnames()) {
314 ret = SMB_VFS_LSTAT(handle->conn, smb_fname_tmp);
316 ret = SMB_VFS_STAT(handle->conn, smb_fname_tmp);
323 ret = SMB_VFS_NEXT_UNLINK(handle, smb_fname_tmp);
329 acl_tdb_delete(handle, db, &smb_fname_tmp->st);
334 /*********************************************************************
335 On rmdir we need to delete the tdb record (if using tdb).
336 *********************************************************************/
338 static int rmdir_acl_tdb(vfs_handle_struct *handle, const char *path)
341 SMB_STRUCT_STAT sbuf;
342 struct db_context *db;
345 SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1);
347 if (lp_posix_pathnames()) {
348 ret = vfs_lstat_smb_fname(handle->conn, path, &sbuf);
350 ret = vfs_stat_smb_fname(handle->conn, path, &sbuf);
357 ret = SMB_VFS_NEXT_RMDIR(handle, path);
362 acl_tdb_delete(handle, db, &sbuf);
366 /*******************************************************************
367 Handle opening the storage tdb if so configured.
368 *******************************************************************/
370 static int connect_acl_tdb(struct vfs_handle_struct *handle,
374 struct db_context *db;
377 res = SMB_VFS_NEXT_CONNECT(handle, service, user);
382 if (!acl_tdb_init(&db)) {
383 SMB_VFS_NEXT_DISCONNECT(handle);
387 SMB_VFS_HANDLE_SET_DATA(handle, db, free_acl_tdb_data,
388 struct db_context, return -1);
393 /*********************************************************************
394 Remove a Windows ACL - we're setting the underlying POSIX ACL.
395 *********************************************************************/
397 static int sys_acl_set_file_tdb(vfs_handle_struct *handle,
402 SMB_STRUCT_STAT sbuf;
403 struct db_context *db;
406 SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1);
408 if (lp_posix_pathnames()) {
409 ret = vfs_lstat_smb_fname(handle->conn, path, &sbuf);
411 ret = vfs_stat_smb_fname(handle->conn, path, &sbuf);
418 ret = SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle,
426 acl_tdb_delete(handle, db, &sbuf);
430 /*********************************************************************
431 Remove a Windows ACL - we're setting the underlying POSIX ACL.
432 *********************************************************************/
434 static int sys_acl_set_fd_tdb(vfs_handle_struct *handle,
438 struct db_context *db;
441 SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1);
443 if (fsp->is_directory || fsp->fh->fd == -1) {
444 if (fsp->posix_open) {
445 ret = SMB_VFS_LSTAT(fsp->conn, fsp->fsp_name);
447 ret = SMB_VFS_STAT(fsp->conn, fsp->fsp_name);
450 ret = SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st);
456 ret = SMB_VFS_NEXT_SYS_ACL_SET_FD(handle,
463 acl_tdb_delete(handle, db, &fsp->fsp_name->st);
467 static struct vfs_fn_pointers vfs_acl_tdb_fns = {
468 .connect_fn = connect_acl_tdb,
469 .mkdir = mkdir_acl_common,
470 .open = open_acl_common,
471 .unlink = unlink_acl_tdb,
472 .rmdir = rmdir_acl_tdb,
473 .fget_nt_acl = fget_nt_acl_common,
474 .get_nt_acl = get_nt_acl_common,
475 .fset_nt_acl = fset_nt_acl_common,
476 .sys_acl_set_file = sys_acl_set_file_tdb,
477 .sys_acl_set_fd = sys_acl_set_fd_tdb
480 NTSTATUS vfs_acl_tdb_init(void)
482 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "acl_tdb",