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