diff options
| author | Jeremy Allison <jra@samba.org> | 2007-09-11 18:31:29 +0000 | 
|---|---|---|
| committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 12:30:40 -0500 | 
| commit | 351eb37a2555ce474ee02758f2f2cfee33d4d434 (patch) | |
| tree | d7a9472eaeece669c613b9d6228b14cfe07ea6d4 | |
| parent | d65ba539a4bd9671bab6f70e140dcc6fb8f0733e (diff) | |
| download | samba-351eb37a2555ce474ee02758f2f2cfee33d4d434.tar.gz samba-351eb37a2555ce474ee02758f2f2cfee33d4d434.tar.bz2 samba-351eb37a2555ce474ee02758f2f2cfee33d4d434.zip  | |
r25102: Rewrite msdfs code to use talloced filenames. Passes make test
and make valgrindtest. Final step will be to change srvstr_get_path()
to return talloced memory in the major codepaths.
Jeremy.
(This used to be commit cf6b6f9c3a38b68d2671c753f412772344506742)
| -rw-r--r-- | source3/include/msdfs.h | 14 | ||||
| -rw-r--r-- | source3/rpc_server/srv_dfs_nt.c | 208 | ||||
| -rwxr-xr-x | source3/script/tests/selftest.sh | 3 | ||||
| -rw-r--r-- | source3/smbd/dir.c | 3 | ||||
| -rw-r--r-- | source3/smbd/msdfs.c | 861 | ||||
| -rw-r--r-- | source3/smbd/nttrans.c | 58 | ||||
| -rw-r--r-- | source3/smbd/reply.c | 213 | ||||
| -rw-r--r-- | source3/smbd/trans2.c | 71 | 
8 files changed, 946 insertions, 485 deletions
diff --git a/source3/include/msdfs.h b/source3/include/msdfs.h index f78f76ba27..717bc85ed5 100644 --- a/source3/include/msdfs.h +++ b/source3/include/msdfs.h @@ -44,23 +44,23 @@ typedef struct _client_referral {  } CLIENT_DFS_REFERRAL;  struct referral { -	pstring alternate_path; /* contains the path referred */ +	char *alternate_path; /* contains the path referred */  	uint32 proximity;  	uint32 ttl; /* how long should client cache referral */  };  struct junction_map { -	fstring service_name; -	pstring volume_name; -	pstring comment; +	char *service_name; +	char *volume_name; +	char *comment;  	int referral_count;  	struct referral* referral_list;  };  struct dfs_path { -	fstring hostname; -	fstring servicename; -	pstring reqpath; +	char *hostname; +	char *servicename; +	char *reqpath;  	BOOL posix_path;  }; diff --git a/source3/rpc_server/srv_dfs_nt.c b/source3/rpc_server/srv_dfs_nt.c index 468a3c4996..1ce81a76f9 100644 --- a/source3/rpc_server/srv_dfs_nt.c +++ b/source3/rpc_server/srv_dfs_nt.c @@ -1,20 +1,20 @@ -/*  +/*   *  Unix SMB/CIFS implementation.   *  RPC Pipe client / server routines for Dfs   *  Copyright (C) Shirish Kalele	2000. - *  Copyright (C) Jeremy Allison	2001. + *  Copyright (C) Jeremy Allison	2001-2007.   *  Copyright (C) Jelmer Vernooij	2005-2006. - *   + *   *  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/>.   */ @@ -40,53 +40,68 @@ void _dfs_GetManagerVersion(pipes_struct *p, struct dfs_GetManagerVersion *r)  WERROR _dfs_Add(pipes_struct *p, struct dfs_Add *r)  { -	struct junction_map jn; -	struct referral* old_referral_list = NULL; +	struct junction_map *jn = NULL; +	struct referral *old_referral_list = NULL;  	BOOL self_ref = False;  	int consumedcnt = 0;  	BOOL exists = False; - -	pstring altpath; +	char *altpath = NULL; +	NTSTATUS status; +	TALLOC_CTX *ctx = talloc_tos();  	if (p->pipe_user.ut.uid != 0) {  		DEBUG(10,("_dfs_add: uid != 0. Access denied.\n"));  		return WERR_ACCESS_DENIED;  	} +	jn = TALLOC_ZERO_P(ctx, struct junction_map); +	if (!jn) { +		return WERR_NOMEM; +	} +  	DEBUG(5,("init_reply_dfs_add: Request to add %s -> %s\\%s.\n",  		r->in.path, r->in.server, r->in.share)); -	pstrcpy(altpath, r->in.server); -	pstrcat(altpath, "\\"); -	pstrcat(altpath, r->in.share); +	altpath = talloc_asprintf(ctx, "%s\\%s", +			r->in.server, +			r->in.share); +	if (!altpath) { +		return WERR_NOMEM; +	}  	/* The following call can change the cwd. */ -	if(NT_STATUS_IS_OK(get_referred_path(p->mem_ctx, r->in.path, &jn, &consumedcnt, &self_ref))) { -		exists = True; -		jn.referral_count += 1; -		old_referral_list = jn.referral_list; -	} else { -		jn.referral_count = 1; +	status = get_referred_path(ctx, r->in.path, jn, +			&consumedcnt, &self_ref); +	if(!NT_STATUS_IS_OK(status)) { +		return ntstatus_to_werror(status);  	} +	exists = True; +	jn->referral_count += 1; +	old_referral_list = jn->referral_list; +  	vfs_ChDir(p->conn,p->conn->connectpath); -	jn.referral_list = TALLOC_ARRAY(p->mem_ctx, struct referral, jn.referral_count); -	if(jn.referral_list == NULL) { +	if (jn->referral_count < 1) { +		return WERR_NOMEM; +	} + +	jn->referral_list = TALLOC_ARRAY(ctx, struct referral, jn->referral_count); +	if(jn->referral_list == NULL) {  		DEBUG(0,("init_reply_dfs_add: talloc failed for referral list!\n"));  		return WERR_DFS_INTERNAL_ERROR;  	} -	if(old_referral_list) { -		memcpy(jn.referral_list, old_referral_list, sizeof(struct referral)*jn.referral_count-1); +	if(old_referral_list && jn->referral_list) { +		memcpy(jn->referral_list, old_referral_list, +				sizeof(struct referral)*jn->referral_count-1);  	} -   -	jn.referral_list[jn.referral_count-1].proximity = 0; -	jn.referral_list[jn.referral_count-1].ttl = REFERRAL_TTL; -	pstrcpy(jn.referral_list[jn.referral_count-1].alternate_path, altpath); -   -	if(!create_msdfs_link(&jn, exists)) { +	jn->referral_list[jn->referral_count-1].proximity = 0; +	jn->referral_list[jn->referral_count-1].ttl = REFERRAL_TTL; +	jn->referral_list[jn->referral_count-1].alternate_path = altpath; + +	if(!create_msdfs_link(jn, exists)) {  		vfs_ChDir(p->conn,p->conn->connectpath);  		return WERR_DFS_CANT_CREATE_JUNCT;  	} @@ -97,35 +112,43 @@ WERROR _dfs_Add(pipes_struct *p, struct dfs_Add *r)  WERROR _dfs_Remove(pipes_struct *p, struct dfs_Remove *r)  { -	struct junction_map jn; +	struct junction_map *jn = NULL;  	BOOL self_ref = False;  	int consumedcnt = 0;  	BOOL found = False; - -	pstring altpath; +	TALLOC_CTX *ctx = talloc_tos(); +	char *altpath = NULL;  	if (p->pipe_user.ut.uid != 0) {  		DEBUG(10,("_dfs_remove: uid != 0. Access denied.\n"));  		return WERR_ACCESS_DENIED;  	} +	jn = TALLOC_ZERO_P(ctx, struct junction_map); +	if (!jn) { +		return WERR_NOMEM; +	} +  	if (r->in.servername && r->in.sharename) { -		pstrcpy(altpath, r->in.servername); -		pstrcat(altpath, "\\"); -		pstrcat(altpath, r->in.sharename); +		altpath = talloc_asprintf(ctx, "%s\\%s", +			r->in.servername, +			r->in.sharename);  		strlower_m(altpath); +		if (!altpath) { +			return WERR_NOMEM; +		} +		DEBUG(5,("init_reply_dfs_remove: Request to remove %s -> %s\\%s.\n", +			r->in.dfs_entry_path, r->in.servername, r->in.sharename));  	} -	DEBUG(5,("init_reply_dfs_remove: Request to remove %s -> %s\\%s.\n", -		r->in.dfs_entry_path, r->in.servername, r->in.sharename)); - -	if(!NT_STATUS_IS_OK(get_referred_path(p->mem_ctx, r->in.dfs_entry_path, &jn, &consumedcnt, &self_ref))) { +	if(!NT_STATUS_IS_OK(get_referred_path(ctx, r->in.dfs_entry_path, jn, +				&consumedcnt, &self_ref))) {  		return WERR_DFS_NO_SUCH_VOL;  	}  	/* if no server-share pair given, remove the msdfs link completely */  	if(!r->in.servername && !r->in.sharename) { -		if(!remove_msdfs_link(&jn)) { +		if(!remove_msdfs_link(jn)) {  			vfs_ChDir(p->conn,p->conn->connectpath);  			return WERR_DFS_NO_SUCH_VOL;  		} @@ -133,14 +156,17 @@ WERROR _dfs_Remove(pipes_struct *p, struct dfs_Remove *r)  	} else {  		int i=0;  		/* compare each referral in the list with the one to remove */ -		DEBUG(10,("altpath: .%s. refcnt: %d\n", altpath, jn.referral_count)); -		for(i=0;i<jn.referral_count;i++) { -			pstring refpath; -			pstrcpy(refpath,jn.referral_list[i].alternate_path); +		DEBUG(10,("altpath: .%s. refcnt: %d\n", altpath, jn->referral_count)); +		for(i=0;i<jn->referral_count;i++) { +			char *refpath = talloc_strdup(ctx, +					jn->referral_list[i].alternate_path); +			if (!refpath) { +				return WERR_NOMEM; +			}  			trim_char(refpath, '\\', '\\');  			DEBUG(10,("_dfs_remove:  refpath: .%s.\n", refpath));  			if(strequal(refpath, altpath)) { -				*(jn.referral_list[i].alternate_path)='\0'; +				*(jn->referral_list[i].alternate_path)='\0';  				DEBUG(10,("_dfs_remove: Removal request matches referral %s\n",  					refpath));  				found = True; @@ -152,13 +178,13 @@ WERROR _dfs_Remove(pipes_struct *p, struct dfs_Remove *r)  		}  		/* Only one referral, remove it */ -		if(jn.referral_count == 1) { -			if(!remove_msdfs_link(&jn)) { +		if(jn->referral_count == 1) { +			if(!remove_msdfs_link(jn)) {  				vfs_ChDir(p->conn,p->conn->connectpath);  				return WERR_DFS_NO_SUCH_VOL;  			}  		} else { -			if(!create_msdfs_link(&jn, True)) {  +			if(!create_msdfs_link(jn, True)) {  				vfs_ChDir(p->conn,p->conn->connectpath);  				return WERR_DFS_CANT_CREATE_JUNCT;  			} @@ -169,10 +195,10 @@ WERROR _dfs_Remove(pipes_struct *p, struct dfs_Remove *r)  	return WERR_OK;  } -static BOOL init_reply_dfs_info_1(TALLOC_CTX *mem_ctx, struct junction_map* j, struct dfs_Info1* dfs1) +static BOOL init_reply_dfs_info_1(TALLOC_CTX *mem_ctx, struct junction_map* j,struct dfs_Info1* dfs1)  { -	dfs1->path = talloc_asprintf(mem_ctx,  -				"\\\\%s\\%s\\%s", global_myname(),  +	dfs1->path = talloc_asprintf(mem_ctx, +				"\\\\%s\\%s\\%s", global_myname(),  				j->service_name, j->volume_name);  	if (dfs1->path == NULL)  		return False; @@ -183,7 +209,7 @@ static BOOL init_reply_dfs_info_1(TALLOC_CTX *mem_ctx, struct junction_map* j, s  static BOOL init_reply_dfs_info_2(TALLOC_CTX *mem_ctx, struct junction_map* j, struct dfs_Info2* dfs2)  { -	dfs2->path = talloc_asprintf(mem_ctx,  +	dfs2->path = talloc_asprintf(mem_ctx,  			"\\\\%s\\%s\\%s", global_myname(), j->service_name, j->volume_name);  	if (dfs2->path == NULL)  		return False; @@ -209,7 +235,7 @@ static BOOL init_reply_dfs_info_3(TALLOC_CTX *mem_ctx, struct junction_map* j, s  	dfs3->comment = talloc_strdup(mem_ctx, j->comment);  	dfs3->state = 1;  	dfs3->num_stores = j->referral_count; -     +  	/* also enumerate the stores */  	if (j->referral_count) {  		dfs3->stores = TALLOC_ARRAY(mem_ctx, struct dfs_StorageInfo, j->referral_count); @@ -221,12 +247,15 @@ static BOOL init_reply_dfs_info_3(TALLOC_CTX *mem_ctx, struct junction_map* j, s  	}  	for(ii=0;ii<j->referral_count;ii++) { -		char* p;  -		pstring path; -		struct dfs_StorageInfo* stor = &(dfs3->stores[ii]); +		char* p; +		char *path = NULL; + 		struct dfs_StorageInfo* stor = &(dfs3->stores[ii]);  		struct referral* ref = &(j->referral_list[ii]); -   -		pstrcpy(path, ref->alternate_path); + +		path = talloc_strdup(mem_ctx, ref->alternate_path); +		if (!path) { +			return False; +		}  		trim_char(path,'\\','\0');  		p = strrchr_m(path,'\\');  		if(p==NULL) { @@ -248,16 +277,20 @@ static BOOL init_reply_dfs_info_100(TALLOC_CTX *mem_ctx, struct junction_map* j,  	return True;  } -  WERROR _dfs_Enum(pipes_struct *p, struct dfs_Enum *r)  { -	struct junction_map jn[MAX_MSDFS_JUNCTIONS]; -	int num_jn = 0; -	int i; - -	num_jn = enum_msdfs_links(p->mem_ctx, jn, ARRAY_SIZE(jn)); +	struct junction_map *jn = NULL; +	size_t num_jn = 0; +	size_t i; +	TALLOC_CTX *ctx = talloc_tos(); + +	jn = enum_msdfs_links(ctx, &num_jn); +	if (!jn || num_jn == 0) { +		num_jn = 0; +		jn = NULL; +	}  	vfs_ChDir(p->conn,p->conn->connectpath); -     +  	DEBUG(5,("_dfs_Enum: %d junctions found in Dfs, doing level %d\n", num_jn, r->in.level));  	*r->out.total = num_jn; @@ -266,7 +299,7 @@ WERROR _dfs_Enum(pipes_struct *p, struct dfs_Enum *r)  	switch (r->in.level) {  	case 1:  		if (num_jn) { -			if ((r->out.info->e.info1->s = TALLOC_ARRAY(p->mem_ctx, struct dfs_Info1, num_jn)) == NULL) { +			if ((r->out.info->e.info1->s = TALLOC_ARRAY(ctx, struct dfs_Info1, num_jn)) == NULL) {  				return WERR_NOMEM;  			}  		} else { @@ -276,7 +309,7 @@ WERROR _dfs_Enum(pipes_struct *p, struct dfs_Enum *r)  		break;  	case 2:  		if (num_jn) { -			if ((r->out.info->e.info2->s = TALLOC_ARRAY(p->mem_ctx, struct dfs_Info2, num_jn)) == NULL) { +			if ((r->out.info->e.info2->s = TALLOC_ARRAY(ctx, struct dfs_Info2, num_jn)) == NULL) {  				return WERR_NOMEM;  			}  		} else { @@ -286,7 +319,7 @@ WERROR _dfs_Enum(pipes_struct *p, struct dfs_Enum *r)  		break;  	case 3:  		if (num_jn) { -			if ((r->out.info->e.info3->s = TALLOC_ARRAY(p->mem_ctx, struct dfs_Info3, num_jn)) == NULL) { +			if ((r->out.info->e.info3->s = TALLOC_ARRAY(ctx, struct dfs_Info3, num_jn)) == NULL) {  				return WERR_NOMEM;  			}  		} else { @@ -300,35 +333,44 @@ WERROR _dfs_Enum(pipes_struct *p, struct dfs_Enum *r)  	for (i = 0; i < num_jn; i++) {  		switch (r->in.level) { -		case 1:  -			init_reply_dfs_info_1(p->mem_ctx, &jn[i], &r->out.info->e.info1->s[i]); +		case 1: +			init_reply_dfs_info_1(ctx, &jn[i], &r->out.info->e.info1->s[i]);  			break;  		case 2: -			init_reply_dfs_info_2(p->mem_ctx, &jn[i], &r->out.info->e.info2->s[i]); +			init_reply_dfs_info_2(ctx, &jn[i], &r->out.info->e.info2->s[i]);  			break;  		case 3: -			init_reply_dfs_info_3(p->mem_ctx, &jn[i], &r->out.info->e.info3->s[i]); +			init_reply_dfs_info_3(ctx, &jn[i], &r->out.info->e.info3->s[i]);  			break;  		default:  			return WERR_INVALID_PARAM;  		}  	} -   +  	return WERR_OK;  }  WERROR _dfs_GetInfo(pipes_struct *p, struct dfs_GetInfo *r)  { -	int consumedcnt = sizeof(pstring); -	struct junction_map jn; +	int consumedcnt = strlen(r->in.dfs_entry_path); +	struct junction_map *jn = NULL;  	BOOL self_ref = False; +	TALLOC_CTX *ctx = talloc_tos();  	BOOL ret; -	if(!create_junction(r->in.dfs_entry_path, &jn)) +	jn = TALLOC_ZERO_P(ctx, struct junction_map); +	if (!jn) { +		return WERR_NOMEM; +	} + +	if(!create_junction(ctx, r->in.dfs_entry_path, jn)) {  		return WERR_DFS_NO_SUCH_SERVER; -   +	} +  	/* The following call can change the cwd. */ -	if(!NT_STATUS_IS_OK(get_referred_path(p->mem_ctx, r->in.dfs_entry_path, &jn, &consumedcnt, &self_ref)) || consumedcnt < strlen(r->in.dfs_entry_path)) { +	if(!NT_STATUS_IS_OK(get_referred_path(ctx, r->in.dfs_entry_path, +					jn, &consumedcnt, &self_ref)) || +			consumedcnt < strlen(r->in.dfs_entry_path)) {  		vfs_ChDir(p->conn,p->conn->connectpath);  		return WERR_DFS_NO_SUCH_VOL;  	} @@ -336,18 +378,18 @@ WERROR _dfs_GetInfo(pipes_struct *p, struct dfs_GetInfo *r)  	vfs_ChDir(p->conn,p->conn->connectpath);  	switch (r->in.level) { -		case 1: ret = init_reply_dfs_info_1(p->mem_ctx, &jn, r->out.info->info1); break; -		case 2: ret = init_reply_dfs_info_2(p->mem_ctx, &jn, r->out.info->info2); break; -		case 3: ret = init_reply_dfs_info_3(p->mem_ctx, &jn, r->out.info->info3); break; -		case 100: ret = init_reply_dfs_info_100(p->mem_ctx, &jn, r->out.info->info100); break; +		case 1: ret = init_reply_dfs_info_1(ctx, jn, r->out.info->info1); break; +		case 2: ret = init_reply_dfs_info_2(ctx, jn, r->out.info->info2); break; +		case 3: ret = init_reply_dfs_info_3(ctx, jn, r->out.info->info3); break; +		case 100: ret = init_reply_dfs_info_100(ctx, jn, r->out.info->info100); break;  		default:  			r->out.info->info1 = NULL;  			return WERR_INVALID_PARAM;  	} -	if (!ret)  +	if (!ret)  		return WERR_INVALID_PARAM; -   +  	return WERR_OK;  } diff --git a/source3/script/tests/selftest.sh b/source3/script/tests/selftest.sh index 8de6420b10..c1d4b23c5f 100755 --- a/source3/script/tests/selftest.sh +++ b/source3/script/tests/selftest.sh @@ -139,6 +139,9 @@ cat >$SERVERCONFFILE<<EOF  	printing = bsd  	printcap name = /dev/null +	host msdfs = yes +	panic action = "/bin/sleep 90000" +  [tmp]  	path = $PREFIX_ABS/tmp  	read only = no diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index e602008b8f..b21e6501d6 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -1019,7 +1019,6 @@ BOOL is_visible_file(connection_struct *conn, const char *dir_path, const char *  	}  	if (hide_unreadable || hide_unwriteable || hide_special) { -		pstring link_target;  		char *entry = NULL;  		if (asprintf(&entry, "%s/%s", dir_path, name) == -1) { @@ -1029,7 +1028,7 @@ BOOL is_visible_file(connection_struct *conn, const char *dir_path, const char *  		/* If it's a dfs symlink, ignore _hide xxxx_ options */  		if (lp_host_msdfs() &&  				lp_msdfs_root(SNUM(conn)) && -				is_msdfs_link(conn, entry, link_target, NULL)) { +				is_msdfs_link(conn, entry, NULL)) {  			SAFE_FREE(entry);  			return True;  		} diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 10652874c5..d687974ff3 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -1,4 +1,4 @@ -/*  +/*     Unix SMB/Netbios implementation.     Version 3.0     MSDFS services for Samba @@ -9,12 +9,12 @@     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/>. @@ -36,22 +36,37 @@ extern uint32 global_client_caps;   SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES bit and then   send a local path, we have to cope with that too.... + This version does everything using pointers within one copy of the + pathname string, talloced on the struct dfs_path pointer (which + must be talloced). This may be too clever to live....   JRA.  **********************************************************************/  static NTSTATUS parse_dfs_path(const char *pathname,  				BOOL allow_wcards, -				struct dfs_path *pdp, +				struct dfs_path *pdp, /* MUST BE TALLOCED */  				BOOL *ppath_contains_wcard)  { -	pstring pathname_local; +	char *pathname_local;  	char *p,*temp; +	char *eos_ptr;  	NTSTATUS status = NT_STATUS_OK;  	char sepchar;  	ZERO_STRUCTP(pdp); -	pstrcpy(pathname_local,pathname); +	/* +	 * This is the only talloc we should need to do +	 * on the struct dfs_path. All the pointers inside +	 * it should point to offsets within this string. +	 */ + +	pathname_local = talloc_strdup(pdp, pathname); +	if (!pathname_local) { +		return NT_STATUS_NO_MEMORY; +	} +	/* Get a pointer to the terminating '\0' */ +	eos_ptr = &pathname_local[strlen(pathname_local)];  	p = temp = pathname_local;  	pdp->posix_path = (lp_posix_pathnames() && *pathname == '/'); @@ -66,17 +81,22 @@ static NTSTATUS parse_dfs_path(const char *pathname,  		 * Try and convert to a local path.  		 */ -		pdp->hostname[0] = '\0'; -		pdp->servicename[0] = '\0'; +		pdp->hostname = eos_ptr; /* "" */ +		pdp->servicename = eos_ptr; /* "" */  		/* We've got no info about separators. */  		pdp->posix_path = lp_posix_pathnames();  		p = temp; -		DEBUG(10,("parse_dfs_path: trying to convert %s to a local path\n", +		DEBUG(10,("parse_dfs_path: trying to convert %s to a " +			"local path\n",  			temp));  		goto local_path;  	} +	/* +	 * Safe to use on talloc'ed string as it only shrinks. +	 * It also doesn't affect the eos_ptr. +	 */  	trim_char(temp,sepchar,sepchar);  	DEBUG(10,("parse_dfs_path: temp = |%s| after trimming %c's\n", @@ -93,34 +113,38 @@ static NTSTATUS parse_dfs_path(const char *pathname,  		 * Try and convert to a local path.  		 */ -		pdp->hostname[0] = '\0'; -		pdp->servicename[0] = '\0'; +		pdp->hostname = eos_ptr; /* "" */ +		pdp->servicename = eos_ptr; /* "" */  		p = temp; -		DEBUG(10,("parse_dfs_path: trying to convert %s to a local path\n", +		DEBUG(10,("parse_dfs_path: trying to convert %s " +			"to a local path\n",  			temp));  		goto local_path;  	}  	*p = '\0'; -	fstrcpy(pdp->hostname,temp); +	pdp->hostname = temp; +  	DEBUG(10,("parse_dfs_path: hostname: %s\n",pdp->hostname));  	/* If we got a hostname, is it ours (or an IP address) ? */  	if (!is_myname_or_ipaddr(pdp->hostname)) {  		/* Repair path. */  		*p = sepchar; -		DEBUG(10,("parse_dfs_path: hostname %s isn't ours. Try local path from path %s\n", +		DEBUG(10,("parse_dfs_path: hostname %s isn't ours. " +			"Try local path from path %s\n",  			pdp->hostname, temp));  		/*  		 * Possibly client sent a local path by mistake.  		 * Try and convert to a local path.  		 */ -		pdp->hostname[0] = '\0'; -		pdp->servicename[0] = '\0'; +		pdp->hostname = eos_ptr; /* "" */ +		pdp->servicename = eos_ptr; /* "" */  		p = temp; -		DEBUG(10,("parse_dfs_path: trying to convert %s to a local path\n", +		DEBUG(10,("parse_dfs_path: trying to convert %s " +			"to a local path\n",  			temp));  		goto local_path;  	} @@ -129,12 +153,12 @@ static NTSTATUS parse_dfs_path(const char *pathname,  	temp = p+1;  	p = strchr_m(temp,sepchar);  	if(p == NULL) { -		fstrcpy(pdp->servicename,temp); -		pdp->reqpath[0] = '\0'; +		pdp->servicename = temp; +		pdp->reqpath = eos_ptr; /* "" */  		return NT_STATUS_OK;  	}  	*p = '\0'; -	fstrcpy(pdp->servicename,temp); +	pdp->servicename = temp;  	DEBUG(10,("parse_dfs_path: servicename: %s\n",pdp->servicename));  	p++; @@ -143,14 +167,15 @@ static NTSTATUS parse_dfs_path(const char *pathname,  	*ppath_contains_wcard = False; -	pstrcpy(pdp->reqpath, p); +	pdp->reqpath = p;  	/* Rest is reqpath. */  	if (pdp->posix_path) {  		status = check_path_syntax_posix(pdp->reqpath);  	} else {  		if (allow_wcards) { -			status = check_path_syntax_wcard(pdp->reqpath, ppath_contains_wcard); +			status = check_path_syntax_wcard(pdp->reqpath, +					ppath_contains_wcard);  		} else {  			status = check_path_syntax(pdp->reqpath);  		} @@ -171,7 +196,9 @@ static NTSTATUS parse_dfs_path(const char *pathname,   Note this CHANGES CWD !!!! JRA.  *********************************************************/ -static NTSTATUS create_conn_struct(connection_struct *conn, int snum, const char *path) +static NTSTATUS create_conn_struct(connection_struct *conn, +				int snum, +				const char *path)  {  	pstring connpath; @@ -187,7 +214,8 @@ static NTSTATUS create_conn_struct(connection_struct *conn, int snum, const char  		return NT_STATUS_NO_MEMORY;  	} -	if (!(conn->params = TALLOC_ZERO_P(conn->mem_ctx, struct share_params))) { +	if (!(conn->params = TALLOC_ZERO_P(conn->mem_ctx, +					struct share_params))) {  		DEBUG(0, ("TALLOC failed\n"));  		return NT_STATUS_NO_MEMORY;  	} @@ -204,15 +232,16 @@ static NTSTATUS create_conn_struct(connection_struct *conn, int snum, const char  	}  	/* -	 * Windows seems to insist on doing trans2getdfsreferral() calls on the IPC$ -	 * share as the anonymous user. If we try to chdir as that user we will -	 * fail.... WTF ? JRA. +	 * Windows seems to insist on doing trans2getdfsreferral() calls on +	 * the IPC$ share as the anonymous user. If we try to chdir as that +	 * user we will fail.... WTF ? JRA.  	 */  	if (vfs_ChDir(conn,conn->connectpath) != 0) {  		NTSTATUS status = map_nt_error_from_unix(errno); -		DEBUG(3,("create_conn_struct: Can't ChDir to new conn path %s. Error was %s\n", -					conn->connectpath, strerror(errno) )); +		DEBUG(3,("create_conn_struct: Can't ChDir to new conn path %s. " +			"Error was %s\n", +			conn->connectpath, strerror(errno) ));  		conn_free_internal(conn);  		return status;  	} @@ -240,23 +269,31 @@ static NTSTATUS create_conn_struct(connection_struct *conn, int snum, const char   **********************************************************************/  static BOOL parse_msdfs_symlink(TALLOC_CTX *ctx, -				char *target, +				const char *target,  				struct referral **preflist,  				int *refcount)  { -	pstring temp; +	char *temp = NULL;  	char *prot; -	char *alt_path[MAX_REFERRAL_COUNT]; +	char **alt_path = NULL;  	int count = 0, i;  	struct referral *reflist; -	pstrcpy(temp,target); +	temp = talloc_strdup(ctx, target); +	if (!temp) { +		return False; +	}  	prot = strtok(temp,":");  	if (!prot) {  		DEBUG(0,("parse_msdfs_symlink: invalid path !\n"));  		return False;  	} +	alt_path = TALLOC_ARRAY(ctx, char *, MAX_REFERRAL_COUNT); +	if (!alt_path) { +		return False; +	} +  	/* parse out the alternate paths */  	while((count<MAX_REFERRAL_COUNT) &&  	      ((alt_path[count] = strtok(NULL,",")) != NULL)) { @@ -266,19 +303,21 @@ static BOOL parse_msdfs_symlink(TALLOC_CTX *ctx,  	DEBUG(10,("parse_msdfs_symlink: count=%d\n", count));  	if (count) { -		reflist = *preflist = TALLOC_ZERO_ARRAY(ctx, struct referral, count); +		reflist = *preflist = TALLOC_ZERO_ARRAY(ctx, +				struct referral, count);  		if(reflist == NULL) { -			DEBUG(0,("parse_msdfs_symlink: talloc failed!\n")); +			TALLOC_FREE(alt_path);  			return False;  		}  	} else {  		reflist = *preflist = NULL;  	} -	 +  	for(i=0;i<count;i++) {  		char *p; -		/* Canonicalize link target. Replace all /'s in the path by a \ */ +		/* Canonicalize link target. +		 * Replace all /'s in the path by a \ */  		string_replace(alt_path[i], '/', '\\');  		/* Remove leading '\\'s */ @@ -287,66 +326,113 @@ static BOOL parse_msdfs_symlink(TALLOC_CTX *ctx,  			p++;  		} -		pstrcpy(reflist[i].alternate_path, "\\"); -		pstrcat(reflist[i].alternate_path, p); +		reflist[i].alternate_path = talloc_asprintf(ctx, +				"\\%s", +				p); +		if (!reflist[i].alternate_path) { +			return False; +		}  		reflist[i].proximity = 0;  		reflist[i].ttl = REFERRAL_TTL; -		DEBUG(10, ("parse_msdfs_symlink: Created alt path: %s\n", reflist[i].alternate_path)); +		DEBUG(10, ("parse_msdfs_symlink: Created alt path: %s\n", +					reflist[i].alternate_path));  		*refcount += 1;  	} +	TALLOC_FREE(alt_path);  	return True;  } -  +  /**********************************************************************   Returns true if the unix path is a valid msdfs symlink and also   returns the target string from inside the link.  **********************************************************************/ -BOOL is_msdfs_link(connection_struct *conn, +static BOOL is_msdfs_link_internal(TALLOC_CTX *ctx, +			connection_struct *conn,  			const char *path, -			pstring link_target, +			char **pp_link_target,  			SMB_STRUCT_STAT *sbufp)  {  	SMB_STRUCT_STAT st;  	int referral_len = 0; +	char link_target_buf[7]; +	size_t bufsize = 0; +	char *link_target = NULL; + +	if (pp_link_target) { +		bufsize = 1024; +		link_target = TALLOC_ARRAY(ctx, char, bufsize); +		if (!link_target) { +			return False; +		} +		*pp_link_target = link_target; +	} else { +		bufsize = sizeof(link_target_buf); +		link_target = link_target_buf; +	}  	if (sbufp == NULL) {  		sbufp = &st;  	}  	if (SMB_VFS_LSTAT(conn, path, sbufp) != 0) { -		DEBUG(5,("is_msdfs_link: %s does not exist.\n",path)); -		return False; +		DEBUG(5,("is_msdfs_link_read_target: %s does not exist.\n", +			path)); +		goto err;  	} -   +  	if (!S_ISLNK(sbufp->st_mode)) { -		DEBUG(5,("is_msdfs_link: %s is not a link.\n",path)); -		return False; +		DEBUG(5,("is_msdfs_link_read_target: %s is not a link.\n", +					path)); +		goto err;  	} -	/* open the link and read it */ -	referral_len = SMB_VFS_READLINK(conn, path, link_target, sizeof(pstring)-1); +	referral_len = SMB_VFS_READLINK(conn, path, link_target, bufsize - 1);  	if (referral_len == -1) { -		DEBUG(0,("is_msdfs_link: Error reading msdfs link %s: %s\n", +		DEBUG(0,("is_msdfs_link_read_target: Error reading " +			"msdfs link %s: %s\n",  			path, strerror(errno))); -		return False; +		goto err;  	}  	link_target[referral_len] = '\0'; -	DEBUG(5,("is_msdfs_link: %s -> %s\n",path, link_target)); +	DEBUG(5,("is_msdfs_link_internal: %s -> %s\n",path, +				link_target));  	if (!strnequal(link_target, "msdfs:", 6)) { -		return False; +		goto err;  	}  	return True; + +  err: + +	if (link_target != link_target_buf) { +		TALLOC_FREE(link_target); +	} +	return False; +} + +/********************************************************************** + Returns true if the unix path is a valid msdfs symlink. +**********************************************************************/ + +BOOL is_msdfs_link(connection_struct *conn, +		const char *path, +		SMB_STRUCT_STAT *sbufp) +{ +	return is_msdfs_link_internal(talloc_tos(), +					conn, +					path, +					NULL, +					sbufp);  }  /*****************************************************************   Used by other functions to decide if a dfs path is remote,   and to get the list of referred locations for that remote path. -  +   search_flag: For findfirsts, dfs links themselves are not   redirected, but paths beyond the links are. For normal smb calls,   even dfs links need to be redirected. @@ -358,25 +444,27 @@ BOOL is_msdfs_link(connection_struct *conn,   link redirect are in targetpath.  *****************************************************************/ -static NTSTATUS dfs_path_lookup(connection_struct *conn, -			const char *dfspath, /* Incoming complete dfs path */ -			const struct dfs_path *pdp, /* Parsed out server+share+extrapath. */ -			BOOL search_flag, /* Called from a findfirst ? */ -			int *consumedcntp, -			pstring targetpath) +static NTSTATUS dfs_path_lookup(TALLOC_CTX *ctx, +		connection_struct *conn, +		const char *dfspath, /* Incoming complete dfs path */ +		const struct dfs_path *pdp, /* Parsed out +					       server+share+extrapath. */ +		BOOL search_flag, /* Called from a findfirst ? */ +		int *consumedcntp, +		char **pp_targetpath)  {  	char *p = NULL;  	char *q = NULL;  	SMB_STRUCT_STAT sbuf;  	NTSTATUS status; -	pstring localpath_in;  	char *localpath = NULL; -	pstring canon_dfspath; /* Canonicalized dfs path. (only '/' components). */ +	char *canon_dfspath = NULL; /* Canonicalized dfs path. (only '/' +				  components). */  	DEBUG(10,("dfs_path_lookup: Conn path = %s reqpath = %s\n",  		conn->connectpath, pdp->reqpath)); -	/*  +	/*   	 * Note the unix path conversion here we're doing we can  	 * throw away. We're looking for a symlink for a dfs  	 * resolution, if we don't find it we'll do another @@ -388,8 +476,8 @@ static NTSTATUS dfs_path_lookup(connection_struct *conn,  	 * think this is needed. JRA.  	 */ -	pstrcpy(localpath_in, pdp->reqpath); -	status = unix_convert(conn, localpath_in, search_flag, &localpath, NULL, &sbuf); +	status = unix_convert(conn, pdp->reqpath, search_flag, &localpath, +			NULL, &sbuf);  	if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status,  					NT_STATUS_OBJECT_PATH_NOT_FOUND)) {  		return status; @@ -397,7 +485,7 @@ static NTSTATUS dfs_path_lookup(connection_struct *conn,  	/* Optimization - check if we can redirect the whole path. */ -	if (is_msdfs_link(conn, localpath, targetpath, NULL)) { +	if (is_msdfs_link_internal(ctx, conn, localpath, pp_targetpath, NULL)) {  		if (search_flag) {  			DEBUG(6,("dfs_path_lookup (FindFirst) No redirection "  				 "for dfs link %s.\n", dfspath)); @@ -405,7 +493,8 @@ static NTSTATUS dfs_path_lookup(connection_struct *conn,  		}  		DEBUG(6,("dfs_path_lookup: %s resolves to a " -			"valid dfs link %s.\n", dfspath, targetpath)); +			"valid dfs link %s.\n", dfspath, +			pp_targetpath ? *pp_targetpath : ""));  		if (consumedcntp) {  			*consumedcntp = strlen(dfspath); @@ -417,7 +506,10 @@ static NTSTATUS dfs_path_lookup(connection_struct *conn,  	 * so if a Windows path replace all '\\' characters with '/'.  	 * For a POSIX DFS path we know all separators are already '/'. */ -	pstrcpy(canon_dfspath, dfspath); +	canon_dfspath = talloc_strdup(ctx, dfspath); +	if (!canon_dfspath) { +		return NT_STATUS_NO_MEMORY; +	}  	if (!pdp->posix_path) {  		string_replace(canon_dfspath, '\\', '/');  	} @@ -432,7 +524,7 @@ static NTSTATUS dfs_path_lookup(connection_struct *conn,  	/*  	 * Redirect if any component in the path is a link. -	 * We do this by walking backwards through the  +	 * We do this by walking backwards through the  	 * local path, chopping off the last component  	 * in both the local path and the canonicalized  	 * DFS path. If we hit a DFS link then we're done. @@ -449,14 +541,17 @@ static NTSTATUS dfs_path_lookup(connection_struct *conn,  			*q = '\0';  		} -		if (is_msdfs_link(conn, localpath, targetpath, NULL)) { +		if (is_msdfs_link_internal(ctx, conn, +					localpath, pp_targetpath, NULL)) {  			DEBUG(4, ("dfs_path_lookup: Redirecting %s because "  				"parent %s is dfs link\n", dfspath, localpath));  			if (consumedcntp) {  				*consumedcntp = strlen(canon_dfspath);  				DEBUG(10, ("dfs_path_lookup: Path consumed: %s " -					"(%d)\n", canon_dfspath, *consumedcntp)); +					"(%d)\n", +					canon_dfspath, +					*consumedcntp));  			}  			return NT_STATUS_PATH_NOT_COVERED; @@ -478,7 +573,7 @@ static NTSTATUS dfs_path_lookup(connection_struct *conn,   Decides if a dfs pathname should be redirected or not.   If not, the pathname is converted to a tcon-relative local unix path - search_wcard_flag: this flag performs 2 functions bother related + search_wcard_flag: this flag performs 2 functions both related   to searches.  See resolve_dfs_path() and parse_dfs_path_XX()   for details. @@ -486,25 +581,36 @@ static NTSTATUS dfs_path_lookup(connection_struct *conn,   (mapped into a local path).   or NT_STATUS_NOT_COVERED meaning return a DFS redirect, or   any other NT_STATUS error which is a genuine error to be - returned to the client.  + returned to the client.  *****************************************************************/ -static NTSTATUS dfs_redirect( connection_struct *conn, -			pstring dfs_path, +static NTSTATUS dfs_redirect(TALLOC_CTX *ctx, +			connection_struct *conn, +			const char *path_in,  			BOOL search_wcard_flag, +			char **pp_path_out,  			BOOL *ppath_contains_wcard)  {  	NTSTATUS status; -	struct dfs_path dp; -	pstring targetpath; -	 -	status = parse_dfs_path(dfs_path, search_wcard_flag, &dp, ppath_contains_wcard); +	struct dfs_path *pdp = TALLOC_P(ctx, struct dfs_path); + +	if (!pdp) { +		return NT_STATUS_NO_MEMORY; +	} + +	status = parse_dfs_path(path_in, search_wcard_flag, pdp, +			ppath_contains_wcard);  	if (!NT_STATUS_IS_OK(status)) { +		TALLOC_FREE(pdp);  		return status;  	} -	if (dp.reqpath[0] == '\0') { -		pstrcpy(dfs_path, dp.reqpath); +	if (pdp->reqpath[0] == '\0') { +		TALLOC_FREE(pdp); +		*pp_path_out = talloc_strdup(ctx, ""); +		if (!*pp_path_out) { +			return NT_STATUS_NO_MEMORY; +		}  		DEBUG(5,("dfs_redirect: self-referral.\n"));  		return NT_STATUS_OK;  	} @@ -513,45 +619,63 @@ static NTSTATUS dfs_redirect( connection_struct *conn,  	   path and return OK */  	if (!lp_msdfs_root(SNUM(conn))) { -		pstrcpy(dfs_path, dp.reqpath); +		*pp_path_out = talloc_strdup(ctx, pdp->reqpath); +		TALLOC_FREE(pdp); +		if (!*pp_path_out) { +			return NT_STATUS_NO_MEMORY; +		}  		return NT_STATUS_OK;  	}  	/* If it looked like a local path (zero hostname/servicename) -	 * just treat as a tcon-relative path. */  +	 * just treat as a tcon-relative path. */ -	if (dp.hostname[0] == '\0' && dp.servicename[0] == '\0') {  -		pstrcpy(dfs_path, dp.reqpath); +	if (pdp->hostname[0] == '\0' && pdp->servicename[0] == '\0') { +		*pp_path_out = talloc_strdup(ctx, pdp->reqpath); +		TALLOC_FREE(pdp); +		if (!*pp_path_out) { +			return NT_STATUS_NO_MEMORY; +		}  		return NT_STATUS_OK;  	} -	if (!( strequal(dp.servicename, lp_servicename(SNUM(conn)))  -			|| (strequal(dp.servicename, HOMES_NAME)  -			&& strequal(lp_servicename(SNUM(conn)), get_current_username()) )) ) { +	if (!( strequal(pdp->servicename, lp_servicename(SNUM(conn))) +			|| (strequal(pdp->servicename, HOMES_NAME) +			&& strequal(lp_servicename(SNUM(conn)), +				get_current_username()) )) ) {  		/* The given sharename doesn't match this connection. */ +		TALLOC_FREE(pdp);  		return NT_STATUS_OBJECT_PATH_NOT_FOUND;  	} -	status = dfs_path_lookup(conn, dfs_path, &dp, -			search_wcard_flag, NULL, targetpath); +	status = dfs_path_lookup(ctx, conn, path_in, pdp, +			search_wcard_flag, NULL, NULL);  	if (!NT_STATUS_IS_OK(status)) {  		if (NT_STATUS_EQUAL(status, NT_STATUS_PATH_NOT_COVERED)) { -			DEBUG(3,("dfs_redirect: Redirecting %s\n", dfs_path)); +			DEBUG(3,("dfs_redirect: Redirecting %s\n", path_in));  		} else { -			DEBUG(10,("dfs_redirect: dfs_path_lookup failed for %s with %s\n", -				dfs_path, nt_errstr(status) )); +			DEBUG(10,("dfs_redirect: dfs_path_lookup " +				"failed for %s with %s\n", +				path_in, nt_errstr(status) ));  		}  		return status;  	} -	DEBUG(3,("dfs_redirect: Not redirecting %s.\n", dfs_path)); +	DEBUG(3,("dfs_redirect: Not redirecting %s.\n", path_in));  	/* Form non-dfs tcon-relative path */ -	pstrcpy(dfs_path, dp.reqpath); +	*pp_path_out = talloc_strdup(ctx, pdp->reqpath); +	TALLOC_FREE(pdp); +	if (!*pp_path_out) { +		return NT_STATUS_NO_MEMORY; +	} + +	DEBUG(3,("dfs_redirect: Path %s converted to non-dfs path %s\n", +				path_in, +				*pp_path_out)); -	DEBUG(3,("dfs_redirect: Path converted to non-dfs path %s\n", dfs_path));  	return NT_STATUS_OK;  } @@ -571,11 +695,13 @@ static NTSTATUS self_ref(TALLOC_CTX *ctx,  	jucn->referral_count = 1;  	if((ref = TALLOC_ZERO_P(ctx, struct referral)) == NULL) { -		DEBUG(0,("self_ref: talloc failed for referral\n"));  		return NT_STATUS_NO_MEMORY;  	} -	pstrcpy(ref->alternate_path,dfs_path); +	ref->alternate_path = talloc_strdup(ctx, dfs_path); +	if (!ref->alternate_path) { +		return NT_STATUS_NO_MEMORY; +	}  	ref->proximity = 0;  	ref->ttl = REFERRAL_TTL;  	jucn->referral_list = ref; @@ -596,57 +722,76 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx,  {  	struct connection_struct conns;  	struct connection_struct *conn = &conns; -	struct dfs_path dp; -	pstring conn_path; -	pstring targetpath; +	char *targetpath = NULL;  	int snum;  	NTSTATUS status = NT_STATUS_NOT_FOUND;  	BOOL dummy; +	struct dfs_path *pdp = TALLOC_P(ctx, struct dfs_path); -	ZERO_STRUCT(conns); +	if (!pdp) { +		return NT_STATUS_NO_MEMORY; +	} +	ZERO_STRUCT(conns);  	*self_referralp = False; -	status = parse_dfs_path(dfs_path, False, &dp, &dummy); +	status = parse_dfs_path(dfs_path, False, pdp, &dummy);  	if (!NT_STATUS_IS_OK(status)) {  		return status;  	}  	/* Verify hostname in path */ -	if (!is_myname_or_ipaddr(dp.hostname)) { +	if (!is_myname_or_ipaddr(pdp->hostname)) {  		DEBUG(3, ("get_referred_path: Invalid hostname %s in path %s\n", -			dp.hostname, dfs_path)); +			pdp->hostname, dfs_path)); +		TALLOC_FREE(pdp);  		return NT_STATUS_NOT_FOUND;  	} -	fstrcpy(jucn->service_name, dp.servicename); -	pstrcpy(jucn->volume_name, dp.reqpath); +	jucn->service_name = talloc_strdup(ctx, pdp->servicename); +	jucn->volume_name = talloc_strdup(ctx, pdp->reqpath); +	if (!jucn->service_name || !jucn->volume_name) { +		TALLOC_FREE(pdp); +		return NT_STATUS_NO_MEMORY; +	}  	/* Verify the share is a dfs root */  	snum = lp_servicenumber(jucn->service_name);  	if(snum < 0) { -		if ((snum = find_service(jucn->service_name)) < 0) { +		fstring service_name; +		fstrcpy(service_name, jucn->service_name); +		if ((snum = find_service(service_name)) < 0) {  			return NT_STATUS_NOT_FOUND;  		} +		TALLOC_FREE(jucn->service_name); +		jucn->service_name = talloc_strdup(ctx, service_name); +		if (!jucn->service_name) { +			TALLOC_FREE(pdp); +			return NT_STATUS_NO_MEMORY; +		}  	}  	if (!lp_msdfs_root(snum)) { -		DEBUG(3,("get_referred_path: |%s| in dfs path %s is not a dfs root.\n", -			 dp.servicename, dfs_path)); +		DEBUG(3,("get_referred_path: |%s| in dfs path %s is not " +			"a dfs root.\n", +			pdp->servicename, dfs_path)); +		TALLOC_FREE(pdp);  		return NT_STATUS_NOT_FOUND;  	}  	/*  	 * Self referrals are tested with a anonymous IPC connection and -	 * a GET_DFS_REFERRAL call to \\server\share. (which means dp.reqpath[0] points -	 * to an empty string). create_conn_struct cd's into the directory and will -	 * fail if it cannot (as the anonymous user). Cope with this. +	 * a GET_DFS_REFERRAL call to \\server\share. (which means +	 * dp.reqpath[0] points to an empty string). create_conn_struct cd's +	 * into the directory and will fail if it cannot (as the anonymous +	 * user). Cope with this.  	 */ -	if (dp.reqpath[0] == '\0') { +	if (pdp->reqpath[0] == '\0') {  		struct referral *ref;  		if (*lp_msdfs_proxy(snum) == '\0') { +			TALLOC_FREE(pdp);  			return self_ref(ctx,  					dfs_path,  					jucn, @@ -654,44 +799,58 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx,  					self_referralp);  		} -		/*  +		/*  		 * It's an msdfs proxy share. Redirect to   		 * the configured target share.   		 */  		jucn->referral_count = 1;  		if ((ref = TALLOC_ZERO_P(ctx, struct referral)) == NULL) { -			DEBUG(0, ("malloc failed for referral\n")); +			TALLOC_FREE(pdp);  			return NT_STATUS_NO_MEMORY;  		} -		pstrcpy(ref->alternate_path, lp_msdfs_proxy(snum)); -		if (dp.reqpath[0] != '\0') { -			pstrcat(ref->alternate_path, dp.reqpath); +		ref->alternate_path = talloc_strdup(ctx, lp_msdfs_proxy(snum)); +		if (!ref->alternate_path) { +			TALLOC_FREE(pdp); +			return NT_STATUS_NO_MEMORY; +		} + +		if (pdp->reqpath[0] != '\0') { +			ref->alternate_path = talloc_asprintf(ctx, +					"%s%s", +					ref->alternate_path, +					pdp->reqpath); +			if (!ref->alternate_path) { +				TALLOC_FREE(pdp); +				return NT_STATUS_NO_MEMORY; +			}  		}  		ref->proximity = 0;  		ref->ttl = REFERRAL_TTL;  		jucn->referral_list = ref;  		*consumedcntp = strlen(dfs_path); +		TALLOC_FREE(pdp);  		return NT_STATUS_OK;  	} -	pstrcpy(conn_path, lp_pathname(snum)); -	status = create_conn_struct(conn, snum, conn_path); +	status = create_conn_struct(conn, snum, lp_pathname(snum));  	if (!NT_STATUS_IS_OK(status)) { +		TALLOC_FREE(pdp);  		return status;  	}  	/* If this is a DFS path dfs_lookup should return  	 * NT_STATUS_PATH_NOT_COVERED. */ -	status = dfs_path_lookup(conn, dfs_path, &dp, -			False, consumedcntp, targetpath); +	status = dfs_path_lookup(ctx, conn, dfs_path, pdp, +			False, consumedcntp, &targetpath);  	if (!NT_STATUS_EQUAL(status, NT_STATUS_PATH_NOT_COVERED)) {  		DEBUG(3,("get_referred_path: No valid referrals for path %s\n",  			dfs_path));  		conn_free_internal(conn); +		TALLOC_FREE(pdp);  		return status;  	} @@ -702,22 +861,24 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx,  		DEBUG(3,("get_referred_path: failed to parse symlink "  			"target %s\n", targetpath ));  		conn_free_internal(conn); +		TALLOC_FREE(pdp);  		return NT_STATUS_NOT_FOUND;  	}  	conn_free_internal(conn); +	TALLOC_FREE(pdp);  	return NT_STATUS_OK;  }  static int setup_ver2_dfs_referral(const char *pathname, -				char **ppdata,  +				char **ppdata,  				struct junction_map *junction,  				int consumedcnt,  				BOOL self_referral)  {  	char* pdata = *ppdata; -	unsigned char uni_requestedpath[1024]; +	unsigned char uni_requestedpath[sizeof(pstring)];  	int uni_reqpathoffset1,uni_reqpathoffset2;  	int uni_curroffset;  	int requestedpathlen=0; @@ -727,30 +888,35 @@ static int setup_ver2_dfs_referral(const char *pathname,  	DEBUG(10,("Setting up version2 referral\nRequested path:\n")); -	requestedpathlen = rpcstr_push(uni_requestedpath, pathname, sizeof(pstring), -				       STR_TERMINATE); +	requestedpathlen = rpcstr_push(uni_requestedpath, +					pathname, sizeof(pstring), +					STR_TERMINATE);  	if (DEBUGLVL(10)) { -	    dump_data(0, uni_requestedpath,requestedpathlen); +		dump_data(0, uni_requestedpath,requestedpathlen);  	}  	DEBUG(10,("ref count = %u\n",junction->referral_count)); -	uni_reqpathoffset1 = REFERRAL_HEADER_SIZE +  +	uni_reqpathoffset1 = REFERRAL_HEADER_SIZE +  			VERSION2_REFERRAL_SIZE * junction->referral_count;  	uni_reqpathoffset2 = uni_reqpathoffset1 + requestedpathlen;  	uni_curroffset = uni_reqpathoffset2 + requestedpathlen; -	reply_size = REFERRAL_HEADER_SIZE + VERSION2_REFERRAL_SIZE*junction->referral_count + -					2 * requestedpathlen; +	reply_size = REFERRAL_HEADER_SIZE + +			VERSION2_REFERRAL_SIZE*junction->referral_count + +			2 * requestedpathlen;  	DEBUG(10,("reply_size: %u\n",reply_size));  	/* add up the unicode lengths of all the referral paths */  	for(i=0;i<junction->referral_count;i++) { -		DEBUG(10,("referral %u : %s\n",i,junction->referral_list[i].alternate_path)); -		reply_size += (strlen(junction->referral_list[i].alternate_path)+1)*2; +		DEBUG(10,("referral %u : %s\n", +			i, +			junction->referral_list[i].alternate_path)); +		reply_size += +			(strlen(junction->referral_list[i].alternate_path)+1)*2;  	}  	DEBUG(10,("reply_size = %u\n",reply_size)); @@ -770,9 +936,10 @@ static int setup_ver2_dfs_referral(const char *pathname,  	/* create the header */  	SSVAL(pdata,0,consumedcnt * 2); /* path consumed */ -	SSVAL(pdata,2,junction->referral_count); /* number of referral in this pkt */ +	/* number of referral in this pkt */ +	SSVAL(pdata,2,junction->referral_count);  	if(self_referral) { -		SIVAL(pdata,4,DFSREF_REFERRAL_SERVER | DFSREF_STORAGE_SERVER);  +		SIVAL(pdata,4,DFSREF_REFERRAL_SERVER | DFSREF_STORAGE_SERVER);  	} else {  		SIVAL(pdata,4,DFSREF_STORAGE_SERVER);  	} @@ -790,7 +957,9 @@ static int setup_ver2_dfs_referral(const char *pathname,  		} else {  			SSVAL(pdata,offset+4,0);  		} -		SSVAL(pdata,offset+6,0); /* ref_flags :use path_consumed bytes? */ + +		/* ref_flags :use path_consumed bytes? */ +		SSVAL(pdata,offset+6,0);  		SIVAL(pdata,offset+8,ref->proximity);  		SIVAL(pdata,offset+12,ref->ttl); @@ -811,41 +980,47 @@ static int setup_ver2_dfs_referral(const char *pathname,  }  static int setup_ver3_dfs_referral(const char *pathname, -				char **ppdata,  +				char **ppdata,  				struct junction_map *junction,  				int consumedcnt,  				BOOL self_referral)  { -	char* pdata = *ppdata; +	char *pdata = *ppdata; -	unsigned char uni_reqpath[1024]; +	unsigned char uni_reqpath[sizeof(pstring)];  	int uni_reqpathoffset1, uni_reqpathoffset2;  	int uni_curroffset;  	int reply_size = 0;  	int reqpathlen = 0;  	int offset,i=0; -	 +  	DEBUG(10,("setting up version3 referral\n")); -	reqpathlen = rpcstr_push(uni_reqpath, pathname, sizeof(pstring), STR_TERMINATE); -	 +	reqpathlen = rpcstr_push(uni_reqpath, pathname, +			sizeof(pstring), STR_TERMINATE); +  	if (DEBUGLVL(10)) { -	    dump_data(0, uni_reqpath,reqpathlen); +		dump_data(0, uni_reqpath,reqpathlen);  	} -	uni_reqpathoffset1 = REFERRAL_HEADER_SIZE + VERSION3_REFERRAL_SIZE * junction->referral_count; +	uni_reqpathoffset1 = REFERRAL_HEADER_SIZE + +			VERSION3_REFERRAL_SIZE * junction->referral_count;  	uni_reqpathoffset2 = uni_reqpathoffset1 + reqpathlen;  	reply_size = uni_curroffset = uni_reqpathoffset2 + reqpathlen;  	for(i=0;i<junction->referral_count;i++) { -		DEBUG(10,("referral %u : %s\n",i,junction->referral_list[i].alternate_path)); -		reply_size += (strlen(junction->referral_list[i].alternate_path)+1)*2; +		DEBUG(10,("referral %u : %s\n", +			i, +			junction->referral_list[i].alternate_path)); +		reply_size += +			(strlen(junction->referral_list[i].alternate_path)+1)*2;  	}  	pdata = (char *)SMB_REALLOC(pdata,reply_size);  	if(pdata == NULL) { -		DEBUG(0,("version3 referral setup: malloc failed for Realloc!\n")); +		DEBUG(0,("version3 referral setup:" +			"malloc failed for Realloc!\n"));  		return -1;  	}  	*ppdata = pdata; @@ -854,15 +1029,15 @@ static int setup_ver3_dfs_referral(const char *pathname,  	SSVAL(pdata,0,consumedcnt * 2); /* path consumed */  	SSVAL(pdata,2,junction->referral_count); /* number of referral */  	if(self_referral) { -		SIVAL(pdata,4,DFSREF_REFERRAL_SERVER | DFSREF_STORAGE_SERVER);  +		SIVAL(pdata,4,DFSREF_REFERRAL_SERVER | DFSREF_STORAGE_SERVER);  	} else {  		SIVAL(pdata,4,DFSREF_STORAGE_SERVER);  	} -	 +  	/* copy in the reqpaths */  	memcpy(pdata+uni_reqpathoffset1,uni_reqpath,reqpathlen);  	memcpy(pdata+uni_reqpathoffset2,uni_reqpath,reqpathlen); -	 +  	offset = 8;  	for(i=0;i<junction->referral_count;i++) {  		struct referral* ref = &(junction->referral_list[i]); @@ -876,14 +1051,16 @@ static int setup_ver3_dfs_referral(const char *pathname,  			SSVAL(pdata,offset+4,0);  		} -		SSVAL(pdata,offset+6,0); /* ref_flags :use path_consumed bytes? */ +		/* ref_flags :use path_consumed bytes? */ +		SSVAL(pdata,offset+6,0);  		SIVAL(pdata,offset+8,ref->ttl); -	     +  		SSVAL(pdata,offset+12,uni_reqpathoffset1-offset);  		SSVAL(pdata,offset+14,uni_reqpathoffset2-offset);  		/* copy referred path into current offset */  		unilen = rpcstr_push(pdata+uni_curroffset,ref->alternate_path, -				     sizeof(pstring), STR_UNICODE | STR_TERMINATE); +				     sizeof(pstring), +				     STR_UNICODE | STR_TERMINATE);  		SSVAL(pdata,offset+16,uni_curroffset-offset);  		/* copy 0x10 bytes of 00's in the ServiceSite GUID */  		memset(pdata+offset+18,'\0',16); @@ -906,12 +1083,12 @@ int setup_dfs_referral(connection_struct *orig_conn,  			int max_referral_level,  			char **ppdata, NTSTATUS *pstatus)  { -	struct junction_map junction; +	struct junction_map *junction = NULL;  	int consumedcnt = 0;  	BOOL self_referral = False;  	int reply_size = 0;  	char *pathnamep = NULL; -	pstring local_dfs_path; +	char *local_dfs_path = NULL;  	TALLOC_CTX *ctx;  	if (!(ctx=talloc_init("setup_dfs_referral"))) { @@ -919,8 +1096,6 @@ int setup_dfs_referral(connection_struct *orig_conn,  		return -1;  	} -	ZERO_STRUCT(junction); -  	/* get the junction entry */  	if (!dfs_path) {  		talloc_destroy(ctx); @@ -928,34 +1103,51 @@ int setup_dfs_referral(connection_struct *orig_conn,  		return -1;  	} -	/*  +	/*  	 * Trim pathname sent by client so it begins with only one backslash.  	 * Two backslashes confuse some dfs clients  	 */ -	pstrcpy(local_dfs_path, dfs_path); +	local_dfs_path = talloc_strdup(ctx,dfs_path); +	if (!local_dfs_path) { +		*pstatus = NT_STATUS_NO_MEMORY; +		talloc_destroy(ctx); +		return -1; +	}  	pathnamep = local_dfs_path; -	while (IS_DIRECTORY_SEP(pathnamep[0]) && IS_DIRECTORY_SEP(pathnamep[1])) { +	while (IS_DIRECTORY_SEP(pathnamep[0]) && +			IS_DIRECTORY_SEP(pathnamep[1])) {  		pathnamep++;  	} +	junction = TALLOC_ZERO_P(ctx, struct junction_map); +	if (!junction) { +		*pstatus = NT_STATUS_NO_MEMORY; +		talloc_destroy(ctx); +		return -1; +	} +  	/* The following call can change cwd. */ -	*pstatus = get_referred_path(ctx, pathnamep, &junction, &consumedcnt, &self_referral); +	*pstatus = get_referred_path(ctx, pathnamep, junction, +			&consumedcnt, &self_referral);  	if (!NT_STATUS_IS_OK(*pstatus)) {  		vfs_ChDir(orig_conn,orig_conn->connectpath);  		talloc_destroy(ctx);  		return -1;  	}  	vfs_ChDir(orig_conn,orig_conn->connectpath); -	 +  	if (!self_referral) {  		pathnamep[consumedcnt] = '\0';  		if( DEBUGLVL( 3 ) ) {  			int i=0; -			dbgtext("setup_dfs_referral: Path %s to alternate path(s):",pathnamep); -			for(i=0;i<junction.referral_count;i++) -				dbgtext(" %s",junction.referral_list[i].alternate_path); +			dbgtext("setup_dfs_referral: Path %s to " +				"alternate path(s):", +				pathnamep); +			for(i=0;i<junction->referral_count;i++) +				dbgtext(" %s", +				junction->referral_list[i].alternate_path);  			dbgtext(".\n");  		}  	} @@ -972,20 +1164,23 @@ int setup_dfs_referral(connection_struct *orig_conn,  	switch(max_referral_level) {  	case 2: -		reply_size = setup_ver2_dfs_referral(pathnamep, ppdata, &junction,  -						     consumedcnt, self_referral); +		reply_size = setup_ver2_dfs_referral(pathnamep, +					ppdata, junction, +					consumedcnt, self_referral);  		break;  	case 3: -		reply_size = setup_ver3_dfs_referral(pathnamep, ppdata, &junction,  -						     consumedcnt, self_referral); +		reply_size = setup_ver3_dfs_referral(pathnamep, ppdata, +					junction, consumedcnt, self_referral);  		break;  	default: -		DEBUG(0,("setup_dfs_referral: Invalid dfs referral version: %d\n", max_referral_level)); +		DEBUG(0,("setup_dfs_referral: Invalid dfs referral " +			"version: %d\n", +			max_referral_level));  		talloc_destroy(ctx);  		*pstatus = NT_STATUS_INVALID_LEVEL;  		return -1;  	} -       +  	if (DEBUGLVL(10)) {  		DEBUGADD(0,("DFS Referral pdata:\n"));  		dump_data(0,(uint8 *)*ppdata,reply_size); @@ -1004,73 +1199,87 @@ int setup_dfs_referral(connection_struct *orig_conn,   Creates a junction structure from a DFS pathname  **********************************************************************/ -BOOL create_junction(const char *dfs_path, struct junction_map *jucn) +BOOL create_junction(TALLOC_CTX *ctx, +		const char *dfs_path, +		struct junction_map *jucn)  {  	int snum;  	BOOL dummy; -	struct dfs_path dp; -  -	NTSTATUS status = parse_dfs_path(dfs_path, False, &dp, &dummy); +	struct dfs_path *pdp = TALLOC_P(ctx,struct dfs_path); +	NTSTATUS status; +	if (!pdp) { +		return False; +	} +	status = parse_dfs_path(dfs_path, False, pdp, &dummy);  	if (!NT_STATUS_IS_OK(status)) {  		return False;  	}  	/* check if path is dfs : validate first token */ -	if (!is_myname_or_ipaddr(dp.hostname)) { -		DEBUG(4,("create_junction: Invalid hostname %s in dfs path %s\n", -			dp.hostname, dfs_path)); +	if (!is_myname_or_ipaddr(pdp->hostname)) { +		DEBUG(4,("create_junction: Invalid hostname %s " +			"in dfs path %s\n", +			pdp->hostname, dfs_path)); +		TALLOC_FREE(pdp);  		return False;  	}  	/* Check for a non-DFS share */ -	snum = lp_servicenumber(dp.servicename); +	snum = lp_servicenumber(pdp->servicename);  	if(snum < 0 || !lp_msdfs_root(snum)) {  		DEBUG(4,("create_junction: %s is not an msdfs root.\n", -			dp.servicename)); +			pdp->servicename)); +		TALLOC_FREE(pdp);  		return False;  	} -	fstrcpy(jucn->service_name,dp.servicename); -	pstrcpy(jucn->volume_name,dp.reqpath); -	pstrcpy(jucn->comment, lp_comment(snum)); +	jucn->service_name = talloc_strdup(ctx, pdp->servicename); +	jucn->volume_name = talloc_strdup(ctx, pdp->reqpath); +	jucn->comment = talloc_strdup(ctx, lp_comment(snum)); + +	TALLOC_FREE(pdp); +	if (!jucn->service_name || !jucn->volume_name || ! jucn->comment) { +		return False; +	}  	return True;  }  /********************************************************************** - Forms a valid Unix pathname from the junction  + Forms a valid Unix pathname from the junction   **********************************************************************/ -static BOOL junction_to_local_path(struct junction_map *jucn, -				char *path, -				int max_pathlen, +static BOOL junction_to_local_path(const struct junction_map *jucn, +				char **pp_path_out,  				connection_struct *conn_out)  {  	int snum; -	pstring conn_path;  	snum = lp_servicenumber(jucn->service_name);  	if(snum < 0) {  		return False;  	} - -	safe_strcpy(path, lp_pathname(snum), max_pathlen-1); -	safe_strcat(path, "/", max_pathlen-1); -	safe_strcat(path, jucn->volume_name, max_pathlen-1); - -	pstrcpy(conn_path, lp_pathname(snum)); -	if (!NT_STATUS_IS_OK(create_conn_struct(conn_out, snum, conn_path))) { +	if (!NT_STATUS_IS_OK(create_conn_struct(conn_out, snum, +					lp_pathname(snum)))) {  		return False;  	} +	*pp_path_out = talloc_asprintf(conn_out->mem_ctx, +			"%s/%s", +			lp_pathname(snum), +			jucn->volume_name); +	if (!*pp_path_out) { +		return False; +	}  	return True;  } -BOOL create_msdfs_link(struct junction_map *jucn, BOOL exists) +BOOL create_msdfs_link(const struct junction_map *jucn, +		BOOL exists)  { -	pstring path; -	pstring msdfs_link; +	char *path = NULL; +	char *msdfs_link = NULL;  	connection_struct conns;   	connection_struct *conn = &conns;  	int i=0; @@ -1079,15 +1288,19 @@ BOOL create_msdfs_link(struct junction_map *jucn, BOOL exists)  	ZERO_STRUCT(conns); -	if(!junction_to_local_path(jucn, path, sizeof(path), conn)) { +	if(!junction_to_local_path(jucn, &path, conn)) {  		return False;  	} -   +  	/* Form the msdfs_link contents */ -	pstrcpy(msdfs_link, "msdfs:"); +	msdfs_link = talloc_strdup(conn->mem_ctx, "msdfs:"); +	if (!msdfs_link) { +		goto out; +	}  	for(i=0; i<jucn->referral_count; i++) { -		char* refpath = jucn->referral_list[i].alternate_path; -       +		char *old_msdfs_link = msdfs_link; +		char *refpath = jucn->referral_list[i].alternate_path; +  		/* Alternate paths always use Windows separators. */  		trim_char(refpath, '\\', '\\');  		if(*refpath == '\0') { @@ -1097,10 +1310,21 @@ BOOL create_msdfs_link(struct junction_map *jucn, BOOL exists)  			continue;  		}  		if (i > 0 && insert_comma) { -			pstrcat(msdfs_link, ","); +			msdfs_link = talloc_asprintf(conn->mem_ctx, +					"%s,%s", +					old_msdfs_link, +					refpath); +		} else { +			msdfs_link = talloc_asprintf(conn->mem_ctx, +					"%s%s", +					old_msdfs_link, +					refpath);  		} -		pstrcat(msdfs_link, refpath); +		if (!msdfs_link) { +			goto out; +		} +		TALLOC_FREE(old_msdfs_link);  		if (!insert_comma) {  			insert_comma = True;  		} @@ -1116,12 +1340,12 @@ BOOL create_msdfs_link(struct junction_map *jucn, BOOL exists)  	}  	if(SMB_VFS_SYMLINK(conn, msdfs_link, path) < 0) { -		DEBUG(1,("create_msdfs_link: symlink failed %s -> %s\nError: %s\n",  -				path, msdfs_link, strerror(errno))); +		DEBUG(1,("create_msdfs_link: symlink failed " +			"%s -> %s\nError: %s\n",  +			path, msdfs_link, strerror(errno)));  		goto out;  	} -	 -	 +  	ret = True;  out: @@ -1130,47 +1354,105 @@ out:  	return ret;  } -BOOL remove_msdfs_link(struct junction_map *jucn) +BOOL remove_msdfs_link(const struct junction_map *jucn)  { -	pstring path; +	char *path = NULL;  	connection_struct conns;   	connection_struct *conn = &conns;  	BOOL ret = False;  	ZERO_STRUCT(conns); -	if( junction_to_local_path(jucn, path, sizeof(path), conn) ) { +	if( junction_to_local_path(jucn, &path, conn) ) {  		if( SMB_VFS_UNLINK(conn, path) == 0 ) {  			ret = True;  		} -		talloc_destroy( conn->mem_ctx );  	}  	conn_free_internal(conn);  	return ret;  } +/********************************************************************* + Return the number of DFS links at the root of this share. +*********************************************************************/ + +static int count_dfs_links(TALLOC_CTX *ctx, int snum) +{ +	size_t cnt = 0; +	SMB_STRUCT_DIR *dirp = NULL; +	char *dname = NULL; +	const char *connect_path = lp_pathname(snum); +	const char *msdfs_proxy = lp_msdfs_proxy(snum); +	connection_struct conn; + +	ZERO_STRUCT(conn); + +	if(*connect_path == '\0') { +		return 0; +	} + +	/* +	 * Fake up a connection struct for the VFS layer. +	 */ + +	if (!NT_STATUS_IS_OK(create_conn_struct(&conn, snum, connect_path))) { +		return 0; +	} + +	/* Count a link for the msdfs root - convention */ +	cnt = 1; + +	/* No more links if this is an msdfs proxy. */ +	if (*msdfs_proxy != '\0') { +		goto out; +	} + +	/* Now enumerate all dfs links */ +	dirp = SMB_VFS_OPENDIR(&conn, ".", NULL, 0); +	if(!dirp) { +		goto out; +	} + +	while ((dname = vfs_readdirname(&conn, dirp)) != NULL) { +		if (is_msdfs_link(&conn, +				dname, +				NULL)) { +			cnt++; +		} +	} + +	SMB_VFS_CLOSEDIR(&conn,dirp); + +out: + +	conn_free_internal(&conn); +	return cnt; +} + +/********************************************************************* +*********************************************************************/ +  static int form_junctions(TALLOC_CTX *ctx,  				int snum,  				struct junction_map *jucn, -				int jn_remain) +				size_t jn_remain)  { -	int cnt = 0; -	SMB_STRUCT_DIR *dirp; -	char *dname; -	pstring connect_path; +	size_t cnt = 0; +	SMB_STRUCT_DIR *dirp = NULL; +	char *dname = NULL; +	const char *connect_path = lp_pathname(snum);  	char *service_name = lp_servicename(snum); +	const char *msdfs_proxy = lp_msdfs_proxy(snum);  	connection_struct conn;  	struct referral *ref = NULL; -  +  	ZERO_STRUCT(conn); -	if (jn_remain <= 0) { +	if (jn_remain == 0) {  		return 0;  	} -	pstrcpy(connect_path,lp_pathname(snum)); -  	if(*connect_path == '\0') {  		return 0;  	} @@ -1183,33 +1465,44 @@ static int form_junctions(TALLOC_CTX *ctx,  		return 0;  	} -	/* form a junction for the msdfs root - convention  +	/* form a junction for the msdfs root - convention  	   DO NOT REMOVE THIS: NT clients will not work with us  	   if this is not present -	*/  -	fstrcpy(jucn[cnt].service_name, service_name); -	jucn[cnt].volume_name[0] = '\0'; +	*/ +	jucn[cnt].service_name = talloc_strdup(ctx,service_name); +	jucn[cnt].volume_name = talloc_strdup(ctx, ""); +	if (!jucn[cnt].service_name || jucn[cnt].volume_name) { +		goto out; +	}  	jucn[cnt].referral_count = 1;  	ref = jucn[cnt].referral_list = TALLOC_ZERO_P(ctx, struct referral);  	if (jucn[cnt].referral_list == NULL) { -		DEBUG(0, ("talloc failed!\n"));  		goto out;  	}  	ref->proximity = 0;  	ref->ttl = REFERRAL_TTL; -	if (*lp_msdfs_proxy(snum) != '\0') { -		pstrcpy(ref->alternate_path, lp_msdfs_proxy(snum)); -		cnt++; -		goto out; -	} - -	pstr_sprintf(ref->alternate_path, "\\\\%s\\%s", +	if (*msdfs_proxy != '\0') { +		ref->alternate_path = talloc_strdup(ctx, +						msdfs_proxy); +	} else { +		ref->alternate_path = talloc_asprintf(ctx, +			"\\\\%s\\%s",  			get_local_machine_name(),  			service_name); +	} + +	if (!ref->alternate_path) { +		goto out; +	}  	cnt++; +	/* Don't enumerate if we're an msdfs proxy. */ +	if (*msdfs_proxy != '\0') { +		goto out; +	} +  	/* Now enumerate all dfs links */  	dirp = SMB_VFS_OPENDIR(&conn, ".", NULL, 0);  	if(!dirp) { @@ -1217,41 +1510,55 @@ static int form_junctions(TALLOC_CTX *ctx,  	}  	while ((dname = vfs_readdirname(&conn, dirp)) != NULL) { -		pstring link_target; +		char *link_target = NULL;  		if (cnt >= jn_remain) {  			SMB_VFS_CLOSEDIR(&conn,dirp); -			DEBUG(2, ("ran out of MSDFS junction slots")); +			DEBUG(2, ("form_junctions: ran out of MSDFS " +				"junction slots"));  			goto out;  		} -		if (is_msdfs_link(&conn, dname, link_target, NULL)) { +		if (is_msdfs_link_internal(ctx, +					&conn, +					dname, &link_target, +					NULL)) {  			if (parse_msdfs_symlink(ctx,  					link_target,  					&jucn[cnt].referral_list,  					&jucn[cnt].referral_count)) { -				fstrcpy(jucn[cnt].service_name, service_name); -				pstrcpy(jucn[cnt].volume_name, dname); +				jucn[cnt].service_name = talloc_strdup(ctx, +								service_name); +				jucn[cnt].volume_name = talloc_strdup(ctx, +								dname); +				if (!jucn[cnt].service_name || +						!jucn[cnt].volume_name) { +					goto out; +				}  				cnt++;  			}  		}  	} -	 -	SMB_VFS_CLOSEDIR(&conn,dirp);  out: +	if (dirp) { +		SMB_VFS_CLOSEDIR(&conn,dirp); +	} +  	conn_free_internal(&conn);  	return cnt;  } -int enum_msdfs_links(TALLOC_CTX *ctx, struct junction_map *jucn, int jn_max) +struct junction_map *enum_msdfs_links(TALLOC_CTX *ctx, size_t *p_num_jn)  { +	struct junction_map *jn = NULL;  	int i=0; +	size_t jn_count;  	int sharecount = 0; -	int jn_count = 0; +	*p_num_jn = 0;  	if(!lp_host_msdfs()) { -		return 0; +		return NULL;  	}  	/* Ensure all the usershares are loaded. */ @@ -1260,24 +1567,57 @@ int enum_msdfs_links(TALLOC_CTX *ctx, struct junction_map *jucn, int jn_max)  	sharecount = load_usershare_shares();  	unbecome_root(); -	for(i=0;i < sharecount && (jn_max - jn_count) > 0;i++) { +	for(i=0;i < sharecount;i++) {  		if(lp_msdfs_root(i)) { -			jn_count += form_junctions(ctx, i,jucn,jn_max - jn_count); +			jn_count += count_dfs_links(ctx, i);  		}  	} -	return jn_count; +	if (jn_count == 0) { +		return NULL; +	} +	jn = TALLOC_ARRAY(ctx,  struct junction_map, jn_count); +	if (!jn) { +		return NULL; +	} +	for(i=0; i < sharecount; i++) { +		if (*p_num_jn >= jn_count) { +			break; +		} +		if(lp_msdfs_root(i)) { +			*p_num_jn += form_junctions(ctx, i, +					&jn[*p_num_jn], +					jn_count - *p_num_jn); +		} +	} +	return jn;  }  /******************************************************************************   Core function to resolve a dfs pathname.  ******************************************************************************/ -NTSTATUS resolve_dfspath(connection_struct *conn, BOOL dfs_pathnames, pstring name) +NTSTATUS resolve_dfspath(TALLOC_CTX *ctx, +			connection_struct *conn, +			BOOL dfs_pathnames, +			const char *name_in, +			char **pp_name_out)  {  	NTSTATUS status = NT_STATUS_OK;  	BOOL dummy;  	if (dfs_pathnames) { -		status = dfs_redirect(conn, name, False, &dummy); +		status = dfs_redirect(ctx, +					conn, +					name_in, +					False, +					pp_name_out, +					&dummy); +	} else { +		/* +		 * Cheat and just return a copy of the in ptr. +		 * Once srvstr_get_path() uses talloc it'll +		 * be a talloced ptr anyway. +		 */ +		*pp_name_out = CONST_DISCARD(char *,name_in);  	}  	return status;  } @@ -1289,11 +1629,28 @@ NTSTATUS resolve_dfspath(connection_struct *conn, BOOL dfs_pathnames, pstring na   we're allowing wildcards and when we're not. JRA.  ******************************************************************************/ -NTSTATUS resolve_dfspath_wcard(connection_struct *conn, BOOL dfs_pathnames, pstring name, BOOL *ppath_contains_wcard) +NTSTATUS resolve_dfspath_wcard(TALLOC_CTX *ctx, +				connection_struct *conn, +				BOOL dfs_pathnames, +				const char *name_in, +				char **pp_name_out, +				BOOL *ppath_contains_wcard)  {  	NTSTATUS status = NT_STATUS_OK;  	if (dfs_pathnames) { -		status = dfs_redirect(conn, name, True, ppath_contains_wcard); +		status = dfs_redirect(ctx, +					conn, +					name_in, +					True, +					pp_name_out, +					ppath_contains_wcard); +	} else { +		/* +		 * Cheat and just return a copy of the in ptr. +		 * Once srvstr_get_path() uses talloc it'll +		 * be a talloced ptr anyway. +		 */ +		*pp_name_out = CONST_DISCARD(char *,name_in);  	}  	return status;  } diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 735c147b8d..114050ae16 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -514,6 +514,7 @@ void reply_ntcreate_and_X(connection_struct *conn,  	BOOL extended_oplock_granted = False;  	NTSTATUS status;  	struct case_semantics_state *case_state = NULL; +	TALLOC_CTX *ctx = talloc_tos();  	START_PROFILE(SMBntcreateX); @@ -682,12 +683,15 @@ void reply_ntcreate_and_X(connection_struct *conn,  			return;  		}  	} -	 +  	/* -	 * Now contruct the smb_open_mode value from the filename,  +	 * 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_in); +	status = resolve_dfspath(ctx, conn, +				req->flags2 & FLAGS2_DFS_PATHNAMES, +				fname_in, +				&fname);  	if (!NT_STATUS_IS_OK(status)) {  		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {  			reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, @@ -718,7 +722,7 @@ void reply_ntcreate_and_X(connection_struct *conn,  		file_attributes &= ~FILE_FLAG_POSIX_SEMANTICS;  	} -	status = unix_convert(conn, fname_in, False, &fname, NULL, &sbuf); +	status = unix_convert(conn, fname, False, &fname, NULL, &sbuf);  	if (!NT_STATUS_IS_OK(status)) {  		TALLOC_FREE(case_state);  		reply_nterror(req, status); @@ -1242,11 +1246,11 @@ static void call_nt_transact_create(connection_struct *conn,  	struct timespec a_timespec;  	struct timespec m_timespec;  	struct ea_list *ea_list = NULL; -	TALLOC_CTX *ctx = NULL;  	char *pdata = NULL;  	NTSTATUS status;  	size_t param_len;  	struct case_semantics_state *case_state = NULL; +	TALLOC_CTX *ctx = talloc_tos();  	DEBUG(5,("call_nt_transact_create\n")); @@ -1424,8 +1428,10 @@ static void call_nt_transact_create(connection_struct *conn,  		file_attributes &= ~FILE_FLAG_POSIX_SEMANTICS;  	} -	status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, -				 fname_in); +	status = resolve_dfspath(ctx, conn, +				req->flags2 & FLAGS2_DFS_PATHNAMES, +				fname_in, +				&fname);  	if (!NT_STATUS_IS_OK(status)) {  		TALLOC_FREE(case_state);  		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { @@ -1437,7 +1443,7 @@ static void call_nt_transact_create(connection_struct *conn,  		return;  	} -	status = unix_convert(conn, fname_in, False, &fname, NULL, &sbuf); +	status = unix_convert(conn, fname, False, &fname, NULL, &sbuf);  	if (!NT_STATUS_IS_OK(status)) {  		TALLOC_FREE(case_state);  		reply_nterror(req, status); @@ -1594,7 +1600,6 @@ static void call_nt_transact_create(connection_struct *conn,  		status = set_sd( fsp, data, sd_len, ALL_SECURITY_INFORMATION);  		if (!NT_STATUS_IS_OK(status)) { -			talloc_destroy(ctx);  			close_file(fsp,ERROR_CLOSE);  			TALLOC_FREE(case_state);  			reply_nterror(req, status); @@ -1918,14 +1923,17 @@ static NTSTATUS copy_internals(connection_struct *conn,  void reply_ntrename(connection_struct *conn, struct smb_request *req)  { -	pstring oldname; -	pstring newname; +	pstring oldname_in; +	pstring newname_in; +	char *oldname = NULL; +	char *newname = NULL;  	char *p;  	NTSTATUS status;  	BOOL src_has_wcard = False;  	BOOL dest_has_wcard = False;  	uint32 attrs;  	uint16 rename_type; +	TALLOC_CTX *ctx = talloc_tos();  	START_PROFILE(SMBntrename); @@ -1939,8 +1947,8 @@ void reply_ntrename(connection_struct *conn, struct smb_request *req)  	rename_type = SVAL(req->inbuf,smb_vwv1);  	p = smb_buf(req->inbuf) + 1; -	p += srvstr_get_path_wcard((char *)req->inbuf, req->flags2, oldname, p, -				   sizeof(oldname), 0, STR_TERMINATE, &status, +	p += srvstr_get_path_wcard((char *)req->inbuf, req->flags2, oldname_in, p, +				   sizeof(oldname_in), 0, STR_TERMINATE, &status,  				   &src_has_wcard);  	if (!NT_STATUS_IS_OK(status)) {  		reply_nterror(req, status); @@ -1948,31 +1956,33 @@ void reply_ntrename(connection_struct *conn, struct smb_request *req)  		return;  	} -	if( is_ntfs_stream_name(oldname)) { +	if( is_ntfs_stream_name(oldname_in)) {  		/* Can't rename a stream. */  		reply_nterror(req, NT_STATUS_ACCESS_DENIED);  		END_PROFILE(SMBntrename);  		return;  	} -	if (ms_has_wild(oldname)) { +	if (ms_has_wild(oldname_in)) {  		reply_nterror(req, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);  		END_PROFILE(SMBntrename);  		return;  	}  	p++; -	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_wcard);  	if (!NT_STATUS_IS_OK(status)) {  		reply_nterror(req, status);  		END_PROFILE(SMBntrename);  		return;  	} -	 -	status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, -				 oldname); + +	status = resolve_dfspath(ctx, conn, +				req->flags2 & FLAGS2_DFS_PATHNAMES, +				oldname_in, +				&oldname);  	if (!NT_STATUS_IS_OK(status)) {  		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {  			reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, @@ -1985,8 +1995,10 @@ void reply_ntrename(connection_struct *conn, struct smb_request *req)  		return;  	} -	status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, -				 newname); +	status = resolve_dfspath(ctx, conn, +				req->flags2 & FLAGS2_DFS_PATHNAMES, +				newname_in, +				&newname);  	if (!NT_STATUS_IS_OK(status)) {  		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {  			reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, @@ -2000,7 +2012,7 @@ void reply_ntrename(connection_struct *conn, struct smb_request *req)  	}  	DEBUG(3,("reply_ntrename : %s -> %s\n",oldname,newname)); -	 +  	switch(rename_type) {  		case RENAME_FLAG_RENAME:  			status = rename_internals(conn, req, oldname, newname, diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index e3c3e8dff0..672c683309 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -452,6 +452,7 @@ void reply_tcon(connection_struct *conn, struct smb_request *req)  	NTSTATUS nt_status;  	char *p;  	DATA_BLOB password_blob; +	TALLOC_CTX *ctx = talloc_tos();  	START_PROFILE(SMBtcon); @@ -462,12 +463,12 @@ void reply_tcon(connection_struct *conn, struct smb_request *req)  	}  	p = smb_buf(req->inbuf)+1; -	p += srvstr_pull_buf_talloc(req, req->inbuf, req->flags2, +	p += srvstr_pull_buf_talloc(ctx, req->inbuf, req->flags2,  				    &service_buf, p, STR_TERMINATE) + 1; -	pwlen = srvstr_pull_buf_talloc(req, req->inbuf, req->flags2, +	pwlen = srvstr_pull_buf_talloc(ctx, req->inbuf, req->flags2,  				       &password, p, STR_TERMINATE) + 1;  	p += pwlen; -	p += srvstr_pull_buf_talloc(req, req->inbuf, req->flags2, +	p += srvstr_pull_buf_talloc(ctx, req->inbuf, req->flags2,  				    &dev, p, STR_TERMINATE) + 1;  	if (service_buf == NULL || password == NULL || dev == NULL) { @@ -515,8 +516,7 @@ void reply_tcon_and_X(connection_struct *conn, struct smb_request *req)  {  	char *service = NULL;  	DATA_BLOB password; - -	TALLOC_CTX *ctx = NULL; +	TALLOC_CTX *ctx = talloc_tos();  	/* what the cleint thinks the device is */  	char *client_devicetype = NULL;  	/* what the server tells the client the share represents */ @@ -567,19 +567,11 @@ void reply_tcon_and_X(connection_struct *conn, struct smb_request *req)  		p = smb_buf(req->inbuf) + passlen + 1;  	} -	ctx = talloc_init("reply_tcon_and_X"); -	if (!ctx) { -		data_blob_clear_free(&password); -		reply_nterror(req, NT_STATUS_NO_MEMORY); -		END_PROFILE(SMBtconX); -		return; -	}  	p += srvstr_pull_buf_talloc(ctx, req->inbuf, req->flags2, &path, p,  			     STR_TERMINATE);  	if (path == NULL) {  		data_blob_clear_free(&password); -		TALLOC_FREE(ctx);  		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);  		END_PROFILE(SMBtconX);  		return; @@ -593,7 +585,6 @@ void reply_tcon_and_X(connection_struct *conn, struct smb_request *req)  		q = strchr_m(path+2,'\\');  		if (!q) {  			data_blob_clear_free(&password); -			TALLOC_FREE(ctx);  			reply_doserror(req, ERRDOS, ERRnosuchshare);  			END_PROFILE(SMBtconX);  			return; @@ -609,7 +600,6 @@ void reply_tcon_and_X(connection_struct *conn, struct smb_request *req)  	if (client_devicetype == NULL) {  		data_blob_clear_free(&password); -		TALLOC_FREE(ctx);  		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);  		END_PROFILE(SMBtconX);  		return; @@ -623,7 +613,6 @@ void reply_tcon_and_X(connection_struct *conn, struct smb_request *req)  	data_blob_clear_free(&password);  	if (!conn) { -		TALLOC_FREE(ctx);  		reply_nterror(req, nt_status);  		END_PROFILE(SMBtconX);  		return; @@ -640,7 +629,6 @@ void reply_tcon_and_X(connection_struct *conn, struct smb_request *req)  		reply_outbuf(req, 2, 0);  		if (message_push_string(&req->outbuf, server_devicetype,  					STR_TERMINATE|STR_ASCII) == -1) { -			TALLOC_FREE(ctx);  			reply_nterror(req, NT_STATUS_NO_MEMORY);  			END_PROFILE(SMBtconX);  			return; @@ -675,7 +663,6 @@ void reply_tcon_and_X(connection_struct *conn, struct smb_request *req)  					 STR_TERMINATE|STR_ASCII) == -1)  		    || (message_push_string(&req->outbuf, fstype,  					    STR_TERMINATE) == -1)) { -			TALLOC_FREE(ctx);  			reply_nterror(req, NT_STATUS_NO_MEMORY);  			END_PROFILE(SMBtconX);  			return; @@ -697,7 +684,6 @@ void reply_tcon_and_X(connection_struct *conn, struct smb_request *req)  	SSVAL(req->inbuf,smb_tid,conn->cnum);  	SSVAL(req->outbuf,smb_tid,conn->cnum); -	TALLOC_FREE(ctx);  	END_PROFILE(SMBtconX);  	chain_reply(req); @@ -827,6 +813,7 @@ void reply_checkpath(connection_struct *conn, struct smb_request *req)  	char *name = NULL;  	SMB_STRUCT_STAT sbuf;  	NTSTATUS status; +	TALLOC_CTX *ctx = talloc_tos();  	START_PROFILE(SMBcheckpath); @@ -840,7 +827,10 @@ void reply_checkpath(connection_struct *conn, struct smb_request *req)  		return;  	} -	status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, name_in); +	status = resolve_dfspath(ctx, conn, +			req->flags2 & FLAGS2_DFS_PATHNAMES, +			name_in, +			&name);  	if (!NT_STATUS_IS_OK(status)) {  		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {  			reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, @@ -853,7 +843,7 @@ void reply_checkpath(connection_struct *conn, struct smb_request *req)  	DEBUG(3,("reply_checkpath %s mode=%d\n", name_in, (int)SVAL(req->inbuf,smb_vwv0))); -	status = unix_convert(conn, name_in, False, &name, NULL, &sbuf); +	status = unix_convert(conn, name, False, &name, NULL, &sbuf);  	if (!NT_STATUS_IS_OK(status)) {  		goto path_err;  	} @@ -922,6 +912,7 @@ void reply_getatr(connection_struct *conn, struct smb_request *req)  	time_t mtime=0;  	char *p;  	NTSTATUS status; +	TALLOC_CTX *ctx = talloc_tos();  	START_PROFILE(SMBgetatr); @@ -934,8 +925,10 @@ void reply_getatr(connection_struct *conn, struct smb_request *req)  		return;  	} -	status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, -				 fname_in); +	status = resolve_dfspath(ctx, conn, +				req->flags2 & FLAGS2_DFS_PATHNAMES, +				fname_in, +				&fname);  	if (!NT_STATUS_IS_OK(status)) {  		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {  			reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, @@ -947,10 +940,10 @@ void reply_getatr(connection_struct *conn, struct smb_request *req)  		END_PROFILE(SMBgetatr);  		return;  	} -   +  	/* dos smetimes asks for a stat of "" - it returns a "hidden directory"  		under WfWg - weird! */ -	if (*fname_in == '\0') { +	if (*fname == '\0') {  		mode = aHIDDEN | aDIR;  		if (!CAN_WRITE(conn)) {  			mode |= aRONLY; @@ -958,7 +951,7 @@ void reply_getatr(connection_struct *conn, struct smb_request *req)  		size = 0;  		mtime = 0;  	} else { -		status = unix_convert(conn, fname_in, False, &fname, NULL,&sbuf); +		status = unix_convert(conn, fname, False, &fname, NULL,&sbuf);  		if (!NT_STATUS_IS_OK(status)) {  			reply_nterror(req, status);  			END_PROFILE(SMBgetatr); @@ -1020,6 +1013,7 @@ void reply_setatr(connection_struct *conn, struct smb_request *req)  	SMB_STRUCT_STAT sbuf;  	char *p;  	NTSTATUS status; +	TALLOC_CTX *ctx = talloc_tos();  	START_PROFILE(SMBsetatr); @@ -1037,8 +1031,10 @@ void reply_setatr(connection_struct *conn, struct smb_request *req)  		return;  	} -	status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, -				 fname_in); +	status = resolve_dfspath(ctx, conn, +				req->flags2 & FLAGS2_DFS_PATHNAMES, +				fname_in, +				&fname);  	if (!NT_STATUS_IS_OK(status)) {  		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {  			reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, @@ -1051,7 +1047,7 @@ void reply_setatr(connection_struct *conn, struct smb_request *req)  		return;  	} -	status = unix_convert(conn, fname_in, False, &fname, NULL, &sbuf); +	status = unix_convert(conn, fname, False, &fname, NULL, &sbuf);  	if (!NT_STATUS_IS_OK(status)) {  		reply_nterror(req, status);  		END_PROFILE(SMBsetatr); @@ -1175,7 +1171,8 @@ void reply_search(connection_struct *conn, struct smb_request *req)  	BOOL finished = False;  	char *p;  	int status_len; -	pstring path; +	pstring path_in; +	char *path = NULL;  	char status[21];  	int dptr_num= -1;  	BOOL check_descend = False; @@ -1183,6 +1180,7 @@ void reply_search(connection_struct *conn, struct smb_request *req)  	NTSTATUS nt_status;  	BOOL mask_contains_wcard = False;  	BOOL allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False; +	TALLOC_CTX *ctx = talloc_tos();  	START_PROFILE(SMBsearch); @@ -1209,8 +1207,8 @@ void reply_search(connection_struct *conn, struct smb_request *req)  	maxentries = SVAL(req->inbuf,smb_vwv0);  	dirtype = SVAL(req->inbuf,smb_vwv1);  	p = smb_buf(req->inbuf) + 1; -	p += srvstr_get_path_wcard((char *)req->inbuf, req->flags2, path, p, -				   sizeof(path), 0, STR_TERMINATE, &nt_status, +	p += srvstr_get_path_wcard((char *)req->inbuf, req->flags2, path_in, p, +				   sizeof(path_in), 0, STR_TERMINATE, &nt_status,  				   &mask_contains_wcard);  	if (!NT_STATUS_IS_OK(nt_status)) {  		reply_nterror(req, nt_status); @@ -1218,9 +1216,11 @@ void reply_search(connection_struct *conn, struct smb_request *req)  		return;  	} -	nt_status = resolve_dfspath_wcard(conn, +	nt_status = resolve_dfspath_wcard(ctx, conn,  					  req->flags2 & FLAGS2_DFS_PATHNAMES, -					  path, &mask_contains_wcard); +					  path_in, +					  &path, +					  &mask_contains_wcard);  	if (!NT_STATUS_IS_OK(nt_status)) {  		if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {  			reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, @@ -1232,11 +1232,11 @@ void reply_search(connection_struct *conn, struct smb_request *req)  		END_PROFILE(SMBsearch);  		return;  	} -   +  	p++;  	status_len = SVAL(p, 0);  	p += 2; -   +  	/* dirtype &= ~aDIR; */  	if (status_len == 0) { @@ -1512,6 +1512,7 @@ void reply_open(connection_struct *conn, struct smb_request *req)  	uint32 create_disposition;  	uint32 create_options = 0;  	NTSTATUS status; +	TALLOC_CTX *ctx = talloc_tos();  	START_PROFILE(SMBopen); @@ -1520,7 +1521,7 @@ void reply_open(connection_struct *conn, struct smb_request *req)  		END_PROFILE(SMBopen);  		return;  	} -  +  	oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);  	deny_mode = SVAL(req->inbuf,smb_vwv0);  	dos_attr = SVAL(req->inbuf,smb_vwv1); @@ -1534,8 +1535,10 @@ void reply_open(connection_struct *conn, struct smb_request *req)  		return;  	} -	status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, -				 fname_in); +	status = resolve_dfspath(ctx, conn, +				req->flags2 & FLAGS2_DFS_PATHNAMES, +				fname_in, +				&fname);  	if (!NT_STATUS_IS_OK(status)) {  		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {  			reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, @@ -1548,7 +1551,7 @@ void reply_open(connection_struct *conn, struct smb_request *req)  		return;  	} -	status = unix_convert(conn, fname_in, False, &fname, NULL, &sbuf); +	status = unix_convert(conn, fname, False, &fname, NULL, &sbuf);  	if (!NT_STATUS_IS_OK(status)) {  		reply_nterror(req, status);  		END_PROFILE(SMBopen); @@ -1658,6 +1661,7 @@ void reply_open_and_X(connection_struct *conn, struct smb_request *req)  	uint32 share_mode;  	uint32 create_disposition;  	uint32 create_options = 0; +	TALLOC_CTX *ctx = talloc_tos();  	START_PROFILE(SMBopenX); @@ -1697,8 +1701,10 @@ void reply_open_and_X(connection_struct *conn, struct smb_request *req)  		return;  	} -	status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, -				 fname_in); +	status = resolve_dfspath(ctx, conn, +				req->flags2 & FLAGS2_DFS_PATHNAMES, +				fname_in, +				&fname);  	if (!NT_STATUS_IS_OK(status)) {  		END_PROFILE(SMBopenX);  		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { @@ -1710,7 +1716,7 @@ void reply_open_and_X(connection_struct *conn, struct smb_request *req)  		return;  	} -	status = unix_convert(conn, fname_in, False, &fname, NULL, &sbuf); +	status = unix_convert(conn, fname, False, &fname, NULL, &sbuf);  	if (!NT_STATUS_IS_OK(status)) {  		reply_nterror(req, status);  		END_PROFILE(SMBopenX); @@ -1889,6 +1895,7 @@ void reply_mknew(connection_struct *conn, struct smb_request *req)  	uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;  	uint32 create_disposition;  	uint32 create_options = 0; +	TALLOC_CTX *ctx = talloc_tos();  	START_PROFILE(SMBcreate); @@ -1915,8 +1922,10 @@ void reply_mknew(connection_struct *conn, struct smb_request *req)  		return;  	} -	status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, -			fname_in); +	status = resolve_dfspath(ctx, conn, +			req->flags2 & FLAGS2_DFS_PATHNAMES, +			fname_in, +			&fname);  	if (!NT_STATUS_IS_OK(status)) {  		END_PROFILE(SMBcreate);  		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { @@ -1928,7 +1937,7 @@ void reply_mknew(connection_struct *conn, struct smb_request *req)  		return;  	} -	status = unix_convert(conn, fname_in, False, &fname, NULL, &sbuf); +	status = unix_convert(conn, fname, False, &fname, NULL, &sbuf);  	if (!NT_STATUS_IS_OK(status)) {  		reply_nterror(req, status);  		END_PROFILE(SMBcreate); @@ -2014,6 +2023,7 @@ void reply_ctemp(connection_struct *conn, struct smb_request *req)  	SMB_STRUCT_STAT sbuf;  	char *s;  	NTSTATUS status; +	TALLOC_CTX *ctx = talloc_tos();  	START_PROFILE(SMBctemp); @@ -2040,8 +2050,10 @@ void reply_ctemp(connection_struct *conn, struct smb_request *req)  		pstrcat(fname_in,"TMXXXXXX");  	} -	status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, -				 fname_in); +	status = resolve_dfspath(ctx, conn, +				req->flags2 & FLAGS2_DFS_PATHNAMES, +				fname_in, +				&fname);  	if (!NT_STATUS_IS_OK(status)) {  		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {  			reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, @@ -2054,20 +2066,20 @@ void reply_ctemp(connection_struct *conn, struct smb_request *req)  		return;  	} -	status = unix_convert(conn, fname_in, False, &fname, NULL, &sbuf); +	status = unix_convert(conn, fname, False, &fname, NULL, &sbuf);  	if (!NT_STATUS_IS_OK(status)) {  		reply_nterror(req, status);  		END_PROFILE(SMBctemp);  		return;  	} -	status = check_name(conn, fname); +	status = check_name(conn, CONST_DISCARD(char *,fname));  	if (!NT_STATUS_IS_OK(status)) {  		reply_nterror(req, status);  		END_PROFILE(SMBctemp);  		return;  	} -   +  	tmpfd = smb_mkstemp(fname);  	if (tmpfd == -1) {  		reply_unixerror(req, ERRDOS, ERRnoaccess); @@ -2446,10 +2458,12 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,  void reply_unlink(connection_struct *conn, struct smb_request *req)  { -	pstring name; +	pstring name_in; +	char *name = NULL;  	uint32 dirtype;  	NTSTATUS status;  	BOOL path_contains_wcard = False; +	TALLOC_CTX *ctx = talloc_tos();  	START_PROFILE(SMBunlink); @@ -2460,9 +2474,9 @@ void reply_unlink(connection_struct *conn, struct smb_request *req)  	}  	dirtype = SVAL(req->inbuf,smb_vwv0); -	 -	srvstr_get_path_wcard((char *)req->inbuf, req->flags2, name, -			      smb_buf(req->inbuf) + 1, sizeof(name), 0, + +	srvstr_get_path_wcard((char *)req->inbuf, req->flags2, name_in, +			      smb_buf(req->inbuf) + 1, sizeof(name_in), 0,  			      STR_TERMINATE, &status, &path_contains_wcard);  	if (!NT_STATUS_IS_OK(status)) {  		reply_nterror(req, status); @@ -2470,9 +2484,11 @@ void reply_unlink(connection_struct *conn, struct smb_request *req)  		return;  	} -	status = resolve_dfspath_wcard(conn, +	status = resolve_dfspath_wcard(ctx, conn,  				       req->flags2 & FLAGS2_DFS_PATHNAMES, -				       name, &path_contains_wcard); +				       name_in, +				       &name, +				       &path_contains_wcard);  	if (!NT_STATUS_IS_OK(status)) {  		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {  			reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, @@ -2484,9 +2500,9 @@ void reply_unlink(connection_struct *conn, struct smb_request *req)  		END_PROFILE(SMBunlink);  		return;  	} -	 +  	DEBUG(3,("reply_unlink : %s\n",name)); -	 +  	status = unlink_internals(conn, req, dirtype, name,  				  path_contains_wcard);  	if (!NT_STATUS_IS_OK(status)) { @@ -4633,7 +4649,7 @@ void reply_printwrite(connection_struct *conn, struct smb_request *req)  	}  	DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) ); -   +  	END_PROFILE(SMBsplwr);  	return;  } @@ -4648,9 +4664,10 @@ void reply_mkdir(connection_struct *conn, struct smb_request *req)  	char *directory = NULL;  	NTSTATUS status;  	SMB_STRUCT_STAT sbuf; +	TALLOC_CTX *ctx = talloc_tos();  	START_PROFILE(SMBmkdir); -  +  	srvstr_get_path((char *)req->inbuf, req->flags2, directory_in,  			smb_buf(req->inbuf) + 1, sizeof(directory_in), 0,  			STR_TERMINATE, &status); @@ -4660,9 +4677,10 @@ void reply_mkdir(connection_struct *conn, struct smb_request *req)  		return;  	} -	status = resolve_dfspath(conn, +	status = resolve_dfspath(ctx, conn,  				 req->flags2 & FLAGS2_DFS_PATHNAMES, -				 directory_in); +				 directory_in, +				 &directory);  	if (!NT_STATUS_IS_OK(status)) {  		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {  			reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, @@ -4675,7 +4693,7 @@ void reply_mkdir(connection_struct *conn, struct smb_request *req)  		return;  	} -	status = unix_convert(conn, directory_in, False, &directory, NULL, &sbuf); +	status = unix_convert(conn, directory, False, &directory, NULL, &sbuf);  	if (!NT_STATUS_IS_OK(status)) {  		reply_nterror(req, status);  		END_PROFILE(SMBmkdir); @@ -4902,6 +4920,8 @@ void reply_rmdir(connection_struct *conn, struct smb_request *req)  	char *directory = NULL;  	SMB_STRUCT_STAT sbuf;  	NTSTATUS status; +	TALLOC_CTX *ctx = talloc_tos(); +  	START_PROFILE(SMBrmdir);  	srvstr_get_path((char *)req->inbuf, req->flags2, directory_in, @@ -4913,9 +4933,10 @@ void reply_rmdir(connection_struct *conn, struct smb_request *req)  		return;  	} -	status = resolve_dfspath(conn, +	status = resolve_dfspath(ctx, conn,  				 req->flags2 & FLAGS2_DFS_PATHNAMES, -				 directory_in); +				 directory_in, +				 &directory);  	if (!NT_STATUS_IS_OK(status)) {  		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {  			reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, @@ -4928,14 +4949,14 @@ void reply_rmdir(connection_struct *conn, struct smb_request *req)  		return;  	} -	status = unix_convert(conn, directory_in, False, &directory, +	status = unix_convert(conn, directory, False, &directory,  			NULL, &sbuf);  	if (!NT_STATUS_IS_OK(status)) {  		reply_nterror(req, status);  		END_PROFILE(SMBrmdir);  		return;  	} -   +  	status = check_name(conn, directory);  	if (!NT_STATUS_IS_OK(status)) {  		reply_nterror(req, status); @@ -5662,13 +5683,16 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,  void reply_mv(connection_struct *conn, struct smb_request *req)  { -	pstring name; -	pstring newname; +	pstring name_in; +	pstring newname_in; +	char *name = NULL; +	char *newname = NULL;  	char *p;  	uint32 attrs;  	NTSTATUS status;  	BOOL src_has_wcard = False;  	BOOL dest_has_wcard = False; +	TALLOC_CTX *ctx = talloc_tos();  	START_PROFILE(SMBmv); @@ -5681,8 +5705,8 @@ void reply_mv(connection_struct *conn, struct smb_request *req)  	attrs = SVAL(req->inbuf,smb_vwv0);  	p = smb_buf(req->inbuf) + 1; -	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,  				   &src_has_wcard);  	if (!NT_STATUS_IS_OK(status)) {  		reply_nterror(req, status); @@ -5690,18 +5714,20 @@ void reply_mv(connection_struct *conn, struct smb_request *req)  		return;  	}  	p++; -	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_wcard);  	if (!NT_STATUS_IS_OK(status)) {  		reply_nterror(req, status);  		END_PROFILE(SMBmv);  		return;  	} -	 -	status = resolve_dfspath_wcard(conn, + +	status = resolve_dfspath_wcard(ctx, conn,  				       req->flags2 & FLAGS2_DFS_PATHNAMES, -				       name, &src_has_wcard); +				       name_in, +				       &name, +				       &src_has_wcard);  	if (!NT_STATUS_IS_OK(status)) {  		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {  			reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, @@ -5714,9 +5740,11 @@ void reply_mv(connection_struct *conn, struct smb_request *req)  		return;  	} -	status = resolve_dfspath_wcard(conn, +	status = resolve_dfspath_wcard(ctx, conn,  				       req->flags2 & FLAGS2_DFS_PATHNAMES, -				       newname, &dest_has_wcard); +				       newname_in, +				       &newname, +				       &dest_has_wcard);  	if (!NT_STATUS_IS_OK(status)) {  		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {  			reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, @@ -5728,9 +5756,9 @@ void reply_mv(connection_struct *conn, struct smb_request *req)  		END_PROFILE(SMBmv);  		return;  	} -	 +  	DEBUG(3,("reply_mv : %s -> %s\n",name,newname)); -	 +  	status = rename_internals(conn, req, name, newname, attrs, False,  				  src_has_wcard, dest_has_wcard);  	if (!NT_STATUS_IS_OK(status)) { @@ -5745,7 +5773,7 @@ void reply_mv(connection_struct *conn, struct smb_request *req)  	}  	reply_outbuf(req, 0, 0); -   +  	END_PROFILE(SMBmv);  	return;  } @@ -5893,6 +5921,7 @@ void reply_copy(connection_struct *conn, struct smb_request *req)  	BOOL dest_has_wild = False;  	SMB_STRUCT_STAT sbuf1, sbuf2;  	NTSTATUS status; +	TALLOC_CTX *ctx = talloc_tos();  	START_PROFILE(SMBcopy); @@ -5925,9 +5954,9 @@ void reply_copy(connection_struct *conn, struct smb_request *req)  		END_PROFILE(SMBcopy);  		return;  	} -    +  	DEBUG(3,("reply_copy : %s -> %s\n",name_in,newname_in)); -    +  	if (tid2 != conn->cnum) {  		/* can't currently handle inter share copies XXXX */  		DEBUG(3,("Rejecting inter-share copy\n")); @@ -5936,9 +5965,11 @@ void reply_copy(connection_struct *conn, struct smb_request *req)  		return;  	} -	status = resolve_dfspath_wcard(conn, +	status = resolve_dfspath_wcard(ctx, conn,  				       req->flags2 & FLAGS2_DFS_PATHNAMES, -				       name_in, &source_has_wild); +				       name_in, +				       &name, +				       &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, @@ -5951,9 +5982,11 @@ void reply_copy(connection_struct *conn, struct smb_request *req)  		return;  	} -	status = resolve_dfspath_wcard(conn, +	status = resolve_dfspath_wcard(ctx, conn,  				       req->flags2 & FLAGS2_DFS_PATHNAMES, -				       newname_in, &dest_has_wild); +				       newname_in, +				       &newname, +				       &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, @@ -5966,14 +5999,14 @@ void reply_copy(connection_struct *conn, struct smb_request *req)  		return;  	} -	status = unix_convert(conn, name_in, source_has_wild, &name, NULL, &sbuf1); +	status = unix_convert(conn, name, 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_in, dest_has_wild, &newname, NULL, &sbuf2); +	status = unix_convert(conn, newname, dest_has_wild, &newname, NULL, &sbuf2);  	if (!NT_STATUS_IS_OK(status)) {  		reply_nterror(req, status);  		END_PROFILE(SMBcopy); diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 59f384e8b0..2ba0781e62 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1268,14 +1268,12 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, uint16 flags2,  					continue;  				}  			} else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) { -				pstring link_target; - -				/* Needed to show the msdfs symlinks as  +				/* Needed to show the msdfs symlinks as  				 * directories */ -				if(lp_host_msdfs() &&  +				if(lp_host_msdfs() &&  				   lp_msdfs_root(SNUM(conn)) && -				   ((ms_dfs_link = is_msdfs_link(conn, pathreal, link_target, &sbuf)) == True)) { +				   ((ms_dfs_link = is_msdfs_link(conn, pathreal, &sbuf)) == True)) {  					DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s "  						"as a directory\n",  						pathreal)); @@ -1778,6 +1776,7 @@ static void call_trans2findfirst(connection_struct *conn,  	TALLOC_CTX *ea_ctx = NULL;  	struct ea_list *ea_list = NULL;  	NTSTATUS ntstatus = NT_STATUS_OK; +	TALLOC_CTX *ctx = talloc_tos();  	if (total_params < 13) {  		reply_nterror(req, NT_STATUS_INVALID_PARAMETER); @@ -1835,7 +1834,11 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",  		return;  	} -	ntstatus = resolve_dfspath_wcard(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, directory_in, &mask_contains_wcard); +	ntstatus = resolve_dfspath_wcard(ctx, conn, +			req->flags2 & FLAGS2_DFS_PATHNAMES, +			directory_in, +			&directory, +			&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, @@ -1846,7 +1849,7 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",  		return;  	} -	ntstatus = unix_convert(conn, directory_in, True, &directory, NULL, &sbuf); +	ntstatus = unix_convert(conn, directory, True, &directory, NULL, &sbuf);  	if (!NT_STATUS_IS_OK(ntstatus)) {  		reply_nterror(req, ntstatus);  		return; @@ -3524,6 +3527,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn,  	struct ea_list *ea_list = NULL;  	uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */  	char *lock_data = NULL; +	TALLOC_CTX *ctx = NULL;  	if (!params) {  		reply_nterror(req, NT_STATUS_INVALID_PARAMETER); @@ -3642,9 +3646,11 @@ static void call_trans2qfilepathinfo(connection_struct *conn,  			return;  		} -		status = resolve_dfspath(conn, -					 req->flags2 & FLAGS2_DFS_PATHNAMES, -					 fname_in); +		status = resolve_dfspath(ctx, +					conn, +					req->flags2 & FLAGS2_DFS_PATHNAMES, +					fname_in, +					&fname);  		if (!NT_STATUS_IS_OK(status)) {  			if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {  				reply_botherror(req, @@ -3655,7 +3661,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn,  			return;  		} -		status = unix_convert(conn, fname_in, False, &fname, NULL, &sbuf); +		status = unix_convert(conn, fname, False, &fname, NULL, &sbuf);  		if (!NT_STATUS_IS_OK(status)) {  			reply_nterror(req, status);  			return; @@ -4431,8 +4437,8 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd  ****************************************************************************/  NTSTATUS hardlink_internals(connection_struct *conn, -		char *oldname_in, -		char *newname_in) +		const char *oldname_in, +		const char *newname_in)  {  	SMB_STRUCT_STAT sbuf1, sbuf2;  	char *last_component_oldname = NULL; @@ -4889,9 +4895,11 @@ static NTSTATUS smb_set_file_unix_link(connection_struct *conn,  static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,  					struct smb_request *req,  					const char *pdata, int total_data, -					pstring fname) +					const char *fname)  { -	pstring oldname; +	pstring oldname_in; +	char *oldname = NULL; +	TALLOC_CTX *ctx = talloc_tos();  	NTSTATUS status = NT_STATUS_OK;  	/* Set a hard link. */ @@ -4899,14 +4907,16 @@ static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,  		return NT_STATUS_INVALID_PARAMETER;  	} -	srvstr_get_path(pdata, req->flags2, oldname, pdata, -			sizeof(oldname), total_data, STR_TERMINATE, &status); +	srvstr_get_path(pdata, req->flags2, oldname_in, pdata, +			sizeof(oldname_in), total_data, STR_TERMINATE, &status);  	if (!NT_STATUS_IS_OK(status)) {  		return status;  	} -	status = resolve_dfspath(conn, req->flags2 & FLAGS2_DFS_PATHNAMES, -				 oldname); +	status = resolve_dfspath(ctx, conn, +				req->flags2 & FLAGS2_DFS_PATHNAMES, +				oldname_in, +				&oldname);  	if (!NT_STATUS_IS_OK(status)) {  		return status;  	} @@ -4932,10 +4942,12 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,  	uint32 root_fid;  	uint32 len;  	pstring newname_in; +	char *newname = NULL;  	pstring base_name;  	BOOL dest_has_wcard = False;  	NTSTATUS status = NT_STATUS_OK;  	char *p; +	TALLOC_CTX *ctx = talloc_tos();  	if (total_data < 13) {  		return NT_STATUS_INVALID_PARAMETER; @@ -4956,15 +4968,17 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,  		return status;  	} -	status = resolve_dfspath_wcard(conn, +	status = resolve_dfspath_wcard(ctx, conn,  				       req->flags2 & FLAGS2_DFS_PATHNAMES, -				       newname_in, &dest_has_wcard); +				       newname_in, +				       &newname, +				       &dest_has_wcard);  	if (!NT_STATUS_IS_OK(status)) {  		return status;  	}  	/* Check the new name has no '/' characters. */ -	if (strchr_m(newname_in, '/')) { +	if (strchr_m(newname, '/')) {  		return NT_STATUS_NOT_SUPPORTED;  	} @@ -4977,16 +4991,15 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,  		pstrcpy(base_name, "./");  	}  	/* Append the new name. */ -	pstrcat(base_name, newname_in); +	pstrcat(base_name, newname);  	if (fsp) {  		SMB_STRUCT_STAT sbuf; -		char *newname = NULL;  		char *newname_last_component = NULL;  		ZERO_STRUCT(sbuf); -		status = unix_convert(conn, newname_in, False, +		status = unix_convert(conn, newname, False,  					&newname,  					&newname_last_component,  					&sbuf); @@ -6171,6 +6184,7 @@ static void call_trans2setfilepathinfo(connection_struct *conn,  	files_struct *fsp = NULL;  	NTSTATUS status = NT_STATUS_OK;  	int data_return_size = 0; +	TALLOC_CTX *ctx = talloc_tos();  	if (!params) {  		reply_nterror(req, NT_STATUS_INVALID_PARAMETER); @@ -6268,9 +6282,10 @@ static void call_trans2setfilepathinfo(connection_struct *conn,  			return;  		} -		status = resolve_dfspath(conn, +		status = resolve_dfspath(ctx, conn,  					 req->flags2 & FLAGS2_DFS_PATHNAMES, -					 fname_in); +					 fname_in, +					 &fname);  		if (!NT_STATUS_IS_OK(status)) {  			if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {  				reply_botherror(req, @@ -6282,7 +6297,7 @@ static void call_trans2setfilepathinfo(connection_struct *conn,  			return;  		} -		status = unix_convert(conn, fname_in, False, &fname, NULL, &sbuf); +		status = unix_convert(conn, fname, False, &fname, NULL, &sbuf);  		if (!NT_STATUS_IS_OK(status)) {  			reply_nterror(req, status);  			return;  | 
