diff options
-rw-r--r-- | source3/include/proto.h | 2 | ||||
-rw-r--r-- | source3/include/vfs.h | 7 | ||||
-rw-r--r-- | source3/include/vfs_macros.h | 8 | ||||
-rw-r--r-- | source3/modules/vfs_default.c | 11 | ||||
-rw-r--r-- | source3/modules/vfs_full_audit.c | 15 | ||||
-rw-r--r-- | source3/modules/vfs_streams_depot.c | 5 | ||||
-rw-r--r-- | source3/smbd/dir.c | 35 | ||||
-rw-r--r-- | source3/smbd/filename.c | 6 | ||||
-rw-r--r-- | source3/smbd/msdfs.c | 4 | ||||
-rw-r--r-- | source3/smbd/reply.c | 50 | ||||
-rw-r--r-- | source3/smbd/vfs.c | 21 |
11 files changed, 138 insertions, 26 deletions
diff --git a/source3/include/proto.h b/source3/include/proto.h index ac0eed2b5b..9314e57cc2 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -6216,7 +6216,7 @@ bool get_dir_entry(TALLOC_CTX *ctx, bool is_visible_file(connection_struct *conn, const char *dir_path, const char *name, SMB_STRUCT_STAT *pst, bool use_veto); struct smb_Dir *OpenDir(TALLOC_CTX *mem_ctx, connection_struct *conn, const char *name, const char *mask, uint32 attr); -const char *ReadDirName(struct smb_Dir *dirp, long *poffset, +char *ReadDirName(struct smb_Dir *dirp, long *poffset, SMB_STRUCT_STAT *sbuf); void RewindDir(struct smb_Dir *dirp, long *poffset); void SeekDir(struct smb_Dir *dirp, long offset); diff --git a/source3/include/vfs.h b/source3/include/vfs.h index 38a972f04c..38d60a0aec 100644 --- a/source3/include/vfs.h +++ b/source3/include/vfs.h @@ -123,6 +123,8 @@ SMB_VFS_RENAME, SMB_VFS_UNLINK, SMB_VFS_NTIMES. */ /* Changed to version 27 - not yet released. Added enum timestamp_set_resolution * return to fs_capabilities call. JRA. */ +/* Leave at 27 - not yet released. Add translate_name VFS call to convert + UNIX names to Windows supported names -- asrinivasan. */ #define SMB_VFS_INTERFACE_VERSION 27 @@ -299,6 +301,9 @@ struct vfs_fn_pointers { struct files_struct *fsp, struct lock_struct *plock); + NTSTATUS (*translate_name)(struct vfs_handle_struct *handle, + char **mapped_name); + /* NT ACL operations. */ NTSTATUS (*fget_nt_acl)(struct vfs_handle_struct *handle, @@ -644,6 +649,8 @@ bool smb_vfs_call_strict_lock(struct vfs_handle_struct *handle, void smb_vfs_call_strict_unlock(struct vfs_handle_struct *handle, struct files_struct *fsp, struct lock_struct *plock); +NTSTATUS smb_vfs_call_translate_name(struct vfs_handle_struct *handle, + char **mapped_name); NTSTATUS smb_vfs_call_fget_nt_acl(struct vfs_handle_struct *handle, struct files_struct *fsp, uint32 security_info, diff --git a/source3/include/vfs_macros.h b/source3/include/vfs_macros.h index e271cdee61..7cc5579e25 100644 --- a/source3/include/vfs_macros.h +++ b/source3/include/vfs_macros.h @@ -345,6 +345,14 @@ #define SMB_VFS_NEXT_STRICT_UNLOCK(handle, fsp, plock) \ smb_vfs_call_strict_unlock((handle)->next, (fsp), (plock)) +#define SMB_VFS_TRANSLATE_NAME(conn, mapped_name) \ + smb_vfs_call_translate_name((conn)->vfs_handles, (mapped_name)) +#define SMB_VFS_NEXT_TRANSLATE_NAME(handle, mapped_name) \ + smb_vfs_call_translate_name((handle)->next, (mapped_name)) + +#define SMB_VFS_NEXT_STRICT_UNLOCK(handle, fsp, plock) \ + smb_vfs_call_strict_unlock((handle)->next, (fsp), (plock)) + #define SMB_VFS_FGET_NT_ACL(fsp, security_info, ppdesc) \ smb_vfs_call_fget_nt_acl((fsp)->conn->vfs_handles, (fsp), (security_info), (ppdesc)) #define SMB_VFS_NEXT_FGET_NT_ACL(handle, fsp, security_info, ppdesc) \ diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c index b70868eb9f..e78ddf242c 100644 --- a/source3/modules/vfs_default.c +++ b/source3/modules/vfs_default.c @@ -651,6 +651,16 @@ static int vfswrap_lstat(vfs_handle_struct *handle, return result; } +static NTSTATUS vfswrap_translate_name(vfs_handle_struct *handle, + char **mapped_name) +{ + /* Default behavior is a NOOP */ + + if (*mapped_name != NULL) + return NT_STATUS_OK; + + return NT_STATUS_INVALID_PARAMETER; +} /******************************************************************** Given a stat buffer return the allocated size on disk, taking into account sparse files. @@ -1725,6 +1735,7 @@ static struct vfs_fn_pointers vfs_default_fns = { .brl_cancel_windows = vfswrap_brl_cancel_windows, .strict_lock = vfswrap_strict_lock, .strict_unlock = vfswrap_strict_unlock, + .translate_name = vfswrap_translate_name, /* NT ACL operations. */ diff --git a/source3/modules/vfs_full_audit.c b/source3/modules/vfs_full_audit.c index 0f6de79bcf..b5c9e6bd9c 100644 --- a/source3/modules/vfs_full_audit.c +++ b/source3/modules/vfs_full_audit.c @@ -143,6 +143,7 @@ typedef enum _vfs_op_type { SMB_VFS_OP_BRL_CANCEL_WINDOWS, SMB_VFS_OP_STRICT_LOCK, SMB_VFS_OP_STRICT_UNLOCK, + SMB_VFS_OP_TRANSLATE_NAME, /* NT ACL operations. */ @@ -280,6 +281,7 @@ static struct { { SMB_VFS_OP_BRL_CANCEL_WINDOWS, "brl_cancel_windows" }, { SMB_VFS_OP_STRICT_LOCK, "strict_lock" }, { SMB_VFS_OP_STRICT_UNLOCK, "strict_unlock" }, + { SMB_VFS_OP_TRANSLATE_NAME, "translate_name" }, { SMB_VFS_OP_FGET_NT_ACL, "fget_nt_acl" }, { SMB_VFS_OP_GET_NT_ACL, "get_nt_acl" }, { SMB_VFS_OP_FSET_NT_ACL, "fset_nt_acl" }, @@ -1515,6 +1517,18 @@ static void smb_full_audit_strict_unlock(struct vfs_handle_struct *handle, return; } +static NTSTATUS smb_full_audit_translate_name(vfs_handle_struct *handle, + char **mapped_name) +{ + NTSTATUS result; + + result = SMB_VFS_NEXT_TRANSLATE_NAME(handle, mapped_name); + + do_log(SMB_VFS_OP_TRANSLATE_NAME, NT_STATUS_IS_OK(result), handle, ""); + + return result; +} + static NTSTATUS smb_full_audit_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) @@ -2229,6 +2243,7 @@ static struct vfs_fn_pointers vfs_full_audit_fns = { .brl_cancel_windows = smb_full_audit_brl_cancel_windows, .strict_lock = smb_full_audit_strict_lock, .strict_unlock = smb_full_audit_strict_unlock, + .translate_name = smb_full_audit_translate_name, .fget_nt_acl = smb_full_audit_fget_nt_acl, .get_nt_acl = smb_full_audit_get_nt_acl, .fset_nt_acl = smb_full_audit_fset_nt_acl, diff --git a/source3/modules/vfs_streams_depot.c b/source3/modules/vfs_streams_depot.c index aa0189123b..51cd56e8fb 100644 --- a/source3/modules/vfs_streams_depot.c +++ b/source3/modules/vfs_streams_depot.c @@ -384,7 +384,7 @@ static NTSTATUS walk_streams(vfs_handle_struct *handle, { char *dirname; SMB_STRUCT_DIR *dirhandle = NULL; - char *dirent; + char *dirent = NULL; dirname = stream_dir(handle, smb_fname_base, &smb_fname_base->st, false); @@ -411,14 +411,17 @@ static NTSTATUS walk_streams(vfs_handle_struct *handle, while ((dirent = vfs_readdirname(handle->conn, dirhandle, NULL)) != NULL) { if (ISDOT(dirent) || ISDOTDOT(dirent)) { + TALLOC_FREE(dirent); continue; } DEBUG(10, ("walk_streams: dirent=%s\n", dirent)); if (!fn(dirname, dirent, private_data)) { + TALLOC_FREE(dirent); break; } + TALLOC_FREE(dirent); } SMB_VFS_NEXT_CLOSEDIR(handle, dirhandle); diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 73c4cbb3e7..60fa0306b9 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -585,15 +585,16 @@ int dptr_dnum(struct dptr_struct *dptr) Return the next visible file name, skipping veto'd and invisible files. ****************************************************************************/ -static const char *dptr_normal_ReadDirName(struct dptr_struct *dptr, +static char *dptr_normal_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT_STAT *pst) { /* Normal search for the next file. */ - const char *name; + char *name; while ((name = ReadDirName(dptr->dir_hnd, poffset, pst)) != NULL) { if (is_visible_file(dptr->conn, dptr->path, name, pst, True)) { return name; } + TALLOC_FREE(name); } return NULL; } @@ -612,14 +613,12 @@ char *dptr_ReadDirName(TALLOC_CTX *ctx, char *pathreal = NULL; char *found_name = NULL; int ret; - const char *name_temp = NULL; NTSTATUS status; SET_STAT_INVALID(*pst); if (dptr->has_wild || dptr->did_stat) { - name_temp = dptr_normal_ReadDirName(dptr, poffset, pst); - name = talloc_strdup(ctx, name_temp); + name = dptr_normal_ReadDirName(dptr, poffset, pst); return name; } @@ -707,8 +706,8 @@ char *dptr_ReadDirName(TALLOC_CTX *ctx, TALLOC_FREE(pathreal); - name_temp = dptr_normal_ReadDirName(dptr, poffset, pst); - name = talloc_strdup(ctx, name_temp); + name = dptr_normal_ReadDirName(dptr, poffset, pst); + return name; clean: @@ -1337,10 +1336,10 @@ struct smb_Dir *OpenDir(TALLOC_CTX *mem_ctx, connection_struct *conn, Don't check for veto or invisible files. ********************************************************************/ -const char *ReadDirName(struct smb_Dir *dirp, long *poffset, +char *ReadDirName(struct smb_Dir *dirp, long *poffset, SMB_STRUCT_STAT *sbuf) { - const char *n; + char *n; connection_struct *conn = dirp->conn; /* Cheat to allow . and .. to be the first entries returned. */ @@ -1348,11 +1347,15 @@ const char *ReadDirName(struct smb_Dir *dirp, long *poffset, (*poffset == DOT_DOT_DIRECTORY_OFFSET)) && (dirp->file_number < 2)) { if (dirp->file_number == 0) { - n = "."; + n = talloc_strdup(talloc_tos(), "."); + if (n == NULL) + return NULL; *poffset = dirp->offset = START_OF_DIRECTORY_OFFSET; } else { *poffset = dirp->offset = DOT_DOT_DIRECTORY_OFFSET; - n = ".."; + n = talloc_strdup(talloc_tos(), ".."); + if (n == NULL) + return NULL; } dirp->file_number++; return n; @@ -1368,6 +1371,7 @@ const char *ReadDirName(struct smb_Dir *dirp, long *poffset, /* Ignore . and .. - we've already returned them. */ if (*n == '.') { if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) { + TALLOC_FREE(n); continue; } } @@ -1470,7 +1474,7 @@ void DirCacheAdd(struct smb_Dir *dirp, const char *name, long offset) bool SearchDir(struct smb_Dir *dirp, const char *name, long *poffset) { int i; - const char *entry; + char *entry = NULL; connection_struct *conn = dirp->conn; /* Search back in the name cache. */ @@ -1499,8 +1503,10 @@ bool SearchDir(struct smb_Dir *dirp, const char *name, long *poffset) *poffset = START_OF_DIRECTORY_OFFSET; while ((entry = ReadDirName(dirp, poffset, NULL))) { if (conn->case_sensitive ? (strcmp(entry, name) == 0) : strequal(entry, name)) { + TALLOC_FREE(entry); return True; } + TALLOC_FREE(entry); } return False; } @@ -1514,7 +1520,7 @@ NTSTATUS can_delete_directory(struct connection_struct *conn, { NTSTATUS status = NT_STATUS_OK; long dirpos = 0; - const char *dname; + char *dname = NULL; SMB_STRUCT_STAT st; struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn, dirname, NULL, 0); @@ -1527,11 +1533,13 @@ NTSTATUS can_delete_directory(struct connection_struct *conn, /* Quick check for "." and ".." */ if (dname[0] == '.') { if (!dname[1] || (dname[1] == '.' && !dname[2])) { + TALLOC_FREE(dname); continue; } } if (!is_visible_file(conn, dirname, dname, &st, True)) { + TALLOC_FREE(dname); continue; } @@ -1540,6 +1548,7 @@ NTSTATUS can_delete_directory(struct connection_struct *conn, status = NT_STATUS_DIRECTORY_NOT_EMPTY; break; } + TALLOC_FREE(dname); TALLOC_FREE(dir_hnd); return status; diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 2538bc1ea6..ee97388da2 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -829,7 +829,7 @@ static int get_real_filename_full_scan(connection_struct *conn, TALLOC_CTX *mem_ctx, char **found_name) { struct smb_Dir *cur_dir; - const char *dname; + char *dname = NULL; char *unmangled_name = NULL; long curpos; @@ -885,6 +885,7 @@ static int get_real_filename_full_scan(connection_struct *conn, /* Is it dot or dot dot. */ if (ISDOT(dname) || ISDOTDOT(dname)) { + TALLOC_FREE(dname); continue; } @@ -907,10 +908,13 @@ static int get_real_filename_full_scan(connection_struct *conn, TALLOC_FREE(cur_dir); if (!*found_name) { errno = ENOMEM; + TALLOC_FREE(dname); return -1; } + TALLOC_FREE(dname); return 0; } + TALLOC_FREE(dname); } TALLOC_FREE(unmangled_name); diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 74e46527bc..4a338fa590 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -1548,6 +1548,7 @@ static int count_dfs_links(TALLOC_CTX *ctx, int snum) NULL)) { cnt++; } + TALLOC_FREE(dname); } SMB_VFS_CLOSEDIR(conn,dirp); @@ -1647,6 +1648,7 @@ static int form_junctions(TALLOC_CTX *ctx, if (cnt >= jn_remain) { DEBUG(2, ("form_junctions: ran out of MSDFS " "junction slots")); + TALLOC_FREE(dname); goto out; } if (is_msdfs_link_internal(ctx, @@ -1664,6 +1666,7 @@ static int form_junctions(TALLOC_CTX *ctx, dname); if (!jucn[cnt].service_name || !jucn[cnt].volume_name) { + TALLOC_FREE(dname); goto out; } jucn[cnt].comment = ""; @@ -1671,6 +1674,7 @@ static int form_junctions(TALLOC_CTX *ctx, } TALLOC_FREE(link_target); } + TALLOC_FREE(dname); } out: diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index bdc71c2404..a3280cb9d4 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2577,7 +2577,7 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req, } else { struct smb_Dir *dir_hnd = NULL; long offset = 0; - const char *dname; + char *dname = NULL; if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) { status = NT_STATUS_OBJECT_NAME_INVALID; @@ -2619,18 +2619,21 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req, if (!is_visible_file(conn, fname_dir, dname, &smb_fname->st, true)) { TALLOC_FREE(frame); + TALLOC_FREE(dname); continue; } /* Quick check for "." and ".." */ if (ISDOT(dname) || ISDOTDOT(dname)) { TALLOC_FREE(frame); + TALLOC_FREE(dname); continue; } if(!mask_match(dname, fname_mask, conn->case_sensitive)) { TALLOC_FREE(frame); + TALLOC_FREE(dname); continue; } @@ -2643,6 +2646,7 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req, TALLOC_FREE(dir_hnd); status = NT_STATUS_NO_MEMORY; TALLOC_FREE(frame); + TALLOC_FREE(dname); goto out; } @@ -2650,12 +2654,14 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req, if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(dir_hnd); TALLOC_FREE(frame); + TALLOC_FREE(dname); goto out; } status = do_unlink(conn, req, smb_fname, dirtype); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(frame); + TALLOC_FREE(dname); continue; } @@ -2664,6 +2670,7 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req, smb_fname->base_name)); TALLOC_FREE(frame); + TALLOC_FREE(dname); } TALLOC_FREE(dir_hnd); } @@ -5287,7 +5294,7 @@ static bool recursive_rmdir(TALLOC_CTX *ctx, connection_struct *conn, struct smb_filename *smb_dname) { - const char *dname = NULL; + char *dname = NULL; bool ret = True; long offset = 0; SMB_STRUCT_STAT st; @@ -5306,11 +5313,13 @@ static bool recursive_rmdir(TALLOC_CTX *ctx, NTSTATUS status; if (ISDOT(dname) || ISDOTDOT(dname)) { + TALLOC_FREE(dname); continue; } if (!is_visible_file(conn, smb_dname->base_name, dname, &st, false)) { + TALLOC_FREE(dname); continue; } @@ -5353,6 +5362,7 @@ static bool recursive_rmdir(TALLOC_CTX *ctx, err_break: TALLOC_FREE(smb_dname_full); TALLOC_FREE(fullname); + TALLOC_FREE(dname); if (do_break) { ret = false; break; @@ -5406,7 +5416,7 @@ NTSTATUS rmdir_internals(TALLOC_CTX *ctx, * retry. If we fail to delete any of them (and we *don't* * do a recursive delete) then fail the rmdir. */ - const char *dname; + char *dname = NULL; long dirpos = 0; struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn, smb_dname->base_name, NULL, @@ -5418,16 +5428,22 @@ NTSTATUS rmdir_internals(TALLOC_CTX *ctx, } while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) { - if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) + if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) { + TALLOC_FREE(dname); continue; + } if (!is_visible_file(conn, smb_dname->base_name, dname, - &st, false)) + &st, false)) { + TALLOC_FREE(dname); continue; + } if(!IS_VETO_PATH(conn, dname)) { TALLOC_FREE(dir_hnd); + TALLOC_FREE(dname); errno = ENOTEMPTY; goto err; } + TALLOC_FREE(dname); } /* We only have veto files/directories. @@ -5448,10 +5464,12 @@ NTSTATUS rmdir_internals(TALLOC_CTX *ctx, NTSTATUS status; if (ISDOT(dname) || ISDOTDOT(dname)) { + TALLOC_FREE(dname); continue; } if (!is_visible_file(conn, smb_dname->base_name, dname, &st, false)) { + TALLOC_FREE(dname); continue; } @@ -5496,6 +5514,7 @@ NTSTATUS rmdir_internals(TALLOC_CTX *ctx, err_break: TALLOC_FREE(fullname); TALLOC_FREE(smb_dname_full); + TALLOC_FREE(dname); if (do_break) break; } @@ -6132,7 +6151,7 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx, int count=0; NTSTATUS status = NT_STATUS_OK; struct smb_Dir *dir_hnd = NULL; - const char *dname; + char *dname = NULL; long offset = 0; int create_options = 0; bool posix_pathnames = lp_posix_pathnames(); @@ -6320,16 +6339,19 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx, if (attrs & aDIR) { sysdir_entry = True; } else { + TALLOC_FREE(dname); continue; } } if (!is_visible_file(conn, fname_src_dir, dname, &smb_fname_src->st, false)) { + TALLOC_FREE(dname); continue; } if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) { + TALLOC_FREE(dname); continue; } @@ -6353,6 +6375,7 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx, &destname)) { DEBUG(6, ("resolve_wildcards %s %s failed\n", smb_fname_src->base_name, destname)); + TALLOC_FREE(dname); continue; } if (!destname) { @@ -6428,7 +6451,7 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx, DEBUG(3,("rename_internals: doing rename on %s -> " "%s\n", smb_fname_str_dbg(smb_fname_src), smb_fname_str_dbg(smb_fname_src))); - + TALLOC_FREE(dname); } TALLOC_FREE(dir_hnd); @@ -6437,6 +6460,7 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx, } out: + TALLOC_FREE(dname); TALLOC_FREE(fname_src_dir); TALLOC_FREE(fname_src_mask); return status; @@ -6901,7 +6925,7 @@ void reply_copy(struct smb_request *req) } } else { struct smb_Dir *dir_hnd = NULL; - const char *dname = NULL; + char *dname = NULL; long offset = 0; /* @@ -6946,16 +6970,19 @@ void reply_copy(struct smb_request *req) char *destname = NULL; if (ISDOT(dname) || ISDOTDOT(dname)) { + TALLOC_FREE(dname); continue; } if (!is_visible_file(conn, fname_src_dir, dname, &smb_fname_src->st, false)) { + TALLOC_FREE(dname); continue; } if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) { + TALLOC_FREE(dname); continue; } @@ -6969,6 +6996,7 @@ void reply_copy(struct smb_request *req) if (!smb_fname_src->base_name) { TALLOC_FREE(dir_hnd); + TALLOC_FREE(dname); reply_nterror(req, NT_STATUS_NO_MEMORY); goto out; } @@ -6976,10 +7004,12 @@ void reply_copy(struct smb_request *req) if (!resolve_wildcards(ctx, smb_fname_src->base_name, smb_fname_dst->base_name, &destname)) { + TALLOC_FREE(dname); continue; } if (!destname) { TALLOC_FREE(dir_hnd); + TALLOC_FREE(dname); reply_nterror(req, NT_STATUS_NO_MEMORY); goto out; } @@ -6990,6 +7020,7 @@ void reply_copy(struct smb_request *req) status = check_name(conn, smb_fname_src->base_name); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(dir_hnd); + TALLOC_FREE(dname); reply_nterror(req, status); goto out; } @@ -6997,6 +7028,7 @@ void reply_copy(struct smb_request *req) status = check_name(conn, smb_fname_dst->base_name); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(dir_hnd); + TALLOC_FREE(dname); reply_nterror(req, status); goto out; } @@ -7011,6 +7043,8 @@ void reply_copy(struct smb_request *req) if (NT_STATUS_IS_OK(status)) { count++; } + + TALLOC_FREE(dname); } TALLOC_FREE(dir_hnd); } diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 5425c55198..42ff8b19cd 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -662,7 +662,8 @@ SMB_OFF_T vfs_transfer_file(files_struct *in, files_struct *out, SMB_OFF_T n) char *vfs_readdirname(connection_struct *conn, void *p, SMB_STRUCT_STAT *sbuf) { SMB_STRUCT_DIRENT *ptr= NULL; - char *dname; + char *dname = NULL; + NTSTATUS result; if (!p) return(NULL); @@ -671,7 +672,16 @@ char *vfs_readdirname(connection_struct *conn, void *p, SMB_STRUCT_STAT *sbuf) if (!ptr) return(NULL); - dname = ptr->d_name; + dname = talloc_strdup(talloc_tos(), ptr->d_name); + if (dname == NULL) { + errno = ENOMEM; + return NULL; + } + result = SMB_VFS_TRANSLATE_NAME(conn, &dname); + if (!NT_STATUS_IS_OK(result)) { + TALLOC_FREE(dname); + return NULL; + } #ifdef NEXT2 if (telldir(p) < 0) @@ -1495,6 +1505,13 @@ void smb_vfs_call_strict_unlock(struct vfs_handle_struct *handle, handle->fns->strict_unlock(handle, fsp, plock); } +NTSTATUS smb_vfs_call_translate_name(struct vfs_handle_struct *handle, + char **mapped_name) +{ + VFS_FIND(translate_name); + return handle->fns->translate_name(handle, mapped_name); +} + NTSTATUS smb_vfs_call_fget_nt_acl(struct vfs_handle_struct *handle, struct files_struct *fsp, uint32 security_info, |