summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2003-10-28 00:51:19 +0000
committerJeremy Allison <jra@samba.org>2003-10-28 00:51:19 +0000
commit3638769e02ca8d1ab9cb17d7b10e6e9cdb6ea2e5 (patch)
treeef492304b579ad03db86ea3e2e0cfdd3bf918187
parent0b86dcc634fb3dab1abc8a1f56b281093af12969 (diff)
downloadsamba-3638769e02ca8d1ab9cb17d7b10e6e9cdb6ea2e5.tar.gz
samba-3638769e02ca8d1ab9cb17d7b10e6e9cdb6ea2e5.tar.bz2
samba-3638769e02ca8d1ab9cb17d7b10e6e9cdb6ea2e5.zip
Fix for bug #667. DFS filenames can now have arbitrary case.
Jeremy. (This used to be commit cbefb5c4f983ca49fcc563111d8704d3770daf81)
-rw-r--r--source3/msdfs/msdfs.c93
-rw-r--r--source3/rpc_server/srv_dfs_nt.c58
-rw-r--r--source3/smbd/trans2.c2
3 files changed, 86 insertions, 67 deletions
diff --git a/source3/msdfs/msdfs.c b/source3/msdfs/msdfs.c
index 5cc4bf45d6..20814c2ceb 100644
--- a/source3/msdfs/msdfs.c
+++ b/source3/msdfs/msdfs.c
@@ -78,6 +78,7 @@ static BOOL parse_dfs_path(char* pathname, struct dfs_path* pdp)
/********************************************************
Fake up a connection struct for the VFS layer.
+ Note this CHANGES CWD !!!! JRA.
*********************************************************/
static BOOL create_conn_struct( connection_struct *conn, int snum, char *path)
@@ -99,6 +100,11 @@ static BOOL create_conn_struct( connection_struct *conn, int snum, char *path)
talloc_destroy( conn->mem_ctx );
return False;
}
+ if (vfs_ChDir(conn,conn->connectpath) != 0) {
+ DEBUG(0,("create_conn_struct: Can't ChDir to new conn path %s\n", conn->connectpath));
+ talloc_destroy( conn->mem_ctx );
+ return False;
+ }
return True;
}
@@ -161,7 +167,8 @@ static BOOL parse_symlink(char* buf,struct referral** preflist,
/**********************************************************************
Returns true if the unix path is a valid msdfs symlink
**********************************************************************/
-BOOL is_msdfs_link(connection_struct* conn, char* path,
+
+BOOL is_msdfs_link(connection_struct* conn, char * path,
struct referral** reflistp, int* refcnt,
SMB_STRUCT_STAT *sbufp)
{
@@ -172,8 +179,6 @@ BOOL is_msdfs_link(connection_struct* conn, char* path,
if (!path || !conn)
return False;
- strlower_m(path);
-
if (sbufp == NULL)
sbufp = &st;
@@ -212,17 +217,21 @@ they request referrals for dfs roots on a server.
consumedcntp: how much of the dfs path is being redirected. the client
should try the remaining path on the redirected server.
+
*****************************************************************/
-static BOOL resolve_dfs_path(char* dfspath, struct dfs_path* dp,
+
+static BOOL resolve_dfs_path(pstring dfspath, struct dfs_path* dp,
connection_struct* conn,
BOOL findfirst_flag,
struct referral** reflistpp, int* refcntp,
BOOL* self_referralp, int* consumedcntp)
{
- fstring localpath;
+ pstring localpath;
int consumed_level = 1;
char *p;
- fstring reqpath;
+ BOOL bad_path = False;
+ SMB_STRUCT_STAT sbuf;
+ pstring reqpath;
if (!dp || !conn) {
DEBUG(1,("resolve_dfs_path: NULL dfs_path* or NULL connection_struct*!\n"));
@@ -237,10 +246,13 @@ static BOOL resolve_dfs_path(char* dfspath, struct dfs_path* dp,
return False;
}
+ DEBUG(10,("resolve_dfs_path: Conn path = %s req_path = %s\n", conn->connectpath, dp->reqpath));
+
+ unix_convert(dp->reqpath,conn,0,&bad_path,&sbuf);
+ /* JRA... should we strlower the last component here.... ? */
+ pstrcpy(localpath, dp->reqpath);
+
/* check if need to redirect */
- fstrcpy(localpath, conn->connectpath);
- fstrcat(localpath, "/");
- fstrcat(localpath, dp->reqpath);
if (is_msdfs_link(conn, localpath, reflistpp, refcntp, NULL)) {
if (findfirst_flag) {
DEBUG(6,("resolve_dfs_path (FindFirst) No redirection "
@@ -256,13 +268,11 @@ static BOOL resolve_dfs_path(char* dfspath, struct dfs_path* dp,
}
/* redirect if any component in the path is a link */
- fstrcpy(reqpath, dp->reqpath);
+ pstrcpy(reqpath, dp->reqpath);
p = strrchr(reqpath, '/');
while (p) {
*p = '\0';
- fstrcpy(localpath, conn->connectpath);
- fstrcat(localpath, "/");
- fstrcat(localpath, reqpath);
+ pstrcpy(localpath, reqpath);
if (is_msdfs_link(conn, localpath, reflistpp, refcntp, NULL)) {
DEBUG(4, ("resolve_dfs_path: Redirecting %s because parent %s is dfs link\n", dfspath, localpath));
@@ -278,7 +288,8 @@ static BOOL resolve_dfs_path(char* dfspath, struct dfs_path* dp,
trim_char(buf, '\0', '\\');
for (; consumed_level; consumed_level--) {
q = strrchr(buf, '\\');
- if (q) *q = 0;
+ if (q)
+ *q = 0;
}
*consumedcntp = strlen(buf);
DEBUG(10, ("resolve_dfs_path: Path consumed: %s (%d)\n", buf, *consumedcntp));
@@ -297,7 +308,8 @@ static BOOL resolve_dfs_path(char* dfspath, struct dfs_path* dp,
Decides if a dfs pathname should be redirected or not.
If not, the pathname is converted to a tcon-relative local unix path
*****************************************************************/
-BOOL dfs_redirect(char* pathname, connection_struct* conn,
+
+BOOL dfs_redirect(pstring pathname, connection_struct* conn,
BOOL findfirst_flag)
{
struct dfs_path dp;
@@ -310,7 +322,7 @@ BOOL dfs_redirect(char* pathname, connection_struct* conn,
/* if dfs pathname for a non-dfs share, convert to tcon-relative
path and return false */
if (!lp_msdfs_root(SNUM(conn))) {
- fstrcpy(pathname, dp.reqpath);
+ pstrcpy(pathname, dp.reqpath);
return False;
}
@@ -325,7 +337,7 @@ BOOL dfs_redirect(char* pathname, connection_struct* conn,
DEBUG(3,("dfs_redirect: Not redirecting %s.\n", pathname));
/* Form non-dfs tcon-relative path */
- fstrcpy(pathname, dp.reqpath);
+ pstrcpy(pathname, dp.reqpath);
DEBUG(3,("dfs_redirect: Path converted to non-dfs path %s\n",
pathname));
return False;
@@ -338,6 +350,7 @@ BOOL dfs_redirect(char* pathname, connection_struct* conn,
Gets valid referrals for a dfs path and fills up the
junction_map structure
**********************************************************************/
+
BOOL get_referred_path(char *pathname, struct junction_map* jn,
int* consumedcntp, BOOL* self_referralp)
{
@@ -363,14 +376,12 @@ BOOL get_referred_path(char *pathname, struct junction_map* jn,
/* Verify hostname in path */
if (local_machine && (!strequal(local_machine, dp.hostname))) {
-
- /* Hostname mismatch, check if one of our IP addresses */
- if (!ismyip(*interpret_addr2(dp.hostname))) {
-
- DEBUG(3, ("get_referred_path: Invalid hostname %s in path %s\n",
- dp.hostname, pathname));
- return False;
- }
+ /* Hostname mismatch, check if one of our IP addresses */
+ if (!ismyip(*interpret_addr2(dp.hostname))) {
+ DEBUG(3, ("get_referred_path: Invalid hostname %s in path %s\n",
+ dp.hostname, pathname));
+ return False;
+ }
}
pstrcpy(jn->service_name, dp.servicename);
@@ -386,7 +397,7 @@ BOOL get_referred_path(char *pathname, struct junction_map* jn,
pstrcpy(conn_path, lp_pathname(snum));
if (!create_conn_struct(conn, snum, conn_path))
return False;
-
+
if (!lp_msdfs_root(SNUM(conn))) {
DEBUG(3,("get_referred_path: .%s. in dfs path %s is not a dfs root.\n",
dp.servicename, pathname));
@@ -626,7 +637,7 @@ static int setup_ver3_dfs_referral(char* pathname, char** ppdata,
* Set up the Dfs referral for the dfs pathname
******************************************************************/
-int setup_dfs_referral(char* pathname, int max_referral_level, char** ppdata)
+int setup_dfs_referral(connection_struct *orig_conn, char *pathname, int max_referral_level, char** ppdata)
{
struct junction_map junction;
int consumedcnt;
@@ -648,12 +659,14 @@ int setup_dfs_referral(char* pathname, int max_referral_level, char** ppdata)
pathnamep++;
pstrcpy(buf, pathnamep);
- if (!get_referred_path(buf, &junction, &consumedcnt,
- &self_referral))
+ /* The following call can change cwd. */
+ if (!get_referred_path(buf, &junction, &consumedcnt, &self_referral)) {
+ vfs_ChDir(orig_conn,orig_conn->connectpath);
return -1;
+ }
+ vfs_ChDir(orig_conn,orig_conn->connectpath);
- if (!self_referral)
- {
+ if (!self_referral) {
pathnamep[consumedcnt] = '\0';
if( DEBUGLVL( 3 ) ) {
@@ -672,24 +685,18 @@ int setup_dfs_referral(char* pathname, int max_referral_level, char** ppdata)
switch(max_referral_level) {
case 2:
- {
reply_size = setup_ver2_dfs_referral(pathnamep, ppdata, &junction,
consumedcnt, self_referral);
SAFE_FREE(junction.referral_list);
break;
- }
case 3:
- {
reply_size = setup_ver3_dfs_referral(pathnamep, ppdata, &junction,
consumedcnt, self_referral);
SAFE_FREE(junction.referral_list);
break;
- }
default:
- {
DEBUG(0,("setup_dfs_referral: Invalid dfs referral version: %d\n", max_referral_level));
return -1;
- }
}
DEBUG(10,("DFS Referral pdata:\n"));
@@ -752,7 +759,6 @@ static BOOL junction_to_local_path(struct junction_map* jn, char* path,
safe_strcpy(path, lp_pathname(snum), max_pathlen-1);
safe_strcat(path, "/", max_pathlen-1);
- strlower_m(jn->volume_name);
safe_strcat(path, jn->volume_name, max_pathlen-1);
pstrcpy(conn_path, lp_pathname(snum));
@@ -885,18 +891,12 @@ static BOOL form_junctions(int snum, struct junction_map* jn, int* jn_count)
cnt++;
/* Now enumerate all dfs links */
- dirp = SMB_VFS_OPENDIR(conn, connect_path);
+ dirp = SMB_VFS_OPENDIR(conn, ".");
if(!dirp)
goto out;
while((dname = vfs_readdirname(conn, dirp)) != NULL) {
- pstring pathreal;
-
- pstrcpy(pathreal, connect_path);
- pstrcat(pathreal, "/");
- pstrcat(pathreal, dname);
-
- if (is_msdfs_link(conn, pathreal, &(jn[cnt].referral_list),
+ if (is_msdfs_link(conn, dname, &(jn[cnt].referral_list),
&(jn[cnt].referral_count), NULL)) {
pstrcpy(jn[cnt].service_name, service_name);
pstrcpy(jn[cnt].volume_name, dname);
@@ -925,4 +925,3 @@ int enum_msdfs_links(struct junction_map* jn)
}
return jn_count;
}
-
diff --git a/source3/rpc_server/srv_dfs_nt.c b/source3/rpc_server/srv_dfs_nt.c
index 751cb6e642..ac3ed9c394 100644
--- a/source3/rpc_server/srv_dfs_nt.c
+++ b/source3/rpc_server/srv_dfs_nt.c
@@ -70,6 +70,7 @@ WERROR _dfs_add(pipes_struct *p, DFS_Q_DFS_ADD* q_u, DFS_R_DFS_ADD *r_u)
pstrcat(altpath, "\\");
pstrcat(altpath, sharename);
+ /* The following call can change the cwd. */
if(get_referred_path(dfspath, &jn, NULL, NULL))
{
exists = True;
@@ -79,6 +80,8 @@ WERROR _dfs_add(pipes_struct *p, DFS_Q_DFS_ADD* q_u, DFS_R_DFS_ADD *r_u)
else
jn.referral_count = 1;
+ vfs_ChDir(p->conn,p->conn->connectpath);
+
jn.referral_list = (struct referral*) talloc(p->mem_ctx, jn.referral_count
* sizeof(struct referral));
@@ -100,8 +103,11 @@ WERROR _dfs_add(pipes_struct *p, DFS_Q_DFS_ADD* q_u, DFS_R_DFS_ADD *r_u)
pstrcpy(jn.referral_list[jn.referral_count-1].alternate_path, altpath);
- if(!create_msdfs_link(&jn, exists))
+ if(!create_msdfs_link(&jn, exists)) {
+ vfs_ChDir(p->conn,p->conn->connectpath);
return WERR_DFS_CANT_CREATE_JUNCT;
+ }
+ vfs_ChDir(p->conn,p->conn->connectpath);
return WERR_OK;
}
@@ -147,8 +153,11 @@ WERROR _dfs_remove(pipes_struct *p, DFS_Q_DFS_REMOVE *q_u,
/* if no server-share pair given, remove the msdfs link completely */
if(!q_u->ptr_ServerName && !q_u->ptr_ShareName)
{
- if(!remove_msdfs_link(&jn))
+ if(!remove_msdfs_link(&jn)) {
+ vfs_ChDir(p->conn,p->conn->connectpath);
return WERR_DFS_NO_SUCH_VOL;
+ }
+ vfs_ChDir(p->conn,p->conn->connectpath);
}
else
{
@@ -175,13 +184,19 @@ WERROR _dfs_remove(pipes_struct *p, DFS_Q_DFS_REMOVE *q_u,
/* Only one referral, remove it */
if(jn.referral_count == 1)
{
- if(!remove_msdfs_link(&jn))
+ if(!remove_msdfs_link(&jn)) {
+ vfs_ChDir(p->conn,p->conn->connectpath);
return WERR_DFS_NO_SUCH_VOL;
+ }
+ vfs_ChDir(p->conn,p->conn->connectpath);
}
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;
+ }
+ vfs_ChDir(p->conn,p->conn->connectpath);
}
}
@@ -325,7 +340,8 @@ WERROR _dfs_enum(pipes_struct *p, DFS_Q_DFS_ENUM *q_u, DFS_R_DFS_ENUM *r_u)
int num_jn = 0;
num_jn = enum_msdfs_links(jn);
-
+ vfs_ChDir(p->conn,p->conn->connectpath);
+
DEBUG(5,("make_reply_dfs_enum: %d junctions found in Dfs, doing level %d\n", num_jn, level));
r_u->ptr_buffer = level;
@@ -351,21 +367,25 @@ WERROR _dfs_enum(pipes_struct *p, DFS_Q_DFS_ENUM *q_u, DFS_R_DFS_ENUM *r_u)
WERROR _dfs_get_info(pipes_struct *p, DFS_Q_DFS_GET_INFO *q_u,
DFS_R_DFS_GET_INFO *r_u)
{
- UNISTR2* uni_path = &q_u->uni_path;
- uint32 level = q_u->level;
- pstring path;
- struct junction_map jn;
-
- unistr2_to_ascii(path, uni_path, sizeof(path)-1);
- if(!create_junction(path, &jn))
- return WERR_DFS_NO_SUCH_SERVER;
+ UNISTR2* uni_path = &q_u->uni_path;
+ uint32 level = q_u->level;
+ pstring path;
+ struct junction_map jn;
+
+ unistr2_to_ascii(path, uni_path, sizeof(path)-1);
+ if(!create_junction(path, &jn))
+ return WERR_DFS_NO_SUCH_SERVER;
- if(!get_referred_path(path, &jn, NULL, NULL))
- return WERR_DFS_NO_SUCH_VOL;
+ /* The following call can change the cwd. */
+ if(!get_referred_path(path, &jn, NULL, NULL)) {
+ vfs_ChDir(p->conn,p->conn->connectpath);
+ return WERR_DFS_NO_SUCH_VOL;
+ }
- r_u->level = level;
- r_u->ptr_ctr = 1;
- r_u->status = init_reply_dfs_ctr(p->mem_ctx, level, &r_u->ctr, &jn, 1);
+ vfs_ChDir(p->conn,p->conn->connectpath);
+ r_u->level = level;
+ r_u->ptr_ctr = 1;
+ r_u->status = init_reply_dfs_ctr(p->mem_ctx, level, &r_u->ctr, &jn, 1);
- return r_u->status;
+ return r_u->status;
}
diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
index 0f02403184..5677fb9a41 100644
--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -3297,7 +3297,7 @@ static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf,
srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), -1, STR_TERMINATE);
- if((reply_size = setup_dfs_referral(pathname,max_referral_level,ppdata)) < 0)
+ if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
return ERROR_DOS(ERRDOS,ERRbadfile);
SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);