loadparm: make the source3/ lp_ functions take an explicit TALLOC_CTX *.
[samba.git] / source3 / smbd / fake_file.c
index ee510eb003f2add7a970cece65e0836a20868f9a..d052d4965df3750dcb38df03554be2d33951ca07 100644 (file)
@@ -5,7 +5,7 @@
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
+#include "smbd/smbd.h"
+#include "smbd/globals.h"
+#include "fake_file.h"
+#include "auth.h"
+
+struct fake_file_type {
+       const char *name;
+       enum FAKE_FILE_TYPE type;
+       void *(*init_pd)(TALLOC_CTX *mem_ctx);
+};
 
-extern struct current_user current_user;
+static const struct fake_file_type fake_files[] = {
+#ifdef WITH_QUOTAS
+       {FAKE_FILE_NAME_QUOTA_UNIX, FAKE_FILE_TYPE_QUOTA, init_quota_handle},
+#endif /* WITH_QUOTAS */
+       {NULL, FAKE_FILE_TYPE_NONE, NULL}
+};
 
 /****************************************************************************
- Open a file with a share mode.
+ Create a fake file handle
 ****************************************************************************/
-files_struct *open_fake_file_shared1(enum FAKE_FILE_TYPE fake_file_type, connection_struct *conn,char *fname,
-                               SMB_STRUCT_STAT *psbuf, 
-                               uint32 desired_access, 
-                               int share_mode,int ofun, uint32 new_dos_attr, int oplock_request, 
-                               int *Access,int *action)
+
+static struct fake_file_handle *init_fake_file_handle(enum FAKE_FILE_TYPE type)
 {
-       int flags=0;
-       files_struct *fsp = NULL;
+       struct fake_file_handle *fh = NULL;
+       int i;
 
-       if (fake_file_type == 0) {
-               return open_file_shared1(conn,fname,psbuf,desired_access,
-                                       share_mode,ofun,new_dos_attr,
-                                       oplock_request,Access,action);  
+       for (i=0; fake_files[i].name!=NULL; i++) {
+               if (fake_files[i].type==type) {
+                       break;
+               }
        }
 
-       /* access check */
-       if (current_user.uid != 0) {
-               DEBUG(1,("access_denied to service[%s] file[%s] user[%s]\n",
-                       lp_servicename(SNUM(conn)),fname,conn->user));
-               errno = EACCES;
+       if (fake_files[i].name == NULL) {
                return NULL;
        }
 
-       fsp = file_new(conn);
-       if(!fsp)
-               return NULL;
+       DEBUG(5,("init_fake_file_handle: for [%s]\n",fake_files[i].name));
 
-       DEBUG(5,("open_fake_file_shared1: fname = %s, FID = %d, share_mode = %x, ofun = %x, oplock request = %d\n",
-               fname, fsp->fnum, share_mode, ofun, oplock_request ));
-
-       if (!check_name(fname,conn)) {
-               file_free(fsp);
-               return NULL;
-       } 
-
-       fsp->fd = -1;
-       fsp->mode = psbuf->st_mode;
-       fsp->inode = psbuf->st_ino;
-       fsp->dev = psbuf->st_dev;
-       fsp->vuid = current_user.vuid;
-       fsp->size = psbuf->st_size;
-       fsp->pos = -1;
-       fsp->can_lock = True;
-       fsp->can_read = ((flags & O_WRONLY)==0);
-       fsp->can_write = ((flags & (O_WRONLY|O_RDWR))!=0);
-       fsp->share_mode = 0;
-       fsp->desired_access = desired_access;
-       fsp->print_file = False;
-       fsp->modified = False;
-       fsp->oplock_type = NO_OPLOCK;
-       fsp->sent_oplock_break = NO_BREAK_SENT;
-       fsp->is_directory = False;
-       fsp->is_stat = False;
-       fsp->directory_delete_on_close = False;
-       fsp->conn = conn;
-       string_set(&fsp->fsp_name,fname);
-       fsp->wcp = NULL; /* Write cache pointer. */
-       
-       fsp->fake_file_handle = init_fake_file_handle(fake_file_type);
-       
-       if (fsp->fake_file_handle==NULL) {
-               file_free(fsp);
+       fh = talloc(NULL, struct fake_file_handle);
+       if (fh == NULL) {
+               DEBUG(0,("TALLOC_ZERO() failed.\n"));
                return NULL;
        }
 
-       conn->num_files_open++;
-       return fsp;
+       fh->type = type;
+
+       if (fake_files[i].init_pd) {
+               fh->private_data = fake_files[i].init_pd(fh);
+       }
+       return fh;
 }
 
-static FAKE_FILE fake_files[] = {
-#ifdef WITH_QUOTAS
-       {FAKE_FILE_NAME_QUOTA_UNIX,     FAKE_FILE_TYPE_QUOTA,   init_quota_handle,      destroy_quota_handle},
-#endif /* WITH_QUOTAS */
-       {NULL,                          FAKE_FILE_TYPE_NONE,    NULL,                   NULL }
-};
+/****************************************************************************
+ Does this name match a fake filename ?
+****************************************************************************/
 
-int is_fake_file(char *fname)
+enum FAKE_FILE_TYPE is_fake_file_path(const char *path)
 {
        int i;
 
-       if (!fname)
-               return 0;
+       if (!path) {
+               return FAKE_FILE_TYPE_NONE;
+       }
 
        for (i=0;fake_files[i].name!=NULL;i++) {
-               if (strncmp(fname,fake_files[i].name,strlen(fake_files[i].name))==0) {
-                       DEBUG(5,("is_fake_file: [%s] is a fake file\n",fname));
+               if (strncmp(path,fake_files[i].name,strlen(fake_files[i].name))==0) {
+                       DEBUG(5,("is_fake_file: [%s] is a fake file\n",path));
                        return fake_files[i].type;
                }
        }
@@ -118,50 +93,98 @@ int is_fake_file(char *fname)
        return FAKE_FILE_TYPE_NONE;
 }
 
-struct _FAKE_FILE_HANDLE *init_fake_file_handle(enum FAKE_FILE_TYPE type)
+enum FAKE_FILE_TYPE is_fake_file(const struct smb_filename *smb_fname)
 {
-       TALLOC_CTX *mem_ctx = NULL;
-       FAKE_FILE_HANDLE *fh = NULL;
-       int i;
+       char *fname = NULL;
+       NTSTATUS status;
+       enum FAKE_FILE_TYPE ret;
 
-       for (i=0;fake_files[i].name!=NULL;i++) {
-               if (fake_files[i].type==type) {
-                       DEBUG(5,("init_fake_file_handle: for [%s]\n",fake_files[i].name));
+       if (!smb_fname) {
+               return FAKE_FILE_TYPE_NONE;
+       }
 
-                       if ((mem_ctx=talloc_init("fake_file_handle"))==NULL) {
-                               DEBUG(0,("talloc_init(fake_file_handle) failed.\n"));
-                               return NULL;    
-                       }
+       status = get_full_smb_filename(talloc_tos(), smb_fname, &fname);
+       if (!NT_STATUS_IS_OK(status)) {
+               return FAKE_FILE_TYPE_NONE;
+       }
 
-                       if ((fh =TALLOC_ZERO_P(mem_ctx, FAKE_FILE_HANDLE))==NULL) {
-                               DEBUG(0,("talloc_zero() failed.\n"));
-                               talloc_destroy(mem_ctx);
-                               return NULL;
-                       }
+       ret = is_fake_file_path(fname);
 
-                       fh->type = type;
-                       fh->mem_ctx = mem_ctx;
+       TALLOC_FREE(fname);
 
-                       if (fake_files[i].init_pd)
-                               fh->pd = fake_files[i].init_pd(fh->mem_ctx);
+       return ret;
+}
 
-                       fh->free_pd = fake_files[i].free_pd;
+/****************************************************************************
+ Open a fake quota file with a share mode.
+****************************************************************************/
 
-                       return fh;
-               }
+NTSTATUS open_fake_file(struct smb_request *req, connection_struct *conn,
+                               uint64_t current_vuid,
+                               enum FAKE_FILE_TYPE fake_file_type,
+                               const struct smb_filename *smb_fname,
+                               uint32 access_mask,
+                               files_struct **result)
+{
+       files_struct *fsp = NULL;
+       NTSTATUS status;
+
+       status = smbd_calculate_access_mask(conn, smb_fname,
+                                           access_mask, &access_mask);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(10, ("open_fake_file: smbd_calculate_access_mask "
+                       "on service[%s] file[%s] returned %s\n",
+                       lp_servicename(talloc_tos(), SNUM(conn)),
+                       smb_fname_str_dbg(smb_fname),
+                       nt_errstr(status)));
+               return status;
        }
 
-       return NULL;    
-}
+       /* access check */
+       if (geteuid() != sec_initial_uid()) {
+               DEBUG(3, ("open_fake_file_shared: access_denied to "
+                         "service[%s] file[%s] user[%s]\n",
+                         lp_servicename(talloc_tos(), SNUM(conn)),
+                         smb_fname_str_dbg(smb_fname),
+                         conn->session_info->unix_info->unix_name));
+               return NT_STATUS_ACCESS_DENIED;
 
-void destroy_fake_file_handle(FAKE_FILE_HANDLE **fh)
-{
-       if (!fh||!(*fh))
-               return;
+       }
 
-       if ((*fh)->free_pd)
-               (*fh)->free_pd(&(*fh)->pd);             
+       status = file_new(req, conn, &fsp);
+       if(!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       DEBUG(5,("open_fake_file_shared: fname = %s, %s, access_mask = 0x%x\n",
+                smb_fname_str_dbg(smb_fname), fsp_fnum_dbg(fsp),
+                (unsigned int)access_mask));
 
-       talloc_destroy((*fh)->mem_ctx);
-       (*fh) = NULL;
+       fsp->conn = conn;
+       fsp->fh->fd = -1;
+       fsp->vuid = current_vuid;
+       fsp->fh->pos = -1;
+       fsp->can_lock = False; /* Should this be true ? - No, JRA */
+       fsp->access_mask = access_mask;
+       status = fsp_set_smb_fname(fsp, smb_fname);
+       if (!NT_STATUS_IS_OK(status)) {
+               file_free(req, fsp);
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       fsp->fake_file_handle = init_fake_file_handle(fake_file_type);
+       
+       if (fsp->fake_file_handle==NULL) {
+               file_free(req, fsp);
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       *result = fsp;
+       return NT_STATUS_OK;
+}
+
+NTSTATUS close_fake_file(struct smb_request *req, files_struct *fsp)
+{
+       file_free(req, fsp);
+       return NT_STATUS_OK;
 }