summaryrefslogtreecommitdiff
path: root/source3/smbd
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2007-09-07 20:57:01 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 12:30:32 -0500
commit132ee3990af5d31573978f5a3abf43db2303880b (patch)
tree2ce69566fb9a4ecb0f8ce19261c60e4ad3d8593a /source3/smbd
parentc5d8fd3772706a469484df8a16abf10547d1c7a4 (diff)
downloadsamba-132ee3990af5d31573978f5a3abf43db2303880b.tar.gz
samba-132ee3990af5d31573978f5a3abf43db2303880b.tar.bz2
samba-132ee3990af5d31573978f5a3abf43db2303880b.zip
r25009: Large patch discussed with Volker. Move unix_convert to a talloc-based
interface. More development will come on top of this. Remove the "mangled map" parameter. Jeremy. (This used to be commit dee8beba7a92b8a3f68bbcc59fd0a827f68c7736)
Diffstat (limited to 'source3/smbd')
-rw-r--r--source3/smbd/dir.c36
-rw-r--r--source3/smbd/filename.c189
-rw-r--r--source3/smbd/mangle.c65
-rw-r--r--source3/smbd/mangle_hash.c201
-rw-r--r--source3/smbd/mangle_hash2.c135
-rw-r--r--source3/smbd/msdfs.c7
-rw-r--r--source3/smbd/nttrans.c93
-rw-r--r--source3/smbd/reply.c489
-rw-r--r--source3/smbd/statcache.c128
-rw-r--r--source3/smbd/trans2.c243
10 files changed, 947 insertions, 639 deletions
diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c
index eec8fa12ef..e602008b8f 100644
--- a/source3/smbd/dir.c
+++ b/source3/smbd/dir.c
@@ -380,12 +380,11 @@ static void dptr_close_oldest(BOOL old)
wcard must not be zero.
****************************************************************************/
-NTSTATUS dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL expect_close,uint16 spid,
+NTSTATUS dptr_create(connection_struct *conn, const char *path, BOOL old_handle, BOOL expect_close,uint16 spid,
const char *wcard, BOOL wcard_has_wild, uint32 attr, struct dptr_struct **dptr_ret)
{
struct dptr_struct *dptr = NULL;
struct smb_Dir *dir_hnd;
- const char *dir2;
NTSTATUS status;
DEBUG(5,("dptr_create dir=%s\n", path));
@@ -399,17 +398,12 @@ NTSTATUS dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOO
return status;
}
- /* use a const pointer from here on */
- dir2 = path;
- if (!*dir2)
- dir2 = ".";
-
- dir_hnd = OpenDir(conn, dir2, wcard, attr);
+ dir_hnd = OpenDir(conn, path, wcard, attr);
if (!dir_hnd) {
return map_nt_error_from_unix(errno);
}
- string_set(&conn->dirpath,dir2);
+ string_set(&conn->dirpath,path);
if (dirhandles_open >= MAX_OPEN_DIRECTORIES) {
dptr_idleoldest();
@@ -488,7 +482,7 @@ NTSTATUS dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOO
dptr->dnum += 1; /* Always bias the dnum by one - no zero dnums allowed. */
- string_set(&dptr->path,dir2);
+ string_set(&dptr->path,path);
dptr->conn = conn;
dptr->dir_hnd = dir_hnd;
dptr->spid = spid;
@@ -758,10 +752,15 @@ BOOL dir_check_ftype(connection_struct *conn, uint32 mode, uint32 dirtype)
return True;
}
-static BOOL mangle_mask_match(connection_struct *conn, fstring filename, char *mask)
+static BOOL mangle_mask_match(connection_struct *conn, const char *filename,
+ char *mask)
{
- mangle_map(filename,True,False,conn->params);
- return mask_match_search(filename,mask,False);
+ char mname[13];
+
+ if (!name_to_8_3(filename,mname,False,conn->params)) {
+ return False;
+ }
+ return mask_match_search(mname,mask,False);
}
/****************************************************************************
@@ -806,9 +805,14 @@ BOOL get_dir_entry(connection_struct *conn,char *mask,uint32 dirtype, pstring fn
mask_match_search(filename,mask,False) ||
mangle_mask_match(conn,filename,mask)) {
- if (!mangle_is_8_3(filename, False, conn->params))
- mangle_map(filename,True,False,
- conn->params);
+ if (!mangle_is_8_3(filename, False, conn->params)) {
+ char mname[13];
+ if (!name_to_8_3(filename,mname,False,
+ conn->params)) {
+ continue;
+ }
+ pstrcpy(filename,mname);
+ }
pstrcpy(fname,filename);
*path = 0;
diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c
index 5f9563b83c..5871fd143f 100644
--- a/source3/smbd/filename.c
+++ b/source3/smbd/filename.c
@@ -2,7 +2,7 @@
Unix SMB/CIFS implementation.
filename handling routines
Copyright (C) Andrew Tridgell 1992-1998
- Copyright (C) Jeremy Allison 1999-2004
+ Copyright (C) Jeremy Allison 1999-2007
Copyright (C) Ying Chen 2000
Copyright (C) Volker Lendecke 2007
@@ -37,11 +37,12 @@ static BOOL mangled_equal(const char *name1,
const char *name2,
const struct share_params *p)
{
- pstring tmpname;
+ char mname[13];
- pstrcpy(tmpname, name2);
- mangle_map(tmpname, True, False, p);
- return strequal(name1, tmpname);
+ if (!name_to_8_3(name2, mname, False, p)) {
+ return False;
+ }
+ return strequal(name1, mname);
}
/****************************************************************************
@@ -107,9 +108,10 @@ for nlinks = 0, which can never be true for any file).
****************************************************************************/
NTSTATUS unix_convert(connection_struct *conn,
- pstring orig_path,
+ const char *orig_path,
BOOL allow_wcard_last_component,
- char *saved_last_component,
+ char **pp_conv_path,
+ char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
{
SMB_STRUCT_STAT st;
@@ -119,16 +121,20 @@ NTSTATUS unix_convert(connection_struct *conn,
BOOL component_was_mangled = False;
BOOL name_has_wildcard = False;
NTSTATUS result;
+ TALLOC_CTX *ctx = talloc_tos();
SET_STAT_INVALID(*pst);
-
- if(saved_last_component) {
- *saved_last_component = 0;
+ *pp_conv_path = NULL;
+ if(pp_saved_last_component) {
+ *pp_saved_last_component = NULL;
}
if (conn->printer) {
/* we don't ever use the filenames on a printer share as a
filename - so don't convert them */
+ if (!(*pp_conv_path = talloc_strdup(ctx,orig_path))) {
+ return NT_STATUS_NO_MEMORY;
+ }
return NT_STATUS_OK;
}
@@ -157,11 +163,13 @@ NTSTATUS unix_convert(connection_struct *conn,
*/
if (!*orig_path) {
- if (!(name = SMB_STRDUP("."))) {
+ if (!(name = talloc_strdup(ctx,"."))) {
return NT_STATUS_NO_MEMORY;
}
if (SMB_VFS_STAT(conn,name,&st) == 0) {
*pst = st;
+ } else {
+ return map_nt_error_from_unix(errno);
}
DEBUG(5,("conversion finished \"\" -> %s\n",name));
goto done;
@@ -183,17 +191,18 @@ NTSTATUS unix_convert(connection_struct *conn,
* Ensure saved_last_component is valid even if file exists.
*/
- if(saved_last_component) {
+ if(pp_saved_last_component) {
end = strrchr_m(orig_path, '/');
if (end) {
- pstrcpy(saved_last_component, end + 1);
+ *pp_saved_last_component = talloc_strdup(ctx, end + 1);
} else {
- pstrcpy(saved_last_component, orig_path);
+ *pp_saved_last_component = talloc_strdup(ctx,
+ orig_path);
}
}
- if (!(name = SMB_STRDUP(orig_path))) {
- DEBUG(0, ("strdup failed\n"));
+ if (!(name = talloc_strdup(ctx, orig_path))) {
+ DEBUG(0, ("talloc_strdup failed\n"));
return NT_STATUS_NO_MEMORY;
}
@@ -224,9 +233,9 @@ NTSTATUS unix_convert(connection_struct *conn,
* building the directories with asprintf and free it.
*/
- if ((dirpath == NULL) && (!(dirpath = SMB_STRDUP("")))) {
- DEBUG(0, ("strdup failed\n"));
- SAFE_FREE(name);
+ if ((dirpath == NULL) && (!(dirpath = talloc_strdup(ctx,"")))) {
+ DEBUG(0, ("talloc_strdup failed\n"));
+ TALLOC_FREE(name);
return NT_STATUS_NO_MEMORY;
}
@@ -264,8 +273,7 @@ NTSTATUS unix_convert(connection_struct *conn,
*/
if (conn->case_sensitive &&
- !mangle_is_mangled(name, conn->params) &&
- !*lp_mangled_map(conn->params)) {
+ !mangle_is_mangled(name, conn->params)) {
goto done;
}
@@ -302,8 +310,14 @@ NTSTATUS unix_convert(connection_struct *conn,
*end = 0;
}
- if (saved_last_component != 0) {
- pstrcpy(saved_last_component, end ? end + 1 : start);
+ if (pp_saved_last_component) {
+ TALLOC_FREE(*pp_saved_last_component);
+ *pp_saved_last_component = talloc_strdup(ctx,
+ end ? end + 1 : start);
+ if (!*pp_saved_last_component) {
+ DEBUG(0, ("talloc failed\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
}
/* The name cannot have a component of "." */
@@ -473,25 +487,27 @@ NTSTATUS unix_convert(connection_struct *conn,
*/
if (mangle_is_mangled(start, conn->params)
- && mangle_check_cache_alloc(start,
- &unmangled,
- conn->params)) {
+ && mangle_lookup_name_from_8_3(ctx,
+ start,
+ &unmangled,
+ conn->params)) {
char *tmp;
size_t start_ofs = start - name;
if (*dirpath != '\0') {
- asprintf(&tmp, "%s/%s", dirpath,
- unmangled);
- SAFE_FREE(unmangled);
+ tmp = talloc_asprintf(ctx,
+ "%s/%s", dirpath,
+ unmangled);
+ TALLOC_FREE(unmangled);
}
else {
tmp = unmangled;
}
if (tmp == NULL) {
- DEBUG(0, ("malloc failed\n"));
- result = NT_STATUS_NO_MEMORY;
+ DEBUG(0, ("talloc failed\n"));
+ return NT_STATUS_NO_MEMORY;
}
- SAFE_FREE(name);
+ TALLOC_FREE(name);
name = tmp;
start = name + start_ofs;
end = start + strlen(start);
@@ -511,18 +527,20 @@ NTSTATUS unix_convert(connection_struct *conn,
size_t start_ofs = start - name;
if (*dirpath != '\0') {
- asprintf(&tmp, "%s/%s/%s", dirpath,
- found_name, end+1);
+ tmp = talloc_asprintf(ctx,
+ "%s/%s/%s", dirpath,
+ found_name, end+1);
}
else {
- asprintf(&tmp, "%s/%s", found_name,
- end+1);
+ tmp = talloc_asprintf(ctx,
+ "%s/%s", found_name,
+ end+1);
}
if (tmp == NULL) {
- DEBUG(0, ("asprintf failed\n"));
- result = NT_STATUS_NO_MEMORY;
+ DEBUG(0, ("talloc_asprintf failed\n"));
+ return NT_STATUS_NO_MEMORY;
}
- SAFE_FREE(name);
+ TALLOC_FREE(name);
name = tmp;
start = name + start_ofs;
end = start + strlen(found_name);
@@ -532,18 +550,19 @@ NTSTATUS unix_convert(connection_struct *conn,
size_t start_ofs = start - name;
if (*dirpath != '\0') {
- asprintf(&tmp, "%s/%s", dirpath,
- found_name);
+ tmp = talloc_asprintf(ctx,
+ "%s/%s", dirpath,
+ found_name);
}
else {
- tmp = SMB_STRDUP(found_name);
+ tmp = talloc_strdup(ctx,
+ found_name);
}
if (tmp == NULL) {
- DEBUG(0, ("malloc failed\n"));
- result = NT_STATUS_NO_MEMORY;
- goto fail;
+ DEBUG(0, ("talloc failed\n"));
+ return NT_STATUS_NO_MEMORY;
}
- SAFE_FREE(name);
+ TALLOC_FREE(name);
name = tmp;
start = name + start_ofs;
@@ -560,7 +579,7 @@ NTSTATUS unix_convert(connection_struct *conn,
}
}
- SAFE_FREE(found_name);
+ TALLOC_FREE(found_name);
} /* end else */
#ifdef DEVELOPER
@@ -577,19 +596,19 @@ NTSTATUS unix_convert(connection_struct *conn,
*/
if (*dirpath != '\0') {
- char *tmp;
-
- if (asprintf(&tmp, "%s/%s", dirpath, start) == -1) {
- DEBUG(0, ("asprintf failed\n"));
+ char *tmp = talloc_asprintf(ctx,
+ "%s/%s", dirpath, start);
+ if (!tmp) {
+ DEBUG(0, ("talloc_asprintf failed\n"));
return NT_STATUS_NO_MEMORY;
}
- SAFE_FREE(dirpath);
+ TALLOC_FREE(dirpath);
dirpath = tmp;
}
else {
- SAFE_FREE(dirpath);
- if (!(dirpath = SMB_STRDUP(start))) {
- DEBUG(0, ("strdup failed\n"));
+ TALLOC_FREE(dirpath);
+ if (!(dirpath = talloc_strdup(ctx,start))) {
+ DEBUG(0, ("talloc_strdup failed\n"));
return NT_STATUS_NO_MEMORY;
}
}
@@ -628,17 +647,23 @@ NTSTATUS unix_convert(connection_struct *conn,
DEBUG(5,("conversion finished %s -> %s\n",orig_path, name));
done:
- pstrcpy(orig_path, name);
- SAFE_FREE(name);
- SAFE_FREE(dirpath);
+ *pp_conv_path = name;
+ TALLOC_FREE(dirpath);
return NT_STATUS_OK;
fail:
DEBUG(10, ("dirpath = [%s] start = [%s]\n", dirpath, start));
- pstrcpy(orig_path, dirpath);
- pstrcat(orig_path, "/");
- pstrcat(orig_path, start);
- SAFE_FREE(name);
- SAFE_FREE(dirpath);
+ if (*dirpath != '\0') {
+ *pp_conv_path = talloc_asprintf(ctx,
+ "%s/%s", dirpath, start);
+ } else {
+ *pp_conv_path = talloc_strdup(ctx, start);
+ }
+ if (!*pp_conv_path) {
+ DEBUG(0, ("talloc_asprintf failed\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+ TALLOC_FREE(name);
+ TALLOC_FREE(dirpath);
return result;
}
@@ -649,7 +674,7 @@ NTSTATUS unix_convert(connection_struct *conn,
a valid one for the user to access.
****************************************************************************/
-NTSTATUS check_name(connection_struct *conn, const pstring name)
+NTSTATUS check_name(connection_struct *conn, const char *name)
{
if (IS_VETO_PATH(conn, name)) {
/* Is it not dot or dot dot. */
@@ -682,8 +707,9 @@ static BOOL fname_equal(const char *name1, const char *name2,
BOOL case_sensitive)
{
/* Normal filename handling */
- if (case_sensitive)
+ if (case_sensitive) {
return(strcmp(name1,name2) == 0);
+ }
return(strequal(name1,name2));
}
@@ -701,17 +727,19 @@ static BOOL scan_directory(connection_struct *conn, const char *path,
BOOL mangled;
char *unmangled_name = NULL;
long curpos;
+ TALLOC_CTX *ctx = talloc_tos();
mangled = mangle_is_mangled(name, conn->params);
/* handle null paths */
- if ((path == NULL) || (*path == 0))
+ if ((path == NULL) || (*path == 0)) {
path = ".";
+ }
/*
* The incoming name can be mangled, and if we de-mangle it
* here it will not compare correctly against the filename (name2)
- * read from the directory and then mangled by the mangle_map()
+ * read from the directory and then mangled by the name_to_8_3()
* call. We need to mangle both names or neither.
* (JRA).
*
@@ -724,15 +752,19 @@ static BOOL scan_directory(connection_struct *conn, const char *path,
*/
if (mangled && !conn->case_sensitive) {
- mangled = !mangle_check_cache_alloc(name, &unmangled_name,
- conn->params);
- name = unmangled_name;
+ mangled = !mangle_lookup_name_from_8_3(ctx,
+ name,
+ &unmangled_name,
+ conn->params);
+ if (mangled) {
+ name = unmangled_name;
+ }
}
/* open the directory */
if (!(cur_dir = OpenDir(conn, path, NULL, 0))) {
DEBUG(3,("scan dir didn't open dir [%s]\n",path));
- SAFE_FREE(unmangled_name);
+ TALLOC_FREE(unmangled_name);
return(False);
}
@@ -741,8 +773,7 @@ static BOOL scan_directory(connection_struct *conn, const char *path,
while ((dname = ReadDirName(cur_dir, &curpos))) {
/* Is it dot or dot dot. */
- if ((dname[0] == '.') && (!dname[1] ||
- (dname[1] == '.' && !dname[2]))) {
+ if (ISDOT(dname) || ISDOTDOT(dname)) {
continue;
}
@@ -760,15 +791,19 @@ static BOOL scan_directory(connection_struct *conn, const char *path,
if ((mangled && mangled_equal(name,dname,conn->params)) ||
fname_equal(name, dname, conn->case_sensitive)) {
/* we've found the file, change it's name and return */
- *found_name = SMB_STRDUP(dname);
- SAFE_FREE(unmangled_name);
+ *found_name = talloc_strdup(ctx,dname);
+ TALLOC_FREE(unmangled_name);
CloseDir(cur_dir);
+ if (!*found_name) {
+ errno = ENOMEM;
+ return False;
+ }
return(True);
}
}
- SAFE_FREE(unmangled_name);
+ TALLOC_FREE(unmangled_name);
CloseDir(cur_dir);
errno = ENOENT;
- return(False);
+ return False;
}
diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c
index fce86903f2..61490c444e 100644
--- a/source3/smbd/mangle.c
+++ b/source3/smbd/mangle.c
@@ -1,18 +1,18 @@
-/*
+/*
Unix SMB/CIFS implementation.
Name mangling interface
Copyright (C) Andrew Tridgell 2002
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
@@ -100,50 +100,51 @@ BOOL mangle_is_8_3_wildcards(const char *fname, BOOL check_case,
return mangle_fns->is_8_3(fname, check_case, True, p);
}
+BOOL mangle_must_mangle(const char *fname,
+ const struct share_params *p)
+{
+ if (!lp_manglednames(p)) {
+ return False;
+ }
+ return mangle_fns->must_mangle(fname, p);
+}
+
/*
- try to reverse map a 8.3 name to the original filename. This doesn't have to
+ try to reverse map a 8.3 name to the original filename. This doesn't have to
always succeed, as the directory handling code in smbd will scan the directory
looking for a matching name if it doesn't. It should succeed most of the time
or there will be a huge performance penalty
*/
-BOOL mangle_check_cache(char *s, size_t maxlen,
+BOOL mangle_lookup_name_from_8_3(TALLOC_CTX *ctx,
+ const char *in,
+ char **out, /* talloced on the given context. */
const struct share_params *p)
{
- return mangle_fns->check_cache(s, maxlen, p);
-}
-
-BOOL mangle_check_cache_alloc(const char *name, char **presult,
- const struct share_params *p)
-{
- pstring tmp;
- char *result;
- pstrcpy(tmp, name);
-
- if (!mangle_check_cache(tmp, sizeof(pstring)-1, p)
- || !(result = SMB_STRDUP(tmp))) {
- return False;
- }
- *presult = result;
- return True;
+ return mangle_fns->lookup_name_from_8_3(ctx, in, out, p);
}
-/*
- map a long filename to a 8.3 name.
+/*
+ mangle a long filename to a 8.3 name.
+ Return True if we did mangle the name (ie. out is filled in).
+ False on error.
+ JRA.
*/
-void mangle_map(pstring OutName, BOOL need83, BOOL cache83,
+BOOL name_to_8_3(const char *in,
+ char out[13],
+ BOOL cache83,
const struct share_params *p)
{
/* name mangling can be disabled for speed, in which case
we just truncate the string */
if (!lp_manglednames(p)) {
- if (need83) {
- string_truncate(OutName, 12);
- }
- return;
+ safe_strcpy(out,in,12);
+ return True;
}
- /* invoke the inane "mangled map" code */
- mangle_map_filename(OutName, p);
- mangle_fns->name_map(OutName, need83, cache83, lp_defaultcase(p->service), p);
+ return mangle_fns->name_to_8_3(in,
+ out,
+ cache83,
+ lp_defaultcase(p->service),
+ p);
}
diff --git a/source3/smbd/mangle_hash.c b/source3/smbd/mangle_hash.c
index 4c02d9685f..d63a980cfb 100644
--- a/source3/smbd/mangle_hash.c
+++ b/source3/smbd/mangle_hash.c
@@ -1,20 +1,21 @@
-/*
+/*
Unix SMB/CIFS implementation.
Name mangling
Copyright (C) Andrew Tridgell 1992-2002
Copyright (C) Simo Sorce 2001
Copyright (C) Andrew Bartlett 2002
-
+ Copyright (C) Jeremy Allison 2007
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
@@ -244,14 +245,14 @@ static NTSTATUS is_8_3_w(const smb_ucs2_t *fname, BOOL allow_wildcards)
if (strlen_w(fname) > 12)
return NT_STATUS_UNSUCCESSFUL;
-
+
if (strcmp_wa(fname, ".") == 0 || strcmp_wa(fname, "..") == 0)
return NT_STATUS_OK;
/* Name cannot start with '.' */
if (*fname == UCS2_CHAR('.'))
return NT_STATUS_UNSUCCESSFUL;
-
+
if (!NT_STATUS_IS_OK(is_valid_name(fname, allow_wildcards, True)))
goto done;
@@ -293,7 +294,7 @@ static BOOL is_8_3(const char *fname, BOOL check_case, BOOL allow_wildcards,
if (strlen(f) > 12)
return False;
-
+
size = push_ucs2_allocate(&ucs2name, f);
if (size == (size_t)-1) {
DEBUG(0,("is_8_3: internal error push_ucs2_allocate() failed!\n"));
@@ -305,15 +306,13 @@ static BOOL is_8_3(const char *fname, BOOL check_case, BOOL allow_wildcards,
done:
SAFE_FREE(ucs2name);
- if (!NT_STATUS_IS_OK(ret)) {
+ if (!NT_STATUS_IS_OK(ret)) {
return False;
}
-
+
return True;
}
-
-
/* -------------------------------------------------------------------------- **
* Functions...
*/
@@ -330,10 +329,11 @@ done:
*
* ************************************************************************** **
*/
+
static void init_chartest( void )
{
const unsigned char *s;
-
+
memset( (char *)chartest, '\0', 256 );
for( s = (const unsigned char *)basechars; *s; s++ ) {
@@ -360,6 +360,7 @@ static void init_chartest( void )
*
* ************************************************************************** **
*/
+
static BOOL is_mangled(const char *s, const struct share_params *p)
{
char *magic;
@@ -406,7 +407,8 @@ static void mangle_reset( void )
crh 07-Apr-1998
**************************************************************************/
-static void cache_mangled_name( const char mangled_name[13], char *raw_name )
+static void cache_mangled_name( const char mangled_name[13],
+ const char *raw_name )
{
TDB_DATA data_val;
char mangled_name_key[13];
@@ -459,30 +461,37 @@ static void cache_mangled_name( const char mangled_name[13], char *raw_name )
* ************************************************************************** **
*/
-static BOOL check_cache( char *s, size_t maxlen, const struct share_params *p )
+static BOOL lookup_name_from_8_3(TALLOC_CTX *ctx,
+ const char *in,
+ char **out, /* talloced on the given context. */
+ const struct share_params *p)
{
TDB_DATA data_val;
- char *ext_start = NULL;
char *saved_ext = NULL;
+ char *s = talloc_strdup(ctx, in);
magic_char = lp_magicchar(p);
/* If the cache isn't initialized, give up. */
- if( !tdb_mangled_cache )
- return( False );
+ if(!s || !tdb_mangled_cache ) {
+ TALLOC_FREE(s);
+ return False;
+ }
data_val = tdb_fetch_bystring(tdb_mangled_cache, s);
/* If we didn't find the name *with* the extension, try without. */
if(data_val.dptr == NULL || data_val.dsize == 0) {
- ext_start = strrchr( s, '.' );
+ char *ext_start = strrchr( s, '.' );
if( ext_start ) {
- if((saved_ext = SMB_STRDUP(ext_start)) == NULL)
+ if((saved_ext = talloc_strdup(ctx,ext_start)) == NULL) {
+ TALLOC_FREE(s);
return False;
+ }
*ext_start = '\0';
data_val = tdb_fetch_bystring(tdb_mangled_cache, s);
- /*
+ /*
* At this point s is the name without the
* extension. We re-add the extension if saved_ext
* is not null, before freeing saved_ext.
@@ -492,31 +501,32 @@ static BOOL check_cache( char *s, size_t maxlen, const struct share_params *p )
/* Okay, if we haven't found it we're done. */
if(data_val.dptr == NULL || data_val.dsize == 0) {
- if(saved_ext) {
- /* Replace the saved_ext as it was truncated. */
- (void)safe_strcat( s, saved_ext, maxlen );
- SAFE_FREE(saved_ext);
- }
- return( False );
+ TALLOC_FREE(saved_ext);
+ TALLOC_FREE(s);
+ return False;
}
- /* If we *did* find it, we need to copy it into the string buffer. */
- (void)safe_strcpy( s, (const char *)data_val.dptr, maxlen );
- if( saved_ext ) {
- /* Replace the saved_ext as it was truncated. */
- (void)safe_strcat( s, saved_ext, maxlen );
- SAFE_FREE(saved_ext);
+ /* If we *did* find it, we need to talloc it on the given ctx. */
+ if (saved_ext) {
+ *out = talloc_asprintf(ctx, "%s%s",
+ (char *)data_val.dptr,
+ saved_ext);
+ } else {
+ *out = talloc_strdup(ctx, (char *)data_val.dptr);
}
+
+ TALLOC_FREE(s);
+ TALLOC_FREE(saved_ext);
SAFE_FREE(data_val.dptr);
- return( True );
+
+ return *out ? True : False;
}
/*****************************************************************************
- * do the actual mangling to 8.3 format
- * the buffer must be able to hold 13 characters (including the null)
- *****************************************************************************
- */
-static void to_8_3(char *s, int default_case)
+ Do the actual mangling to 8.3 format.
+*****************************************************************************/
+
+static BOOL to_8_3(const char *in, char out[13], int default_case)
{
int csum;
char *p;
@@ -524,11 +534,16 @@ static void to_8_3(char *s, int default_case)
char base[9];
int baselen = 0;
int extlen = 0;
+ char *s = SMB_STRDUP(in);
extension[0] = 0;
base[0] = 0;
- p = strrchr(s,'.');
+ if (!s) {
+ return False;
+ }
+
+ p = strrchr(s,'.');
if( p && (strlen(p+1) < (size_t)4) ) {
BOOL all_normal = ( strisnormal(p+1, default_case) ); /* XXXXXXXXX */
@@ -557,7 +572,7 @@ static void to_8_3(char *s, int default_case)
extension[extlen] = 0;
}
}
-
+
p = s;
while( *p && baselen < 5 ) {
@@ -567,79 +582,88 @@ static void to_8_3(char *s, int default_case)
p++;
}
base[baselen] = 0;
-
+
csum = csum % (MANGLE_BASE*MANGLE_BASE);
-
- (void)slprintf(s, 12, "%s%c%c%c",
- base, magic_char, mangle( csum/MANGLE_BASE ), mangle( csum ) );
-
+
+ memcpy(out, base, baselen);
+ out[baselen] = magic_char;
+ out[baselen+1] = mangle( csum/MANGLE_BASE );
+ out[baselen+2] = mangle( csum );
+
if( *extension ) {
- (void)pstrcat( s, "." );
- (void)pstrcat( s, extension );
+ out[baselen+3] = '.';
+ safe_strcpy(&out[baselen+4], extension, 3);
+ }
+
+ SAFE_FREE(s);
+ return True;
+}
+
+static BOOL must_mangle(const char *name,
+ const struct share_params *p)
+{
+ smb_ucs2_t *name_ucs2 = NULL;
+ NTSTATUS status;
+ magic_char = lp_magicchar(p);
+
+ if (push_ucs2_allocate(&name_ucs2, name) == (size_t)-1) {
+ DEBUG(0, ("push_ucs2_allocate failed!\n"));
+ return False;
}
+ status = is_valid_name(name_ucs2, False, False);
+ SAFE_FREE(name_ucs2);
+ return NT_STATUS_IS_OK(status);
}
/*****************************************************************************
* Convert a filename to DOS format. Return True if successful.
+ * Input: in Incoming name.
*
- * Input: OutName - Source *and* destination buffer.
+ * out 8.3 DOS name.
*
- * NOTE that OutName must point to a memory space that
- * is at least 13 bytes in size!
- *
- * need83 - If False, name mangling will be skipped unless the
- * name contains illegal characters. Mapping will still
- * be done, if appropriate. This is probably used to
- * signal that a client does not require name mangling,
- * thus skipping the name mangling even on shares which
- * have name-mangling turned on.
* cache83 - If False, the mangled name cache will not be updated.
* This is usually used to prevent that we overwrite
* a conflicting cache entry prematurely, i.e. before
* we know whether the client is really interested in the
* current name. (See PR#13758). UKD.
*
- * Output: Returns False only if the name wanted mangling but the share does
- * not have name mangling turned on.
- *
* ****************************************************************************
*/
-static void name_map(char *OutName, BOOL need83, BOOL cache83,
- int default_case, const struct share_params *p)
+static BOOL hash_name_to_8_3(const char *in,
+ char out[13],
+ BOOL cache83,
+ int default_case,
+ const struct share_params *p)
{
- smb_ucs2_t *OutName_ucs2;
+ smb_ucs2_t *in_ucs2 = NULL;
magic_char = lp_magicchar(p);
- DEBUG(5,("name_map( %s, need83 = %s, cache83 = %s)\n", OutName,
- need83 ? "True" : "False", cache83 ? "True" : "False"));
-
- if (push_ucs2_allocate(&OutName_ucs2, OutName) == (size_t)-1) {
+ DEBUG(5,("hash_name_to_8_3( %s, cache83 = %s)\n", in,
+ cache83 ? "True" : "False"));
+
+ if (push_ucs2_allocate(&in_ucs2, in) == (size_t)-1) {
DEBUG(0, ("push_ucs2_allocate failed!\n"));
- return;
+ return False;
}
- if( !need83 && !NT_STATUS_IS_OK(is_valid_name(OutName_ucs2, False, False)))
- need83 = True;
-
- /* check if it's already in 8.3 format */
- if (need83 && !NT_STATUS_IS_OK(is_8_3_w(OutName_ucs2, False))) {
- char *tmp = NULL;
-
- /* mangle it into 8.3 */
- if (cache83)
- tmp = SMB_STRDUP(OutName);
-
- to_8_3(OutName, default_case);
+ /* If it's already 8.3, just copy. */
+ if (NT_STATUS_IS_OK(is_valid_name(in_ucs2, False, False)) &&
+ NT_STATUS_IS_OK(is_8_3_w(in_ucs2, False))) {
+ SAFE_FREE(in_ucs2);
+ safe_strcpy(out, in, 12);
+ return True;
+ }
- if(tmp != NULL) {
- cache_mangled_name(OutName, tmp);
- SAFE_FREE(tmp);
- }
+ SAFE_FREE(in_ucs2);
+ if (!to_8_3(in, out, default_case)) {
+ return False;
}
- DEBUG(5,("name_map() ==> [%s]\n", OutName));
- SAFE_FREE(OutName_ucs2);
+ cache_mangled_name(out, in);
+
+ DEBUG(5,("hash_name_to_8_3(%s) ==> [%s]\n", in, out));
+ return True;
}
/*
@@ -649,9 +673,10 @@ static void name_map(char *OutName, BOOL need83, BOOL cache83,
static struct mangle_fns mangle_fns = {
mangle_reset,
is_mangled,
+ must_mangle,
is_8_3,
- check_cache,
- name_map
+ lookup_name_from_8_3,
+ hash_name_to_8_3
};
/* return the methods for this mangling implementation */
diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c
index c3db112051..73f81fe9ae 100644
--- a/source3/smbd/mangle_hash2.c
+++ b/source3/smbd/mangle_hash2.c
@@ -368,18 +368,23 @@ static void mangle_reset(void)
/*
try to find a 8.3 name in the cache, and if found then
- replace the string with the original long name.
+ replace the string with the original long name.
*/
-static BOOL check_cache(char *name, size_t maxlen, const struct share_params *p)
+static BOOL lookup_name_from_8_3(TALLOC_CTX *ctx,
+ const char *name,
+ char **pp_out, /* talloced on the given context. */
+ const struct share_params *p)
{
unsigned int hash, multiplier;
unsigned int i;
const char *prefix;
char extension[4];
+ *pp_out = NULL;
+
/* make sure that this is a mangled name from this cache */
if (!is_mangled(name, p)) {
- M_DEBUG(10,("check_cache: %s -> not mangled\n", name));
+ M_DEBUG(10,("lookup_name_from_8_3: %s -> not mangled\n", name));
return False;
}
@@ -394,7 +399,8 @@ static BOOL check_cache(char *name, size_t maxlen, const struct share_params *p)
/* now look in the prefix cache for that hash */
prefix = cache_lookup(hash);
if (!prefix) {
- M_DEBUG(10,("check_cache: %s -> %08X -> not found\n", name, hash));
+ M_DEBUG(10,("lookup_name_from_8_3: %s -> %08X -> not found\n",
+ name, hash));
return False;
}
@@ -407,17 +413,22 @@ static BOOL check_cache(char *name, size_t maxlen, const struct share_params *p)
}
if (extension[0]) {
- M_DEBUG(10,("check_cache: %s -> %s.%s\n", name, prefix, extension));
- slprintf(name, maxlen, "%s.%s", prefix, extension);
+ M_DEBUG(10,("lookup_name_from_8_3: %s -> %s.%s\n",
+ name, prefix, extension));
+ *pp_out = talloc_asprintf(ctx, "%s.%s", prefix, extension);
} else {
- M_DEBUG(10,("check_cache: %s -> %s\n", name, prefix));
- safe_strcpy(name, prefix, maxlen);
+ M_DEBUG(10,("lookup_name_from_8_3: %s -> %s\n", name, prefix));
+ *pp_out = talloc_strdup(ctx, prefix);
+ }
+
+ if (!pp_out) {
+ M_DEBUG(0,("talloc_fail"));
+ return False;
}
return True;
}
-
/*
look for a DOS reserved name
*/
@@ -499,18 +510,27 @@ static BOOL is_legal_name(const char *name)
return True;
}
+static BOOL must_mangle(const char *name,
+ const struct share_params *p)
+{
+ if (is_reserved_name(name)) {
+ return True;
+ }
+ return !is_legal_name(name);
+}
+
/*
the main forward mapping function, which converts a long filename to
a 8.3 name
- if need83 is not set then we only do the mangling if the name is illegal
- as a long name
-
if cache83 is not set then we don't cache the result
- the name parameter must be able to hold 13 bytes
*/
-static void name_map(fstring name, BOOL need83, BOOL cache83, int default_case, const struct share_params *p)
+static BOOL hash2_name_to_8_3(const char *name,
+ char new_name[13],
+ BOOL cache83,
+ int default_case,
+ const struct share_params *p)
{
char *dot_p;
char lead_chars[7];
@@ -518,20 +538,14 @@ static void name_map(fstring name, BOOL need83, BOOL cache83, int default_case,
unsigned int extension_length, i;
unsigned int prefix_len;
unsigned int hash, v;
- char new_name[13];
/* reserved names are handled specially */
if (!is_reserved_name(name)) {
- /* if the name is already a valid 8.3 name then we don't need to
- do anything */
- if (is_8_3(name, False, False, p)) {
- return;
- }
-
- /* if the caller doesn't strictly need 8.3 then just check for illegal
- filenames */
- if (!need83 && is_legal_name(name)) {
- return;
+ /* if the name is already a valid 8.3 name then we don't need to
+ * change anything */
+ if (is_legal_name(name) && is_8_3(name, False, False, p)) {
+ safe_strcpy(new_name, name, 12);
+ return True;
}
}
@@ -548,7 +562,9 @@ static void name_map(fstring name, BOOL need83, BOOL cache83, int default_case,
break;
}
}
- if (i == 0 || i == 4) dot_p = NULL;
+ if (i == 0 || i == 4) {
+ dot_p = NULL;
+ }
}
/* the leading characters in the mangled name is taken from
@@ -580,11 +596,12 @@ static void name_map(fstring name, BOOL need83, BOOL cache83, int default_case,
for (i=1; extension_length < 3 && dot_p[i]; i++) {
char c = dot_p[i];
if (FLAG_CHECK(c, FLAG_ASCII)) {
- extension[extension_length++] = toupper_ascii(c);
+ extension[extension_length++] =
+ toupper_ascii(c);
}
}
}
-
+
/* find the hash for this prefix */
v = hash = mangle_hash(name, prefix_len);
@@ -593,7 +610,7 @@ static void name_map(fstring name, BOOL need83, BOOL cache83, int default_case,
new_name[i] = lead_chars[i];
}
new_name[7] = base_forward(v % 36);
- new_name[6] = '~';
+ new_name[6] = '~';
for (i=5; i>=mangle_prefix; i--) {
v = v / 36;
new_name[i] = base_forward(v % 36);
@@ -613,22 +630,18 @@ static void name_map(fstring name, BOOL need83, BOOL cache83, int default_case,
cache_insert(name, prefix_len, hash);
}
- M_DEBUG(10,("name_map: %s -> %08X -> %s (cache=%d)\n",
+ M_DEBUG(10,("hash2_name_to_8_3: %s -> %08X -> %s (cache=%d)\n",
name, hash, new_name, cache83));
- /* and overwrite the old name */
- fstrcpy(name, new_name);
-
- /* all done, we've managed to mangle it */
+ return True;
}
-
-/* initialise the flags table
+/* initialise the flags table
we allow only a very restricted set of characters as 'ascii' in this
mangling backend. This isn't a significant problem as modern clients
use the 'long' filenames anyway, and those don't have these
- restrictions.
+ restrictions.
*/
static void init_tables(void)
{
@@ -642,8 +655,8 @@ static void init_tables(void)
char_flags[i] |= FLAG_ILLEGAL;
}
- if ((i >= '0' && i <= '9') ||
- (i >= 'a' && i <= 'z') ||
+ if ((i >= '0' && i <= '9') ||
+ (i >= 'a' && i <= 'z') ||
(i >= 'A' && i <= 'Z')) {
char_flags[i] |= (FLAG_ASCII | FLAG_BASECHAR);
}
@@ -663,7 +676,7 @@ static void init_tables(void)
memset(base_reverse, 0, sizeof(base_reverse));
for (i=0;i<36;i++) {
base_reverse[(unsigned char)base_forward(i)] = i;
- }
+ }
/* fill in the reserved names flags. These are used as a very
fast filter for finding possible DOS reserved filenames */
@@ -694,9 +707,10 @@ static void init_tables(void)
static struct mangle_fns mangle_fns = {
mangle_reset,
is_mangled,
+ must_mangle,
is_8_3,
- check_cache,
- name_map
+ lookup_name_from_8_3,
+ hash2_name_to_8_3
};
/* return the methods for this mangling implementation */
@@ -729,30 +743,45 @@ static BOOL posix_is_mangled(const char *s, const struct share_params *p)
return False;
}
-static BOOL posix_is_8_3(const char *fname, BOOL check_case, BOOL allow_wildcards, const struct share_params *p)
+static BOOL posix_must_mangle(const char *s, const struct share_params *p)
{
return False;
}
-static BOOL posix_check_cache( char *s, size_t maxlen, const struct share_params *p )
+static BOOL posix_is_8_3(const char *fname,
+ BOOL check_case,
+ BOOL allow_wildcards,
+ const struct share_params *p)
{
return False;
}
-static void posix_name_map(char *OutName, BOOL need83, BOOL cache83, int default_case, const struct share_params *p)
+static BOOL posix_lookup_name_from_8_3(TALLOC_CTX *ctx,
+ const char *in,
+ char **out, /* talloced on the given context. */
+ const struct share_params *p)
{
- if (need83) {
- memset(OutName, '\0', 13);
- }
+ return False;
+}
+
+static BOOL posix_name_to_8_3(const char *in,
+ char out[13],
+ BOOL cache83,
+ int default_case,
+ const struct share_params *p)
+{
+ memset(out, '\0', 13);
+ return True;
}
/* POSIX paths backend - no mangle. */
static struct mangle_fns posix_mangle_fns = {
- posix_mangle_reset,
- posix_is_mangled,
- posix_is_8_3,
- posix_check_cache,
- posix_name_map
+ posix_mangle_reset,
+ posix_is_mangled,
+ posix_must_mangle,
+ posix_is_8_3,
+ posix_lookup_name_from_8_3,
+ posix_name_to_8_3
};
struct mangle_fns *posix_mangle_init(void)
diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c
index 16f3cd4370..10652874c5 100644
--- a/source3/smbd/msdfs.c
+++ b/source3/smbd/msdfs.c
@@ -369,7 +369,8 @@ static NTSTATUS dfs_path_lookup(connection_struct *conn,
char *q = NULL;
SMB_STRUCT_STAT sbuf;
NTSTATUS status;
- pstring localpath;
+ pstring localpath_in;
+ char *localpath = NULL;
pstring canon_dfspath; /* Canonicalized dfs path. (only '/' components). */
DEBUG(10,("dfs_path_lookup: Conn path = %s reqpath = %s\n",
@@ -387,8 +388,8 @@ static NTSTATUS dfs_path_lookup(connection_struct *conn,
* think this is needed. JRA.
*/
- pstrcpy(localpath, pdp->reqpath);
- status = unix_convert(conn, localpath, search_flag, NULL, &sbuf);
+ pstrcpy(localpath_in, pdp->reqpath);
+ status = unix_convert(conn, localpath_in, search_flag, &localpath, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status,
NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
return status;
diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c
index b5af173d45..735c147b8d 100644
--- a/source3/smbd/nttrans.c
+++ b/source3/smbd/nttrans.c
@@ -489,7 +489,8 @@ static void reply_ntcreate_and_X_quota(connection_struct *conn,
void reply_ntcreate_and_X(connection_struct *conn,
struct smb_request *req)
{
- pstring fname;
+ pstring fname_in;
+ char *fname = NULL;
uint32 flags;
uint32 access_mask;
uint32 file_attributes;
@@ -589,8 +590,8 @@ void reply_ntcreate_and_X(connection_struct *conn,
if(!dir_fsp->is_directory) {
- srvstr_get_path((char *)req->inbuf, req->flags2, fname,
- smb_buf(req->inbuf), sizeof(fname), 0,
+ srvstr_get_path((char *)req->inbuf, req->flags2, fname_in,
+ smb_buf(req->inbuf), sizeof(fname_in), 0,
STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
@@ -602,7 +603,7 @@ void reply_ntcreate_and_X(connection_struct *conn,
* Check to see if this is a mac fork of some kind.
*/
- if( is_ntfs_stream_name(fname)) {
+ if( is_ntfs_stream_name(fname_in)) {
reply_nterror(
req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
END_PROFILE(SMBntcreateX);
@@ -625,15 +626,15 @@ void reply_ntcreate_and_X(connection_struct *conn,
* Copy in the base directory name.
*/
- pstrcpy( fname, dir_fsp->fsp_name );
- dir_name_len = strlen(fname);
+ pstrcpy( fname_in, dir_fsp->fsp_name );
+ dir_name_len = strlen(fname_in);
/*
* Ensure it ends in a '\'.
*/
- if((fname[dir_name_len-1] != '\\') && (fname[dir_name_len-1] != '/')) {
- pstrcat(fname, "/");
+ if((fname_in[dir_name_len-1] != '\\') && (fname_in[dir_name_len-1] != '/')) {
+ pstrcat(fname_in, "/");
dir_name_len++;
}
@@ -645,10 +646,10 @@ void reply_ntcreate_and_X(connection_struct *conn,
END_PROFILE(SMBntcreateX);
return;
}
- pstrcat(fname, rel_fname);
+ pstrcat(fname_in, rel_fname);
} else {
- srvstr_get_path((char *)req->inbuf, req->flags2, fname,
- smb_buf(req->inbuf), sizeof(fname), 0,
+ srvstr_get_path((char *)req->inbuf, req->flags2, fname_in,
+ smb_buf(req->inbuf), sizeof(fname_in), 0,
STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
@@ -660,8 +661,8 @@ void reply_ntcreate_and_X(connection_struct *conn,
* Check to see if this is a mac fork of some kind.
*/
- if( is_ntfs_stream_name(fname)) {
- enum FAKE_FILE_TYPE fake_file_type = is_fake_file(fname);
+ if( is_ntfs_stream_name(fname_in)) {
+ enum FAKE_FILE_TYPE fake_file_type = is_fake_file(fname_in);
if (fake_file_type!=FAKE_FILE_TYPE_NONE) {
/*
* Here we go! support for changing the disk quotas --metze
@@ -673,7 +674,7 @@ void reply_ntcreate_and_X(connection_struct *conn,
* xp also tries a QUERY_FILE_INFO on the file and then close it
*/
reply_ntcreate_and_X_quota(conn, req,
- fake_file_type, fname);
+ fake_file_type, fname_in);
} else {
reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
}
@@ -686,7 +687,7 @@ void reply_ntcreate_and_X(connection_struct *conn,
* Now contruct the smb_open_mode value from the filename,
* desired access and the share access.
*/
- status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, fname);
+ status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, fname_in);
if (!NT_STATUS_IS_OK(status)) {
if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
@@ -707,17 +708,17 @@ void reply_ntcreate_and_X(connection_struct *conn,
/*
* Ordinary file or directory.
*/
-
+
/*
* Check if POSIX semantics are wanted.
*/
-
+
if (file_attributes & FILE_FLAG_POSIX_SEMANTICS) {
case_state = set_posix_case_semantics(NULL, conn);
file_attributes &= ~FILE_FLAG_POSIX_SEMANTICS;
}
-
- status = unix_convert(conn, fname, False, NULL, &sbuf);
+
+ status = unix_convert(conn, fname_in, False, &fname, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
TALLOC_FREE(case_state);
reply_nterror(req, status);
@@ -1200,7 +1201,7 @@ static struct ea_list *read_nttrans_ea_list(TALLOC_CTX *ctx, const char *pdata,
}
offset += next_offset;
}
-
+
return ea_list_head;
}
@@ -1215,7 +1216,8 @@ static void call_nt_transact_create(connection_struct *conn,
char **ppdata, uint32 data_count,
uint32 max_data_count)
{
- pstring fname;
+ pstring fname_in;
+ char *fname = NULL;
char *params = *ppparams;
char *data = *ppdata;
/* Breakout the oplock request bits so we can set the reply bits separately. */
@@ -1334,8 +1336,8 @@ static void call_nt_transact_create(connection_struct *conn,
}
if(!dir_fsp->is_directory) {
- srvstr_get_path(params, req->flags2, fname,
- params+53, sizeof(fname),
+ srvstr_get_path(params, req->flags2, fname_in,
+ params+53, sizeof(fname_in),
parameter_count-53, STR_TERMINATE,
&status);
if (!NT_STATUS_IS_OK(status)) {
@@ -1347,7 +1349,7 @@ static void call_nt_transact_create(connection_struct *conn,
* Check to see if this is a mac fork of some kind.
*/
- if( is_ntfs_stream_name(fname)) {
+ if( is_ntfs_stream_name(fname_in)) {
reply_nterror(req,
NT_STATUS_OBJECT_PATH_NOT_FOUND);
return;
@@ -1361,15 +1363,15 @@ static void call_nt_transact_create(connection_struct *conn,
* Copy in the base directory name.
*/
- pstrcpy( fname, dir_fsp->fsp_name );
- dir_name_len = strlen(fname);
+ pstrcpy( fname_in, dir_fsp->fsp_name );
+ dir_name_len = strlen(fname_in);
/*
* Ensure it ends in a '\'.
*/
- if((fname[dir_name_len-1] != '\\') && (fname[dir_name_len-1] != '/')) {
- pstrcat(fname, "/");
+ if((fname_in[dir_name_len-1] != '\\') && (fname_in[dir_name_len-1] != '/')) {
+ pstrcat(fname_in, "/");
dir_name_len++;
}
@@ -1383,11 +1385,11 @@ static void call_nt_transact_create(connection_struct *conn,
reply_nterror(req, status);
return;
}
- pstrcat(fname, tmpname);
+ pstrcat(fname_in, tmpname);
}
} else {
- srvstr_get_path(params, req->flags2, fname, params+53,
- sizeof(fname), parameter_count-53,
+ srvstr_get_path(params, req->flags2, fname_in, params+53,
+ sizeof(fname_in), parameter_count-53,
STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
@@ -1398,7 +1400,7 @@ static void call_nt_transact_create(connection_struct *conn,
* Check to see if this is a mac fork of some kind.
*/
- if( is_ntfs_stream_name(fname)) {
+ if( is_ntfs_stream_name(fname_in)) {
reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
return;
}
@@ -1412,7 +1414,7 @@ static void call_nt_transact_create(connection_struct *conn,
/*
* Ordinary file or directory.
*/
-
+
/*
* Check if POSIX semantics are wanted.
*/
@@ -1421,9 +1423,9 @@ static void call_nt_transact_create(connection_struct *conn,
case_state = set_posix_case_semantics(NULL, conn);
file_attributes &= ~FILE_FLAG_POSIX_SEMANTICS;
}
-
+
status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES,
- fname);
+ fname_in);
if (!NT_STATUS_IS_OK(status)) {
TALLOC_FREE(case_state);
if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
@@ -1435,7 +1437,7 @@ static void call_nt_transact_create(connection_struct *conn,
return;
}
- status = unix_convert(conn, fname, False, NULL, &sbuf);
+ status = unix_convert(conn, fname_in, False, &fname, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
TALLOC_FREE(case_state);
reply_nterror(req, status);
@@ -1776,11 +1778,15 @@ void reply_ntcancel(connection_struct *conn, struct smb_request *req)
static NTSTATUS copy_internals(connection_struct *conn,
struct smb_request *req,
- char *oldname, char *newname, uint32 attrs)
+ const char *oldname_in,
+ const char *newname_in,
+ uint32 attrs)
{
SMB_STRUCT_STAT sbuf1, sbuf2;
- pstring last_component_oldname;
- pstring last_component_newname;
+ char *oldname = NULL;
+ char *newname = NULL;
+ char *last_component_oldname = NULL;
+ char *last_component_newname = NULL;
files_struct *fsp1,*fsp2;
uint32 fattr;
int info;
@@ -1794,7 +1800,8 @@ static NTSTATUS copy_internals(connection_struct *conn,
return NT_STATUS_MEDIA_WRITE_PROTECTED;
}
- status = unix_convert(conn, oldname, False, last_component_oldname, &sbuf1);
+ status = unix_convert(conn, oldname_in, False, &oldname,
+ &last_component_oldname, &sbuf1);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
@@ -1814,7 +1821,8 @@ static NTSTATUS copy_internals(connection_struct *conn,
return NT_STATUS_NO_SUCH_FILE;
}
- status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
+ status = unix_convert(conn, newname_in, False, &newname,
+ &last_component_newname, &sbuf2);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
@@ -1840,7 +1848,8 @@ static NTSTATUS copy_internals(connection_struct *conn,
return status;
}
- DEBUG(10,("copy_internals: doing file copy %s to %s\n", oldname, newname));
+ DEBUG(10,("copy_internals: doing file copy %s to %s\n",
+ oldname, newname));
status = open_file_ntcreate(conn, req, oldname, &sbuf1,
FILE_READ_DATA, /* Read-only. */
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index 2694176ca7..dec0e26c41 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -285,11 +285,10 @@ size_t srvstr_get_path(const char *inbuf, uint16 smb_flags2, char *dest,
}
/****************************************************************************
- Check if we have a correct fsp pointing to a file. Replacement for the
- CHECK_FSP macro.
+ Check if we have a correct fsp pointing to a file. Basic check for open fsp.
****************************************************************************/
-BOOL check_fsp(connection_struct *conn, struct smb_request *req,
+BOOL check_fsp_open(connection_struct *conn, struct smb_request *req,
files_struct *fsp, struct current_user *user)
{
if (!(fsp) || !(conn)) {
@@ -300,6 +299,20 @@ BOOL check_fsp(connection_struct *conn, struct smb_request *req,
reply_nterror(req, NT_STATUS_INVALID_HANDLE);
return False;
}
+ return True;
+}
+
+/****************************************************************************
+ Check if we have a correct fsp pointing to a file. Replacement for the
+ CHECK_FSP macro.
+****************************************************************************/
+
+BOOL check_fsp(connection_struct *conn, struct smb_request *req,
+ files_struct *fsp, struct current_user *user)
+{
+ if (!check_fsp_open(conn, req, fsp, user)) {
+ return False;
+ }
if ((fsp)->is_directory) {
reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
return False;
@@ -755,7 +768,9 @@ void reply_ioctl(connection_struct *conn, struct smb_request *req)
SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
- p = smb_buf(req->outbuf) + 1; /* Allow for alignment */
+ p = smb_buf(req->outbuf);
+ memset(p, '\0', replysize+1); /* valgrind-safe. */
+ p += 1; /* Allow for alignment */
switch (ioctl_code) {
case IOCTL_QUERY_JOB_INFO:
@@ -775,8 +790,7 @@ void reply_ioctl(connection_struct *conn, struct smb_request *req)
srvstr_push((char *)req->outbuf, req->flags2,
p+18, lp_servicename(SNUM(conn)),
13, STR_TERMINATE|STR_ASCII);
- }
- else {
+ } else {
memset(p+18, 0, 13);
}
break;
@@ -809,14 +823,15 @@ static NTSTATUS map_checkpath_error(const char *inbuf, NTSTATUS status)
void reply_checkpath(connection_struct *conn, struct smb_request *req)
{
- pstring name;
+ pstring name_in;
+ char *name = NULL;
SMB_STRUCT_STAT sbuf;
NTSTATUS status;
START_PROFILE(SMBcheckpath);
- srvstr_get_path((char *)req->inbuf, req->flags2, name,
- smb_buf(req->inbuf) + 1, sizeof(name), 0,
+ srvstr_get_path((char *)req->inbuf, req->flags2, name_in,
+ smb_buf(req->inbuf) + 1, sizeof(name_in), 0,
STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
status = map_checkpath_error((char *)req->inbuf, status);
@@ -825,7 +840,7 @@ void reply_checkpath(connection_struct *conn, struct smb_request *req)
return;
}
- status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, name);
+ status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, name_in);
if (!NT_STATUS_IS_OK(status)) {
if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
@@ -836,9 +851,9 @@ void reply_checkpath(connection_struct *conn, struct smb_request *req)
goto path_err;
}
- DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->inbuf,smb_vwv0)));
+ DEBUG(3,("reply_checkpath %s mode=%d\n", name_in, (int)SVAL(req->inbuf,smb_vwv0)));
- status = unix_convert(conn, name, False, NULL, &sbuf);
+ status = unix_convert(conn, name_in, False, &name, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
goto path_err;
}
@@ -899,7 +914,8 @@ void reply_checkpath(connection_struct *conn, struct smb_request *req)
void reply_getatr(connection_struct *conn, struct smb_request *req)
{
- pstring fname;
+ pstring fname_in;
+ char *fname = NULL;
SMB_STRUCT_STAT sbuf;
int mode=0;
SMB_OFF_T size=0;
@@ -910,8 +926,8 @@ void reply_getatr(connection_struct *conn, struct smb_request *req)
START_PROFILE(SMBgetatr);
p = smb_buf(req->inbuf) + 1;
- p += srvstr_get_path((char *)req->inbuf, req->flags2, fname, p,
- sizeof(fname), 0, STR_TERMINATE, &status);
+ p += srvstr_get_path((char *)req->inbuf, req->flags2, fname_in, p,
+ sizeof(fname_in), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
END_PROFILE(SMBgetatr);
@@ -919,7 +935,7 @@ void reply_getatr(connection_struct *conn, struct smb_request *req)
}
status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES,
- fname);
+ fname_in);
if (!NT_STATUS_IS_OK(status)) {
if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
@@ -934,7 +950,7 @@ void reply_getatr(connection_struct *conn, struct smb_request *req)
/* dos smetimes asks for a stat of "" - it returns a "hidden directory"
under WfWg - weird! */
- if (*fname == '\0') {
+ if (*fname_in == '\0') {
mode = aHIDDEN | aDIR;
if (!CAN_WRITE(conn)) {
mode |= aRONLY;
@@ -942,7 +958,7 @@ void reply_getatr(connection_struct *conn, struct smb_request *req)
size = 0;
mtime = 0;
} else {
- status = unix_convert(conn, fname, False, NULL,&sbuf);
+ status = unix_convert(conn, fname_in, False, &fname, NULL,&sbuf);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
END_PROFILE(SMBgetatr);
@@ -997,7 +1013,8 @@ void reply_getatr(connection_struct *conn, struct smb_request *req)
void reply_setatr(connection_struct *conn, struct smb_request *req)
{
- pstring fname;
+ pstring fname_in;
+ char *fname = NULL;
int mode;
time_t mtime;
SMB_STRUCT_STAT sbuf;
@@ -1012,8 +1029,8 @@ void reply_setatr(connection_struct *conn, struct smb_request *req)
}
p = smb_buf(req->inbuf) + 1;
- p += srvstr_get_path((char *)req->inbuf, req->flags2, fname, p,
- sizeof(fname), 0, STR_TERMINATE, &status);
+ p += srvstr_get_path((char *)req->inbuf, req->flags2, fname_in, p,
+ sizeof(fname_in), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
END_PROFILE(SMBsetatr);
@@ -1021,7 +1038,7 @@ void reply_setatr(connection_struct *conn, struct smb_request *req)
}
status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES,
- fname);
+ fname_in);
if (!NT_STATUS_IS_OK(status)) {
if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
@@ -1034,7 +1051,7 @@ void reply_setatr(connection_struct *conn, struct smb_request *req)
return;
}
- status = unix_convert(conn, fname, False, NULL, &sbuf);
+ status = unix_convert(conn, fname_in, False, &fname, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
END_PROFILE(SMBsetatr);
@@ -1147,7 +1164,7 @@ void reply_dskattr(connection_struct *conn, struct smb_request *req)
void reply_search(connection_struct *conn, struct smb_request *req)
{
pstring mask;
- pstring directory;
+ char *directory = NULL;
pstring fname;
SMB_OFF_T size;
uint32 mode;
@@ -1181,7 +1198,7 @@ void reply_search(connection_struct *conn, struct smb_request *req)
return;
}
- *mask = *directory = *fname = 0;
+ *mask = *fname = 0;
/* If we were called as SMBffirst then we must expect close. */
if(CVAL(req->inbuf,smb_com) == SMBffirst) {
@@ -1225,8 +1242,7 @@ void reply_search(connection_struct *conn, struct smb_request *req)
if (status_len == 0) {
SMB_STRUCT_STAT sbuf;
- pstrcpy(directory,path);
- nt_status = unix_convert(conn, directory, True, NULL, &sbuf);
+ nt_status = unix_convert(conn, path, True, &directory, NULL, &sbuf);
if (!NT_STATUS_IS_OK(nt_status)) {
reply_nterror(req, nt_status);
END_PROFILE(SMBsearch);
@@ -1243,17 +1259,43 @@ void reply_search(connection_struct *conn, struct smb_request *req)
p = strrchr_m(directory,'/');
if (!p) {
pstrcpy(mask,directory);
- pstrcpy(directory,".");
+ directory = talloc_strdup(talloc_tos(),".");
+ if (!directory) {
+ reply_nterror(req, NT_STATUS_NO_MEMORY);
+ END_PROFILE(SMBsearch);
+ return;
+ }
} else {
*p = 0;
pstrcpy(mask,p+1);
}
if (*directory == '\0') {
- pstrcpy(directory,".");
+ directory = talloc_strdup(talloc_tos(),".");
+ if (!directory) {
+ reply_nterror(req, NT_STATUS_NO_MEMORY);
+ END_PROFILE(SMBsearch);
+ return;
+ }
}
memset((char *)status,'\0',21);
SCVAL(status,0,(dirtype & 0x1F));
+
+ nt_status = dptr_create(conn,
+ directory,
+ True,
+ expect_close,
+ req->smbpid,
+ mask,
+ mask_contains_wcard,
+ dirtype,
+ &conn->dirptr);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ reply_nterror(req, nt_status);
+ END_PROFILE(SMBsearch);
+ return;
+ }
+ dptr_num = dptr_dnum(conn->dirptr);
} else {
int status_dirtype;
@@ -1263,7 +1305,7 @@ void reply_search(connection_struct *conn, struct smb_request *req)
dirtype = status_dirtype;
}
- conn->dirptr = dptr_fetch(status+12,&dptr_num);
+ conn->dirptr = dptr_fetch(status+12,&dptr_num);
if (!conn->dirptr) {
goto SearchEmpty;
}
@@ -1274,25 +1316,6 @@ void reply_search(connection_struct *conn, struct smb_request *req)
* check from the initial saved string.
*/
mask_contains_wcard = ms_has_wild(mask);
- }
-
- if (status_len == 0) {
- nt_status = dptr_create(conn,
- directory,
- True,
- expect_close,
- req->smbpid,
- mask,
- mask_contains_wcard,
- dirtype,
- &conn->dirptr);
- if (!NT_STATUS_IS_OK(nt_status)) {
- reply_nterror(req, nt_status);
- END_PROFILE(SMBsearch);
- return;
- }
- dptr_num = dptr_dnum(conn->dirptr);
- } else {
dirtype = dptr_attr(dptr_num);
}
@@ -1393,13 +1416,18 @@ void reply_search(connection_struct *conn, struct smb_request *req)
/* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
SSVAL(req->outbuf, smb_flg2,
(SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
-
- if ((! *directory) && dptr_path(dptr_num))
- slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
- DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
+ if (!directory) {
+ directory = dptr_path(dptr_num);
+ }
+
+ DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
smb_fn_name(CVAL(req->inbuf,smb_com)),
- mask, directory, dirtype, numentries, maxentries ) );
+ mask,
+ directory ? directory : "./",
+ dirtype,
+ numentries,
+ maxentries ));
END_PROFILE(SMBsearch);
return;
@@ -1468,7 +1496,8 @@ void reply_fclose(connection_struct *conn, struct smb_request *req)
void reply_open(connection_struct *conn, struct smb_request *req)
{
- pstring fname;
+ pstring fname_in;
+ char *fname = NULL;
uint32 fattr=0;
SMB_OFF_T size = 0;
time_t mtime=0;
@@ -1496,8 +1525,8 @@ void reply_open(connection_struct *conn, struct smb_request *req)
deny_mode = SVAL(req->inbuf,smb_vwv0);
dos_attr = SVAL(req->inbuf,smb_vwv1);
- srvstr_get_path((char *)req->inbuf, req->flags2, fname,
- smb_buf(req->inbuf)+1, sizeof(fname), 0,
+ srvstr_get_path((char *)req->inbuf, req->flags2, fname_in,
+ smb_buf(req->inbuf)+1, sizeof(fname_in), 0,
STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
@@ -1506,7 +1535,7 @@ void reply_open(connection_struct *conn, struct smb_request *req)
}
status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES,
- fname);
+ fname_in);
if (!NT_STATUS_IS_OK(status)) {
if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
@@ -1519,7 +1548,7 @@ void reply_open(connection_struct *conn, struct smb_request *req)
return;
}
- status = unix_convert(conn, fname, False, NULL, &sbuf);
+ status = unix_convert(conn, fname_in, False, &fname, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
END_PROFILE(SMBopen);
@@ -1602,7 +1631,8 @@ void reply_open(connection_struct *conn, struct smb_request *req)
void reply_open_and_X(connection_struct *conn, struct smb_request *req)
{
- pstring fname;
+ pstring fname_in;
+ char *fname = NULL;
uint16 open_flags;
int deny_mode;
uint32 smb_attr;
@@ -1658,8 +1688,8 @@ void reply_open_and_X(connection_struct *conn, struct smb_request *req)
}
/* XXXX we need to handle passed times, sattr and flags */
- srvstr_get_path((char *)req->inbuf, req->flags2, fname,
- smb_buf(req->inbuf), sizeof(fname), 0, STR_TERMINATE,
+ srvstr_get_path((char *)req->inbuf, req->flags2, fname_in,
+ smb_buf(req->inbuf), sizeof(fname_in), 0, STR_TERMINATE,
&status);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
@@ -1668,7 +1698,7 @@ void reply_open_and_X(connection_struct *conn, struct smb_request *req)
}
status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES,
- fname);
+ fname_in);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBopenX);
if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
@@ -1680,7 +1710,7 @@ void reply_open_and_X(connection_struct *conn, struct smb_request *req)
return;
}
- status = unix_convert(conn, fname, False, NULL, &sbuf);
+ status = unix_convert(conn, fname_in, False, &fname, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
END_PROFILE(SMBopenX);
@@ -1846,7 +1876,8 @@ void reply_ulogoffX(connection_struct *conn, struct smb_request *req)
void reply_mknew(connection_struct *conn, struct smb_request *req)
{
- pstring fname;
+ pstring fname_in;
+ char *fname = NULL;
int com;
uint32 fattr = 0;
struct timespec ts[2];
@@ -1875,8 +1906,8 @@ void reply_mknew(connection_struct *conn, struct smb_request *req)
srv_make_unix_date3(req->inbuf + smb_vwv1));
/* mtime. */
- srvstr_get_path((char *)req->inbuf, req->flags2, fname,
- smb_buf(req->inbuf) + 1, sizeof(fname), 0,
+ srvstr_get_path((char *)req->inbuf, req->flags2, fname_in,
+ smb_buf(req->inbuf) + 1, sizeof(fname_in), 0,
STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
@@ -1885,7 +1916,7 @@ void reply_mknew(connection_struct *conn, struct smb_request *req)
}
status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES,
- fname);
+ fname_in);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBcreate);
if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
@@ -1897,7 +1928,7 @@ void reply_mknew(connection_struct *conn, struct smb_request *req)
return;
}
- status = unix_convert(conn, fname, False, NULL, &sbuf);
+ status = unix_convert(conn, fname_in, False, &fname, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
END_PROFILE(SMBcreate);
@@ -1974,7 +2005,8 @@ void reply_mknew(connection_struct *conn, struct smb_request *req)
void reply_ctemp(connection_struct *conn, struct smb_request *req)
{
- pstring fname;
+ pstring fname_in;
+ char *fname = NULL;
uint32 fattr;
files_struct *fsp;
int oplock_request;
@@ -1994,22 +2026,22 @@ void reply_ctemp(connection_struct *conn, struct smb_request *req)
fattr = SVAL(req->inbuf,smb_vwv0);
oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
- srvstr_get_path((char *)req->inbuf, req->flags2, fname,
- smb_buf(req->inbuf)+1, sizeof(fname), 0, STR_TERMINATE,
+ srvstr_get_path((char *)req->inbuf, req->flags2, fname_in,
+ smb_buf(req->inbuf)+1, sizeof(fname_in), 0, STR_TERMINATE,
&status);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
END_PROFILE(SMBctemp);
return;
}
- if (*fname) {
- pstrcat(fname,"/TMXXXXXX");
+ if (*fname_in) {
+ pstrcat(fname_in,"/TMXXXXXX");
} else {
- pstrcat(fname,"TMXXXXXX");
+ pstrcat(fname_in,"TMXXXXXX");
}
status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES,
- fname);
+ fname_in);
if (!NT_STATUS_IS_OK(status)) {
if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
@@ -2022,7 +2054,7 @@ void reply_ctemp(connection_struct *conn, struct smb_request *req)
return;
}
- status = unix_convert(conn, fname, False, NULL, &sbuf);
+ status = unix_convert(conn, fname_in, False, &fname, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
END_PROFILE(SMBctemp);
@@ -2266,22 +2298,23 @@ static NTSTATUS do_unlink(connection_struct *conn, struct smb_request *req,
****************************************************************************/
NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
- uint32 dirtype, char *name, BOOL has_wild)
+ uint32 dirtype, const char *name_in, BOOL has_wild)
{
pstring directory;
pstring mask;
+ char *name = NULL;
char *p;
int count=0;
NTSTATUS status = NT_STATUS_OK;
SMB_STRUCT_STAT sbuf;
-
+
*directory = *mask = 0;
-
- status = unix_convert(conn, name, has_wild, NULL, &sbuf);
+
+ status = unix_convert(conn, name_in, has_wild, &name, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
-
+
p = strrchr_m(name,'/');
if (!p) {
pstrcpy(directory,".");
@@ -2291,7 +2324,7 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
pstrcpy(directory,name);
pstrcpy(mask,p+1);
}
-
+
/*
* We should only check the mangled cache
* here if unix_convert failed. This means
@@ -2300,10 +2333,18 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
* for a possible mangle. This patch from
* Tine Smukavec <valentin.smukavec@hermes.si>.
*/
-
- if (!VALID_STAT(sbuf) && mangle_is_mangled(mask,conn->params))
- mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
-
+
+ if (!VALID_STAT(sbuf) && mangle_is_mangled(mask,conn->params)) {
+ char *new_mask = NULL;
+ mangle_lookup_name_from_8_3(talloc_tos(),
+ mask,
+ &new_mask,
+ conn->params );
+ if (new_mask) {
+ pstrcpy(mask, new_mask);
+ }
+ }
+
if (!has_wild) {
pstrcat(directory,"/");
pstrcat(directory,mask);
@@ -2326,7 +2367,7 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
struct smb_Dir *dir_hnd = NULL;
long offset = 0;
const char *dname;
-
+
if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
return NT_STATUS_OBJECT_NAME_INVALID;
}
@@ -2798,6 +2839,7 @@ void reply_lockread(connection_struct *conn, struct smb_request *req)
NTSTATUS status;
files_struct *fsp;
struct byte_range_lock *br_lck = NULL;
+ char *p = NULL;
START_PROFILE(SMBlockread);
@@ -2879,7 +2921,9 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n",
SSVAL(req->outbuf,smb_vwv0,nread);
SSVAL(req->outbuf,smb_vwv5,nread+3);
- SSVAL(smb_buf(req->outbuf),1,nread);
+ p = smb_buf(req->outbuf);
+ SCVAL(p,0,0); /* pad byte. */
+ SSVAL(p,1,nread);
DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
fsp->fnum, (int)numtoread, (int)nread));
@@ -4600,14 +4644,15 @@ void reply_printwrite(connection_struct *conn, struct smb_request *req)
void reply_mkdir(connection_struct *conn, struct smb_request *req)
{
- pstring directory;
+ pstring directory_in;
+ char *directory = NULL;
NTSTATUS status;
SMB_STRUCT_STAT sbuf;
START_PROFILE(SMBmkdir);
- srvstr_get_path((char *)req->inbuf, req->flags2, directory,
- smb_buf(req->inbuf) + 1, sizeof(directory), 0,
+ srvstr_get_path((char *)req->inbuf, req->flags2, directory_in,
+ smb_buf(req->inbuf) + 1, sizeof(directory_in), 0,
STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
@@ -4617,7 +4662,7 @@ void reply_mkdir(connection_struct *conn, struct smb_request *req)
status = resolve_dfspath(conn,
req->flags2 & FLAGS2_DFS_PATHNAMES,
- directory);
+ directory_in);
if (!NT_STATUS_IS_OK(status)) {
if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
@@ -4630,7 +4675,7 @@ void reply_mkdir(connection_struct *conn, struct smb_request *req)
return;
}
- status = unix_convert(conn, directory, False, NULL, &sbuf);
+ status = unix_convert(conn, directory_in, False, &directory, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
END_PROFILE(SMBmkdir);
@@ -4853,13 +4898,14 @@ NTSTATUS rmdir_internals(connection_struct *conn, const char *directory)
void reply_rmdir(connection_struct *conn, struct smb_request *req)
{
- pstring directory;
+ pstring directory_in;
+ char *directory = NULL;
SMB_STRUCT_STAT sbuf;
NTSTATUS status;
START_PROFILE(SMBrmdir);
- srvstr_get_path((char *)req->inbuf, req->flags2, directory,
- smb_buf(req->inbuf) + 1, sizeof(directory), 0,
+ srvstr_get_path((char *)req->inbuf, req->flags2, directory_in,
+ smb_buf(req->inbuf) + 1, sizeof(directory_in), 0,
STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
@@ -4869,7 +4915,7 @@ void reply_rmdir(connection_struct *conn, struct smb_request *req)
status = resolve_dfspath(conn,
req->flags2 & FLAGS2_DFS_PATHNAMES,
- directory);
+ directory_in);
if (!NT_STATUS_IS_OK(status)) {
if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
@@ -4882,7 +4928,8 @@ void reply_rmdir(connection_struct *conn, struct smb_request *req)
return;
}
- status = unix_convert(conn, directory, False, NULL, &sbuf);
+ status = unix_convert(conn, directory_in, False, &directory,
+ NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
END_PROFILE(SMBrmdir);
@@ -4914,87 +4961,129 @@ void reply_rmdir(connection_struct *conn, struct smb_request *req)
/*******************************************************************
Resolve wildcards in a filename rename.
- Note that name is in UNIX charset and thus potentially can be more
- than fstring buffer (255 bytes) especially in default UTF-8 case.
- Therefore, we use pstring inside and all calls should ensure that
- name2 is at least pstring-long (they do already)
********************************************************************/
-static BOOL resolve_wildcards(const char *name1, char *name2)
+static BOOL resolve_wildcards(TALLOC_CTX *ctx,
+ const char *name1,
+ const char *name2,
+ char **pp_newname)
{
- pstring root1,root2;
- pstring ext1,ext2;
+ char *name2_copy = NULL;
+ char *root1 = NULL;
+ char *root2 = NULL;
+ char *ext1 = NULL;
+ char *ext2 = NULL;
char *p,*p2, *pname1, *pname2;
- int available_space, actual_space;
+ name2_copy = talloc_strdup(ctx, name2);
+ if (!name2_copy) {
+ return False;
+ }
+
pname1 = strrchr_m(name1,'/');
- pname2 = strrchr_m(name2,'/');
+ pname2 = strrchr_m(name2_copy,'/');
- if (!pname1 || !pname2)
- return(False);
+ if (!pname1 || !pname2) {
+ return False;
+ }
- pstrcpy(root1,pname1);
- pstrcpy(root2,pname2);
+ /* Truncate the copy of name2 at the last '/' */
+ *pname2 = '\0';
+
+ /* Now go past the '/' */
+ pname1++;
+ pname2++;
+
+ root1 = talloc_strdup(ctx, pname1);
+ root2 = talloc_strdup(ctx, pname2);
+
+ if (!root1 || !root2) {
+ return False;
+ }
+
p = strrchr_m(root1,'.');
if (p) {
*p = 0;
- pstrcpy(ext1,p+1);
+ ext1 = talloc_strdup(ctx, p+1);
} else {
- pstrcpy(ext1,"");
+ ext1 = talloc_strdup(ctx, "");
}
p = strrchr_m(root2,'.');
if (p) {
*p = 0;
- pstrcpy(ext2,p+1);
+ ext2 = talloc_strdup(ctx, p+1);
} else {
- pstrcpy(ext2,"");
+ ext2 = talloc_strdup(ctx, "");
+ }
+
+ if (!ext1 || !ext2) {
+ return False;
}
p = root1;
p2 = root2;
while (*p2) {
if (*p2 == '?') {
+ /* Hmmm. Should this be mb-aware ? */
*p2 = *p;
p2++;
} else if (*p2 == '*') {
- pstrcpy(p2, p);
+ *p2 = '\0';
+ root2 = talloc_asprintf(ctx, "%s%s",
+ root2,
+ p);
+ if (!root2) {
+ return False;
+ }
break;
} else {
p2++;
}
- if (*p)
+ if (*p) {
p++;
+ }
}
p = ext1;
p2 = ext2;
while (*p2) {
if (*p2 == '?') {
+ /* Hmmm. Should this be mb-aware ? */
*p2 = *p;
p2++;
} else if (*p2 == '*') {
- pstrcpy(p2, p);
+ *p2 = '\0';
+ ext2 = talloc_asprintf(ctx, "%s%s",
+ ext2,
+ p);
+ if (!ext2) {
+ return False;
+ }
break;
} else {
p2++;
}
- if (*p)
+ if (*p) {
p++;
+ }
}
- available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
-
- if (ext2[0]) {
- actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
- if (actual_space >= available_space - 1) {
- DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
- actual_space - available_space));
- }
+ if (*ext2) {
+ *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
+ name2_copy,
+ root2,
+ ext2);
} else {
- pstrcpy_base(pname2, root2, name2);
+ *pp_newname = talloc_asprintf(ctx, "%s/%s",
+ name2_copy,
+ root2);
}
- return(True);
+ if (!*pp_newname) {
+ return False;
+ }
+
+ return True;
}
/****************************************************************************
@@ -5110,11 +5199,14 @@ static void notify_rename(connection_struct *conn, BOOL is_dir,
Rename an open file - given an fsp.
****************************************************************************/
-NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp,
- pstring newname,
- const char *newname_last_component,
- uint32 attrs, BOOL replace_if_exists)
+NTSTATUS rename_internals_fsp(connection_struct *conn,
+ files_struct *fsp,
+ char *newname,
+ const char *newname_last_component,
+ uint32 attrs,
+ BOOL replace_if_exists)
{
+ TALLOC_CTX *ctx = talloc_tos();
SMB_STRUCT_STAT sbuf, sbuf1;
NTSTATUS status = NT_STATUS_OK;
struct share_mode_lock *lck = NULL;
@@ -5126,14 +5218,15 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp,
if (!NT_STATUS_IS_OK(status)) {
return status;
}
-
+
/* Ensure newname contains a '/' */
if(strrchr_m(newname,'/') == 0) {
- pstring tmpstr;
-
- pstrcpy(tmpstr, "./");
- pstrcat(tmpstr, newname);
- pstrcpy(newname, tmpstr);
+ newname = talloc_asprintf(ctx,
+ "./%s",
+ newname);
+ if (!newname) {
+ return NT_STATUS_NO_MEMORY;
+ }
}
/*
@@ -5147,7 +5240,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp,
if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
strequal(newname, fsp->fsp_name)) {
char *p;
- pstring newname_modified_last_component;
+ char *newname_modified_last_component = NULL;
/*
* Get the last component of the modified name.
@@ -5155,15 +5248,23 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp,
* character above.
*/
p = strrchr_m(newname,'/');
- pstrcpy(newname_modified_last_component,p+1);
-
- if(strcsequal(newname_modified_last_component,
+ newname_modified_last_component = talloc_strdup(ctx,
+ p+1);
+ if (!newname_modified_last_component) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if(strcsequal(newname_modified_last_component,
newname_last_component) == False) {
/*
* Replace the modified last component with
* the original.
*/
- pstrcpy(p+1, newname_last_component);
+ *p = '\0'; /* Truncate at the '/' */
+ newname = talloc_asprintf(ctx,
+ "%s/%s",
+ newname,
+ newname_last_component);
}
}
@@ -5263,7 +5364,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp,
}
}
TALLOC_FREE(lck);
- return NT_STATUS_OK;
+ return NT_STATUS_OK;
}
TALLOC_FREE(lck);
@@ -5273,7 +5374,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp,
} else {
status = map_nt_error_from_unix(errno);
}
-
+
DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
nt_errstr(status), fsp->fsp_name,newname));
@@ -5286,8 +5387,8 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp,
****************************************************************************/
NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
- pstring name,
- pstring newname,
+ const char *name_in,
+ const char *newname_in,
uint32 attrs,
BOOL replace_if_exists,
BOOL src_has_wild,
@@ -5295,8 +5396,10 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
{
pstring directory;
pstring mask;
- pstring last_component_src;
- pstring last_component_dest;
+ char *last_component_src = NULL;
+ char *last_component_dest = NULL;
+ char *name = NULL;
+ char *newname = NULL;
char *p;
int count=0;
NTSTATUS status = NT_STATUS_OK;
@@ -5311,12 +5414,14 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
ZERO_STRUCT(sbuf1);
ZERO_STRUCT(sbuf2);
- status = unix_convert(conn, name, src_has_wild, last_component_src, &sbuf1);
+ status = unix_convert(conn, name_in, src_has_wild, &name,
+ &last_component_src, &sbuf1);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
- status = unix_convert(conn, newname, dest_has_wild, last_component_dest, &sbuf2);
+ status = unix_convert(conn, newname_in, dest_has_wild, &newname,
+ &last_component_dest, &sbuf2);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
@@ -5351,7 +5456,14 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
*/
if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
- mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
+ char *new_mask = NULL;
+ mangle_lookup_name_from_8_3(talloc_tos(),
+ mask,
+ &new_mask,
+ conn->params );
+ if (new_mask) {
+ pstrcpy(mask, new_mask);
+ }
}
if (!src_has_wild) {
@@ -5365,16 +5477,17 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
/* Add a terminating '/' to the directory name. */
pstrcat(directory,"/");
pstrcat(directory,mask);
-
+
/* Ensure newname contains a '/' also */
if(strrchr_m(newname,'/') == 0) {
- pstring tmpstr;
-
- pstrcpy(tmpstr, "./");
- pstrcat(tmpstr, newname);
- pstrcpy(newname, tmpstr);
+ newname = talloc_asprintf(talloc_tos(),
+ "./%s",
+ newname);
+ if (!newname) {
+ return NT_STATUS_NO_MEMORY;
+ }
}
-
+
DEBUG(3, ("rename_internals: case_sensitive = %d, "
"case_preserve = %d, short case preserve = %d, "
"directory = %s, newname = %s, "
@@ -5385,11 +5498,14 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
/* The dest name still may have wildcards. */
if (dest_has_wild) {
- if (!resolve_wildcards(directory,newname)) {
+ char *mod_newname = NULL;
+ if (!resolve_wildcards(talloc_tos(),
+ directory,newname,&mod_newname)) {
DEBUG(6, ("rename_internals: resolve_wildcards %s %s failed\n",
directory,newname));
return NT_STATUS_NO_MEMORY;
}
+ newname = mod_newname;
}
ZERO_STRUCT(sbuf1);
@@ -5452,6 +5568,7 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
files_struct *fsp;
pstring fname;
BOOL sysdir_entry = False;
+ char *mod_destname = NULL;
pstrcpy(fname,dname);
@@ -5483,11 +5600,13 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
pstrcpy(destname,newname);
- if (!resolve_wildcards(fname,destname)) {
+ if (!resolve_wildcards(talloc_tos(),
+ fname,destname,&mod_destname)) {
DEBUG(6, ("resolve_wildcards %s %s failed\n",
fname, destname));
continue;
}
+ pstrcpy(destname,mod_destname);
ZERO_STRUCT(sbuf1);
SMB_VFS_STAT(conn, fname, &sbuf1);
@@ -5756,9 +5875,12 @@ NTSTATUS copy_file(connection_struct *conn,
void reply_copy(connection_struct *conn, struct smb_request *req)
{
- pstring name;
+ pstring name_in;
+ char *name = NULL;
+ pstring newname_in;
+ char *newname = NULL;
pstring directory;
- pstring mask,newname;
+ pstring mask;
char *p;
int count=0;
int error = ERRnoaccess;
@@ -5787,16 +5909,16 @@ void reply_copy(connection_struct *conn, struct smb_request *req)
*directory = *mask = 0;
p = smb_buf(req->inbuf);
- p += srvstr_get_path_wcard((char *)req->inbuf, req->flags2, name, p,
- sizeof(name), 0, STR_TERMINATE, &status,
+ p += srvstr_get_path_wcard((char *)req->inbuf, req->flags2, name_in, p,
+ sizeof(name_in), 0, STR_TERMINATE, &status,
&source_has_wild);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
END_PROFILE(SMBcopy);
return;
}
- p += srvstr_get_path_wcard((char *)req->inbuf, req->flags2, newname, p,
- sizeof(newname), 0, STR_TERMINATE, &status,
+ p += srvstr_get_path_wcard((char *)req->inbuf, req->flags2, newname_in, p,
+ sizeof(newname_in), 0, STR_TERMINATE, &status,
&dest_has_wild);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
@@ -5804,7 +5926,7 @@ void reply_copy(connection_struct *conn, struct smb_request *req)
return;
}
- DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
+ DEBUG(3,("reply_copy : %s -> %s\n",name_in,newname_in));
if (tid2 != conn->cnum) {
/* can't currently handle inter share copies XXXX */
@@ -5816,7 +5938,7 @@ void reply_copy(connection_struct *conn, struct smb_request *req)
status = resolve_dfspath_wcard(conn,
req->flags2 & FLAGS2_DFS_PATHNAMES,
- name, &source_has_wild);
+ name_in, &source_has_wild);
if (!NT_STATUS_IS_OK(status)) {
if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
@@ -5831,7 +5953,7 @@ void reply_copy(connection_struct *conn, struct smb_request *req)
status = resolve_dfspath_wcard(conn,
req->flags2 & FLAGS2_DFS_PATHNAMES,
- newname, &dest_has_wild);
+ newname_in, &dest_has_wild);
if (!NT_STATUS_IS_OK(status)) {
if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
@@ -5844,14 +5966,14 @@ void reply_copy(connection_struct *conn, struct smb_request *req)
return;
}
- status = unix_convert(conn, name, source_has_wild, NULL, &sbuf1);
+ status = unix_convert(conn, name_in, source_has_wild, &name, NULL, &sbuf1);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
END_PROFILE(SMBcopy);
return;
}
- status = unix_convert(conn, newname, dest_has_wild, NULL, &sbuf2);
+ status = unix_convert(conn, newname_in, dest_has_wild, &newname, NULL, &sbuf2);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
END_PROFILE(SMBcopy);
@@ -5900,18 +6022,28 @@ void reply_copy(connection_struct *conn, struct smb_request *req)
*/
if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
- mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
+ char *new_mask = NULL;
+ mangle_lookup_name_from_8_3( talloc_tos(),
+ mask,
+ &new_mask,
+ conn->params );
+ if (new_mask) {
+ pstrcpy(mask, new_mask);
+ }
}
if (!source_has_wild) {
pstrcat(directory,"/");
pstrcat(directory,mask);
if (dest_has_wild) {
- if (!resolve_wildcards(directory,newname)) {
+ char *mod_newname = NULL;
+ if (!resolve_wildcards(talloc_tos(),
+ directory,newname,&mod_newname)) {
reply_nterror(req, NT_STATUS_NO_MEMORY);
END_PROFILE(SMBcopy);
return;
}
+ newname = mod_newname;
}
status = check_name(conn, directory);
@@ -5965,6 +6097,7 @@ void reply_copy(connection_struct *conn, struct smb_request *req)
error = ERRbadfile;
while ((dname = ReadDirName(dir_hnd, &offset))) {
+ char *mod_destname = NULL;
pstring fname;
pstrcpy(fname,dname);
@@ -5979,9 +6112,11 @@ void reply_copy(connection_struct *conn, struct smb_request *req)
error = ERRnoaccess;
slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
pstrcpy(destname,newname);
- if (!resolve_wildcards(fname,destname)) {
+ if (!resolve_wildcards(talloc_tos(),
+ fname,destname,&mod_destname)) {
continue;
}
+ pstrcpy(destname,mod_destname);
status = check_name(conn, fname);
if (!NT_STATUS_IS_OK(status)) {
diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c
index d2f09930a0..a066091b52 100644
--- a/source3/smbd/statcache.c
+++ b/source3/smbd/statcache.c
@@ -2,7 +2,7 @@
Unix SMB/CIFS implementation.
stat cache code
Copyright (C) Andrew Tridgell 1992-2000
- Copyright (C) Jeremy Allison 1999-2004
+ Copyright (C) Jeremy Allison 1999-2007
Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003
Copyright (C) Volker Lendecke 2007
@@ -40,7 +40,8 @@ static TDB_CONTEXT *tdb_stat_cache;
*
*/
-void stat_cache_add( const char *full_orig_name, const char *translated_path,
+void stat_cache_add( const char *full_orig_name,
+ char *translated_path,
BOOL case_sensitive)
{
size_t translated_path_length;
@@ -48,9 +49,12 @@ void stat_cache_add( const char *full_orig_name, const char *translated_path,
char *original_path;
size_t original_path_length;
size_t sc_size = lp_max_stat_cache_size();
+ char saved_char;
+ TALLOC_CTX *ctx = talloc_tos();
- if (!lp_stat_cache())
+ if (!lp_stat_cache()) {
return;
+ }
if (sc_size && (tdb_map_size(tdb_stat_cache) > sc_size*1024)) {
reset_stat_cache();
@@ -73,20 +77,15 @@ void stat_cache_add( const char *full_orig_name, const char *translated_path,
* would be a waste.
*/
- if (case_sensitive && (strcmp(full_orig_name, translated_path) == 0))
+ if (case_sensitive && (strcmp(full_orig_name, translated_path) == 0)) {
return;
+ }
/*
* Remove any trailing '/' characters from the
* translated path.
*/
- /*
- * To save a strdup we don't necessarily 0-terminate the translated
- * path in the tdb. Instead, we do it directly after the tdb_fetch in
- * stat_cache_lookup.
- */
-
translated_path_length = strlen(translated_path);
if(translated_path[translated_path_length-1] == '/') {
@@ -94,9 +93,9 @@ void stat_cache_add( const char *full_orig_name, const char *translated_path,
}
if(case_sensitive) {
- original_path = SMB_STRDUP(full_orig_name);
+ original_path = talloc_strdup(ctx,full_orig_name);
} else {
- original_path = strdup_upper(full_orig_name);
+ original_path = talloc_strdup_upper(ctx,full_orig_name);
}
if (!original_path) {
@@ -118,7 +117,7 @@ void stat_cache_add( const char *full_orig_name, const char *translated_path,
(unsigned long)original_path_length,
translated_path,
(unsigned long)translated_path_length));
- SAFE_FREE(original_path);
+ TALLOC_FREE(original_path);
return;
}
@@ -129,13 +128,17 @@ void stat_cache_add( const char *full_orig_name, const char *translated_path,
original_path_length = translated_path_length;
}
- /*
- * New entry or replace old entry.
- */
+ /* Ensure we're null terminated. */
+ saved_char = translated_path[translated_path_length];
+ translated_path[translated_path_length] = '\0';
data_val.dsize = translated_path_length + 1;
data_val.dptr = (uint8 *)translated_path;
+ /*
+ * New entry or replace old entry.
+ */
+
if (tdb_store_bystring(tdb_stat_cache, original_path, data_val,
TDB_REPLACE) != 0) {
DEBUG(0,("stat_cache_add: Error storing entry %s -> %s\n",
@@ -148,7 +151,8 @@ void stat_cache_add( const char *full_orig_name, const char *translated_path,
translated_path));
}
- SAFE_FREE(original_path);
+ translated_path[translated_path_length] = saved_char;
+ TALLOC_FREE(original_path);
}
/**
@@ -157,8 +161,10 @@ void stat_cache_add( const char *full_orig_name, const char *translated_path,
* @param conn A connection struct to do the stat() with.
* @param name The path we are attempting to cache, modified by this routine
* to be correct as far as the cache can tell us. We assume that
- * it is a malloc'ed string, we free it if necessary.
- * @param dirpath The path as far as the stat cache told us.
+ * it is a talloc'ed string from top of stack, we free it if
+ * necessary.
+ * @param dirpath The path as far as the stat cache told us. Also talloced
+ * from top of stack.
* @param start A pointer into name, for where to 'start' in fixing the rest
* of the name up.
* @param psd A stat buffer, NOT from the cache, but just a side-effect.
@@ -168,8 +174,11 @@ void stat_cache_add( const char *full_orig_name, const char *translated_path,
*
*/
-BOOL stat_cache_lookup(connection_struct *conn, char **pname, char **dirpath,
- char **start, SMB_STRUCT_STAT *pst)
+BOOL stat_cache_lookup(connection_struct *conn,
+ char **pp_name,
+ char **pp_dirpath,
+ char **pp_start,
+ SMB_STRUCT_STAT *pst)
{
char *chk_name;
size_t namelen;
@@ -179,15 +188,18 @@ BOOL stat_cache_lookup(connection_struct *conn, char **pname, char **dirpath,
size_t translated_path_length;
TDB_DATA data_val;
char *name;
+ TALLOC_CTX *ctx = talloc_tos();
- if (!lp_stat_cache())
+ *pp_dirpath = NULL;
+ *pp_start = *pp_name;
+
+ if (!lp_stat_cache()) {
return False;
+ }
- name = *pname;
+ name = *pp_name;
namelen = strlen(name);
- *start = name;
-
DO_PROFILE_INC(statcache_lookups);
/*
@@ -198,14 +210,14 @@ BOOL stat_cache_lookup(connection_struct *conn, char **pname, char **dirpath,
}
if (conn->case_sensitive) {
- chk_name = SMB_STRDUP(name);
+ chk_name = talloc_strdup(ctx,name);
if (!chk_name) {
DEBUG(0, ("stat_cache_lookup: strdup failed!\n"));
return False;
}
} else {
- chk_name = strdup_upper(name);
+ chk_name = talloc_strdup_upper(ctx,name);
if (!chk_name) {
DEBUG(0, ("stat_cache_lookup: strdup_upper failed!\n"));
return False;
@@ -216,8 +228,9 @@ BOOL stat_cache_lookup(connection_struct *conn, char **pname, char **dirpath,
* if we uppercase. We need to treat this differently
* below.
*/
- if (strlen(chk_name) != namelen)
+ if (strlen(chk_name) != namelen) {
sizechanged = True;
+ }
}
while (1) {
@@ -239,7 +252,7 @@ BOOL stat_cache_lookup(connection_struct *conn, char **pname, char **dirpath,
* We reached the end of the name - no match.
*/
DO_PROFILE_INC(statcache_misses);
- SAFE_FREE(chk_name);
+ TALLOC_FREE(chk_name);
return False;
}
@@ -249,25 +262,25 @@ BOOL stat_cache_lookup(connection_struct *conn, char **pname, char **dirpath,
* Count the number of times we have done this, we'll
* need it when reconstructing the string.
*/
- if (sizechanged)
+
+ if (sizechanged) {
num_components++;
+ }
if ((*chk_name == '\0')
|| ISDOT(chk_name) || ISDOTDOT(chk_name)) {
DO_PROFILE_INC(statcache_misses);
- SAFE_FREE(chk_name);
+ TALLOC_FREE(chk_name);
return False;
}
}
- translated_path = (char *)data_val.dptr;
+ translated_path = talloc_strdup(ctx,(char *)data_val.dptr);
+ if (!translated_path) {
+ smb_panic("talloc failed");
+ }
translated_path_length = data_val.dsize - 1;
-
- /*
- * In stat_cache_add we did not necessarily 0-terminate the translated
- * path. Do it here, where we do have a freshly malloc'ed blob.
- */
- translated_path[translated_path_length] = '\0';
+ SAFE_FREE(data_val.dptr);
DEBUG(10,("stat_cache_lookup: lookup succeeded for name [%s] "
"-> [%s]\n", chk_name, translated_path ));
@@ -276,50 +289,51 @@ BOOL stat_cache_lookup(connection_struct *conn, char **pname, char **dirpath,
if (SMB_VFS_STAT(conn, translated_path, pst) != 0) {
/* Discard this entry - it doesn't exist in the filesystem. */
tdb_delete_bystring(tdb_stat_cache, chk_name);
- SAFE_FREE(chk_name);
- SAFE_FREE(data_val.dptr);
+ TALLOC_FREE(chk_name);
+ TALLOC_FREE(translated_path);
return False;
}
if (!sizechanged) {
- memcpy(name, translated_path,
+ memcpy(*pp_name, translated_path,
MIN(namelen, translated_path_length));
- }
- else {
+ } else {
if (num_components == 0) {
- name = SMB_STRNDUP(translated_path,
+ name = talloc_strndup(ctx, translated_path,
translated_path_length);
} else {
char *sp;
sp = strnrchr_m(name, '/', num_components);
if (sp) {
- asprintf(&name, "%.*s%s",
+ name = talloc_asprintf(ctx,"%.*s%s",
(int)translated_path_length,
translated_path, sp);
} else {
- name = SMB_STRNDUP(translated_path,
- translated_path_length);
+ name = talloc_strndup(ctx,
+ translated_path,
+ translated_path_length);
}
}
if (name == NULL) {
/*
* TODO: Get us out of here with a real error message
*/
- smb_panic("malloc failed");
+ smb_panic("talloc failed");
}
- SAFE_FREE(*pname);
- *pname = name;
+ TALLOC_FREE(*pp_name);
+ *pp_name = name;
}
/* set pointer for 'where to start' on fixing the rest of the name */
- *start = &name[translated_path_length];
- if (**start == '/')
- ++*start;
+ *pp_start = &name[translated_path_length];
+ if (**pp_start == '/') {
+ ++*pp_start;
+ }
- *dirpath = translated_path;
- SAFE_FREE(chk_name);
+ *pp_dirpath = translated_path;
+ TALLOC_FREE(chk_name);
return (namelen == translated_path_length);
}
@@ -344,7 +358,7 @@ void send_stat_cache_delete_message(const char *name)
void stat_cache_delete(const char *name)
{
- char *lname = strdup_upper(name);
+ char *lname = talloc_strdup_upper(talloc_tos(), name);
if (!lname) {
return;
@@ -353,7 +367,7 @@ void stat_cache_delete(const char *name)
lname, name ));
tdb_delete_bystring(tdb_stat_cache, lname);
- SAFE_FREE(lname);
+ TALLOC_FREE(lname);
}
/***************************************************************
diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
index ed4d4554d4..59f384e8b0 100644
--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -783,7 +783,8 @@ static void call_trans2open(connection_struct *conn,
int open_ofun;
uint32 open_size;
char *pname;
- pstring fname;
+ pstring fname_in;
+ char *fname = NULL;
SMB_OFF_T size=0;
int fattr=0,mtime=0;
SMB_INO_T inode = 0;
@@ -829,8 +830,8 @@ static void call_trans2open(connection_struct *conn,
return;
}
- srvstr_get_path(params, req->flags2, fname, pname,
- sizeof(fname), total_params - 28, STR_TERMINATE,
+ srvstr_get_path(params, req->flags2, fname_in, pname,
+ sizeof(fname_in), total_params - 28, STR_TERMINATE,
&status);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
@@ -843,7 +844,7 @@ static void call_trans2open(connection_struct *conn,
/* XXXX we need to handle passed times, sattr and flags */
- status = unix_convert(conn, fname, False, NULL, &sbuf);
+ status = unix_convert(conn, fname_in, False, &fname, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
return;
@@ -1163,6 +1164,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, uint16 flags2,
uint32 nt_extmode; /* Used for NT connections instead of mode */
BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
BOOL check_mangled_names = lp_manglednames(conn->params);
+ char mangled_name[13]; /* mangled 8.3 name. */
*fname = 0;
*out_of_space = False;
@@ -1215,10 +1217,15 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, uint16 flags2,
* pathreal which is composed from dname.
*/
- pstrcpy(fname,dname);
+ pstrcpy(fname,dname);
- /* This will mangle fname if it's an illegal name. */
- mangle_map(fname,False,True,conn->params);
+ /* Mangle fname if it's an illegal name. */
+ if (mangle_must_mangle(fname,conn->params)) {
+ if (!name_to_8_3(fname,mangled_name,True,conn->params)) {
+ continue; /* Error - couldn't mangle. */
+ }
+ pstrcpy(fname,mangled_name);
+ }
if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
got_match = mask_match(fname, mask, conn->case_sensitive);
@@ -1226,19 +1233,17 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, uint16 flags2,
if(!got_match && check_mangled_names &&
!mangle_is_8_3(fname, False, conn->params)) {
- pstring mangled_name;
-
/*
* It turns out that NT matches wildcards against
* both long *and* short names. This may explain some
* of the wildcard wierdness from old DOS clients
* that some people have been seeing.... JRA.
*/
-
- pstrcpy(mangled_name, fname);
-
/* Force the mangling into 8.3. */
- mangle_map( mangled_name, True, False, conn->params);
+ if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
+ continue; /* Error - couldn't mangle. */
+ }
+
if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
got_match = mask_match(mangled_name, mask, conn->case_sensitive);
}
@@ -1483,10 +1488,11 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, uint16 flags2,
* a Win2k client bug. JRA.
*/
if (!was_8_3 && check_mangled_names) {
- pstring mangled_name;
- pstrcpy(mangled_name, fname);
- mangle_map(mangled_name,True,True,
- conn->params);
+ if (!name_to_8_3(fname,mangled_name,True,
+ conn->params)) {
+ /* Error - mangle failed ! */
+ memset(mangled_name,'\0',12);
+ }
mangled_name[12] = 0;
len = srvstr_push(base_data, flags2,
p+2, mangled_name, 24,
@@ -1638,10 +1644,11 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, uint16 flags2,
* a Win2k client bug. JRA.
*/
if (!was_8_3 && check_mangled_names) {
- pstring mangled_name;
- pstrcpy(mangled_name, fname);
- mangle_map(mangled_name,True,True,
- conn->params);
+ if (!name_to_8_3(fname,mangled_name,True,
+ conn->params)) {
+ /* Error - mangle failed ! */
+ memset(mangled_name,'\0',12);
+ }
mangled_name[12] = 0;
len = srvstr_push(base_data, flags2,
p+2, mangled_name, 24,
@@ -1754,7 +1761,8 @@ static void call_trans2findfirst(connection_struct *conn,
BOOL close_if_end;
BOOL requires_resume_key;
int info_level;
- pstring directory;
+ pstring directory_in;
+ char *directory = NULL;
pstring mask;
char *p;
int last_entry_off=0;
@@ -1784,7 +1792,7 @@ static void call_trans2findfirst(connection_struct *conn,
requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
info_level = SVAL(params,6);
- *directory = *mask = 0;
+ *directory_in = *mask = 0;
DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
@@ -1819,15 +1827,15 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
return;
}
- srvstr_get_path_wcard(params, req->flags2, directory,
- params+12, sizeof(directory), total_params - 12,
+ srvstr_get_path_wcard(params, req->flags2, directory_in,
+ params+12, sizeof(directory_in), total_params - 12,
STR_TERMINATE, &ntstatus, &mask_contains_wcard);
if (!NT_STATUS_IS_OK(ntstatus)) {
reply_nterror(req, ntstatus);
return;
}
- ntstatus = resolve_dfspath_wcard(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, directory, &mask_contains_wcard);
+ ntstatus = resolve_dfspath_wcard(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, directory_in, &mask_contains_wcard);
if (!NT_STATUS_IS_OK(ntstatus)) {
if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
@@ -1838,11 +1846,12 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
return;
}
- ntstatus = unix_convert(conn, directory, True, NULL, &sbuf);
+ ntstatus = unix_convert(conn, directory_in, True, &directory, NULL, &sbuf);
if (!NT_STATUS_IS_OK(ntstatus)) {
reply_nterror(req, ntstatus);
return;
}
+
ntstatus = check_name(conn, directory);
if (!NT_STATUS_IS_OK(ntstatus)) {
reply_nterror(req, ntstatus);
@@ -1858,7 +1867,11 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
} else {
pstrcpy(mask,directory);
}
- pstrcpy(directory,"./");
+ directory = talloc_strdup(talloc_tos(), "./");
+ if (!directory) {
+ reply_nterror(req, NT_STATUS_NO_MEMORY);
+ return;
+ }
} else {
pstrcpy(mask,p+1);
*p = 0;
@@ -2030,14 +2043,18 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
send_trans2_replies(req, params, 10, pdata, PTR_DIFF(p,pdata),
max_data_bytes);
- if ((! *directory) && dptr_path(dptr_num))
- slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
+ if ((! *directory) && dptr_path(dptr_num)) {
+ directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
+ if (!directory) {
+ reply_nterror(req, NT_STATUS_NO_MEMORY);
+ }
+ }
DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
smb_fn_name(CVAL(req->inbuf,smb_com)),
mask, directory, dirtype, numentries ) );
- /*
+ /*
* Force a name mangle here to ensure that the
* mask as an 8.3 name is top of the mangled cache.
* The reasons for this are subtle. Don't remove
@@ -2045,8 +2062,10 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
* (see PR#13758). JRA.
*/
- if(!mangle_is_8_3_wildcards( mask, False, conn->params))
- mangle_map(mask, True, True, conn->params);
+ if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
+ char mangled_name[13];
+ name_to_8_3(mask, mangled_name, True, conn->params);
+ }
return;
}
@@ -2270,14 +2289,20 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
long current_pos = 0;
/*
- * Remember, mangle_map is called by
+ * Remember, name_to_8_3 is called by
* get_lanman2_dir_entry(), so the resume name
* could be mangled. Ensure we check the unmangled name.
*/
if (mangle_is_mangled(resume_name, conn->params)) {
- mangle_check_cache(resume_name, sizeof(resume_name)-1,
- conn->params);
+ char *new_resume_name = NULL;
+ mangle_lookup_name_from_8_3(talloc_tos(),
+ resume_name,
+ &new_resume_name,
+ conn->params);
+ if (new_resume_name) {
+ pstrcpy(resume_name, new_resume_name);
+ }
}
/*
@@ -3483,7 +3508,8 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
unsigned int data_size = 0;
unsigned int param_size = 2;
SMB_STRUCT_STAT sbuf;
- pstring fname, dos_fname;
+ pstring dos_fname;
+ char *fname = NULL;
char *fullpathname;
char *base_name;
char *p;
@@ -3530,23 +3556,31 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
return;
}
- if(fsp && (fsp->fake_file_handle)) {
+ /* Initial check for valid fsp ptr. */
+ if (!check_fsp_open(conn, req, fsp, &current_user)) {
+ return;
+ }
+
+ fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
+ if (!fname) {
+ reply_nterror(req, NT_STATUS_NO_MEMORY);
+ return;
+ }
+
+ if(fsp->fake_file_handle) {
/*
* This is actually for the QUOTA_FAKE_FILE --metze
*/
-
- pstrcpy(fname, fsp->fsp_name);
+
/* We know this name is ok, it's already passed the checks. */
-
+
} else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
/*
* This is actually a QFILEINFO on a directory
* handle (returned from an NT SMB). NT5.0 seems
* to do this call. JRA.
*/
- /* We know this name is ok, it's already passed the checks. */
- pstrcpy(fname, fsp->fsp_name);
-
+
if (INFO_LEVEL_IS_UNIX(info_level)) {
/* Always do lstat for UNIX calls. */
if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
@@ -3570,7 +3604,6 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
return;
}
- pstrcpy(fname, fsp->fsp_name);
if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
reply_unixerror(req, ERRDOS, ERRbadfid);
@@ -3581,7 +3614,9 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
delete_pending = get_delete_on_close_flag(fileid);
access_mask = fsp->access_mask;
}
+
} else {
+ pstring fname_in;
NTSTATUS status = NT_STATUS_OK;
/* qpathinfo */
@@ -3599,8 +3634,8 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
return;
}
- srvstr_get_path(params, req->flags2, fname, &params[6],
- sizeof(fname), total_params - 6,
+ srvstr_get_path(params, req->flags2, fname_in, &params[6],
+ sizeof(fname_in), total_params - 6,
STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
@@ -3609,7 +3644,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
status = resolve_dfspath(conn,
req->flags2 & FLAGS2_DFS_PATHNAMES,
- fname);
+ fname_in);
if (!NT_STATUS_IS_OK(status)) {
if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
reply_botherror(req,
@@ -3620,7 +3655,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
return;
}
- status = unix_convert(conn, fname, False, NULL, &sbuf);
+ status = unix_convert(conn, fname_in, False, &fname, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
return;
@@ -3962,16 +3997,16 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
case SMB_QUERY_FILE_ALT_NAME_INFO:
case SMB_FILE_ALTERNATE_NAME_INFORMATION:
{
- pstring short_name;
-
+ char mangled_name[13];
DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
- pstrcpy(short_name,base_name);
- /* Mangle if not already 8.3 */
- if(!mangle_is_8_3(short_name, True, conn->params)) {
- mangle_map(short_name,True,True,conn->params);
+ if (!name_to_8_3(base_name,mangled_name,
+ True,conn->params)) {
+ reply_nterror(
+ req,
+ NT_STATUS_NO_MEMORY);
}
len = srvstr_push(dstart, req->flags2,
- pdata+4, short_name,
+ pdata+4, mangled_name,
PTR_DIFF(dend, pdata+4),
STR_UNICODE);
data_size = 4 + len;
@@ -4395,17 +4430,22 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
code.
****************************************************************************/
-NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring newname)
+NTSTATUS hardlink_internals(connection_struct *conn,
+ char *oldname_in,
+ char *newname_in)
{
SMB_STRUCT_STAT sbuf1, sbuf2;
- pstring last_component_oldname;
- pstring last_component_newname;
+ char *last_component_oldname = NULL;
+ char *last_component_newname = NULL;
+ char *oldname = NULL;
+ char *newname = NULL;
NTSTATUS status = NT_STATUS_OK;
ZERO_STRUCT(sbuf1);
ZERO_STRUCT(sbuf2);
- status = unix_convert(conn, oldname, False, last_component_oldname, &sbuf1);
+ status = unix_convert(conn, oldname_in, False, &oldname,
+ &last_component_oldname, &sbuf1);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
@@ -4420,7 +4460,8 @@ NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring ne
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
- status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
+ status = unix_convert(conn, newname_in, False, &newname,
+ &last_component_newname, &sbuf2);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
@@ -4882,13 +4923,15 @@ static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
static NTSTATUS smb_file_rename_information(connection_struct *conn,
struct smb_request *req,
- const char *pdata, int total_data,
- files_struct *fsp, pstring fname)
+ const char *pdata,
+ int total_data,
+ files_struct *fsp,
+ const char *fname)
{
BOOL overwrite;
uint32 root_fid;
uint32 len;
- pstring newname;
+ pstring newname_in;
pstring base_name;
BOOL dest_has_wcard = False;
NTSTATUS status = NT_STATUS_OK;
@@ -4906,8 +4949,8 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
return NT_STATUS_INVALID_PARAMETER;
}
- srvstr_get_path_wcard(pdata, req->flags2, newname, &pdata[12],
- sizeof(newname), len, 0, &status,
+ srvstr_get_path_wcard(pdata, req->flags2, newname_in, &pdata[12],
+ sizeof(newname_in), len, 0, &status,
&dest_has_wcard);
if (!NT_STATUS_IS_OK(status)) {
return status;
@@ -4915,13 +4958,13 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
status = resolve_dfspath_wcard(conn,
req->flags2 & FLAGS2_DFS_PATHNAMES,
- newname, &dest_has_wcard);
+ newname_in, &dest_has_wcard);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
/* Check the new name has no '/' characters. */
- if (strchr_m(newname, '/')) {
+ if (strchr_m(newname_in, '/')) {
return NT_STATUS_NOT_SUPPORTED;
}
@@ -4934,16 +4977,19 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
pstrcpy(base_name, "./");
}
/* Append the new name. */
- pstrcat(base_name, newname);
+ pstrcat(base_name, newname_in);
if (fsp) {
SMB_STRUCT_STAT sbuf;
- pstring newname_last_component;
+ char *newname = NULL;
+ char *newname_last_component = NULL;
ZERO_STRUCT(sbuf);
- status = unix_convert(conn, newname, False,
- newname_last_component, &sbuf);
+ status = unix_convert(conn, newname_in, False,
+ &newname,
+ &newname_last_component,
+ &sbuf);
/* If an error we expect this to be
* NT_STATUS_OBJECT_PATH_NOT_FOUND */
@@ -4961,7 +5007,7 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
overwrite);
} else {
DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
- fname, newname ));
+ fname, base_name ));
status = rename_internals(conn, req, fname, base_name, 0,
overwrite, False, dest_has_wcard);
}
@@ -6121,7 +6167,7 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
char *pdata = *ppdata;
uint16 info_level;
SMB_STRUCT_STAT sbuf;
- pstring fname;
+ char *fname = NULL;
files_struct *fsp = NULL;
NTSTATUS status = NT_STATUS_OK;
int data_return_size = 0;
@@ -6140,15 +6186,24 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
}
fsp = file_fsp(SVAL(params,0));
- info_level = SVAL(params,2);
+ /* Basic check for non-null fsp. */
+ if (!check_fsp_open(conn, req, fsp, &current_user)) {
+ return;
+ }
+ info_level = SVAL(params,2);
- if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
+ fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
+ if (!fname) {
+ reply_nterror(req, NT_STATUS_NO_MEMORY);
+ return;
+ }
+
+ if(fsp->is_directory || fsp->fh->fd == -1) {
/*
* This is actually a SETFILEINFO on a directory
* handle (returned from an NT SMB). NT5.0 seems
* to do this call. JRA.
*/
- pstrcpy(fname, fsp->fsp_name);
if (INFO_LEVEL_IS_UNIX(info_level)) {
/* Always do lstat for UNIX calls. */
if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
@@ -6163,7 +6218,7 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
return;
}
}
- } else if (fsp && fsp->print_file) {
+ } else if (fsp->print_file) {
/*
* Doing a DELETE_ON_CLOSE should cancel a print job.
*/
@@ -6171,18 +6226,17 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
-
+
SSVAL(params,0,0);
send_trans2_replies(req, params, 2,
*ppdata, 0,
max_data_bytes);
return;
- }
- else {
+ } else {
reply_unixerror(req, ERRDOS, ERRbadpath);
return;
}
- } else {
+ } else {
/*
* Original code - this is an open file.
*/
@@ -6190,8 +6244,6 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
return;
}
- pstrcpy(fname, fsp->fsp_name);
-
if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
reply_unixerror(req, ERRDOS, ERRbadfid);
@@ -6199,15 +6251,17 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
}
}
} else {
+ pstring fname_in;
+
/* set path info */
if (total_params < 7) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
return;
}
- info_level = SVAL(params,0);
- srvstr_get_path(params, req->flags2, fname, &params[6],
- sizeof(fname), total_params - 6, STR_TERMINATE,
+ info_level = SVAL(params,0);
+ srvstr_get_path(params, req->flags2, fname_in, &params[6],
+ sizeof(fname_in), total_params - 6, STR_TERMINATE,
&status);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
@@ -6216,7 +6270,7 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
status = resolve_dfspath(conn,
req->flags2 & FLAGS2_DFS_PATHNAMES,
- fname);
+ fname_in);
if (!NT_STATUS_IS_OK(status)) {
if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
reply_botherror(req,
@@ -6228,7 +6282,7 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
return;
}
- status = unix_convert(conn, fname, False, NULL, &sbuf);
+ status = unix_convert(conn, fname_in, False, &fname, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
return;
@@ -6550,7 +6604,8 @@ static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
{
char *params = *pparams;
char *pdata = *ppdata;
- pstring directory;
+ pstring directory_in;
+ char *directory = NULL;
SMB_STRUCT_STAT sbuf;
NTSTATUS status = NT_STATUS_OK;
struct ea_list *ea_list = NULL;
@@ -6565,17 +6620,17 @@ static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
return;
}
- srvstr_get_path(params, req->flags2, directory, &params[4],
- sizeof(directory), total_params - 4, STR_TERMINATE,
+ srvstr_get_path(params, req->flags2, directory_in, &params[4],
+ sizeof(directory_in), total_params - 4, STR_TERMINATE,
&status);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
return;
}
- DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
+ DEBUG(3,("call_trans2mkdir : name = %s\n", directory_in));
- status = unix_convert(conn, directory, False, NULL, &sbuf);
+ status = unix_convert(conn, directory_in, False, &directory, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
return;