[PATCH] Fix bug 9992 - Windows error 0x800700FE when copying files with xattr names containing ":"

Jeremy Allison jra at samba.org
Thu Jul 18 11:50:12 MDT 2013


Set of fixes that correctly (as probed against
Windows 2012) restricts the allowable EA names
to and from a Windows client, and fixes our
code when atomically trying to create a file
with attached EAs.

Adds a comprehensive test to show what characters
are allowed within EA names and an error code
mapping for STATUS_INVALID_EA_NAME -> ERRDOS, ERRbadfile
(as probed against a Windows 2012 server).

Original reporter confirms this fixes the
bug.

(As you can tell I did a lot of work on
this sucker :-).

Please review/push.

Cheers,

Jeremy.
-------------- next part --------------
From 65ea05d8aa7b7c516b0cb7278b79288ec0106445 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Tue, 9 Jul 2013 15:50:47 -0700
Subject: [PATCH 01/11] Add ea_list_has_invalid_name() function.

Invalid character list probed from Windows Server 2012.

Bug 9992: Windows error 0x800700FE when copying files with xattr names containing ":"

Signed-off-by: Jeremy Allison <jra at samba.org>
---
 source3/include/proto.h     |  2 ++
 source3/lib/filename_util.c | 34 ++++++++++++++++++++++++++++++++++
 2 files changed, 36 insertions(+)

diff --git a/source3/include/proto.h b/source3/include/proto.h
index 83ab77a..a9270fc 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -1611,6 +1611,8 @@ struct smb_filename *cp_smb_filename(TALLOC_CTX *mem_ctx,
 				     const struct smb_filename *in);
 bool is_ntfs_stream_smb_fname(const struct smb_filename *smb_fname);
 bool is_ntfs_default_stream_smb_fname(const struct smb_filename *smb_fname);
+bool is_invalid_windows_ea_name(const char *name);
+bool ea_list_has_invalid_name(struct ea_list *ea_list);
 
 /* The following definitions come from lib/dummyroot.c */
 
diff --git a/source3/lib/filename_util.c b/source3/lib/filename_util.c
index 656dd2a..19ffcc3 100644
--- a/source3/lib/filename_util.c
+++ b/source3/lib/filename_util.c
@@ -224,3 +224,37 @@ bool is_ntfs_default_stream_smb_fname(const struct smb_filename *smb_fname)
 
 	return strcasecmp_m(smb_fname->stream_name, "::$DATA") == 0;
 }
+
+/****************************************************************************
+ Filter out Windows invalid EA names (list probed from Windows 2012).
+****************************************************************************/
+
+static char bad_ea_name_chars[] = "\"*+,/:;<=>?[\\]|";
+
+bool is_invalid_windows_ea_name(const char *name)
+{
+	int i;
+	/* EA name is pulled as ascii so we can examine
+	   individual bytes here. */
+	for (i = 0; name[i] != 0; i++) {
+		int val = (name[i] & 0xff);
+		if (val < ' ' || strchr(bad_ea_name_chars, val)) {
+			return true;
+		}
+	}
+	return false;
+}
+
+bool ea_list_has_invalid_name(struct ea_list *ea_list)
+{
+	if (lp_posix_pathnames()) {
+		return false;
+	}
+
+	for (;ea_list; ea_list = ea_list->next) {
+		if (is_invalid_windows_ea_name(ea_list->ea.name)) {
+			return true;
+		}
+	}
+	return false;
+}
-- 
1.8.3


From 437d26f08f5efee953574307693d340b5e787975 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Tue, 9 Jul 2013 15:52:47 -0700
Subject: [PATCH 02/11] Ensure set_ea cannot set invalid Windows EA names.

Bug 9992 - Windows error 0x800700FE when copying files with xattr names containing ":"

Signed-off-by: Jeremy Allison <jra at samba.org>
---
 source3/smbd/trans2.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
index 14a2e0f..7bce6ea 100644
--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -623,6 +623,15 @@ NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
 		return NT_STATUS_INVALID_PARAMETER;
 	}
 
+	/*
+	 * Filter out invalid Windows EA names - before
+	 * we set *any* of them.
+	 */
+
+	if (ea_list_has_invalid_name(ea_list)) {
+		return STATUS_INVALID_EA_NAME;
+	}
+
 	fname = smb_fname->base_name;
 
 	for (;ea_list; ea_list = ea_list->next) {
-- 
1.8.3


From e07d10b8f9072059ecd02210cac114692b64169c Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Tue, 9 Jul 2013 16:21:18 -0700
Subject: [PATCH 03/11] Ensure we never return an EA name to a Windows client
 it can't handle.

Bug 9992 - Windows error 0x800700FE when copying files with xattr names containing ":"

Signed-off-by: Jeremy Allison <jra at samba.org>
---
 source3/smbd/trans2.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
index 7bce6ea..8532240 100644
--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -345,6 +345,15 @@ static NTSTATUS get_ea_list_from_file_path(TALLOC_CTX *mem_ctx, connection_struc
 		    || samba_private_attr_name(names[i]))
 			continue;
 
+		/*
+		 * Filter out any underlying POSIX EA names
+		 * that a Windows client can't handle.
+		 */
+		if (!lp_posix_pathnames() &&
+				is_invalid_windows_ea_name(names[i])) {
+			continue;
+		}
+
 		listp = talloc(mem_ctx, struct ea_list);
 		if (listp == NULL) {
 			return NT_STATUS_NO_MEMORY;
-- 
1.8.3


From b2f0a4d0940a3c2a56fdb23cef31ed26221fedbf Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Tue, 9 Jul 2013 16:02:50 -0700
Subject: [PATCH 04/11] Ensure we can't create a file using SMB2_CREATE with an
 invalid EA list.

Bug 9992 - Windows error 0x800700FE when copying files with xattr names containing ":"

Signed-off-by: Jeremy Allison <jra at samba.org>
---
 source3/smbd/smb2_create.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/source3/smbd/smb2_create.c b/source3/smbd/smb2_create.c
index ba743e7..4f2edfc 100644
--- a/source3/smbd/smb2_create.c
+++ b/source3/smbd/smb2_create.c
@@ -584,6 +584,11 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
 				tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
 				return tevent_req_post(req, ev);
 			}
+
+			if (ea_list_has_invalid_name(ea_list)) {
+				tevent_req_nterror(req, STATUS_INVALID_EA_NAME);
+				return tevent_req_post(req, ev);
+			}
 		}
 
 		if (mxac) {
-- 
1.8.3


From 6cd344e37a23c4dac407039d8218a21374a0f5a5 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Wed, 10 Jul 2013 12:38:41 -0700
Subject: [PATCH 05/11] Add the ability to send an NTSTATUS result back with a
 trans2 reply so we can return a parameter block with an error code.

This is needed when returning a STATUS_INVALID_NAME result (tested
from Windows 2012).

Bug 9992 - Windows error 0x800700FE when copying files with xattr names containing ":"

Signed-off-by: Jeremy Allison <jra at samba.org>
---
 source3/smbd/blocking.c |  2 +-
 source3/smbd/proto.h    |  1 +
 source3/smbd/trans2.c   | 43 ++++++++++++++++++++++++++++++-------------
 3 files changed, 32 insertions(+), 14 deletions(-)

diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c
index 4bd7a57..5f6dda3 100644
--- a/source3/smbd/blocking.c
+++ b/source3/smbd/blocking.c
@@ -563,7 +563,7 @@ static bool process_trans2(struct blocking_lock_record *blr)
 
 	SSVAL(params,0,0);
 	/* Fake up max_data_bytes here - we know it fits. */
-	send_trans2_replies(blr->fsp->conn, blr->req, params, 2, NULL, 0, 0xffff);
+	send_trans2_replies(blr->fsp->conn, blr->req, NT_STATUS_OK, params, 2, NULL, 0, 0xffff);
 	return True;
 }
 
diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h
index 38707d5..9c76609 100644
--- a/source3/smbd/proto.h
+++ b/source3/smbd/proto.h
@@ -1071,6 +1071,7 @@ NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used);
 void send_trans2_replies(connection_struct *conn,
 			struct smb_request *req,
+			NTSTATUS status,
 			 const char *params,
 			 int paramsize,
 			 const char *pdata,
diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
index 8532240..7f0aaf9 100644
--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -896,6 +896,7 @@ static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *
 
 void send_trans2_replies(connection_struct *conn,
 			struct smb_request *req,
+			NTSTATUS status,
 			 const char *params,
 			 int paramsize,
 			 const char *pdata,
@@ -936,6 +937,14 @@ void send_trans2_replies(connection_struct *conn,
 
 	if(params_to_send == 0 && data_to_send == 0) {
 		reply_outbuf(req, 10, 0);
+		if (NT_STATUS_V(status)) {
+			uint8_t eclass;
+			uint32_t ecode;
+			ntstatus_to_dos(status, &eclass, &ecode);
+			error_packet_set((char *)req->outbuf,
+					eclass, ecode, status,
+					__LINE__,__FILE__);
+		}
 		show_msg((char *)req->outbuf);
 		if (!srv_send_smb(sconn,
 				(char *)req->outbuf,
@@ -1066,6 +1075,13 @@ void send_trans2_replies(connection_struct *conn,
 					 ERRDOS,ERRbufferoverflow,
 					 STATUS_BUFFER_OVERFLOW,
 					 __LINE__,__FILE__);
+		} else if (NT_STATUS_V(status)) {
+			uint8_t eclass;
+			uint32_t ecode;
+			ntstatus_to_dos(status, &eclass, &ecode);
+			error_packet_set((char *)req->outbuf,
+					eclass, ecode, status,
+					__LINE__,__FILE__);
 		}
 
 		/* Send the packet */
@@ -1312,7 +1328,7 @@ static void call_trans2open(connection_struct *conn,
 	}
 
 	/* Send the required number of replies */
-	send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
+	send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
  out:
 	TALLOC_FREE(smb_fname);
 }
@@ -2676,7 +2692,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
 	SSVAL(params,6,0); /* Never an EA error */
 	SSVAL(params,8,last_entry_off);
 
-	send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
+	send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
 			    max_data_bytes);
 
 	if ((! *directory) && dptr_path(sconn, dptr_num)) {
@@ -3027,7 +3043,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
 	SSVAL(params,4,0); /* Never an EA error */
 	SSVAL(params,6,last_entry_off);
 
-	send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
+	send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
 			    max_data_bytes);
 
 	return;
@@ -3671,7 +3687,7 @@ static void call_trans2qfsinfo(connection_struct *conn,
 		return;
 	}
 
-	send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
+	send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
 			    max_data_bytes);
 
 	DEBUG( 4, ( "%s info_level = %d\n",
@@ -3827,6 +3843,7 @@ static void call_trans2setfsinfo(connection_struct *conn,
 				}
 
 				send_trans2_replies(conn, req,
+						NT_STATUS_OK,
 						*pparams,
 						param_len,
 						*ppdata,
@@ -4359,7 +4376,7 @@ static void call_trans2qpipeinfo(connection_struct *conn,
 			return;
 	}
 
-	send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
+	send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
 			    max_data_bytes);
 
 	return;
@@ -5561,7 +5578,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
 		return;
 	}
 
-	send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
+	send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
 			    max_data_bytes);
 
 	return;
@@ -8124,7 +8141,7 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
 					 fsp_str_dbg(fsp)));
 
 				SSVAL(params,0,0);
-				send_trans2_replies(conn, req, params, 2,
+				send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
 						    *ppdata, 0,
 						    max_data_bytes);
 				return;
@@ -8251,7 +8268,7 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
 		return;
 	}
 
-	send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
+	send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
 			    max_data_bytes);
 
 	return;
@@ -8376,7 +8393,7 @@ static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
 
 	SSVAL(params,0,0);
 
-	send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
+	send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
 
  out:
 	TALLOC_FREE(smb_dname);
@@ -8431,7 +8448,7 @@ static void call_trans2findnotifyfirst(connection_struct *conn,
 	if(fnf_handle == 0)
 		fnf_handle = 257;
 
-	send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
+	send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
 
 	return;
 }
@@ -8462,7 +8479,7 @@ static void call_trans2findnotifynext(connection_struct *conn,
 	SSVAL(params,0,0); /* No changes */
 	SSVAL(params,2,0); /* No EA errors */
 
-	send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
+	send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
 
 	return;
 }
@@ -8512,7 +8529,7 @@ static void call_trans2getdfsreferral(connection_struct *conn,
 
 	SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
 	      SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
-	send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
+	send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
 
 	return;
 }
@@ -8561,7 +8578,7 @@ static void call_trans2ioctl(connection_struct *conn,
 		srvstr_push(pdata, req->flags2, pdata+18,
 			    lp_servicename(talloc_tos(), SNUM(conn)), 13,
 			    STR_ASCII|STR_TERMINATE); /* Service name */
-		send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
+		send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
 				    max_data_bytes);
 		return;
 	}
-- 
1.8.3


From ba17cbb6452ea4639691fddd57fc4511ba9a4676 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Wed, 10 Jul 2013 12:18:36 -0700
Subject: [PATCH 06/11] Add error map of STATUS_INVALID_EA_NAME -> ERRDOS,
 ERRbadfile

(from Windows2012 tests).

Bug 9992 - Windows error 0x800700FE when copying files with xattr names containing ":"

Signed-off-by: Jeremy Allison <jra at samba.org>
---
 libcli/util/errormap.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/libcli/util/errormap.c b/libcli/util/errormap.c
index 714e62c..3870619 100644
--- a/libcli/util/errormap.c
+++ b/libcli/util/errormap.c
@@ -54,6 +54,7 @@ static const struct {
  */
 	{ERRDOS,	ERRmoredata,	STATUS_BUFFER_OVERFLOW},
 	{ERRDOS,	ERRnofiles,	STATUS_NO_MORE_FILES},
+	{ERRDOS,	ERRbadfile,	STATUS_INVALID_EA_NAME},
 	{ERRDOS,	ERRnofiles,	NT_STATUS_NO_MORE_ENTRIES},
 	{ERRDOS,	ERRgeneral,	NT_STATUS_UNSUCCESSFUL},
 	{ERRDOS,	ERRbadfunc,	NT_STATUS_NOT_IMPLEMENTED},
-- 
1.8.3


From aba81e934948b5862c0ed3bbf599aaf97f99c003 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Tue, 9 Jul 2013 15:59:53 -0700
Subject: [PATCH 07/11] Ensure we can't create a file using TRANS2_OPEN with an
 invalid EA list.

Bug 9992 - Windows error 0x800700FE when copying files with xattr names containing ":"

Signed-off-by: Jeremy Allison <jra at samba.org>
---
 source3/smbd/trans2.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
index 7f0aaf9..916686c 100644
--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -1253,6 +1253,20 @@ static void call_trans2open(connection_struct *conn,
 			reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
 			goto out;
 		}
+
+		if (ea_list_has_invalid_name(ea_list)) {
+			int param_len = 30;
+			*pparams = (char *)SMB_REALLOC(*pparams, param_len);
+			if(*pparams == NULL ) {
+				reply_nterror(req, NT_STATUS_NO_MEMORY);
+				goto out;
+			}
+			params = *pparams;
+			memset(params, '\0', param_len);
+			send_trans2_replies(conn, req, STATUS_INVALID_EA_NAME,
+				params, param_len, NULL, 0, max_data_bytes);
+			goto out;
+		}
 	}
 
 	status = SMB_VFS_CREATE_FILE(
-- 
1.8.3


From 8d1f37dc4ac4a66b0dd71e4ea2e433ac54abc785 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Tue, 9 Jul 2013 15:54:39 -0700
Subject: [PATCH 08/11] Ensure we can't create a file using NTTRANS with an
 invalid EA list.

Bug 9992 - Windows error 0x800700FE when copying files with xattr names containing ":"

Signed-off-by: Jeremy Allison <jra at samba.org>
---
 source3/smbd/nttrans.c | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c
index 516b826..1c3e3b8 100644
--- a/source3/smbd/nttrans.c
+++ b/source3/smbd/nttrans.c
@@ -1142,6 +1142,26 @@ static void call_nt_transact_create(connection_struct *conn,
 			reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
 			goto out;
 		}
+
+		if (ea_list_has_invalid_name(ea_list)) {
+			/* Realloc the size of parameters and data we will return */
+			if (flags & EXTENDED_RESPONSE_REQUIRED) {
+				/* Extended response is 32 more byyes. */
+				param_len = 101;
+			} else {
+				param_len = 69;
+			}
+			params = nttrans_realloc(ppparams, param_len);
+			if(params == NULL) {
+				reply_nterror(req, NT_STATUS_NO_MEMORY);
+				goto out;
+			}
+
+			memset(params, '\0', param_len);
+			send_nt_replies(conn, req, STATUS_INVALID_EA_NAME,
+				params, param_len, NULL, 0);
+			goto out;
+		}
 	}
 
 	srvstr_get_path(ctx, params, req->flags2, &fname,
-- 
1.8.3


From 810fe480ebcc5a9fe4fb0ee2c1314bfa9becce95 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Tue, 16 Jul 2013 11:05:10 -0700
Subject: [PATCH 09/11] Ensure we do pathname processing before SD and EA
 processing in NTTRANS_CREATE.

Bug 9992 - Windows error 0x800700FE when copying files with xattr names containing ":"

Signed-off-by: Jeremy Allison <jra at samba.org>
---
 source3/smbd/nttrans.c | 76 +++++++++++++++++++++++++-------------------------
 1 file changed, 38 insertions(+), 38 deletions(-)

diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c
index 1c3e3b8..c8116b0 100644
--- a/source3/smbd/nttrans.c
+++ b/source3/smbd/nttrans.c
@@ -1092,6 +1092,44 @@ static void call_nt_transact_create(connection_struct *conn,
 	 */
 	create_options &= ~NTCREATEX_OPTIONS_MUST_IGNORE_MASK;
 
+	srvstr_get_path(ctx, params, req->flags2, &fname,
+			params+53, parameter_count-53,
+			STR_TERMINATE, &status);
+	if (!NT_STATUS_IS_OK(status)) {
+		reply_nterror(req, status);
+		goto out;
+	}
+
+	if (file_attributes & FILE_FLAG_POSIX_SEMANTICS) {
+		case_state = set_posix_case_semantics(ctx, conn);
+		if (!case_state) {
+			reply_nterror(req, NT_STATUS_NO_MEMORY);
+			goto out;
+		}
+	}
+
+	status = filename_convert(ctx,
+				conn,
+				req->flags2 & FLAGS2_DFS_PATHNAMES,
+				fname,
+				(create_disposition == FILE_CREATE)
+				  ? UCF_CREATING_FILE : 0,
+				NULL,
+				&smb_fname);
+
+	TALLOC_FREE(case_state);
+
+	if (!NT_STATUS_IS_OK(status)) {
+		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+			reply_botherror(req,
+				NT_STATUS_PATH_NOT_COVERED,
+				ERRSRV, ERRbadpath);
+			goto out;
+		}
+		reply_nterror(req, status);
+		goto out;
+	}
+
 	/* Ensure the data_len is correct for the sd and ea values given. */
 	if ((ea_len + sd_len > data_count)
 	    || (ea_len > data_count) || (sd_len > data_count)
@@ -1164,44 +1202,6 @@ static void call_nt_transact_create(connection_struct *conn,
 		}
 	}
 
-	srvstr_get_path(ctx, params, req->flags2, &fname,
-			params+53, parameter_count-53,
-			STR_TERMINATE, &status);
-	if (!NT_STATUS_IS_OK(status)) {
-		reply_nterror(req, status);
-		goto out;
-	}
-
-	if (file_attributes & FILE_FLAG_POSIX_SEMANTICS) {
-		case_state = set_posix_case_semantics(ctx, conn);
-		if (!case_state) {
-			reply_nterror(req, NT_STATUS_NO_MEMORY);
-			goto out;
-		}
-	}
-
-	status = filename_convert(ctx,
-				conn,
-				req->flags2 & FLAGS2_DFS_PATHNAMES,
-				fname,
-				(create_disposition == FILE_CREATE)
-				  ? UCF_CREATING_FILE : 0,
-				NULL,
-				&smb_fname);
-
-	TALLOC_FREE(case_state);
-
-	if (!NT_STATUS_IS_OK(status)) {
-		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
-			reply_botherror(req,
-				NT_STATUS_PATH_NOT_COVERED,
-				ERRSRV, ERRbadpath);
-			goto out;
-		}
-		reply_nterror(req, status);
-		goto out;
-	}
-
 	oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
 	if (oplock_request) {
 		oplock_request |= (flags & REQUEST_BATCH_OPLOCK)
-- 
1.8.3


From c8f92e5136859c1fc3b5c84775e54a02b35bf147 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Tue, 16 Jul 2013 09:14:12 -0700
Subject: [PATCH 10/11] Reply with correct trans2 message on a setpathinfo with
 a bad EA name.

Bug 9992 - Windows error 0x800700FE when copying files with xattr names containing ":"

Signed-off-by: Jeremy Allison <jra at samba.org>
---
 source3/smbd/trans2.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
index 916686c..a216f15 100644
--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -8278,7 +8278,16 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
 			return;
 		}
 
-		reply_nterror(req, status);
+		/*
+		 * Invalid EA name needs to return 2 param bytes,
+		 * not a zero-length error packet.
+		 */
+		if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
+			send_trans2_replies(conn, req, status, params, 2, NULL, 0,
+					max_data_bytes);
+		} else {
+			reply_nterror(req, status);
+		}
 		return;
 	}
 
-- 
1.8.3


From 1821b7252764039731ba091bf1804a9ed88063d7 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Tue, 9 Jul 2013 16:37:48 -0700
Subject: [PATCH 11/11] Add torture tests to raw.eas to check sending Windows
 invalid names in the middle of an EA list.

Add torture tests to probe the set of invalid
Windows EA names.

Bug 9992 - Windows error 0x800700FE when copying files with xattr names containing ":"

Signed-off-by: Jeremy Allison <jra at samba.org>
---
 selftest/knownfail        |   1 +
 source4/torture/raw/eas.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 115 insertions(+)

diff --git a/selftest/knownfail b/selftest/knownfail
index 313d6c9..4fe96f3 100644
--- a/selftest/knownfail
+++ b/selftest/knownfail
@@ -81,6 +81,7 @@
 ^samba4.raw.session.expire1
 ^samba4.raw.rename.*.osxrename
 ^samba4.raw.rename.*.directory rename
+^samba4.raw.eas
 ^samba4.rpc.winreg.*security
 ^samba4.local.registry.(dir|ldb).check hive security
 ^samba4.local.registry.local.security
diff --git a/source4/torture/raw/eas.c b/source4/torture/raw/eas.c
index a0ba06f..95a55d1 100644
--- a/source4/torture/raw/eas.c
+++ b/source4/torture/raw/eas.c
@@ -42,6 +42,8 @@ static bool check_ea(struct smbcli_state *cli,
 	return NT_STATUS_IS_OK(status);
 }
 
+static char bad_ea_chars[] = "\"*+,/:;<=>?[\\]|";
+
 static bool test_eas(struct smbcli_state *cli, struct torture_context *tctx)
 {
 	NTSTATUS status;
@@ -49,6 +51,8 @@ static bool test_eas(struct smbcli_state *cli, struct torture_context *tctx)
 	union smb_open io;
 	const char *fname = BASEDIR "\\ea.txt";
 	bool ret = true;
+	char bad_ea_name[6];
+	int i;
 	int fnum = -1;
 
 	torture_comment(tctx, "TESTING SETFILEINFO EA_SET\n");
@@ -131,6 +135,59 @@ static bool test_eas(struct smbcli_state *cli, struct torture_context *tctx)
 	ret &= check_ea(cli, fname, "EAONE", NULL);
 	ret &= check_ea(cli, fname, "SECONDEA", NULL);
 
+	/* Check EA name containing colon. All EA's set
+	   must be ignored, not just the one with the bad
+	   name. */
+
+	torture_comment(tctx, "Adding bad EA name\n");
+	setfile.generic.level = RAW_SFILEINFO_EA_SET;
+	setfile.generic.in.file.fnum = fnum;
+	setfile.ea_set.in.num_eas = 3;
+	setfile.ea_set.in.eas = talloc_array(tctx, struct ea_struct, 3);
+	setfile.ea_set.in.eas[0].flags = 0;
+	setfile.ea_set.in.eas[0].name.s = "EAONE";
+	setfile.ea_set.in.eas[0].value = data_blob_string_const("VALUE1");
+	setfile.ea_set.in.eas[1].flags = 0;
+	setfile.ea_set.in.eas[1].name.s = "SECOND:EA";
+	setfile.ea_set.in.eas[1].value = data_blob_string_const("ValueTwo");
+	setfile.ea_set.in.eas[2].flags = 0;
+	setfile.ea_set.in.eas[2].name.s = "THIRDEA";
+	setfile.ea_set.in.eas[2].value = data_blob_string_const("ValueThree");
+
+	status = smb_raw_setfileinfo(cli->tree, &setfile);
+	CHECK_STATUS(status, STATUS_INVALID_EA_NAME);
+
+	ret &= check_ea(cli, fname, "EAONE", NULL);
+	ret &= check_ea(cli, fname, "THIRDEA", NULL);
+
+	setfile.generic.level = RAW_SFILEINFO_EA_SET;
+	setfile.generic.in.file.fnum = fnum;
+	setfile.ea_set.in.num_eas = 1;
+	setfile.ea_set.in.eas = talloc_array(tctx, struct ea_struct, 1);
+	setfile.ea_set.in.eas[0].flags = 0;
+	strlcpy(bad_ea_name, "TEST_X", sizeof(bad_ea_name));
+	setfile.ea_set.in.eas[0].name.s = bad_ea_name;
+
+	torture_comment(tctx, "Testing bad EA name range.\n");
+
+	for (i = 1; i < 256; i++) {
+		setfile.ea_set.in.eas[0].value = data_blob_string_const("VALUE1");
+		bad_ea_name[5] = (char)i;
+		torture_comment(tctx, "Testing bad EA name %d.\n", i);
+		status = smb_raw_setfileinfo(cli->tree, &setfile);
+		if (i < 32 || strchr(bad_ea_chars, i)) {
+			CHECK_STATUS(status, STATUS_INVALID_EA_NAME);
+		} else {
+			CHECK_STATUS(status, NT_STATUS_OK);
+
+			/* Now delete the EA we just set to make
+			   sure we don't run out of room. */
+			setfile.ea_set.in.eas[0].value = data_blob(NULL, 0);
+			status = smb_raw_setfileinfo(cli->tree, &setfile);
+			CHECK_STATUS(status, NT_STATUS_OK);
+		}
+	}
+
 done:
 	smbcli_close(cli->tree, fnum);
 	return ret;
@@ -365,6 +422,7 @@ static bool test_nttrans_create(struct smbcli_state *cli, struct torture_context
 	NTSTATUS status;
 	union smb_open io;
 	const char *fname = BASEDIR "\\ea2.txt";
+	const char *fname_bad = BASEDIR "\\ea2_bad.txt";
 	bool ret = true;
 	int fnum = -1;
 	struct ea_struct eas[3];
@@ -434,6 +492,62 @@ static bool test_nttrans_create(struct smbcli_state *cli, struct torture_context
 	ret &= check_ea(cli, fname, "and 3rd", "final value");
 	ret &= check_ea(cli, fname, "Fourth EA", NULL);
 
+	torture_comment(tctx, "TESTING NTTRANS CREATE WITH BAD EA NAMES\n");
+
+	io.generic.level = RAW_OPEN_NTTRANS_CREATE;
+	io.ntcreatex.in.root_fid.fnum = 0;
+	io.ntcreatex.in.flags = 0;
+	io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
+	io.ntcreatex.in.create_options = 0;
+	io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
+	io.ntcreatex.in.share_access =
+		NTCREATEX_SHARE_ACCESS_READ |
+		NTCREATEX_SHARE_ACCESS_WRITE;
+	io.ntcreatex.in.alloc_size = 0;
+	io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
+	io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
+	io.ntcreatex.in.security_flags = 0;
+	io.ntcreatex.in.fname = fname_bad;
+
+	ea_list.num_eas = 3;
+	ea_list.eas = eas;
+
+	eas[0].flags = 0;
+	eas[0].name.s = "1st EA";
+	eas[0].value = data_blob_string_const("Value One");
+
+	eas[1].flags = 0;
+	eas[1].name.s = "2nd:BAD:EA";
+	eas[1].value = data_blob_string_const("Second Value");
+
+	eas[2].flags = 0;
+	eas[2].name.s = "and 3rd";
+	eas[2].value = data_blob_string_const("final value");
+
+	io.ntcreatex.in.ea_list = &ea_list;
+	io.ntcreatex.in.sec_desc = NULL;
+
+	status = smb_raw_open(cli->tree, tctx, &io);
+	CHECK_STATUS(status, STATUS_INVALID_EA_NAME);
+
+	/* File must not exist. */
+	io.generic.level = RAW_OPEN_NTCREATEX;
+	io.ntcreatex.in.root_fid.fnum = 0;
+	io.ntcreatex.in.flags = 0;
+	io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
+	io.ntcreatex.in.create_options = 0;
+	io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
+	io.ntcreatex.in.share_access =
+		NTCREATEX_SHARE_ACCESS_READ |
+		NTCREATEX_SHARE_ACCESS_WRITE;
+	io.ntcreatex.in.alloc_size = 0;
+	io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
+	io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
+	io.ntcreatex.in.security_flags = 0;
+	io.ntcreatex.in.fname = fname_bad;
+	status = smb_raw_open(cli->tree, tctx, &io);
+	CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
+
 done:
 	smbcli_close(cli->tree, fnum);
 	return ret;
-- 
1.8.3



More information about the samba-technical mailing list