From bafe8d22fde97755bf35e8abf389d52b8993a551 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 13 May 2008 14:01:19 -0700 Subject: Fix bug #5460. The problem is RHEL5.0 shipped a CIFS client that sets the DFS bit on pathnames but doesn't send DFS paths. This causes lookups to fail as the smbd/msdfs.c code now just eats the first two parts of the pathname and uses the rest as the local path. The previous hostname check used to protect us from that as we knew that when the hostname was invalid it was a local path (and a broken client). I didn't want to put that check back in, but came up with another idea - even though the hostname can be a different one, the sharename must be valid on this machine. So we can check for a valid sharename instead. Jeremy. (This used to be commit e1cda82f6f7de3306a653af920756c1640057f2d) --- source3/smbd/conn.c | 25 +++++++++++++++++++++++-- source3/smbd/msdfs.c | 10 ++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) (limited to 'source3') diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index e899af1319..125277be21 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -63,10 +63,10 @@ bool conn_snum_used(int snum) return(False); } - /**************************************************************************** -find a conn given a cnum + Find a conn given a cnum. ****************************************************************************/ + connection_struct *conn_find(unsigned cnum) { int count=0; @@ -84,6 +84,27 @@ connection_struct *conn_find(unsigned cnum) return NULL; } +/**************************************************************************** + Find a conn given a service name. +****************************************************************************/ + +connection_struct *conn_find_byname(const char *service) +{ + int count=0; + connection_struct *conn; + + for (conn=Connections;conn;conn=conn->next,count++) { + if (strequal(lp_servicename(SNUM(conn)),service)) { + if (count > 10) { + DLIST_PROMOTE(Connections, conn); + } + return conn; + } + } + + return NULL; +} + /**************************************************************************** find first available connection slot, starting from a random position. diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index e321a8c8e4..6306745574 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -133,6 +133,16 @@ static NTSTATUS parse_dfs_path(const char *pathname, if(p == NULL) { pdp->servicename = temp; pdp->reqpath = eos_ptr; /* "" */ + /* Is this really our servicename ? */ + if (NULL == conn_find_byname(pdp->servicename)) { + DEBUG(10,("parse_dfs_path: %s is not our servicename\n", + pdp->servicename)); + p = temp; + DEBUG(10,("parse_dfs_path: trying to convert %s " + "to a local path\n", + temp)); + goto local_path; + } return NT_STATUS_OK; } *p = '\0'; -- cgit From b833615721d6d2e328908afeb1cb965ab5d38284 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 13 May 2008 15:02:11 -0700 Subject: Second part of patch for bug #5460. Cope with pathnames that don't look like \xxx\yyy, cope with arbitrary length. Jeremy. (This used to be commit 635035d999fcd8e06b70c8cb1137127c289dc9e6) --- source3/smbd/msdfs.c | 54 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 15 deletions(-) (limited to 'source3') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 6306745574..4e673d8000 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -49,6 +49,7 @@ static NTSTATUS parse_dfs_path(const char *pathname, { char *pathname_local; char *p,*temp; + char *servicename; char *eos_ptr; NTSTATUS status = NT_STATUS_OK; char sepchar; @@ -128,25 +129,48 @@ static NTSTATUS parse_dfs_path(const char *pathname, DEBUG(10,("parse_dfs_path: hostname: %s\n",pdp->hostname)); /* Parse out servicename. */ - temp = p+1; - p = strchr_m(temp,sepchar); + servicename = p+1; + p = strchr_m(servicename,sepchar); + if (p) { + *p = '\0'; + } + + /* Is this really our servicename ? */ + if (NULL == conn_find_byname(servicename)) { + DEBUG(10,("parse_dfs_path: %s is not our servicename\n", + servicename)); + + /* + * Possibly client sent a local path by mistake. + * Try and convert to a local path. + */ + + pdp->hostname = eos_ptr; /* "" */ + pdp->servicename = eos_ptr; /* "" */ + + /* Repair the path - replace the sepchar's + we nulled out */ + servicename--; + *servicename = sepchar; + if (p) { + *p = sepchar; + } + + p = temp; + DEBUG(10,("parse_dfs_path: trying to convert %s " + "to a local path\n", + temp)); + goto local_path; + } + + pdp->servicename = servicename; + if(p == NULL) { - pdp->servicename = temp; + /* Client sent self referral \server\share. */ pdp->reqpath = eos_ptr; /* "" */ - /* Is this really our servicename ? */ - if (NULL == conn_find_byname(pdp->servicename)) { - DEBUG(10,("parse_dfs_path: %s is not our servicename\n", - pdp->servicename)); - p = temp; - DEBUG(10,("parse_dfs_path: trying to convert %s " - "to a local path\n", - temp)); - goto local_path; - } return NT_STATUS_OK; } - *p = '\0'; - pdp->servicename = temp; + DEBUG(10,("parse_dfs_path: servicename: %s\n",pdp->servicename)); p++; -- cgit From b8398d19af01cbdaec3af6c264e4d073fa85f78d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 13 May 2008 15:25:26 -0700 Subject: Fix debug message. Jeremy. (This used to be commit 08d168f0e5b8fb07e95a5118a839e0da53e9d363) --- source3/smbd/msdfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 4e673d8000..04b9b7deaa 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -165,14 +165,14 @@ static NTSTATUS parse_dfs_path(const char *pathname, pdp->servicename = servicename; + DEBUG(10,("parse_dfs_path: servicename: %s\n",pdp->servicename)); + if(p == NULL) { /* Client sent self referral \server\share. */ pdp->reqpath = eos_ptr; /* "" */ return NT_STATUS_OK; } - DEBUG(10,("parse_dfs_path: servicename: %s\n",pdp->servicename)); - p++; local_path: -- cgit