X-Git-Url: http://git.samba.org/samba.git/?a=blobdiff_plain;f=source3%2Fsmbd%2Fmsdfs.c;h=17caa36d5d129c3316c64e2830b6b7c83c25f501;hb=0e771263eed0b9bc364ce523765ea17dd1192841;hp=98a41e4ec3172eb7884a6ac654f31e9636e84ab6;hpb=2b3c44e4fb980335c22abcc07a88f32b13e5918f;p=ira%2Fwip.git diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 98a41e4ec31..17caa36d5d1 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -22,8 +22,9 @@ #define DBGC_CLASS DBGC_MSDFS #include "includes.h" - -extern uint32 global_client_caps; +#include "system/filesys.h" +#include "smbd/globals.h" +#include "msdfs.h" /********************************************************************** Parse a DFS pathname of the form \hostname\service\reqpath @@ -36,19 +37,25 @@ extern uint32 global_client_caps; SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES bit and then send a local path, we have to cope with that too.... + If conn != NULL then ensure the provided service is + the one pointed to by the connection. + This version does everything using pointers within one copy of the pathname string, talloced on the struct dfs_path pointer (which must be talloced). This may be too clever to live.... JRA. **********************************************************************/ -static NTSTATUS parse_dfs_path(const char *pathname, +static NTSTATUS parse_dfs_path(connection_struct *conn, + const char *pathname, bool allow_wcards, struct dfs_path *pdp, /* MUST BE TALLOCED */ bool *ppath_contains_wcard) { + struct smbd_server_connection *sconn = smbd_server_conn; char *pathname_local; char *p,*temp; + char *servicename; char *eos_ptr; NTSTATUS status = NT_STATUS_OK; char sepchar; @@ -73,7 +80,7 @@ static NTSTATUS parse_dfs_path(const char *pathname, sepchar = pdp->posix_path ? '/' : '\\'; - if (*pathname != sepchar) { + if (!sconn->using_smb2 && (*pathname != sepchar)) { DEBUG(10,("parse_dfs_path: path %s doesn't start with %c\n", pathname, sepchar )); /* @@ -127,13 +134,21 @@ static NTSTATUS parse_dfs_path(const char *pathname, DEBUG(10,("parse_dfs_path: hostname: %s\n",pdp->hostname)); - /* If we got a hostname, is it ours (or an IP address) ? */ - if (!is_myname_or_ipaddr(pdp->hostname)) { - /* Repair path. */ - *p = sepchar; - DEBUG(10,("parse_dfs_path: hostname %s isn't ours. " - "Try local path from path %s\n", - pdp->hostname, temp)); + /* Parse out servicename. */ + servicename = p+1; + p = strchr_m(servicename,sepchar); + if (p) { + *p = '\0'; + } + + /* Is this really our servicename ? */ + if (conn && !( strequal(servicename, lp_servicename(SNUM(conn))) + || (strequal(servicename, HOMES_NAME) + && strequal(lp_servicename(SNUM(conn)), + get_current_username()) )) ) { + DEBUG(10,("parse_dfs_path: %s is not our servicename\n", + servicename)); + /* * Possibly client sent a local path by mistake. * Try and convert to a local path. @@ -142,6 +157,14 @@ static NTSTATUS parse_dfs_path(const char *pathname, pdp->hostname = eos_ptr; /* "" */ pdp->servicename = eos_ptr; /* "" */ + /* Repair the path - replace the sepchar's + we nulled out */ + servicename--; + *servicename = sepchar; + if (p) { + *p = sepchar; + } + p = temp; DEBUG(10,("parse_dfs_path: trying to convert %s " "to a local path\n", @@ -149,17 +172,15 @@ static NTSTATUS parse_dfs_path(const char *pathname, goto local_path; } - /* Parse out servicename. */ - temp = p+1; - p = strchr_m(temp,sepchar); + pdp->servicename = servicename; + + DEBUG(10,("parse_dfs_path: servicename: %s\n",pdp->servicename)); + if(p == NULL) { - pdp->servicename = temp; + /* Client sent self referral \server\share. */ pdp->reqpath = eos_ptr; /* "" */ return NT_STATUS_OK; } - *p = '\0'; - pdp->servicename = temp; - DEBUG(10,("parse_dfs_path: servicename: %s\n",pdp->servicename)); p++; @@ -193,69 +214,110 @@ static NTSTATUS parse_dfs_path(const char *pathname, /******************************************************** Fake up a connection struct for the VFS layer. - Note this CHANGES CWD !!!! JRA. + Note: this performs a vfs connect and CHANGES CWD !!!! JRA. *********************************************************/ -static NTSTATUS create_conn_struct(TALLOC_CTX *ctx, - connection_struct *conn, +NTSTATUS create_conn_struct(TALLOC_CTX *ctx, + connection_struct **pconn, int snum, - const char *path) + const char *path, + const struct auth_serversupplied_info *session_info, + char **poldcwd) { + connection_struct *conn; char *connpath; + char *oldcwd; + const char *vfs_user; - ZERO_STRUCTP(conn); + conn = TALLOC_ZERO_P(ctx, connection_struct); + if (conn == NULL) { + return NT_STATUS_NO_MEMORY; + } - connpath = talloc_strdup(ctx, path); + connpath = talloc_strdup(conn, path); if (!connpath) { + TALLOC_FREE(conn); return NT_STATUS_NO_MEMORY; } - connpath = talloc_string_sub(ctx, + connpath = talloc_string_sub(conn, connpath, "%S", lp_servicename(snum)); if (!connpath) { + TALLOC_FREE(conn); return NT_STATUS_NO_MEMORY; } /* needed for smbd_vfs_init() */ - if ((conn->mem_ctx=talloc_init("connection_struct")) == NULL) { - DEBUG(0,("talloc_init(connection_struct) failed!\n")); - return NT_STATUS_NO_MEMORY; - } - - if (!(conn->params = TALLOC_ZERO_P(conn->mem_ctx, - struct share_params))) { + if (!(conn->params = TALLOC_ZERO_P(conn, struct share_params))) { DEBUG(0, ("TALLOC failed\n")); + TALLOC_FREE(conn); return NT_STATUS_NO_MEMORY; } conn->params->service = snum; + conn->sconn = smbd_server_conn; + conn->sconn->num_tcons_open++; + + if (session_info != NULL) { + conn->session_info = copy_serverinfo(conn, session_info); + if (conn->session_info == NULL) { + DEBUG(0, ("copy_serverinfo failed\n")); + TALLOC_FREE(conn); + return NT_STATUS_NO_MEMORY; + } + vfs_user = conn->session_info->unix_name; + } else { + /* use current authenticated user in absence of session_info */ + vfs_user = get_current_username(); + } + set_conn_connectpath(conn, connpath); if (!smbd_vfs_init(conn)) { NTSTATUS status = map_nt_error_from_unix(errno); DEBUG(0,("create_conn_struct: smbd_vfs_init failed.\n")); - conn_free_internal(conn); + conn_free(conn); return status; } + /* this must be the first filesystem operation that we do */ + if (SMB_VFS_CONNECT(conn, lp_servicename(snum), vfs_user) < 0) { + DEBUG(0,("VFS connect failed!\n")); + conn_free(conn); + return NT_STATUS_UNSUCCESSFUL; + } + + conn->fs_capabilities = SMB_VFS_FS_CAPABILITIES(conn, &conn->ts_res); + /* * 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. */ + oldcwd = vfs_GetWd(ctx, conn); + if (oldcwd == NULL) { + NTSTATUS status = map_nt_error_from_unix(errno); + DEBUG(3, ("vfs_GetWd failed: %s\n", strerror(errno))); + conn_free(conn); + return status; + } + if (vfs_ChDir(conn,conn->connectpath) != 0) { NTSTATUS status = map_nt_error_from_unix(errno); DEBUG(3,("create_conn_struct: Can't ChDir to new conn path %s. " "Error was %s\n", conn->connectpath, strerror(errno) )); - conn_free_internal(conn); + conn_free(conn); return status; } + *pconn = conn; + *poldcwd = oldcwd; + return NT_STATUS_OK; } @@ -288,12 +350,13 @@ static bool parse_msdfs_symlink(TALLOC_CTX *ctx, char **alt_path = NULL; int count = 0, i; struct referral *reflist; + char *saveptr; temp = talloc_strdup(ctx, target); if (!temp) { return False; } - prot = strtok(temp,":"); + prot = strtok_r(temp, ":", &saveptr); if (!prot) { DEBUG(0,("parse_msdfs_symlink: invalid path !\n")); return False; @@ -306,7 +369,7 @@ static bool parse_msdfs_symlink(TALLOC_CTX *ctx, /* parse out the alternate paths */ while((countst_mode)) { + if (!S_ISLNK(smb_fname.st.st_ex_mode)) { DEBUG(5,("is_msdfs_link_read_target: %s is not a link.\n", path)); goto err; } + if (sbufp != NULL) { + *sbufp = smb_fname.st; + } referral_len = SMB_VFS_READLINK(conn, path, link_target, bufsize - 1); if (referral_len == -1) { @@ -465,9 +534,8 @@ static NTSTATUS dfs_path_lookup(TALLOC_CTX *ctx, { char *p = NULL; char *q = NULL; - SMB_STRUCT_STAT sbuf; NTSTATUS status; - char *localpath = NULL; + struct smb_filename *smb_fname = NULL; char *canon_dfspath = NULL; /* Canonicalized dfs path. (only '/' components). */ @@ -481,25 +549,37 @@ static NTSTATUS dfs_path_lookup(TALLOC_CTX *ctx, * unix_convert later in the codepath. * If we needed to remember what we'd resolved in * dp->reqpath (as the original code did) we'd - * pstrcpy(localhost, dp->reqpath) on any code + * copy (localhost, dp->reqpath) on any code * path below that returns True - but I don't * think this is needed. JRA. */ - status = unix_convert(ctx, conn, pdp->reqpath, search_flag, &localpath, - NULL, &sbuf); - if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status, - NT_STATUS_OBJECT_PATH_NOT_FOUND)) { - return status; + status = unix_convert(ctx, conn, pdp->reqpath, &smb_fname, + search_flag ? UCF_ALWAYS_ALLOW_WCARD_LCOMP : 0); + + if (!NT_STATUS_IS_OK(status)) { + if (!NT_STATUS_EQUAL(status, + NT_STATUS_OBJECT_PATH_NOT_FOUND)) { + return status; + } + + /* Create an smb_fname to use below. */ + status = create_synthetic_smb_fname(ctx, pdp->reqpath, NULL, + NULL, &smb_fname); + if (!NT_STATUS_IS_OK(status)) { + return status; + } } /* Optimization - check if we can redirect the whole path. */ - if (is_msdfs_link_internal(ctx, conn, localpath, pp_targetpath, NULL)) { + if (is_msdfs_link_internal(ctx, conn, smb_fname->base_name, + pp_targetpath, NULL)) { if (search_flag) { DEBUG(6,("dfs_path_lookup (FindFirst) No redirection " "for dfs link %s.\n", dfspath)); - return NT_STATUS_OK; + status = NT_STATUS_OK; + goto out; } DEBUG(6,("dfs_path_lookup: %s resolves to a " @@ -509,7 +589,8 @@ static NTSTATUS dfs_path_lookup(TALLOC_CTX *ctx, if (consumedcntp) { *consumedcntp = strlen(dfspath); } - return NT_STATUS_PATH_NOT_COVERED; + status = NT_STATUS_PATH_NOT_COVERED; + goto out; } /* Prepare to test only for '/' components in the given path, @@ -518,7 +599,8 @@ static NTSTATUS dfs_path_lookup(TALLOC_CTX *ctx, canon_dfspath = talloc_strdup(ctx, dfspath); if (!canon_dfspath) { - return NT_STATUS_NO_MEMORY; + status = NT_STATUS_NO_MEMORY; + goto out; } if (!pdp->posix_path) { string_replace(canon_dfspath, '\\', '/'); @@ -540,7 +622,7 @@ static NTSTATUS dfs_path_lookup(TALLOC_CTX *ctx, * DFS path. If we hit a DFS link then we're done. */ - p = strrchr_m(localpath, '/'); + p = strrchr_m(smb_fname->base_name, '/'); if (consumedcntp) { q = strrchr_m(canon_dfspath, '/'); } @@ -552,9 +634,11 @@ static NTSTATUS dfs_path_lookup(TALLOC_CTX *ctx, } if (is_msdfs_link_internal(ctx, conn, - localpath, pp_targetpath, NULL)) { + smb_fname->base_name, pp_targetpath, + NULL)) { DEBUG(4, ("dfs_path_lookup: Redirecting %s because " - "parent %s is dfs link\n", dfspath, localpath)); + "parent %s is dfs link\n", dfspath, + smb_fname_str_dbg(smb_fname))); if (consumedcntp) { *consumedcntp = strlen(canon_dfspath); @@ -564,11 +648,12 @@ static NTSTATUS dfs_path_lookup(TALLOC_CTX *ctx, *consumedcntp)); } - return NT_STATUS_PATH_NOT_COVERED; + status = NT_STATUS_PATH_NOT_COVERED; + goto out; } /* Step back on the filesystem. */ - p = strrchr_m(localpath, '/'); + p = strrchr_m(smb_fname->base_name, '/'); if (consumedcntp) { /* And in the canonicalized dfs path. */ @@ -576,7 +661,10 @@ static NTSTATUS dfs_path_lookup(TALLOC_CTX *ctx, } } - return NT_STATUS_OK; + status = NT_STATUS_OK; + out: + TALLOC_FREE(smb_fname); + return status; } /***************************************************************** @@ -608,7 +696,7 @@ static NTSTATUS dfs_redirect(TALLOC_CTX *ctx, return NT_STATUS_NO_MEMORY; } - status = parse_dfs_path(path_in, search_wcard_flag, pdp, + status = parse_dfs_path(conn, path_in, search_wcard_flag, pdp, ppath_contains_wcard); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(pdp); @@ -652,7 +740,7 @@ static NTSTATUS dfs_redirect(TALLOC_CTX *ctx, if (!( strequal(pdp->servicename, lp_servicename(SNUM(conn))) || (strequal(pdp->servicename, HOMES_NAME) && strequal(lp_servicename(SNUM(conn)), - get_current_username()) )) ) { + conn->session_info->sanitized_username) )) ) { /* The given sharename doesn't match this connection. */ TALLOC_FREE(pdp); @@ -730,34 +818,25 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx, int *consumedcntp, bool *self_referralp) { - struct connection_struct conns; - struct connection_struct *conn = &conns; + struct connection_struct *conn; char *targetpath = NULL; int snum; NTSTATUS status = NT_STATUS_NOT_FOUND; bool dummy; struct dfs_path *pdp = TALLOC_P(ctx, struct dfs_path); + char *oldpath; if (!pdp) { return NT_STATUS_NO_MEMORY; } - ZERO_STRUCT(conns); *self_referralp = False; - status = parse_dfs_path(dfs_path, False, pdp, &dummy); + status = parse_dfs_path(NULL, dfs_path, False, pdp, &dummy); if (!NT_STATUS_IS_OK(status)) { return status; } - /* Verify hostname in path */ - if (!is_myname_or_ipaddr(pdp->hostname)) { - DEBUG(3, ("get_referred_path: Invalid hostname %s in path %s\n", - pdp->hostname, dfs_path)); - TALLOC_FREE(pdp); - return NT_STATUS_NOT_FOUND; - } - jucn->service_name = talloc_strdup(ctx, pdp->servicename); jucn->volume_name = talloc_strdup(ctx, pdp->reqpath); if (!jucn->service_name || !jucn->volume_name) { @@ -768,11 +847,13 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx, /* Verify the share is a dfs root */ snum = lp_servicenumber(jucn->service_name); if(snum < 0) { - fstring service_name; - fstrcpy(service_name, jucn->service_name); - if ((snum = find_service(service_name)) < 0) { + char *service_name = NULL; + if ((snum = find_service(ctx, jucn->service_name, &service_name)) < 0) { return NT_STATUS_NOT_FOUND; } + if (!service_name) { + return NT_STATUS_NO_MEMORY; + } TALLOC_FREE(jucn->service_name); jucn->service_name = talloc_strdup(ctx, service_name); if (!jucn->service_name) { @@ -854,7 +935,8 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx, return NT_STATUS_OK; } - status = create_conn_struct(ctx, conn, snum, lp_pathname(snum)); + status = create_conn_struct(ctx, &conn, snum, lp_pathname(snum), + NULL, &oldpath); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(pdp); return status; @@ -869,9 +951,7 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx, if (!NT_STATUS_EQUAL(status, NT_STATUS_PATH_NOT_COVERED)) { DEBUG(3,("get_referred_path: No valid referrals for path %s\n", dfs_path)); - conn_free_internal(conn); - TALLOC_FREE(pdp); - return status; + goto err_exit; } /* We know this is a valid dfs link. Parse the targetpath. */ @@ -880,20 +960,22 @@ NTSTATUS get_referred_path(TALLOC_CTX *ctx, &jucn->referral_count)) { 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; + status = NT_STATUS_NOT_FOUND; + goto err_exit; } - conn_free_internal(conn); + status = NT_STATUS_OK; + err_exit: + vfs_ChDir(conn, oldpath); + SMB_VFS_DISCONNECT(conn); + conn_free(conn); TALLOC_FREE(pdp); - return NT_STATUS_OK; + return status; } static int setup_ver2_dfs_referral(const char *pathname, char **ppdata, struct junction_map *junction, - int consumedcnt, bool self_referral) { char* pdata = *ppdata; @@ -958,7 +1040,8 @@ static int setup_ver2_dfs_referral(const char *pathname, memcpy(pdata+uni_reqpathoffset2,uni_requestedpath,requestedpathlen); /* create the header */ - SSVAL(pdata,0,consumedcnt * 2); /* path consumed */ + SSVAL(pdata,0,requestedpathlen - 2); /* UCS2 of path consumed minus + 2 byte null */ /* number of referral in this pkt */ SSVAL(pdata,2,junction->referral_count); if(self_referral) { @@ -1007,7 +1090,6 @@ static int setup_ver2_dfs_referral(const char *pathname, static int setup_ver3_dfs_referral(const char *pathname, char **ppdata, struct junction_map *junction, - int consumedcnt, bool self_referral) { char *pdata = *ppdata; @@ -1054,7 +1136,8 @@ static int setup_ver3_dfs_referral(const char *pathname, *ppdata = pdata; /* create the header */ - SSVAL(pdata,0,consumedcnt * 2); /* path consumed */ + SSVAL(pdata,0,reqpathlen - 2); /* UCS2 of path consumed minus + 2 byte null */ SSVAL(pdata,2,junction->referral_count); /* number of referral */ if(self_referral) { SIVAL(pdata,4,DFSREF_REFERRAL_SERVER | DFSREF_STORAGE_SERVER); @@ -1194,11 +1277,11 @@ int setup_dfs_referral(connection_struct *orig_conn, case 2: reply_size = setup_ver2_dfs_referral(pathnamep, ppdata, junction, - consumedcnt, self_referral); + self_referral); break; case 3: reply_size = setup_ver3_dfs_referral(pathnamep, ppdata, - junction, consumedcnt, self_referral); + junction, self_referral); break; default: DEBUG(0,("setup_dfs_referral: Invalid dfs referral " @@ -1239,7 +1322,7 @@ bool create_junction(TALLOC_CTX *ctx, if (!pdp) { return False; } - status = parse_dfs_path(dfs_path, False, pdp, &dummy); + status = parse_dfs_path(NULL, dfs_path, False, pdp, &dummy); if (!NT_STATUS_IS_OK(status)) { return False; } @@ -1279,50 +1362,52 @@ bool create_junction(TALLOC_CTX *ctx, **********************************************************************/ static bool junction_to_local_path(const struct junction_map *jucn, - char **pp_path_out, - connection_struct *conn_out) + char **pp_path_out, + connection_struct **conn_out, + char **oldpath) { int snum; + NTSTATUS status; snum = lp_servicenumber(jucn->service_name); if(snum < 0) { return False; } - if (!NT_STATUS_IS_OK(create_conn_struct(talloc_tos(), - conn_out, snum, - lp_pathname(snum)))) { + status = create_conn_struct(talloc_tos(), conn_out, snum, + lp_pathname(snum), NULL, oldpath); + if (!NT_STATUS_IS_OK(status)) { return False; } - *pp_path_out = talloc_asprintf(conn_out->mem_ctx, + *pp_path_out = talloc_asprintf(*conn_out, "%s/%s", lp_pathname(snum), jucn->volume_name); if (!*pp_path_out) { + vfs_ChDir(*conn_out, *oldpath); + SMB_VFS_DISCONNECT(*conn_out); + conn_free(*conn_out); return False; } return True; } -bool create_msdfs_link(const struct junction_map *jucn, - bool exists) +bool create_msdfs_link(const struct junction_map *jucn) { char *path = NULL; + char *cwd; char *msdfs_link = NULL; - connection_struct conns; - connection_struct *conn = &conns; + connection_struct *conn; int i=0; bool insert_comma = False; bool ret = False; - ZERO_STRUCT(conns); - - if(!junction_to_local_path(jucn, &path, conn)) { + if(!junction_to_local_path(jucn, &path, &conn, &cwd)) { return False; } /* Form the msdfs_link contents */ - msdfs_link = talloc_strdup(conn->mem_ctx, "msdfs:"); + msdfs_link = talloc_strdup(conn, "msdfs:"); if (!msdfs_link) { goto out; } @@ -1358,43 +1443,71 @@ bool create_msdfs_link(const struct junction_map *jucn, DEBUG(5,("create_msdfs_link: Creating new msdfs link: %s -> %s\n", path, msdfs_link)); - if(exists) { - if(SMB_VFS_UNLINK(conn,path)!=0) { + if(SMB_VFS_SYMLINK(conn, msdfs_link, path) < 0) { + if (errno == EEXIST) { + struct smb_filename *smb_fname = NULL; + NTSTATUS status; + + status = create_synthetic_smb_fname(talloc_tos(), path, + NULL, NULL, + &smb_fname); + if (!NT_STATUS_IS_OK(status)) { + errno = map_errno_from_nt_status(status); + goto out; + } + + if(SMB_VFS_UNLINK(conn, smb_fname)!=0) { + TALLOC_FREE(smb_fname); + goto out; + } + TALLOC_FREE(smb_fname); + } + if (SMB_VFS_SYMLINK(conn, msdfs_link, path) < 0) { + DEBUG(1,("create_msdfs_link: symlink failed " + "%s -> %s\nError: %s\n", + path, msdfs_link, strerror(errno))); goto out; } } - if(SMB_VFS_SYMLINK(conn, msdfs_link, path) < 0) { - DEBUG(1,("create_msdfs_link: symlink failed " - "%s -> %s\nError: %s\n", - path, msdfs_link, strerror(errno))); - goto out; - } - ret = True; out: - - conn_free_internal(conn); + vfs_ChDir(conn, cwd); + SMB_VFS_DISCONNECT(conn); + conn_free(conn); return ret; } bool remove_msdfs_link(const struct junction_map *jucn) { char *path = NULL; - connection_struct conns; - connection_struct *conn = &conns; + char *cwd; + connection_struct *conn; bool ret = False; + struct smb_filename *smb_fname = NULL; + NTSTATUS status; - ZERO_STRUCT(conns); + if (!junction_to_local_path(jucn, &path, &conn, &cwd)) { + return false; + } - if( junction_to_local_path(jucn, &path, conn) ) { - if( SMB_VFS_UNLINK(conn, path) == 0 ) { - ret = True; - } + status = create_synthetic_smb_fname(talloc_tos(), path, + NULL, NULL, + &smb_fname); + if (!NT_STATUS_IS_OK(status)) { + errno = map_errno_from_nt_status(status); + return false; + } + + if( SMB_VFS_UNLINK(conn, smb_fname) == 0 ) { + ret = True; } - conn_free_internal(conn); + TALLOC_FREE(smb_fname); + vfs_ChDir(conn, cwd); + SMB_VFS_DISCONNECT(conn); + conn_free(conn); return ret; } @@ -1406,12 +1519,13 @@ static int count_dfs_links(TALLOC_CTX *ctx, int snum) { size_t cnt = 0; SMB_STRUCT_DIR *dirp = NULL; - char *dname = NULL; + const char *dname = NULL; + char *talloced = NULL; const char *connect_path = lp_pathname(snum); const char *msdfs_proxy = lp_msdfs_proxy(snum); - connection_struct conn; - - ZERO_STRUCT(conn); + connection_struct *conn; + NTSTATUS status; + char *cwd; if(*connect_path == '\0') { return 0; @@ -1421,8 +1535,11 @@ static int count_dfs_links(TALLOC_CTX *ctx, int snum) * Fake up a connection struct for the VFS layer. */ - if (!NT_STATUS_IS_OK(create_conn_struct(talloc_tos(), - &conn, snum, connect_path))) { + status = create_conn_struct(talloc_tos(), &conn, snum, connect_path, + NULL, &cwd); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(3, ("create_conn_struct failed: %s\n", + nt_errstr(status))); return 0; } @@ -1435,24 +1552,27 @@ static int count_dfs_links(TALLOC_CTX *ctx, int snum) } /* Now enumerate all dfs links */ - dirp = SMB_VFS_OPENDIR(&conn, ".", NULL, 0); + dirp = SMB_VFS_OPENDIR(conn, ".", NULL, 0); if(!dirp) { goto out; } - while ((dname = vfs_readdirname(&conn, dirp)) != NULL) { - if (is_msdfs_link(&conn, + while ((dname = vfs_readdirname(conn, dirp, NULL, &talloced)) + != NULL) { + if (is_msdfs_link(conn, dname, NULL)) { cnt++; } + TALLOC_FREE(talloced); } - SMB_VFS_CLOSEDIR(&conn,dirp); + SMB_VFS_CLOSEDIR(conn,dirp); out: - - conn_free_internal(&conn); + vfs_ChDir(conn, cwd); + SMB_VFS_DISCONNECT(conn); + conn_free(conn); return cnt; } @@ -1466,14 +1586,15 @@ static int form_junctions(TALLOC_CTX *ctx, { size_t cnt = 0; SMB_STRUCT_DIR *dirp = NULL; - char *dname = NULL; + const char *dname = NULL; + char *talloced = 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; + connection_struct *conn; struct referral *ref = NULL; - - ZERO_STRUCT(conn); + char *cwd; + NTSTATUS status; if (jn_remain == 0) { return 0; @@ -1487,7 +1608,11 @@ static int form_junctions(TALLOC_CTX *ctx, * Fake up a connection struct for the VFS layer. */ - if (!NT_STATUS_IS_OK(create_conn_struct(ctx, &conn, snum, connect_path))) { + status = create_conn_struct(ctx, &conn, snum, connect_path, NULL, + &cwd); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(3, ("create_conn_struct failed: %s\n", + nt_errstr(status))); return 0; } @@ -1497,9 +1622,10 @@ static int form_junctions(TALLOC_CTX *ctx, */ jucn[cnt].service_name = talloc_strdup(ctx,service_name); jucn[cnt].volume_name = talloc_strdup(ctx, ""); - if (!jucn[cnt].service_name || jucn[cnt].volume_name) { + if (!jucn[cnt].service_name || !jucn[cnt].volume_name) { goto out; } + jucn[cnt].comment = ""; jucn[cnt].referral_count = 1; ref = jucn[cnt].referral_list = TALLOC_ZERO_P(ctx, struct referral); @@ -1530,21 +1656,22 @@ static int form_junctions(TALLOC_CTX *ctx, } /* Now enumerate all dfs links */ - dirp = SMB_VFS_OPENDIR(&conn, ".", NULL, 0); + dirp = SMB_VFS_OPENDIR(conn, ".", NULL, 0); if(!dirp) { goto out; } - while ((dname = vfs_readdirname(&conn, dirp)) != NULL) { + while ((dname = vfs_readdirname(conn, dirp, NULL, &talloced)) + != NULL) { char *link_target = NULL; if (cnt >= jn_remain) { - SMB_VFS_CLOSEDIR(&conn,dirp); DEBUG(2, ("form_junctions: ran out of MSDFS " "junction slots")); + TALLOC_FREE(talloced); goto out; } if (is_msdfs_link_internal(ctx, - &conn, + conn, dname, &link_target, NULL)) { if (parse_msdfs_symlink(ctx, @@ -1558,20 +1685,25 @@ static int form_junctions(TALLOC_CTX *ctx, dname); if (!jucn[cnt].service_name || !jucn[cnt].volume_name) { + TALLOC_FREE(talloced); goto out; } + jucn[cnt].comment = ""; cnt++; } + TALLOC_FREE(link_target); } + TALLOC_FREE(talloced); } out: if (dirp) { - SMB_VFS_CLOSEDIR(&conn,dirp); + SMB_VFS_CLOSEDIR(conn,dirp); } - conn_free_internal(&conn); + vfs_ChDir(conn, cwd); + conn_free(conn); return cnt; } @@ -1619,57 +1751,33 @@ struct junction_map *enum_msdfs_links(TALLOC_CTX *ctx, size_t *p_num_jn) } /****************************************************************************** - Core function to resolve a dfs pathname. -******************************************************************************/ - -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(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; -} - -/****************************************************************************** - Core function to resolve a dfs pathname possibly containing a wildcard. - This function is identical to the above except for the bool param to - dfs_redirect but I need this to be separate so it's really clear when - we're allowing wildcards and when we're not. JRA. + Core function to resolve a dfs pathname possibly containing a wildcard. If + ppath_contains_wcard != NULL, it will be set to true if a wildcard is + detected during dfs resolution. ******************************************************************************/ NTSTATUS resolve_dfspath_wcard(TALLOC_CTX *ctx, connection_struct *conn, bool dfs_pathnames, const char *name_in, + bool allow_wcards, char **pp_name_out, bool *ppath_contains_wcard) { + bool path_contains_wcard; NTSTATUS status = NT_STATUS_OK; + if (dfs_pathnames) { status = dfs_redirect(ctx, conn, name_in, - True, + allow_wcards, pp_name_out, - ppath_contains_wcard); + &path_contains_wcard); + + if (NT_STATUS_IS_OK(status) && ppath_contains_wcard != NULL) { + *ppath_contains_wcard = path_contains_wcard; + } } else { /* * Cheat and just return a copy of the in ptr.