summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2013-03-26 13:26:49 -0700
committerDavid Disseldorp <ddiss@samba.org>2013-04-02 20:06:38 +0200
commit7bee3ef68490bb38942d717e03e203d00be32f9f (patch)
tree97f013122ea0d762182eb6a2f8ce31a91b0b2732
parentb96bc9fa260c397887ba6199181f3b8bca7046a6 (diff)
downloadsamba-7bee3ef68490bb38942d717e03e203d00be32f9f.tar.gz
samba-7bee3ef68490bb38942d717e03e203d00be32f9f.tar.bz2
samba-7bee3ef68490bb38942d717e03e203d00be32f9f.zip
Add a test to show that zero-length EA's are never returned over SMB2.
Zero length EA's only delete an EA, never store. Proves we should never return zero-length EA's even if they have been set on the POSIX side. ntvfs server doesn't implement the FULL_EA_INFORMATION setinfo call, so add to selftest/knownfail. Signed-off-by: Jeremy Allison <jra@samba.org> Reviewed-by: David Disseldorp <ddiss@suse.de>
-rw-r--r--selftest/knownfail1
-rw-r--r--source4/torture/smb2/setinfo.c121
2 files changed, 122 insertions, 0 deletions
diff --git a/selftest/knownfail b/selftest/knownfail
index 61a0a0ed24..e4b4694db3 100644
--- a/selftest/knownfail
+++ b/selftest/knownfail
@@ -162,6 +162,7 @@
^samba4.blackbox.upgradeprovision.alpha13.ldapcmp_sd\(none\) # Due to something rewriting the NT ACL on DNS objects
^samba4.blackbox.upgradeprovision.alpha13.ldapcmp_full_sd\(none\) # Due to something rewriting the NT ACL on DNS objects
^samba4.blackbox.upgradeprovision.release-4-0-0.ldapcmp_sd\(none\) # Due to something rewriting the NT ACL on DNS objects
+^samba4.smb2.setinfo.setinfo # ntvfs doesn't support FULL_EA_INFORMATION set.
^samba3.smb2.create.gentest
^samba3.smb2.create.blob
^samba3.smb2.create.open
diff --git a/source4/torture/smb2/setinfo.c b/source4/torture/smb2/setinfo.c
index 719e8f0b01..fee72931b6 100644
--- a/source4/torture/smb2/setinfo.c
+++ b/source4/torture/smb2/setinfo.c
@@ -30,6 +30,36 @@
#include "libcli/security/security.h"
#include "librpc/gen_ndr/ndr_security.h"
+static bool find_returned_ea(union smb_fileinfo *finfo2,
+ const char *eaname,
+ const char *eavalue)
+{
+ unsigned int i;
+ unsigned int num_eas = finfo2->all_eas.out.num_eas;
+ struct ea_struct *eas = finfo2->all_eas.out.eas;
+
+ for (i = 0; i < num_eas; i++) {
+ if (eas[i].name.s == NULL) {
+ continue;
+ }
+ /* Windows capitalizes returned EA names. */
+ if (strcasecmp_m(eas[i].name.s, eaname)) {
+ continue;
+ }
+ if (eavalue == NULL && eas[i].value.length == 0) {
+ /* Null value, found it ! */
+ return true;
+ }
+ if (eas[i].value.length == strlen(eavalue) &&
+ memcmp(eas[i].value.data,
+ eavalue,
+ strlen(eavalue)) == 0) {
+ return true;
+ }
+ }
+ return false;
+}
+
#define BASEDIR ""
#define FAIL_UNLESS(__cond) \
@@ -60,6 +90,7 @@ bool torture_smb2_setinfo(struct torture_context *tctx)
const char *call_name;
time_t basetime = (time(NULL) - 86400) & ~1;
int n = time(NULL) % 100;
+ struct ea_struct ea;
ZERO_STRUCT(handle);
@@ -276,6 +307,96 @@ bool torture_smb2_setinfo(struct torture_context *tctx)
CHECK_CALL(SEC_DESC, NT_STATUS_OK);
FAIL_UNLESS(smb2_util_verify_sd(tctx, tree, handle, sd));
+ torture_comment(tctx, "Check zero length EA's behavior\n");
+
+ /* Set a new EA. */
+ sfinfo.full_ea_information.in.eas.num_eas = 1;
+ ea.flags = 0;
+ ea.name.private_length = 6;
+ ea.name.s = "NewEA";
+ ea.value = data_blob_string_const("testme");
+ sfinfo.full_ea_information.in.eas.eas = &ea;
+ CHECK_CALL(FULL_EA_INFORMATION, NT_STATUS_OK);
+
+ /* Does it still exist ? */
+ finfo2.generic.level = RAW_FILEINFO_SMB2_ALL_EAS;
+ finfo2.generic.in.file.handle = handle;
+ finfo2.all_eas.in.continue_flags = 1;
+ status2 = smb2_getinfo_file(tree, tctx, &finfo2);
+ if (!NT_STATUS_IS_OK(status2)) {
+ torture_result(tctx, TORTURE_FAIL, "(%s) %s - %s\n", __location__,
+ "SMB2_ALL_EAS", nt_errstr(status2));
+ ret = false;
+ goto done;
+ }
+
+ /* Note on Windows EA name is returned capitalized. */
+ if (!find_returned_ea(&finfo2, "NewEA", "testme")) {
+ torture_result(tctx, TORTURE_FAIL, "(%s) Missing EA 'NewEA'\n", __location__);
+ ret = false;
+ }
+
+ /* Now zero it out (should delete it) */
+ sfinfo.full_ea_information.in.eas.num_eas = 1;
+ ea.flags = 0;
+ ea.name.private_length = 6;
+ ea.name.s = "NewEA";
+ ea.value = data_blob_null;
+ sfinfo.full_ea_information.in.eas.eas = &ea;
+ CHECK_CALL(FULL_EA_INFORMATION, NT_STATUS_OK);
+
+ /* Does it still exist ? */
+ finfo2.generic.level = RAW_FILEINFO_SMB2_ALL_EAS;
+ finfo2.generic.in.file.handle = handle;
+ finfo2.all_eas.in.continue_flags = 1;
+ status2 = smb2_getinfo_file(tree, tctx, &finfo2);
+ if (!NT_STATUS_IS_OK(status2)) {
+ torture_result(tctx, TORTURE_FAIL, "(%s) %s - %s\n", __location__,
+ "SMB2_ALL_EAS", nt_errstr(status2));
+ ret = false;
+ goto done;
+ }
+
+ if (find_returned_ea(&finfo2, "NewEA", NULL)) {
+ torture_result(tctx, TORTURE_FAIL, "(%s) EA 'NewEA' should be deleted\n", __location__);
+ ret = false;
+ }
+
+ /* Set a zero length EA. */
+ sfinfo.full_ea_information.in.eas.num_eas = 1;
+ ea.flags = 0;
+ ea.name.private_length = 6;
+ ea.name.s = "ZeroEA";
+ ea.value = data_blob_null;
+ sfinfo.full_ea_information.in.eas.eas = &ea;
+ CHECK_CALL(FULL_EA_INFORMATION, NT_STATUS_OK);
+
+ /* Does it still exist ? */
+ finfo2.generic.level = RAW_FILEINFO_SMB2_ALL_EAS;
+ finfo2.generic.in.file.handle = handle;
+ finfo2.all_eas.in.continue_flags = 1;
+ status2 = smb2_getinfo_file(tree, tctx, &finfo2);
+ if (!NT_STATUS_IS_OK(status2)) {
+ torture_result(tctx, TORTURE_FAIL, "(%s) %s - %s\n", __location__,
+ "SMB2_ALL_EAS", nt_errstr(status2));
+ ret = false;
+ goto done;
+ }
+
+ /* Over SMB2 ZeroEA should not exist. */
+ if (!find_returned_ea(&finfo2, "EAONE", "VALUE1")) {
+ torture_result(tctx, TORTURE_FAIL, "(%s) Missing EA 'EAONE'\n", __location__);
+ ret = false;
+ }
+ if (!find_returned_ea(&finfo2, "SECONDEA", "ValueTwo")) {
+ torture_result(tctx, TORTURE_FAIL, "(%s) Missing EA 'SECONDEA'\n", __location__);
+ ret = false;
+ }
+ if (find_returned_ea(&finfo2, "ZeroEA", NULL)) {
+ torture_result(tctx, TORTURE_FAIL, "(%s) Found null EA 'ZeroEA'\n", __location__);
+ ret = false;
+ }
+
done:
status = smb2_util_close(tree, handle);
if (NT_STATUS_IS_ERR(status)) {