diff options
Diffstat (limited to 'source3/smbd')
-rw-r--r-- | source3/smbd/dir.c | 48 | ||||
-rw-r--r-- | source3/smbd/dosmode.c | 177 | ||||
-rw-r--r-- | source3/smbd/fileio.c | 34 | ||||
-rw-r--r-- | source3/smbd/nttrans.c | 18 | ||||
-rw-r--r-- | source3/smbd/open.c | 21 | ||||
-rw-r--r-- | source3/smbd/posix_acls.c | 260 | ||||
-rw-r--r-- | source3/smbd/reply.c | 65 | ||||
-rw-r--r-- | source3/smbd/smb2_create.c | 13 | ||||
-rw-r--r-- | source3/smbd/trans2.c | 120 |
9 files changed, 417 insertions, 339 deletions
diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 723fb6fd6f2..642fb09362c 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -876,6 +876,8 @@ bool get_dir_entry(TALLOC_CTX *ctx, mask_match_search(filename,mask,False) || mangle_mask_match(conn,filename,mask)) { char mname[13]; + struct smb_filename *smb_fname = NULL; + NTSTATUS status; if (!mangle_is_8_3(filename, False, conn->params)) { if (!name_to_8_3(filename,mname,False, @@ -905,51 +907,47 @@ bool get_dir_entry(TALLOC_CTX *ctx, return False; } - if (!VALID_STAT(sbuf)) { - struct smb_filename *smb_fname = NULL; - NTSTATUS status; - - /* Create smb_fname with NULL stream_name. */ - status = - create_synthetic_smb_fname(ctx, pathreal, - NULL, NULL, - &smb_fname); - if (!NT_STATUS_IS_OK(status)) { - TALLOC_FREE(pathreal); - TALLOC_FREE(filename); - return NULL; - } + /* Create smb_fname with NULL stream_name. */ + status = create_synthetic_smb_fname(ctx, pathreal, + NULL, &sbuf, + &smb_fname); + TALLOC_FREE(pathreal); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(filename); + return false; + } + + if (!VALID_STAT(smb_fname->st)) { if ((SMB_VFS_STAT(conn, smb_fname)) != 0) { DEBUG(5,("Couldn't stat 1 [%s]. Error " - "= %s\n", pathreal, + "= %s\n", + smb_fname_str_dbg(smb_fname), strerror(errno))); TALLOC_FREE(smb_fname); - TALLOC_FREE(pathreal); TALLOC_FREE(filename); continue; } - sbuf = smb_fname->st; - TALLOC_FREE(smb_fname); } - *mode = dos_mode(conn,pathreal,&sbuf); + *mode = dos_mode(conn, smb_fname); if (!dir_check_ftype(conn,*mode,dirtype)) { DEBUG(5,("[%s] attribs 0x%x didn't match 0x%x\n",filename,(unsigned int)*mode,(unsigned int)dirtype)); - TALLOC_FREE(pathreal); + TALLOC_FREE(smb_fname); TALLOC_FREE(filename); continue; } - *size = sbuf.st_ex_size; - *date = sbuf.st_ex_mtime; + *size = smb_fname->st.st_ex_size; + *date = smb_fname->st.st_ex_mtime; if (ask_sharemode) { struct timespec write_time_ts; struct file_id fileid; - fileid = vfs_file_id_from_sbuf(conn, &sbuf); + fileid = vfs_file_id_from_sbuf(conn, + &smb_fname->st); get_file_infos(fileid, NULL, &write_time_ts); if (!null_timespec(write_time_ts)) { *date = write_time_ts; @@ -959,7 +957,7 @@ bool get_dir_entry(TALLOC_CTX *ctx, DEBUG(3,("get_dir_entry mask=[%s] found %s " "fname=%s (%s)\n", mask, - pathreal, + smb_fname_str_dbg(smb_fname), dname, filename)); @@ -969,7 +967,7 @@ bool get_dir_entry(TALLOC_CTX *ctx, *pp_fname_out = filename; DirCacheAdd(conn->dirptr->dir_hnd, dname, curoff); - TALLOC_FREE(pathreal); + TALLOC_FREE(smb_fname); } if (!found) diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 9bd097c0bbe..ca926aa33c5 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -158,45 +158,38 @@ mode_t unix_mode(connection_struct *conn, int dosmode, Change a unix mode to a dos mode. ****************************************************************************/ -static uint32 dos_mode_from_sbuf(connection_struct *conn, const char *path, const SMB_STRUCT_STAT *sbuf) +static uint32 dos_mode_from_sbuf(connection_struct *conn, + const struct smb_filename *smb_fname) { int result = 0; enum mapreadonly_options ro_opts = (enum mapreadonly_options)lp_map_readonly(SNUM(conn)); if (ro_opts == MAP_READONLY_YES) { /* Original Samba method - map inverse of user "w" bit. */ - if ((sbuf->st_ex_mode & S_IWUSR) == 0) { + if ((smb_fname->st.st_ex_mode & S_IWUSR) == 0) { result |= aRONLY; } } else if (ro_opts == MAP_READONLY_PERMISSIONS) { - struct smb_filename *smb_fname = NULL; - NTSTATUS status; - - status = create_synthetic_smb_fname_split(talloc_tos(), path, - sbuf, &smb_fname); - if (NT_STATUS_IS_OK(status)) { - /* Check actual permissions for read-only. */ - if (!can_write_to_file(conn, smb_fname)) { - result |= aRONLY; - } + /* Check actual permissions for read-only. */ + if (!can_write_to_file(conn, smb_fname)) { + result |= aRONLY; } - TALLOC_FREE(smb_fname); } /* Else never set the readonly bit. */ - if (MAP_ARCHIVE(conn) && ((sbuf->st_ex_mode & S_IXUSR) != 0)) + if (MAP_ARCHIVE(conn) && ((smb_fname->st.st_ex_mode & S_IXUSR) != 0)) result |= aARCH; - if (MAP_SYSTEM(conn) && ((sbuf->st_ex_mode & S_IXGRP) != 0)) + if (MAP_SYSTEM(conn) && ((smb_fname->st.st_ex_mode & S_IXGRP) != 0)) result |= aSYSTEM; - if (MAP_HIDDEN(conn) && ((sbuf->st_ex_mode & S_IXOTH) != 0)) + if (MAP_HIDDEN(conn) && ((smb_fname->st.st_ex_mode & S_IXOTH) != 0)) result |= aHIDDEN; - if (S_ISDIR(sbuf->st_ex_mode)) + if (S_ISDIR(smb_fname->st.st_ex_mode)) result = aDIR | (result & aRONLY); - result |= set_sparse_flag(sbuf); - result |= set_link_read_only_flag(sbuf); + result |= set_sparse_flag(&smb_fname->st); + result |= set_link_read_only_flag(&smb_fname->st); DEBUG(8,("dos_mode_from_sbuf returning ")); @@ -214,7 +207,9 @@ static uint32 dos_mode_from_sbuf(connection_struct *conn, const char *path, cons Get DOS attributes from an EA. ****************************************************************************/ -static bool get_ea_dos_attribute(connection_struct *conn, const char *path, const SMB_STRUCT_STAT *sbuf, uint32 *pattr) +static bool get_ea_dos_attribute(connection_struct *conn, + const struct smb_filename *smb_fname, + uint32 *pattr) { ssize_t sizeret; fstring attrstr; @@ -227,7 +222,9 @@ static bool get_ea_dos_attribute(connection_struct *conn, const char *path, cons /* Don't reset pattr to zero as we may already have filename-based attributes we need to preserve. */ - sizeret = SMB_VFS_GETXATTR(conn, path, SAMBA_XATTR_DOS_ATTRIB, attrstr, sizeof(attrstr)); + sizeret = SMB_VFS_GETXATTR(conn, smb_fname->base_name, + SAMBA_XATTR_DOS_ATTRIB, attrstr, + sizeof(attrstr)); if (sizeret == -1) { if (errno == ENOSYS #if defined(ENOTSUP) @@ -235,23 +232,28 @@ static bool get_ea_dos_attribute(connection_struct *conn, const char *path, cons #else ) { #endif - DEBUG(1,("get_ea_dos_attributes: Cannot get attribute from EA on file %s: Error = %s\n", - path, strerror(errno) )); + DEBUG(1,("get_ea_dos_attributes: Cannot get attribute " + "from EA on file %s: Error = %s\n", + smb_fname_str_dbg(smb_fname), + strerror(errno))); set_store_dos_attributes(SNUM(conn), False); } return False; } /* Null terminate string. */ attrstr[sizeret] = 0; - DEBUG(10,("get_ea_dos_attribute: %s attrstr = %s\n", path, attrstr)); + DEBUG(10,("get_ea_dos_attribute: %s attrstr = %s\n", + smb_fname_str_dbg(smb_fname), attrstr)); if (sizeret < 2 || attrstr[0] != '0' || attrstr[1] != 'x' || sscanf(attrstr, "%x", &dosattr) != 1) { - DEBUG(1,("get_ea_dos_attributes: Badly formed DOSATTRIB on file %s - %s\n", path, attrstr)); + DEBUG(1,("get_ea_dos_attributes: Badly formed DOSATTRIB on " + "file %s - %s\n", smb_fname_str_dbg(smb_fname), + attrstr)); return False; } - if (S_ISDIR(sbuf->st_ex_mode)) { + if (S_ISDIR(smb_fname->st.st_ex_mode)) { dosattr |= aDIR; } *pattr = (uint32)(dosattr & SAMBA_ATTRIBUTES_MASK); @@ -273,7 +275,9 @@ static bool get_ea_dos_attribute(connection_struct *conn, const char *path, cons Set DOS attributes in an EA. ****************************************************************************/ -static bool set_ea_dos_attribute(connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf, uint32 dosmode) +static bool set_ea_dos_attribute(connection_struct *conn, + struct smb_filename *smb_fname, + uint32 dosmode) { fstring attrstr; files_struct *fsp = NULL; @@ -284,7 +288,9 @@ static bool set_ea_dos_attribute(connection_struct *conn, const char *path, SMB_ } snprintf(attrstr, sizeof(attrstr)-1, "0x%x", dosmode & SAMBA_ATTRIBUTES_MASK); - if (SMB_VFS_SETXATTR(conn, path, SAMBA_XATTR_DOS_ATTRIB, attrstr, strlen(attrstr), 0) == -1) { + if (SMB_VFS_SETXATTR(conn, smb_fname->base_name, + SAMBA_XATTR_DOS_ATTRIB, attrstr, strlen(attrstr), + 0) == -1) { if((errno != EPERM) && (errno != EACCES)) { if (errno == ENOSYS #if defined(ENOTSUP) @@ -292,8 +298,10 @@ static bool set_ea_dos_attribute(connection_struct *conn, const char *path, SMB_ #else ) { #endif - DEBUG(1,("set_ea_dos_attributes: Cannot set attribute EA on file %s: Error = %s\n", - path, strerror(errno) )); + DEBUG(1,("set_ea_dos_attributes: Cannot set " + "attribute EA on file %s: Error = %s\n", + smb_fname_str_dbg(smb_fname), + strerror(errno) )); set_store_dos_attributes(SNUM(conn), False); } return False; @@ -313,18 +321,21 @@ static bool set_ea_dos_attribute(connection_struct *conn, const char *path, SMB_ * are not violating security in doing the setxattr. */ - if (!NT_STATUS_IS_OK(open_file_fchmod(NULL, conn, path, sbuf, + if (!NT_STATUS_IS_OK(open_file_fchmod(NULL, conn, smb_fname, &fsp))) return ret; become_root(); - if (SMB_VFS_SETXATTR(conn, path, SAMBA_XATTR_DOS_ATTRIB, attrstr, strlen(attrstr), 0) == 0) { + if (SMB_VFS_SETXATTR(conn, smb_fname->base_name, + SAMBA_XATTR_DOS_ATTRIB, attrstr, + strlen(attrstr), 0) == 0) { ret = True; } unbecome_root(); close_file_fchmod(NULL, fsp); return ret; } - DEBUG(10,("set_ea_dos_attribute: set EA %s on file %s\n", attrstr, path)); + DEBUG(10,("set_ea_dos_attribute: set EA %s on file %s\n", attrstr, + smb_fname_str_dbg(smb_fname))); return True; } @@ -332,25 +343,25 @@ 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, const SMB_STRUCT_STAT *psbuf) +uint32 dos_mode_msdfs(connection_struct *conn, + const struct smb_filename *smb_fname) { - SMB_STRUCT_STAT sbuf = *psbuf; uint32 result = 0; - DEBUG(8,("dos_mode_msdfs: %s\n", path)); + DEBUG(8,("dos_mode_msdfs: %s\n", smb_fname_str_dbg(smb_fname))); - if (!VALID_STAT(sbuf)) { + if (!VALID_STAT(smb_fname->st)) { return 0; } /* First do any modifications that depend on the path name. */ /* hide files with a name starting with a . */ if (lp_hide_dot_files(SNUM(conn))) { - const char *p = strrchr_m(path,'/'); + const char *p = strrchr_m(smb_fname->base_name, '/'); if (p) { p++; } else { - p = path; + p = smb_fname->base_name; } /* Only . and .. are not hidden. */ @@ -360,11 +371,12 @@ uint32 dos_mode_msdfs(connection_struct *conn, const char *path, const SMB_STRUC } } - result |= dos_mode_from_sbuf(conn, path, &sbuf); + result |= dos_mode_from_sbuf(conn, smb_fname); /* Optimization : Only call is_hidden_path if it's not already hidden. */ - if (!(result & aHIDDEN) && IS_HIDDEN_PATH(conn,path)) { + if (!(result & aHIDDEN) && + IS_HIDDEN_PATH(conn, smb_fname->base_name)) { result |= aHIDDEN; } @@ -410,34 +422,34 @@ int dos_attributes_to_stat_dos_flags(uint32_t dosmode) ****************************************************************************/ static bool get_stat_dos_flags(connection_struct *conn, - const char *fname, - const SMB_STRUCT_STAT *sbuf, + const struct smb_filename *smb_fname, uint32_t *dosmode) { - SMB_ASSERT(sbuf && VALID_STAT(*sbuf)); + SMB_ASSERT(VALID_STAT(smb_fname->st)); SMB_ASSERT(dosmode); if (!lp_store_dos_attributes(SNUM(conn))) { return false; } - DEBUG(5, ("Getting stat dos attributes for %s.\n", fname)); + DEBUG(5, ("Getting stat dos attributes for %s.\n", + smb_fname_str_dbg(smb_fname))); - if (sbuf->st_ex_flags & UF_DOS_ARCHIVE) + if (smb_fname->st.st_ex_flags & UF_DOS_ARCHIVE) *dosmode |= aARCH; - if (sbuf->st_ex_flags & UF_DOS_HIDDEN) + if (smb_fname->st.st_ex_flags & UF_DOS_HIDDEN) *dosmode |= aHIDDEN; - if (sbuf->st_ex_flags & UF_DOS_RO) + if (smb_fname->st.st_ex_flags & UF_DOS_RO) *dosmode |= aRONLY; - if (sbuf->st_ex_flags & UF_DOS_SYSTEM) + if (smb_fname->st.st_ex_flags & UF_DOS_SYSTEM) *dosmode |= aSYSTEM; - if (sbuf->st_ex_flags & UF_DOS_NOINDEX) + if (smb_fname->st.st_ex_flags & UF_DOS_NOINDEX) *dosmode |= FILE_ATTRIBUTE_NONINDEXED; - if (S_ISDIR(sbuf->st_ex_mode)) + if (S_ISDIR(smb_fname->st.st_ex_mode)) *dosmode |= aDIR; - *dosmode |= set_sparse_flag(sbuf); - *dosmode |= set_link_read_only_flag(sbuf); + *dosmode |= set_sparse_flag(smb_fname->st); + *dosmode |= set_link_read_only_flag(smb_fname->st); return true; } @@ -494,26 +506,26 @@ 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, const SMB_STRUCT_STAT *psbuf) +uint32 dos_mode(connection_struct *conn, const struct smb_filename *smb_fname) { - SMB_STRUCT_STAT sbuf = *psbuf; + SMB_STRUCT_STAT sbuf; uint32 result = 0; bool offline, used_stat_dos_flags = false; - DEBUG(8,("dos_mode: %s\n", path)); + DEBUG(8,("dos_mode: %s\n", smb_fname_str_dbg(smb_fname))); - if (!VALID_STAT(sbuf)) { + if (!VALID_STAT(smb_fname->st)) { return 0; } /* First do any modifications that depend on the path name. */ /* hide files with a name starting with a . */ if (lp_hide_dot_files(SNUM(conn))) { - const char *p = strrchr_m(path,'/'); + const char *p = strrchr_m(smb_fname->base_name,'/'); if (p) { p++; } else { - p = path; + p = smb_fname->base_name; } /* Only . and .. are not hidden. */ @@ -524,25 +536,27 @@ uint32 dos_mode(connection_struct *conn, const char *path, const SMB_STRUCT_STAT } #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, smb_fname, &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, smb_fname, &result)) { + result |= set_sparse_flag(&smb_fname->st); } else { - result |= dos_mode_from_sbuf(conn, path, &sbuf); + result |= dos_mode_from_sbuf(conn, smb_fname); } } - offline = SMB_VFS_IS_OFFLINE(conn, path, &sbuf); + sbuf = smb_fname->st; + offline = SMB_VFS_IS_OFFLINE(conn, smb_fname->base_name, &sbuf); if (S_ISREG(sbuf.st_ex_mode) && offline) { result |= FILE_ATTRIBUTE_OFFLINE; } /* Optimization : Only call is_hidden_path if it's not already hidden. */ - if (!(result & aHIDDEN) && IS_HIDDEN_PATH(conn,path)) { + if (!(result & aHIDDEN) && + IS_HIDDEN_PATH(conn, smb_fname->base_name)) { result |= aHIDDEN; } @@ -572,8 +586,6 @@ int file_set_dosmode(connection_struct *conn, struct smb_filename *smb_fname, mode_t unixmode; int ret = -1, lret = -1; uint32_t old_mode; - char *fname = NULL; - NTSTATUS status; /* We only allow READONLY|HIDDEN|SYSTEM|DIRECTORY|ARCHIVE here. */ dosmode &= (SAMBA_ATTRIBUTES_MASK | FILE_ATTRIBUTE_OFFLINE); @@ -596,17 +608,11 @@ int file_set_dosmode(connection_struct *conn, struct smb_filename *smb_fname, else dosmode &= ~aDIR; - status = get_full_smb_filename(talloc_tos(), smb_fname, &fname); - if (!NT_STATUS_IS_OK(status)) { - errno = map_errno_from_nt_status(status); - return -1; - } - - old_mode = dos_mode(conn, fname, &smb_fname->st); + old_mode = dos_mode(conn, smb_fname); if (dosmode & FILE_ATTRIBUTE_OFFLINE) { if (!(old_mode & FILE_ATTRIBUTE_OFFLINE)) { - lret = SMB_VFS_SET_OFFLINE(conn, fname); + lret = SMB_VFS_SET_OFFLINE(conn, smb_fname->base_name); if (lret == -1) { DEBUG(0, ("set_dos_mode: client has asked to " "set FILE_ATTRIBUTE_OFFLINE to " @@ -635,19 +641,20 @@ int file_set_dosmode(connection_struct *conn, struct smb_filename *smb_fname, { if (!newfile && attributes_changed) { notify_fname(conn, NOTIFY_ACTION_MODIFIED, - FILE_NOTIFY_CHANGE_ATTRIBUTES, fname); + FILE_NOTIFY_CHANGE_ATTRIBUTES, + smb_fname->base_name); } smb_fname->st.st_ex_mode = unixmode; return 0; } } #endif - /* Store the DOS attributes in an EA by preference. */ - if (set_ea_dos_attribute(conn, fname, &smb_fname->st, dosmode)) { + if (set_ea_dos_attribute(conn, smb_fname, dosmode)) { if (!newfile) { notify_fname(conn, NOTIFY_ACTION_MODIFIED, - FILE_NOTIFY_CHANGE_ATTRIBUTES, fname); + FILE_NOTIFY_CHANGE_ATTRIBUTES, + smb_fname->base_name); } smb_fname->st.st_ex_mode = unixmode; return 0; @@ -685,11 +692,12 @@ int file_set_dosmode(connection_struct *conn, struct smb_filename *smb_fname, unixmode |= (smb_fname->st.st_ex_mode & (S_IWUSR|S_IWGRP|S_IWOTH)); } - ret = SMB_VFS_CHMOD(conn, fname, unixmode); + ret = SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode); if (ret == 0) { if(!newfile || (lret != -1)) { notify_fname(conn, NOTIFY_ACTION_MODIFIED, - FILE_NOTIFY_CHANGE_ATTRIBUTES, fname); + FILE_NOTIFY_CHANGE_ATTRIBUTES, + smb_fname->base_name); } smb_fname->st.st_ex_mode = unixmode; return 0; @@ -716,8 +724,8 @@ int file_set_dosmode(connection_struct *conn, struct smb_filename *smb_fname, * break batch oplocks open by others. JRA. */ files_struct *fsp; - if (!NT_STATUS_IS_OK(open_file_fchmod(NULL, conn, fname, - &smb_fname->st, &fsp))) + if (!NT_STATUS_IS_OK(open_file_fchmod(NULL, conn, smb_fname, + &fsp))) return -1; become_root(); ret = SMB_VFS_FCHMOD(fsp, unixmode); @@ -725,7 +733,8 @@ int file_set_dosmode(connection_struct *conn, struct smb_filename *smb_fname, close_file_fchmod(NULL, fsp); if (!newfile) { notify_fname(conn, NOTIFY_ACTION_MODIFIED, - FILE_NOTIFY_CHANGE_ATTRIBUTES, fname); + FILE_NOTIFY_CHANGE_ATTRIBUTES, + smb_fname->base_name); } if (ret == 0) { smb_fname->st.st_ex_mode = unixmode; diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index caaebf6217b..0c13b845df8 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -284,32 +284,28 @@ ssize_t write_file(struct smb_request *req, } if (!fsp->modified) { - SMB_STRUCT_STAT st; + struct smb_filename *smb_fname = NULL; + NTSTATUS status; + fsp->modified = True; - if (SMB_VFS_FSTAT(fsp, &st) == 0) { + status = create_synthetic_smb_fname_split(talloc_tos(), + fsp->fsp_name, NULL, + &smb_fname); + if (!NT_STATUS_IS_OK(status)) { + errno = map_errno_from_nt_status(status); + return -1; + } + + if (SMB_VFS_FSTAT(fsp, &smb_fname->st) == 0) { int dosmode; trigger_write_time_update(fsp); - dosmode = dos_mode(fsp->conn,fsp->fsp_name,&st); + dosmode = dos_mode(fsp->conn, smb_fname); if ((lp_store_dos_attributes(SNUM(fsp->conn)) || MAP_ARCHIVE(fsp->conn)) && !IS_DOS_ARCHIVE(dosmode)) { - struct smb_filename *smb_fname = NULL; - NTSTATUS status; - - status = create_synthetic_smb_fname_split( - talloc_tos(), fsp->fsp_name, &st, - &smb_fname); - if (!NT_STATUS_IS_OK(status)) { - errno = - map_errno_from_nt_status(status); - return -1; - } - file_set_dosmode(fsp->conn, smb_fname, dosmode | aARCH, NULL, false); - st = smb_fname->st; - TALLOC_FREE(smb_fname); } /* @@ -318,10 +314,12 @@ ssize_t write_file(struct smb_request *req, */ if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && !wcp) { - setup_write_cache(fsp, st.st_ex_size); + setup_write_cache(fsp, + smb_fname->st.st_ex_size); wcp = fsp->wcp; } } + TALLOC_FREE(smb_fname); } #ifdef WITH_PROFILE diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 5d676470c8a..e28e6f3a843 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -620,7 +620,7 @@ void reply_ntcreate_and_X(struct smb_request *req) } file_len = smb_fname->st.st_ex_size; - fattr = dos_mode(conn,fsp->fsp_name,&smb_fname->st); + fattr = dos_mode(conn, smb_fname); if (fattr == 0) { fattr = FILE_ATTRIBUTE_NORMAL; } @@ -704,7 +704,7 @@ void reply_ntcreate_and_X(struct smb_request *req) } DEBUG(5,("reply_ntcreate_and_X: fnum = %d, open name = %s\n", - fsp->fnum, fsp->fsp_name)); + fsp->fnum, smb_fname_str_dbg(smb_fname))); chain_reply(req); out: @@ -1111,7 +1111,7 @@ static void call_nt_transact_create(connection_struct *conn, } file_len = smb_fname->st.st_ex_size; - fattr = dos_mode(conn, fsp->fsp_name, &smb_fname->st); + fattr = dos_mode(conn, smb_fname); if (fattr == 0) { fattr = FILE_ATTRIBUTE_NORMAL; } @@ -1194,7 +1194,8 @@ static void call_nt_transact_create(connection_struct *conn, SIVAL(p,0,perms); } - DEBUG(5,("call_nt_transact_create: open name = %s\n", fsp->fsp_name)); + DEBUG(5,("call_nt_transact_create: open name = %s\n", + smb_fname_str_dbg(smb_fname))); /* Send the required number of replies */ send_nt_replies(conn, req, NT_STATUS_OK, params, param_len, *ppdata, 0); @@ -1236,7 +1237,6 @@ static NTSTATUS copy_internals(TALLOC_CTX *ctx, struct smb_filename *smb_fname_dst, uint32 attrs) { - char *oldname = NULL; files_struct *fsp1,*fsp2; uint32 fattr; int info; @@ -1255,13 +1255,8 @@ static NTSTATUS copy_internals(TALLOC_CTX *ctx, goto out; } - status = get_full_smb_filename(ctx, smb_fname_src, &oldname); - if (!NT_STATUS_IS_OK(status)) { - goto out; - } - /* Ensure attributes match. */ - fattr = dos_mode(conn, oldname, &smb_fname_src->st); + fattr = dos_mode(conn, smb_fname_src); if ((fattr & ~attrs) & (aHIDDEN | aSYSTEM)) { status = NT_STATUS_NO_SUCH_FILE; goto out; @@ -1367,7 +1362,6 @@ static NTSTATUS copy_internals(TALLOC_CTX *ctx, smb_fname_str_dbg(smb_fname_dst))); } - TALLOC_FREE(oldname); return status; } diff --git a/source3/smbd/open.c b/source3/smbd/open.c index a58cffa2578..e73b3e4fdd3 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1567,8 +1567,7 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, if (!posix_open) { new_dos_attributes &= SAMBA_ATTRIBUTES_MASK; if (file_existed) { - existing_dos_attributes = dos_mode(conn, fname, - &smb_fname->st); + existing_dos_attributes = dos_mode(conn, smb_fname); } } @@ -2265,14 +2264,13 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn, ****************************************************************************/ NTSTATUS open_file_fchmod(struct smb_request *req, connection_struct *conn, - const char *fname, - SMB_STRUCT_STAT *psbuf, files_struct **result) + struct smb_filename *smb_fname, + files_struct **result) { - struct smb_filename *smb_fname = NULL; files_struct *fsp = NULL; NTSTATUS status; - if (!VALID_STAT(*psbuf)) { + if (!VALID_STAT(smb_fname->st)) { return NT_STATUS_INVALID_PARAMETER; } @@ -2281,12 +2279,6 @@ NTSTATUS open_file_fchmod(struct smb_request *req, connection_struct *conn, return status; } - status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf, - &smb_fname); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - status = SMB_VFS_CREATE_FILE( conn, /* conn */ NULL, /* req */ @@ -2303,10 +2295,7 @@ NTSTATUS open_file_fchmod(struct smb_request *req, connection_struct *conn, NULL, /* sd */ NULL, /* ea_list */ &fsp, /* result */ - NULL); /* psbuf */ - - *psbuf = smb_fname->st; - TALLOC_FREE(smb_fname); + NULL); /* pinfo */ /* * This is not a user visible file open. diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index 0c7f4b7bb7f..76eee9b56aa 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -2560,36 +2560,23 @@ static bool current_user_in_group(gid_t gid) ****************************************************************************/ static bool acl_group_override(connection_struct *conn, - const SMB_STRUCT_STAT *psbuf, - const char *fname) + const struct smb_filename *smb_fname) { - struct smb_filename *smb_fname = NULL; - NTSTATUS status; - if ((errno != EPERM) && (errno != EACCES)) { return false; } /* file primary group == user primary or supplementary group */ if (lp_acl_group_control(SNUM(conn)) && - current_user_in_group(psbuf->st_ex_gid)) { + current_user_in_group(smb_fname->st.st_ex_gid)) { return true; } - status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf, - &smb_fname); - - if (!NT_STATUS_IS_OK(status)) { - return false; - } - /* user has writeable permission */ if (lp_dos_filemode(SNUM(conn)) && can_write_to_file(conn, smb_fname)) { - TALLOC_FREE(smb_fname); return true; } - TALLOC_FREE(smb_fname); return false; } @@ -2615,6 +2602,14 @@ static bool set_canon_ace_list(files_struct *fsp, SMB_ACL_TYPE_T the_acl_type = (default_ace ? SMB_ACL_TYPE_DEFAULT : SMB_ACL_TYPE_ACCESS); bool needs_mask = False; mode_t mask_perms = 0; + struct smb_filename *smb_fname = NULL; + NTSTATUS status; + + status = create_synthetic_smb_fname_split(talloc_tos(), fsp->fsp_name, + psbuf, &smb_fname); + if (!NT_STATUS_IS_OK(status)) { + goto fail; + } #if defined(POSIX_ACL_NEEDS_MASK) /* HP-UX always wants to have a mask (called "class" there). */ @@ -2632,7 +2627,7 @@ static bool set_canon_ace_list(files_struct *fsp, default_ace ? "default" : "file", strerror(errno) )); } *pacl_set_support = False; - return False; + goto fail; } if( DEBUGLVL( 10 )) { @@ -2772,7 +2767,8 @@ static bool set_canon_ace_list(files_struct *fsp, */ if(default_ace || fsp->is_directory || fsp->fh->fd == -1) { - if (SMB_VFS_SYS_ACL_SET_FILE(conn, fsp->fsp_name, the_acl_type, the_acl) == -1) { + if (SMB_VFS_SYS_ACL_SET_FILE(conn, smb_fname->base_name, + the_acl_type, the_acl) == -1) { /* * Some systems allow all the above calls and only fail with no ACL support * when attempting to apply the acl. HPUX with HFS is an example of this. JRA. @@ -2781,14 +2777,18 @@ static bool set_canon_ace_list(files_struct *fsp, *pacl_set_support = False; } - if (acl_group_override(conn, psbuf, fsp->fsp_name)) { + if (acl_group_override(conn, smb_fname)) { int sret; - DEBUG(5,("set_canon_ace_list: acl group control on and current user in file %s primary group.\n", - fsp->fsp_name )); + DEBUG(5,("set_canon_ace_list: acl group " + "control on and current user in file " + "%s primary group.\n", + smb_fname_str_dbg(smb_fname))); become_root(); - sret = SMB_VFS_SYS_ACL_SET_FILE(conn, fsp->fsp_name, the_acl_type, the_acl); + sret = SMB_VFS_SYS_ACL_SET_FILE(conn, + smb_fname->base_name, the_acl_type, + the_acl); unbecome_root(); if (sret == 0) { ret = True; @@ -2796,9 +2796,13 @@ static bool set_canon_ace_list(files_struct *fsp, } if (ret == False) { - DEBUG(2,("set_canon_ace_list: sys_acl_set_file type %s failed for file %s (%s).\n", - the_acl_type == SMB_ACL_TYPE_DEFAULT ? "directory default" : "file", - fsp->fsp_name, strerror(errno) )); + DEBUG(2,("set_canon_ace_list: " + "sys_acl_set_file type %s failed for " + "file %s (%s).\n", + the_acl_type == SMB_ACL_TYPE_DEFAULT ? + "directory default" : "file", + smb_fname_str_dbg(smb_fname), + strerror(errno))); goto fail; } } @@ -2812,11 +2816,13 @@ static bool set_canon_ace_list(files_struct *fsp, *pacl_set_support = False; } - if (acl_group_override(conn, psbuf, fsp->fsp_name)) { + if (acl_group_override(conn, smb_fname)) { int sret; - DEBUG(5,("set_canon_ace_list: acl group control on and current user in file %s primary group.\n", - fsp->fsp_name )); + DEBUG(5,("set_canon_ace_list: acl group " + "control on and current user in file " + "%s primary group.\n", + smb_fname_str_dbg(smb_fname))); become_root(); sret = SMB_VFS_SYS_ACL_SET_FD(fsp, the_acl); @@ -2827,8 +2833,11 @@ static bool set_canon_ace_list(files_struct *fsp, } if (ret == False) { - DEBUG(2,("set_canon_ace_list: sys_acl_set_file failed for file %s (%s).\n", - fsp->fsp_name, strerror(errno) )); + DEBUG(2,("set_canon_ace_list: " + "sys_acl_set_file failed for file %s " + "(%s).\n", + smb_fname_str_dbg(smb_fname), + strerror(errno) )); goto fail; } } @@ -2841,6 +2850,7 @@ static bool set_canon_ace_list(files_struct *fsp, if (the_acl != NULL) { SMB_VFS_SYS_ACL_FREE_ACL(conn, the_acl); } + TALLOC_FREE(smb_fname); return ret; } @@ -3405,11 +3415,11 @@ NTSTATUS posix_get_nt_acl(struct connection_struct *conn, const char *name, then allow chown to the currently authenticated user. ****************************************************************************/ -int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid) +int try_chown(connection_struct *conn, struct smb_filename *smb_fname, + uid_t uid, gid_t gid) { int ret; files_struct *fsp; - SMB_STRUCT_STAT st; if(!CAN_WRITE(conn)) { return -1; @@ -3417,7 +3427,7 @@ int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid) /* Case (1). */ /* try the direct way first */ - ret = SMB_VFS_CHOWN(conn, fname, uid, gid); + ret = SMB_VFS_CHOWN(conn, smb_fname->base_name, uid, gid); if (ret == 0) return 0; @@ -3436,7 +3446,8 @@ int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid) become_root(); /* Keep the current file gid the same - take ownership doesn't imply group change. */ - ret = SMB_VFS_CHOWN(conn, fname, uid, (gid_t)-1); + ret = SMB_VFS_CHOWN(conn, smb_fname->base_name, uid, + (gid_t)-1); unbecome_root(); return ret; } @@ -3457,11 +3468,11 @@ int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid) return -1; } - if (vfs_stat_smb_fname(conn,fname,&st)) { + if (SMB_VFS_STAT(conn, smb_fname)) { return -1; } - if (!NT_STATUS_IS_OK(open_file_fchmod(NULL, conn, fname, &st, &fsp))) { + if (!NT_STATUS_IS_OK(open_file_fchmod(NULL, conn, smb_fname, &fsp))) { return -1; } @@ -3507,8 +3518,8 @@ NTSTATUS append_parent_acl(files_struct *fsp, return NT_STATUS_NO_MEMORY; } - status = create_synthetic_smb_fname_split(mem_ctx, parent_name, NULL, - &smb_dname); + status = create_synthetic_smb_fname(mem_ctx, parent_name, NULL, NULL, + &smb_dname); if (!NT_STATUS_IS_OK(status)) { goto fail; } @@ -3530,16 +3541,16 @@ NTSTATUS append_parent_acl(files_struct *fsp, &parent_fsp, /* result */ &info); /* pinfo */ - TALLOC_FREE(smb_fname); - if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(smb_dname); return status; } - status = SMB_VFS_GET_NT_ACL(parent_fsp->conn, parent_fsp->fsp_name, + status = SMB_VFS_GET_NT_ACL(parent_fsp->conn, smb_dname->base_name, DACL_SECURITY_INFORMATION, &parent_sd ); close_file(NULL, parent_fsp, NORMAL_CLOSE); + TALLOC_FREE(smb_dname); if (!NT_STATUS_IS_OK(status)) { return status; @@ -3686,7 +3697,6 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC connection_struct *conn = fsp->conn; uid_t user = (uid_t)-1; gid_t grp = (gid_t)-1; - SMB_STRUCT_STAT sbuf; DOM_SID file_owner_sid; DOM_SID file_grp_sid; canon_ace *file_ace_list = NULL; @@ -3697,12 +3707,21 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC bool set_acl_as_root = false; bool acl_set_support = false; bool ret = false; + struct smb_filename *smb_fname = NULL; + + status = create_synthetic_smb_fname_split(talloc_tos(), fsp->fsp_name, + NULL, &smb_fname); + if (!NT_STATUS_IS_OK(status)) { + goto out; + } - DEBUG(10,("set_nt_acl: called for file %s\n", fsp->fsp_name )); + DEBUG(10,("set_nt_acl: called for file %s\n", + smb_fname_str_dbg(smb_fname))); if (!CAN_WRITE(conn)) { DEBUG(10,("set acl rejected on read-only share\n")); - return NT_STATUS_MEDIA_WRITE_PROTECTED; + status = NT_STATUS_MEDIA_WRITE_PROTECTED; + goto out; } /* @@ -3710,15 +3729,19 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC */ if(fsp->is_directory || fsp->fh->fd == -1) { - if(vfs_stat_smb_fname(fsp->conn,fsp->fsp_name, &sbuf) != 0) - return map_nt_error_from_unix(errno); + if(SMB_VFS_STAT(fsp->conn, smb_fname) != 0) { + status = map_nt_error_from_unix(errno); + goto out; + } } else { - if(SMB_VFS_FSTAT(fsp, &sbuf) != 0) - return map_nt_error_from_unix(errno); + if(SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) { + status = map_nt_error_from_unix(errno); + goto out; + } } /* Save the original element we check against. */ - orig_mode = sbuf.st_ex_mode; + orig_mode = smb_fname->st.st_ex_mode; /* * Unpack the user/group/world id's. @@ -3726,7 +3749,7 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC status = unpack_nt_owners( SNUM(conn), &user, &grp, security_info_sent, psd); if (!NT_STATUS_IS_OK(status)) { - return status; + goto out; } /* @@ -3735,18 +3758,24 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC * Noticed by Simo. */ - if (((user != (uid_t)-1) && (sbuf.st_ex_uid != user)) || (( grp != (gid_t)-1) && (sbuf.st_ex_gid != grp))) { + if (((user != (uid_t)-1) && (smb_fname->st.st_ex_uid != user)) || + (( grp != (gid_t)-1) && (smb_fname->st.st_ex_gid != grp))) { DEBUG(3,("set_nt_acl: chown %s. uid = %u, gid = %u.\n", - fsp->fsp_name, (unsigned int)user, (unsigned int)grp )); - - if(try_chown( fsp->conn, fsp->fsp_name, user, grp) == -1) { - DEBUG(3,("set_nt_acl: chown %s, %u, %u failed. Error = %s.\n", - fsp->fsp_name, (unsigned int)user, (unsigned int)grp, strerror(errno) )); + smb_fname_str_dbg(smb_fname), (unsigned int)user, + (unsigned int)grp )); + + if(try_chown(fsp->conn, smb_fname, user, grp) == -1) { + DEBUG(3,("set_nt_acl: chown %s, %u, %u failed. Error " + "= %s.\n", smb_fname_str_dbg(smb_fname), + (unsigned int)user, (unsigned int)grp, + strerror(errno))); if (errno == EPERM) { - return NT_STATUS_INVALID_OWNER; + status = NT_STATUS_INVALID_OWNER; + goto out; } - return map_nt_error_from_unix(errno); + status = map_nt_error_from_unix(errno); + goto out; } /* @@ -3755,27 +3784,25 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC */ if(fsp->is_directory) { - if(vfs_stat_smb_fname(fsp->conn, fsp->fsp_name, - &sbuf) != 0) { - return map_nt_error_from_unix(errno); + if(SMB_VFS_STAT(fsp->conn, smb_fname) != 0) { + status = map_nt_error_from_unix(errno); + goto out; } } else { int sret; if(fsp->fh->fd == -1) - sret = vfs_stat_smb_fname(fsp->conn, - fsp->fsp_name, - &sbuf); + sret = SMB_VFS_STAT(fsp->conn, smb_fname); else - sret = SMB_VFS_FSTAT(fsp, &sbuf); + sret = SMB_VFS_FSTAT(fsp, &smb_fname->st); if(sret != 0) return map_nt_error_from_unix(errno); } /* Save the original element we check against. */ - orig_mode = sbuf.st_ex_mode; + orig_mode = smb_fname->st.st_ex_mode; /* If we successfully chowned, we know we must * be able to set the acl, so do it as root. @@ -3783,21 +3810,24 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC set_acl_as_root = true; } - create_file_sids(&sbuf, &file_owner_sid, &file_grp_sid); + create_file_sids(&smb_fname->st, &file_owner_sid, &file_grp_sid); - acl_perms = unpack_canon_ace( fsp, &sbuf, &file_owner_sid, &file_grp_sid, - &file_ace_list, &dir_ace_list, security_info_sent, psd); + acl_perms = unpack_canon_ace(fsp, &smb_fname->st, &file_owner_sid, + &file_grp_sid, &file_ace_list, + &dir_ace_list, security_info_sent, psd); /* Ignore W2K traverse DACL set. */ if (!file_ace_list && !dir_ace_list) { - return NT_STATUS_OK; + status = NT_STATUS_OK; + goto out; } if (!acl_perms) { DEBUG(3,("set_nt_acl: cannot set permissions\n")); free_canon_ace_list(file_ace_list); free_canon_ace_list(dir_ace_list); - return NT_STATUS_ACCESS_DENIED; + status = NT_STATUS_ACCESS_DENIED; + goto out; } /* @@ -3807,7 +3837,8 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC if(!(security_info_sent & DACL_SECURITY_INFORMATION) || (psd->dacl == NULL)) { free_canon_ace_list(file_ace_list); free_canon_ace_list(dir_ace_list); - return NT_STATUS_OK; + status = NT_STATUS_OK; + goto out; } /* @@ -3819,15 +3850,19 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC if (set_acl_as_root) { become_root(); } - ret = set_canon_ace_list(fsp, file_ace_list, False, &sbuf, &acl_set_support); + ret = set_canon_ace_list(fsp, file_ace_list, false, + &smb_fname->st, &acl_set_support); if (set_acl_as_root) { unbecome_root(); } if (acl_set_support && ret == false) { - DEBUG(3,("set_nt_acl: failed to set file acl on file %s (%s).\n", fsp->fsp_name, strerror(errno) )); + DEBUG(3,("set_nt_acl: failed to set file acl on file " + "%s (%s).\n", smb_fname_str_dbg(smb_fname), + strerror(errno))); free_canon_ace_list(file_ace_list); free_canon_ace_list(dir_ace_list); - return map_nt_error_from_unix(errno); + status = map_nt_error_from_unix(errno); + goto out; } } @@ -3836,15 +3871,21 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC if (set_acl_as_root) { become_root(); } - ret = set_canon_ace_list(fsp, dir_ace_list, True, &sbuf, &acl_set_support); + ret = set_canon_ace_list(fsp, dir_ace_list, true, + &smb_fname->st, + &acl_set_support); if (set_acl_as_root) { unbecome_root(); } if (ret == false) { - DEBUG(3,("set_nt_acl: failed to set default acl on directory %s (%s).\n", fsp->fsp_name, strerror(errno) )); + DEBUG(3,("set_nt_acl: failed to set default " + "acl on directory %s (%s).\n", + smb_fname_str_dbg(smb_fname), + strerror(errno) )); free_canon_ace_list(file_ace_list); free_canon_ace_list(dir_ace_list); - return map_nt_error_from_unix(errno); + status = map_nt_error_from_unix(errno); + goto out; } } else { int sret = -1; @@ -3856,18 +3897,24 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC if (set_acl_as_root) { become_root(); } - sret = SMB_VFS_SYS_ACL_DELETE_DEF_FILE(conn, fsp->fsp_name); + sret = SMB_VFS_SYS_ACL_DELETE_DEF_FILE(conn, + smb_fname->base_name); if (set_acl_as_root) { unbecome_root(); } if (sret == -1) { - if (acl_group_override(conn, &sbuf, fsp->fsp_name)) { - 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 )); + if (acl_group_override(conn, smb_fname)) { + DEBUG(5,("set_nt_acl: acl group " + "control on and current user " + "in file %s primary group. " + "Override delete_def_acl\n", + smb_fname_str_dbg(smb_fname))); become_root(); - sret = SMB_VFS_SYS_ACL_DELETE_DEF_FILE(conn, fsp->fsp_name); + sret = + SMB_VFS_SYS_ACL_DELETE_DEF_FILE( + conn, + smb_fname->base_name); unbecome_root(); } @@ -3875,7 +3922,8 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC DEBUG(3,("set_nt_acl: sys_acl_delete_def_file failed (%s)\n", strerror(errno))); free_canon_ace_list(file_ace_list); free_canon_ace_list(dir_ace_list); - return map_nt_error_from_unix(errno); + status = map_nt_error_from_unix(errno); + goto out; } } } @@ -3904,41 +3952,54 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC if (!convert_canon_ace_to_posix_perms( fsp, file_ace_list, &posix_perms)) { free_canon_ace_list(file_ace_list); free_canon_ace_list(dir_ace_list); - DEBUG(3,("set_nt_acl: failed to convert file acl to posix permissions for file %s.\n", - fsp->fsp_name )); - return NT_STATUS_ACCESS_DENIED; + DEBUG(3,("set_nt_acl: failed to convert file acl to " + "posix permissions for file %s.\n", + smb_fname_str_dbg(smb_fname))); + status = NT_STATUS_ACCESS_DENIED; + goto out; } if (orig_mode != posix_perms) { int sret = -1; DEBUG(3,("set_nt_acl: chmod %s. perms = 0%o.\n", - fsp->fsp_name, (unsigned int)posix_perms )); + smb_fname_str_dbg(smb_fname), + (unsigned int)posix_perms)); if (set_acl_as_root) { become_root(); } - sret = SMB_VFS_CHMOD(conn,fsp->fsp_name, posix_perms); + sret = SMB_VFS_CHMOD(conn, smb_fname->base_name, + posix_perms); if (set_acl_as_root) { unbecome_root(); } if(sret == -1) { - if (acl_group_override(conn, &sbuf, fsp->fsp_name)) { - DEBUG(5,("set_nt_acl: acl group control on and " - "current user in file %s primary group. Override chmod\n", - fsp->fsp_name )); + if (acl_group_override(conn, smb_fname)) { + DEBUG(5,("set_nt_acl: acl group " + "control on and current user " + "in file %s primary group. " + "Override chmod\n", + smb_fname_str_dbg(smb_fname))); become_root(); - sret = SMB_VFS_CHMOD(conn,fsp->fsp_name, posix_perms); + sret = + SMB_VFS_CHMOD(conn, + smb_fname->base_name, + posix_perms); unbecome_root(); } if (sret == -1) { - DEBUG(3,("set_nt_acl: chmod %s, 0%o failed. Error = %s.\n", - fsp->fsp_name, (unsigned int)posix_perms, strerror(errno) )); + DEBUG(3,("set_nt_acl: chmod %s, 0%o " + "failed. Error = %s.\n", + smb_fname_str_dbg(smb_fname), + (unsigned int)posix_perms, + strerror(errno))); free_canon_ace_list(file_ace_list); free_canon_ace_list(dir_ace_list); - return map_nt_error_from_unix(errno); + status = map_nt_error_from_unix(errno); + goto out; } } } @@ -3947,7 +4008,10 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC free_canon_ace_list(file_ace_list); free_canon_ace_list(dir_ace_list); - return NT_STATUS_OK; + status = NT_STATUS_OK; + out: + TALLOC_FREE(smb_fname); + return status; } /**************************************************************************** diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 0afaf56c96a..483f68947ed 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1091,7 +1091,7 @@ void reply_getatr(struct smb_request *req) req->flags2 & FLAGS2_DFS_PATHNAMES, fname, &smb_fname, - &fname); + NULL); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, @@ -1110,7 +1110,7 @@ void reply_getatr(struct smb_request *req) goto out; } - mode = dos_mode(conn, fname, &smb_fname->st); + mode = dos_mode(conn, smb_fname); size = smb_fname->st.st_ex_size; if (ask_sharemode) { @@ -1747,7 +1747,7 @@ void reply_open(struct smb_request *req) req->flags2 & FLAGS2_DFS_PATHNAMES, fname, &smb_fname, - &fname); + NULL); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { reply_botherror(req, @@ -1760,8 +1760,9 @@ void reply_open(struct smb_request *req) } if (!map_open_params_to_ntcreate( - fname, deny_mode, OPENX_FILE_EXISTS_OPEN, &access_mask, - &share_mode, &create_disposition, &create_options)) { + smb_fname->base_name, deny_mode, OPENX_FILE_EXISTS_OPEN, + &access_mask, &share_mode, &create_disposition, + &create_options)) { reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess)); goto out; } @@ -1793,7 +1794,7 @@ void reply_open(struct smb_request *req) } size = smb_fname->st.st_ex_size; - fattr = dos_mode(conn,fsp->fsp_name,&smb_fname->st); + fattr = dos_mode(conn, smb_fname); /* Deal with other possible opens having a modified write time. JRA. */ @@ -1916,7 +1917,7 @@ void reply_open_and_X(struct smb_request *req) req->flags2 & FLAGS2_DFS_PATHNAMES, fname, &smb_fname, - &fname); + NULL); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { reply_botherror(req, @@ -1929,7 +1930,7 @@ void reply_open_and_X(struct smb_request *req) } if (!map_open_params_to_ntcreate( - fname, deny_mode, smb_ofun, &access_mask, + smb_fname->base_name, deny_mode, smb_ofun, &access_mask, &share_mode, &create_disposition, &create_options)) { reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess)); goto out; @@ -1980,7 +1981,7 @@ void reply_open_and_X(struct smb_request *req) SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &smb_fname->st); } - fattr = dos_mode(conn,fsp->fsp_name,&smb_fname->st); + fattr = dos_mode(conn, smb_fname); mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime); if (fattr & aDIR) { close_file(req, fsp, ERROR_CLOSE); @@ -2354,13 +2355,22 @@ void reply_ctemp(struct smb_request *req) static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp, uint16 dirtype, SMB_STRUCT_STAT *pst) { + struct smb_filename *smb_fname = NULL; + NTSTATUS status; uint32 fmode; if (!CAN_WRITE(conn)) { return NT_STATUS_MEDIA_WRITE_PROTECTED; } - fmode = dos_mode(conn, fsp->fsp_name, pst); + status = create_synthetic_smb_fname_split(talloc_tos(), fsp->fsp_name, + pst, &smb_fname); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + fmode = dos_mode(conn, smb_fname); + TALLOC_FREE(smb_fname); if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) { return NT_STATUS_NO_SUCH_FILE; } @@ -2395,13 +2405,14 @@ static NTSTATUS do_unlink(connection_struct *conn, struct smb_filename *smb_fname, uint32 dirtype) { - char *fname = NULL; uint32 fattr; files_struct *fsp; uint32 dirtype_orig = dirtype; NTSTATUS status; - DEBUG(10,("do_unlink: %s, dirtype = %d\n", fname, dirtype )); + DEBUG(10,("do_unlink: %s, dirtype = %d\n", + smb_fname_str_dbg(smb_fname), + dirtype)); if (!CAN_WRITE(conn)) { return NT_STATUS_MEDIA_WRITE_PROTECTED; @@ -2411,12 +2422,7 @@ static NTSTATUS do_unlink(connection_struct *conn, return map_nt_error_from_unix(errno); } - status = get_full_smb_filename(smb_fname, smb_fname, &fname); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - fattr = dos_mode(conn, fname, &smb_fname->st); - TALLOC_FREE(fname); + fattr = dos_mode(conn, smb_fname); if (dirtype & FILE_ATTRIBUTE_NORMAL) { dirtype = aDIR|aARCH|aRONLY; @@ -6578,7 +6584,6 @@ NTSTATUS copy_file(TALLOC_CTX *ctx, bool target_is_directory) { struct smb_filename *smb_fname_dst_tmp = NULL; - char *fname_src = NULL; SMB_OFF_T ret=-1; files_struct *fsp1,*fsp2; uint32 dosattrs; @@ -6655,14 +6660,7 @@ NTSTATUS copy_file(TALLOC_CTX *ctx, goto out; } - status = get_full_smb_filename(talloc_tos(), smb_fname_src, &fname_src); - if (!NT_STATUS_IS_OK(status)) { - goto out; - } - - dosattrs = dos_mode(conn, fname_src, &smb_fname_src->st); - - TALLOC_FREE(fname_src); + dosattrs = dos_mode(conn, smb_fname_src); if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) { ZERO_STRUCTP(&smb_fname_dst_tmp->st); @@ -7739,6 +7737,8 @@ void reply_getattrE(struct smb_request *req) int mode; files_struct *fsp; struct timespec create_ts; + struct smb_filename *smb_fname = NULL; + NTSTATUS status; START_PROFILE(SMBgetattrE); @@ -7763,7 +7763,16 @@ void reply_getattrE(struct smb_request *req) return; } - mode = dos_mode(conn,fsp->fsp_name,&sbuf); + status = create_synthetic_smb_fname_split(talloc_tos(), fsp->fsp_name, + &sbuf, &smb_fname); + if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); + END_PROFILE(SMBgetattrE); + return; + } + + mode = dos_mode(conn, smb_fname); + TALLOC_FREE(smb_fname); /* * Convert the times into dos times. Set create diff --git a/source3/smbd/smb2_create.c b/source3/smbd/smb2_create.c index a936a0892e4..bdff1939e5f 100644 --- a/source3/smbd/smb2_create.c +++ b/source3/smbd/smb2_create.c @@ -353,6 +353,16 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx, sbuf = smb_fname->st; } + if (!smb_fname) { + status = create_synthetic_smb_fname_split(talloc_tos(), + result->fsp_name, + &sbuf, &smb_fname); + if (!NT_STATUS_IS_OK(status)) { + tevent_req_nterror(req, status); + goto out; + } + } + smb2req->compat_chain_fsp = smbreq->chain_fsp; state->out_oplock_level = 0; @@ -369,8 +379,7 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx, state->out_allocation_size = sbuf.st_ex_blksize * sbuf.st_ex_blocks; state->out_end_of_file = sbuf.st_ex_size; state->out_file_attributes = dos_mode(result->conn, - result->fsp_name, - &sbuf); + smb_fname); if (state->out_file_attributes == 0) { state->out_file_attributes = FILE_ATTRIBUTE_NORMAL; } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 0dd2ca2e3cb..62280ddde03 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -964,7 +964,7 @@ static void call_trans2open(connection_struct *conn, req->flags2 & FLAGS2_DFS_PATHNAMES, fname, &smb_fname, - &fname); + NULL); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { reply_botherror(req, @@ -981,7 +981,8 @@ static void call_trans2open(connection_struct *conn, goto out; } - if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun, + if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode, + open_ofun, &access_mask, &share_mode, &create_disposition, @@ -1047,7 +1048,7 @@ static void call_trans2open(connection_struct *conn, } size = get_file_size_stat(&smb_fname->st); - fattr = dos_mode(conn, fsp->fsp_name, &smb_fname->st); + fattr = dos_mode(conn, smb_fname); mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime); inode = smb_fname->st.st_ex_ino; if (fattr & aDIR) { @@ -1388,6 +1389,8 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx, if (got_match) { bool isdots = (ISDOT(dname) || ISDOTDOT(dname)); + struct smb_filename *smb_fname = NULL; + NTSTATUS status; if (dont_descend && !isdots) { TALLOC_FREE(fname); @@ -1412,25 +1415,40 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx, return False; } + /* A dirent from dptr_ReadDirName isn't a stream. */ + status = create_synthetic_smb_fname(ctx, pathreal, + NULL, &sbuf, + &smb_fname); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(fname); + } + if (INFO_LEVEL_IS_UNIX(info_level)) { - if (vfs_lstat_smb_fname(conn, pathreal, - &sbuf) != 0) { - DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n", - pathreal,strerror(errno))); + if (SMB_VFS_LSTAT(conn, smb_fname) != 0) { + DEBUG(5,("get_lanman2_dir_entry: " + "Couldn't lstat [%s] (%s)\n", + smb_fname_str_dbg(smb_fname), + strerror(errno))); + TALLOC_FREE(smb_fname); TALLOC_FREE(pathreal); TALLOC_FREE(fname); continue; } - } else if (!VALID_STAT(sbuf) && - vfs_stat_smb_fname(conn, pathreal, - &sbuf) != 0) { + } else if (!VALID_STAT(smb_fname->st) && + SMB_VFS_STAT(conn, smb_fname) != 0) { /* Needed to show the msdfs symlinks as * directories */ - ms_dfs_link = check_msdfs_link(conn, pathreal, &sbuf); + ms_dfs_link = + check_msdfs_link(conn, + smb_fname->base_name, + &smb_fname->st); if (!ms_dfs_link) { - DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n", - pathreal,strerror(errno))); + DEBUG(5,("get_lanman2_dir_entry: " + "Couldn't stat [%s] (%s)\n", + smb_fname_str_dbg(smb_fname), + strerror(errno))); + TALLOC_FREE(smb_fname); TALLOC_FREE(pathreal); TALLOC_FREE(fname); continue; @@ -1438,38 +1456,42 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx, } if (ms_dfs_link) { - mode = dos_mode_msdfs(conn,pathreal,&sbuf); + mode = dos_mode_msdfs(conn, smb_fname); } else { - mode = dos_mode(conn,pathreal,&sbuf); + mode = dos_mode(conn, smb_fname); } if (!dir_check_ftype(conn,mode,dirtype)) { DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype)); + TALLOC_FREE(smb_fname); TALLOC_FREE(pathreal); TALLOC_FREE(fname); continue; } if (!(mode & aDIR)) { - file_size = get_file_size_stat(&sbuf); + file_size = get_file_size_stat(&smb_fname->st); } - allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,NULL,&sbuf); + allocation_size = + SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st); if (ask_sharemode) { struct timespec write_time_ts; struct file_id fileid; ZERO_STRUCT(write_time_ts); - fileid = vfs_file_id_from_sbuf(conn, &sbuf); + fileid = vfs_file_id_from_sbuf(conn, + &smb_fname->st); get_file_infos(fileid, NULL, &write_time_ts); if (!null_timespec(write_time_ts)) { - update_stat_ex_mtime(&sbuf, write_time_ts); + update_stat_ex_mtime(&smb_fname->st, + write_time_ts); } } - mdate_ts = sbuf.st_ex_mtime; - adate_ts = sbuf.st_ex_atime; - create_date_ts = sbuf.st_ex_btime; + mdate_ts = smb_fname->st.st_ex_mtime; + adate_ts = smb_fname->st.st_ex_atime; + create_date_ts = smb_fname->st.st_ex_btime; if (lp_dos_filetime_resolution(SNUM(conn))) { dos_filetime_timespec(&create_date_ts); @@ -1482,11 +1504,14 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx, adate = convert_timespec_to_time_t(adate_ts); DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n", - pathreal,fname)); + smb_fname_str_dbg(smb_fname), fname)); found = True; dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos); + sbuf = smb_fname->st; + + TALLOC_FREE(smb_fname); } if (!found) @@ -4137,16 +4162,16 @@ static void call_trans2qfilepathinfo(connection_struct *conn, DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n", fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data)); - p = strrchr_m(fname,'/'); + p = strrchr_m(smb_fname->base_name,'/'); if (!p) - base_name = fname; + base_name = smb_fname->base_name; else base_name = p+1; if (ms_dfs_link) { - mode = dos_mode_msdfs(conn,fname,&sbuf); + mode = dos_mode_msdfs(conn, smb_fname); } else { - mode = dos_mode(conn,fname,&sbuf); + mode = dos_mode(conn, smb_fname); } if (!mode) mode = FILE_ATTRIBUTE_NORMAL; @@ -5072,9 +5097,7 @@ static NTSTATUS smb_set_file_dosmode(connection_struct *conn, DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode)); /* check the mode isn't different, before changing it */ - if ((dosmode != 0) && (dosmode != dos_mode(conn, - smb_fname_base->base_name, - &smb_fname_base->st))) { + if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) { DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode " "0x%x\n", smb_fname_str_dbg(smb_fname_base), (unsigned int)dosmode)); @@ -5226,8 +5249,7 @@ static NTSTATUS smb_set_file_disposition_info(connection_struct *conn, const char *pdata, int total_data, files_struct *fsp, - const char *fname, - SMB_STRUCT_STAT *psbuf) + const struct smb_filename *smb_fname) { NTSTATUS status = NT_STATUS_OK; bool delete_on_close; @@ -5242,11 +5264,11 @@ static NTSTATUS smb_set_file_disposition_info(connection_struct *conn, } delete_on_close = (CVAL(pdata,0) ? True : False); - dosmode = dos_mode(conn, fname, psbuf); + dosmode = dos_mode(conn, smb_fname); DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, " "delete_on_close = %u\n", - fsp->fsp_name, + smb_fname_str_dbg(smb_fname), (unsigned int)dosmode, (unsigned int)delete_on_close )); @@ -6748,10 +6770,8 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn, struct smb_request *req, const char *pdata, int total_data, - const char *fname, - SMB_STRUCT_STAT *psbuf) + struct smb_filename *smb_fname) { - struct smb_filename *smb_fname = NULL; NTSTATUS status = NT_STATUS_OK; files_struct *fsp = NULL; uint16 flags = 0; @@ -6767,29 +6787,23 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn, flags = SVAL(pdata,0); - if (!VALID_STAT(*psbuf)) { + if (!VALID_STAT(smb_fname->st)) { return NT_STATUS_OBJECT_NAME_NOT_FOUND; } if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) && - !VALID_STAT_OF_DIR(*psbuf)) { + !VALID_STAT_OF_DIR(smb_fname->st)) { return NT_STATUS_NOT_A_DIRECTORY; } DEBUG(10,("smb_posix_unlink: %s %s\n", (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file", - fname)); + smb_fname_str_dbg(smb_fname))); - if (VALID_STAT_OF_DIR(*psbuf)) { + if (VALID_STAT_OF_DIR(smb_fname->st)) { create_options |= FILE_DIRECTORY_FILE; } - status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf, - &smb_fname); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - status = SMB_VFS_CREATE_FILE( conn, /* conn */ req, /* req */ @@ -6808,9 +6822,6 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn, &fsp, /* result */ &info); /* pinfo */ - *psbuf = smb_fname->st; - TALLOC_FREE(smb_fname); - if (!NT_STATUS_IS_OK(status)) { return status; } @@ -6854,8 +6865,7 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn, &del, 1, fsp, - fname, - psbuf); + smb_fname); if (!NT_STATUS_IS_OK(status)) { close_file(req, fsp, NORMAL_CLOSE); @@ -7133,8 +7143,7 @@ static void call_trans2setfilepathinfo(connection_struct *conn, pdata, total_data, fsp, - fname, - &sbuf); + smb_fname); break; } @@ -7270,8 +7279,7 @@ static void call_trans2setfilepathinfo(connection_struct *conn, status = smb_posix_unlink(conn, req, pdata, total_data, - fname, - &sbuf); + smb_fname); break; } |