1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-11 05:18:09 +03:00

Fix for bug #667. DFS filenames can now have arbitrary case.

Jeremy.
This commit is contained in:
Jeremy Allison 0001-01-01 00:00:00 +00:00
parent 67dd1c4366
commit 74148111e1
3 changed files with 85 additions and 66 deletions

View File

@ -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;
}

View File

@ -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* 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_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;
}

View File

@ -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);