summaryrefslogtreecommitdiff
path: root/source3/smbd/open.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/smbd/open.c')
-rw-r--r--source3/smbd/open.c126
1 files changed, 73 insertions, 53 deletions
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index 72370c8c7c..5b62ff022d 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -193,31 +193,41 @@ void change_file_owner_to_parent(connection_struct *conn,
const char *inherit_from_dir,
files_struct *fsp)
{
- SMB_STRUCT_STAT parent_st;
+ struct smb_filename *smb_fname_parent = NULL;
+ NTSTATUS status;
int ret;
- ret = SMB_VFS_STAT(conn, inherit_from_dir, &parent_st);
+ status = create_synthetic_smb_fname(talloc_tos(), inherit_from_dir,
+ NULL, NULL, &smb_fname_parent);
+ if (!NT_STATUS_IS_OK(status)) {
+ return;
+ }
+
+ ret = SMB_VFS_STAT(conn, smb_fname_parent);
if (ret == -1) {
DEBUG(0,("change_file_owner_to_parent: failed to stat parent "
"directory %s. Error was %s\n",
- inherit_from_dir, strerror(errno) ));
+ smb_fname_str_dbg(smb_fname_parent),
+ strerror(errno)));
return;
}
become_root();
- ret = SMB_VFS_FCHOWN(fsp, parent_st.st_ex_uid, (gid_t)-1);
+ ret = SMB_VFS_FCHOWN(fsp, smb_fname_parent->st.st_ex_uid, (gid_t)-1);
unbecome_root();
if (ret == -1) {
DEBUG(0,("change_file_owner_to_parent: failed to fchown "
"file %s to parent directory uid %u. Error "
"was %s\n", fsp->fsp_name,
- (unsigned int)parent_st.st_ex_uid,
+ (unsigned int)smb_fname_parent->st.st_ex_uid,
strerror(errno) ));
}
DEBUG(10,("change_file_owner_to_parent: changed new file %s to "
"parent directory uid %u.\n", fsp->fsp_name,
- (unsigned int)parent_st.st_ex_uid ));
+ (unsigned int)smb_fname_parent->st.st_ex_uid));
+
+ TALLOC_FREE(smb_fname_parent);
}
NTSTATUS change_dir_owner_to_parent(connection_struct *conn,
@@ -225,20 +235,27 @@ NTSTATUS change_dir_owner_to_parent(connection_struct *conn,
const char *fname,
SMB_STRUCT_STAT *psbuf)
{
+ struct smb_filename *smb_fname_parent = NULL;
+ struct smb_filename *smb_fname_cwd = NULL;
char *saved_dir = NULL;
- SMB_STRUCT_STAT sbuf;
- SMB_STRUCT_STAT parent_st;
TALLOC_CTX *ctx = talloc_tos();
NTSTATUS status = NT_STATUS_OK;
int ret;
- ret = SMB_VFS_STAT(conn, inherit_from_dir, &parent_st);
+ status = create_synthetic_smb_fname(ctx, inherit_from_dir, NULL, NULL,
+ &smb_fname_parent);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ ret = SMB_VFS_STAT(conn, smb_fname_parent);
if (ret == -1) {
status = map_nt_error_from_unix(errno);
DEBUG(0,("change_dir_owner_to_parent: failed to stat parent "
"directory %s. Error was %s\n",
- inherit_from_dir, strerror(errno) ));
- return status;
+ smb_fname_str_dbg(smb_fname_parent),
+ strerror(errno)));
+ goto out;
}
/* We've already done an lstat into psbuf, and we know it's a
@@ -254,7 +271,7 @@ NTSTATUS change_dir_owner_to_parent(connection_struct *conn,
DEBUG(0,("change_dir_owner_to_parent: failed to get "
"current working directory. Error was %s\n",
strerror(errno)));
- return status;
+ goto out;
}
/* Chdir into the new path. */
@@ -263,47 +280,58 @@ NTSTATUS change_dir_owner_to_parent(connection_struct *conn,
DEBUG(0,("change_dir_owner_to_parent: failed to change "
"current working directory to %s. Error "
"was %s\n", fname, strerror(errno) ));
- goto out;
+ goto chdir;
+ }
+
+ status = create_synthetic_smb_fname(ctx, ".", NULL, NULL,
+ &smb_fname_cwd);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
- if (SMB_VFS_STAT(conn,".",&sbuf) == -1) {
+ ret = SMB_VFS_STAT(conn, smb_fname_cwd);
+ if (ret == -1) {
status = map_nt_error_from_unix(errno);
DEBUG(0,("change_dir_owner_to_parent: failed to stat "
"directory '.' (%s) Error was %s\n",
fname, strerror(errno)));
- goto out;
+ goto chdir;
}
/* Ensure we're pointing at the same place. */
- if (sbuf.st_ex_dev != psbuf->st_ex_dev ||
- sbuf.st_ex_ino != psbuf->st_ex_ino ||
- sbuf.st_ex_mode != psbuf->st_ex_mode ) {
+ if (smb_fname_cwd->st.st_ex_dev != psbuf->st_ex_dev ||
+ smb_fname_cwd->st.st_ex_ino != psbuf->st_ex_ino ||
+ smb_fname_cwd->st.st_ex_mode != psbuf->st_ex_mode ) {
DEBUG(0,("change_dir_owner_to_parent: "
"device/inode/mode on directory %s changed. "
"Refusing to chown !\n", fname ));
status = NT_STATUS_ACCESS_DENIED;
- goto out;
+ goto chdir;
}
become_root();
- ret = SMB_VFS_CHOWN(conn, ".", parent_st.st_ex_uid, (gid_t)-1);
+ ret = SMB_VFS_CHOWN(conn, ".", smb_fname_parent->st.st_ex_uid,
+ (gid_t)-1);
unbecome_root();
if (ret == -1) {
status = map_nt_error_from_unix(errno);
DEBUG(10,("change_dir_owner_to_parent: failed to chown "
"directory %s to parent directory uid %u. "
"Error was %s\n", fname,
- (unsigned int)parent_st.st_ex_uid, strerror(errno) ));
- goto out;
+ (unsigned int)smb_fname_parent->st.st_ex_uid,
+ strerror(errno) ));
+ goto chdir;
}
DEBUG(10,("change_dir_owner_to_parent: changed ownership of new "
"directory %s to parent directory uid %u.\n",
- fname, (unsigned int)parent_st.st_ex_uid ));
-
- out:
+ fname, (unsigned int)smb_fname_parent->st.st_ex_uid ));
+ chdir:
vfs_ChDir(conn,saved_dir);
+ out:
+ TALLOC_FREE(smb_fname_parent);
+ TALLOC_FREE(smb_fname_cwd);
return status;
}
@@ -537,7 +565,7 @@ static NTSTATUS open_file(files_struct *fsp,
int ret;
if (fsp->fh->fd == -1) {
- ret = SMB_VFS_STAT(conn, path, &smb_fname->st);
+ ret = SMB_VFS_STAT(conn, smb_fname);
} else {
ret = SMB_VFS_FSTAT(fsp, &smb_fname->st);
/* If we have an fd, this stat should succeed. */
@@ -1857,8 +1885,10 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
can_access_mask = FILE_READ_DATA;
}
- if (((can_access_mask & FILE_WRITE_DATA) && !CAN_WRITE(conn)) ||
- !can_access_file_data(conn, fname, &smb_fname->st, can_access_mask)) {
+ if (((can_access_mask & FILE_WRITE_DATA) &&
+ !CAN_WRITE(conn)) ||
+ !can_access_file_data(conn, smb_fname,
+ can_access_mask)) {
can_access = False;
}
@@ -2347,7 +2377,7 @@ static NTSTATUS mkdir_internal(connection_struct *conn,
/* Ensure we're checking for a symlink here.... */
/* We don't want to get caught by a symlink racer. */
- if (SMB_VFS_LSTAT(conn, name, psbuf) == -1) {
+ if (vfs_lstat_smb_fname(conn, name, psbuf) == -1) {
DEBUG(2, ("Could not stat directory '%s' just created: %s\n",
name, strerror(errno)));
return map_nt_error_from_unix(errno);
@@ -2471,7 +2501,7 @@ static NTSTATUS open_directory(connection_struct *conn,
* We want to follow symlinks here.
*/
- if (SMB_VFS_STAT(conn, fname, &smb_dname->st) != 0) {
+ if (SMB_VFS_STAT(conn, smb_dname) != 0) {
return map_nt_error_from_unix(errno);
}
@@ -2836,34 +2866,24 @@ NTSTATUS open_streams_for_delete(connection_struct *conn,
for (i=0; i<num_streams; i++) {
struct smb_filename *smb_fname = NULL;
- char *streamname = NULL;
- SMB_STRUCT_STAT sbuf;
if (strequal(stream_info[i].name, "::$DATA")) {
streams[i] = NULL;
continue;
}
- streamname = talloc_asprintf(talloc_tos(), "%s%s", fname,
- stream_info[i].name);
- if (streamname == NULL) {
- DEBUG(0, ("talloc_aprintf failed\n"));
- status = NT_STATUS_NO_MEMORY;
- }
-
- if (SMB_VFS_STAT(conn, streamname, &sbuf) == -1) {
- SET_STAT_INVALID(sbuf);
- }
-
- TALLOC_FREE(streamname);
-
status = create_synthetic_smb_fname(talloc_tos(), fname,
stream_info[i].name,
- &sbuf, &smb_fname);
+ NULL, &smb_fname);
if (!NT_STATUS_IS_OK(status)) {
goto fail;
}
+ if (SMB_VFS_STAT(conn, smb_fname) == -1) {
+ DEBUG(10, ("Unable to stat stream: %s\n",
+ smb_fname_str_dbg(smb_fname)));
+ }
+
status = SMB_VFS_CREATE_FILE(
conn, /* conn */
NULL, /* req */
@@ -2999,7 +3019,7 @@ static NTSTATUS create_file_unixpath(connection_struct *conn,
&& (share_access & FILE_SHARE_DELETE)
&& (access_mask & DELETE_ACCESS)
&& (!(can_delete_file_in_directory(conn, smb_fname) ||
- can_access_file_acl(conn, fname, DELETE_ACCESS)))) {
+ can_access_file_acl(conn, smb_fname, DELETE_ACCESS)))) {
status = NT_STATUS_ACCESS_DENIED;
DEBUG(10,("create_file_unixpath: open file %s "
"for delete ACCESS_DENIED\n",
@@ -3036,7 +3056,6 @@ static NTSTATUS create_file_unixpath(connection_struct *conn,
&& (!(create_options & NTCREATEX_OPTIONS_PRIVATE_STREAM_DELETE))) {
uint32 base_create_disposition;
struct smb_filename *smb_fname_base = NULL;
- SMB_STRUCT_STAT sbuf;
if (create_options & FILE_DIRECTORY_FILE) {
status = NT_STATUS_NOT_A_DIRECTORY;
@@ -3052,19 +3071,20 @@ static NTSTATUS create_file_unixpath(connection_struct *conn,
break;
}
- if (SMB_VFS_STAT(conn, smb_fname->base_name, &sbuf) == -1) {
- SET_STAT_INVALID(sbuf);
- }
-
/* Create an smb_filename with stream_name == NULL. */
status = create_synthetic_smb_fname(talloc_tos(),
smb_fname->base_name,
- NULL, &sbuf,
+ NULL, NULL,
&smb_fname_base);
if (!NT_STATUS_IS_OK(status)) {
goto fail;
}
+ if (SMB_VFS_STAT(conn, smb_fname_base) == -1) {
+ DEBUG(10, ("Unable to stat stream: %s\n",
+ smb_fname_str_dbg(smb_fname_base)));
+ }
+
/* Open the base file. */
status = create_file_unixpath(conn, NULL, smb_fname_base, 0,
FILE_SHARE_READ