LCOV - code coverage report
Current view: top level - source3/modules - vfs_acl_tdb.c (source / functions) Hit Total Coverage
Test: coverage report for master 98b443d9 Lines: 2 134 1.5 %
Date: 2024-05-31 13:13:24 Functions: 1 11 9.1 %

          Line data    Source code
       1             : /*
       2             :  * Store Windows ACLs in a tdb.
       3             :  *
       4             :  * Copyright (C) Volker Lendecke, 2008
       5             :  * Copyright (C) Jeremy Allison, 2008
       6             :  *
       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.
      11             :  *
      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.
      16             :  *
      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/>.
      19             :  */
      20             : 
      21             : #include "includes.h"
      22             : #include "smbd/smbd.h"
      23             : #include "system/filesys.h"
      24             : #include "librpc/gen_ndr/xattr.h"
      25             : #include "dbwrap/dbwrap.h"
      26             : #include "dbwrap/dbwrap_open.h"
      27             : #include "auth.h"
      28             : #include "util_tdb.h"
      29             : #include "vfs_acl_common.h"
      30             : 
      31             : #undef DBGC_CLASS
      32             : #define DBGC_CLASS DBGC_VFS
      33             : 
      34             : #define ACL_MODULE_NAME "acl_tdb"
      35             : 
      36             : static unsigned int ref_count;
      37             : static struct db_context *acl_db;
      38             : 
      39             : /*******************************************************************
      40             :  Open acl_db if not already open, increment ref count.
      41             : *******************************************************************/
      42             : 
      43           0 : static bool acl_tdb_init(void)
      44             : {
      45             :         char *dbname;
      46             : 
      47           0 :         if (acl_db) {
      48           0 :                 ref_count++;
      49           0 :                 return true;
      50             :         }
      51             : 
      52           0 :         dbname = state_path(talloc_tos(), "file_ntacls.tdb");
      53             : 
      54           0 :         if (dbname == NULL) {
      55           0 :                 errno = ENOSYS;
      56           0 :                 return false;
      57             :         }
      58             : 
      59           0 :         become_root();
      60           0 :         acl_db = db_open(NULL, dbname, 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600,
      61             :                          DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE);
      62           0 :         unbecome_root();
      63             : 
      64           0 :         if (acl_db == NULL) {
      65             : #if defined(ENOTSUP)
      66           0 :                 errno = ENOTSUP;
      67             : #else
      68             :                 errno = ENOSYS;
      69             : #endif
      70           0 :                 TALLOC_FREE(dbname);
      71           0 :                 return false;
      72             :         }
      73             : 
      74           0 :         ref_count++;
      75           0 :         TALLOC_FREE(dbname);
      76           0 :         return true;
      77             : }
      78             : 
      79             : /*******************************************************************
      80             :  Lower ref count and close acl_db if zero.
      81             : *******************************************************************/
      82             : 
      83           0 : static void disconnect_acl_tdb(struct vfs_handle_struct *handle)
      84             : {
      85           0 :         SMB_VFS_NEXT_DISCONNECT(handle);
      86           0 :         ref_count--;
      87           0 :         if (ref_count == 0) {
      88           0 :                 TALLOC_FREE(acl_db);
      89             :         }
      90           0 : }
      91             : 
      92             : /*******************************************************************
      93             :  Delete the tdb acl record for a file
      94             : *******************************************************************/
      95             : 
      96           0 : static NTSTATUS acl_tdb_delete(vfs_handle_struct *handle,
      97             :                                 struct db_context *db,
      98             :                                 SMB_STRUCT_STAT *psbuf)
      99             : {
     100             :         NTSTATUS status;
     101           0 :         struct file_id id = vfs_file_id_from_sbuf(handle->conn, psbuf);
     102             :         uint8_t id_buf[16];
     103             : 
     104             :         /* For backwards compatibility only store the dev/inode. */
     105           0 :         push_file_id_16(id_buf, &id);
     106             : 
     107           0 :         status = dbwrap_delete(db, make_tdb_data(id_buf, sizeof(id_buf)));
     108           0 :         return status;
     109             : }
     110             : 
     111             : /*******************************************************************
     112             :  Pull a security descriptor from an fsp into a DATA_BLOB from a tdb store.
     113             : *******************************************************************/
     114             : 
     115           0 : static NTSTATUS fget_acl_blob(TALLOC_CTX *ctx,
     116             :                         vfs_handle_struct *handle,
     117             :                         files_struct *fsp,
     118             :                         DATA_BLOB *pblob)
     119             : {
     120             :         uint8_t id_buf[16];
     121             :         TDB_DATA data;
     122             :         struct file_id id;
     123           0 :         struct db_context *db = acl_db;
     124           0 :         NTSTATUS status = NT_STATUS_OK;
     125             : 
     126           0 :         status = vfs_stat_fsp(fsp);
     127           0 :         if (!NT_STATUS_IS_OK(status)) {
     128           0 :                 return status;
     129             :         }
     130             : 
     131           0 :         id = vfs_file_id_from_sbuf(handle->conn, &fsp->fsp_name->st);
     132             : 
     133             :         /* For backwards compatibility only store the dev/inode. */
     134           0 :         push_file_id_16(id_buf, &id);
     135             : 
     136           0 :         status = dbwrap_fetch(db,
     137             :                               ctx,
     138             :                               make_tdb_data(id_buf, sizeof(id_buf)),
     139             :                               &data);
     140           0 :         if (!NT_STATUS_IS_OK(status)) {
     141           0 :                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
     142             :         }
     143             : 
     144           0 :         pblob->data = data.dptr;
     145           0 :         pblob->length = data.dsize;
     146             : 
     147           0 :         DBG_DEBUG("returned %u bytes from file %s\n",
     148             :                 (unsigned int)data.dsize,
     149             :                 fsp_str_dbg(fsp));
     150             : 
     151           0 :         if (pblob->length == 0 || pblob->data == NULL) {
     152           0 :                 return NT_STATUS_NOT_FOUND;
     153             :         }
     154           0 :         return NT_STATUS_OK;
     155             : }
     156             : 
     157             : /*******************************************************************
     158             :  Store a DATA_BLOB into a tdb record given an fsp pointer.
     159             : *******************************************************************/
     160             : 
     161           0 : static NTSTATUS store_acl_blob_fsp(vfs_handle_struct *handle,
     162             :                                 files_struct *fsp,
     163             :                                 DATA_BLOB *pblob)
     164             : {
     165             :         uint8_t id_buf[16];
     166             :         struct file_id id;
     167           0 :         TDB_DATA data = { .dptr = pblob->data, .dsize = pblob->length };
     168           0 :         struct db_context *db = acl_db;
     169             :         NTSTATUS status;
     170             : 
     171           0 :         DEBUG(10,("store_acl_blob_fsp: storing blob length %u on file %s\n",
     172             :                   (unsigned int)pblob->length, fsp_str_dbg(fsp)));
     173             : 
     174           0 :         status = vfs_stat_fsp(fsp);
     175           0 :         if (!NT_STATUS_IS_OK(status)) {
     176           0 :                 return status;
     177             :         }
     178             : 
     179           0 :         id = vfs_file_id_from_sbuf(handle->conn, &fsp->fsp_name->st);
     180             : 
     181             :         /* For backwards compatibility only store the dev/inode. */
     182           0 :         push_file_id_16(id_buf, &id);
     183             : 
     184           0 :         status = dbwrap_store(
     185             :                 db, make_tdb_data(id_buf, sizeof(id_buf)), data, 0);
     186           0 :         return status;
     187             : }
     188             : 
     189             : /*********************************************************************
     190             :  On unlinkat we need to delete the tdb record (if using tdb).
     191             : *********************************************************************/
     192             : 
     193           0 : static int unlinkat_acl_tdb(vfs_handle_struct *handle,
     194             :                         struct files_struct *dirfsp,
     195             :                         const struct smb_filename *smb_fname,
     196             :                         int flags)
     197             : {
     198           0 :         struct smb_filename *smb_fname_tmp = NULL;
     199           0 :         struct db_context *db = acl_db;
     200           0 :         int ret = -1;
     201             : 
     202           0 :         smb_fname_tmp = cp_smb_filename_nostream(talloc_tos(), smb_fname);
     203           0 :         if (smb_fname_tmp == NULL) {
     204           0 :                 errno = ENOMEM;
     205           0 :                 goto out;
     206             :         }
     207             : 
     208           0 :         ret = vfs_stat(handle->conn, smb_fname_tmp);
     209           0 :         if (ret == -1) {
     210           0 :                 goto out;
     211             :         }
     212             : 
     213           0 :         if (flags & AT_REMOVEDIR) {
     214           0 :                 ret = rmdir_acl_common(handle,
     215             :                                 dirfsp,
     216             :                                 smb_fname_tmp);
     217             :         } else {
     218           0 :                 ret = unlink_acl_common(handle,
     219             :                                 dirfsp,
     220             :                                 smb_fname_tmp,
     221             :                                 flags);
     222             :         }
     223             : 
     224           0 :         if (ret == -1) {
     225           0 :                 goto out;
     226             :         }
     227             : 
     228           0 :         acl_tdb_delete(handle, db, &smb_fname_tmp->st);
     229           0 :  out:
     230           0 :         return ret;
     231             : }
     232             : 
     233             : /*******************************************************************
     234             :  Handle opening the storage tdb if so configured.
     235             : *******************************************************************/
     236             : 
     237           0 : static int connect_acl_tdb(struct vfs_handle_struct *handle,
     238             :                                 const char *service,
     239             :                                 const char *user)
     240             : {
     241           0 :         int ret = SMB_VFS_NEXT_CONNECT(handle, service, user);
     242             :         bool ok;
     243           0 :         struct acl_common_config *config = NULL;
     244             : 
     245           0 :         if (ret < 0) {
     246           0 :                 return ret;
     247             :         }
     248             : 
     249           0 :         if (!acl_tdb_init()) {
     250           0 :                 SMB_VFS_NEXT_DISCONNECT(handle);
     251           0 :                 return -1;
     252             :         }
     253             : 
     254           0 :         ok = init_acl_common_config(handle, ACL_MODULE_NAME);
     255           0 :         if (!ok) {
     256           0 :                 DBG_ERR("init_acl_common_config failed\n");
     257           0 :                 return -1;
     258             :         }
     259             : 
     260             :         /* Ensure we have the parameters correct if we're
     261             :          * using this module. */
     262           0 :         DEBUG(2,("connect_acl_tdb: setting 'inherit acls = true' "
     263             :                 "'dos filemode = true' and "
     264             :                 "'force unknown acl user = true' for service %s\n",
     265             :                 service ));
     266             : 
     267           0 :         lp_do_parameter(SNUM(handle->conn), "inherit acls", "true");
     268           0 :         lp_do_parameter(SNUM(handle->conn), "dos filemode", "true");
     269           0 :         lp_do_parameter(SNUM(handle->conn), "force unknown acl user", "true");
     270             : 
     271           0 :         SMB_VFS_HANDLE_GET_DATA(handle, config,
     272             :                                 struct acl_common_config,
     273             :                                 return -1);
     274             : 
     275           0 :         if (config->ignore_system_acls) {
     276           0 :                 mode_t create_mask = lp_create_mask(SNUM(handle->conn));
     277           0 :                 char *create_mask_str = NULL;
     278             : 
     279           0 :                 if ((create_mask & 0666) != 0666) {
     280           0 :                         create_mask |= 0666;
     281           0 :                         create_mask_str = talloc_asprintf(handle, "0%o",
     282             :                                                           create_mask);
     283           0 :                         if (create_mask_str == NULL) {
     284           0 :                                 DBG_ERR("talloc_asprintf failed\n");
     285           0 :                                 return -1;
     286             :                         }
     287             : 
     288           0 :                         DBG_NOTICE("setting 'create mask = %s'\n", create_mask_str);
     289             : 
     290           0 :                         lp_do_parameter (SNUM(handle->conn),
     291             :                                         "create mask", create_mask_str);
     292             : 
     293           0 :                         TALLOC_FREE(create_mask_str);
     294             :                 }
     295             : 
     296           0 :                 DBG_NOTICE("setting 'directory mask = 0777', "
     297             :                            "'store dos attributes = yes' and all "
     298             :                            "'map ...' options to 'no'\n");
     299             : 
     300           0 :                 lp_do_parameter(SNUM(handle->conn), "directory mask", "0777");
     301           0 :                 lp_do_parameter(SNUM(handle->conn), "map archive", "no");
     302           0 :                 lp_do_parameter(SNUM(handle->conn), "map hidden", "no");
     303           0 :                 lp_do_parameter(SNUM(handle->conn), "map readonly", "no");
     304           0 :                 lp_do_parameter(SNUM(handle->conn), "map system", "no");
     305           0 :                 lp_do_parameter(SNUM(handle->conn), "store dos attributes",
     306             :                                 "yes");
     307             :         }
     308             : 
     309           0 :         return 0;
     310             : }
     311             : 
     312             : /*********************************************************************
     313             :  Remove a Windows ACL - we're setting the underlying POSIX ACL.
     314             : *********************************************************************/
     315             : 
     316           0 : static int sys_acl_set_fd_tdb(vfs_handle_struct *handle,
     317             :                             files_struct *fsp,
     318             :                             SMB_ACL_TYPE_T type,
     319             :                             SMB_ACL_T theacl)
     320             : {
     321             :         struct acl_common_fsp_ext *ext = (struct acl_common_fsp_ext *)
     322           0 :                 VFS_FETCH_FSP_EXTENSION(handle, fsp);
     323           0 :         struct db_context *db = acl_db;
     324             :         NTSTATUS status;
     325             :         int ret;
     326             : 
     327           0 :         status = vfs_stat_fsp(fsp);
     328           0 :         if (!NT_STATUS_IS_OK(status)) {
     329           0 :                 return -1;
     330             :         }
     331             : 
     332           0 :         ret = SMB_VFS_NEXT_SYS_ACL_SET_FD(handle,
     333             :                                           fsp,
     334             :                                           type,
     335             :                                           theacl);
     336           0 :         if (ret == -1) {
     337           0 :                 return -1;
     338             :         }
     339             : 
     340           0 :         if (ext != NULL && ext->setting_nt_acl) {
     341           0 :                 return 0;
     342             :         }
     343             : 
     344           0 :         acl_tdb_delete(handle, db, &fsp->fsp_name->st);
     345           0 :         return 0;
     346             : }
     347             : 
     348           0 : static NTSTATUS acl_tdb_fget_nt_acl(vfs_handle_struct *handle,
     349             :                                     files_struct *fsp,
     350             :                                     uint32_t security_info,
     351             :                                     TALLOC_CTX *mem_ctx,
     352             :                                     struct security_descriptor **ppdesc)
     353             : {
     354             :         NTSTATUS status;
     355           0 :         status = fget_nt_acl_common(fget_acl_blob, handle, fsp,
     356             :                                    security_info, mem_ctx, ppdesc);
     357           0 :         return status;
     358             : }
     359             : 
     360           0 : static NTSTATUS acl_tdb_fset_nt_acl(vfs_handle_struct *handle,
     361             :                                     files_struct *fsp,
     362             :                                     uint32_t security_info_sent,
     363             :                                     const struct security_descriptor *psd)
     364             : {
     365             :         NTSTATUS status;
     366           0 :         status = fset_nt_acl_common(fget_acl_blob, store_acl_blob_fsp,
     367             :                                     ACL_MODULE_NAME,
     368             :                                     handle, fsp, security_info_sent, psd);
     369           0 :         return status;
     370             : }
     371             : 
     372             : static struct vfs_fn_pointers vfs_acl_tdb_fns = {
     373             :         .connect_fn = connect_acl_tdb,
     374             :         .disconnect_fn = disconnect_acl_tdb,
     375             :         .unlinkat_fn = unlinkat_acl_tdb,
     376             :         .fchmod_fn = fchmod_acl_module_common,
     377             :         .fget_nt_acl_fn = acl_tdb_fget_nt_acl,
     378             :         .fset_nt_acl_fn = acl_tdb_fset_nt_acl,
     379             :         .sys_acl_set_fd_fn = sys_acl_set_fd_tdb
     380             : };
     381             : 
     382             : static_decl_vfs;
     383          27 : NTSTATUS vfs_acl_tdb_init(TALLOC_CTX *ctx)
     384             : {
     385          27 :         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "acl_tdb",
     386             :                                 &vfs_acl_tdb_fns);
     387             : }

Generated by: LCOV version 1.14