/* * Test creating a file with a NULL DACL. */ static bool test_create_null_dacl(struct torture_context *tctx, struct smb2_tree *tree) { NTSTATUS status; struct smb2_create io; const char *fname = "nulldacl.txt"; bool ret = true; struct smb2_handle handle; union smb_fileinfo q; union smb_setfileinfo s; struct security_descriptor *sd = security_descriptor_initialise(tctx); struct security_acl dacl; torture_comment(tctx, "TESTING SEC_DESC WITH A NULL DACL\n"); smb2_util_unlink(tree, fname); ZERO_STRUCT(io); io.level = RAW_OPEN_SMB2; io.in.create_flags = 0; io.in.desired_access = SEC_STD_READ_CONTROL | SEC_STD_WRITE_DAC | SEC_STD_WRITE_OWNER; io.in.create_options = 0; io.in.file_attributes = FILE_ATTRIBUTE_NORMAL; io.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE; io.in.alloc_size = 0; io.in.create_disposition = NTCREATEX_DISP_CREATE; io.in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS; io.in.security_flags = 0; io.in.fname = fname; io.in.sec_desc = sd; /* XXX create_options ? */ io.in.create_options = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY | NTCREATEX_OPTIONS_ASYNC_ALERT | NTCREATEX_OPTIONS_NON_DIRECTORY_FILE | 0x00200000; torture_comment(tctx, "creating a file with a empty sd\n"); status = smb2_create(tree, tctx, &io); CHECK_STATUS(status, NT_STATUS_OK); handle = io.out.file.handle; torture_comment(tctx, "get the original sd\n"); q.query_secdesc.level = RAW_FILEINFO_SEC_DESC; q.query_secdesc.in.file.handle = handle; q.query_secdesc.in.secinfo_flags = SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL; status = smb2_getinfo_file(tree, tctx, &q); CHECK_STATUS(status, NT_STATUS_OK); /* * Testing the created DACL, * the server should add the inherited DACL * when SEC_DESC_DACL_PRESENT isn't specified */ if (!(q.query_secdesc.out.sd->type & SEC_DESC_DACL_PRESENT)) { ret = false; torture_fail_goto(tctx, done, "DACL_PRESENT flag not set by the server!\n"); } if (q.query_secdesc.out.sd->dacl == NULL) { ret = false; torture_fail_goto(tctx, done, "no DACL has been created on the server!\n"); } torture_comment(tctx, "set NULL DACL\n"); sd->type |= SEC_DESC_DACL_PRESENT; s.set_secdesc.level = RAW_SFILEINFO_SEC_DESC; s.set_secdesc.in.file.handle = handle; s.set_secdesc.in.secinfo_flags = SECINFO_DACL; s.set_secdesc.in.sd = sd; status = smb2_setinfo_file(tree, &s); CHECK_STATUS(status, NT_STATUS_OK); torture_comment(tctx, "get the sd\n"); q.query_secdesc.level = RAW_FILEINFO_SEC_DESC; q.query_secdesc.in.file.handle = handle; q.query_secdesc.in.secinfo_flags = SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL; status = smb2_getinfo_file(tree, tctx, &q); CHECK_STATUS(status, NT_STATUS_OK); /* Testing the modified DACL */ if (!(q.query_secdesc.out.sd->type & SEC_DESC_DACL_PRESENT)) { ret = false; torture_fail_goto(tctx, done, "DACL_PRESENT flag not set by the server!\n"); } if (q.query_secdesc.out.sd->dacl != NULL) { ret = false; torture_fail_goto(tctx, done, "DACL has been created on the server!\n"); } io.in.create_disposition = NTCREATEX_DISP_OPEN; torture_comment(tctx, "try open for read control\n"); io.in.desired_access = SEC_STD_READ_CONTROL; status = smb2_create(tree, tctx, &io); CHECK_STATUS(status, NT_STATUS_OK); CHECK_ACCESS_FLAGS(io.out.file.handle, SEC_STD_READ_CONTROL); smb2_util_close(tree, io.out.file.handle); torture_comment(tctx, "try open for write\n"); io.in.desired_access = SEC_FILE_WRITE_DATA; status = smb2_create(tree, tctx, &io); CHECK_STATUS(status, NT_STATUS_OK); CHECK_ACCESS_FLAGS(io.out.file.handle, SEC_FILE_WRITE_DATA); smb2_util_close(tree, io.out.file.handle); torture_comment(tctx, "try open for read\n"); io.in.desired_access = SEC_FILE_READ_DATA; status = smb2_create(tree, tctx, &io); CHECK_STATUS(status, NT_STATUS_OK); CHECK_ACCESS_FLAGS(io.out.file.handle, SEC_FILE_READ_DATA); smb2_util_close(tree, io.out.file.handle); torture_comment(tctx, "try open for generic write\n"); io.in.desired_access = SEC_GENERIC_WRITE; status = smb2_create(tree, tctx, &io); CHECK_STATUS(status, NT_STATUS_OK); CHECK_ACCESS_FLAGS(io.out.file.handle, SEC_RIGHTS_FILE_WRITE); smb2_util_close(tree, io.out.file.handle); torture_comment(tctx, "try open for generic read\n"); io.in.desired_access = SEC_GENERIC_READ; status = smb2_create(tree, tctx, &io); CHECK_STATUS(status, NT_STATUS_OK); CHECK_ACCESS_FLAGS(io.out.file.handle, SEC_RIGHTS_FILE_READ); smb2_util_close(tree, io.out.file.handle); torture_comment(tctx, "set DACL with 0 aces\n"); ZERO_STRUCT(dacl); dacl.revision = SECURITY_ACL_REVISION_NT4; dacl.num_aces = 0; sd->dacl = &dacl; s.set_secdesc.level = RAW_SFILEINFO_SEC_DESC; s.set_secdesc.in.file.handle = handle; s.set_secdesc.in.secinfo_flags = SECINFO_DACL; s.set_secdesc.in.sd = sd; status = smb2_setinfo_file(tree, &s); CHECK_STATUS(status, NT_STATUS_OK); torture_comment(tctx, "get the sd\n"); q.query_secdesc.level = RAW_FILEINFO_SEC_DESC; q.query_secdesc.in.file.handle = handle; q.query_secdesc.in.secinfo_flags = SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL; status = smb2_getinfo_file(tree, tctx, &q); CHECK_STATUS(status, NT_STATUS_OK); /* Testing the modified DACL */ if (!(q.query_secdesc.out.sd->type & SEC_DESC_DACL_PRESENT)) { ret = false; torture_fail_goto(tctx, done, "DACL_PRESENT flag not set by the server!\n"); } if (q.query_secdesc.out.sd->dacl == NULL) { ret = false; torture_fail_goto(tctx, done, "no DACL has been created on the server!\n"); } if (q.query_secdesc.out.sd->dacl->num_aces != 0) { torture_result(tctx, TORTURE_FAIL, "DACL has %u aces!\n", q.query_secdesc.out.sd->dacl->num_aces); ret = false; goto done; } torture_comment(tctx, "try open for read control\n"); io.in.desired_access = SEC_STD_READ_CONTROL; status = smb2_create(tree, tctx, &io); CHECK_STATUS(status, NT_STATUS_OK); CHECK_ACCESS_FLAGS(io.out.file.handle, SEC_STD_READ_CONTROL); smb2_util_close(tree, io.out.file.handle); torture_comment(tctx, "try open for write => access_denied\n"); io.in.desired_access = SEC_FILE_WRITE_DATA; status = smb2_create(tree, tctx, &io); if (torture_setting_bool(tctx, "hide_on_access_denied", false)) { CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND); } else { CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED); } torture_comment(tctx, "try open for read => access_denied\n"); io.in.desired_access = SEC_FILE_READ_DATA; status = smb2_create(tree, tctx, &io); if (torture_setting_bool(tctx, "hide_on_access_denied", false)) { CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND); } else { CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED); } torture_comment(tctx, "try open for generic write => access_denied\n"); io.in.desired_access = SEC_GENERIC_WRITE; status = smb2_create(tree, tctx, &io); if (torture_setting_bool(tctx, "hide_on_access_denied", false)) { CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND); } else { CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED); } torture_comment(tctx, "try open for generic read => access_denied\n"); io.in.desired_access = SEC_GENERIC_READ; status = smb2_create(tree, tctx, &io); if (torture_setting_bool(tctx, "hide_on_access_denied", false)) { CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND); } else { CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED); } torture_comment(tctx, "set empty sd\n"); sd->type &= ~SEC_DESC_DACL_PRESENT; sd->dacl = NULL; s.set_secdesc.level = RAW_SFILEINFO_SEC_DESC; s.set_secdesc.in.file.handle = handle; s.set_secdesc.in.secinfo_flags = SECINFO_DACL; s.set_secdesc.in.sd = sd; status = smb2_setinfo_file(tree, &s); CHECK_STATUS(status, NT_STATUS_OK); torture_comment(tctx, "get the sd\n"); q.query_secdesc.level = RAW_FILEINFO_SEC_DESC; q.query_secdesc.in.file.handle = handle; q.query_secdesc.in.secinfo_flags = SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL; status = smb2_getinfo_file(tree, tctx, &q); CHECK_STATUS(status, NT_STATUS_OK); /* Testing the modified DACL */ if (!(q.query_secdesc.out.sd->type & SEC_DESC_DACL_PRESENT)) { ret = false; torture_fail_goto(tctx, done, "DACL_PRESENT flag not set by the server!\n"); } if (q.query_secdesc.out.sd->dacl != NULL) { ret = false; torture_fail_goto(tctx, done, "DACL has been created on the server!\n"); } done: smb2_util_close(tree, handle); smb2_util_unlink(tree, fname); smb2_tdis(tree); smb2_logoff(tree->session); return ret; }
/* basic testing of SMB2 connection calls */ BOOL torture_smb2_connect(struct torture_context *torture) { TALLOC_CTX *mem_ctx = talloc_new(NULL); struct smb2_tree *tree; struct smb2_handle h1, h2; NTSTATUS status; if (!torture_smb2_connection(mem_ctx, &tree)) { return False; } h1 = torture_smb2_create(tree, "test9.dat"); h2 = torture_smb2_create(tree, "test9.dat"); status = torture_smb2_write(tree, h1); if (!NT_STATUS_IS_OK(status)) { printf("Write failed - %s\n", nt_errstr(status)); return False; } status = torture_smb2_close(tree, h1); if (!NT_STATUS_IS_OK(status)) { printf("Close failed - %s\n", nt_errstr(status)); return False; } status = torture_smb2_close(tree, h2); if (!NT_STATUS_IS_OK(status)) { printf("Close failed - %s\n", nt_errstr(status)); return False; } status = smb2_util_close(tree, h1); if (!NT_STATUS_EQUAL(status, NT_STATUS_FILE_CLOSED)) { printf("close should have closed the handle - %s\n", nt_errstr(status)); return False; } status = smb2_tdis(tree); if (!NT_STATUS_IS_OK(status)) { printf("tdis failed - %s\n", nt_errstr(status)); return False; } status = smb2_tdis(tree); if (!NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_NAME_DELETED)) { printf("tdis should have disabled session - %s\n", nt_errstr(status)); return False; } status = smb2_logoff(tree->session); if (!NT_STATUS_IS_OK(status)) { printf("Logoff failed - %s\n", nt_errstr(status)); return False; } status = smb2_logoff(tree->session); if (!NT_STATUS_EQUAL(status, NT_STATUS_USER_SESSION_DELETED)) { printf("Logoff should have disabled session - %s\n", nt_errstr(status)); return False; } status = smb2_keepalive(tree->session->transport); if (!NT_STATUS_IS_OK(status)) { printf("keepalive failed? - %s\n", nt_errstr(status)); return False; } talloc_free(mem_ctx); return True; }