From 9b4e6c7ea6f9be7b7a29a9a467c7131342caa6b1 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 29 Apr 2004 20:47:48 +0000 Subject: r410: merge tpot's changeset 353 from trunk: Move msdfs.c into the source/smbd directory and remove source/msdfs. metze (This used to be commit 88e6e6d29ca14e0cddbc1df611051a96568dc0c9) --- source3/smbd/msdfs.c | 1019 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1019 insertions(+) create mode 100644 source3/smbd/msdfs.c (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c new file mode 100644 index 0000000000..c66f0477a8 --- /dev/null +++ b/source3/smbd/msdfs.c @@ -0,0 +1,1019 @@ +/* + Unix SMB/Netbios implementation. + Version 3.0 + MSDfs services for Samba + Copyright (C) Shirish Kalele 2000 + + 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include "includes.h" + +extern fstring local_machine; +extern uint32 global_client_caps; + +/********************************************************************** + Parse the pathname of the form \hostname\service\reqpath + into the dfs_path structure + **********************************************************************/ + +static BOOL parse_dfs_path(char* pathname, struct dfs_path* pdp) +{ + pstring pathname_local; + char* p,*temp; + + pstrcpy(pathname_local,pathname); + p = temp = pathname_local; + + ZERO_STRUCTP(pdp); + + trim_char(temp,'\\','\\'); + DEBUG(10,("temp in parse_dfs_path: .%s. after trimming \\'s\n",temp)); + + /* now tokenize */ + /* parse out hostname */ + p = strchr_m(temp,'\\'); + if(p == NULL) + return False; + *p = '\0'; + pstrcpy(pdp->hostname,temp); + DEBUG(10,("parse_dfs_path: hostname: %s\n",pdp->hostname)); + + /* parse out servicename */ + temp = p+1; + p = strchr_m(temp,'\\'); + if(p == NULL) { + pstrcpy(pdp->servicename,temp); + pdp->reqpath[0] = '\0'; + return True; + } + *p = '\0'; + pstrcpy(pdp->servicename,temp); + DEBUG(10,("parse_dfs_path: servicename: %s\n",pdp->servicename)); + + /* rest is reqpath */ + check_path_syntax(pdp->reqpath, p+1); + + DEBUG(10,("parse_dfs_path: rest of the path: %s\n",pdp->reqpath)); + return True; +} + +/********************************************************************** + Parse the pathname of the form /hostname/service/reqpath + into the dfs_path structure + **********************************************************************/ + +static BOOL parse_processed_dfs_path(char* pathname, struct dfs_path* pdp) +{ + pstring pathname_local; + char* p,*temp; + + pstrcpy(pathname_local,pathname); + p = temp = pathname_local; + + ZERO_STRUCTP(pdp); + + trim_char(temp,'/','/'); + DEBUG(10,("temp in parse_processed_dfs_path: .%s. after trimming \\'s\n",temp)); + + /* now tokenize */ + /* parse out hostname */ + p = strchr_m(temp,'/'); + if(p == NULL) + return False; + *p = '\0'; + pstrcpy(pdp->hostname,temp); + DEBUG(10,("parse_processed_dfs_path: hostname: %s\n",pdp->hostname)); + + /* parse out servicename */ + temp = p+1; + p = strchr_m(temp,'/'); + if(p == NULL) { + pstrcpy(pdp->servicename,temp); + pdp->reqpath[0] = '\0'; + return True; + } + *p = '\0'; + pstrcpy(pdp->servicename,temp); + DEBUG(10,("parse_processed_dfs_path: servicename: %s\n",pdp->servicename)); + + /* rest is reqpath */ + check_path_syntax(pdp->reqpath, p+1); + + DEBUG(10,("parse_processed_dfs_path: rest of the path: %s\n",pdp->reqpath)); + return True; +} + +/******************************************************** + Fake up a connection struct for the VFS layer. + Note this CHANGES CWD !!!! JRA. +*********************************************************/ + +static BOOL create_conn_struct( connection_struct *conn, int snum, char *path) +{ + ZERO_STRUCTP(conn); + conn->service = snum; + conn->connectpath = path; + pstring_sub(conn->connectpath , "%S", lp_servicename(snum)); + + /* needed for smbd_vfs_init() */ + + if ( (conn->mem_ctx=talloc_init("connection_struct")) == NULL ) { + DEBUG(0,("talloc_init(connection_struct) failed!\n")); + return False; + } + + if (!smbd_vfs_init(conn)) { + DEBUG(0,("create_conn_struct: smbd_vfs_init failed.\n")); + talloc_destroy( conn->mem_ctx ); + return False; + } + + /* + * 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) { + DEBUG(3,("create_conn_struct: Can't ChDir to new conn path %s. Error was %s\n", + conn->connectpath, strerror(errno) )); + talloc_destroy( conn->mem_ctx ); + return False; + } + return True; +} + + +/********************************************************************** + Parse the contents of a symlink to verify if it is an msdfs referral + A valid referral is of the form: msdfs:server1\share1,server2\share2 + **********************************************************************/ + +static BOOL parse_symlink(char* buf,struct referral** preflist, + int* refcount) +{ + pstring temp; + char* prot; + char* alt_path[MAX_REFERRAL_COUNT]; + int count=0, i; + struct referral* reflist; + + pstrcpy(temp,buf); + + prot = strtok(temp,":"); + + if (!strequal(prot, "msdfs")) + return False; + + /* No referral list requested. Just yes/no. */ + if (!preflist) + return True; + + /* parse out the alternate paths */ + while(((alt_path[count] = strtok(NULL,",")) != NULL) && countst_mode)) { + /* open the link and read it */ + referral_len = SMB_VFS_READLINK(conn, path, referral, + sizeof(pstring)); + if (referral_len == -1) { + DEBUG(0,("is_msdfs_link: Error reading msdfs link %s: %s\n", path, strerror(errno))); + return False; + } + + referral[referral_len] = '\0'; + DEBUG(5,("is_msdfs_link: %s -> %s\n",path,referral)); + if (parse_symlink(referral, reflistp, refcnt)) + return True; + } + return False; +} + +/***************************************************************** + Used by other functions to decide if a dfs path is remote, +and to get the list of referred locations for that remote path. + +findfirst_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. + +self_referralp: clients expect a dfs referral for the same share when +they request referrals for dfs roots on a server. + +consumedcntp: how much of the dfs path is being redirected. the client +should try the remaining path on the redirected server. + +*****************************************************************/ + +static BOOL resolve_dfs_path(pstring dfspath, struct dfs_path* dp, + connection_struct* conn, + BOOL findfirst_flag, + struct referral** reflistpp, int* refcntp, + BOOL* self_referralp, int* consumedcntp) +{ + pstring localpath; + int consumed_level = 1; + char *p; + BOOL bad_path = False; + SMB_STRUCT_STAT sbuf; + pstring reqpath; + + if (!dp || !conn) { + DEBUG(1,("resolve_dfs_path: NULL dfs_path* or NULL connection_struct*!\n")); + return False; + } + + if (dp->reqpath[0] == '\0') { + if (self_referralp) { + DEBUG(6,("resolve_dfs_path: self-referral. returning False\n")); + *self_referralp = True; + } + return False; + } + + DEBUG(10,("resolve_dfs_path: Conn path = %s req_path = %s\n", conn->connectpath, dp->reqpath)); + + unix_convert(dp->reqpath,conn,0,&bad_path,&sbuf); + /* JRA... should we strlower the last component here.... ? */ + pstrcpy(localpath, dp->reqpath); + + /* check if need to redirect */ + if (is_msdfs_link(conn, localpath, reflistpp, refcntp, NULL)) { + if (findfirst_flag) { + DEBUG(6,("resolve_dfs_path (FindFirst) No redirection " + "for dfs link %s.\n", dfspath)); + return False; + } else { + DEBUG(6,("resolve_dfs_path: %s resolves to a valid Dfs link.\n", + dfspath)); + if (consumedcntp) + *consumedcntp = strlen(dfspath); + return True; + } + } + + /* redirect if any component in the path is a link */ + pstrcpy(reqpath, dp->reqpath); + p = strrchr_m(reqpath, '/'); + while (p) { + *p = '\0'; + pstrcpy(localpath, reqpath); + if (is_msdfs_link(conn, localpath, reflistpp, refcntp, NULL)) { + DEBUG(4, ("resolve_dfs_path: Redirecting %s because parent %s is dfs link\n", dfspath, localpath)); + + /* To find the path consumed, we truncate the original + DFS pathname passed to use to remove the last + component. The length of the resulting string is + the path consumed + */ + if (consumedcntp) { + char *q; + pstring buf; + pstrcpy(buf, dfspath); + trim_char(buf, '\0', '\\'); + for (; consumed_level; consumed_level--) { + q = strrchr_m(buf, '\\'); + if (q) + *q = 0; + } + *consumedcntp = strlen(buf); + DEBUG(10, ("resolve_dfs_path: Path consumed: %s (%d)\n", buf, *consumedcntp)); + } + + return True; + } + p = strrchr_m(reqpath, '/'); + consumed_level++; + } + + return False; +} + +/***************************************************************** + Decides if a dfs pathname should be redirected or not. + If not, the pathname is converted to a tcon-relative local unix path +*****************************************************************/ + +BOOL dfs_redirect(pstring pathname, connection_struct* conn, + BOOL findfirst_flag) +{ + struct dfs_path dp; + + if (!conn || !pathname) + return False; + + parse_processed_dfs_path(pathname, &dp); + + /* if dfs pathname for a non-dfs share, convert to tcon-relative + path and return false */ + if (!lp_msdfs_root(SNUM(conn))) { + pstrcpy(pathname, dp.reqpath); + return False; + } + + if (!strequal(dp.servicename, lp_servicename(SNUM(conn)) )) + return False; + + if (resolve_dfs_path(pathname, &dp, conn, findfirst_flag, + NULL, NULL, NULL, NULL)) { + DEBUG(3,("dfs_redirect: Redirecting %s\n", pathname)); + return True; + } else { + DEBUG(3,("dfs_redirect: Not redirecting %s.\n", pathname)); + + /* Form non-dfs tcon-relative path */ + pstrcpy(pathname, dp.reqpath); + DEBUG(3,("dfs_redirect: Path converted to non-dfs path %s\n", + pathname)); + return False; + } + + /* never reached */ +} + +/********************************************************************** + Return a self referral. +**********************************************************************/ + +static BOOL self_ref(char *pathname, struct junction_map *jucn, + int *consumedcntp, BOOL *self_referralp) +{ + struct referral *ref; + + if (self_referralp != NULL) + *self_referralp = True; + + jucn->referral_count = 1; + if((ref = (struct referral*) malloc(sizeof(struct referral))) == NULL) { + DEBUG(0,("self_ref: malloc failed for referral\n")); + return False; + } + + pstrcpy(ref->alternate_path,pathname); + ref->proximity = 0; + ref->ttl = REFERRAL_TTL; + jucn->referral_list = ref; + if (consumedcntp) + *consumedcntp = strlen(pathname); + + return True; +} + +/********************************************************************** + Gets valid referrals for a dfs path and fills up the + junction_map structure +**********************************************************************/ + +BOOL get_referred_path(char *pathname, struct junction_map *jucn, + int *consumedcntp, BOOL *self_referralp) +{ + struct dfs_path dp; + + struct connection_struct conns; + struct connection_struct* conn = &conns; + pstring conn_path; + int snum; + BOOL ret = False; + BOOL self_referral = False; + + if (!pathname || !jucn) + return False; + + ZERO_STRUCT(conns); + + if (self_referralp) + *self_referralp = False; + else + self_referralp = &self_referral; + + parse_dfs_path(pathname, &dp); + + /* Verify hostname in path */ + if (local_machine && (!strequal(local_machine, dp.hostname))) { + /* Hostname mismatch, check if one of our IP addresses */ + if (!ismyip(*interpret_addr2(dp.hostname))) { + DEBUG(3, ("get_referred_path: Invalid hostname %s in path %s\n", + dp.hostname, pathname)); + return False; + } + } + + pstrcpy(jucn->service_name, dp.servicename); + pstrcpy(jucn->volume_name, dp.reqpath); + + /* Verify the share is a dfs root */ + snum = lp_servicenumber(jucn->service_name); + if(snum < 0) { + if ((snum = find_service(jucn->service_name)) < 0) + return False; + } + + if (!lp_msdfs_root(snum)) { + DEBUG(3,("get_referred_path: .%s. in dfs path %s is not a dfs root.\n", + dp.servicename, pathname)); + goto out; + } + + /* + * 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. + */ + + if (dp.reqpath[0] == '\0') { + + struct referral* ref; + + if (*lp_msdfs_proxy(snum) == '\0') + return self_ref(pathname, jucn, consumedcntp, + self_referralp); + + jucn->referral_count = 1; + if ((ref = (struct referral*) malloc(sizeof(struct referral))) == NULL) { + DEBUG(0, ("malloc failed for referral\n")); + goto out; + } + + pstrcpy(ref->alternate_path, lp_msdfs_proxy(snum)); + if (dp.reqpath[0] != '\0') + pstrcat(ref->alternate_path, dp.reqpath); + ref->proximity = 0; + ref->ttl = REFERRAL_TTL; + jucn->referral_list = ref; + if (consumedcntp) + *consumedcntp = strlen(pathname); + ret = True; + goto out; + } + + pstrcpy(conn_path, lp_pathname(snum)); + if (!create_conn_struct(conn, snum, conn_path)) + return False; + + /* If not remote & not a self referral, return False */ + if (!resolve_dfs_path(pathname, &dp, conn, False, + &jucn->referral_list, &jucn->referral_count, + self_referralp, consumedcntp)) { + if (!*self_referralp) { + DEBUG(3,("get_referred_path: No valid referrals for path %s\n", pathname)); + goto out; + } + } + + /* if self_referral, fill up the junction map */ + if (*self_referralp) { + if (self_ref(pathname, jucn, consumedcntp, self_referralp) == False) { + goto out; + } + } + + ret = True; + +out: + if (conn->mem_ctx) + talloc_destroy( conn->mem_ctx ); + + return ret; +} + +static int setup_ver2_dfs_referral(char* pathname, char** ppdata, + struct junction_map* junction, + int consumedcnt, + BOOL self_referral) +{ + char* pdata = *ppdata; + + unsigned char uni_requestedpath[1024]; + int uni_reqpathoffset1,uni_reqpathoffset2; + int uni_curroffset; + int requestedpathlen=0; + int offset; + int reply_size = 0; + int i=0; + + DEBUG(10,("setting up version2 referral\nRequested path:\n")); + + requestedpathlen = rpcstr_push(uni_requestedpath, pathname, -1, + STR_TERMINATE); + + dump_data(10, (const char *) uni_requestedpath,requestedpathlen); + + DEBUG(10,("ref count = %u\n",junction->referral_count)); + + 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; + DEBUG(10,("reply_size: %u\n",reply_size)); + + /* add up the unicode lengths of all the referral paths */ + for(i=0;ireferral_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,("reply_size = %u\n",reply_size)); + /* add the unexplained 0x16 bytes */ + reply_size += 0x16; + + pdata = Realloc(pdata,reply_size); + if(pdata == NULL) { + DEBUG(0,("malloc failed for Realloc!\n")); + return -1; + } else + *ppdata = pdata; + + /* copy in the dfs requested paths.. required for offset calculations */ + memcpy(pdata+uni_reqpathoffset1,uni_requestedpath,requestedpathlen); + memcpy(pdata+uni_reqpathoffset2,uni_requestedpath,requestedpathlen); + + /* create the header */ + SSVAL(pdata,0,consumedcnt * 2); /* path consumed */ + SSVAL(pdata,2,junction->referral_count); /* number of referral in this pkt */ + if(self_referral) + SIVAL(pdata,4,DFSREF_REFERRAL_SERVER | DFSREF_STORAGE_SERVER); + else + SIVAL(pdata,4,DFSREF_STORAGE_SERVER); + + offset = 8; + /* add the referral elements */ + for(i=0;ireferral_count;i++) { + struct referral* ref = &junction->referral_list[i]; + int unilen; + + SSVAL(pdata,offset,2); /* version 2 */ + SSVAL(pdata,offset+2,VERSION2_REFERRAL_SIZE); + if(self_referral) + SSVAL(pdata,offset+4,1); + else + SSVAL(pdata,offset+4,0); + SSVAL(pdata,offset+6,0); /* ref_flags :use path_consumed bytes? */ + SIVAL(pdata,offset+8,ref->proximity); + SIVAL(pdata,offset+12,ref->ttl); + + SSVAL(pdata,offset+16,uni_reqpathoffset1-offset); + SSVAL(pdata,offset+18,uni_reqpathoffset2-offset); + /* copy referred path into current offset */ + unilen = rpcstr_push(pdata+uni_curroffset, ref->alternate_path, + -1, STR_UNICODE); + + SSVAL(pdata,offset+20,uni_curroffset-offset); + + uni_curroffset += unilen; + offset += VERSION2_REFERRAL_SIZE; + } + /* add in the unexplained 22 (0x16) bytes at the end */ + memset(pdata+uni_curroffset,'\0',0x16); + return reply_size; +} + +static int setup_ver3_dfs_referral(char* pathname, char** ppdata, + struct junction_map* junction, + int consumedcnt, + BOOL self_referral) +{ + char* pdata = *ppdata; + + unsigned char uni_reqpath[1024]; + 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, -1, STR_TERMINATE); + + dump_data(10, (char *) uni_reqpath,reqpathlen); + + 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;ireferral_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; + } + + pdata = Realloc(pdata,reply_size); + if(pdata == NULL) { + DEBUG(0,("version3 referral setup: malloc failed for Realloc!\n")); + return -1; + } else + *ppdata = pdata; + + /* create the header */ + 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); + 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;ireferral_count;i++) { + struct referral* ref = &(junction->referral_list[i]); + int unilen; + + SSVAL(pdata,offset,3); /* version 3 */ + SSVAL(pdata,offset+2,VERSION3_REFERRAL_SIZE); + if(self_referral) + SSVAL(pdata,offset+4,1); + else + SSVAL(pdata,offset+4,0); + + SSVAL(pdata,offset+6,0); /* ref_flags :use path_consumed bytes? */ + 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, + -1, 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); + + uni_curroffset += unilen; + offset += VERSION3_REFERRAL_SIZE; + } + return reply_size; +} + +/****************************************************************** + * Set up the Dfs referral for the dfs pathname + ******************************************************************/ + +int setup_dfs_referral(connection_struct *orig_conn, char *pathname, int max_referral_level, char** ppdata) +{ + struct junction_map junction; + int consumedcnt; + BOOL self_referral = False; + pstring buf; + int reply_size = 0; + char *pathnamep = pathname; + + ZERO_STRUCT(junction); + + /* get the junction entry */ + if (!pathnamep) + return -1; + + /* Trim pathname sent by client so it begins with only one backslash. + Two backslashes confuse some dfs clients + */ + while (pathnamep[0] == '\\' && pathnamep[1] == '\\') + pathnamep++; + + pstrcpy(buf, pathnamep); + /* The following call can change cwd. */ + if (!get_referred_path(buf, &junction, &consumedcnt, &self_referral)) { + vfs_ChDir(orig_conn,orig_conn->connectpath); + 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;i3) + max_referral_level = 2; + + switch(max_referral_level) { + case 2: + reply_size = setup_ver2_dfs_referral(pathnamep, ppdata, &junction, + consumedcnt, self_referral); + SAFE_FREE(junction.referral_list); + break; + case 3: + reply_size = setup_ver3_dfs_referral(pathnamep, ppdata, &junction, + consumedcnt, self_referral); + SAFE_FREE(junction.referral_list); + break; + default: + DEBUG(0,("setup_dfs_referral: Invalid dfs referral version: %d\n", max_referral_level)); + return -1; + } + + DEBUG(10,("DFS Referral pdata:\n")); + dump_data(10,*ppdata,reply_size); + return reply_size; +} + +/********************************************************************** + The following functions are called by the NETDFS RPC pipe functions + **********************************************************************/ + +/********************************************************************** + Creates a junction structure from a Dfs pathname + **********************************************************************/ +BOOL create_junction(char* pathname, struct junction_map* jucn) +{ + struct dfs_path dp; + + parse_dfs_path(pathname,&dp); + + /* check if path is dfs : validate first token */ + if (local_machine && (!strequal(local_machine,dp.hostname))) { + + /* Hostname mismatch, check if one of our IP addresses */ + if (!ismyip(*interpret_addr2(dp.hostname))) { + DEBUG(4,("create_junction: Invalid hostname %s in dfs path %s\n", + dp.hostname, pathname)); + return False; + } + } + + /* Check for a non-DFS share */ + if(!lp_msdfs_root(lp_servicenumber(dp.servicename))) { + DEBUG(4,("create_junction: %s is not an msdfs root.\n", + dp.servicename)); + return False; + } + + pstrcpy(jucn->service_name,dp.servicename); + pstrcpy(jucn->volume_name,dp.reqpath); + return True; +} + +/********************************************************************** + Forms a valid Unix pathname from the junction + **********************************************************************/ + +static BOOL junction_to_local_path(struct junction_map* jucn, char* path, + int max_pathlen, connection_struct *conn) +{ + int snum; + pstring conn_path; + + if(!path || !jucn) + return False; + + 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 (!create_conn_struct(conn, snum, conn_path)) + return False; + + return True; +} + +BOOL create_msdfs_link(struct junction_map *jucn, BOOL exists) +{ + pstring path; + pstring msdfs_link; + connection_struct conns; + connection_struct *conn = &conns; + int i=0; + BOOL insert_comma = False; + BOOL ret = False; + + if(!junction_to_local_path(jucn, path, sizeof(path), conn)) + return False; + + /* form the msdfs_link contents */ + pstrcpy(msdfs_link, "msdfs:"); + for(i=0; ireferral_count; i++) { + char* refpath = jucn->referral_list[i].alternate_path; + + trim_char(refpath, '\\', '\\'); + if(*refpath == '\0') { + if (i == 0) + insert_comma = False; + continue; + } + if (i > 0 && insert_comma) + pstrcat(msdfs_link, ","); + + pstrcat(msdfs_link, refpath); + if (!insert_comma) + insert_comma = True; + + } + + DEBUG(5,("create_msdfs_link: Creating new msdfs link: %s -> %s\n", path, msdfs_link)); + + if(exists) + if(SMB_VFS_UNLINK(conn,path)!=0) + goto out; + + 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))); + goto out; + } + + + ret = True; + +out: + talloc_destroy( conn->mem_ctx ); + return ret; +} + +BOOL remove_msdfs_link(struct junction_map* jucn) +{ + pstring path; + connection_struct conns; + connection_struct *conn = &conns; + BOOL ret = False; + + if( junction_to_local_path(jucn, path, sizeof(path), conn) ) { + if( SMB_VFS_UNLINK(conn, path) == 0 ) + ret = True; + + talloc_destroy( conn->mem_ctx ); + } + + return ret; +} + +static BOOL form_junctions(int snum, struct junction_map* jucn, int* jn_count) +{ + int cnt = *jn_count; + DIR *dirp; + char* dname; + pstring connect_path; + char* service_name = lp_servicename(snum); + connection_struct conns; + connection_struct *conn = &conns; + struct referral *ref = NULL; + BOOL ret = False; + + pstrcpy(connect_path,lp_pathname(snum)); + + if(*connect_path == '\0') + return False; + + /* + * Fake up a connection struct for the VFS layer. + */ + + if (!create_conn_struct(conn, snum, connect_path)) + return False; + + /* form a junction for the msdfs root - convention + DO NOT REMOVE THIS: NT clients will not work with us + if this is not present + */ + pstrcpy(jucn[cnt].service_name, service_name); + jucn[cnt].volume_name[0] = '\0'; + jucn[cnt].referral_count = 1; + + ref = jucn[cnt].referral_list + = (struct referral*) malloc(sizeof(struct referral)); + if (jucn[cnt].referral_list == NULL) { + DEBUG(0, ("Malloc 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)); + *jn_count = ++cnt; + ret = True; + goto out; + } + + slprintf(ref->alternate_path, sizeof(pstring)-1, + "\\\\%s\\%s", local_machine, service_name); + cnt++; + + /* Now enumerate all dfs links */ + dirp = SMB_VFS_OPENDIR(conn, "."); + if(!dirp) + goto out; + + while((dname = vfs_readdirname(conn, dirp)) != NULL) { + if (is_msdfs_link(conn, dname, &(jucn[cnt].referral_list), + &(jucn[cnt].referral_count), NULL)) { + pstrcpy(jucn[cnt].service_name, service_name); + pstrcpy(jucn[cnt].volume_name, dname); + cnt++; + } + } + + SMB_VFS_CLOSEDIR(conn,dirp); + *jn_count = cnt; +out: + talloc_destroy(conn->mem_ctx); + return ret; +} + +int enum_msdfs_links(struct junction_map* jucn) +{ + int i=0; + int jn_count = 0; + + if(!lp_host_msdfs()) + return 0; + + for(i=0;i < lp_numservices();i++) { + if(lp_msdfs_root(i)) + form_junctions(i,jucn,&jn_count); + } + return jn_count; +} -- cgit From fddef6fc201ed127eaac737e725d1c2dd8c6926e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 11 Jun 2004 17:54:23 +0000 Subject: r1115: Fix for #1427. Catch bad path errors at the right point. Ensure all our pathname parsing is consistent. Jeremy. (This used to be commit 5e8237e306f0bb0e492f10fb6487938132899384) --- source3/smbd/msdfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index c66f0477a8..6c132897f9 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -65,7 +65,7 @@ static BOOL parse_dfs_path(char* pathname, struct dfs_path* pdp) DEBUG(10,("parse_dfs_path: servicename: %s\n",pdp->servicename)); /* rest is reqpath */ - check_path_syntax(pdp->reqpath, p+1); + check_path_syntax(pdp->reqpath, p+1,True); DEBUG(10,("parse_dfs_path: rest of the path: %s\n",pdp->reqpath)); return True; @@ -111,7 +111,7 @@ static BOOL parse_processed_dfs_path(char* pathname, struct dfs_path* pdp) DEBUG(10,("parse_processed_dfs_path: servicename: %s\n",pdp->servicename)); /* rest is reqpath */ - check_path_syntax(pdp->reqpath, p+1); + check_path_syntax(pdp->reqpath, p+1,True); DEBUG(10,("parse_processed_dfs_path: rest of the path: %s\n",pdp->reqpath)); return True; -- cgit From acf9d61421faa6c0055d57fdee7db300dc5431aa Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 7 Dec 2004 18:25:53 +0000 Subject: r4088: Get medieval on our ass about malloc.... :-). Take control of all our allocation functions so we can funnel through some well known functions. Should help greatly with malloc checking. HEAD patch to follow. Jeremy. (This used to be commit 620f2e608f70ba92f032720c031283d295c5c06a) --- source3/smbd/msdfs.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 6c132897f9..b5ae7486d3 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -189,7 +189,7 @@ static BOOL parse_symlink(char* buf,struct referral** preflist, DEBUG(10,("parse_symlink: count=%d\n", count)); - reflist = *preflist = (struct referral*) malloc(count * sizeof(struct referral)); + reflist = *preflist = SMB_MALLOC_ARRAY(struct referral, count); if(reflist == NULL) { DEBUG(0,("parse_symlink: Malloc failed!\n")); return False; @@ -417,7 +417,7 @@ static BOOL self_ref(char *pathname, struct junction_map *jucn, *self_referralp = True; jucn->referral_count = 1; - if((ref = (struct referral*) malloc(sizeof(struct referral))) == NULL) { + if((ref = SMB_MALLOC_P(struct referral)) == NULL) { DEBUG(0,("self_ref: malloc failed for referral\n")); return False; } @@ -503,7 +503,7 @@ BOOL get_referred_path(char *pathname, struct junction_map *jucn, self_referralp); jucn->referral_count = 1; - if ((ref = (struct referral*) malloc(sizeof(struct referral))) == NULL) { + if ((ref = SMB_MALLOC_P(struct referral)) == NULL) { DEBUG(0, ("malloc failed for referral\n")); goto out; } @@ -595,7 +595,7 @@ static int setup_ver2_dfs_referral(char* pathname, char** ppdata, /* add the unexplained 0x16 bytes */ reply_size += 0x16; - pdata = Realloc(pdata,reply_size); + pdata = SMB_REALLOC(pdata,reply_size); if(pdata == NULL) { DEBUG(0,("malloc failed for Realloc!\n")); return -1; @@ -676,7 +676,7 @@ static int setup_ver3_dfs_referral(char* pathname, char** ppdata, reply_size += (strlen(junction->referral_list[i].alternate_path)+1)*2; } - pdata = Realloc(pdata,reply_size); + pdata = SMB_REALLOC(pdata,reply_size); if(pdata == NULL) { DEBUG(0,("version3 referral setup: malloc failed for Realloc!\n")); return -1; @@ -962,8 +962,7 @@ static BOOL form_junctions(int snum, struct junction_map* jucn, int* jn_count) jucn[cnt].volume_name[0] = '\0'; jucn[cnt].referral_count = 1; - ref = jucn[cnt].referral_list - = (struct referral*) malloc(sizeof(struct referral)); + ref = jucn[cnt].referral_list = SMB_MALLOC_P(struct referral); if (jucn[cnt].referral_list == NULL) { DEBUG(0, ("Malloc failed!\n")); goto out; -- cgit From c1b9243c2892220b906df86d7b021d1bf18571b6 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Tue, 1 Feb 2005 20:43:14 +0000 Subject: r5165: BUG 2295: always use get_local_machine_name() rather than digging in the gloval variable 'local_machine' (This used to be commit 6a6e4af46a5c0a693a3dd9d558a4d1c1e5d72d95) --- source3/smbd/msdfs.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index b5ae7486d3..184dde1635 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -22,7 +22,6 @@ #include "includes.h" -extern fstring local_machine; extern uint32 global_client_caps; /********************************************************************** @@ -462,7 +461,7 @@ BOOL get_referred_path(char *pathname, struct junction_map *jucn, parse_dfs_path(pathname, &dp); /* Verify hostname in path */ - if (local_machine && (!strequal(local_machine, dp.hostname))) { + if ( !strequal(get_local_machine_name(), dp.hostname) ) { /* Hostname mismatch, check if one of our IP addresses */ if (!ismyip(*interpret_addr2(dp.hostname))) { DEBUG(3, ("get_referred_path: Invalid hostname %s in path %s\n", @@ -810,7 +809,7 @@ BOOL create_junction(char* pathname, struct junction_map* jucn) parse_dfs_path(pathname,&dp); /* check if path is dfs : validate first token */ - if (local_machine && (!strequal(local_machine,dp.hostname))) { + if ( !strequal(get_local_machine_name(),dp.hostname) ) { /* Hostname mismatch, check if one of our IP addresses */ if (!ismyip(*interpret_addr2(dp.hostname))) { @@ -978,7 +977,7 @@ static BOOL form_junctions(int snum, struct junction_map* jucn, int* jn_count) } slprintf(ref->alternate_path, sizeof(pstring)-1, - "\\\\%s\\%s", local_machine, service_name); + "\\\\%s\\%s", get_local_machine_name(), service_name); cnt++; /* Now enumerate all dfs links */ -- cgit From 27b84e5e5573cf922b77bdf935a715af2c4ce1c2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 24 Mar 2005 22:32:52 +0000 Subject: r6048: Split out the check_path_syntax into a findfirst/next/wildcard version. The semantics are different with wildcards. Jeremy. (This used to be commit f8b67159fc1c8224a7caf41409b2654846f34a2d) --- source3/smbd/msdfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 184dde1635..36baff8022 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -64,7 +64,7 @@ static BOOL parse_dfs_path(char* pathname, struct dfs_path* pdp) DEBUG(10,("parse_dfs_path: servicename: %s\n",pdp->servicename)); /* rest is reqpath */ - check_path_syntax(pdp->reqpath, p+1,True); + check_path_syntax(pdp->reqpath, p+1); DEBUG(10,("parse_dfs_path: rest of the path: %s\n",pdp->reqpath)); return True; @@ -110,7 +110,7 @@ static BOOL parse_processed_dfs_path(char* pathname, struct dfs_path* pdp) DEBUG(10,("parse_processed_dfs_path: servicename: %s\n",pdp->servicename)); /* rest is reqpath */ - check_path_syntax(pdp->reqpath, p+1,True); + check_path_syntax(pdp->reqpath, p+1); DEBUG(10,("parse_processed_dfs_path: rest of the path: %s\n",pdp->reqpath)); return True; -- cgit From a5433c4bf7a256880725173b96af5405c3c2eb9c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 25 Mar 2005 00:58:15 +0000 Subject: r6053: Fixup dfs path with the new wildcard parser code split out. Jeremy. (This used to be commit e831cef618d55c362e8d3a8a4c2b9f2ed7d4d7bd) --- source3/smbd/msdfs.c | 39 +++++++++++++++++---------------------- 1 file changed, 17 insertions(+), 22 deletions(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 36baff8022..2e4649efed 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -75,7 +75,7 @@ static BOOL parse_dfs_path(char* pathname, struct dfs_path* pdp) into the dfs_path structure **********************************************************************/ -static BOOL parse_processed_dfs_path(char* pathname, struct dfs_path* pdp) +static BOOL parse_processed_dfs_path(char* pathname, struct dfs_path* pdp, BOOL allow_wcards) { pstring pathname_local; char* p,*temp; @@ -110,7 +110,11 @@ static BOOL parse_processed_dfs_path(char* pathname, struct dfs_path* pdp) DEBUG(10,("parse_processed_dfs_path: servicename: %s\n",pdp->servicename)); /* rest is reqpath */ - check_path_syntax(pdp->reqpath, p+1); + if (allow_wcards) { + check_path_syntax_wcard(pdp->reqpath, p+1); + } else { + check_path_syntax(pdp->reqpath, p+1); + } DEBUG(10,("parse_processed_dfs_path: rest of the path: %s\n",pdp->reqpath)); return True; @@ -265,9 +269,7 @@ BOOL is_msdfs_link(connection_struct* conn, char * path, Used by other functions to decide if a dfs path is remote, and to get the list of referred locations for that remote path. -findfirst_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. +allow_wcards: Should we allow wildcards when parsing paths. self_referralp: clients expect a dfs referral for the same share when they request referrals for dfs roots on a server. @@ -279,7 +281,7 @@ should try the remaining path on the redirected server. static BOOL resolve_dfs_path(pstring dfspath, struct dfs_path* dp, connection_struct* conn, - BOOL findfirst_flag, + BOOL allow_wcards, struct referral** reflistpp, int* refcntp, BOOL* self_referralp, int* consumedcntp) { @@ -311,18 +313,11 @@ static BOOL resolve_dfs_path(pstring dfspath, struct dfs_path* dp, /* check if need to redirect */ if (is_msdfs_link(conn, localpath, reflistpp, refcntp, NULL)) { - if (findfirst_flag) { - DEBUG(6,("resolve_dfs_path (FindFirst) No redirection " - "for dfs link %s.\n", dfspath)); - return False; - } else { - DEBUG(6,("resolve_dfs_path: %s resolves to a valid Dfs link.\n", - dfspath)); - if (consumedcntp) - *consumedcntp = strlen(dfspath); - return True; - } - } + DEBUG(6,("resolve_dfs_path: %s resolves to a valid Dfs link.\n", dfspath)); + if (consumedcntp) + *consumedcntp = strlen(dfspath); + return True; + } /* redirect if any component in the path is a link */ pstrcpy(reqpath, dp->reqpath); @@ -366,15 +361,14 @@ static BOOL resolve_dfs_path(pstring dfspath, struct dfs_path* dp, If not, the pathname is converted to a tcon-relative local unix path *****************************************************************/ -BOOL dfs_redirect(pstring pathname, connection_struct* conn, - BOOL findfirst_flag) +BOOL dfs_redirect(pstring pathname, connection_struct* conn, BOOL allow_wcards) { struct dfs_path dp; if (!conn || !pathname) return False; - parse_processed_dfs_path(pathname, &dp); + parse_processed_dfs_path(pathname, &dp, allow_wcards); /* if dfs pathname for a non-dfs share, convert to tcon-relative path and return false */ @@ -386,7 +380,7 @@ BOOL dfs_redirect(pstring pathname, connection_struct* conn, if (!strequal(dp.servicename, lp_servicename(SNUM(conn)) )) return False; - if (resolve_dfs_path(pathname, &dp, conn, findfirst_flag, + if (resolve_dfs_path(pathname, &dp, conn, allow_wcards, NULL, NULL, NULL, NULL)) { DEBUG(3,("dfs_redirect: Redirecting %s\n", pathname)); return True; @@ -802,6 +796,7 @@ int setup_dfs_referral(connection_struct *orig_conn, char *pathname, int max_ref /********************************************************************** Creates a junction structure from a Dfs pathname **********************************************************************/ + BOOL create_junction(char* pathname, struct junction_map* jucn) { struct dfs_path dp; -- cgit From b751f95a256e0309f878ef93e6da9003fbde92d2 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 7 Apr 2005 19:43:19 +0000 Subject: r6237: fix my breakage of WinXP sp2 msdfs support. We did need the special case for RESOLVE_DFSPATH in the findfirst() code. Jeremy, please verify I haven't broken the allow_wcard code you added to resolve_dfs_path() (This used to be commit 29983398e2f7f1dc609d4d981e20f594918243bb) --- source3/smbd/msdfs.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 2e4649efed..c5e9d8d21c 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -269,7 +269,9 @@ BOOL is_msdfs_link(connection_struct* conn, char * path, Used by other functions to decide if a dfs path is remote, and to get the list of referred locations for that remote path. -allow_wcards: Should we allow wildcards when parsing paths. +findfirst_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. self_referralp: clients expect a dfs referral for the same share when they request referrals for dfs roots on a server. @@ -281,7 +283,7 @@ should try the remaining path on the redirected server. static BOOL resolve_dfs_path(pstring dfspath, struct dfs_path* dp, connection_struct* conn, - BOOL allow_wcards, + BOOL findfirst_flag, BOOL allow_wcards, struct referral** reflistpp, int* refcntp, BOOL* self_referralp, int* consumedcntp) { @@ -313,6 +315,12 @@ static BOOL resolve_dfs_path(pstring dfspath, struct dfs_path* dp, /* check if need to redirect */ if (is_msdfs_link(conn, localpath, reflistpp, refcntp, NULL)) { + if (findfirst_flag) { + DEBUG(6,("resolve_dfs_path (FindFirst) No redirection " + "for dfs link %s.\n", dfspath)); + return False; + } + DEBUG(6,("resolve_dfs_path: %s resolves to a valid Dfs link.\n", dfspath)); if (consumedcntp) *consumedcntp = strlen(dfspath); @@ -326,6 +334,7 @@ static BOOL resolve_dfs_path(pstring dfspath, struct dfs_path* dp, *p = '\0'; pstrcpy(localpath, reqpath); if (is_msdfs_link(conn, localpath, reflistpp, refcntp, NULL)) { + DEBUG(4, ("resolve_dfs_path: Redirecting %s because parent %s is dfs link\n", dfspath, localpath)); /* To find the path consumed, we truncate the original @@ -333,6 +342,7 @@ static BOOL resolve_dfs_path(pstring dfspath, struct dfs_path* dp, component. The length of the resulting string is the path consumed */ + if (consumedcntp) { char *q; pstring buf; @@ -361,7 +371,8 @@ static BOOL resolve_dfs_path(pstring dfspath, struct dfs_path* dp, If not, the pathname is converted to a tcon-relative local unix path *****************************************************************/ -BOOL dfs_redirect(pstring pathname, connection_struct* conn, BOOL allow_wcards) +BOOL dfs_redirect( pstring pathname, connection_struct* conn, + BOOL findfirst_flag, BOOL allow_wcards ) { struct dfs_path dp; @@ -380,7 +391,7 @@ BOOL dfs_redirect(pstring pathname, connection_struct* conn, BOOL allow_wcards) if (!strequal(dp.servicename, lp_servicename(SNUM(conn)) )) return False; - if (resolve_dfs_path(pathname, &dp, conn, allow_wcards, + if (resolve_dfs_path(pathname, &dp, conn, findfirst_flag, allow_wcards, NULL, NULL, NULL, NULL)) { DEBUG(3,("dfs_redirect: Redirecting %s\n", pathname)); return True; @@ -518,7 +529,7 @@ BOOL get_referred_path(char *pathname, struct junction_map *jucn, return False; /* If not remote & not a self referral, return False */ - if (!resolve_dfs_path(pathname, &dp, conn, False, + if (!resolve_dfs_path(pathname, &dp, conn, False, False, &jucn->referral_list, &jucn->referral_count, self_referralp, consumedcntp)) { if (!*self_referralp) { -- cgit From 1253a174f376f575819d0c84e8ee10ac43d18725 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 7 Apr 2005 22:37:03 +0000 Subject: r6242: after talking to jeremy, we can actually consolidate the 2 BOOL flags in dfs_redirect() down to one since they both are used in essentially the same context (from what we can tell). Tested Win98SE, WinXP sp 1 & 2, Win2k3 sp1, and WIn2k Sp4. All dfs operations still seem to work. (This used to be commit 59ffacf59c98f2f8277d76ec22712e438fd40618) --- source3/smbd/msdfs.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index c5e9d8d21c..b61a328080 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -282,8 +282,7 @@ should try the remaining path on the redirected server. *****************************************************************/ static BOOL resolve_dfs_path(pstring dfspath, struct dfs_path* dp, - connection_struct* conn, - BOOL findfirst_flag, BOOL allow_wcards, + connection_struct* conn, BOOL search_flag, struct referral** reflistpp, int* refcntp, BOOL* self_referralp, int* consumedcntp) { @@ -315,7 +314,7 @@ static BOOL resolve_dfs_path(pstring dfspath, struct dfs_path* dp, /* check if need to redirect */ if (is_msdfs_link(conn, localpath, reflistpp, refcntp, NULL)) { - if (findfirst_flag) { + if ( search_flag ) { DEBUG(6,("resolve_dfs_path (FindFirst) No redirection " "for dfs link %s.\n", dfspath)); return False; @@ -369,17 +368,20 @@ static BOOL resolve_dfs_path(pstring dfspath, struct dfs_path* dp, /***************************************************************** 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 + to searches. See resolve_dfs_path() and parse_processed_dfs_path() + for details. *****************************************************************/ -BOOL dfs_redirect( pstring pathname, connection_struct* conn, - BOOL findfirst_flag, BOOL allow_wcards ) +BOOL dfs_redirect( pstring pathname, connection_struct* conn, BOOL search_wcard_flag ) { struct dfs_path dp; if (!conn || !pathname) return False; - parse_processed_dfs_path(pathname, &dp, allow_wcards); + parse_processed_dfs_path(pathname, &dp, search_wcard_flag); /* if dfs pathname for a non-dfs share, convert to tcon-relative path and return false */ @@ -391,7 +393,7 @@ BOOL dfs_redirect( pstring pathname, connection_struct* conn, if (!strequal(dp.servicename, lp_servicename(SNUM(conn)) )) return False; - if (resolve_dfs_path(pathname, &dp, conn, findfirst_flag, allow_wcards, + if (resolve_dfs_path(pathname, &dp, conn, search_wcard_flag, NULL, NULL, NULL, NULL)) { DEBUG(3,("dfs_redirect: Redirecting %s\n", pathname)); return True; @@ -529,7 +531,7 @@ BOOL get_referred_path(char *pathname, struct junction_map *jucn, return False; /* If not remote & not a self referral, return False */ - if (!resolve_dfs_path(pathname, &dp, conn, False, False, + if (!resolve_dfs_path(pathname, &dp, conn, False, &jucn->referral_list, &jucn->referral_count, self_referralp, consumedcntp)) { if (!*self_referralp) { -- cgit From ff7e5c26733c933d0ed71616c39e2d931ad1e597 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 25 Jun 2005 03:03:44 +0000 Subject: r7893: Add in the extra parameters to opendir() to fix the large directory/insane app problem. Rev vfs version. Doesn't change the normal codepath. Jeremy. (This used to be commit 0f03a6bdcdbdf60da81e0aeffa84ac6e48fc6a04) --- source3/smbd/msdfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index b61a328080..be88a92414 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -989,7 +989,7 @@ static BOOL form_junctions(int snum, struct junction_map* jucn, int* jn_count) cnt++; /* Now enumerate all dfs links */ - dirp = SMB_VFS_OPENDIR(conn, "."); + dirp = SMB_VFS_OPENDIR(conn, ".", NULL, 0); if(!dirp) goto out; -- cgit From bf547ff1ad4120f898e89fd75ec94f577a0fc84d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 28 Jun 2005 19:25:48 +0000 Subject: r7981: MS-DFS tidyup patches from James Peach . Looking forward to the day he can commit these himself :-). Jeremy. (This used to be commit 12ff2978295a84fe6177af129c495a0021befacc) --- source3/smbd/msdfs.c | 61 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 25 deletions(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index be88a92414..fffe44ab60 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -20,6 +20,7 @@ */ +#define DBGC_CLASS DBGC_MSDFS #include "includes.h" extern uint32 global_client_caps; @@ -576,7 +577,9 @@ static int setup_ver2_dfs_referral(char* pathname, char** ppdata, requestedpathlen = rpcstr_push(uni_requestedpath, pathname, -1, STR_TERMINATE); - dump_data(10, (const char *) uni_requestedpath,requestedpathlen); + if (DEBUGLVL(10)) { + dump_data(0, (const char *) uni_requestedpath,requestedpathlen); + } DEBUG(10,("ref count = %u\n",junction->referral_count)); @@ -671,7 +674,9 @@ static int setup_ver3_dfs_referral(char* pathname, char** ppdata, reqpathlen = rpcstr_push(uni_reqpath, pathname, -1, STR_TERMINATE); - dump_data(10, (char *) uni_reqpath,reqpathlen); + if (DEBUGLVL(10)) { + dump_data(0, (char *) uni_reqpath,reqpathlen); + } uni_reqpathoffset1 = REFERRAL_HEADER_SIZE + VERSION3_REFERRAL_SIZE * junction->referral_count; uni_reqpathoffset2 = uni_reqpathoffset1 + reqpathlen; @@ -797,8 +802,11 @@ int setup_dfs_referral(connection_struct *orig_conn, char *pathname, int max_ref return -1; } - DEBUG(10,("DFS Referral pdata:\n")); - dump_data(10,*ppdata,reply_size); + if (DEBUGLVL(10)) { + DEBUGADD(0,("DFS Referral pdata:\n")); + dump_data(0,*ppdata,reply_size); + } + return reply_size; } @@ -937,29 +945,30 @@ BOOL remove_msdfs_link(struct junction_map* jucn) return ret; } -static BOOL form_junctions(int snum, struct junction_map* jucn, int* jn_count) +static int form_junctions(int snum, struct junction_map* jucn, int jn_remain) { - int cnt = *jn_count; + int cnt = 0; DIR *dirp; char* dname; pstring connect_path; char* service_name = lp_servicename(snum); - connection_struct conns; - connection_struct *conn = &conns; + connection_struct conn; struct referral *ref = NULL; - BOOL ret = False; + if (jn_remain <= 0) + return(0); + pstrcpy(connect_path,lp_pathname(snum)); if(*connect_path == '\0') - return False; + return 0; /* * Fake up a connection struct for the VFS layer. */ - if (!create_conn_struct(conn, snum, connect_path)) - return False; + if (!create_conn_struct(&conn, snum, connect_path)) + return 0; /* form a junction for the msdfs root - convention DO NOT REMOVE THIS: NT clients will not work with us @@ -979,22 +988,25 @@ static BOOL form_junctions(int snum, struct junction_map* jucn, int* jn_count) ref->ttl = REFERRAL_TTL; if (*lp_msdfs_proxy(snum) != '\0') { pstrcpy(ref->alternate_path, lp_msdfs_proxy(snum)); - *jn_count = ++cnt; - ret = True; goto out; } slprintf(ref->alternate_path, sizeof(pstring)-1, "\\\\%s\\%s", get_local_machine_name(), service_name); cnt++; - + /* Now enumerate all dfs links */ - dirp = SMB_VFS_OPENDIR(conn, ".", NULL, 0); + dirp = SMB_VFS_OPENDIR(&conn, ".", NULL, 0); if(!dirp) goto out; - while((dname = vfs_readdirname(conn, dirp)) != NULL) { - if (is_msdfs_link(conn, dname, &(jucn[cnt].referral_list), + while ((dname = vfs_readdirname(&conn, dirp)) != NULL) { + if (cnt >= jn_remain) { + SMB_VFS_CLOSEDIR(&conn,dirp); + DEBUG(2, ("ran out of MSDFS junction slots")); + goto out; + } + if (is_msdfs_link(&conn, dname, &(jucn[cnt].referral_list), &(jucn[cnt].referral_count), NULL)) { pstrcpy(jucn[cnt].service_name, service_name); pstrcpy(jucn[cnt].volume_name, dname); @@ -1002,14 +1014,13 @@ static BOOL form_junctions(int snum, struct junction_map* jucn, int* jn_count) } } - SMB_VFS_CLOSEDIR(conn,dirp); - *jn_count = cnt; + SMB_VFS_CLOSEDIR(&conn,dirp); out: - talloc_destroy(conn->mem_ctx); - return ret; + conn_free(&conn); + return cnt; } -int enum_msdfs_links(struct junction_map* jucn) +int enum_msdfs_links(struct junction_map* jucn, int jn_max) { int i=0; int jn_count = 0; @@ -1017,9 +1028,9 @@ int enum_msdfs_links(struct junction_map* jucn) if(!lp_host_msdfs()) return 0; - for(i=0;i < lp_numservices();i++) { + for(i=0;i < lp_numservices() && (jn_max - jn_count) > 0;i++) { if(lp_msdfs_root(i)) - form_junctions(i,jucn,&jn_count); + jn_count += form_junctions(i,jucn,jn_max - jn_count); } return jn_count; } -- cgit From 9365669a5988ea67764e051d626f664daf6596eb Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 22 Jul 2005 03:35:28 +0000 Subject: r8697: BUG 2908: make sure to allow for the trailing NULL (This used to be commit 3b505a824365222352be6a5ad2fb26586415a7a3) --- source3/smbd/msdfs.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index fffe44ab60..d0438b01af 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -251,8 +251,7 @@ BOOL is_msdfs_link(connection_struct* conn, char * path, if (S_ISLNK(sbufp->st_mode)) { /* open the link and read it */ - referral_len = SMB_VFS_READLINK(conn, path, referral, - sizeof(pstring)); + referral_len = SMB_VFS_READLINK(conn, path, referral, sizeof(pstring)-1); if (referral_len == -1) { DEBUG(0,("is_msdfs_link: Error reading msdfs link %s: %s\n", path, strerror(errno))); return False; -- cgit From dada62cf82f82c8a7eec053e2b0d29ec32293160 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 2 Aug 2005 20:50:16 +0000 Subject: r8948: Fix valgrind bad free bug found by Gunther. Jeremy. (This used to be commit ff291f4c97b76fb3e9b71a07752ca68c23011273) --- source3/smbd/msdfs.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index d0438b01af..e66c13ab93 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -128,10 +128,14 @@ static BOOL parse_processed_dfs_path(char* pathname, struct dfs_path* pdp, BOOL static BOOL create_conn_struct( connection_struct *conn, int snum, char *path) { + pstring connpath; + ZERO_STRUCTP(conn); conn->service = snum; - conn->connectpath = path; - pstring_sub(conn->connectpath , "%S", lp_servicename(snum)); + pstrcpy(connpath, path); + pstring_sub(connpath , "%S", lp_servicename(snum)); + + string_set(&conn->connectpath, connpath); /* needed for smbd_vfs_init() */ -- cgit From a4cdedcc085e0b9a94e6757a9b427af503ad6593 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 2 Aug 2005 20:59:20 +0000 Subject: r8950: Fix one more mem leak found by Gunther. Jeremy. (This used to be commit 547c6ee0a965b425719cdb834dd5d68a3a3e7117) --- source3/smbd/msdfs.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index e66c13ab93..0f63966a7d 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -948,7 +948,7 @@ BOOL remove_msdfs_link(struct junction_map* jucn) return ret; } -static int form_junctions(int snum, struct junction_map* jucn, int jn_remain) +static int form_junctions(TALLOC_CTX *ctx, int snum, struct junction_map* jucn, int jn_remain) { int cnt = 0; DIR *dirp; @@ -981,7 +981,7 @@ static int form_junctions(int snum, struct junction_map* jucn, int jn_remain) jucn[cnt].volume_name[0] = '\0'; jucn[cnt].referral_count = 1; - ref = jucn[cnt].referral_list = SMB_MALLOC_P(struct referral); + ref = jucn[cnt].referral_list = TALLOC_P(ctx, struct referral); if (jucn[cnt].referral_list == NULL) { DEBUG(0, ("Malloc failed!\n")); goto out; @@ -1023,7 +1023,7 @@ out: return cnt; } -int enum_msdfs_links(struct junction_map* jucn, int jn_max) +int enum_msdfs_links(TALLOC_CTX *ctx, struct junction_map* jucn, int jn_max) { int i=0; int jn_count = 0; @@ -1033,7 +1033,7 @@ int enum_msdfs_links(struct junction_map* jucn, int jn_max) for(i=0;i < lp_numservices() && (jn_max - jn_count) > 0;i++) { if(lp_msdfs_root(i)) - jn_count += form_junctions(i,jucn,jn_max - jn_count); + jn_count += form_junctions(ctx, i,jucn,jn_max - jn_count); } return jn_count; } -- cgit From abb81cfe2688dec69fe154d3abff8eff388c779c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 2 Aug 2005 23:24:32 +0000 Subject: r8959: Make msdfs code talloc based. Fix leaks. Jeremy. (This used to be commit 076023df8ea7c0f03baf8102e55d347e05542c7b) --- source3/smbd/msdfs.c | 329 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 195 insertions(+), 134 deletions(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 0f63966a7d..ade167f3c5 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -30,10 +30,10 @@ extern uint32 global_client_caps; into the dfs_path structure **********************************************************************/ -static BOOL parse_dfs_path(char* pathname, struct dfs_path* pdp) +static BOOL parse_dfs_path(char *pathname, struct dfs_path *pdp) { pstring pathname_local; - char* p,*temp; + char *p, *temp; pstrcpy(pathname_local,pathname); p = temp = pathname_local; @@ -46,8 +46,9 @@ static BOOL parse_dfs_path(char* pathname, struct dfs_path* pdp) /* now tokenize */ /* parse out hostname */ p = strchr_m(temp,'\\'); - if(p == NULL) + if(p == NULL) { return False; + } *p = '\0'; pstrcpy(pdp->hostname,temp); DEBUG(10,("parse_dfs_path: hostname: %s\n",pdp->hostname)); @@ -76,10 +77,10 @@ static BOOL parse_dfs_path(char* pathname, struct dfs_path* pdp) into the dfs_path structure **********************************************************************/ -static BOOL parse_processed_dfs_path(char* pathname, struct dfs_path* pdp, BOOL allow_wcards) +static BOOL parse_processed_dfs_path(char* pathname, struct dfs_path *pdp, BOOL allow_wcards) { pstring pathname_local; - char* p,*temp; + char *p,*temp; pstrcpy(pathname_local,pathname); p = temp = pathname_local; @@ -92,8 +93,9 @@ static BOOL parse_processed_dfs_path(char* pathname, struct dfs_path* pdp, BOOL /* now tokenize */ /* parse out hostname */ p = strchr_m(temp,'/'); - if(p == NULL) + if(p == NULL) { return False; + } *p = '\0'; pstrcpy(pdp->hostname,temp); DEBUG(10,("parse_processed_dfs_path: hostname: %s\n",pdp->hostname)); @@ -126,7 +128,7 @@ static BOOL parse_processed_dfs_path(char* pathname, struct dfs_path* pdp, BOOL Note this CHANGES CWD !!!! JRA. *********************************************************/ -static BOOL create_conn_struct( connection_struct *conn, int snum, char *path) +static BOOL create_conn_struct(connection_struct *conn, int snum, char *path) { pstring connpath; @@ -165,41 +167,48 @@ static BOOL create_conn_struct( connection_struct *conn, int snum, char *path) return True; } - /********************************************************************** Parse the contents of a symlink to verify if it is an msdfs referral A valid referral is of the form: msdfs:server1\share1,server2\share2 + talloc CTX can be NULL here if preflist and refcount pointers are null. **********************************************************************/ -static BOOL parse_symlink(char* buf,struct referral** preflist, - int* refcount) +static BOOL parse_symlink(TALLOC_CTX *ctx, char *buf, struct referral **preflist, int *refcount) { pstring temp; - char* prot; - char* alt_path[MAX_REFERRAL_COUNT]; - int count=0, i; - struct referral* reflist; + char *prot; + char *alt_path[MAX_REFERRAL_COUNT]; + int count = 0, i; + struct referral *reflist; pstrcpy(temp,buf); prot = strtok(temp,":"); - if (!strequal(prot, "msdfs")) + if (!strequal(prot, "msdfs")) { return False; + } /* No referral list requested. Just yes/no. */ - if (!preflist) + if (!preflist) { return True; + } + + if (!ctx) { + DEBUG(0,("parse_symlink: logic error. TALLOC_CTX should not be null.\n")); + return True; + } /* parse out the alternate paths */ - while(((alt_path[count] = strtok(NULL,",")) != NULL) && count %s\n",path,referral)); - if (parse_symlink(referral, reflistp, refcnt)) + if (parse_symlink(ctx, referral, reflistp, refcnt)) { return True; + } } return False; } @@ -282,13 +296,15 @@ they request referrals for dfs roots on a server. consumedcntp: how much of the dfs path is being redirected. the client should try the remaining path on the redirected server. - + +TALLOC_CTX can be NULL here if struct referral **reflistpp, int *refcntp +are also NULL. *****************************************************************/ -static BOOL resolve_dfs_path(pstring dfspath, struct dfs_path* dp, - connection_struct* conn, BOOL search_flag, - struct referral** reflistpp, int* refcntp, - BOOL* self_referralp, int* consumedcntp) +static BOOL resolve_dfs_path(TALLOC_CTX *ctx, pstring dfspath, struct dfs_path *dp, + connection_struct *conn, BOOL search_flag, + struct referral **reflistpp, int *refcntp, + BOOL *self_referralp, int *consumedcntp) { pstring localpath; int consumed_level = 1; @@ -302,6 +318,10 @@ static BOOL resolve_dfs_path(pstring dfspath, struct dfs_path* dp, return False; } + if (!ctx && (reflistpp || refcntp)) { + DEBUG(0,("resolve_dfs_path: logic error. TALLOC_CTX must not be NULL.\n")); + } + if (dp->reqpath[0] == '\0') { if (self_referralp) { DEBUG(6,("resolve_dfs_path: self-referral. returning False\n")); @@ -317,16 +337,17 @@ static BOOL resolve_dfs_path(pstring dfspath, struct dfs_path* dp, pstrcpy(localpath, dp->reqpath); /* check if need to redirect */ - if (is_msdfs_link(conn, localpath, reflistpp, refcntp, NULL)) { + if (is_msdfs_link(ctx, conn, localpath, reflistpp, refcntp, NULL)) { if ( search_flag ) { DEBUG(6,("resolve_dfs_path (FindFirst) No redirection " "for dfs link %s.\n", dfspath)); return False; } - + DEBUG(6,("resolve_dfs_path: %s resolves to a valid Dfs link.\n", dfspath)); - if (consumedcntp) + if (consumedcntp) { *consumedcntp = strlen(dfspath); + } return True; } @@ -336,8 +357,7 @@ static BOOL resolve_dfs_path(pstring dfspath, struct dfs_path* dp, while (p) { *p = '\0'; pstrcpy(localpath, reqpath); - if (is_msdfs_link(conn, localpath, reflistpp, refcntp, NULL)) { - + if (is_msdfs_link(ctx, conn, localpath, reflistpp, refcntp, NULL)) { DEBUG(4, ("resolve_dfs_path: Redirecting %s because parent %s is dfs link\n", dfspath, localpath)); /* To find the path consumed, we truncate the original @@ -353,8 +373,9 @@ static BOOL resolve_dfs_path(pstring dfspath, struct dfs_path* dp, trim_char(buf, '\0', '\\'); for (; consumed_level; consumed_level--) { q = strrchr_m(buf, '\\'); - if (q) + if (q) { *q = 0; + } } *consumedcntp = strlen(buf); DEBUG(10, ("resolve_dfs_path: Path consumed: %s (%d)\n", buf, *consumedcntp)); @@ -365,7 +386,7 @@ static BOOL resolve_dfs_path(pstring dfspath, struct dfs_path* dp, p = strrchr_m(reqpath, '/'); consumed_level++; } - + return False; } @@ -378,12 +399,13 @@ static BOOL resolve_dfs_path(pstring dfspath, struct dfs_path* dp, for details. *****************************************************************/ -BOOL dfs_redirect( pstring pathname, connection_struct* conn, BOOL search_wcard_flag ) +BOOL dfs_redirect( pstring pathname, connection_struct *conn, BOOL search_wcard_flag ) { struct dfs_path dp; - if (!conn || !pathname) + if (!conn || !pathname) { return False; + } parse_processed_dfs_path(pathname, &dp, search_wcard_flag); @@ -394,10 +416,11 @@ BOOL dfs_redirect( pstring pathname, connection_struct* conn, BOOL search_wcard_ return False; } - if (!strequal(dp.servicename, lp_servicename(SNUM(conn)) )) + if (!strequal(dp.servicename, lp_servicename(SNUM(conn)) )) { return False; + } - if (resolve_dfs_path(pathname, &dp, conn, search_wcard_flag, + if (resolve_dfs_path(NULL, pathname, &dp, conn, search_wcard_flag, NULL, NULL, NULL, NULL)) { DEBUG(3,("dfs_redirect: Redirecting %s\n", pathname)); return True; @@ -406,8 +429,7 @@ BOOL dfs_redirect( pstring pathname, connection_struct* conn, BOOL search_wcard_ /* Form non-dfs tcon-relative path */ pstrcpy(pathname, dp.reqpath); - DEBUG(3,("dfs_redirect: Path converted to non-dfs path %s\n", - pathname)); + DEBUG(3,("dfs_redirect: Path converted to non-dfs path %s\n", pathname)); return False; } @@ -418,16 +440,17 @@ BOOL dfs_redirect( pstring pathname, connection_struct* conn, BOOL search_wcard_ Return a self referral. **********************************************************************/ -static BOOL self_ref(char *pathname, struct junction_map *jucn, +static BOOL self_ref(TALLOC_CTX *ctx, char *pathname, struct junction_map *jucn, int *consumedcntp, BOOL *self_referralp) { struct referral *ref; - if (self_referralp != NULL) + if (self_referralp != NULL) { *self_referralp = True; + } jucn->referral_count = 1; - if((ref = SMB_MALLOC_P(struct referral)) == NULL) { + if((ref = TALLOC_P(ctx, struct referral)) == NULL) { DEBUG(0,("self_ref: malloc failed for referral\n")); return False; } @@ -436,18 +459,19 @@ static BOOL self_ref(char *pathname, struct junction_map *jucn, ref->proximity = 0; ref->ttl = REFERRAL_TTL; jucn->referral_list = ref; - if (consumedcntp) + if (consumedcntp) { *consumedcntp = strlen(pathname); + } return True; } /********************************************************************** Gets valid referrals for a dfs path and fills up the - junction_map structure + junction_map structure. **********************************************************************/ -BOOL get_referred_path(char *pathname, struct junction_map *jucn, +BOOL get_referred_path(TALLOC_CTX *ctx, char *pathname, struct junction_map *jucn, int *consumedcntp, BOOL *self_referralp) { struct dfs_path dp; @@ -459,15 +483,17 @@ BOOL get_referred_path(char *pathname, struct junction_map *jucn, BOOL ret = False; BOOL self_referral = False; - if (!pathname || !jucn) + if (!pathname || !jucn) { return False; + } ZERO_STRUCT(conns); - if (self_referralp) + if (self_referralp) { *self_referralp = False; - else + } else { self_referralp = &self_referral; + } parse_dfs_path(pathname, &dp); @@ -487,8 +513,9 @@ BOOL get_referred_path(char *pathname, struct junction_map *jucn, /* Verify the share is a dfs root */ snum = lp_servicenumber(jucn->service_name); if(snum < 0) { - if ((snum = find_service(jucn->service_name)) < 0) + if ((snum = find_service(jucn->service_name)) < 0) { return False; + } } if (!lp_msdfs_root(snum)) { @@ -508,34 +535,37 @@ BOOL get_referred_path(char *pathname, struct junction_map *jucn, struct referral* ref; - if (*lp_msdfs_proxy(snum) == '\0') - return self_ref(pathname, jucn, consumedcntp, - self_referralp); + if (*lp_msdfs_proxy(snum) == '\0') { + return self_ref(ctx, pathname, jucn, consumedcntp, self_referralp); + } jucn->referral_count = 1; - if ((ref = SMB_MALLOC_P(struct referral)) == NULL) { + if ((ref = TALLOC_P(ctx, struct referral)) == NULL) { DEBUG(0, ("malloc failed for referral\n")); goto out; } pstrcpy(ref->alternate_path, lp_msdfs_proxy(snum)); - if (dp.reqpath[0] != '\0') + if (dp.reqpath[0] != '\0') { pstrcat(ref->alternate_path, dp.reqpath); + } ref->proximity = 0; ref->ttl = REFERRAL_TTL; jucn->referral_list = ref; - if (consumedcntp) + if (consumedcntp) { *consumedcntp = strlen(pathname); + } ret = True; goto out; } pstrcpy(conn_path, lp_pathname(snum)); - if (!create_conn_struct(conn, snum, conn_path)) + if (!create_conn_struct(conn, snum, conn_path)) { return False; + } /* If not remote & not a self referral, return False */ - if (!resolve_dfs_path(pathname, &dp, conn, False, + if (!resolve_dfs_path(ctx, pathname, &dp, conn, False, &jucn->referral_list, &jucn->referral_count, self_referralp, consumedcntp)) { if (!*self_referralp) { @@ -546,7 +576,7 @@ BOOL get_referred_path(char *pathname, struct junction_map *jucn, /* if self_referral, fill up the junction map */ if (*self_referralp) { - if (self_ref(pathname, jucn, consumedcntp, self_referralp) == False) { + if (self_ref(ctx, pathname, jucn, consumedcntp, self_referralp) == False) { goto out; } } @@ -554,14 +584,16 @@ BOOL get_referred_path(char *pathname, struct junction_map *jucn, ret = True; out: - if (conn->mem_ctx) + + if (conn->mem_ctx) { talloc_destroy( conn->mem_ctx ); + } return ret; } -static int setup_ver2_dfs_referral(char* pathname, char** ppdata, - struct junction_map* junction, +static int setup_ver2_dfs_referral(char *pathname, char **ppdata, + struct junction_map *junction, int consumedcnt, BOOL self_referral) { @@ -611,8 +643,9 @@ static int setup_ver2_dfs_referral(char* pathname, char** ppdata, if(pdata == NULL) { DEBUG(0,("malloc failed for Realloc!\n")); return -1; - } else + } else { *ppdata = pdata; + } /* copy in the dfs requested paths.. required for offset calculations */ memcpy(pdata+uni_reqpathoffset1,uni_requestedpath,requestedpathlen); @@ -621,10 +654,11 @@ static int setup_ver2_dfs_referral(char* pathname, char** ppdata, /* create the header */ SSVAL(pdata,0,consumedcnt * 2); /* path consumed */ SSVAL(pdata,2,junction->referral_count); /* number of referral in this pkt */ - if(self_referral) + if(self_referral) { SIVAL(pdata,4,DFSREF_REFERRAL_SERVER | DFSREF_STORAGE_SERVER); - else + } else { SIVAL(pdata,4,DFSREF_STORAGE_SERVER); + } offset = 8; /* add the referral elements */ @@ -634,10 +668,11 @@ static int setup_ver2_dfs_referral(char* pathname, char** ppdata, SSVAL(pdata,offset,2); /* version 2 */ SSVAL(pdata,offset+2,VERSION2_REFERRAL_SIZE); - if(self_referral) + if(self_referral) { SSVAL(pdata,offset+4,1); - else + } else { SSVAL(pdata,offset+4,0); + } SSVAL(pdata,offset+6,0); /* ref_flags :use path_consumed bytes? */ SIVAL(pdata,offset+8,ref->proximity); SIVAL(pdata,offset+12,ref->ttl); @@ -658,8 +693,8 @@ static int setup_ver2_dfs_referral(char* pathname, char** ppdata, return reply_size; } -static int setup_ver3_dfs_referral(char* pathname, char** ppdata, - struct junction_map* junction, +static int setup_ver3_dfs_referral(char *pathname, char **ppdata, + struct junction_map *junction, int consumedcnt, BOOL self_referral) { @@ -694,16 +729,18 @@ static int setup_ver3_dfs_referral(char* pathname, char** ppdata, if(pdata == NULL) { DEBUG(0,("version3 referral setup: malloc failed for Realloc!\n")); return -1; - } else + } else { *ppdata = pdata; + } /* create the header */ SSVAL(pdata,0,consumedcnt * 2); /* path consumed */ SSVAL(pdata,2,junction->referral_count); /* number of referral */ - if(self_referral) + if(self_referral) { SIVAL(pdata,4,DFSREF_REFERRAL_SERVER | DFSREF_STORAGE_SERVER); - else + } else { SIVAL(pdata,4,DFSREF_STORAGE_SERVER); + } /* copy in the reqpaths */ memcpy(pdata+uni_reqpathoffset1,uni_reqpath,reqpathlen); @@ -716,10 +753,11 @@ static int setup_ver3_dfs_referral(char* pathname, char** ppdata, SSVAL(pdata,offset,3); /* version 3 */ SSVAL(pdata,offset+2,VERSION3_REFERRAL_SIZE); - if(self_referral) + if(self_referral) { SSVAL(pdata,offset+4,1); - else + } else { SSVAL(pdata,offset+4,0); + } SSVAL(pdata,offset+6,0); /* ref_flags :use path_consumed bytes? */ SIVAL(pdata,offset+8,ref->ttl); @@ -740,10 +778,10 @@ static int setup_ver3_dfs_referral(char* pathname, char** ppdata, } /****************************************************************** - * Set up the Dfs referral for the dfs pathname - ******************************************************************/ + Set up the Dfs referral for the dfs pathname +******************************************************************/ -int setup_dfs_referral(connection_struct *orig_conn, char *pathname, int max_referral_level, char** ppdata) +int setup_dfs_referral(connection_struct *orig_conn, char *pathname, int max_referral_level, char **ppdata) { struct junction_map junction; int consumedcnt; @@ -751,23 +789,32 @@ int setup_dfs_referral(connection_struct *orig_conn, char *pathname, int max_ref pstring buf; int reply_size = 0; char *pathnamep = pathname; + TALLOC_CTX *ctx; + + if (!(ctx=talloc_init("setup_dfs_referral"))) { + return -1; + } ZERO_STRUCT(junction); /* get the junction entry */ - if (!pathnamep) + if (!pathnamep) { + talloc_destroy(ctx); return -1; + } /* Trim pathname sent by client so it begins with only one backslash. Two backslashes confuse some dfs clients */ - while (pathnamep[0] == '\\' && pathnamep[1] == '\\') + while (pathnamep[0] == '\\' && pathnamep[1] == '\\') { pathnamep++; + } pstrcpy(buf, pathnamep); /* The following call can change cwd. */ - if (!get_referred_path(buf, &junction, &consumedcnt, &self_referral)) { + if (!get_referred_path(ctx, buf, &junction, &consumedcnt, &self_referral)) { vfs_ChDir(orig_conn,orig_conn->connectpath); + talloc_destroy(ctx); return -1; } vfs_ChDir(orig_conn,orig_conn->connectpath); @@ -786,30 +833,31 @@ int setup_dfs_referral(connection_struct *orig_conn, char *pathname, int max_ref /* create the referral depeding on version */ DEBUG(10,("max_referral_level :%d\n",max_referral_level)); - if(max_referral_level<2 || max_referral_level>3) + if(max_referral_level<2 || max_referral_level>3) { max_referral_level = 2; + } switch(max_referral_level) { case 2: reply_size = setup_ver2_dfs_referral(pathnamep, ppdata, &junction, consumedcnt, self_referral); - SAFE_FREE(junction.referral_list); break; case 3: reply_size = setup_ver3_dfs_referral(pathnamep, ppdata, &junction, consumedcnt, self_referral); - SAFE_FREE(junction.referral_list); break; default: DEBUG(0,("setup_dfs_referral: Invalid dfs referral version: %d\n", max_referral_level)); + talloc_destroy(ctx); return -1; } if (DEBUGLVL(10)) { - DEBUGADD(0,("DFS Referral pdata:\n")); - dump_data(0,*ppdata,reply_size); + DEBUGADD(0,("DFS Referral pdata:\n")); + dump_data(0,*ppdata,reply_size); } + talloc_destroy(ctx); return reply_size; } @@ -817,11 +865,11 @@ int setup_dfs_referral(connection_struct *orig_conn, char *pathname, int max_ref The following functions are called by the NETDFS RPC pipe functions **********************************************************************/ -/********************************************************************** +/********************************************************************* Creates a junction structure from a Dfs pathname - **********************************************************************/ +**********************************************************************/ -BOOL create_junction(char* pathname, struct junction_map* jucn) +BOOL create_junction(char *pathname, struct junction_map *jucn) { struct dfs_path dp; @@ -829,51 +877,52 @@ BOOL create_junction(char* pathname, struct junction_map* jucn) /* check if path is dfs : validate first token */ if ( !strequal(get_local_machine_name(),dp.hostname) ) { - - /* Hostname mismatch, check if one of our IP addresses */ - if (!ismyip(*interpret_addr2(dp.hostname))) { - DEBUG(4,("create_junction: Invalid hostname %s in dfs path %s\n", - dp.hostname, pathname)); - return False; - } - } + /* Hostname mismatch, check if one of our IP addresses */ + if (!ismyip(*interpret_addr2(dp.hostname))) { + DEBUG(4,("create_junction: Invalid hostname %s in dfs path %s\n", + dp.hostname, pathname)); + return False; + } + } - /* Check for a non-DFS share */ - if(!lp_msdfs_root(lp_servicenumber(dp.servicename))) { - DEBUG(4,("create_junction: %s is not an msdfs root.\n", - dp.servicename)); - return False; - } + /* Check for a non-DFS share */ + if(!lp_msdfs_root(lp_servicenumber(dp.servicename))) { + DEBUG(4,("create_junction: %s is not an msdfs root.\n", dp.servicename)); + return False; + } - pstrcpy(jucn->service_name,dp.servicename); - pstrcpy(jucn->volume_name,dp.reqpath); - return True; + pstrcpy(jucn->service_name,dp.servicename); + pstrcpy(jucn->volume_name,dp.reqpath); + return True; } /********************************************************************** Forms a valid Unix pathname from the junction **********************************************************************/ -static BOOL junction_to_local_path(struct junction_map* jucn, char* path, +static BOOL junction_to_local_path(struct junction_map *jucn, char *path, int max_pathlen, connection_struct *conn) { int snum; pstring conn_path; - if(!path || !jucn) + if(!path || !jucn) { return False; + } snum = lp_servicenumber(jucn->service_name); - if(snum < 0) + 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 (!create_conn_struct(conn, snum, conn_path)) + if (!create_conn_struct(conn, snum, conn_path)) { return False; + } return True; } @@ -888,8 +937,9 @@ BOOL create_msdfs_link(struct junction_map *jucn, BOOL exists) BOOL insert_comma = False; BOOL ret = False; - if(!junction_to_local_path(jucn, path, sizeof(path), conn)) + if(!junction_to_local_path(jucn, path, sizeof(path), conn)) { return False; + } /* form the msdfs_link contents */ pstrcpy(msdfs_link, "msdfs:"); @@ -898,24 +948,28 @@ BOOL create_msdfs_link(struct junction_map *jucn, BOOL exists) trim_char(refpath, '\\', '\\'); if(*refpath == '\0') { - if (i == 0) + if (i == 0) { insert_comma = False; + } continue; } - if (i > 0 && insert_comma) + if (i > 0 && insert_comma) { pstrcat(msdfs_link, ","); + } pstrcat(msdfs_link, refpath); - if (!insert_comma) + if (!insert_comma) { insert_comma = True; - + } } DEBUG(5,("create_msdfs_link: Creating new msdfs link: %s -> %s\n", path, msdfs_link)); - if(exists) - if(SMB_VFS_UNLINK(conn,path)!=0) + if(exists) { + if(SMB_VFS_UNLINK(conn,path)!=0) { goto out; + } + } if(SMB_VFS_SYMLINK(conn, msdfs_link, path) < 0) { DEBUG(1,("create_msdfs_link: symlink failed %s -> %s\nError: %s\n", @@ -931,7 +985,7 @@ out: return ret; } -BOOL remove_msdfs_link(struct junction_map* jucn) +BOOL remove_msdfs_link(struct junction_map *jucn) { pstring path; connection_struct conns; @@ -939,16 +993,16 @@ BOOL remove_msdfs_link(struct junction_map* jucn) BOOL ret = False; if( junction_to_local_path(jucn, path, sizeof(path), conn) ) { - if( SMB_VFS_UNLINK(conn, path) == 0 ) + if( SMB_VFS_UNLINK(conn, path) == 0 ) { ret = True; - + } talloc_destroy( conn->mem_ctx ); } - + return ret; } -static int form_junctions(TALLOC_CTX *ctx, int snum, struct junction_map* jucn, int jn_remain) +static int form_junctions(TALLOC_CTX *ctx, int snum, struct junction_map *jucn, int jn_remain) { int cnt = 0; DIR *dirp; @@ -958,20 +1012,23 @@ static int form_junctions(TALLOC_CTX *ctx, int snum, struct junction_map* jucn, connection_struct conn; struct referral *ref = NULL; - if (jn_remain <= 0) - return(0); + if (jn_remain <= 0) { + return 0; + } pstrcpy(connect_path,lp_pathname(snum)); - if(*connect_path == '\0') + if(*connect_path == '\0') { return 0; + } /* * Fake up a connection struct for the VFS layer. */ - if (!create_conn_struct(&conn, snum, connect_path)) + if (!create_conn_struct(&conn, snum, connect_path)) { return 0; + } /* form a junction for the msdfs root - convention DO NOT REMOVE THIS: NT clients will not work with us @@ -1000,8 +1057,9 @@ static int form_junctions(TALLOC_CTX *ctx, int snum, struct junction_map* jucn, /* Now enumerate all dfs links */ dirp = SMB_VFS_OPENDIR(&conn, ".", NULL, 0); - if(!dirp) + if(!dirp) { goto out; + } while ((dname = vfs_readdirname(&conn, dirp)) != NULL) { if (cnt >= jn_remain) { @@ -1009,8 +1067,8 @@ static int form_junctions(TALLOC_CTX *ctx, int snum, struct junction_map* jucn, DEBUG(2, ("ran out of MSDFS junction slots")); goto out; } - if (is_msdfs_link(&conn, dname, &(jucn[cnt].referral_list), - &(jucn[cnt].referral_count), NULL)) { + if (is_msdfs_link(ctx, &conn, dname, &jucn[cnt].referral_list, + &jucn[cnt].referral_count, NULL)) { pstrcpy(jucn[cnt].service_name, service_name); pstrcpy(jucn[cnt].volume_name, dname); cnt++; @@ -1018,22 +1076,25 @@ static int form_junctions(TALLOC_CTX *ctx, int snum, struct junction_map* jucn, } SMB_VFS_CLOSEDIR(&conn,dirp); + out: conn_free(&conn); return cnt; } -int enum_msdfs_links(TALLOC_CTX *ctx, struct junction_map* jucn, int jn_max) +int enum_msdfs_links(TALLOC_CTX *ctx, struct junction_map *jucn, int jn_max) { int i=0; int jn_count = 0; - if(!lp_host_msdfs()) + if(!lp_host_msdfs()) { return 0; + } for(i=0;i < lp_numservices() && (jn_max - jn_count) > 0;i++) { - if(lp_msdfs_root(i)) + if(lp_msdfs_root(i)) { jn_count += form_junctions(ctx, i,jucn,jn_max - jn_count); + } } return jn_count; } -- cgit From 78d6fa7277fadc77d80c400d3a38114a9e296d12 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 2 Aug 2005 23:55:38 +0000 Subject: r8963: Clean up the horrid "fake conn struct" part of MSDFS. Jeremy. (This used to be commit 14dd5ab632ff9abb9582e6484187c6ee1573cdd6) --- source3/smbd/msdfs.c | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index ade167f3c5..2b13e2a4b5 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -133,12 +133,11 @@ static BOOL create_conn_struct(connection_struct *conn, int snum, char *path) pstring connpath; ZERO_STRUCTP(conn); + conn->service = snum; pstrcpy(connpath, path); pstring_sub(connpath , "%S", lp_servicename(snum)); - string_set(&conn->connectpath, connpath); - /* needed for smbd_vfs_init() */ if ( (conn->mem_ctx=talloc_init("connection_struct")) == NULL ) { @@ -146,9 +145,11 @@ static BOOL create_conn_struct(connection_struct *conn, int snum, char *path) return False; } + string_set(&conn->connectpath, connpath); + if (!smbd_vfs_init(conn)) { DEBUG(0,("create_conn_struct: smbd_vfs_init failed.\n")); - talloc_destroy( conn->mem_ctx ); + conn_free_internal(conn); return False; } @@ -161,9 +162,10 @@ static BOOL create_conn_struct(connection_struct *conn, int snum, char *path) if (vfs_ChDir(conn,conn->connectpath) != 0) { DEBUG(3,("create_conn_struct: Can't ChDir to new conn path %s. Error was %s\n", conn->connectpath, strerror(errno) )); - talloc_destroy( conn->mem_ctx ); + conn_free_internal(conn); return False; } + return True; } @@ -477,7 +479,7 @@ BOOL get_referred_path(TALLOC_CTX *ctx, char *pathname, struct junction_map *juc struct dfs_path dp; struct connection_struct conns; - struct connection_struct* conn = &conns; + struct connection_struct *conn = &conns; pstring conn_path; int snum; BOOL ret = False; @@ -585,10 +587,7 @@ BOOL get_referred_path(TALLOC_CTX *ctx, char *pathname, struct junction_map *juc out: - if (conn->mem_ctx) { - talloc_destroy( conn->mem_ctx ); - } - + conn_free_internal(conn); return ret; } @@ -937,6 +936,8 @@ BOOL create_msdfs_link(struct junction_map *jucn, BOOL exists) BOOL insert_comma = False; BOOL ret = False; + ZERO_STRUCT(conns); + if(!junction_to_local_path(jucn, path, sizeof(path), conn)) { return False; } @@ -981,7 +982,8 @@ BOOL create_msdfs_link(struct junction_map *jucn, BOOL exists) ret = True; out: - talloc_destroy( conn->mem_ctx ); + + conn_free_internal(conn); return ret; } @@ -992,6 +994,8 @@ BOOL remove_msdfs_link(struct junction_map *jucn) connection_struct *conn = &conns; BOOL ret = False; + ZERO_STRUCT(conns); + if( junction_to_local_path(jucn, path, sizeof(path), conn) ) { if( SMB_VFS_UNLINK(conn, path) == 0 ) { ret = True; @@ -999,6 +1003,7 @@ BOOL remove_msdfs_link(struct junction_map *jucn) talloc_destroy( conn->mem_ctx ); } + conn_free_internal(conn); return ret; } @@ -1012,6 +1017,8 @@ static int form_junctions(TALLOC_CTX *ctx, int snum, struct junction_map *jucn, connection_struct conn; struct referral *ref = NULL; + ZERO_STRUCT(conn); + if (jn_remain <= 0) { return 0; } @@ -1078,7 +1085,8 @@ static int form_junctions(TALLOC_CTX *ctx, int snum, struct junction_map *jucn, SMB_VFS_CLOSEDIR(&conn,dirp); out: - conn_free(&conn); + + conn_free_internal(&conn); return cnt; } -- cgit From b67ba1e36b11aa140822f92b148438a1387d4d9d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 23 Aug 2005 21:29:37 +0000 Subject: r9545: (Hopefully the last) fixes for DIR -> SMB_STRUCT_DIR. Jeremy. (This used to be commit b242f278601e1a23c9116009482e802326d418f7) --- source3/smbd/msdfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 2b13e2a4b5..1e6306382a 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -1010,7 +1010,7 @@ BOOL remove_msdfs_link(struct junction_map *jucn) static int form_junctions(TALLOC_CTX *ctx, int snum, struct junction_map *jucn, int jn_remain) { int cnt = 0; - DIR *dirp; + SMB_STRUCT_DIR *dirp; char* dname; pstring connect_path; char* service_name = lp_servicename(snum); -- cgit From 6baec64a7370ff1871f0b806a623b1fc1a898acb Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 31 Oct 2005 20:11:58 +0000 Subject: r11420: Fix issue pointed out by Dina Fine . We can only tell at parse time from the wire if an incoming name has wildcards or not. If it's a mangled name and we demangle the demangled name may contain wildcard characters. Ensure these are ignored. Jeremy. (This used to be commit 4cd8e2a96b98ff711905e8c6f416b22440c16062) --- source3/smbd/msdfs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 1e6306382a..a4f371b18f 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -114,7 +114,8 @@ static BOOL parse_processed_dfs_path(char* pathname, struct dfs_path *pdp, BOOL /* rest is reqpath */ if (allow_wcards) { - check_path_syntax_wcard(pdp->reqpath, p+1); + BOOL path_contains_wcard; + check_path_syntax_wcard(pdp->reqpath, p+1, &path_contains_wcard); } else { check_path_syntax(pdp->reqpath, p+1); } -- cgit From fa4df827d0b7e6e280a1736fb45772ed27131e64 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 12 Dec 2005 18:21:59 +0000 Subject: r12194: Ensure that when we set a connection path we've canonicalized the name (must be abolute - start with /, must not end in /, must have ./ and ../ removed). Of course for realpath resolved paths this won't be the case but for others we need this name to be canonicalized. This name is going into the sharemode db for #3303 so needs to be in a normalized format. Jeremy. (This used to be commit 22e3300911809692b595f49e87d91e3111923e6a) --- source3/smbd/msdfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index a4f371b18f..1279fe185d 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -146,7 +146,7 @@ static BOOL create_conn_struct(connection_struct *conn, int snum, char *path) return False; } - string_set(&conn->connectpath, connpath); + set_conn_connectpath(conn, connpath); if (!smbd_vfs_init(conn)) { DEBUG(0,("create_conn_struct: smbd_vfs_init failed.\n")); -- cgit From 0af1500fc0bafe61019f1b2ab1d9e1d369221240 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 3 Feb 2006 22:19:41 +0000 Subject: r13316: Let the carnage begin.... Sync with trunk as off r13315 (This used to be commit 17e63ac4ed8325c0d44fe62b2442449f3298559f) --- source3/smbd/msdfs.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 1279fe185d..4f7858d985 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -1094,13 +1094,19 @@ out: int enum_msdfs_links(TALLOC_CTX *ctx, struct junction_map *jucn, int jn_max) { int i=0; + int sharecount = 0; int jn_count = 0; if(!lp_host_msdfs()) { return 0; } - for(i=0;i < lp_numservices() && (jn_max - jn_count) > 0;i++) { + /* Ensure all the usershares are loaded. */ + become_root(); + sharecount = load_usershare_shares(); + unbecome_root(); + + for(i=0;i < sharecount && (jn_max - jn_count) > 0;i++) { if(lp_msdfs_root(i)) { jn_count += form_junctions(ctx, i,jucn,jn_max - jn_count); } -- cgit From 894358a8f3e338b339b6c37233edef794b312087 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 7 Mar 2006 06:31:04 +0000 Subject: r13915: Fixed a very interesting class of realloc() bugs found by Coverity. realloc can return NULL in one of two cases - (1) the realloc failed, (2) realloc succeeded but the new size requested was zero, in which case this is identical to a free() call. The error paths dealing with these two cases should be different, but mostly weren't. Secondly the standard idiom for dealing with realloc when you know the new size is non-zero is the following : tmp = realloc(p, size); if (!tmp) { SAFE_FREE(p); return error; } else { p = tmp; } However, there were *many* *many* places in Samba where we were using the old (broken) idiom of : p = realloc(p, size) if (!p) { return error; } which will leak the memory pointed to by p on realloc fail. This commit (hopefully) fixes all these cases by moving to a standard idiom of : p = SMB_REALLOC(p, size) if (!p) { return error; } Where if the realloc returns null due to the realloc failing or size == 0 we *guarentee* that the storage pointed to by p has been freed. This allows me to remove a lot of code that was dealing with the standard (more verbose) method that required a tmp pointer. This is almost always what you want. When a realloc fails you never usually want the old memory, you want to free it and get into your error processing asap. For the 11 remaining cases where we really do need to keep the old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR, which can be used as follows : tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size); if (!tmp) { SAFE_FREE(p); return error; } else { p = tmp; } SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the pointer p, even on size == 0 or realloc fail. All this is done by a hidden extra argument to Realloc(), BOOL free_old_on_error which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR macros (and their array counterparts). It remains to be seen what this will do to our Coverity bug count :-). Jeremy. (This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0) --- source3/smbd/msdfs.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 4f7858d985..955197a425 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -643,9 +643,8 @@ static int setup_ver2_dfs_referral(char *pathname, char **ppdata, if(pdata == NULL) { DEBUG(0,("malloc failed for Realloc!\n")); return -1; - } else { - *ppdata = pdata; } + *ppdata = pdata; /* copy in the dfs requested paths.. required for offset calculations */ memcpy(pdata+uni_reqpathoffset1,uni_requestedpath,requestedpathlen); @@ -729,9 +728,8 @@ static int setup_ver3_dfs_referral(char *pathname, char **ppdata, if(pdata == NULL) { DEBUG(0,("version3 referral setup: malloc failed for Realloc!\n")); return -1; - } else { - *ppdata = pdata; } + *ppdata = pdata; /* create the header */ SSVAL(pdata,0,consumedcnt * 2); /* path consumed */ -- cgit From ed5095a4903abf41673b8d6c9fbd9a02b994a310 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 13 Mar 2006 18:56:26 +0000 Subject: r14336: Try and quieten coverity #53 and #54. Make it obvious we're using -1 as a special size_t case by casting. Jeremy. (This used to be commit 415530bd082bf351f5e4c1fd32408f123ed77f85) --- source3/smbd/msdfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 955197a425..257a6105c5 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -680,7 +680,7 @@ static int setup_ver2_dfs_referral(char *pathname, char **ppdata, SSVAL(pdata,offset+18,uni_reqpathoffset2-offset); /* copy referred path into current offset */ unilen = rpcstr_push(pdata+uni_curroffset, ref->alternate_path, - -1, STR_UNICODE); + (size_t)-1, STR_UNICODE); SSVAL(pdata,offset+20,uni_curroffset-offset); @@ -709,7 +709,7 @@ static int setup_ver3_dfs_referral(char *pathname, char **ppdata, DEBUG(10,("setting up version3 referral\n")); - reqpathlen = rpcstr_push(uni_reqpath, pathname, -1, STR_TERMINATE); + reqpathlen = rpcstr_push(uni_reqpath, pathname, (size_t)-1, STR_TERMINATE); if (DEBUGLVL(10)) { dump_data(0, (char *) uni_reqpath,reqpathlen); -- cgit From e6676a9a6928deb03c2a43a66c1245dd05d03e71 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 14 Mar 2006 17:21:30 +0000 Subject: r14387: Try and fix the coverity issues (#53, #54) with negative sink by ensuring all uses of rpcstr_push are consistent with a size_t dest size arg. Jeremy. (This used to be commit f65d7afe1977d9d85046732842f9643716c15088) --- source3/smbd/msdfs.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 257a6105c5..4606441c3a 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -609,7 +609,7 @@ static int setup_ver2_dfs_referral(char *pathname, char **ppdata, DEBUG(10,("setting up version2 referral\nRequested path:\n")); - requestedpathlen = rpcstr_push(uni_requestedpath, pathname, -1, + requestedpathlen = rpcstr_push(uni_requestedpath, pathname, sizeof(pstring), STR_TERMINATE); if (DEBUGLVL(10)) { @@ -680,7 +680,7 @@ static int setup_ver2_dfs_referral(char *pathname, char **ppdata, SSVAL(pdata,offset+18,uni_reqpathoffset2-offset); /* copy referred path into current offset */ unilen = rpcstr_push(pdata+uni_curroffset, ref->alternate_path, - (size_t)-1, STR_UNICODE); + sizeof(pstring), STR_UNICODE); SSVAL(pdata,offset+20,uni_curroffset-offset); @@ -709,7 +709,7 @@ static int setup_ver3_dfs_referral(char *pathname, char **ppdata, DEBUG(10,("setting up version3 referral\n")); - reqpathlen = rpcstr_push(uni_reqpath, pathname, (size_t)-1, STR_TERMINATE); + reqpathlen = rpcstr_push(uni_reqpath, pathname, sizeof(pstring), STR_TERMINATE); if (DEBUGLVL(10)) { dump_data(0, (char *) uni_reqpath,reqpathlen); @@ -764,7 +764,7 @@ static int setup_ver3_dfs_referral(char *pathname, char **ppdata, SSVAL(pdata,offset+14,uni_reqpathoffset2-offset); /* copy referred path into current offset */ unilen = rpcstr_push(pdata+uni_curroffset,ref->alternate_path, - -1, 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); -- cgit From 679e539655dcf37a719816f9c4e4cddfdf73379d Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 19 May 2006 14:00:12 +0000 Subject: r15712: BUG 3435: patch from volker to fix 'msdfs root = yes' in [homes] (This used to be commit 466478f07e6233b89f442660ad42ef7ee870ad48) --- source3/smbd/msdfs.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 4606441c3a..700aa2ae81 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -419,7 +419,10 @@ BOOL dfs_redirect( pstring pathname, connection_struct *conn, BOOL search_wcard_ return False; } - if (!strequal(dp.servicename, lp_servicename(SNUM(conn)) )) { + if ( !( strequal(dp.servicename, lp_servicename(SNUM(conn))) + || ( strequal(dp.servicename, HOMES_NAME) + && strequal(lp_servicename(SNUM(conn)), get_current_username()) )) ) + { return False; } -- cgit From a47ffac30d3363a93182584859ab273cfc3de2d3 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 13 Jun 2006 19:40:28 +0000 Subject: r16203: Fix potentially writing one result of strtok beyond the end of alt_path. Found by Klocwork, ID 653. Volker (This used to be commit 4cb8cf221f986b15de3ac608b173310c14248533) --- source3/smbd/msdfs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 700aa2ae81..55a6850478 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -203,7 +203,8 @@ static BOOL parse_symlink(TALLOC_CTX *ctx, char *buf, struct referral **preflist } /* parse out the alternate paths */ - while(((alt_path[count] = strtok(NULL,",")) != NULL) && count Date: Tue, 4 Jul 2006 13:49:17 +0000 Subject: r16797: Add msdfs proxy junctions in the netdfs rpc enumeration. Guenther (This used to be commit 6bf350895a648ef9b824c94b894e8d7a8989eb97) --- source3/smbd/msdfs.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 55a6850478..b22b5674d6 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -1058,6 +1058,7 @@ static int form_junctions(TALLOC_CTX *ctx, int snum, struct junction_map *jucn, ref->ttl = REFERRAL_TTL; if (*lp_msdfs_proxy(snum) != '\0') { pstrcpy(ref->alternate_path, lp_msdfs_proxy(snum)); + cnt++; goto out; } -- cgit From fbdcf2663b56007a438ac4f0d8d82436b1bfe688 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 11 Jul 2006 18:01:26 +0000 Subject: r16945: Sync trunk -> 3.0 for 3.0.24 code. Still need to do the upper layer directories but this is what everyone is waiting for.... Jeremy. (This used to be commit 9dafb7f48ca3e7af956b0a7d1720c2546fc4cfb8) --- source3/smbd/msdfs.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index b22b5674d6..69da4194fd 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -135,7 +135,6 @@ static BOOL create_conn_struct(connection_struct *conn, int snum, char *path) ZERO_STRUCTP(conn); - conn->service = snum; pstrcpy(connpath, path); pstring_sub(connpath , "%S", lp_servicename(snum)); @@ -145,6 +144,13 @@ static BOOL create_conn_struct(connection_struct *conn, int snum, char *path) DEBUG(0,("talloc_init(connection_struct) failed!\n")); return False; } + + if (!(conn->params = TALLOC_P(conn->mem_ctx, struct share_params))) { + DEBUG(0, ("TALLOC failed\n")); + return False; + } + + conn->params->service = snum; set_conn_connectpath(conn, connpath); -- cgit From 725d88b6d460f6495ee3117a8124d30115cf37fe Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 12 Jul 2006 03:02:33 +0000 Subject: r16968: The function parse_processed_dfs_path() is dependent on the fact that check_path_syntax() will convert '\\' characters to '/'. When POSIX pathnames have been selected this doesn't happen, so we must look for the unaltered separator of '\\' instead of the modified '/'. Stevef please check this with the CIFSFS MS-DFS code ! Jeremy (This used to be commit 883bb398e58f54ee79160487b49b79a4774ef939) --- source3/smbd/msdfs.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 69da4194fd..b698bc781d 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -73,26 +73,32 @@ static BOOL parse_dfs_path(char *pathname, struct dfs_path *pdp) } /********************************************************************** - Parse the pathname of the form /hostname/service/reqpath - into the dfs_path structure + Parse the pathname of the form /hostname/service/reqpath + into the dfs_path structure + This code is dependent on the fact that check_path_syntax() will + convert '\\' characters to '/'. + When POSIX pathnames have been selected this doesn't happen, so we + must look for the unaltered separator of '\\' instead of the modified '/'. + JRA. **********************************************************************/ static BOOL parse_processed_dfs_path(char* pathname, struct dfs_path *pdp, BOOL allow_wcards) { pstring pathname_local; char *p,*temp; + const char sepchar = lp_posix_pathnames() ? '\\' : '/'; pstrcpy(pathname_local,pathname); p = temp = pathname_local; ZERO_STRUCTP(pdp); - trim_char(temp,'/','/'); + trim_char(temp,sepchar,sepchar); DEBUG(10,("temp in parse_processed_dfs_path: .%s. after trimming \\'s\n",temp)); /* now tokenize */ /* parse out hostname */ - p = strchr_m(temp,'/'); + p = strchr_m(temp,sepchar); if(p == NULL) { return False; } @@ -102,7 +108,7 @@ static BOOL parse_processed_dfs_path(char* pathname, struct dfs_path *pdp, BOOL /* parse out servicename */ temp = p+1; - p = strchr_m(temp,'/'); + p = strchr_m(temp,sepchar); if(p == NULL) { pstrcpy(pdp->servicename,temp); pdp->reqpath[0] = '\0'; -- cgit From 430fa0eba08cbf180d83740a895a0018af1c7f21 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 31 Jul 2006 21:40:25 +0000 Subject: r17348: Some C++ warnings (This used to be commit ae6b9b34e59167e3958bfdb9997fa25340b9a0a3) --- source3/smbd/msdfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index b698bc781d..6891022264 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -655,7 +655,7 @@ static int setup_ver2_dfs_referral(char *pathname, char **ppdata, /* add the unexplained 0x16 bytes */ reply_size += 0x16; - pdata = SMB_REALLOC(pdata,reply_size); + pdata = (char *)SMB_REALLOC(pdata,reply_size); if(pdata == NULL) { DEBUG(0,("malloc failed for Realloc!\n")); return -1; @@ -740,7 +740,7 @@ static int setup_ver3_dfs_referral(char *pathname, char **ppdata, reply_size += (strlen(junction->referral_list[i].alternate_path)+1)*2; } - pdata = SMB_REALLOC(pdata,reply_size); + pdata = (char *)SMB_REALLOC(pdata,reply_size); if(pdata == NULL) { DEBUG(0,("version3 referral setup: malloc failed for Realloc!\n")); return -1; -- cgit From f569db1c06848b4205c141938e0d11359855673e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 2 Aug 2006 16:18:45 +0000 Subject: r17376: Fix bug #3985 - ensure in msdfs we check for our netbios aliases. Reported by Björn Jacke . Probably needs to be in 3.0.23b (if Björn approves of the fix). Jeremy. (This used to be commit e9e711fe37d9aec28b329dbfe2ad3ebfc1771825) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source3/smbd/msdfs.c | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 6891022264..2edad311ea 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -517,13 +517,10 @@ BOOL get_referred_path(TALLOC_CTX *ctx, char *pathname, struct junction_map *juc parse_dfs_path(pathname, &dp); /* Verify hostname in path */ - if ( !strequal(get_local_machine_name(), dp.hostname) ) { - /* Hostname mismatch, check if one of our IP addresses */ - if (!ismyip(*interpret_addr2(dp.hostname))) { - DEBUG(3, ("get_referred_path: Invalid hostname %s in path %s\n", - dp.hostname, pathname)); - return False; - } + if (!is_myname_or_ipaddr(dp.hostname)) { + DEBUG(3, ("get_referred_path: Invalid hostname %s in path %s\n", + dp.hostname, pathname)); + return False; } pstrcpy(jucn->service_name, dp.servicename); @@ -890,13 +887,10 @@ BOOL create_junction(char *pathname, struct junction_map *jucn) parse_dfs_path(pathname,&dp); /* check if path is dfs : validate first token */ - if ( !strequal(get_local_machine_name(),dp.hostname) ) { - /* Hostname mismatch, check if one of our IP addresses */ - if (!ismyip(*interpret_addr2(dp.hostname))) { - DEBUG(4,("create_junction: Invalid hostname %s in dfs path %s\n", - dp.hostname, pathname)); - return False; - } + if (!is_myname_or_ipaddr(dp.hostname)) { + DEBUG(4,("create_junction: Invalid hostname %s in dfs path %s\n", + dp.hostname, pathname)); + return False; } /* Check for a non-DFS share */ -- cgit From 11673dc07a137e911de3920f0ee6717b365f2ab4 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Tue, 8 Aug 2006 11:00:16 +0000 Subject: r17453: Fix msdfs RPC management (this broke with the autogenerated dfs rpcs). * Remove "unknown" from dfs_Enum (samba4 dfs IDL updates to follow). * When encountering an unsupported infolevel the rpc server must reply with a dfs_info_0 structure and WERR_OK (observed from w2k3 when talking to nt4). Guenther (This used to be commit f9bef1f08f7d2a4c95c28329ac73e8646f033998) --- source3/smbd/msdfs.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 2edad311ea..44415ddd16 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -901,6 +901,7 @@ BOOL create_junction(char *pathname, struct junction_map *jucn) pstrcpy(jucn->service_name,dp.servicename); pstrcpy(jucn->volume_name,dp.reqpath); + pstrcpy(jucn->comment, lp_comment(lp_servicenumber(dp.servicename))); return True; } -- cgit From 48e2a2bfb75cdc914345b498012e82331546f0c0 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 13 Sep 2006 16:28:25 +0000 Subject: r18481: Use pidl-generated server side code for dfs. (This used to be commit 3f337c104d42321595161d0283b39357df252a8e) --- source3/smbd/msdfs.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 44415ddd16..1f04356b4f 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -30,7 +30,7 @@ extern uint32 global_client_caps; into the dfs_path structure **********************************************************************/ -static BOOL parse_dfs_path(char *pathname, struct dfs_path *pdp) +static BOOL parse_dfs_path(const char *pathname, struct dfs_path *pdp) { pstring pathname_local; char *p, *temp; @@ -317,7 +317,8 @@ TALLOC_CTX can be NULL here if struct referral **reflistpp, int *refcntp are also NULL. *****************************************************************/ -static BOOL resolve_dfs_path(TALLOC_CTX *ctx, pstring dfspath, struct dfs_path *dp, +static BOOL resolve_dfs_path(TALLOC_CTX *ctx, const char *dfspath, + struct dfs_path *dp, connection_struct *conn, BOOL search_flag, struct referral **reflistpp, int *refcntp, BOOL *self_referralp, int *consumedcntp) @@ -459,7 +460,7 @@ BOOL dfs_redirect( pstring pathname, connection_struct *conn, BOOL search_wcard_ Return a self referral. **********************************************************************/ -static BOOL self_ref(TALLOC_CTX *ctx, char *pathname, struct junction_map *jucn, +static BOOL self_ref(TALLOC_CTX *ctx, const char *pathname, struct junction_map *jucn, int *consumedcntp, BOOL *self_referralp) { struct referral *ref; @@ -490,7 +491,7 @@ static BOOL self_ref(TALLOC_CTX *ctx, char *pathname, struct junction_map *jucn, junction_map structure. **********************************************************************/ -BOOL get_referred_path(TALLOC_CTX *ctx, char *pathname, struct junction_map *jucn, +BOOL get_referred_path(TALLOC_CTX *ctx, const char *pathname, struct junction_map *jucn, int *consumedcntp, BOOL *self_referralp) { struct dfs_path dp; @@ -880,7 +881,7 @@ int setup_dfs_referral(connection_struct *orig_conn, char *pathname, int max_ref Creates a junction structure from a Dfs pathname **********************************************************************/ -BOOL create_junction(char *pathname, struct junction_map *jucn) +BOOL create_junction(const char *pathname, struct junction_map *jucn) { struct dfs_path dp; -- cgit From 575845ccbeb2acc5dcb5133b80fd19b1d80169f2 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 30 Nov 2006 07:38:40 +0000 Subject: r19963: Add 'registry shares = yes' and registry key security descriptors. (This used to be commit 6cab254c49e07b11c170511ec613f0f33914c3e6) --- source3/smbd/msdfs.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 1f04356b4f..12fd333efe 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -1114,6 +1114,7 @@ int enum_msdfs_links(TALLOC_CTX *ctx, struct junction_map *jucn, int jn_max) /* Ensure all the usershares are loaded. */ become_root(); + load_registry_shares(); sharecount = load_usershare_shares(); unbecome_root(); -- cgit From db0ad252a0622dfac17d44ca646168df4c1c22e5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 12 Jan 2007 23:47:16 +0000 Subject: r20718: Sync up the filename path parsing changes from SAMBA_3_0_24. The only difference between the two trees now w.r.t file serving are the changes to smbd/open.c in this branch I need to review. Jeremy. (This used to be commit f4474edf6a0c71001dbd01429ef70bafad6abd74) --- source3/smbd/msdfs.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 12fd333efe..42595c033e 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -326,8 +326,8 @@ static BOOL resolve_dfs_path(TALLOC_CTX *ctx, const char *dfspath, pstring localpath; int consumed_level = 1; char *p; - BOOL bad_path = False; SMB_STRUCT_STAT sbuf; + NTSTATUS status; pstring reqpath; if (!dp || !conn) { @@ -349,7 +349,9 @@ static BOOL resolve_dfs_path(TALLOC_CTX *ctx, const char *dfspath, DEBUG(10,("resolve_dfs_path: Conn path = %s req_path = %s\n", conn->connectpath, dp->reqpath)); - unix_convert(dp->reqpath,conn,0,&bad_path,&sbuf); + status = unix_convert(conn, dp->reqpath, False, NULL, &sbuf); + /* Should we terminate on status != NT_STATUS_OK ???? */ + /* JRA... should we strlower the last component here.... ? */ pstrcpy(localpath, dp->reqpath); -- cgit From ffe646b1e67bc532fd954fc84cc85d21d1f4b8f8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 7 Feb 2007 22:20:31 +0000 Subject: r21226: Fix bug #4377 (rename of "foo" -> "Foo" fails). This is actually an interesting case as it exposed bad code in our DFS redirect module (that was where the bug was introduced). Caused by our turning on dfsroot be default. Jeremy. (This used to be commit 5fe25588f57ee59d70a66c755dfe70312e7afd08) --- source3/smbd/msdfs.c | 40 +++++++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 11 deletions(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 42595c033e..a5cdd8130d 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -261,7 +261,7 @@ static BOOL parse_symlink(TALLOC_CTX *ctx, char *buf, struct referral **preflist talloc CTX can be NULL here if reflistp and refcnt pointers are null. **********************************************************************/ -BOOL is_msdfs_link(TALLOC_CTX *ctx, connection_struct *conn, char *path, +BOOL is_msdfs_link(TALLOC_CTX *ctx, connection_struct *conn, const char *path, struct referral **reflistp, int *refcnt, SMB_STRUCT_STAT *sbufp) { @@ -317,11 +317,15 @@ TALLOC_CTX can be NULL here if struct referral **reflistpp, int *refcntp are also NULL. *****************************************************************/ -static BOOL resolve_dfs_path(TALLOC_CTX *ctx, const char *dfspath, - struct dfs_path *dp, - connection_struct *conn, BOOL search_flag, - struct referral **reflistpp, int *refcntp, - BOOL *self_referralp, int *consumedcntp) +static BOOL resolve_dfs_path(TALLOC_CTX *ctx, + const char *dfspath, + struct dfs_path *dp, + connection_struct *conn, + BOOL search_flag, + struct referral **reflistpp, + int *refcntp, + BOOL *self_referralp, + int *consumedcntp) { pstring localpath; int consumed_level = 1; @@ -349,12 +353,25 @@ static BOOL resolve_dfs_path(TALLOC_CTX *ctx, const char *dfspath, DEBUG(10,("resolve_dfs_path: Conn path = %s req_path = %s\n", conn->connectpath, dp->reqpath)); - status = unix_convert(conn, dp->reqpath, False, NULL, &sbuf); - /* Should we terminate on status != NT_STATUS_OK ???? */ + /* + * 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 + * unix_convert later in the codepath. + * If we needed to remember what we'd resolved in + * dp->reqpath (as the original code did) we'd + * pstrcpy(localhost, dp->reqpath) on any code + * path below that returns True - but I don't + * think this is needed. JRA. + */ - /* JRA... should we strlower the last component here.... ? */ pstrcpy(localpath, dp->reqpath); + status = unix_convert(conn, localpath, False, NULL, &sbuf); + if (!NT_STATUS_IS_OK(status)) { + return False; + } + /* check if need to redirect */ if (is_msdfs_link(ctx, conn, localpath, reflistpp, refcntp, NULL)) { if ( search_flag ) { @@ -371,7 +388,7 @@ static BOOL resolve_dfs_path(TALLOC_CTX *ctx, const char *dfspath, } /* redirect if any component in the path is a link */ - pstrcpy(reqpath, dp->reqpath); + pstrcpy(reqpath, localpath); p = strrchr_m(reqpath, '/'); while (p) { *p = '\0'; @@ -448,9 +465,10 @@ BOOL dfs_redirect( pstring pathname, connection_struct *conn, BOOL search_wcard_ return True; } else { DEBUG(3,("dfs_redirect: Not redirecting %s.\n", pathname)); - + /* Form non-dfs tcon-relative path */ pstrcpy(pathname, dp.reqpath); + DEBUG(3,("dfs_redirect: Path converted to non-dfs path %s\n", pathname)); return False; } -- cgit From 5920d870cfc6be3c5bbc65ab63a6e63d1d7286f4 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 8 Feb 2007 21:57:41 +0000 Subject: r21251: Okay, after Jeremy has kindly tested this, check it in :-) Attached find a workaround that works for me. This is not the "correct" fix, to me it seems our DFS referral marshalling is broken. Vista requests level 4, we reply with level 2, and Vista seems not to like that. If we reply with level 3 it seems more happy. Needs more work! Volker (This used to be commit 4c3a9135629415086698da28596f68f7a9db9133) --- source3/smbd/msdfs.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index a5cdd8130d..c24cdcc708 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -865,9 +865,13 @@ int setup_dfs_referral(connection_struct *orig_conn, char *pathname, int max_ref /* create the referral depeding on version */ DEBUG(10,("max_referral_level :%d\n",max_referral_level)); - if(max_referral_level<2 || max_referral_level>3) { + + if (max_referral_level < 2) { max_referral_level = 2; } + if (max_referral_level > 3) { + max_referral_level = 3; + } switch(max_referral_level) { case 2: -- cgit From 7b2c2e415543aaee13193be1bd11706f2528c692 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 7 Mar 2007 22:12:58 +0000 Subject: r21754: Volker is completely correct. There's no need for the RESOLVE_DFSPATH macros and their varients any more. Fix reporting profile bug with all error returns. Jeremy. (This used to be commit cdf0fdb1049fd68b46885cbea887dc0e595fa524) --- source3/smbd/msdfs.c | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index c24cdcc708..f06bb3b044 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -3,6 +3,7 @@ Version 3.0 MSDfs services for Samba Copyright (C) Shirish Kalele 2000 + Copyright (C) Jeremy Allison 2007 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -435,7 +436,7 @@ static BOOL resolve_dfs_path(TALLOC_CTX *ctx, for details. *****************************************************************/ -BOOL dfs_redirect( pstring pathname, connection_struct *conn, BOOL search_wcard_flag ) +static BOOL dfs_redirect( connection_struct *conn, pstring pathname, BOOL search_wcard_flag ) { struct dfs_path dp; @@ -1149,3 +1150,32 @@ int enum_msdfs_links(TALLOC_CTX *ctx, struct junction_map *jucn, int jn_max) } return jn_count; } + +/****************************************************************************** + Core function to resolve a dfs pathname. +******************************************************************************/ + +BOOL resolve_dfspath(connection_struct *conn, BOOL dfs_pathnames, pstring name) +{ + if (dfs_pathnames && lp_host_msdfs() && lp_msdfs_root(SNUM(conn)) && + dfs_redirect(conn, name, False)) { + return False; /* Pathname didn't resolve. */ + } + return True; +} + +/****************************************************************************** + Core function to resolve a dfs pathname possibly containing a wildcard. + This function is identical to the above except for the BOOL param to + dfs_redirect but I need this to be separate so it's really clear when + we're allowing wildcards and when we're not. JRA. +******************************************************************************/ + +BOOL resolve_dfspath_wcard(connection_struct *conn, BOOL dfs_pathnames, pstring name) +{ + if (dfs_pathnames && lp_host_msdfs() && lp_msdfs_root(SNUM(conn)) && + dfs_redirect(conn, name, True)) { + return False; /* Pathname didn't resolve. */ + } + return True; +} -- cgit From 286d8554aa4547629b7e5d1349be4550885b76a2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 7 Mar 2007 23:58:40 +0000 Subject: r21756: An invarient the dfs code depended on for POSIX paths is no longer true, so fix it. Jeremy. (This used to be commit 698159c0ee8d9adb3b56231c0c8ad2ddebd5be11) --- source3/smbd/msdfs.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index f06bb3b044..25c9c59497 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -78,16 +78,13 @@ static BOOL parse_dfs_path(const char *pathname, struct dfs_path *pdp) into the dfs_path structure This code is dependent on the fact that check_path_syntax() will convert '\\' characters to '/'. - When POSIX pathnames have been selected this doesn't happen, so we - must look for the unaltered separator of '\\' instead of the modified '/'. - JRA. **********************************************************************/ static BOOL parse_processed_dfs_path(char* pathname, struct dfs_path *pdp, BOOL allow_wcards) { pstring pathname_local; char *p,*temp; - const char sepchar = lp_posix_pathnames() ? '\\' : '/'; + const char sepchar = '/'; pstrcpy(pathname_local,pathname); p = temp = pathname_local; -- cgit From c4ea95fd303ae6fd51d125e756c1289f440adbd2 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 8 Mar 2007 02:51:41 +0000 Subject: r21758: Fix a very specific dfs bug when passing in POSIX pathnames. When we're working out how much we've consumed we need to backtrack by either a '/' or '\\' component, as both are valid separators. Jeremy. (This used to be commit 1722ea20db2d531f92fb18fa5783f09258727c64) --- source3/smbd/msdfs.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 25c9c59497..c34512493f 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -92,7 +92,7 @@ static BOOL parse_processed_dfs_path(char* pathname, struct dfs_path *pdp, BOOL ZERO_STRUCTP(pdp); trim_char(temp,sepchar,sepchar); - DEBUG(10,("temp in parse_processed_dfs_path: .%s. after trimming \\'s\n",temp)); + DEBUG(10,("temp in parse_processed_dfs_path: .%s. after trimming /'s\n",temp)); /* now tokenize */ /* parse out hostname */ @@ -401,12 +401,15 @@ static BOOL resolve_dfs_path(TALLOC_CTX *ctx, */ if (consumedcntp) { - char *q; pstring buf; pstrcpy(buf, dfspath); trim_char(buf, '\0', '\\'); for (; consumed_level; consumed_level--) { - q = strrchr_m(buf, '\\'); + char *q, *q1, *q2; + /* Either '\\' or '/' may be a separator. */ + q1 = strrchr_m(buf, '\\'); + q2 = strrchr_m(buf, '/'); + q = MAX(q1,q2); if (q) { *q = 0; } -- cgit From db32963181843c0ae425ee5a3bb517010ab0bf0f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 8 Mar 2007 03:00:42 +0000 Subject: r21759: Fix the same bug in a more elegant way, strrchr_m is an expensive call.... Jeremy. (This used to be commit 321a136dbce1a0532f123ea79ecb91f987b9a286) --- source3/smbd/msdfs.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index c34512493f..861588e6b7 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -331,6 +331,7 @@ static BOOL resolve_dfs_path(TALLOC_CTX *ctx, SMB_STRUCT_STAT sbuf; NTSTATUS status; pstring reqpath; + pstring local_dfspath; if (!dp || !conn) { DEBUG(1,("resolve_dfs_path: NULL dfs_path* or NULL connection_struct*!\n")); @@ -385,6 +386,12 @@ static BOOL resolve_dfs_path(TALLOC_CTX *ctx, return True; } + /* Prepare to test only for '/' components in the given path, + * so replace all '\\' characters with '/'. */ + + pstrcpy(local_dfspath, dfspath); + string_replace(local_dfspath, '\\', '/'); + /* redirect if any component in the path is a link */ pstrcpy(reqpath, localpath); p = strrchr_m(reqpath, '/'); @@ -402,14 +409,12 @@ static BOOL resolve_dfs_path(TALLOC_CTX *ctx, if (consumedcntp) { pstring buf; - pstrcpy(buf, dfspath); - trim_char(buf, '\0', '\\'); + pstrcpy(buf, local_dfspath); + trim_char(buf, '\0', '/'); for (; consumed_level; consumed_level--) { - char *q, *q1, *q2; - /* Either '\\' or '/' may be a separator. */ - q1 = strrchr_m(buf, '\\'); - q2 = strrchr_m(buf, '/'); - q = MAX(q1,q2); + char *q; + /* We made sure only '/' may be a separator above. */ + q = strrchr_m(buf, '/'); if (q) { *q = 0; } -- cgit From 24cdd7c73389c9eed981313973df2c3595222781 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 12 Mar 2007 17:55:24 +0000 Subject: r21800: Check-in the DFS rewrite. I am still testing this but it works from smbclient and Windows, and I am promising to support and fix both client and server code moving forward. Still need to test the RPC admin support but I haven't changed that code. Jeremy. (This used to be commit 7a7862c01d07796ef206b255c676ad7dc2cc42fc) --- source3/smbd/msdfs.c | 829 ++++++++++++++++++++++++++++----------------------- 1 file changed, 459 insertions(+), 370 deletions(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 861588e6b7..ae2009ad38 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -1,7 +1,7 @@ /* Unix SMB/Netbios implementation. Version 3.0 - MSDfs services for Samba + MSDFS services for Samba Copyright (C) Shirish Kalele 2000 Copyright (C) Jeremy Allison 2007 @@ -27,105 +27,142 @@ extern uint32 global_client_caps; /********************************************************************** - Parse the pathname of the form \hostname\service\reqpath - into the dfs_path structure - **********************************************************************/ + Parse a DFS pathname of the form \hostname\service\reqpath + into the dfs_path structure. + If POSIX pathnames is true, the pathname may also be of the + form /hostname/service/reqpath. + We cope with either here. + + Unfortunately, due to broken clients who might set the + SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES bit and then + send a local path, we have to cope with that too.... + + JRA. +**********************************************************************/ -static BOOL parse_dfs_path(const char *pathname, struct dfs_path *pdp) +static NTSTATUS parse_dfs_path(const char *pathname, + BOOL allow_wcards, + struct dfs_path *pdp, + BOOL *ppath_contains_wcard) { pstring pathname_local; - char *p, *temp; + char *p,*temp; + NTSTATUS status = NT_STATUS_OK; + char sepchar; + + ZERO_STRUCTP(pdp); pstrcpy(pathname_local,pathname); p = temp = pathname_local; - ZERO_STRUCTP(pdp); + pdp->posix_path = (lp_posix_pathnames() && *pathname == '/'); - trim_char(temp,'\\','\\'); - DEBUG(10,("temp in parse_dfs_path: .%s. after trimming \\'s\n",temp)); + sepchar = pdp->posix_path ? '/' : '\\'; - /* now tokenize */ - /* parse out hostname */ - p = strchr_m(temp,'\\'); - if(p == NULL) { - return False; - } - *p = '\0'; - pstrcpy(pdp->hostname,temp); - DEBUG(10,("parse_dfs_path: hostname: %s\n",pdp->hostname)); + if (*pathname != sepchar) { + DEBUG(10,("parse_dfs_path: path %s doesn't start with %c\n", + pathname, sepchar )); + /* + * Possibly client sent a local path by mistake. + * Try and convert to a local path. + */ - /* parse out servicename */ - temp = p+1; - p = strchr_m(temp,'\\'); - if(p == NULL) { - pstrcpy(pdp->servicename,temp); - pdp->reqpath[0] = '\0'; - return True; + pdp->hostname[0] = '\0'; + pdp->servicename[0] = '\0'; + + /* 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", + temp)); + goto local_path; } - *p = '\0'; - pstrcpy(pdp->servicename,temp); - DEBUG(10,("parse_dfs_path: servicename: %s\n",pdp->servicename)); - /* rest is reqpath */ - check_path_syntax(pdp->reqpath, p+1); + trim_char(temp,sepchar,sepchar); - DEBUG(10,("parse_dfs_path: rest of the path: %s\n",pdp->reqpath)); - return True; -} + DEBUG(10,("parse_dfs_path: temp = |%s| after trimming %c's\n", + temp, sepchar)); -/********************************************************************** - Parse the pathname of the form /hostname/service/reqpath - into the dfs_path structure - This code is dependent on the fact that check_path_syntax() will - convert '\\' characters to '/'. - **********************************************************************/ + /* Now tokenize. */ + /* Parse out hostname. */ + p = strchr_m(temp,sepchar); + if(p == NULL) { + DEBUG(10,("parse_dfs_path: can't parse hostname from path %s\n", + temp)); + /* + * Possibly client sent a local path by mistake. + * Try and convert to a local path. + */ -static BOOL parse_processed_dfs_path(char* pathname, struct dfs_path *pdp, BOOL allow_wcards) -{ - pstring pathname_local; - char *p,*temp; - const char sepchar = '/'; + pdp->hostname[0] = '\0'; + pdp->servicename[0] = '\0'; - pstrcpy(pathname_local,pathname); - p = temp = pathname_local; + p = temp; + DEBUG(10,("parse_dfs_path: trying to convert %s to a local path\n", + temp)); + goto local_path; + } + *p = '\0'; + fstrcpy(pdp->hostname,temp); + DEBUG(10,("parse_dfs_path: hostname: %s\n",pdp->hostname)); - ZERO_STRUCTP(pdp); + /* 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", + pdp->hostname, temp)); + /* + * Possibly client sent a local path by mistake. + * Try and convert to a local path. + */ - trim_char(temp,sepchar,sepchar); - DEBUG(10,("temp in parse_processed_dfs_path: .%s. after trimming /'s\n",temp)); + pdp->hostname[0] = '\0'; + pdp->servicename[0] = '\0'; - /* now tokenize */ - /* parse out hostname */ - p = strchr_m(temp,sepchar); - if(p == NULL) { - return False; + p = temp; + DEBUG(10,("parse_dfs_path: trying to convert %s to a local path\n", + temp)); + goto local_path; } - *p = '\0'; - pstrcpy(pdp->hostname,temp); - DEBUG(10,("parse_processed_dfs_path: hostname: %s\n",pdp->hostname)); - /* parse out servicename */ + /* Parse out servicename. */ temp = p+1; p = strchr_m(temp,sepchar); if(p == NULL) { - pstrcpy(pdp->servicename,temp); + fstrcpy(pdp->servicename,temp); pdp->reqpath[0] = '\0'; - return True; + return NT_STATUS_OK; } *p = '\0'; - pstrcpy(pdp->servicename,temp); - DEBUG(10,("parse_processed_dfs_path: servicename: %s\n",pdp->servicename)); + fstrcpy(pdp->servicename,temp); + DEBUG(10,("parse_dfs_path: servicename: %s\n",pdp->servicename)); + + p++; + + local_path: - /* rest is reqpath */ - if (allow_wcards) { - BOOL path_contains_wcard; - check_path_syntax_wcard(pdp->reqpath, p+1, &path_contains_wcard); + *ppath_contains_wcard = False; + + /* Rest is reqpath. */ + if (pdp->posix_path) { + status = check_path_syntax_posix(pdp->reqpath, p); } else { - check_path_syntax(pdp->reqpath, p+1); + if (allow_wcards) { + status = check_path_syntax_wcard(pdp->reqpath, p, ppath_contains_wcard); + } else { + status = check_path_syntax(pdp->reqpath, p); + } } - DEBUG(10,("parse_processed_dfs_path: rest of the path: %s\n",pdp->reqpath)); - return True; + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10,("parse_dfs_path: '%s' failed with %s\n", + p, nt_errstr(status) )); + return status; + } + + DEBUG(10,("parse_dfs_path: rest of the path: %s\n",pdp->reqpath)); + return NT_STATUS_OK; } /******************************************************** @@ -133,7 +170,7 @@ static BOOL parse_processed_dfs_path(char* pathname, struct dfs_path *pdp, BOOL Note this CHANGES CWD !!!! JRA. *********************************************************/ -static BOOL create_conn_struct(connection_struct *conn, int snum, char *path) +static BOOL create_conn_struct(connection_struct *conn, int snum, const char *path) { pstring connpath; @@ -143,19 +180,19 @@ static BOOL create_conn_struct(connection_struct *conn, int snum, char *path) pstring_sub(connpath , "%S", lp_servicename(snum)); /* needed for smbd_vfs_init() */ - - if ( (conn->mem_ctx=talloc_init("connection_struct")) == NULL ) { - DEBUG(0,("talloc_init(connection_struct) failed!\n")); - return False; - } - if (!(conn->params = TALLOC_P(conn->mem_ctx, struct share_params))) { + if ((conn->mem_ctx=talloc_init("connection_struct")) == NULL) { + DEBUG(0,("talloc_init(connection_struct) failed!\n")); + return False; + } + + if (!(conn->params = TALLOC_ZERO_P(conn->mem_ctx, struct share_params))) { DEBUG(0, ("TALLOC failed\n")); return False; } - + conn->params->service = snum; - + set_conn_connectpath(conn, connpath); if (!smbd_vfs_init(conn)) { @@ -182,11 +219,27 @@ static BOOL create_conn_struct(connection_struct *conn, int snum, char *path) /********************************************************************** Parse the contents of a symlink to verify if it is an msdfs referral - A valid referral is of the form: msdfs:server1\share1,server2\share2 - talloc CTX can be NULL here if preflist and refcount pointers are null. + A valid referral is of the form: + + msdfs:server1\share1,server2\share2 + msdfs:server1\share1\pathname,server2\share2\pathname + msdfs:server1/share1,server2/share2 + msdfs:server1/share1/pathname,server2/share2/pathname. + + Note that the alternate paths returned here must be of the canonicalized + form: + + \server\share or + \server\share\path\to\file, + + even in posix path mode. This is because we have no knowledge if the + server we're referring to understands posix paths. **********************************************************************/ -static BOOL parse_symlink(TALLOC_CTX *ctx, char *buf, struct referral **preflist, int *refcount) +static BOOL parse_msdfs_symlink(TALLOC_CTX *ctx, + char *target, + struct referral **preflist, + int *refcount) { pstring temp; char *prot; @@ -194,45 +247,28 @@ static BOOL parse_symlink(TALLOC_CTX *ctx, char *buf, struct referral **preflist int count = 0, i; struct referral *reflist; - pstrcpy(temp,buf); - + pstrcpy(temp,target); prot = strtok(temp,":"); - if (!strequal(prot, "msdfs")) { - return False; - } - - /* No referral list requested. Just yes/no. */ - if (!preflist) { - return True; - } - - if (!ctx) { - DEBUG(0,("parse_symlink: logic error. TALLOC_CTX should not be null.\n")); - return True; - } - /* parse out the alternate paths */ while((countst_mode)) { - /* open the link and read it */ - referral_len = SMB_VFS_READLINK(conn, path, referral, sizeof(pstring)-1); - if (referral_len == -1) { - DEBUG(0,("is_msdfs_link: Error reading msdfs link %s: %s\n", path, strerror(errno))); - return False; - } + if (!S_ISLNK(sbufp->st_mode)) { + DEBUG(5,("is_msdfs_link: %s is not a link.\n",path)); + return False; + } - referral[referral_len] = '\0'; - DEBUG(5,("is_msdfs_link: %s -> %s\n",path,referral)); - if (parse_symlink(ctx, referral, reflistp, refcnt)) { - return True; - } + /* open the link and read it */ + referral_len = SMB_VFS_READLINK(conn, path, link_target, sizeof(pstring)-1); + if (referral_len == -1) { + DEBUG(0,("is_msdfs_link: Error reading msdfs link %s: %s\n", + path, strerror(errno))); + return False; } - return False; + link_target[referral_len] = '\0'; + + DEBUG(5,("is_msdfs_link: %s -> %s\n",path, link_target)); + + if (!strnequal(link_target, "msdfs:", 6)) { + return False; + } + return True; } /***************************************************************** Used by other functions to decide if a dfs path is remote, -and to get the list of referred locations for that remote path. + and to get the list of referred locations for that remote path. -findfirst_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. - -self_referralp: clients expect a dfs referral for the same share when -they request referrals for dfs roots on a server. + 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. -consumedcntp: how much of the dfs path is being redirected. the client -should try the remaining path on the redirected server. + consumedcntp: how much of the dfs path is being redirected. the client + should try the remaining path on the redirected server. -TALLOC_CTX can be NULL here if struct referral **reflistpp, int *refcntp -are also NULL. + If this returns NT_STATUS_PATH_NOT_COVERED the contents of the msdfs + link redirect are in targetpath. *****************************************************************/ -static BOOL resolve_dfs_path(TALLOC_CTX *ctx, - const char *dfspath, - struct dfs_path *dp, - connection_struct *conn, - BOOL search_flag, - struct referral **reflistpp, - int *refcntp, - BOOL *self_referralp, - int *consumedcntp) +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) { - pstring localpath; - int consumed_level = 1; - char *p; + char *p = NULL; + char *q = NULL; SMB_STRUCT_STAT sbuf; NTSTATUS status; - pstring reqpath; - pstring local_dfspath; - - if (!dp || !conn) { - DEBUG(1,("resolve_dfs_path: NULL dfs_path* or NULL connection_struct*!\n")); - return False; - } - - if (!ctx && (reflistpp || refcntp)) { - DEBUG(0,("resolve_dfs_path: logic error. TALLOC_CTX must not be NULL.\n")); - } - - if (dp->reqpath[0] == '\0') { - if (self_referralp) { - DEBUG(6,("resolve_dfs_path: self-referral. returning False\n")); - *self_referralp = True; - } - return False; - } + pstring localpath; + pstring canon_dfspath; /* Canonicalized dfs path. (only '/' components). */ - DEBUG(10,("resolve_dfs_path: Conn path = %s req_path = %s\n", conn->connectpath, dp->reqpath)); + 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 @@ -364,151 +376,188 @@ static BOOL resolve_dfs_path(TALLOC_CTX *ctx, * think this is needed. JRA. */ - pstrcpy(localpath, dp->reqpath); - - status = unix_convert(conn, localpath, False, NULL, &sbuf); + pstrcpy(localpath, pdp->reqpath); + status = unix_convert(conn, localpath, search_flag, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { - return False; + return status; } - /* check if need to redirect */ - if (is_msdfs_link(ctx, conn, localpath, reflistpp, refcntp, NULL)) { - if ( search_flag ) { - DEBUG(6,("resolve_dfs_path (FindFirst) No redirection " + /* Optimization - check if we can redirect the whole path. */ + + if (is_msdfs_link(conn, localpath, targetpath, NULL)) { + if (search_flag) { + DEBUG(6,("dfs_path_lookup (FindFirst) No redirection " "for dfs link %s.\n", dfspath)); - return False; + return NT_STATUS_OK; } - DEBUG(6,("resolve_dfs_path: %s resolves to a valid Dfs link.\n", dfspath)); + DEBUG(6,("dfs_path_lookup: %s resolves to a " + "valid dfs link %s.\n", dfspath, targetpath)); + if (consumedcntp) { *consumedcntp = strlen(dfspath); } - return True; + return NT_STATUS_PATH_NOT_COVERED; } /* Prepare to test only for '/' components in the given path, - * so replace all '\\' characters with '/'. */ + * so if a Windows path replace all '\\' characters with '/'. + * For a POSIX DFS path we know all separators are already '/'. */ - pstrcpy(local_dfspath, dfspath); - string_replace(local_dfspath, '\\', '/'); + pstrcpy(canon_dfspath, dfspath); + if (!pdp->posix_path) { + string_replace(canon_dfspath, '\\', '/'); + } + + /* + * Redirect if any component in the path is a link. + * 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. + */ + + p = strrchr_m(localpath, '/'); + if (consumedcntp) { + q = strrchr_m(canon_dfspath, '/'); + } - /* redirect if any component in the path is a link */ - pstrcpy(reqpath, localpath); - p = strrchr_m(reqpath, '/'); while (p) { *p = '\0'; - pstrcpy(localpath, reqpath); - if (is_msdfs_link(ctx, conn, localpath, reflistpp, refcntp, NULL)) { - DEBUG(4, ("resolve_dfs_path: Redirecting %s because parent %s is dfs link\n", dfspath, localpath)); - - /* To find the path consumed, we truncate the original - DFS pathname passed to use to remove the last - component. The length of the resulting string is - the path consumed - */ - + if (q) { + *q = '\0'; + } + + if (is_msdfs_link(conn, localpath, targetpath, NULL)) { + DEBUG(4, ("dfs_path_lookup: Redirecting %s because " + "parent %s is dfs link\n", dfspath, localpath)); + if (consumedcntp) { - pstring buf; - pstrcpy(buf, local_dfspath); - trim_char(buf, '\0', '/'); - for (; consumed_level; consumed_level--) { - char *q; - /* We made sure only '/' may be a separator above. */ - q = strrchr_m(buf, '/'); - if (q) { - *q = 0; - } - } - *consumedcntp = strlen(buf); - DEBUG(10, ("resolve_dfs_path: Path consumed: %s (%d)\n", buf, *consumedcntp)); + *consumedcntp = strlen(canon_dfspath); + DEBUG(10, ("dfs_path_lookup: Path consumed: %s " + "(%d)\n", canon_dfspath, *consumedcntp)); } - - return True; + + return NT_STATUS_PATH_NOT_COVERED; + } + + /* Step back on the filesystem. */ + p = strrchr_m(localpath, '/'); + + if (consumedcntp) { + /* And in the canonicalized dfs path. */ + q = strrchr_m(canon_dfspath, '/'); } - p = strrchr_m(reqpath, '/'); - consumed_level++; } - return False; + return NT_STATUS_OK; } /***************************************************************** - 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 - to searches. See resolve_dfs_path() and parse_processed_dfs_path() - for details. + 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 + to searches. See resolve_dfs_path() and parse_dfs_path_XX() + for details. + + This function can return NT_STATUS_OK, meaning use the returned path as-is + (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. *****************************************************************/ -static BOOL dfs_redirect( connection_struct *conn, pstring pathname, BOOL search_wcard_flag ) +static NTSTATUS dfs_redirect( connection_struct *conn, + pstring dfs_path, + BOOL search_wcard_flag, + BOOL *ppath_contains_wcard) { + NTSTATUS status; struct dfs_path dp; + pstring targetpath; - if (!conn || !pathname) { - return False; + status = parse_dfs_path(dfs_path, search_wcard_flag, &dp, ppath_contains_wcard); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + if (dp.reqpath[0] == '\0') { + DEBUG(5,("dfs_redirect: self-referral.\n")); + return NT_STATUS_OK; } - parse_processed_dfs_path(pathname, &dp, search_wcard_flag); + /* If dfs pathname for a non-dfs share, convert to tcon-relative + path and return OK */ - /* if dfs pathname for a non-dfs share, convert to tcon-relative - path and return false */ if (!lp_msdfs_root(SNUM(conn))) { - pstrcpy(pathname, dp.reqpath); - return False; + pstrcpy(dfs_path, dp.reqpath); + 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()) )) ) - { - return False; + + /* If it looked like a local path (zero hostname/servicename) + * just treat as a tcon-relative path. */ + + if (dp.hostname[0] == '\0' && dp.servicename[0] == '\0') { + pstrcpy(dfs_path, dp.reqpath); + return NT_STATUS_OK; } - if (resolve_dfs_path(NULL, pathname, &dp, conn, search_wcard_flag, - NULL, NULL, NULL, NULL)) { - DEBUG(3,("dfs_redirect: Redirecting %s\n", pathname)); - return True; - } else { - DEBUG(3,("dfs_redirect: Not redirecting %s.\n", pathname)); + if (!( strequal(dp.servicename, lp_servicename(SNUM(conn))) + || (strequal(dp.servicename, HOMES_NAME) + && strequal(lp_servicename(SNUM(conn)), get_current_username()) )) ) { - /* Form non-dfs tcon-relative path */ - pstrcpy(pathname, dp.reqpath); + /* The given sharename doesn't match this connection. */ - DEBUG(3,("dfs_redirect: Path converted to non-dfs path %s\n", pathname)); - return False; + return NT_STATUS_OBJECT_PATH_NOT_FOUND; + } + + status = dfs_path_lookup(conn, dfs_path, &dp, + search_wcard_flag, NULL, targetpath); + 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)); + } else { + DEBUG(10,("dfs_redirect: dfs_path_lookup failed for %s with %s\n", + dfs_path, nt_errstr(status) )); + } + return status; } - /* never reached */ + DEBUG(3,("dfs_redirect: Not redirecting %s.\n", dfs_path)); + + /* Form non-dfs tcon-relative path */ + pstrcpy(dfs_path, dp.reqpath); + + DEBUG(3,("dfs_redirect: Path converted to non-dfs path %s\n", dfs_path)); + return NT_STATUS_OK; } /********************************************************************** Return a self referral. **********************************************************************/ -static BOOL self_ref(TALLOC_CTX *ctx, const char *pathname, struct junction_map *jucn, - int *consumedcntp, BOOL *self_referralp) +static BOOL self_ref(TALLOC_CTX *ctx, + const char *dfs_path, + struct junction_map *jucn, + int *consumedcntp, + BOOL *self_referralp) { struct referral *ref; - if (self_referralp != NULL) { - *self_referralp = True; - } + *self_referralp = True; jucn->referral_count = 1; - if((ref = TALLOC_P(ctx, struct referral)) == NULL) { - DEBUG(0,("self_ref: malloc failed for referral\n")); + if((ref = TALLOC_ZERO_P(ctx, struct referral)) == NULL) { + DEBUG(0,("self_ref: talloc failed for referral\n")); return False; } - pstrcpy(ref->alternate_path,pathname); + pstrcpy(ref->alternate_path,dfs_path); ref->proximity = 0; ref->ttl = REFERRAL_TTL; jucn->referral_list = ref; - if (consumedcntp) { - *consumedcntp = strlen(pathname); - } - + *consumedcntp = strlen(dfs_path); return True; } @@ -517,40 +566,39 @@ static BOOL self_ref(TALLOC_CTX *ctx, const char *pathname, struct junction_map junction_map structure. **********************************************************************/ -BOOL get_referred_path(TALLOC_CTX *ctx, const char *pathname, struct junction_map *jucn, - int *consumedcntp, BOOL *self_referralp) +BOOL get_referred_path(TALLOC_CTX *ctx, + const char *dfs_path, + struct junction_map *jucn, + int *consumedcntp, + BOOL *self_referralp) { - struct dfs_path dp; - struct connection_struct conns; struct connection_struct *conn = &conns; + struct dfs_path dp; pstring conn_path; + pstring targetpath; int snum; + NTSTATUS status; BOOL ret = False; - BOOL self_referral = False; - - if (!pathname || !jucn) { - return False; - } + BOOL dummy; ZERO_STRUCT(conns); - if (self_referralp) { - *self_referralp = False; - } else { - self_referralp = &self_referral; - } + *self_referralp = False; - parse_dfs_path(pathname, &dp); + status = parse_dfs_path(dfs_path, False, &dp, &dummy); + if (!NT_STATUS_IS_OK(status)) { + return False; + } /* Verify hostname in path */ if (!is_myname_or_ipaddr(dp.hostname)) { DEBUG(3, ("get_referred_path: Invalid hostname %s in path %s\n", - dp.hostname, pathname)); + dp.hostname, dfs_path)); return False; } - pstrcpy(jucn->service_name, dp.servicename); + fstrcpy(jucn->service_name, dp.servicename); pstrcpy(jucn->volume_name, dp.reqpath); /* Verify the share is a dfs root */ @@ -562,8 +610,8 @@ BOOL get_referred_path(TALLOC_CTX *ctx, const char *pathname, struct junction_ma } if (!lp_msdfs_root(snum)) { - DEBUG(3,("get_referred_path: .%s. in dfs path %s is not a dfs root.\n", - dp.servicename, pathname)); + DEBUG(3,("get_referred_path: |%s| in dfs path %s is not a dfs root.\n", + dp.servicename, dfs_path)); goto out; } @@ -575,15 +623,23 @@ BOOL get_referred_path(TALLOC_CTX *ctx, const char *pathname, struct junction_ma */ if (dp.reqpath[0] == '\0') { - - struct referral* ref; + struct referral *ref; if (*lp_msdfs_proxy(snum) == '\0') { - return self_ref(ctx, pathname, jucn, consumedcntp, self_referralp); + return self_ref(ctx, + dfs_path, + jucn, + consumedcntp, + self_referralp); } + /* + * It's an msdfs proxy share. Redirect to + * the configured target share. + */ + jucn->referral_count = 1; - if ((ref = TALLOC_P(ctx, struct referral)) == NULL) { + if ((ref = TALLOC_ZERO_P(ctx, struct referral)) == NULL) { DEBUG(0, ("malloc failed for referral\n")); goto out; } @@ -595,9 +651,7 @@ BOOL get_referred_path(TALLOC_CTX *ctx, const char *pathname, struct junction_ma ref->proximity = 0; ref->ttl = REFERRAL_TTL; jucn->referral_list = ref; - if (consumedcntp) { - *consumedcntp = strlen(pathname); - } + *consumedcntp = strlen(dfs_path); ret = True; goto out; } @@ -607,23 +661,27 @@ BOOL get_referred_path(TALLOC_CTX *ctx, const char *pathname, struct junction_ma return False; } - /* If not remote & not a self referral, return False */ - if (!resolve_dfs_path(ctx, pathname, &dp, conn, False, - &jucn->referral_list, &jucn->referral_count, - self_referralp, consumedcntp)) { - if (!*self_referralp) { - DEBUG(3,("get_referred_path: No valid referrals for path %s\n", pathname)); - goto out; - } + /* 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); + + if (!NT_STATUS_EQUAL(status, NT_STATUS_PATH_NOT_COVERED)) { + DEBUG(3,("get_referred_path: No valid referrals for path %s\n", + dfs_path)); + goto out; } - - /* if self_referral, fill up the junction map */ - if (*self_referralp) { - if (self_ref(ctx, pathname, jucn, consumedcntp, self_referralp) == False) { - goto out; - } + + /* We know this is a valid dfs link. Parse the targetpath. */ + if (!parse_msdfs_symlink(ctx, targetpath, + &jucn->referral_list, + &jucn->referral_count)) { + DEBUG(3,("get_referred_path: failed to parse symlink " + "target %s\n", targetpath )); + goto out; } - + ret = True; out: @@ -632,10 +690,11 @@ out: return ret; } -static int setup_ver2_dfs_referral(char *pathname, char **ppdata, - struct junction_map *junction, - int consumedcnt, - BOOL self_referral) +static int setup_ver2_dfs_referral(const char *pathname, + char **ppdata, + struct junction_map *junction, + int consumedcnt, + BOOL self_referral) { char* pdata = *ppdata; @@ -647,7 +706,7 @@ static int setup_ver2_dfs_referral(char *pathname, char **ppdata, int reply_size = 0; int i=0; - DEBUG(10,("setting up version2 referral\nRequested path:\n")); + DEBUG(10,("Setting up version2 referral\nRequested path:\n")); requestedpathlen = rpcstr_push(uni_requestedpath, pathname, sizeof(pstring), STR_TERMINATE); @@ -681,7 +740,7 @@ static int setup_ver2_dfs_referral(char *pathname, char **ppdata, pdata = (char *)SMB_REALLOC(pdata,reply_size); if(pdata == NULL) { - DEBUG(0,("malloc failed for Realloc!\n")); + DEBUG(0,("Realloc failed!\n")); return -1; } *ppdata = pdata; @@ -732,10 +791,11 @@ static int setup_ver2_dfs_referral(char *pathname, char **ppdata, return reply_size; } -static int setup_ver3_dfs_referral(char *pathname, char **ppdata, - struct junction_map *junction, - int consumedcnt, - BOOL self_referral) +static int setup_ver3_dfs_referral(const char *pathname, + char **ppdata, + struct junction_map *junction, + int consumedcnt, + BOOL self_referral) { char* pdata = *ppdata; @@ -816,17 +876,23 @@ static int setup_ver3_dfs_referral(char *pathname, char **ppdata, } /****************************************************************** - Set up the Dfs referral for the dfs pathname + Set up the DFS referral for the dfs pathname. This call returns + the amount of the path covered by this server, and where the + client should be redirected to. This is the meat of the + TRANS2_GET_DFS_REFERRAL call. ******************************************************************/ -int setup_dfs_referral(connection_struct *orig_conn, char *pathname, int max_referral_level, char **ppdata) +int setup_dfs_referral(connection_struct *orig_conn, + const char *dfs_path, + int max_referral_level, + char **ppdata) { struct junction_map junction; - int consumedcnt; + int consumedcnt = 0; BOOL self_referral = False; - pstring buf; int reply_size = 0; - char *pathnamep = pathname; + char *pathnamep = NULL; + pstring local_dfs_path; TALLOC_CTX *ctx; if (!(ctx=talloc_init("setup_dfs_referral"))) { @@ -836,21 +902,24 @@ int setup_dfs_referral(connection_struct *orig_conn, char *pathname, int max_ref ZERO_STRUCT(junction); /* get the junction entry */ - if (!pathnamep) { + if (!dfs_path) { talloc_destroy(ctx); return -1; } - /* Trim pathname sent by client so it begins with only one backslash. - Two backslashes confuse some dfs clients + /* + * Trim pathname sent by client so it begins with only one backslash. + * Two backslashes confuse some dfs clients */ - while (pathnamep[0] == '\\' && pathnamep[1] == '\\') { + + pstrcpy(local_dfs_path, dfs_path); + pathnamep = local_dfs_path; + while (IS_DIRECTORY_SEP(pathnamep[0]) && IS_DIRECTORY_SEP(pathnamep[1])) { pathnamep++; } - pstrcpy(buf, pathnamep); /* The following call can change cwd. */ - if (!get_referred_path(ctx, buf, &junction, &consumedcnt, &self_referral)) { + if (!get_referred_path(ctx, pathnamep, &junction, &consumedcnt, &self_referral)) { vfs_ChDir(orig_conn,orig_conn->connectpath); talloc_destroy(ctx); return -1; @@ -908,31 +977,40 @@ int setup_dfs_referral(connection_struct *orig_conn, char *pathname, int max_ref **********************************************************************/ /********************************************************************* - Creates a junction structure from a Dfs pathname + Creates a junction structure from a DFS pathname **********************************************************************/ -BOOL create_junction(const char *pathname, struct junction_map *jucn) +BOOL create_junction(const char *dfs_path, struct junction_map *jucn) { - struct dfs_path dp; + int snum; + BOOL dummy; + struct dfs_path dp; - parse_dfs_path(pathname,&dp); + NTSTATUS status = parse_dfs_path(dfs_path, False, &dp, &dummy); + + if (!NT_STATUS_IS_OK(status)) { + return False; + } - /* check if path is dfs : validate first token */ + /* 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, pathname)); + dp.hostname, dfs_path)); return False; } /* Check for a non-DFS share */ - if(!lp_msdfs_root(lp_servicenumber(dp.servicename))) { - DEBUG(4,("create_junction: %s is not an msdfs root.\n", dp.servicename)); + snum = lp_servicenumber(dp.servicename); + + if(snum < 0 || !lp_msdfs_root(snum)) { + DEBUG(4,("create_junction: %s is not an msdfs root.\n", + dp.servicename)); return False; } - pstrcpy(jucn->service_name,dp.servicename); + fstrcpy(jucn->service_name,dp.servicename); pstrcpy(jucn->volume_name,dp.reqpath); - pstrcpy(jucn->comment, lp_comment(lp_servicenumber(dp.servicename))); + pstrcpy(jucn->comment, lp_comment(snum)); return True; } @@ -940,16 +1018,14 @@ BOOL create_junction(const char *pathname, struct junction_map *jucn) Forms a valid Unix pathname from the junction **********************************************************************/ -static BOOL junction_to_local_path(struct junction_map *jucn, char *path, - int max_pathlen, connection_struct *conn) +static BOOL junction_to_local_path(struct junction_map *jucn, + char *path, + int max_pathlen, + connection_struct *conn_out) { int snum; pstring conn_path; - if(!path || !jucn) { - return False; - } - snum = lp_servicenumber(jucn->service_name); if(snum < 0) { return False; @@ -960,7 +1036,7 @@ static BOOL junction_to_local_path(struct junction_map *jucn, char *path, safe_strcat(path, jucn->volume_name, max_pathlen-1); pstrcpy(conn_path, lp_pathname(snum)); - if (!create_conn_struct(conn, snum, conn_path)) { + if (!create_conn_struct(conn_out, snum, conn_path)) { return False; } @@ -983,11 +1059,12 @@ BOOL create_msdfs_link(struct junction_map *jucn, BOOL exists) return False; } - /* form the msdfs_link contents */ + /* Form the msdfs_link contents */ pstrcpy(msdfs_link, "msdfs:"); for(i=0; ireferral_count; i++) { char* refpath = jucn->referral_list[i].alternate_path; + /* Alternate paths always use Windows separators. */ trim_char(refpath, '\\', '\\'); if(*refpath == '\0') { if (i == 0) { @@ -1005,7 +1082,8 @@ BOOL create_msdfs_link(struct junction_map *jucn, BOOL exists) } } - DEBUG(5,("create_msdfs_link: Creating new msdfs link: %s -> %s\n", path, msdfs_link)); + DEBUG(5,("create_msdfs_link: Creating new msdfs link: %s -> %s\n", + path, msdfs_link)); if(exists) { if(SMB_VFS_UNLINK(conn,path)!=0) { @@ -1021,7 +1099,7 @@ BOOL create_msdfs_link(struct junction_map *jucn, BOOL exists) ret = True; - + out: conn_free_internal(conn); @@ -1048,13 +1126,16 @@ BOOL remove_msdfs_link(struct junction_map *jucn) return ret; } -static int form_junctions(TALLOC_CTX *ctx, int snum, struct junction_map *jucn, int jn_remain) +static int form_junctions(TALLOC_CTX *ctx, + int snum, + struct junction_map *jucn, + int jn_remain) { int cnt = 0; SMB_STRUCT_DIR *dirp; - char* dname; + char *dname; pstring connect_path; - char* service_name = lp_servicename(snum); + char *service_name = lp_servicename(snum); connection_struct conn; struct referral *ref = NULL; @@ -1082,13 +1163,13 @@ static int form_junctions(TALLOC_CTX *ctx, int snum, struct junction_map *jucn, DO NOT REMOVE THIS: NT clients will not work with us if this is not present */ - pstrcpy(jucn[cnt].service_name, service_name); + fstrcpy(jucn[cnt].service_name, service_name); jucn[cnt].volume_name[0] = '\0'; jucn[cnt].referral_count = 1; - ref = jucn[cnt].referral_list = TALLOC_P(ctx, struct referral); + ref = jucn[cnt].referral_list = TALLOC_ZERO_P(ctx, struct referral); if (jucn[cnt].referral_list == NULL) { - DEBUG(0, ("Malloc failed!\n")); + DEBUG(0, ("talloc failed!\n")); goto out; } @@ -1099,9 +1180,10 @@ static int form_junctions(TALLOC_CTX *ctx, int snum, struct junction_map *jucn, cnt++; goto out; } - - slprintf(ref->alternate_path, sizeof(pstring)-1, - "\\\\%s\\%s", get_local_machine_name(), service_name); + + pstr_sprintf(ref->alternate_path, "\\\\%s\\%s", + get_local_machine_name(), + service_name); cnt++; /* Now enumerate all dfs links */ @@ -1111,16 +1193,22 @@ static int form_junctions(TALLOC_CTX *ctx, int snum, struct junction_map *jucn, } while ((dname = vfs_readdirname(&conn, dirp)) != NULL) { + pstring link_target; if (cnt >= jn_remain) { SMB_VFS_CLOSEDIR(&conn,dirp); DEBUG(2, ("ran out of MSDFS junction slots")); goto out; } - if (is_msdfs_link(ctx, &conn, dname, &jucn[cnt].referral_list, - &jucn[cnt].referral_count, NULL)) { - pstrcpy(jucn[cnt].service_name, service_name); - pstrcpy(jucn[cnt].volume_name, dname); - cnt++; + if (is_msdfs_link(&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); + cnt++; + } } } @@ -1160,13 +1248,14 @@ int enum_msdfs_links(TALLOC_CTX *ctx, struct junction_map *jucn, int jn_max) Core function to resolve a dfs pathname. ******************************************************************************/ -BOOL resolve_dfspath(connection_struct *conn, BOOL dfs_pathnames, pstring name) +NTSTATUS resolve_dfspath(connection_struct *conn, BOOL dfs_pathnames, pstring name) { - if (dfs_pathnames && lp_host_msdfs() && lp_msdfs_root(SNUM(conn)) && - dfs_redirect(conn, name, False)) { - return False; /* Pathname didn't resolve. */ + NTSTATUS status = NT_STATUS_OK; + BOOL dummy; + if (dfs_pathnames && lp_host_msdfs() && lp_msdfs_root(SNUM(conn))) { + status = dfs_redirect(conn, name, False, &dummy); } - return True; + return status; } /****************************************************************************** @@ -1176,11 +1265,11 @@ BOOL resolve_dfspath(connection_struct *conn, BOOL dfs_pathnames, pstring name) we're allowing wildcards and when we're not. JRA. ******************************************************************************/ -BOOL resolve_dfspath_wcard(connection_struct *conn, BOOL dfs_pathnames, pstring name) +NTSTATUS resolve_dfspath_wcard(connection_struct *conn, BOOL dfs_pathnames, pstring name, BOOL *ppath_contains_wcard) { - if (dfs_pathnames && lp_host_msdfs() && lp_msdfs_root(SNUM(conn)) && - dfs_redirect(conn, name, True)) { - return False; /* Pathname didn't resolve. */ + NTSTATUS status = NT_STATUS_OK; + if (dfs_pathnames && lp_host_msdfs() && lp_msdfs_root(SNUM(conn))) { + status = dfs_redirect(conn, name, True, ppath_contains_wcard); } - return True; + return status; } -- cgit From a5dd4355cddbd49de1f2434c1a890799dd1a1dd0 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 12 Mar 2007 20:10:12 +0000 Subject: r21803: Missed part of patch to make self-referrals work. Jeremy. (This used to be commit b1fa55e513f506bfb58687b692e1507732b00fbc) --- source3/smbd/msdfs.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index ae2009ad38..1641679a35 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -483,6 +483,7 @@ static NTSTATUS dfs_redirect( connection_struct *conn, } if (dp.reqpath[0] == '\0') { + pstrcpy(dfs_path, dp.reqpath); DEBUG(5,("dfs_redirect: self-referral.\n")); return NT_STATUS_OK; } -- cgit From bf26a7632e438199ab10c9557f7d018e19705604 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 22 Mar 2007 22:15:35 +0000 Subject: r21942: Hoist by our own petard :-). Older smbclient binaries were not able to connect to the rewritten dfs code as they set the dfs flag bit but then send local paths. Now that our dfs code is a *lot* more robust in detecting this sort of braindamage we can just call into it directly on getting a DFS flag and let the parser sort it out without having to check it's actually connecting to a dfs enabled share (I'm proud of this code :-). Jeremy. (This used to be commit 8c4d929c76ba56d59f651c57d1feb37d2916a436) --- source3/smbd/msdfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 1641679a35..13c44e9420 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -1253,7 +1253,7 @@ NTSTATUS resolve_dfspath(connection_struct *conn, BOOL dfs_pathnames, pstring na { NTSTATUS status = NT_STATUS_OK; BOOL dummy; - if (dfs_pathnames && lp_host_msdfs() && lp_msdfs_root(SNUM(conn))) { + if (dfs_pathnames) { status = dfs_redirect(conn, name, False, &dummy); } return status; @@ -1269,7 +1269,7 @@ NTSTATUS resolve_dfspath(connection_struct *conn, BOOL dfs_pathnames, pstring na NTSTATUS resolve_dfspath_wcard(connection_struct *conn, BOOL dfs_pathnames, pstring name, BOOL *ppath_contains_wcard) { NTSTATUS status = NT_STATUS_OK; - if (dfs_pathnames && lp_host_msdfs() && lp_msdfs_root(SNUM(conn))) { + if (dfs_pathnames) { status = dfs_redirect(conn, name, True, ppath_contains_wcard); } return status; -- cgit From eca13022ef78237f915c8fec1ecbe676b1c86ae3 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 24 Mar 2007 18:14:46 +0000 Subject: r21960: Fix bugs 4463,4464,4465,4466. Thanks Jason :-) (This used to be commit a2e27c443101a59ef3429a55e049af3ebd5ec1f2) --- source3/smbd/msdfs.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 13c44e9420..8f85b90fdc 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -242,13 +242,11 @@ static BOOL parse_msdfs_symlink(TALLOC_CTX *ctx, int *refcount) { pstring temp; - char *prot; char *alt_path[MAX_REFERRAL_COUNT]; int count = 0, i; struct referral *reflist; pstrcpy(temp,target); - prot = strtok(temp,":"); /* parse out the alternate paths */ while((count Date: Sat, 24 Mar 2007 18:22:20 +0000 Subject: r21961: Repair bug introduced by rev. 21960. We need to do the initial strtok to set up the internal state. Jeremy. (This used to be commit 8c7042b4192cb33988c1bbccdd4a80bb99fd0118) --- source3/smbd/msdfs.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 8f85b90fdc..916f661eaa 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -242,11 +242,17 @@ static BOOL parse_msdfs_symlink(TALLOC_CTX *ctx, int *refcount) { pstring temp; + char *prot; char *alt_path[MAX_REFERRAL_COUNT]; int count = 0, i; struct referral *reflist; pstrcpy(temp,target); + prot = strtok(temp,":"); + if (!prot) { + DEBUG(0,("parse_msdfs_symlink: invalid path !\n")); + return False; + } /* parse out the alternate paths */ while((count Date: Wed, 28 Mar 2007 13:34:59 +0000 Subject: r22001: change prototype of dump_data(), so that it takes unsigned char * now, which matches what samba4 has. also fix all the callers to prevent compiler warnings metze (This used to be commit fa322f0cc9c26a9537ba3f0a7d4e4a25941317e7) --- source3/smbd/msdfs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 916f661eaa..397d43b8bb 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -717,7 +717,7 @@ static int setup_ver2_dfs_referral(const char *pathname, STR_TERMINATE); if (DEBUGLVL(10)) { - dump_data(0, (const char *) uni_requestedpath,requestedpathlen); + dump_data(0, uni_requestedpath,requestedpathlen); } DEBUG(10,("ref count = %u\n",junction->referral_count)); @@ -817,7 +817,7 @@ static int setup_ver3_dfs_referral(const char *pathname, reqpathlen = rpcstr_push(uni_reqpath, pathname, sizeof(pstring), STR_TERMINATE); if (DEBUGLVL(10)) { - dump_data(0, (char *) uni_reqpath,reqpathlen); + dump_data(0, uni_reqpath,reqpathlen); } uni_reqpathoffset1 = REFERRAL_HEADER_SIZE + VERSION3_REFERRAL_SIZE * junction->referral_count; @@ -970,7 +970,7 @@ int setup_dfs_referral(connection_struct *orig_conn, if (DEBUGLVL(10)) { DEBUGADD(0,("DFS Referral pdata:\n")); - dump_data(0,*ppdata,reply_size); + dump_data(0,(uint8 *)*ppdata,reply_size); } talloc_destroy(ctx); -- cgit From cab91684e51356215a4c764e1673e4fd8420b8e8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 3 Apr 2007 22:59:55 +0000 Subject: r22064: Fix the DFS code to work better with Vista clients. Allow "host msdfs = true" to be set in the [global] section and allow Vista to see shares with "msdfs root = yes" and "msdfs root = no" off the same server. Down to an error message really :-). Jeremy. (This used to be commit 1a0f69bb21fd03a18514dfc93c84568708144e28) --- source3/smbd/msdfs.c | 68 +++++++++++++++++++++++++++------------------------- 1 file changed, 36 insertions(+), 32 deletions(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 397d43b8bb..effe868657 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -170,7 +170,7 @@ static NTSTATUS parse_dfs_path(const char *pathname, Note this CHANGES CWD !!!! JRA. *********************************************************/ -static BOOL 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; @@ -183,12 +183,12 @@ static BOOL create_conn_struct(connection_struct *conn, int snum, const char *pa if ((conn->mem_ctx=talloc_init("connection_struct")) == NULL) { DEBUG(0,("talloc_init(connection_struct) failed!\n")); - return False; + return NT_STATUS_NO_MEMORY; } if (!(conn->params = TALLOC_ZERO_P(conn->mem_ctx, struct share_params))) { DEBUG(0, ("TALLOC failed\n")); - return False; + return NT_STATUS_NO_MEMORY; } conn->params->service = snum; @@ -196,9 +196,10 @@ static BOOL create_conn_struct(connection_struct *conn, int snum, const char *pa set_conn_connectpath(conn, connpath); if (!smbd_vfs_init(conn)) { + NTSTATUS status = map_nt_error_from_unix(errno); DEBUG(0,("create_conn_struct: smbd_vfs_init failed.\n")); conn_free_internal(conn); - return False; + return status; } /* @@ -208,13 +209,14 @@ static BOOL create_conn_struct(connection_struct *conn, int snum, const char *pa */ 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) )); conn_free_internal(conn); - return False; + return status; } - return True; + return NT_STATUS_OK; } /********************************************************************** @@ -542,7 +544,7 @@ static NTSTATUS dfs_redirect( connection_struct *conn, Return a self referral. **********************************************************************/ -static BOOL self_ref(TALLOC_CTX *ctx, +static NTSTATUS self_ref(TALLOC_CTX *ctx, const char *dfs_path, struct junction_map *jucn, int *consumedcntp, @@ -555,7 +557,7 @@ static BOOL 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 False; + return NT_STATUS_NO_MEMORY; } pstrcpy(ref->alternate_path,dfs_path); @@ -563,7 +565,7 @@ static BOOL self_ref(TALLOC_CTX *ctx, ref->ttl = REFERRAL_TTL; jucn->referral_list = ref; *consumedcntp = strlen(dfs_path); - return True; + return NT_STATUS_OK; } /********************************************************************** @@ -571,7 +573,7 @@ static BOOL self_ref(TALLOC_CTX *ctx, junction_map structure. **********************************************************************/ -BOOL get_referred_path(TALLOC_CTX *ctx, +NTSTATUS get_referred_path(TALLOC_CTX *ctx, const char *dfs_path, struct junction_map *jucn, int *consumedcntp, @@ -583,8 +585,7 @@ BOOL get_referred_path(TALLOC_CTX *ctx, pstring conn_path; pstring targetpath; int snum; - NTSTATUS status; - BOOL ret = False; + NTSTATUS status = NT_STATUS_NOT_FOUND; BOOL dummy; ZERO_STRUCT(conns); @@ -593,14 +594,14 @@ BOOL get_referred_path(TALLOC_CTX *ctx, status = parse_dfs_path(dfs_path, False, &dp, &dummy); if (!NT_STATUS_IS_OK(status)) { - return False; + return status; } /* Verify hostname in path */ if (!is_myname_or_ipaddr(dp.hostname)) { DEBUG(3, ("get_referred_path: Invalid hostname %s in path %s\n", dp.hostname, dfs_path)); - return False; + return NT_STATUS_NOT_FOUND; } fstrcpy(jucn->service_name, dp.servicename); @@ -610,14 +611,14 @@ BOOL get_referred_path(TALLOC_CTX *ctx, snum = lp_servicenumber(jucn->service_name); if(snum < 0) { if ((snum = find_service(jucn->service_name)) < 0) { - return False; + return NT_STATUS_NOT_FOUND; } } 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)); - goto out; + return NT_STATUS_NOT_FOUND; } /* @@ -646,7 +647,7 @@ BOOL get_referred_path(TALLOC_CTX *ctx, jucn->referral_count = 1; if ((ref = TALLOC_ZERO_P(ctx, struct referral)) == NULL) { DEBUG(0, ("malloc failed for referral\n")); - goto out; + return NT_STATUS_NO_MEMORY; } pstrcpy(ref->alternate_path, lp_msdfs_proxy(snum)); @@ -657,13 +658,13 @@ BOOL get_referred_path(TALLOC_CTX *ctx, ref->ttl = REFERRAL_TTL; jucn->referral_list = ref; *consumedcntp = strlen(dfs_path); - ret = True; - goto out; + return NT_STATUS_OK; } pstrcpy(conn_path, lp_pathname(snum)); - if (!create_conn_struct(conn, snum, conn_path)) { - return False; + status = create_conn_struct(conn, snum, conn_path); + if (!NT_STATUS_IS_OK(status)) { + return status; } /* If this is a DFS path dfs_lookup should return @@ -675,7 +676,8 @@ BOOL get_referred_path(TALLOC_CTX *ctx, if (!NT_STATUS_EQUAL(status, NT_STATUS_PATH_NOT_COVERED)) { DEBUG(3,("get_referred_path: No valid referrals for path %s\n", dfs_path)); - goto out; + conn_free_internal(conn); + return status; } /* We know this is a valid dfs link. Parse the targetpath. */ @@ -684,15 +686,12 @@ BOOL get_referred_path(TALLOC_CTX *ctx, &jucn->referral_count)) { DEBUG(3,("get_referred_path: failed to parse symlink " "target %s\n", targetpath )); - goto out; + conn_free_internal(conn); + return NT_STATUS_NOT_FOUND; } - ret = True; - -out: - conn_free_internal(conn); - return ret; + return NT_STATUS_OK; } static int setup_ver2_dfs_referral(const char *pathname, @@ -890,7 +889,7 @@ static int setup_ver3_dfs_referral(const char *pathname, int setup_dfs_referral(connection_struct *orig_conn, const char *dfs_path, int max_referral_level, - char **ppdata) + char **ppdata, NTSTATUS *pstatus) { struct junction_map junction; int consumedcnt = 0; @@ -901,6 +900,7 @@ int setup_dfs_referral(connection_struct *orig_conn, TALLOC_CTX *ctx; if (!(ctx=talloc_init("setup_dfs_referral"))) { + *pstatus = NT_STATUS_NO_MEMORY; return -1; } @@ -909,6 +909,7 @@ int setup_dfs_referral(connection_struct *orig_conn, /* get the junction entry */ if (!dfs_path) { talloc_destroy(ctx); + *pstatus = NT_STATUS_NOT_FOUND; return -1; } @@ -924,7 +925,8 @@ int setup_dfs_referral(connection_struct *orig_conn, } /* The following call can change cwd. */ - if (!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; @@ -965,6 +967,7 @@ int setup_dfs_referral(connection_struct *orig_conn, default: DEBUG(0,("setup_dfs_referral: Invalid dfs referral version: %d\n", max_referral_level)); talloc_destroy(ctx); + *pstatus = NT_STATUS_INVALID_LEVEL; return -1; } @@ -974,6 +977,7 @@ int setup_dfs_referral(connection_struct *orig_conn, } talloc_destroy(ctx); + *pstatus = NT_STATUS_OK; return reply_size; } @@ -1041,7 +1045,7 @@ static BOOL junction_to_local_path(struct junction_map *jucn, safe_strcat(path, jucn->volume_name, max_pathlen-1); pstrcpy(conn_path, lp_pathname(snum)); - if (!create_conn_struct(conn_out, snum, conn_path)) { + if (!NT_STATUS_IS_OK(create_conn_struct(conn_out, snum, conn_path))) { return False; } @@ -1160,7 +1164,7 @@ static int form_junctions(TALLOC_CTX *ctx, * Fake up a connection struct for the VFS layer. */ - if (!create_conn_struct(&conn, snum, connect_path)) { + if (!NT_STATUS_IS_OK(create_conn_struct(&conn, snum, connect_path))) { return 0; } -- cgit From 56a5d05b8b285250bdc0e9cc3c8f3c3d8af80382 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 30 Apr 2007 02:51:26 +0000 Subject: r22590: Make TALLOC_ARRAY consistent across all uses. That should be it.... Jeremy. (This used to be commit 603233a98bbf65467c8b4f04719d771c70b3b4c9) --- source3/smbd/msdfs.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index effe868657..9f203bfd19 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -264,10 +264,14 @@ static BOOL parse_msdfs_symlink(TALLOC_CTX *ctx, DEBUG(10,("parse_msdfs_symlink: count=%d\n", count)); - reflist = *preflist = TALLOC_ZERO_ARRAY(ctx, struct referral, count); - if(reflist == NULL) { - DEBUG(0,("parse_msdfs_symlink: talloc failed!\n")); - return False; + if (count) { + reflist = *preflist = TALLOC_ZERO_ARRAY(ctx, struct referral, count); + if(reflist == NULL) { + DEBUG(0,("parse_msdfs_symlink: talloc failed!\n")); + return False; + } + } else { + reflist = *preflist = NULL; } for(i=0;i Date: Sat, 16 Jun 2007 18:07:44 +0000 Subject: r23522: Save us a kilobyte stack space in a hot code path: I can't see a reason why check_path_syntax should not be able to run in-line. The destination pointer either walks side by side with the source pointer or is decremented. So as far as I can see s>=d is true throughout the whole routine. Jeremy, I'm checking this only into 3_0 for now. Please review and ack or directly merge this to 3_0_26. Thanks, Volker (This used to be commit 34a13c82a3b72d6900614b57c58fbaefeeca8fa7) --- source3/smbd/msdfs.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 9f203bfd19..a3de199116 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -144,14 +144,16 @@ static NTSTATUS parse_dfs_path(const char *pathname, *ppath_contains_wcard = False; + pstrcpy(pdp->reqpath, p); + /* Rest is reqpath. */ if (pdp->posix_path) { - status = check_path_syntax_posix(pdp->reqpath, p); + status = check_path_syntax_posix(pdp->reqpath); } else { if (allow_wcards) { - status = check_path_syntax_wcard(pdp->reqpath, p, ppath_contains_wcard); + status = check_path_syntax_wcard(pdp->reqpath, ppath_contains_wcard); } else { - status = check_path_syntax(pdp->reqpath, p); + status = check_path_syntax(pdp->reqpath); } } -- cgit From d824b98f80ba186030cbb70b3a1e5daf80469ecd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 9 Jul 2007 19:25:36 +0000 Subject: r23779: Change from v2 or later to v3 or later. Jeremy. (This used to be commit 407e6e695b8366369b7c76af1ff76869b45347b3) --- source3/smbd/msdfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index a3de199116..01c29ce6a2 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -7,7 +7,7 @@ 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 2 of the License, or + 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, -- cgit From 5e54558c6dea67b56bbfaba5698f3a434d3dffb6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 10 Jul 2007 00:52:41 +0000 Subject: r23784: use the GPLv3 boilerplate as recommended by the FSF and the license text (This used to be commit b0132e94fc5fef936aa766fb99a306b3628e9f07) --- source3/smbd/msdfs.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 01c29ce6a2..d4c08848d7 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -16,8 +16,7 @@ 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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + along with this program. If not, see . */ -- cgit From 188b84f9d07ec33f8780ea5494d5892568cdbfe8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 11 Jul 2007 21:01:06 +0000 Subject: r23843: Fix bug #4777, reported by Bill Marshall . Doing a DFS traverse through a deep link could fail (not using explorer). Jeremy. (This used to be commit cd93f0cb00207098014e41e0ba16210cb150b895) --- source3/smbd/msdfs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index d4c08848d7..a89f4ceffc 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -389,7 +389,8 @@ static NTSTATUS dfs_path_lookup(connection_struct *conn, pstrcpy(localpath, pdp->reqpath); status = unix_convert(conn, localpath, search_flag, NULL, &sbuf); - if (!NT_STATUS_IS_OK(status)) { + if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status, + NT_STATUS_OBJECT_PATH_NOT_FOUND)) { return status; } -- cgit From d75a38ae264ab3bbe73414576b37ccdafbbb9975 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 6 Aug 2007 18:54:26 +0000 Subject: r24253: From Jan Martin . ---------------------------------------------------------- In rare cases, Samba 3.0.25b shows directory contents at the wrong position in the file tree when displaying a subdirectory of a DFS link. The problem occurs whenever Windows XP asks for a DFS referral for a subdirectory of a DFS link with a trailing backslash. Windows does not do this very often, but we saw it several times per day on our central DFS server. smbd/msdfs.c, dfs_path_lookup() does the following with the requested path: - in line 390, the local copy 'localpath' is 'unix_convert'ed; the trailing backslash is removed inside unix_convert - in lines 417-20, 'dfspath' (another copy of the requested path) is mangled another way without removing trailing backslashes That's why the following loop (lines 435-461) that is meant to synchronously cut off the last path component from both strings until it comes to a DFS link, does not handle both strings the same. When the original path ended with a backslash, 'canon_dfspath' has always one component more than 'localpath', so that *consumedcntp gets too big in line 446. This value is reported to the client. ---------------------------------------------------------- Bug #4860. Jeremy. (This used to be commit 42d1c6713a56197ca8dfebf74eb0d483102148f7) --- source3/smbd/msdfs.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index a89f4ceffc..16f3cd4370 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -421,6 +421,14 @@ static NTSTATUS dfs_path_lookup(connection_struct *conn, string_replace(canon_dfspath, '\\', '/'); } + /* + * localpath comes out of unix_convert, so it has + * no trailing backslash. Make sure that canon_dfspath hasn't either. + * Fix for bug #4860 from Jan Martin . + */ + + trim_char(canon_dfspath,0,'/'); + /* * Redirect if any component in the path is a link. * We do this by walking backwards through the -- cgit From 132ee3990af5d31573978f5a3abf43db2303880b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 7 Sep 2007 20:57:01 +0000 Subject: r25009: Large patch discussed with Volker. Move unix_convert to a talloc-based interface. More development will come on top of this. Remove the "mangled map" parameter. Jeremy. (This used to be commit dee8beba7a92b8a3f68bbcc59fd0a827f68c7736) --- source3/smbd/msdfs.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 16f3cd4370..10652874c5 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -369,7 +369,8 @@ static NTSTATUS dfs_path_lookup(connection_struct *conn, char *q = NULL; SMB_STRUCT_STAT sbuf; NTSTATUS status; - pstring localpath; + pstring localpath_in; + char *localpath = NULL; pstring canon_dfspath; /* Canonicalized dfs path. (only '/' components). */ DEBUG(10,("dfs_path_lookup: Conn path = %s reqpath = %s\n", @@ -387,8 +388,8 @@ static NTSTATUS dfs_path_lookup(connection_struct *conn, * think this is needed. JRA. */ - pstrcpy(localpath, pdp->reqpath); - status = unix_convert(conn, localpath, search_flag, NULL, &sbuf); + pstrcpy(localpath_in, pdp->reqpath); + status = unix_convert(conn, localpath_in, search_flag, &localpath, NULL, &sbuf); if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) { return status; -- cgit From 351eb37a2555ce474ee02758f2f2cfee33d4d434 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 11 Sep 2007 18:31:29 +0000 Subject: 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) --- source3/smbd/msdfs.c | 861 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 609 insertions(+), 252 deletions(-) (limited to 'source3/smbd/msdfs.c') 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 . @@ -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((countst_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;ireferral_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;ireferral_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;ireferral_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;ireferral_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; ireferral_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; } -- cgit From 3a9d3821649c9ea88a6cd424f0838a453165a00a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 11 Sep 2007 23:57:59 +0000 Subject: r25111: Move to talloced pathnames on most code paths. There are now ony 17 pstrings left in reply.c, and these will be easy to remove (and I'll be doing that shortly). Had to fix an interesting bug in pull_ucs2_base_talloc() when a source string is not null terminated :-). Jeremy. (This used to be commit 0c9a8c4dff10974dbffd2a302ae982896122fcc0) --- source3/smbd/msdfs.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index d687974ff3..5cbe8c68ac 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -817,9 +817,9 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx, } if (pdp->reqpath[0] != '\0') { - ref->alternate_path = talloc_asprintf(ctx, - "%s%s", + ref->alternate_path = talloc_asprintf_append( ref->alternate_path, + "%s", pdp->reqpath); if (!ref->alternate_path) { TALLOC_FREE(pdp); @@ -1298,7 +1298,6 @@ BOOL create_msdfs_link(const struct junction_map *jucn, goto out; } for(i=0; ireferral_count; i++) { - char *old_msdfs_link = msdfs_link; char *refpath = jucn->referral_list[i].alternate_path; /* Alternate paths always use Windows separators. */ @@ -1310,21 +1309,18 @@ BOOL create_msdfs_link(const struct junction_map *jucn, continue; } if (i > 0 && insert_comma) { - msdfs_link = talloc_asprintf(conn->mem_ctx, - "%s,%s", - old_msdfs_link, + msdfs_link = talloc_asprintf_append(msdfs_link, + ",%s", refpath); } else { - msdfs_link = talloc_asprintf(conn->mem_ctx, - "%s%s", - old_msdfs_link, + msdfs_link = talloc_asprintf_append(msdfs_link, + "%s", refpath); } if (!msdfs_link) { goto out; } - TALLOC_FREE(old_msdfs_link); if (!insert_comma) { insert_comma = True; } -- cgit From eacd3140573d1122a3785823e4003bfc6352c431 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 13 Sep 2007 22:08:59 +0000 Subject: r25138: More pstring elimination. Add a TALLOC_CTX parameter to unix_convert(). Jeremy. (This used to be commit 39c211a702e91c34c1a5a689e1b0c4530ea8a1ac) --- source3/smbd/msdfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 5cbe8c68ac..1917eb4d10 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -476,7 +476,7 @@ static NTSTATUS dfs_path_lookup(TALLOC_CTX *ctx, * think this is needed. JRA. */ - status = unix_convert(conn, pdp->reqpath, search_flag, &localpath, + status = unix_convert(ctx, conn, pdp->reqpath, search_flag, &localpath, NULL, &sbuf); if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND)) { -- cgit From bb4773e30f6c524fc2c403111238d61a92474aed Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 14 Sep 2007 22:27:27 +0000 Subject: r25173: Use the append_buffer version in a loop. Jeremy. (This used to be commit 37cf2c272751065245dd46708af0a78f1f0c47df) --- source3/smbd/msdfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 1917eb4d10..56089fbe95 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -1309,11 +1309,11 @@ BOOL create_msdfs_link(const struct junction_map *jucn, continue; } if (i > 0 && insert_comma) { - msdfs_link = talloc_asprintf_append(msdfs_link, + msdfs_link = talloc_asprintf_append_buffer(msdfs_link, ",%s", refpath); } else { - msdfs_link = talloc_asprintf_append(msdfs_link, + msdfs_link = talloc_asprintf_append_buffer(msdfs_link, "%s", refpath); } -- cgit From ad97bcf813d5f06df4711896eefc99c0c32651cc Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 15 Sep 2007 20:24:35 +0000 Subject: r25184: Fix some C++ warnings and an uninitialized variable (This used to be commit b64df8a3c504ab7749c21ffb26e4771a9a0a328f) --- source3/smbd/msdfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 56089fbe95..69612dc571 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -1549,7 +1549,7 @@ 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; + size_t jn_count = 0; int sharecount = 0; *p_num_jn = 0; -- cgit From e0402fa870ccf99c6ff6dc19a5005743cfe4b8d2 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 25 Sep 2007 21:41:39 +0000 Subject: r25324: Fix "msdfs proxy" Jeremy, please check! (This used to be commit d4eddf88d20b09c450d4358d2ef1bc35736501ff) --- source3/smbd/msdfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 69612dc571..a2d7b778ca 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -771,7 +771,7 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx, } } - if (!lp_msdfs_root(snum)) { + if (!lp_msdfs_root(snum) && (*lp_msdfs_proxy(snum) == '\0')) { DEBUG(3,("get_referred_path: |%s| in dfs path %s is not " "a dfs root.\n", pdp->servicename, dfs_path)); -- cgit From aea0d4b9a0540e31392712bfeeb2185975919c42 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 25 Sep 2007 23:26:05 +0000 Subject: r25327: Normalize the path we return for 'msdfs proxy' We now accept both \\server\tmp and \server\tmp. There are other places where this might be necessary, but at least the functionality is a bit easier now. (This used to be commit 25cc27df97e9eecb470f99ea934de12f2a0f4df9) --- source3/smbd/msdfs.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index a2d7b778ca..ff55904b81 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -788,6 +788,7 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx, */ if (pdp->reqpath[0] == '\0') { + char *tmp; struct referral *ref; if (*lp_msdfs_proxy(snum) == '\0') { @@ -810,7 +811,16 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx, return NT_STATUS_NO_MEMORY; } - ref->alternate_path = talloc_strdup(ctx, lp_msdfs_proxy(snum)); + if (!(tmp = talloc_strdup(ctx, lp_msdfs_proxy(snum)))) { + TALLOC_FREE(pdp); + return NT_STATUS_NO_MEMORY; + } + + trim_string(tmp, "\\", 0); + + ref->alternate_path = talloc_asprintf(ctx, "\\%s", tmp); + TALLOC_FREE(tmp); + if (!ref->alternate_path) { TALLOC_FREE(pdp); return NT_STATUS_NO_MEMORY; -- cgit From 30191d1a5704ad2b158386b511558972d539ce47 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 18 Oct 2007 17:40:25 -0700 Subject: RIP BOOL. Convert BOOL -> bool. I found a few interesting bugs in various places whilst doing this (places that assumed BOOL == int). I also need to fix the Samba4 pidl generation (next checkin). Jeremy. (This used to be commit f35a266b3cbb3e5fa6a86be60f34fe340a3ca71f) --- source3/smbd/msdfs.c | 56 ++++++++++++++++++++++++++-------------------------- 1 file changed, 28 insertions(+), 28 deletions(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index ff55904b81..cca1e0a428 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -43,9 +43,9 @@ extern uint32 global_client_caps; **********************************************************************/ static NTSTATUS parse_dfs_path(const char *pathname, - BOOL allow_wcards, + bool allow_wcards, struct dfs_path *pdp, /* MUST BE TALLOCED */ - BOOL *ppath_contains_wcard) + bool *ppath_contains_wcard) { char *pathname_local; char *p,*temp; @@ -268,7 +268,7 @@ static NTSTATUS create_conn_struct(connection_struct *conn, server we're referring to understands posix paths. **********************************************************************/ -static BOOL parse_msdfs_symlink(TALLOC_CTX *ctx, +static bool parse_msdfs_symlink(TALLOC_CTX *ctx, const char *target, struct referral **preflist, int *refcount) @@ -349,7 +349,7 @@ static BOOL parse_msdfs_symlink(TALLOC_CTX *ctx, returns the target string from inside the link. **********************************************************************/ -static BOOL is_msdfs_link_internal(TALLOC_CTX *ctx, +static bool is_msdfs_link_internal(TALLOC_CTX *ctx, connection_struct *conn, const char *path, char **pp_link_target, @@ -418,7 +418,7 @@ static BOOL is_msdfs_link_internal(TALLOC_CTX *ctx, Returns true if the unix path is a valid msdfs symlink. **********************************************************************/ -BOOL is_msdfs_link(connection_struct *conn, +bool is_msdfs_link(connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbufp) { @@ -449,7 +449,7 @@ static NTSTATUS dfs_path_lookup(TALLOC_CTX *ctx, const char *dfspath, /* Incoming complete dfs path */ const struct dfs_path *pdp, /* Parsed out server+share+extrapath. */ - BOOL search_flag, /* Called from a findfirst ? */ + bool search_flag, /* Called from a findfirst ? */ int *consumedcntp, char **pp_targetpath) { @@ -587,9 +587,9 @@ static NTSTATUS dfs_path_lookup(TALLOC_CTX *ctx, static NTSTATUS dfs_redirect(TALLOC_CTX *ctx, connection_struct *conn, const char *path_in, - BOOL search_wcard_flag, + bool search_wcard_flag, char **pp_path_out, - BOOL *ppath_contains_wcard) + bool *ppath_contains_wcard) { NTSTATUS status; struct dfs_path *pdp = TALLOC_P(ctx, struct dfs_path); @@ -687,7 +687,7 @@ static NTSTATUS self_ref(TALLOC_CTX *ctx, const char *dfs_path, struct junction_map *jucn, int *consumedcntp, - BOOL *self_referralp) + bool *self_referralp) { struct referral *ref; @@ -718,14 +718,14 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx, const char *dfs_path, struct junction_map *jucn, int *consumedcntp, - BOOL *self_referralp) + bool *self_referralp) { struct connection_struct conns; struct connection_struct *conn = &conns; char *targetpath = NULL; int snum; NTSTATUS status = NT_STATUS_NOT_FOUND; - BOOL dummy; + bool dummy; struct dfs_path *pdp = TALLOC_P(ctx, struct dfs_path); if (!pdp) { @@ -884,7 +884,7 @@ static int setup_ver2_dfs_referral(const char *pathname, char **ppdata, struct junction_map *junction, int consumedcnt, - BOOL self_referral) + bool self_referral) { char* pdata = *ppdata; @@ -993,7 +993,7 @@ static int setup_ver3_dfs_referral(const char *pathname, char **ppdata, struct junction_map *junction, int consumedcnt, - BOOL self_referral) + bool self_referral) { char *pdata = *ppdata; @@ -1095,7 +1095,7 @@ int setup_dfs_referral(connection_struct *orig_conn, { struct junction_map *junction = NULL; int consumedcnt = 0; - BOOL self_referral = False; + bool self_referral = False; int reply_size = 0; char *pathnamep = NULL; char *local_dfs_path = NULL; @@ -1209,12 +1209,12 @@ int setup_dfs_referral(connection_struct *orig_conn, Creates a junction structure from a DFS pathname **********************************************************************/ -BOOL create_junction(TALLOC_CTX *ctx, +bool create_junction(TALLOC_CTX *ctx, const char *dfs_path, struct junction_map *jucn) { int snum; - BOOL dummy; + bool dummy; struct dfs_path *pdp = TALLOC_P(ctx,struct dfs_path); NTSTATUS status; @@ -1260,7 +1260,7 @@ BOOL create_junction(TALLOC_CTX *ctx, Forms a valid Unix pathname from the junction **********************************************************************/ -static BOOL junction_to_local_path(const struct junction_map *jucn, +static bool junction_to_local_path(const struct junction_map *jucn, char **pp_path_out, connection_struct *conn_out) { @@ -1285,16 +1285,16 @@ static BOOL junction_to_local_path(const struct junction_map *jucn, return True; } -BOOL create_msdfs_link(const struct junction_map *jucn, - BOOL exists) +bool create_msdfs_link(const struct junction_map *jucn, + bool exists) { char *path = NULL; char *msdfs_link = NULL; connection_struct conns; connection_struct *conn = &conns; int i=0; - BOOL insert_comma = False; - BOOL ret = False; + bool insert_comma = False; + bool ret = False; ZERO_STRUCT(conns); @@ -1360,12 +1360,12 @@ out: return ret; } -BOOL remove_msdfs_link(const struct junction_map *jucn) +bool remove_msdfs_link(const struct junction_map *jucn) { char *path = NULL; connection_struct conns; connection_struct *conn = &conns; - BOOL ret = False; + bool ret = False; ZERO_STRUCT(conns); @@ -1604,12 +1604,12 @@ struct junction_map *enum_msdfs_links(TALLOC_CTX *ctx, size_t *p_num_jn) NTSTATUS resolve_dfspath(TALLOC_CTX *ctx, connection_struct *conn, - BOOL dfs_pathnames, + bool dfs_pathnames, const char *name_in, char **pp_name_out) { NTSTATUS status = NT_STATUS_OK; - BOOL dummy; + bool dummy; if (dfs_pathnames) { status = dfs_redirect(ctx, conn, @@ -1630,17 +1630,17 @@ NTSTATUS resolve_dfspath(TALLOC_CTX *ctx, /****************************************************************************** Core function to resolve a dfs pathname possibly containing a wildcard. - This function is identical to the above except for the BOOL param to + This function is identical to the above except for the bool param to dfs_redirect but I need this to be separate so it's really clear when we're allowing wildcards and when we're not. JRA. ******************************************************************************/ NTSTATUS resolve_dfspath_wcard(TALLOC_CTX *ctx, connection_struct *conn, - BOOL dfs_pathnames, + bool dfs_pathnames, const char *name_in, char **pp_name_out, - BOOL *ppath_contains_wcard) + bool *ppath_contains_wcard) { NTSTATUS status = NT_STATUS_OK; if (dfs_pathnames) { -- cgit From 2b3c44e4fb980335c22abcc07a88f32b13e5918f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 10 Nov 2007 22:31:34 -0800 Subject: Always define PATH_MAX. Makes code simpler (removes a bunch of #defines). Remove pstring from msdfs.c. Jeremy. (This used to be commit e203ba22275320808bc11b17361ad1f2d5b0b897) --- source3/smbd/msdfs.c | 62 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 41 insertions(+), 21 deletions(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index cca1e0a428..98a41e4ec3 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -196,16 +196,26 @@ static NTSTATUS parse_dfs_path(const char *pathname, Note this CHANGES CWD !!!! JRA. *********************************************************/ -static NTSTATUS create_conn_struct(connection_struct *conn, +static NTSTATUS create_conn_struct(TALLOC_CTX *ctx, + connection_struct *conn, int snum, const char *path) { - pstring connpath; + char *connpath; ZERO_STRUCTP(conn); - pstrcpy(connpath, path); - pstring_sub(connpath , "%S", lp_servicename(snum)); + connpath = talloc_strdup(ctx, path); + if (!connpath) { + return NT_STATUS_NO_MEMORY; + } + connpath = talloc_string_sub(ctx, + connpath, + "%S", + lp_servicename(snum)); + if (!connpath) { + return NT_STATUS_NO_MEMORY; + } /* needed for smbd_vfs_init() */ @@ -844,7 +854,7 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx, return NT_STATUS_OK; } - status = create_conn_struct(conn, snum, lp_pathname(snum)); + status = create_conn_struct(ctx, conn, snum, lp_pathname(snum)); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(pdp); return status; @@ -888,7 +898,7 @@ static int setup_ver2_dfs_referral(const char *pathname, { char* pdata = *ppdata; - unsigned char uni_requestedpath[sizeof(pstring)]; + smb_ucs2_t *uni_requestedpath = NULL; int uni_reqpathoffset1,uni_reqpathoffset2; int uni_curroffset; int requestedpathlen=0; @@ -898,12 +908,15 @@ 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_talloc(talloc_tos(), + &uni_requestedpath, pathname); + if (uni_requestedpath == NULL || requestedpathlen == 0) { + return -1; + } if (DEBUGLVL(10)) { - dump_data(0, uni_requestedpath,requestedpathlen); + dump_data(0, (unsigned char *)uni_requestedpath, + requestedpathlen); } DEBUG(10,("ref count = %u\n",junction->referral_count)); @@ -976,8 +989,10 @@ static int setup_ver2_dfs_referral(const char *pathname, SSVAL(pdata,offset+16,uni_reqpathoffset1-offset); SSVAL(pdata,offset+18,uni_reqpathoffset2-offset); /* copy referred path into current offset */ - unilen = rpcstr_push(pdata+uni_curroffset, ref->alternate_path, - sizeof(pstring), STR_UNICODE); + unilen = rpcstr_push(pdata+uni_curroffset, + ref->alternate_path, + reply_size - uni_curroffset, + STR_UNICODE); SSVAL(pdata,offset+20,uni_curroffset-offset); @@ -997,7 +1012,7 @@ static int setup_ver3_dfs_referral(const char *pathname, { char *pdata = *ppdata; - unsigned char uni_reqpath[sizeof(pstring)]; + smb_ucs2_t *uni_reqpath = NULL; int uni_reqpathoffset1, uni_reqpathoffset2; int uni_curroffset; int reply_size = 0; @@ -1007,11 +1022,14 @@ static int setup_ver3_dfs_referral(const char *pathname, DEBUG(10,("setting up version3 referral\n")); - reqpathlen = rpcstr_push(uni_reqpath, pathname, - sizeof(pstring), STR_TERMINATE); + reqpathlen = rpcstr_push_talloc(talloc_tos(), &uni_reqpath, pathname); + if (uni_reqpath == NULL || reqpathlen == 0) { + return -1; + } if (DEBUGLVL(10)) { - dump_data(0, uni_reqpath,reqpathlen); + dump_data(0, (unsigned char *)uni_reqpath, + reqpathlen); } uni_reqpathoffset1 = REFERRAL_HEADER_SIZE + @@ -1069,8 +1087,8 @@ static int setup_ver3_dfs_referral(const char *pathname, 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); + reply_size - uni_curroffset, + 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); @@ -1270,7 +1288,8 @@ static bool junction_to_local_path(const struct junction_map *jucn, if(snum < 0) { return False; } - if (!NT_STATUS_IS_OK(create_conn_struct(conn_out, snum, + if (!NT_STATUS_IS_OK(create_conn_struct(talloc_tos(), + conn_out, snum, lp_pathname(snum)))) { return False; } @@ -1402,7 +1421,8 @@ static int count_dfs_links(TALLOC_CTX *ctx, int snum) * Fake up a connection struct for the VFS layer. */ - if (!NT_STATUS_IS_OK(create_conn_struct(&conn, snum, connect_path))) { + if (!NT_STATUS_IS_OK(create_conn_struct(talloc_tos(), + &conn, snum, connect_path))) { return 0; } @@ -1467,7 +1487,7 @@ static int form_junctions(TALLOC_CTX *ctx, * Fake up a connection struct for the VFS layer. */ - if (!NT_STATUS_IS_OK(create_conn_struct(&conn, snum, connect_path))) { + if (!NT_STATUS_IS_OK(create_conn_struct(ctx, &conn, snum, connect_path))) { return 0; } -- cgit From acf15ae730c95443681404c76b67ccfca0253d8b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 7 Dec 2007 12:26:32 -0800 Subject: Don't build rpctorture anymore - not maintained. Just remove. Remove all vestiges of pstring (except for smbctool as noted in previous commit). Jeremy (This used to be commit 4c32a22ac50ada3275d2ffba3c1aa08bee7d1549) --- source3/smbd/msdfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 98a41e4ec3..4ae735633b 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -481,7 +481,7 @@ static NTSTATUS dfs_path_lookup(TALLOC_CTX *ctx, * unix_convert later in the codepath. * If we needed to remember what we'd resolved in * dp->reqpath (as the original code did) we'd - * pstrcpy(localhost, dp->reqpath) on any code + * copy (localhost, dp->reqpath) on any code * path below that returns True - but I don't * think this is needed. JRA. */ -- cgit From 587cf54c61c9f1f7bcae431a82035fd942716c32 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 23 Jan 2008 11:04:10 +0100 Subject: strtok -> strtok_r (This used to be commit fd34ce437057bb34cdc37f4b066e424000d36789) --- source3/smbd/msdfs.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 4ae735633b..8ffa0f7751 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -288,12 +288,13 @@ static bool parse_msdfs_symlink(TALLOC_CTX *ctx, char **alt_path = NULL; int count = 0, i; struct referral *reflist; + char *saveptr; temp = talloc_strdup(ctx, target); if (!temp) { return False; } - prot = strtok(temp,":"); + prot = strtok_r(temp, ":", &saveptr); if (!prot) { DEBUG(0,("parse_msdfs_symlink: invalid path !\n")); return False; @@ -306,7 +307,7 @@ static bool parse_msdfs_symlink(TALLOC_CTX *ctx, /* parse out the alternate paths */ while((count Date: Wed, 2 Apr 2008 11:23:36 -0700 Subject: Fix MSDFS bug noticed by Ofir Azoulay . There is no reason to ensure the target host is ourselves, and this breaks MS clients in some cases. Jeremy. (This used to be commit c19fdf43d16ce9fba3e8e12e6192bac31837715e) --- source3/smbd/msdfs.c | 30 ------------------------------ 1 file changed, 30 deletions(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 8ffa0f7751..fb757a5f74 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -127,28 +127,6 @@ static NTSTATUS parse_dfs_path(const char *pathname, 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", - pdp->hostname, temp)); - /* - * Possibly client sent a local path by mistake. - * Try and convert to a local path. - */ - - pdp->hostname = eos_ptr; /* "" */ - pdp->servicename = eos_ptr; /* "" */ - - p = temp; - DEBUG(10,("parse_dfs_path: trying to convert %s " - "to a local path\n", - temp)); - goto local_path; - } - /* Parse out servicename. */ temp = p+1; p = strchr_m(temp,sepchar); @@ -751,14 +729,6 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx, return status; } - /* Verify hostname in path */ - if (!is_myname_or_ipaddr(pdp->hostname)) { - DEBUG(3, ("get_referred_path: Invalid hostname %s in path %s\n", - pdp->hostname, dfs_path)); - TALLOC_FREE(pdp); - return NT_STATUS_NOT_FOUND; - } - jucn->service_name = talloc_strdup(ctx, pdp->servicename); jucn->volume_name = talloc_strdup(ctx, pdp->reqpath); if (!jucn->service_name || !jucn->volume_name) { -- cgit From d62563342e8c83d67dbcfb0c4b8e2ed886742006 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 28 Apr 2008 10:31:49 +0200 Subject: Remove connection_struct->mem_ctx, connection_struct is its own parent (This used to be commit 559180f7d30606d1999399d954ceedc798c669a4) --- source3/smbd/msdfs.c | 81 +++++++++++++++++++++++----------------------------- 1 file changed, 36 insertions(+), 45 deletions(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index fb757a5f74..14062e129d 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -175,36 +175,37 @@ static NTSTATUS parse_dfs_path(const char *pathname, *********************************************************/ static NTSTATUS create_conn_struct(TALLOC_CTX *ctx, - connection_struct *conn, + connection_struct **pconn, int snum, const char *path) { + connection_struct *conn; char *connpath; - ZERO_STRUCTP(conn); + conn = TALLOC_ZERO_P(ctx, connection_struct); + if (conn == NULL) { + return NT_STATUS_NO_MEMORY; + } - connpath = talloc_strdup(ctx, path); + connpath = talloc_strdup(conn, path); if (!connpath) { + TALLOC_FREE(conn); return NT_STATUS_NO_MEMORY; } - connpath = talloc_string_sub(ctx, + connpath = talloc_string_sub(conn, connpath, "%S", lp_servicename(snum)); if (!connpath) { + TALLOC_FREE(conn); return NT_STATUS_NO_MEMORY; } /* needed for smbd_vfs_init() */ - if ((conn->mem_ctx=talloc_init("connection_struct")) == NULL) { - DEBUG(0,("talloc_init(connection_struct) failed!\n")); - return NT_STATUS_NO_MEMORY; - } - - if (!(conn->params = TALLOC_ZERO_P(conn->mem_ctx, - struct share_params))) { + if (!(conn->params = TALLOC_ZERO_P(conn, struct share_params))) { DEBUG(0, ("TALLOC failed\n")); + TALLOC_FREE(conn); return NT_STATUS_NO_MEMORY; } @@ -234,6 +235,8 @@ static NTSTATUS create_conn_struct(TALLOC_CTX *ctx, return status; } + *pconn = conn; + return NT_STATUS_OK; } @@ -709,8 +712,7 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx, int *consumedcntp, bool *self_referralp) { - struct connection_struct conns; - struct connection_struct *conn = &conns; + struct connection_struct *conn; char *targetpath = NULL; int snum; NTSTATUS status = NT_STATUS_NOT_FOUND; @@ -721,7 +723,6 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx, return NT_STATUS_NO_MEMORY; } - ZERO_STRUCT(conns); *self_referralp = False; status = parse_dfs_path(dfs_path, False, pdp, &dummy); @@ -825,7 +826,7 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx, return NT_STATUS_OK; } - status = create_conn_struct(ctx, conn, snum, lp_pathname(snum)); + status = create_conn_struct(ctx, &conn, snum, lp_pathname(snum)); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(pdp); return status; @@ -1251,7 +1252,7 @@ bool create_junction(TALLOC_CTX *ctx, static bool junction_to_local_path(const struct junction_map *jucn, char **pp_path_out, - connection_struct *conn_out) + connection_struct **conn_out) { int snum; @@ -1265,7 +1266,7 @@ static bool junction_to_local_path(const struct junction_map *jucn, return False; } - *pp_path_out = talloc_asprintf(conn_out->mem_ctx, + *pp_path_out = talloc_asprintf(conn_out, "%s/%s", lp_pathname(snum), jucn->volume_name); @@ -1280,20 +1281,17 @@ bool create_msdfs_link(const struct junction_map *jucn, { char *path = NULL; char *msdfs_link = NULL; - connection_struct conns; - connection_struct *conn = &conns; + connection_struct *conn; int i=0; bool insert_comma = False; bool ret = False; - ZERO_STRUCT(conns); - - if(!junction_to_local_path(jucn, &path, conn)) { + if(!junction_to_local_path(jucn, &path, &conn)) { return False; } /* Form the msdfs_link contents */ - msdfs_link = talloc_strdup(conn->mem_ctx, "msdfs:"); + msdfs_link = talloc_strdup(conn, "msdfs:"); if (!msdfs_link) { goto out; } @@ -1353,13 +1351,10 @@ out: bool remove_msdfs_link(const struct junction_map *jucn) { char *path = NULL; - connection_struct conns; - connection_struct *conn = &conns; + connection_struct *conn; bool ret = False; - ZERO_STRUCT(conns); - - if( junction_to_local_path(jucn, &path, conn) ) { + if( junction_to_local_path(jucn, &path, &conn) ) { if( SMB_VFS_UNLINK(conn, path) == 0 ) { ret = True; } @@ -1380,9 +1375,7 @@ static int count_dfs_links(TALLOC_CTX *ctx, int snum) char *dname = NULL; const char *connect_path = lp_pathname(snum); const char *msdfs_proxy = lp_msdfs_proxy(snum); - connection_struct conn; - - ZERO_STRUCT(conn); + connection_struct *conn; if(*connect_path == '\0') { return 0; @@ -1406,24 +1399,24 @@ static int count_dfs_links(TALLOC_CTX *ctx, int snum) } /* Now enumerate all dfs links */ - dirp = SMB_VFS_OPENDIR(&conn, ".", NULL, 0); + dirp = SMB_VFS_OPENDIR(conn, ".", NULL, 0); if(!dirp) { goto out; } - while ((dname = vfs_readdirname(&conn, dirp)) != NULL) { - if (is_msdfs_link(&conn, + while ((dname = vfs_readdirname(conn, dirp)) != NULL) { + if (is_msdfs_link(conn, dname, NULL)) { cnt++; } } - SMB_VFS_CLOSEDIR(&conn,dirp); + SMB_VFS_CLOSEDIR(conn,dirp); out: - conn_free_internal(&conn); + conn_free_internal(conn); return cnt; } @@ -1441,11 +1434,9 @@ static int form_junctions(TALLOC_CTX *ctx, const char *connect_path = lp_pathname(snum); char *service_name = lp_servicename(snum); const char *msdfs_proxy = lp_msdfs_proxy(snum); - connection_struct conn; + connection_struct *conn; struct referral *ref = NULL; - ZERO_STRUCT(conn); - if (jn_remain == 0) { return 0; } @@ -1501,21 +1492,21 @@ static int form_junctions(TALLOC_CTX *ctx, } /* Now enumerate all dfs links */ - dirp = SMB_VFS_OPENDIR(&conn, ".", NULL, 0); + dirp = SMB_VFS_OPENDIR(conn, ".", NULL, 0); if(!dirp) { goto out; } - while ((dname = vfs_readdirname(&conn, dirp)) != NULL) { + while ((dname = vfs_readdirname(conn, dirp)) != NULL) { char *link_target = NULL; if (cnt >= jn_remain) { - SMB_VFS_CLOSEDIR(&conn,dirp); + SMB_VFS_CLOSEDIR(conn,dirp); DEBUG(2, ("form_junctions: ran out of MSDFS " "junction slots")); goto out; } if (is_msdfs_link_internal(ctx, - &conn, + conn, dname, &link_target, NULL)) { if (parse_msdfs_symlink(ctx, @@ -1539,10 +1530,10 @@ static int form_junctions(TALLOC_CTX *ctx, out: if (dirp) { - SMB_VFS_CLOSEDIR(&conn,dirp); + SMB_VFS_CLOSEDIR(conn,dirp); } - conn_free_internal(&conn); + conn_free_internal(conn); return cnt; } -- cgit From 768c0d6b22f85ff9fe34922e30a822c69e1d5bd7 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 5 May 2008 12:45:12 +0200 Subject: Fix dfs_Enum: In form_junctions, correctly check for malloc failure (This used to be commit 1b1614c3261e1e93a2cad1f1063e28cbbb13f434) --- source3/smbd/msdfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 14062e129d..e321a8c8e4 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -1459,7 +1459,7 @@ static int form_junctions(TALLOC_CTX *ctx, */ 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) { + if (!jucn[cnt].service_name || !jucn[cnt].volume_name) { goto out; } jucn[cnt].referral_count = 1; -- cgit From bafe8d22fde97755bf35e8abf389d52b8993a551 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 13 May 2008 14:01:19 -0700 Subject: Fix bug #5460. The problem is RHEL5.0 shipped a CIFS client that sets the DFS bit on pathnames but doesn't send DFS paths. This causes lookups to fail as the smbd/msdfs.c code now just eats the first two parts of the pathname and uses the rest as the local path. The previous hostname check used to protect us from that as we knew that when the hostname was invalid it was a local path (and a broken client). I didn't want to put that check back in, but came up with another idea - even though the hostname can be a different one, the sharename must be valid on this machine. So we can check for a valid sharename instead. Jeremy. (This used to be commit e1cda82f6f7de3306a653af920756c1640057f2d) --- source3/smbd/msdfs.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index e321a8c8e4..6306745574 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -133,6 +133,16 @@ static NTSTATUS parse_dfs_path(const char *pathname, if(p == NULL) { pdp->servicename = temp; pdp->reqpath = eos_ptr; /* "" */ + /* Is this really our servicename ? */ + if (NULL == conn_find_byname(pdp->servicename)) { + DEBUG(10,("parse_dfs_path: %s is not our servicename\n", + pdp->servicename)); + p = temp; + DEBUG(10,("parse_dfs_path: trying to convert %s " + "to a local path\n", + temp)); + goto local_path; + } return NT_STATUS_OK; } *p = '\0'; -- cgit From b833615721d6d2e328908afeb1cb965ab5d38284 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 13 May 2008 15:02:11 -0700 Subject: Second part of patch for bug #5460. Cope with pathnames that don't look like \xxx\yyy, cope with arbitrary length. Jeremy. (This used to be commit 635035d999fcd8e06b70c8cb1137127c289dc9e6) --- source3/smbd/msdfs.c | 54 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 15 deletions(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 6306745574..4e673d8000 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -49,6 +49,7 @@ static NTSTATUS parse_dfs_path(const char *pathname, { char *pathname_local; char *p,*temp; + char *servicename; char *eos_ptr; NTSTATUS status = NT_STATUS_OK; char sepchar; @@ -128,25 +129,48 @@ static NTSTATUS parse_dfs_path(const char *pathname, DEBUG(10,("parse_dfs_path: hostname: %s\n",pdp->hostname)); /* Parse out servicename. */ - temp = p+1; - p = strchr_m(temp,sepchar); + servicename = p+1; + p = strchr_m(servicename,sepchar); + if (p) { + *p = '\0'; + } + + /* Is this really our servicename ? */ + if (NULL == conn_find_byname(servicename)) { + DEBUG(10,("parse_dfs_path: %s is not our servicename\n", + servicename)); + + /* + * Possibly client sent a local path by mistake. + * Try and convert to a local path. + */ + + pdp->hostname = eos_ptr; /* "" */ + pdp->servicename = eos_ptr; /* "" */ + + /* Repair the path - replace the sepchar's + we nulled out */ + servicename--; + *servicename = sepchar; + if (p) { + *p = sepchar; + } + + p = temp; + DEBUG(10,("parse_dfs_path: trying to convert %s " + "to a local path\n", + temp)); + goto local_path; + } + + pdp->servicename = servicename; + if(p == NULL) { - pdp->servicename = temp; + /* Client sent self referral \server\share. */ pdp->reqpath = eos_ptr; /* "" */ - /* Is this really our servicename ? */ - if (NULL == conn_find_byname(pdp->servicename)) { - DEBUG(10,("parse_dfs_path: %s is not our servicename\n", - pdp->servicename)); - p = temp; - DEBUG(10,("parse_dfs_path: trying to convert %s " - "to a local path\n", - temp)); - goto local_path; - } return NT_STATUS_OK; } - *p = '\0'; - pdp->servicename = temp; + DEBUG(10,("parse_dfs_path: servicename: %s\n",pdp->servicename)); p++; -- cgit From b8398d19af01cbdaec3af6c264e4d073fa85f78d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 13 May 2008 15:25:26 -0700 Subject: Fix debug message. Jeremy. (This used to be commit 08d168f0e5b8fb07e95a5118a839e0da53e9d363) --- source3/smbd/msdfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 4e673d8000..04b9b7deaa 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -165,14 +165,14 @@ static NTSTATUS parse_dfs_path(const char *pathname, pdp->servicename = servicename; + DEBUG(10,("parse_dfs_path: servicename: %s\n",pdp->servicename)); + if(p == NULL) { /* Client sent self referral \server\share. */ pdp->reqpath = eos_ptr; /* "" */ return NT_STATUS_OK; } - DEBUG(10,("parse_dfs_path: servicename: %s\n",pdp->servicename)); - p++; local_path: -- cgit From c7f5d24d813097a5bdb29c68bd30f4d117e083be Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 19 May 2008 13:11:00 -0700 Subject: Restructuring of code to fix #5460. Remove search by name code from conn, we were already doing the same check in the dfs_redirect() function, so move it into parse_dfs_path() instead. Jeremy. (This used to be commit 8a7c6df122c5e4a1d0f74ab0f1bc9376a0a8bcb1) --- source3/smbd/msdfs.c | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 04b9b7deaa..e4760ec461 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -36,13 +36,17 @@ 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.... + If conn != NULL then ensure the provided service is + the one pointed to by the connection. + 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, +static NTSTATUS parse_dfs_path(connection_struct *conn, + const char *pathname, bool allow_wcards, struct dfs_path *pdp, /* MUST BE TALLOCED */ bool *ppath_contains_wcard) @@ -136,7 +140,10 @@ static NTSTATUS parse_dfs_path(const char *pathname, } /* Is this really our servicename ? */ - if (NULL == conn_find_byname(servicename)) { + if (conn && !( strequal(servicename, lp_servicename(SNUM(conn))) + || (strequal(servicename, HOMES_NAME) + && strequal(lp_servicename(SNUM(conn)), + get_current_username()) )) ) { DEBUG(10,("parse_dfs_path: %s is not our servicename\n", servicename)); @@ -624,7 +631,7 @@ static NTSTATUS dfs_redirect(TALLOC_CTX *ctx, return NT_STATUS_NO_MEMORY; } - status = parse_dfs_path(path_in, search_wcard_flag, pdp, + status = parse_dfs_path(conn, path_in, search_wcard_flag, pdp, ppath_contains_wcard); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(pdp); @@ -665,17 +672,6 @@ static NTSTATUS dfs_redirect(TALLOC_CTX *ctx, return NT_STATUS_OK; } - 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(ctx, conn, path_in, pdp, search_wcard_flag, NULL, NULL); if (!NT_STATUS_IS_OK(status)) { @@ -759,7 +755,7 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx, *self_referralp = False; - status = parse_dfs_path(dfs_path, False, pdp, &dummy); + status = parse_dfs_path(NULL, dfs_path, False, pdp, &dummy); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -1245,7 +1241,7 @@ bool create_junction(TALLOC_CTX *ctx, if (!pdp) { return False; } - status = parse_dfs_path(dfs_path, False, pdp, &dummy); + status = parse_dfs_path(NULL, dfs_path, False, pdp, &dummy); if (!NT_STATUS_IS_OK(status)) { return False; } -- cgit From 50ab871813d8281760e0c70d454cba996e0b67d8 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 11 May 2008 11:26:33 +0200 Subject: Remove some references to get_current_username() and current_user_info (This used to be commit 344d69f95e217d16213eaa6b53141af6ab459708) --- source3/smbd/msdfs.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index e4760ec461..de57d8def2 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -672,6 +672,17 @@ static NTSTATUS dfs_redirect(TALLOC_CTX *ctx, return NT_STATUS_OK; } + if (!( strequal(pdp->servicename, lp_servicename(SNUM(conn))) + || (strequal(pdp->servicename, HOMES_NAME) + && strequal(lp_servicename(SNUM(conn)), + conn->server_info->sanitized_username) )) ) { + + /* The given sharename doesn't match this connection. */ + TALLOC_FREE(pdp); + + return NT_STATUS_OBJECT_PATH_NOT_FOUND; + } + status = dfs_path_lookup(ctx, conn, path_in, pdp, search_wcard_flag, NULL, NULL); if (!NT_STATUS_IS_OK(status)) { -- cgit From a8ae3bc317c9fb0c77798b361e54efff6cdb8a9b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 21 Jun 2008 16:39:05 +0200 Subject: Fix a double-closedir() in form_junctions() (This used to be commit 1d7ad0dea7ebf7a46af6e695797e5132264307d6) --- source3/smbd/msdfs.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index de57d8def2..25b22f4cc0 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -1541,7 +1541,6 @@ static int form_junctions(TALLOC_CTX *ctx, while ((dname = vfs_readdirname(conn, dirp)) != NULL) { char *link_target = NULL; if (cnt >= jn_remain) { - SMB_VFS_CLOSEDIR(conn,dirp); DEBUG(2, ("form_junctions: ran out of MSDFS " "junction slots")); goto out; -- cgit From 62f69165f6b66e149055ba431a48aab1a67c4215 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 22 Jun 2008 12:50:30 +0200 Subject: Fix an uninitialized variable access in callers of parse_msdfs_symlink At least form_junctions() does not initialize refcount, and I don't see it in get_referred_path(). For the latters, the callers might initialize it. But even if they did, I think parse_msdfs_symlink() should unconditionally return the number of referrals it found. I don't think it makes sense to count them up from somewhere else. (This used to be commit 73172113484a2c6c9af014f59e84707716c61a7d) --- source3/smbd/msdfs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 25b22f4cc0..bdcdc92df2 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -370,9 +370,10 @@ static bool parse_msdfs_symlink(TALLOC_CTX *ctx, reflist[i].ttl = REFERRAL_TTL; DEBUG(10, ("parse_msdfs_symlink: Created alt path: %s\n", reflist[i].alternate_path)); - *refcount += 1; } + *refcount = count; + TALLOC_FREE(alt_path); return True; } -- cgit From 65f7457583e7074ab5c07aa23f1281289fe66359 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 22 Jun 2008 13:06:35 +0200 Subject: Fix a crash in _dfs_Enum (cherry picked from commit 4a996476297963d4cb300b4d45c23e83a493c339) (This used to be commit 86cae83a7db87063ecd6e58eaa15f11441c45040) --- source3/smbd/msdfs.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index bdcdc92df2..84ee282372 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -1504,6 +1504,7 @@ static int form_junctions(TALLOC_CTX *ctx, if (!jucn[cnt].service_name || !jucn[cnt].volume_name) { goto out; } + jucn[cnt].comment = ""; jucn[cnt].referral_count = 1; ref = jucn[cnt].referral_list = TALLOC_ZERO_P(ctx, struct referral); @@ -1563,6 +1564,7 @@ static int form_junctions(TALLOC_CTX *ctx, !jucn[cnt].volume_name) { goto out; } + jucn[cnt].comment = ""; cnt++; } } -- cgit From b4587a7c78fc8452f87f114b07b574180a3ea159 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 22 Jun 2008 18:36:37 +0200 Subject: Fix an abort in junction_to_local_path (This used to be commit 587bd636cb70d09600111ced040adaa55af35d0f) --- source3/smbd/msdfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 84ee282372..df30257fcc 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -1308,7 +1308,7 @@ static bool junction_to_local_path(const struct junction_map *jucn, return False; } - *pp_path_out = talloc_asprintf(conn_out, + *pp_path_out = talloc_asprintf(*conn_out, "%s/%s", lp_pathname(snum), jucn->volume_name); -- cgit From a7e284c62d4b961780130a3ae8594094f1fb841d Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 22 Jun 2008 11:28:57 +0200 Subject: Reduce memory usage in form_junctions() a little bit (This used to be commit d031e6d8cabe2dd0b29e90d173d45843e145176a) --- source3/smbd/msdfs.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index df30257fcc..bc7cd81337 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -1567,6 +1567,7 @@ static int form_junctions(TALLOC_CTX *ctx, jucn[cnt].comment = ""; cnt++; } + TALLOC_FREE(link_target); } } -- cgit From 13ebf889b39e0b71f1f98198b0d003f5461d42a6 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 22 Jun 2008 20:33:28 +0200 Subject: Remove the "exists" parameter from create_msdfs_link Jeremy, setting "exists" to True in _dfs_Add prevented the initial creation of a new symlink for me, because the SMB_VFS_UNLINK failed. This also exists in 3.2. I only check it into 3.3 as I would like you to look at it first. Thanks, Volker (This used to be commit f58b098a4172949018e84c4d0c722d6eb9bba514) --- source3/smbd/msdfs.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index bc7cd81337..062ab804cc 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -1318,8 +1318,7 @@ static bool junction_to_local_path(const struct junction_map *jucn, return True; } -bool create_msdfs_link(const struct junction_map *jucn, - bool exists) +bool create_msdfs_link(const struct junction_map *jucn) { char *path = NULL; char *msdfs_link = NULL; @@ -1369,19 +1368,20 @@ bool create_msdfs_link(const struct junction_map *jucn, DEBUG(5,("create_msdfs_link: Creating new msdfs link: %s -> %s\n", path, msdfs_link)); - if(exists) { - if(SMB_VFS_UNLINK(conn,path)!=0) { + if(SMB_VFS_SYMLINK(conn, msdfs_link, path) < 0) { + if (errno == EEXIST) { + if(SMB_VFS_UNLINK(conn,path)!=0) { + goto out; + } + } + 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))); goto out; } } - 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))); - goto out; - } - ret = True; out: -- cgit From 344941bb49d91e6b382196c347e5259e133f506d Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 22 Jun 2008 22:19:10 +0200 Subject: Move the responsibility to keep the cwd from srv_dfs_nt to msdfs.c (This used to be commit 7db382588ac90fe250b72cf4cd07afb39fcae7c0) --- source3/smbd/msdfs.c | 70 +++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 53 insertions(+), 17 deletions(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 062ab804cc..8e83a6c17e 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -218,10 +218,12 @@ static NTSTATUS parse_dfs_path(connection_struct *conn, static NTSTATUS create_conn_struct(TALLOC_CTX *ctx, connection_struct **pconn, int snum, - const char *path) + const char *path, + char **poldcwd) { connection_struct *conn; char *connpath; + char *oldcwd; conn = TALLOC_ZERO_P(ctx, connection_struct); if (conn == NULL) { @@ -267,6 +269,14 @@ static NTSTATUS create_conn_struct(TALLOC_CTX *ctx, * user we will fail.... WTF ? JRA. */ + oldcwd = vfs_GetWd(ctx, conn); + if (oldcwd == NULL) { + NTSTATUS status = map_nt_error_from_unix(errno); + DEBUG(3, ("vfs_GetWd failed: %s\n", strerror(errno))); + conn_free_internal(conn); + return status; + } + 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. " @@ -277,6 +287,7 @@ static NTSTATUS create_conn_struct(TALLOC_CTX *ctx, } *pconn = conn; + *poldcwd = oldcwd; return NT_STATUS_OK; } @@ -760,6 +771,7 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx, NTSTATUS status = NT_STATUS_NOT_FOUND; bool dummy; struct dfs_path *pdp = TALLOC_P(ctx, struct dfs_path); + char *oldpath; if (!pdp) { return NT_STATUS_NO_MEMORY; @@ -868,7 +880,8 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx, return NT_STATUS_OK; } - status = create_conn_struct(ctx, &conn, snum, lp_pathname(snum)); + status = create_conn_struct(ctx, &conn, snum, lp_pathname(snum), + &oldpath); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(pdp); return status; @@ -883,6 +896,7 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx, if (!NT_STATUS_EQUAL(status, NT_STATUS_PATH_NOT_COVERED)) { DEBUG(3,("get_referred_path: No valid referrals for path %s\n", dfs_path)); + vfs_ChDir(conn, oldpath); conn_free_internal(conn); TALLOC_FREE(pdp); return status; @@ -894,11 +908,13 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx, &jucn->referral_count)) { DEBUG(3,("get_referred_path: failed to parse symlink " "target %s\n", targetpath )); + vfs_ChDir(conn, oldpath); conn_free_internal(conn); TALLOC_FREE(pdp); return NT_STATUS_NOT_FOUND; } + vfs_ChDir(conn, oldpath); conn_free_internal(conn); TALLOC_FREE(pdp); return NT_STATUS_OK; @@ -1293,18 +1309,20 @@ bool create_junction(TALLOC_CTX *ctx, **********************************************************************/ static bool junction_to_local_path(const struct junction_map *jucn, - char **pp_path_out, - connection_struct **conn_out) + char **pp_path_out, + connection_struct **conn_out, + char **oldpath) { int snum; + NTSTATUS status; snum = lp_servicenumber(jucn->service_name); if(snum < 0) { return False; } - if (!NT_STATUS_IS_OK(create_conn_struct(talloc_tos(), - conn_out, snum, - lp_pathname(snum)))) { + status = create_conn_struct(talloc_tos(), conn_out, snum, + lp_pathname(snum), oldpath); + if (!NT_STATUS_IS_OK(status)) { return False; } @@ -1313,6 +1331,8 @@ static bool junction_to_local_path(const struct junction_map *jucn, lp_pathname(snum), jucn->volume_name); if (!*pp_path_out) { + vfs_ChDir(*conn_out, *oldpath); + conn_free_internal(*conn_out); return False; } return True; @@ -1321,13 +1341,14 @@ static bool junction_to_local_path(const struct junction_map *jucn, bool create_msdfs_link(const struct junction_map *jucn) { char *path = NULL; + char *cwd; char *msdfs_link = NULL; connection_struct *conn; int i=0; bool insert_comma = False; bool ret = False; - if(!junction_to_local_path(jucn, &path, &conn)) { + if(!junction_to_local_path(jucn, &path, &conn, &cwd)) { return False; } @@ -1385,7 +1406,7 @@ bool create_msdfs_link(const struct junction_map *jucn) ret = True; out: - + vfs_ChDir(conn, cwd); conn_free_internal(conn); return ret; } @@ -1393,15 +1414,19 @@ out: bool remove_msdfs_link(const struct junction_map *jucn) { char *path = NULL; + char *cwd; connection_struct *conn; bool ret = False; - if( junction_to_local_path(jucn, &path, &conn) ) { - if( SMB_VFS_UNLINK(conn, path) == 0 ) { - ret = True; - } + if (!junction_to_local_path(jucn, &path, &conn, &cwd)) { + return false; + } + + if( SMB_VFS_UNLINK(conn, path) == 0 ) { + ret = True; } + vfs_ChDir(conn, cwd); conn_free_internal(conn); return ret; } @@ -1418,6 +1443,8 @@ static int count_dfs_links(TALLOC_CTX *ctx, int snum) const char *connect_path = lp_pathname(snum); const char *msdfs_proxy = lp_msdfs_proxy(snum); connection_struct *conn; + NTSTATUS status; + char *cwd; if(*connect_path == '\0') { return 0; @@ -1427,8 +1454,11 @@ static int count_dfs_links(TALLOC_CTX *ctx, int snum) * Fake up a connection struct for the VFS layer. */ - if (!NT_STATUS_IS_OK(create_conn_struct(talloc_tos(), - &conn, snum, connect_path))) { + status = create_conn_struct(talloc_tos(), &conn, snum, connect_path, + &cwd); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(3, ("create_conn_struct failed: %s\n", + nt_errstr(status))); return 0; } @@ -1457,7 +1487,7 @@ static int count_dfs_links(TALLOC_CTX *ctx, int snum) SMB_VFS_CLOSEDIR(conn,dirp); out: - + vfs_ChDir(conn, cwd); conn_free_internal(conn); return cnt; } @@ -1478,6 +1508,8 @@ static int form_junctions(TALLOC_CTX *ctx, const char *msdfs_proxy = lp_msdfs_proxy(snum); connection_struct *conn; struct referral *ref = NULL; + char *cwd; + NTSTATUS status; if (jn_remain == 0) { return 0; @@ -1491,7 +1523,10 @@ static int form_junctions(TALLOC_CTX *ctx, * Fake up a connection struct for the VFS layer. */ - if (!NT_STATUS_IS_OK(create_conn_struct(ctx, &conn, snum, connect_path))) { + status = create_conn_struct(ctx, &conn, snum, connect_path, &cwd); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(3, ("create_conn_struct failed: %s\n", + nt_errstr(status))); return 0; } @@ -1577,6 +1612,7 @@ out: SMB_VFS_CLOSEDIR(conn,dirp); } + vfs_ChDir(conn, cwd); conn_free_internal(conn); return cnt; } -- cgit From 49403ee82f5b4a40f4feacd441b2e27f23e6c156 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 27 Jul 2008 17:56:48 +0200 Subject: Make create_conn_struct() public (This used to be commit e115e2582256c34e6905afc8c2929efd6ea61088) --- source3/smbd/msdfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/msdfs.c') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 8e83a6c17e..32240ff0d5 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -215,7 +215,7 @@ static NTSTATUS parse_dfs_path(connection_struct *conn, Note this CHANGES CWD !!!! JRA. *********************************************************/ -static NTSTATUS create_conn_struct(TALLOC_CTX *ctx, +NTSTATUS create_conn_struct(TALLOC_CTX *ctx, connection_struct **pconn, int snum, const char *path, -- cgit