From d163d2624dca3de3192a37f5341af412b61d374a Mon Sep 17 00:00:00 2001 From: Jeremy Allison 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 --- 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 6e23b4febad46692212880edbd10d4c1cf9d2150 Mon Sep 17 00:00:00 2001 From: Jeremy Allison 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 --- 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 05eed65e0c2474401660b4dd219eccee844351ec Mon Sep 17 00:00:00 2001 From: Jeremy Allison 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 --- 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 c71b16347e98d3055db14201deacc78fdf78d997 Mon Sep 17 00:00:00 2001 From: Jeremy Allison 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 --- 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 68cd1db86698fd85115d5bbcacab2decfcd724ee Mon Sep 17 00:00:00 2001 From: Jeremy Allison 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 --- 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 48b0f551bebc982105267f4981f731d34be71368 Mon Sep 17 00:00:00 2001 From: Jeremy Allison 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 --- 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 e7bec0cc78162ceff19d860df47bd06960dd7629 Mon Sep 17 00:00:00 2001 From: Jeremy Allison 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 --- 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 f8a752ac22c66695fba33f6683ae227ed87044a7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison 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 --- 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 b85c0acbfd5cceb678caf02a2990b628774172e7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison 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 --- 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 f79da3333d12f89e4b0ec05fd725c5d135e48330 Mon Sep 17 00:00:00 2001 From: Jeremy Allison 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 --- 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 e489e3dc48d122a81c429651d0312c6416956960 Mon Sep 17 00:00:00 2001 From: Jeremy Allison 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 --- 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