[PATCH] Fix bug #10650 - "case sensitive = True" option doesn't work with "max protocol = SMB2" or higher in large directories.

Volker Lendecke Volker.Lendecke at SerNet.DE
Wed Jun 11 03:39:48 MDT 2014


Hi!

Attached find your patches with my r-b. Also find two
more-or-less cosmetic patches on top.

Please review and/or push!

Thanks,

Volker

On Tue, Jun 10, 2014 at 04:16:18PM -0700, Jeremy Allison wrote:
> Here's a fix for the SMB2/3 server when given a non-wildcard
> search path.
> 
> For a non-wildcard string we need it to go through the
> filename_convert() function that takes care of name
> canonicalization and lookup in the same way as any
> other given pathname.
> 
> This is the same way it's done in the old SMB1 trans2
> findfirst code.
> 
> Please review and/or push if you're happy.
> 
> Thanks !
> 
> Jeremy.

> From c997a4a4a40f9f8f7755e60be783de106371caec Mon Sep 17 00:00:00 2001
> From: Jeremy Allison <jra at samba.org>
> Date: Tue, 10 Jun 2014 14:41:45 -0700
> Subject: [PATCH 1/2] s3: smbd - SMB[2|3]. Ensure a \ or / can't be found
>  anywhere in a search path, not just at the start.
> 
> Signed-off-by: Jeremy Allison <jra at samba.org>
> ---
>  source3/smbd/smb2_find.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/source3/smbd/smb2_find.c b/source3/smbd/smb2_find.c
> index 3f779b8..d66c093 100644
> --- a/source3/smbd/smb2_find.c
> +++ b/source3/smbd/smb2_find.c
> @@ -252,11 +252,11 @@ static struct tevent_req *smbd_smb2_find_send(TALLOC_CTX *mem_ctx,
>  		tevent_req_nterror(req, NT_STATUS_OBJECT_NAME_INVALID);
>  		return tevent_req_post(req, ev);
>  	}
> -	if (strcmp(in_file_name, "\\") == 0) {
> +	if (strchr_m(in_file_name, '\\') != NULL) {
>  		tevent_req_nterror(req, NT_STATUS_OBJECT_NAME_INVALID);
>  		return tevent_req_post(req, ev);
>  	}
> -	if (strcmp(in_file_name, "/") == 0) {
> +	if (strchr_m(in_file_name, '/') != NULL) {
>  		tevent_req_nterror(req, NT_STATUS_OBJECT_NAME_INVALID);
>  		return tevent_req_post(req, ev);
>  	}
> -- 
> 2.0.0.526.g5318336
> 
> 
> From f5a1dde50b0328965c859c39a61b79cf88a363e7 Mon Sep 17 00:00:00 2001
> From: Jeremy Allison <jra at samba.org>
> Date: Tue, 10 Jun 2014 15:58:15 -0700
> Subject: [PATCH 2/2] s3: smbd : SMB2 - fix SMB2_SEARCH when searching non
>  wildcard string with a case-canonicalized share.
> 
> We need to go through filename_convert() in order for the filename
> canonicalization to be done on a non-wildcard search string (as is
> done in the SMB1 findfirst code path).
> 
> Fixes Bug #10650 - "case sensitive = True" option doesn't work with "max protocol = SMB2" or higher in large directories.
> 
> https://bugzilla.samba.org/show_bug.cgi?id=10650
> 
> Signed-off-by: Jeremy Allison <jra at samba.org>
> ---
>  source3/smbd/smb2_find.c | 37 ++++++++++++++++++++++++++++++++++---
>  1 file changed, 34 insertions(+), 3 deletions(-)
> 
> diff --git a/source3/smbd/smb2_find.c b/source3/smbd/smb2_find.c
> index d66c093..e9e0542 100644
> --- a/source3/smbd/smb2_find.c
> +++ b/source3/smbd/smb2_find.c
> @@ -224,6 +224,7 @@ static struct tevent_req *smbd_smb2_find_send(TALLOC_CTX *mem_ctx,
>  	uint32_t dirtype = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_DIRECTORY;
>  	bool dont_descend = false;
>  	bool ask_sharemode = true;
> +	bool wcard_has_wild;
>  	struct tm tm;
>  	char *p;
>  
> @@ -323,11 +324,41 @@ static struct tevent_req *smbd_smb2_find_send(TALLOC_CTX *mem_ctx,
>  		dptr_CloseDir(fsp);
>  	}
>  
> -	if (fsp->dptr == NULL) {
> -		bool wcard_has_wild;
> +	wcard_has_wild = ms_has_wild(in_file_name);
>  
> -		wcard_has_wild = ms_has_wild(in_file_name);
> +	/* Ensure we've canonicalized any search path if not a wildcard. */
> +	if (!wcard_has_wild) {
> +		struct smb_filename *smb_fname = NULL;
> +		const char *fullpath;
>  
> +		if (ISDOT(fsp->fsp_name->base_name)) {
> +			fullpath = in_file_name;
> +		} else {
> +			fullpath = talloc_asprintf(state,
> +					"%s/%s",
> +					fsp->fsp_name->base_name,
> +					in_file_name);
> +		}
> +		if (tevent_req_nomem(fullpath, req)) {
> +			return tevent_req_post(req, ev);
> +		}
> +		status = filename_convert(state,
> +				conn,
> +				false, /* Not a DFS path. */
> +				fullpath,
> +				UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP,
> +				&wcard_has_wild,
> +				&smb_fname);
> +
> +		if (!NT_STATUS_IS_OK(status)) {
> +			tevent_req_nterror(req, status);
> +			return tevent_req_post(req, ev);
> +		}
> +
> +		in_file_name = smb_fname->original_lcomp;
> +	}
> +
> +	if (fsp->dptr == NULL) {
>  		status = dptr_create(conn,
>  				     NULL, /* req */
>  				     fsp,
> -- 
> 2.0.0.526.g5318336
> 


-- 
SerNet GmbH, Bahnhofsallee 1b, 37081 Göttingen
phone: +49-551-370000-0, fax: +49-551-370000-9
AG Göttingen, HRB 2816, GF: Dr. Johannes Loxen
http://www.sernet.de, mailto:kontakt at sernet.de
-------------- next part --------------
From 5f5c94531028a611055fbc42de66122035c0bf2e Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Tue, 10 Jun 2014 14:41:45 -0700
Subject: [PATCH 1/4] s3: smbd - SMB[2|3]. Ensure a \ or / can't be found
 anywhere in a search path, not just at the start.

Signed-off-by: Jeremy Allison <jra at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
---
 source3/smbd/smb2_find.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/source3/smbd/smb2_find.c b/source3/smbd/smb2_find.c
index 3f779b8..d66c093 100644
--- a/source3/smbd/smb2_find.c
+++ b/source3/smbd/smb2_find.c
@@ -252,11 +252,11 @@ static struct tevent_req *smbd_smb2_find_send(TALLOC_CTX *mem_ctx,
 		tevent_req_nterror(req, NT_STATUS_OBJECT_NAME_INVALID);
 		return tevent_req_post(req, ev);
 	}
-	if (strcmp(in_file_name, "\\") == 0) {
+	if (strchr_m(in_file_name, '\\') != NULL) {
 		tevent_req_nterror(req, NT_STATUS_OBJECT_NAME_INVALID);
 		return tevent_req_post(req, ev);
 	}
-	if (strcmp(in_file_name, "/") == 0) {
+	if (strchr_m(in_file_name, '/') != NULL) {
 		tevent_req_nterror(req, NT_STATUS_OBJECT_NAME_INVALID);
 		return tevent_req_post(req, ev);
 	}
-- 
1.8.1.2


From 88bdeab70770ba6fa51251324d3f502e316d65e5 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Tue, 10 Jun 2014 15:58:15 -0700
Subject: [PATCH 2/4] s3: smbd : SMB2 - fix SMB2_SEARCH when searching non
 wildcard string with a case-canonicalized share.

We need to go through filename_convert() in order for the filename
canonicalization to be done on a non-wildcard search string (as is
done in the SMB1 findfirst code path).

Fixes Bug #10650 - "case sensitive = True" option doesn't work with "max protocol = SMB2" or higher in large directories.

https://bugzilla.samba.org/show_bug.cgi?id=10650

Signed-off-by: Jeremy Allison <jra at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
---
 source3/smbd/smb2_find.c | 37 ++++++++++++++++++++++++++++++++++---
 1 file changed, 34 insertions(+), 3 deletions(-)

diff --git a/source3/smbd/smb2_find.c b/source3/smbd/smb2_find.c
index d66c093..e9e0542 100644
--- a/source3/smbd/smb2_find.c
+++ b/source3/smbd/smb2_find.c
@@ -224,6 +224,7 @@ static struct tevent_req *smbd_smb2_find_send(TALLOC_CTX *mem_ctx,
 	uint32_t dirtype = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_DIRECTORY;
 	bool dont_descend = false;
 	bool ask_sharemode = true;
+	bool wcard_has_wild;
 	struct tm tm;
 	char *p;
 
@@ -323,11 +324,41 @@ static struct tevent_req *smbd_smb2_find_send(TALLOC_CTX *mem_ctx,
 		dptr_CloseDir(fsp);
 	}
 
-	if (fsp->dptr == NULL) {
-		bool wcard_has_wild;
+	wcard_has_wild = ms_has_wild(in_file_name);
 
-		wcard_has_wild = ms_has_wild(in_file_name);
+	/* Ensure we've canonicalized any search path if not a wildcard. */
+	if (!wcard_has_wild) {
+		struct smb_filename *smb_fname = NULL;
+		const char *fullpath;
 
+		if (ISDOT(fsp->fsp_name->base_name)) {
+			fullpath = in_file_name;
+		} else {
+			fullpath = talloc_asprintf(state,
+					"%s/%s",
+					fsp->fsp_name->base_name,
+					in_file_name);
+		}
+		if (tevent_req_nomem(fullpath, req)) {
+			return tevent_req_post(req, ev);
+		}
+		status = filename_convert(state,
+				conn,
+				false, /* Not a DFS path. */
+				fullpath,
+				UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP,
+				&wcard_has_wild,
+				&smb_fname);
+
+		if (!NT_STATUS_IS_OK(status)) {
+			tevent_req_nterror(req, status);
+			return tevent_req_post(req, ev);
+		}
+
+		in_file_name = smb_fname->original_lcomp;
+	}
+
+	if (fsp->dptr == NULL) {
 		status = dptr_create(conn,
 				     NULL, /* req */
 				     fsp,
-- 
1.8.1.2


From c91d72228e36a3894522be9b7aec96ac57641c19 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Wed, 11 Jun 2014 09:32:56 +0000
Subject: [PATCH 3/4] smbd: Use full_path_tos() where appropriate

Recently I've got reports that SMB2_FIND is slower than trans2 findfirst,
so this tries to use recent performance-sensitive APIs right from the
start :-)

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/smbd/smb2_find.c | 22 +++++++++++++++-------
 1 file changed, 15 insertions(+), 7 deletions(-)

diff --git a/source3/smbd/smb2_find.c b/source3/smbd/smb2_find.c
index e9e0542..481dcb9 100644
--- a/source3/smbd/smb2_find.c
+++ b/source3/smbd/smb2_find.c
@@ -330,17 +330,23 @@ static struct tevent_req *smbd_smb2_find_send(TALLOC_CTX *mem_ctx,
 	if (!wcard_has_wild) {
 		struct smb_filename *smb_fname = NULL;
 		const char *fullpath;
+		char tmpbuf[PATH_MAX];
+		char *to_free = NULL;
 
 		if (ISDOT(fsp->fsp_name->base_name)) {
 			fullpath = in_file_name;
 		} else {
-			fullpath = talloc_asprintf(state,
-					"%s/%s",
-					fsp->fsp_name->base_name,
-					in_file_name);
-		}
-		if (tevent_req_nomem(fullpath, req)) {
-			return tevent_req_post(req, ev);
+			size_t len;
+			char *tmp;
+
+			len = full_path_tos(
+				fsp->fsp_name->base_name, in_file_name,
+				tmpbuf, sizeof(tmpbuf), &tmp, &to_free);
+			if (len == -1) {
+				tevent_req_oom(req);
+				return tevent_req_post(req, ev);
+			}
+			fullpath = tmp;
 		}
 		status = filename_convert(state,
 				conn,
@@ -350,6 +356,8 @@ static struct tevent_req *smbd_smb2_find_send(TALLOC_CTX *mem_ctx,
 				&wcard_has_wild,
 				&smb_fname);
 
+		TALLOC_FREE(to_free);
+
 		if (!NT_STATUS_IS_OK(status)) {
 			tevent_req_nterror(req, status);
 			return tevent_req_post(req, ev);
-- 
1.8.1.2


From 6aa6ae585ec99fe21f63e7fd22e9c1696bd9870e Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Wed, 11 Jun 2014 09:35:37 +0000
Subject: [PATCH 4/4] smbd: tevent_req_nterror already returns bool :-)

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/smbd/smb2_find.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/source3/smbd/smb2_find.c b/source3/smbd/smb2_find.c
index 481dcb9..6bc44a5 100644
--- a/source3/smbd/smb2_find.c
+++ b/source3/smbd/smb2_find.c
@@ -358,8 +358,7 @@ static struct tevent_req *smbd_smb2_find_send(TALLOC_CTX *mem_ctx,
 
 		TALLOC_FREE(to_free);
 
-		if (!NT_STATUS_IS_OK(status)) {
-			tevent_req_nterror(req, status);
+		if (tevent_req_nterror(req, status)) {
 			return tevent_req_post(req, ev);
 		}
 
-- 
1.8.1.2



More information about the samba-technical mailing list