Fix bug #8370 - vfs_chown_fsp broken -- returns in the wrong directory
[idra/samba.git] / source3 / smbd / vfs.c
index a714b86ef263c61ce5973ce66aaa647fcd0bc4b4..c6edef282faaa806c349a1163d8edc01bebf15ac 100644 (file)
@@ -183,7 +183,7 @@ bool vfs_init_custom(connection_struct *conn, const char *vfs_object)
 
        DEBUGADD(5,("Successfully loaded vfs module [%s] with the new modules system\n", vfs_object));
 
-       handle = TALLOC_ZERO_P(conn, vfs_handle_struct);
+       handle = talloc_zero(conn, vfs_handle_struct);
        if (!handle) {
                DEBUG(0,("TALLOC_ZERO() failed!\n"));
                goto fail;
@@ -729,7 +729,7 @@ const char *vfs_readdirname(connection_struct *conn, void *p,
        if (!p)
                return(NULL);
 
-       ptr = SMB_VFS_READDIR(conn, (DIR *)p, sbuf);
+       ptr = SMB_VFS_READDIR(conn, (SMB_STRUCT_DIR *)p, sbuf);
        if (!ptr)
                return(NULL);
 
@@ -795,7 +795,7 @@ int vfs_ChDir(connection_struct *conn, const char *path)
 
 char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
 {
-        char s[PATH_MAX+1];
+        char *current_dir = NULL;
        char *result = NULL;
        DATA_BLOB cache_value;
        struct file_id key;
@@ -803,8 +803,6 @@ char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
        struct smb_filename *smb_fname_full = NULL;
        NTSTATUS status;
 
-       *s = 0;
-
        if (!lp_getwd_cache()) {
                goto nocache;
        }
@@ -866,7 +864,8 @@ char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
         * systems, or the not quite so bad getwd.
         */
 
-       if (!SMB_VFS_GETWD(conn,s)) {
+       current_dir = SMB_VFS_GETWD(conn);
+       if (current_dir == NULL) {
                DEBUG(0, ("vfs_GetWd: SMB_VFS_GETWD call failed: %s\n",
                          strerror(errno)));
                goto out;
@@ -877,10 +876,11 @@ char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
 
                memcache_add(smbd_memcache(), GETWD_CACHE,
                             data_blob_const(&key, sizeof(key)),
-                            data_blob_const(s, strlen(s)+1));
+                            data_blob_const(current_dir,
+                                               strlen(current_dir)+1));
        }
 
-       result = talloc_strdup(ctx, s);
+       result = talloc_strdup(ctx, current_dir);
        if (result == NULL) {
                errno = ENOMEM;
        }
@@ -888,6 +888,7 @@ char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
  out:
        TALLOC_FREE(smb_fname_dot);
        TALLOC_FREE(smb_fname_full);
+       SAFE_FREE(current_dir);
        return result;
 }
 
@@ -1005,12 +1006,10 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname)
 
                /* Extra checks if all symlinks are disallowed. */
                if (!allow_symlinks) {
-                       struct smb_filename *smb_fname = NULL;
-                       NTSTATUS status;
                        /* fname can't have changed in resolved_path. */
                        const char *p = &resolved_name[rootdir_len];
 
-                       /* *p ran be '\0' if fname was "." */
+                       /* *p can be '\0' if fname was "." */
                        if (*p == '\0' && ISDOT(fname)) {
                                goto out;
                        }
@@ -1032,27 +1031,6 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname)
                                SAFE_FREE(resolved_name);
                                return NT_STATUS_ACCESS_DENIED;
                        }
-
-                       /* Check if we are allowing users to follow symlinks */
-                       /* Patch from David Clerc <David.Clerc@cui.unige.ch>
-                          University of Geneva */
-                       status = create_synthetic_smb_fname(talloc_tos(),
-                                       fname, NULL,
-                                       NULL, &smb_fname);
-                       if (!NT_STATUS_IS_OK(status)) {
-                               SAFE_FREE(resolved_name);
-                               return status;
-                       }
-
-                       if ( (SMB_VFS_LSTAT(conn, smb_fname) != -1) &&
-                                       (S_ISLNK(smb_fname->st.st_ex_mode)) ) {
-                               SAFE_FREE(resolved_name);
-                               DEBUG(3,("check_reduced_name: denied: file path name "
-                                       "%s is a symlink\n",resolved_name));
-                               TALLOC_FREE(smb_fname);
-                               return NT_STATUS_ACCESS_DENIED;
-                       }
-                       TALLOC_FREE(smb_fname);
                }
        }
 
@@ -1197,7 +1175,7 @@ int smb_vfs_call_set_quota(struct vfs_handle_struct *handle,
 
 int smb_vfs_call_get_shadow_copy_data(struct vfs_handle_struct *handle,
                                      struct files_struct *fsp,
-                                     SHADOW_COPY_DATA *shadow_copy_data,
+                                     struct shadow_copy_data *shadow_copy_data,
                                      bool labels)
 {
        VFS_FIND(get_shadow_copy_data);
@@ -1523,23 +1501,25 @@ NTSTATUS vfs_chown_fsp(files_struct *fsp, uid_t uid, gid_t gid)
                }
 
                /* cd into the parent dir to pin it. */
-               ret = SMB_VFS_CHDIR(fsp->conn, parent_dir);
+               ret = vfs_ChDir(fsp->conn, parent_dir);
                if (ret == -1) {
                        return map_nt_error_from_unix(errno);
                }
 
                ZERO_STRUCT(local_fname);
-               local_fname.base_name = CONST_DISCARD(char *,final_component);
+               local_fname.base_name = discard_const_p(char, final_component);
 
                /* Must use lstat here. */
                ret = SMB_VFS_LSTAT(fsp->conn, &local_fname);
                if (ret == -1) {
-                       return map_nt_error_from_unix(errno);
+                       status = map_nt_error_from_unix(errno);
+                       goto out;
                }
 
                /* Ensure it matches the fsp stat. */
                if (!check_same_stat(&local_fname.st, &fsp->fsp_name->st)) {
-                        return NT_STATUS_ACCESS_DENIED;
+                        status = NT_STATUS_ACCESS_DENIED;
+                       goto out;
                 }
                 path = final_component;
         } else {
@@ -1562,6 +1542,8 @@ NTSTATUS vfs_chown_fsp(files_struct *fsp, uid_t uid, gid_t gid)
                status = map_nt_error_from_unix(errno);
        }
 
+  out:
+
        if (as_root) {
                vfs_ChDir(fsp->conn,saved_dir);
                TALLOC_FREE(saved_dir);
@@ -1576,10 +1558,10 @@ int smb_vfs_call_chdir(struct vfs_handle_struct *handle, const char *path)
        return handle->fns->chdir(handle, path);
 }
 
-char *smb_vfs_call_getwd(struct vfs_handle_struct *handle, char *buf)
+char *smb_vfs_call_getwd(struct vfs_handle_struct *handle)
 {
        VFS_FIND(getwd);
-       return handle->fns->getwd(handle, buf);
+       return handle->fns->getwd(handle);
 }
 
 int smb_vfs_call_ntimes(struct vfs_handle_struct *handle,