From d2da9dee686881106678d50a96713f0632dcdf10 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 18 Jun 2009 15:07:14 -0700 Subject: [PATCH] Add some const to the stat struct in the dosmode calls. Fix a couple more unix_convert uses to filename_convert. Fix bug in acl_group_override() where an uninitialized struct could be used. Move unix_convert with wildcard use in SMBsearch reply to boilerplate code. Jeremy. --- source3/include/proto.h | 8 +++--- source3/rpc_server/srv_srvsvc_nt.c | 19 +++----------- source3/smbd/dosmode.c | 28 +++++++++++---------- source3/smbd/file_access.c | 11 +++----- source3/smbd/nttrans.c | 40 +++++------------------------- source3/smbd/open.c | 1 - source3/smbd/posix_acls.c | 31 ++++++++++++++++------- source3/smbd/reply.c | 36 +++++++++++++-------------- 8 files changed, 72 insertions(+), 102 deletions(-) diff --git a/source3/include/proto.h b/source3/include/proto.h index 6fc28259d69..598d83aee60 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -6290,9 +6290,9 @@ bool smbd_setup_mdns_registration(struct tevent_context *ev, mode_t unix_mode(connection_struct *conn, int dosmode, const char *fname, const char *inherit_from_dir); -uint32 dos_mode_msdfs(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf); +uint32 dos_mode_msdfs(connection_struct *conn, const char *path, const SMB_STRUCT_STAT *sbuf); int dos_attributes_to_stat_dos_flags(uint32_t dosmode); -uint32 dos_mode(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf); +uint32 dos_mode(connection_struct *conn, const char *path, const SMB_STRUCT_STAT *sbuf); int file_set_dosmode(connection_struct *conn, const char *fname, uint32 dosmode, SMB_STRUCT_STAT *st, const char *parent_dir, @@ -6339,8 +6339,8 @@ bool can_access_file_acl(struct connection_struct *conn, uint32_t access_mask); bool can_delete_file_in_directory(connection_struct *conn, const struct smb_filename *smb_fname); -bool can_access_file_data(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf, uint32 access_mask); -bool can_write_to_file(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf); +bool can_access_file_data(connection_struct *conn, const char *fname, const SMB_STRUCT_STAT *psbuf, uint32 access_mask); +bool can_write_to_file(connection_struct *conn, const char *fname, const SMB_STRUCT_STAT *psbuf); bool directory_has_default_acl(connection_struct *conn, const char *fname); /* The following definitions come from smbd/fileio.c */ diff --git a/source3/rpc_server/srv_srvsvc_nt.c b/source3/rpc_server/srv_srvsvc_nt.c index 1b07fc213e6..070f7fd0ca2 100644 --- a/source3/rpc_server/srv_srvsvc_nt.c +++ b/source3/rpc_server/srv_srvsvc_nt.c @@ -2067,23 +2067,17 @@ WERROR _srvsvc_NetGetFileSecurity(pipes_struct *p, goto error_exit; } - nt_status = resolve_dfspath(talloc_tos(), + nt_status = filename_convert(talloc_tos(), conn, false, r->in.file, + &smb_fname, &fname); if (!NT_STATUS_IS_OK(nt_status)) { werr = ntstatus_to_werror(nt_status); goto error_exit; } - nt_status = unix_convert(talloc_tos(), conn, fname, &smb_fname, - 0); - if (!NT_STATUS_IS_OK(nt_status)) { - werr = ntstatus_to_werror(nt_status); - goto error_exit; - } - nt_status = SMB_VFS_CREATE_FILE( conn, /* conn */ NULL, /* req */ @@ -2203,21 +2197,16 @@ WERROR _srvsvc_NetSetFileSecurity(pipes_struct *p, goto error_exit; } - nt_status = resolve_dfspath(talloc_tos(), + nt_status = filename_convert(talloc_tos(), conn, false, r->in.file, + &smb_fname, &fname); if (!NT_STATUS_IS_OK(nt_status)) { werr = ntstatus_to_werror(nt_status); goto error_exit; } - nt_status = unix_convert(talloc_tos(), conn, fname, &smb_fname, - 0); - if (!NT_STATUS_IS_OK(nt_status)) { - werr = ntstatus_to_werror(nt_status); - goto error_exit; - } nt_status = SMB_VFS_CREATE_FILE( conn, /* conn */ diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index eeed76329cc..8149eea7f59 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -140,7 +140,7 @@ mode_t unix_mode(connection_struct *conn, int dosmode, const char *fname, Change a unix mode to a dos mode. ****************************************************************************/ -static uint32 dos_mode_from_sbuf(connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf) +static uint32 dos_mode_from_sbuf(connection_struct *conn, const char *path, const SMB_STRUCT_STAT *sbuf) { int result = 0; enum mapreadonly_options ro_opts = (enum mapreadonly_options)lp_map_readonly(SNUM(conn)); @@ -188,7 +188,7 @@ static uint32 dos_mode_from_sbuf(connection_struct *conn, const char *path, SMB_ Get DOS attributes from an EA. ****************************************************************************/ -static bool get_ea_dos_attribute(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf, uint32 *pattr) +static bool get_ea_dos_attribute(connection_struct *conn, const char *path, const SMB_STRUCT_STAT *sbuf, uint32 *pattr) { ssize_t sizeret; fstring attrstr; @@ -306,13 +306,14 @@ static bool set_ea_dos_attribute(connection_struct *conn, const char *path, SMB_ Change a unix mode to a dos mode for an ms dfs link. ****************************************************************************/ -uint32 dos_mode_msdfs(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf) +uint32 dos_mode_msdfs(connection_struct *conn, const char *path, const SMB_STRUCT_STAT *psbuf) { + SMB_STRUCT_STAT sbuf = *psbuf; uint32 result = 0; DEBUG(8,("dos_mode_msdfs: %s\n", path)); - if (!VALID_STAT(*sbuf)) { + if (!VALID_STAT(sbuf)) { return 0; } @@ -333,7 +334,7 @@ uint32 dos_mode_msdfs(connection_struct *conn, const char *path,SMB_STRUCT_STAT } } - result |= dos_mode_from_sbuf(conn, path, sbuf); + result |= dos_mode_from_sbuf(conn, path, &sbuf); /* Optimization : Only call is_hidden_path if it's not already hidden. */ @@ -466,14 +467,15 @@ static bool set_stat_dos_flags(connection_struct *conn, Change a unix mode to a dos mode. ****************************************************************************/ -uint32 dos_mode(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf) +uint32 dos_mode(connection_struct *conn, const char *path, const SMB_STRUCT_STAT *psbuf) { + SMB_STRUCT_STAT sbuf = *psbuf; uint32 result = 0; bool offline, used_stat_dos_flags = false; DEBUG(8,("dos_mode: %s\n", path)); - if (!VALID_STAT(*sbuf)) { + if (!VALID_STAT(sbuf)) { return 0; } @@ -495,19 +497,19 @@ uint32 dos_mode(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf) } #ifdef HAVE_STAT_DOS_FLAGS - used_stat_dos_flags = get_stat_dos_flags(conn, path, sbuf, &result); + used_stat_dos_flags = get_stat_dos_flags(conn, path, &sbuf, &result); #endif if (!used_stat_dos_flags) { /* Get the DOS attributes from an EA by preference. */ - if (get_ea_dos_attribute(conn, path, sbuf, &result)) { - result |= set_sparse_flag(sbuf); + if (get_ea_dos_attribute(conn, path, &sbuf, &result)) { + result |= set_sparse_flag(&sbuf); } else { - result |= dos_mode_from_sbuf(conn, path, sbuf); + result |= dos_mode_from_sbuf(conn, path, &sbuf); } } - offline = SMB_VFS_IS_OFFLINE(conn, path, sbuf); - if (S_ISREG(sbuf->st_ex_mode) && offline) { + offline = SMB_VFS_IS_OFFLINE(conn, path, &sbuf); + if (S_ISREG(sbuf.st_ex_mode) && offline) { result |= FILE_ATTRIBUTE_OFFLINE; } diff --git a/source3/smbd/file_access.c b/source3/smbd/file_access.c index 8b282e25b66..195f722471d 100644 --- a/source3/smbd/file_access.c +++ b/source3/smbd/file_access.c @@ -155,7 +155,7 @@ bool can_delete_file_in_directory(connection_struct *conn, Note this doesn't take into account share write permissions. ****************************************************************************/ -bool can_access_file_data(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf, uint32 access_mask) +bool can_access_file_data(connection_struct *conn, const char *fname, const SMB_STRUCT_STAT *psbuf, uint32 access_mask) { if (!(access_mask & (FILE_READ_DATA|FILE_WRITE_DATA))) { return False; @@ -172,12 +172,7 @@ bool can_access_file_data(connection_struct *conn, const char *fname, SMB_STRUCT return True; } - if (!VALID_STAT(*psbuf)) { - /* Get the file permission mask and owners. */ - if(SMB_VFS_STAT(conn, fname, psbuf) != 0) { - return False; - } - } + SMB_ASSERT(psbuf && VALID_STAT(*psbuf)); /* Check primary owner access. */ if (conn->server_info->utok.uid == psbuf->st_ex_uid) { @@ -208,7 +203,7 @@ bool can_access_file_data(connection_struct *conn, const char *fname, SMB_STRUCT Note this doesn't take into account share write permissions. ****************************************************************************/ -bool can_write_to_file(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf) +bool can_write_to_file(connection_struct *conn, const char *fname, const SMB_STRUCT_STAT *psbuf) { return can_access_file_data(conn, fname, psbuf, FILE_WRITE_DATA); } diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 73c062e69fe..222caae5169 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1205,12 +1205,10 @@ void reply_ntcancel(struct smb_request *req) static NTSTATUS copy_internals(TALLOC_CTX *ctx, connection_struct *conn, struct smb_request *req, - const char *oldname_in, - const char *newname_in, + struct smb_filename *smb_fname_src, + struct smb_filename *smb_fname_dst, uint32 attrs) { - struct smb_filename *smb_fname_src = NULL; - struct smb_filename *smb_fname_dst = NULL; char *oldname = NULL; char *newname = NULL; files_struct *fsp1,*fsp2; @@ -1225,16 +1223,6 @@ static NTSTATUS copy_internals(TALLOC_CTX *ctx, goto out; } - status = unix_convert(ctx, conn, oldname_in, &smb_fname_src, 0); - if (!NT_STATUS_IS_OK(status)) { - goto out; - } - - status = check_name(conn, smb_fname_src->base_name); - if (!NT_STATUS_IS_OK(status)) { - goto out; - } - /* Source must already exist. */ if (!VALID_STAT(smb_fname_src->st)) { status = NT_STATUS_OBJECT_NAME_NOT_FOUND; @@ -1253,16 +1241,6 @@ static NTSTATUS copy_internals(TALLOC_CTX *ctx, goto out; } - status = unix_convert(ctx, conn, newname_in, &smb_fname_dst, 0); - if (!NT_STATUS_IS_OK(status)) { - goto out; - } - - status = check_name(conn, smb_fname_dst->base_name); - if (!NT_STATUS_IS_OK(status)) { - goto out; - } - /* Disallow if dst file already exists. */ if (VALID_STAT(smb_fname_dst->st)) { status = NT_STATUS_OBJECT_NAME_COLLISION; @@ -1275,12 +1253,6 @@ static NTSTATUS copy_internals(TALLOC_CTX *ctx, goto out; } - /* Ensure this is within the share. */ - status = check_reduced_name(conn, smb_fname_src->base_name); - if (!NT_STATUS_IS_OK(status)) { - goto out; - } - DEBUG(10,("copy_internals: doing file copy %s to %s\n", smb_fname_str_dbg(smb_fname_src), smb_fname_str_dbg(smb_fname_dst))); @@ -1374,8 +1346,6 @@ static NTSTATUS copy_internals(TALLOC_CTX *ctx, smb_fname_str_dbg(smb_fname_dst))); } - TALLOC_FREE(smb_fname_src); - TALLOC_FREE(smb_fname_dst); TALLOC_FREE(oldname); TALLOC_FREE(newname); @@ -1501,8 +1471,10 @@ void reply_ntrename(struct smb_request *req) /* No wildcards. */ status = NT_STATUS_OBJECT_PATH_SYNTAX_BAD; } else { - status = copy_internals(ctx, conn, req, oldname, - newname, attrs); + status = copy_internals(ctx, conn, req, + smb_fname_old, + smb_fname_new, + attrs); } break; case RENAME_FLAG_MOVE_CLUSTER_INFORMATION: diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 5d82738f6ab..d6331ee487a 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -3401,7 +3401,6 @@ NTSTATUS create_file_default(connection_struct *conn, uint64_t allocation_size, struct security_descriptor *sd, struct ea_list *ea_list, - files_struct **result, int *pinfo) { diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 2d0062ab947..6eed92cb3ed 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -2548,9 +2548,8 @@ static bool current_user_in_group(gid_t gid) static bool acl_group_override(connection_struct *conn, gid_t prim_gid, - const char *fname) + files_struct *fsp) { - SMB_STRUCT_STAT sbuf; if ((errno != EPERM) && (errno != EACCES)) { return false; @@ -2563,9 +2562,23 @@ static bool acl_group_override(connection_struct *conn, } /* user has writeable permission */ - if (lp_dos_filemode(SNUM(conn)) && - can_write_to_file(conn, fname, &sbuf)) { - return true; + if (lp_dos_filemode(SNUM(conn))) { + SMB_STRUCT_STAT sbuf; + int ret; + + if (fsp->posix_open) { + ret = SMB_VFS_LSTAT(conn,fsp->fsp_name,&sbuf); + } else { + ret = SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf); + } + + if (ret == -1) { + return false; + } + + if (can_write_to_file(conn, fsp->fsp_name, &sbuf)) { + return true; + } } return false; @@ -2754,7 +2767,7 @@ static bool set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, bool defau *pacl_set_support = False; } - if (acl_group_override(conn, prim_gid, fsp->fsp_name)) { + if (acl_group_override(conn, prim_gid, fsp)) { int sret; DEBUG(5,("set_canon_ace_list: acl group control on and current user in file %s primary group.\n", @@ -2785,7 +2798,7 @@ static bool set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, bool defau *pacl_set_support = False; } - if (acl_group_override(conn, prim_gid, fsp->fsp_name)) { + if (acl_group_override(conn, prim_gid, fsp)) { int sret; DEBUG(5,("set_canon_ace_list: acl group control on and current user in file %s primary group.\n", @@ -3831,7 +3844,7 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC unbecome_root(); } if (sret == -1) { - if (acl_group_override(conn, sbuf.st_ex_gid, fsp->fsp_name)) { + if (acl_group_override(conn, sbuf.st_ex_gid, fsp)) { DEBUG(5,("set_nt_acl: acl group control on and " "current user in file %s primary group. Override delete_def_acl\n", fsp->fsp_name )); @@ -3893,7 +3906,7 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC unbecome_root(); } if(sret == -1) { - if (acl_group_override(conn, sbuf.st_ex_gid, fsp->fsp_name)) { + if (acl_group_override(conn, sbuf.st_ex_gid, fsp)) { DEBUG(5,("set_nt_acl: acl group control on and " "current user in file %s primary group. Override chmod\n", fsp->fsp_name )); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index f11f3bfed7d..9544b845da5 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1323,6 +1323,7 @@ static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in, void reply_search(struct smb_request *req) { connection_struct *conn = req->conn; + char *path = NULL; const char *mask = NULL; char *directory = NULL; char *fname = NULL; @@ -1335,7 +1336,6 @@ void reply_search(struct smb_request *req) bool finished = False; const char *p; int status_len; - char *path = NULL; char status[21]; int dptr_num= -1; bool check_descend = False; @@ -1377,23 +1377,6 @@ void reply_search(struct smb_request *req) return; } - nt_status = resolve_dfspath_wcard(ctx, conn, - req->flags2 & FLAGS2_DFS_PATHNAMES, - path, - &path, - &mask_contains_wcard); - if (!NT_STATUS_IS_OK(nt_status)) { - if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) { - reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, - ERRSRV, ERRbadpath); - END_PROFILE(SMBsearch); - return; - } - reply_nterror(req, nt_status); - END_PROFILE(SMBsearch); - return; - } - p++; status_len = SVAL(p, 0); p += 2; @@ -1403,6 +1386,23 @@ void reply_search(struct smb_request *req) if (status_len == 0) { struct smb_filename *smb_fname = NULL; + nt_status = resolve_dfspath_wcard(ctx, conn, + req->flags2 & FLAGS2_DFS_PATHNAMES, + path, + &path, + &mask_contains_wcard); + if (!NT_STATUS_IS_OK(nt_status)) { + if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) { + reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, + ERRSRV, ERRbadpath); + END_PROFILE(SMBsearch); + return; + } + reply_nterror(req, nt_status); + END_PROFILE(SMBsearch); + return; + } + nt_status = unix_convert(ctx, conn, path, &smb_fname, UCF_ALLOW_WCARD_LCOMP); if (!NT_STATUS_IS_OK(nt_status)) { -- 2.34.1