static bool test_handles_drsuapi(struct torture_context *torture) { NTSTATUS status; struct dcerpc_pipe *p1, *p2; struct policy_handle handle; struct policy_handle handle2; struct GUID bind_guid; struct drsuapi_DsBind r; struct drsuapi_DsUnbind c; TALLOC_CTX *mem_ctx = talloc_new(torture); torture_comment(torture, "RPC-HANDLE-DRSUAPI\n"); status = torture_rpc_connection(mem_ctx, &p1, &dcerpc_table_drsuapi); torture_assert_ntstatus_ok(torture, status, "opening drsuapi pipe1"); status = torture_rpc_connection(mem_ctx, &p2, &dcerpc_table_drsuapi); torture_assert_ntstatus_ok(torture, status, "opening drsuapi pipe1"); GUID_from_string(DRSUAPI_DS_BIND_GUID, &bind_guid); r.in.bind_guid = &bind_guid; r.in.bind_info = NULL; r.out.bind_handle = &handle; status = dcerpc_drsuapi_DsBind(p1, mem_ctx, &r); if (!NT_STATUS_IS_OK(status)) { torture_comment(torture, "drsuapi_DsBind not supported - skipping\n"); talloc_free(mem_ctx); return true; } c.in.bind_handle = &handle; c.out.bind_handle = &handle2; status = dcerpc_drsuapi_DsUnbind(p2, mem_ctx, &c); torture_assert_ntstatus_equal(torture, status, NT_STATUS_NET_WRITE_FAULT, "closing policy handle on p2"); torture_assert_int_equal(torture, p2->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH, "closing policy handle on p2"); status = dcerpc_drsuapi_DsUnbind(p1, mem_ctx, &c); torture_assert_ntstatus_ok(torture, status, "closing policy handle on p1"); status = dcerpc_drsuapi_DsUnbind(p1, mem_ctx, &c); torture_assert_ntstatus_equal(torture, status, NT_STATUS_NET_WRITE_FAULT, "closing policy handle on p1 again"); torture_assert_int_equal(torture, p1->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH, "closing policy handle on p1 again"); talloc_free(mem_ctx); return true; }
/* test request timeouts */ #if 0 /* this test needs fixing to work over ncacn_np */ static bool test_timeout(struct torture_context *tctx, struct dcerpc_pipe *p) { NTSTATUS status; struct rpc_request *req; struct echo_TestSleep r; int timeout_saved = p->request_timeout; if (torture_setting_bool(tctx, "quick", false)) { torture_skip(tctx, "timeout testing disabled - use \"torture:quick=no\" to enable\n"); } torture_comment(tctx, "testing request timeouts\n"); r.in.seconds = 2; p->request_timeout = 1; req = dcerpc_echo_TestSleep_send(p, tctx, &r); if (!req) { torture_comment(tctx, "Failed to send async sleep request\n"); goto failed; } req->ignore_timeout = true; status = dcerpc_ndr_request_recv(req); torture_assert_ntstatus_equal(tctx, status, NT_STATUS_IO_TIMEOUT, "request should have timed out"); torture_comment(tctx, "testing request destruction\n"); req = dcerpc_echo_TestSleep_send(p, tctx, &r); if (!req) { torture_comment(tctx, "Failed to send async sleep request\n"); goto failed; } talloc_free(req); req = dcerpc_echo_TestSleep_send(p, tctx, &r); if (!req) { torture_comment(tctx, "Failed to send async sleep request\n"); goto failed; } req->ignore_timeout = true; status = dcerpc_ndr_request_recv(req); torture_assert_ntstatus_equal(tctx, status, NT_STATUS_IO_TIMEOUT, "request should have timed out"); p->request_timeout = timeout_saved; return test_addone(tctx, p); failed: p->request_timeout = timeout_saved; return false; }
static bool test_handles_samr(struct torture_context *torture) { NTSTATUS status; struct dcerpc_pipe *p1, *p2; struct dcerpc_binding_handle *b1, *b2; struct policy_handle handle; struct policy_handle handle2; struct samr_Connect r; struct samr_Close c; TALLOC_CTX *mem_ctx = talloc_new(torture); torture_comment(torture, "RPC-HANDLE-SAMR\n"); status = torture_rpc_connection(torture, &p1, &ndr_table_samr); torture_assert_ntstatus_ok(torture, status, "opening samr pipe1"); b1 = p1->binding_handle; status = torture_rpc_connection(torture, &p2, &ndr_table_samr); torture_assert_ntstatus_ok(torture, status, "opening samr pipe2"); b2 = p2->binding_handle; r.in.system_name = 0; r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; r.out.connect_handle = &handle; torture_assert_ntstatus_ok(torture, dcerpc_samr_Connect_r(b1, mem_ctx, &r), "Connect failed"); torture_assert_ntstatus_ok(torture, r.out.result, "opening policy handle on p1"); c.in.handle = &handle; c.out.handle = &handle2; status = dcerpc_samr_Close_r(b2, mem_ctx, &c); torture_assert_ntstatus_equal(torture, status, NT_STATUS_RPC_SS_CONTEXT_MISMATCH, "closing policy handle on p2"); torture_assert_ntstatus_ok(torture, dcerpc_samr_Close_r(b1, mem_ctx, &c), "Close failed"); torture_assert_ntstatus_ok(torture, c.out.result, "closing policy handle on p1"); status = dcerpc_samr_Close_r(b1, mem_ctx, &c); torture_assert_ntstatus_equal(torture, status, NT_STATUS_RPC_SS_CONTEXT_MISMATCH, "closing policy handle on p1 again"); talloc_free(mem_ctx); return true; }
static bool find_single_info2(void *mem_ctx, struct torture_context *torture, struct smbcli_state *cli, const char *fname, struct unix_info2 *info2) { union smb_search_first search; NTSTATUS status; /* Set up a new search for a single item, not using resume keys. */ ZERO_STRUCT(search); search.t2ffirst.level = RAW_SEARCH_TRANS2; search.t2ffirst.data_level = SMB_FIND_UNIX_INFO2; search.t2ffirst.in.max_count = 1; search.t2ffirst.in.flags = FLAG_TRANS2_FIND_CLOSE; search.t2ffirst.in.pattern = fname; status = smb_raw_search_first(cli->tree, mem_ctx, &search, info2, search_callback); torture_assert_ntstatus_equal(torture, status, NT_STATUS_OK, smbcli_errstr(cli->tree)); torture_assert_int_equal(torture, search.t2ffirst.out.count, 1, "expected exactly one result"); torture_assert_int_equal(torture, search.t2ffirst.out.end_of_search, 1, "expected end_of_search to be true"); return check_unix_info2(torture, info2); }
/* Check that we are able to receive the certificate of the DCs * used for client wrap version of the backup key protocol */ static bool test_RetreiveBackupKeyGUID(struct torture_context *tctx, struct dcerpc_pipe *p) { struct dcerpc_binding_handle *b = p->binding_handle; DATA_BLOB out_blob; struct bkrp_BackupKey *r = createRetreiveBackupKeyGUIDStruct(tctx, p, 2, &out_blob); if (r == NULL) { return false; } if (p->conn->security_state.auth_info != NULL && p->conn->security_state.auth_info->auth_level == 6) { torture_assert_ntstatus_ok(tctx, dcerpc_bkrp_BackupKey_r(b, tctx, r), "Get GUID"); out_blob.length = *r->out.data_out_len; torture_assert_werr_equal(tctx, r->out.result, WERR_OK, "Wrong dce/rpc error code"); } else { torture_assert_ntstatus_equal(tctx, dcerpc_bkrp_BackupKey_r(b, tctx, r), NT_STATUS_ACCESS_DENIED, "Get GUID"); } return true; }
/* see if the server recognises wide-a characters */ static bool test_widea(struct torture_context *tctx, struct smbcli_state *cli) { const uint32_t name1[] = {'a'}; const uint32_t name2[] = {0xff41}; const uint32_t name3[] = {0xff21}; NTSTATUS status; torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "setting up basedir"); status = unicode_open(tctx, cli->tree, tctx, NTCREATEX_DISP_CREATE, name1, 1); torture_assert_ntstatus_ok(tctx, status, "Failed to create 'a'"); status = unicode_open(tctx, cli->tree, tctx, NTCREATEX_DISP_CREATE, name2, 1); torture_assert_ntstatus_ok(tctx, status, "Failed to create wide-a"); status = unicode_open(tctx, cli->tree, tctx, NTCREATEX_DISP_CREATE, name3, 1); torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OBJECT_NAME_COLLISION, "Failed to create wide-A"); return true; }
static bool test_RestoreGUID(struct torture_context *tctx, struct dcerpc_pipe *p) { enum ndr_err_code ndr_err; struct dcerpc_binding_handle *b = p->binding_handle; DATA_BLOB out_blob; struct bkrp_client_side_unwrapped resp; if (p->conn->security_state.auth_info != NULL && p->conn->security_state.auth_info->auth_level == 6) { struct bkrp_BackupKey *r = createRestoreGUIDStruct(tctx, p, 2, &out_blob, false, false, false, false, false, false, false); torture_assert_ntstatus_ok(tctx, dcerpc_bkrp_BackupKey_r(b, tctx, r), "Restore GUID"); out_blob.length = *r->out.data_out_len; ndr_err = ndr_pull_struct_blob(&out_blob, tctx, &resp, (ndr_pull_flags_fn_t)ndr_pull_bkrp_client_side_unwrapped); torture_assert_int_equal(tctx, NDR_ERR_CODE_IS_SUCCESS(ndr_err), 1, "Unable to unmarshall bkrp_client_side_unwrapped"); torture_assert_werr_equal(tctx, r->out.result, WERR_OK, "Restore GUID"); torture_assert_str_equal(tctx, (char*)resp.secret.data, secret, "Wrong secret"); } else { struct bkrp_BackupKey *r = createRetreiveBackupKeyGUIDStruct(tctx, p, 2, &out_blob); torture_assert_ntstatus_equal(tctx, dcerpc_bkrp_BackupKey_r(b, tctx, r), NT_STATUS_ACCESS_DENIED, "Get GUID"); } return true; }
static bool test_RestoreGUID_emptyrequest(struct torture_context *tctx, struct dcerpc_pipe *p) { struct dcerpc_binding_handle *b = p->binding_handle; DATA_BLOB out_blob; if (p->conn->security_state.auth_info != NULL && p->conn->security_state.auth_info->auth_level == 6) { struct bkrp_BackupKey *r = createRestoreGUIDStruct(tctx, p, 3, &out_blob, false, false, false, true, false, false, true); torture_assert_int_equal(tctx, r != NULL, 1, "Error while creating the restoreGUID struct"); r->in.data_in = talloc(tctx, uint8_t); r->in.data_in_len = 0; r->in.param = 0; torture_assert_ntstatus_ok(tctx, dcerpc_bkrp_BackupKey_r(b, tctx, r), "Restore GUID"); out_blob.length = *r->out.data_out_len; torture_assert_werr_equal(tctx, r->out.result, WERR_INVALID_PARAM, "Bad error code on wrong has in access check"); } else { struct bkrp_BackupKey *r = createRetreiveBackupKeyGUIDStruct(tctx, p, 2, &out_blob); torture_assert_ntstatus_equal(tctx, dcerpc_bkrp_BackupKey_r(b, tctx, r), NT_STATUS_ACCESS_DENIED, "Get GUID"); } return true; }
static bool test_FlushEventLog(struct torture_context *tctx, struct dcerpc_pipe *p) { struct eventlog_FlushEventLog r; struct eventlog_CloseEventLog cr; struct policy_handle handle; if (!get_policy_handle(tctx, p, &handle)) return false; r.in.handle = &handle; /* Huh? Does this RPC always return access denied? */ torture_assert_ntstatus_equal(tctx, dcerpc_eventlog_FlushEventLog(p, tctx, &r), NT_STATUS_ACCESS_DENIED, "FlushEventLog failed"); cr.in.handle = cr.out.handle = &handle; torture_assert_ntstatus_ok(tctx, dcerpc_eventlog_CloseEventLog(p, tctx, &cr), "CloseEventLog failed"); return true; }
static bool test_handles_samr(struct torture_context *torture) { NTSTATUS status; struct dcerpc_pipe *p1, *p2; struct policy_handle handle; struct policy_handle handle2; struct samr_Connect r; struct samr_Close c; TALLOC_CTX *mem_ctx = talloc_new(torture); torture_comment(torture, "RPC-HANDLE-SAMR\n"); status = torture_rpc_connection(mem_ctx, &p1, &dcerpc_table_samr); torture_assert_ntstatus_ok(torture, status, "opening samr pipe1"); status = torture_rpc_connection(mem_ctx, &p2, &dcerpc_table_samr); torture_assert_ntstatus_ok(torture, status, "opening samr pipe1"); r.in.system_name = 0; r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; r.out.connect_handle = &handle; status = dcerpc_samr_Connect(p1, mem_ctx, &r); torture_assert_ntstatus_ok(torture, status, "opening policy handle on p1"); c.in.handle = &handle; c.out.handle = &handle2; status = dcerpc_samr_Close(p2, mem_ctx, &c); torture_assert_ntstatus_equal(torture, status, NT_STATUS_NET_WRITE_FAULT, "closing policy handle on p2"); torture_assert_int_equal(torture, p2->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH, "closing policy handle on p2"); status = dcerpc_samr_Close(p1, mem_ctx, &c); torture_assert_ntstatus_ok(torture, status, "closing policy handle on p1"); status = dcerpc_samr_Close(p1, mem_ctx, &c); torture_assert_ntstatus_equal(torture, status, NT_STATUS_NET_WRITE_FAULT, "closing policy handle on p1 again"); torture_assert_int_equal(torture, p1->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH, "closing policy handle on p1 again"); talloc_free(mem_ctx); return true; }
static bool test_guid_from_string_invalid(struct torture_context *tctx) { struct GUID g1; torture_assert_ntstatus_equal(tctx, NT_STATUS_INVALID_PARAMETER, GUID_from_string("bla", &g1), "parameter not invalid"); return true; }
static bool test_guid_from_string_null(struct torture_context *tctx) { struct GUID guid; torture_assert_ntstatus_equal(tctx, NT_STATUS_INVALID_PARAMETER, GUID_from_string(NULL, &guid), "NULL failed"); return true; }
static bool test_handles_random_assoc(struct torture_context *torture) { NTSTATUS status; struct dcerpc_pipe *p1, *p2, *p3; TALLOC_CTX *mem_ctx = talloc_new(torture); enum dcerpc_transport_t transport; uint32_t assoc_group_id; torture_comment(torture, "RPC-HANDLE-RANDOM-ASSOC\n"); torture_comment(torture, "connect samr pipe1\n"); status = torture_rpc_connection(torture, &p1, &ndr_table_samr); torture_assert_ntstatus_ok(torture, status, "opening samr pipe1"); torture_comment(torture, "pipe1 uses assoc_group_id[0x%08X]\n", dcerpc_binding_get_assoc_group_id(p1->binding)); transport = p1->conn->transport.transport; /* * We use ~p1->assoc_group_id instead of p1->assoc_group_id, because * this way we are less likely to use an id which is already in use. */ assoc_group_id = dcerpc_binding_get_assoc_group_id(p1->binding); assoc_group_id = ~assoc_group_id; torture_comment(torture, "connect samr pipe2 with assoc_group_id[0x%08X]- should fail\n", ++assoc_group_id); status = torture_rpc_connection_transport(torture, &p2, &ndr_table_samr, transport, assoc_group_id); torture_assert_ntstatus_equal(torture, status, NT_STATUS_UNSUCCESSFUL, "opening samr pipe2"); torture_comment(torture, "connect samr pipe3 with assoc_group_id[0x%08X]- should fail\n", ++assoc_group_id); status = torture_rpc_connection_transport(torture, &p3, &ndr_table_samr, transport, assoc_group_id); torture_assert_ntstatus_equal(torture, status, NT_STATUS_UNSUCCESSFUL, "opening samr pipe3"); talloc_free(mem_ctx); return true; }
static bool netrlogonsamlogon_w2k_out_check(struct torture_context *tctx, struct netr_LogonSamLogon *r) { uint8_t return_authenticator_expected[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; torture_assert_mem_equal(tctx, r->out.return_authenticator->cred.data, return_authenticator_expected, 8, "return_authenticator.cred.data"); torture_assert_int_equal(tctx, r->out.return_authenticator->timestamp, 0, "return_authenticator.timestamp"); torture_assert(tctx, r->out.validation, "validation NULL pointer"); torture_assert(tctx, (r->out.validation->sam6 == NULL), "sam6 not NULL"); torture_assert_int_equal(tctx, *r->out.authoritative, 1, "authoritative"); torture_assert_ntstatus_equal(tctx, r->out.result, NT_STATUS_INVALID_INFO_CLASS, "unexpected result"); return true; }
static bool test_handles_random_assoc(struct torture_context *torture) { NTSTATUS status; struct dcerpc_pipe *p1, *p2, *p3; TALLOC_CTX *mem_ctx = talloc_new(torture); enum dcerpc_transport_t transport; uint32_t assoc_group_id; torture_comment(torture, "RPC-HANDLE-RANDOM-ASSOC\n"); torture_comment(torture, "connect samr pipe1\n"); status = torture_rpc_connection(mem_ctx, &p1, &dcerpc_table_samr); torture_assert_ntstatus_ok(torture, status, "opening samr pipe1"); transport = p1->conn->transport.transport, assoc_group_id = p1->assoc_group_id; torture_comment(torture, "pip1 use assoc_group_id[0x%08X]\n", assoc_group_id); torture_comment(torture, "connect samr pipe2 with assoc_group_id[0x%08X]- should fail\n", ++assoc_group_id); status = torture_rpc_connection_transport(mem_ctx, &p2, &dcerpc_table_samr, transport, assoc_group_id); torture_assert_ntstatus_equal(torture, status, NT_STATUS_UNSUCCESSFUL, "opening samr pipe2"); torture_comment(torture, "connect samr pipe3 with assoc_group_id[0x%08X]- should fail\n", ++assoc_group_id); status = torture_rpc_connection_transport(mem_ctx, &p3, &dcerpc_table_samr, transport, assoc_group_id); torture_assert_ntstatus_equal(torture, status, NT_STATUS_UNSUCCESSFUL, "opening samr pipe3"); talloc_free(mem_ctx); return true; }
static bool query_file_path_info2(void *mem_ctx, struct torture_context *torture, struct smbcli_state *cli, int fnum, const char *fname, struct unix_info2 *info2) { NTSTATUS result; union smb_fileinfo finfo; finfo.generic.level = RAW_FILEINFO_UNIX_INFO2; if (fname) { finfo.generic.in.file.path = fname; result = smb_raw_pathinfo(cli->tree, mem_ctx, &finfo); } else { finfo.generic.in.file.fnum = fnum; result = smb_raw_fileinfo(cli->tree, mem_ctx, &finfo); } torture_assert_ntstatus_equal(torture, result, NT_STATUS_OK, smbcli_errstr(cli->tree)); info2->end_of_file = finfo.unix_info2.out.end_of_file; info2->num_bytes = finfo.unix_info2.out.num_bytes; info2->status_change_time = finfo.unix_info2.out.status_change_time; info2->access_time = finfo.unix_info2.out.access_time; info2->change_time = finfo.unix_info2.out.change_time; info2->uid = finfo.unix_info2.out.uid; info2->gid = finfo.unix_info2.out.gid; info2->file_type = finfo.unix_info2.out.file_type; info2->dev_major = finfo.unix_info2.out.dev_major; info2->dev_minor = finfo.unix_info2.out.dev_minor; info2->unique_id = finfo.unix_info2.out.unique_id; info2->permissions = finfo.unix_info2.out.permissions; info2->nlink = finfo.unix_info2.out.nlink; info2->create_time = finfo.unix_info2.out.create_time; info2->file_flags = finfo.unix_info2.out.file_flags; info2->flags_mask = finfo.unix_info2.out.flags_mask; if (!check_unix_info2(torture, info2)) { return false; } return true; }
static bool test_get_policy_handle(struct torture_context *tctx, struct dcerpc_pipe *p, uint32_t access_mask, struct policy_handle **handle ) { struct policy_handle *h; struct lsa_OpenPolicy2 pr; struct lsa_ObjectAttribute attr; NTSTATUS status; h = talloc(tctx, struct policy_handle); if (!h) { return false; } attr.len = 0; attr.root_dir = NULL; attr.object_name = NULL; attr.attributes = 0; attr.sec_desc = NULL; attr.sec_qos = NULL; pr.in.system_name = "\\"; pr.in.attr = &attr; pr.in.access_mask = access_mask; pr.out.handle = h; status = dcerpc_lsa_OpenPolicy2_r(p->binding_handle, tctx, &pr); torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OK, "OpenPolicy2 failed"); if (!NT_STATUS_IS_OK(pr.out.result)) { torture_comment(tctx, "OpenPolicy2 failed - %s\n", nt_errstr(pr.out.result)); talloc_free(h); return false; } *handle = h; return true; }
bool test_DsRoleGetPrimaryDomainInformation_ext(struct torture_context *tctx, struct dcerpc_pipe *p, NTSTATUS ext_status) { struct dssetup_DsRoleGetPrimaryDomainInformation r; NTSTATUS status; int i; struct dcerpc_binding_handle *b = p->binding_handle; for (i=DS_ROLE_BASIC_INFORMATION; i <= DS_ROLE_OP_STATUS; i++) { r.in.level = i; torture_comment(tctx, "dcerpc_dssetup_DsRoleGetPrimaryDomainInformation level %d\n", i); status = dcerpc_dssetup_DsRoleGetPrimaryDomainInformation_r(b, tctx, &r); torture_assert_ntstatus_equal(tctx, ext_status, status, "DsRoleGetPrimaryDomainInformation failed"); if (NT_STATUS_IS_OK(ext_status)) { torture_assert_werr_ok(tctx, r.out.result, "DsRoleGetPrimaryDomainInformation failed"); } } return true; }
bool torture_samba3_closeerr(struct torture_context *tctx) { struct smbcli_state *cli = NULL; bool result = false; NTSTATUS status; const char *dname = "closeerr.dir"; const char *fname = "closeerr.dir\\closerr.txt"; int fnum; if (!torture_open_connection(&cli, tctx, 0)) { goto fail; } smbcli_deltree(cli->tree, dname); torture_assert_ntstatus_ok( tctx, smbcli_mkdir(cli->tree, dname), talloc_asprintf(tctx, "smbcli_mdir failed: (%s)\n", smbcli_errstr(cli->tree))); fnum = smbcli_open(cli->tree, fname, O_CREAT|O_RDWR, DENY_NONE); torture_assert(tctx, fnum != -1, talloc_asprintf(tctx, "smbcli_open failed: %s\n", smbcli_errstr(cli->tree))); smbcli_close(cli->tree, fnum); fnum = smbcli_nt_create_full(cli->tree, fname, 0, SEC_RIGHTS_FILE_ALL, FILE_ATTRIBUTE_NORMAL, NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN, 0, 0); torture_assert(tctx, fnum != -1, talloc_asprintf(tctx, "smbcli_open failed: %s\n", smbcli_errstr(cli->tree))); status = smbcli_nt_delete_on_close(cli->tree, fnum, true); torture_assert_ntstatus_ok(tctx, status, "setting delete_on_close on file failed !"); status = smbcli_chmod(cli->tree, dname, 0); torture_assert_ntstatus_ok(tctx, status, "smbcli_chmod on file failed !"); status = smbcli_close(cli->tree, fnum); smbcli_chmod(cli->tree, dname, UNIX_R_USR|UNIX_W_USR|UNIX_X_USR); smbcli_deltree(cli->tree, dname); torture_assert_ntstatus_equal(tctx, status, NT_STATUS_ACCESS_DENIED, "smbcli_close"); result = true; fail: if (cli) { torture_close_connection(cli); } return result; }
static bool test_handles_mixed_shared(struct torture_context *torture) { NTSTATUS status; struct dcerpc_pipe *p1, *p2, *p3, *p4, *p5, *p6; struct dcerpc_binding_handle *b1, *b2; struct policy_handle handle; struct policy_handle handle2; struct samr_Connect r; struct lsa_Close lc; struct samr_Close sc; TALLOC_CTX *mem_ctx = talloc_new(torture); enum dcerpc_transport_t transport; uint32_t assoc_group_id; torture_comment(torture, "RPC-HANDLE-MIXED-SHARED\n"); torture_comment(torture, "connect samr pipe1\n"); status = torture_rpc_connection(torture, &p1, &ndr_table_samr); torture_assert_ntstatus_ok(torture, status, "opening samr pipe1"); b1 = p1->binding_handle; transport = p1->conn->transport.transport; assoc_group_id = dcerpc_binding_get_assoc_group_id(p1->binding); torture_comment(torture, "use assoc_group_id[0x%08X] for new connections\n", assoc_group_id); torture_comment(torture, "connect lsa pipe2\n"); status = torture_rpc_connection_transport(torture, &p2, &ndr_table_lsarpc, transport, assoc_group_id); torture_assert_ntstatus_ok(torture, status, "opening lsa pipe2"); b2 = p2->binding_handle; torture_comment(torture, "got assoc_group_id[0x%08X] for p2\n", dcerpc_binding_get_assoc_group_id(p2->binding)); r.in.system_name = 0; r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; r.out.connect_handle = &handle; torture_comment(torture, "samr_Connect to open a policy handle on samr p1\n"); torture_assert_ntstatus_ok(torture, dcerpc_samr_Connect_r(b1, mem_ctx, &r), "Connect failed"); torture_assert_ntstatus_ok(torture, r.out.result, "opening policy handle on p1"); lc.in.handle = &handle; lc.out.handle = &handle2; sc.in.handle = &handle; sc.out.handle = &handle2; torture_comment(torture, "use policy handle on lsa p2 - should fail\n"); status = dcerpc_lsa_Close_r(b2, mem_ctx, &lc); torture_assert_ntstatus_equal(torture, status, NT_STATUS_RPC_SS_CONTEXT_MISMATCH, "closing handle on lsa p2"); torture_comment(torture, "closing policy handle on samr p1\n"); torture_assert_ntstatus_ok(torture, dcerpc_samr_Close_r(b1, mem_ctx, &sc), "Close failed"); torture_assert_ntstatus_ok(torture, sc.out.result, "closing policy handle on p1"); talloc_free(p1); talloc_free(p2); smb_msleep(10); torture_comment(torture, "connect samr pipe3 - should fail\n"); status = torture_rpc_connection_transport(torture, &p3, &ndr_table_samr, transport, assoc_group_id); torture_assert_ntstatus_equal(torture, status, NT_STATUS_UNSUCCESSFUL, "opening samr pipe3"); torture_comment(torture, "connect lsa pipe4 - should fail\n"); status = torture_rpc_connection_transport(torture, &p4, &ndr_table_lsarpc, transport, assoc_group_id); torture_assert_ntstatus_equal(torture, status, NT_STATUS_UNSUCCESSFUL, "opening lsa pipe4"); /* * We use ~assoc_group_id instead of p1->assoc_group_id, because * this way we are less likely to use an id which is already in use. */ assoc_group_id = ~assoc_group_id; torture_comment(torture, "connect samr pipe5 with assoc_group_id[0x%08X]- should fail\n", ++assoc_group_id); status = torture_rpc_connection_transport(torture, &p5, &ndr_table_samr, transport, assoc_group_id); torture_assert_ntstatus_equal(torture, status, NT_STATUS_UNSUCCESSFUL, "opening samr pipe5"); torture_comment(torture, "connect lsa pipe6 with assoc_group_id[0x%08X]- should fail\n", ++assoc_group_id); status = torture_rpc_connection_transport(torture, &p6, &ndr_table_lsarpc, transport, assoc_group_id); torture_assert_ntstatus_equal(torture, status, NT_STATUS_UNSUCCESSFUL, "opening lsa pipe6"); talloc_free(mem_ctx); return true; }
static bool torture_ntlmssp_self_check(struct torture_context *tctx) { struct gensec_security *gensec_security; struct gensec_ntlmssp_state *gensec_ntlmssp_state; DATA_BLOB data; DATA_BLOB sig, expected_sig; TALLOC_CTX *mem_ctx = tctx; torture_assert_ntstatus_ok(tctx, gensec_client_start(mem_ctx, &gensec_security, tctx->ev, lp_gensec_settings(tctx, tctx->lp_ctx)), "gensec client start"); gensec_set_credentials(gensec_security, cmdline_credentials); gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN); gensec_want_feature(gensec_security, GENSEC_FEATURE_SEAL); torture_assert_ntstatus_ok(tctx, gensec_start_mech_by_oid(gensec_security, GENSEC_OID_NTLMSSP), "Failed to start GENSEC for NTLMSSP"); gensec_ntlmssp_state = (struct gensec_ntlmssp_state *)gensec_security->private_data; gensec_ntlmssp_state->session_key = strhex_to_data_blob(tctx, "0102030405060708090a0b0c0d0e0f00"); dump_data_pw("NTLMSSP session key: \n", gensec_ntlmssp_state->session_key.data, gensec_ntlmssp_state->session_key.length); gensec_ntlmssp_state->neg_flags = NTLMSSP_NEGOTIATE_SIGN | NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_KEY_EXCH | NTLMSSP_NEGOTIATE_NTLM2; torture_assert_ntstatus_ok(tctx, ntlmssp_sign_init(gensec_ntlmssp_state), "Failed to sign_init"); data = strhex_to_data_blob(tctx, "6a43494653"); gensec_ntlmssp_sign_packet(gensec_security, gensec_security, data.data, data.length, data.data, data.length, &sig); expected_sig = strhex_to_data_blob(tctx, "01000000e37f97f2544f4d7e00000000"); dump_data_pw("NTLMSSP calc sig: ", sig.data, sig.length); dump_data_pw("NTLMSSP expected sig: ", expected_sig.data, expected_sig.length); torture_assert_int_equal(tctx, sig.length, expected_sig.length, "Wrong sig length"); torture_assert_mem_equal(tctx, sig.data, expected_sig.data, sig.length, "data mismatch"); torture_assert_ntstatus_equal(tctx, gensec_ntlmssp_check_packet(gensec_security, gensec_security, data.data, data.length, data.data, data.length, &sig), NT_STATUS_ACCESS_DENIED, "Check of just signed packet (should fail, wrong end)"); gensec_ntlmssp_state->session_key = data_blob(NULL, 0); torture_assert_ntstatus_equal(tctx, gensec_ntlmssp_check_packet(gensec_security, gensec_security, data.data, data.length, data.data, data.length, &sig), NT_STATUS_NO_USER_SESSION_KEY, "Check of just signed packet without a session key should fail"); talloc_free(gensec_security); torture_assert_ntstatus_ok(tctx, gensec_client_start(mem_ctx, &gensec_security, tctx->ev, lp_gensec_settings(tctx, tctx->lp_ctx)), "Failed to start GENSEC for NTLMSSP"); gensec_set_credentials(gensec_security, cmdline_credentials); gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN); gensec_want_feature(gensec_security, GENSEC_FEATURE_SEAL); torture_assert_ntstatus_ok(tctx, gensec_start_mech_by_oid(gensec_security, GENSEC_OID_NTLMSSP), "GENSEC start mech by oid"); gensec_ntlmssp_state = (struct gensec_ntlmssp_state *)gensec_security->private_data; gensec_ntlmssp_state->session_key = strhex_to_data_blob(tctx, "0102030405e538b0"); dump_data_pw("NTLMSSP session key: \n", gensec_ntlmssp_state->session_key.data, gensec_ntlmssp_state->session_key.length); gensec_ntlmssp_state->neg_flags = NTLMSSP_NEGOTIATE_SIGN | NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_KEY_EXCH; torture_assert_ntstatus_ok(tctx, ntlmssp_sign_init(gensec_ntlmssp_state), "Failed to sign_init"); data = strhex_to_data_blob(tctx, "6a43494653"); gensec_ntlmssp_sign_packet(gensec_security, gensec_security, data.data, data.length, data.data, data.length, &sig); expected_sig = strhex_to_data_blob(tctx, "0100000078010900397420fe0e5a0f89"); dump_data_pw("NTLMSSP calc sig: ", sig.data, sig.length); dump_data_pw("NTLMSSP expected sig: ", expected_sig.data, expected_sig.length); torture_assert_int_equal(tctx, sig.length, expected_sig.length, "Wrong sig length"); torture_assert_mem_equal(tctx, sig.data+8, expected_sig.data+8, sig.length-8, "data mismatch"); torture_assert_ntstatus_equal(tctx, gensec_ntlmssp_check_packet(gensec_security, gensec_security, data.data, data.length, data.data, data.length, &sig), NT_STATUS_ACCESS_DENIED, "Check of just signed packet (should fail, wrong end)"); sig.length /= 2; torture_assert_ntstatus_equal(tctx, gensec_ntlmssp_check_packet(gensec_security, gensec_security, data.data, data.length, data.data, data.length, &sig), NT_STATUS_ACCESS_DENIED, "Check of just signed packet with short sig"); talloc_free(gensec_security); return true; }
static bool test_handles_lsa(struct torture_context *torture) { NTSTATUS status; struct dcerpc_pipe *p1, *p2; struct dcerpc_binding_handle *b1, *b2; struct policy_handle handle; struct policy_handle handle2; struct lsa_ObjectAttribute attr; struct lsa_QosInfo qos; struct lsa_OpenPolicy r; struct lsa_Close c; uint16_t system_name = '\\'; TALLOC_CTX *mem_ctx = talloc_new(torture); torture_comment(torture, "RPC-HANDLE-LSARPC\n"); status = torture_rpc_connection(torture, &p1, &ndr_table_lsarpc); torture_assert_ntstatus_ok(torture, status, "opening lsa pipe1"); b1 = p1->binding_handle; status = torture_rpc_connection(torture, &p2, &ndr_table_lsarpc); torture_assert_ntstatus_ok(torture, status, "opening lsa pipe1"); b2 = p2->binding_handle; qos.len = 0; qos.impersonation_level = 2; qos.context_mode = 1; qos.effective_only = 0; attr.len = 0; attr.root_dir = NULL; attr.object_name = NULL; attr.attributes = 0; attr.sec_desc = NULL; attr.sec_qos = &qos; r.in.system_name = &system_name; r.in.attr = &attr; r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; r.out.handle = &handle; torture_assert_ntstatus_ok(torture, dcerpc_lsa_OpenPolicy_r(b1, mem_ctx, &r), "OpenPolicy failed"); if (!NT_STATUS_IS_OK(r.out.result)) { torture_comment(torture, "lsa_OpenPolicy not supported - skipping\n"); talloc_free(mem_ctx); return true; } c.in.handle = &handle; c.out.handle = &handle2; status = dcerpc_lsa_Close_r(b2, mem_ctx, &c); torture_assert_ntstatus_equal(torture, status, NT_STATUS_RPC_SS_CONTEXT_MISMATCH, "closing policy handle on p2"); torture_assert_ntstatus_ok(torture, dcerpc_lsa_Close_r(b1, mem_ctx, &c), "Close failed"); torture_assert_ntstatus_ok(torture, c.out.result, "closing policy handle on p1"); status = dcerpc_lsa_Close_r(b1, mem_ctx, &c); torture_assert_ntstatus_equal(torture, status, NT_STATUS_RPC_SS_CONTEXT_MISMATCH, "closing policy handle on p1 again"); talloc_free(mem_ctx); return true; }
static bool test_handles_lsa_shared(struct torture_context *torture) { NTSTATUS status; struct dcerpc_pipe *p1, *p2, *p3, *p4, *p5; struct dcerpc_binding_handle *b1, *b2, *b3, *b4; struct policy_handle handle; struct policy_handle handle2; struct lsa_ObjectAttribute attr; struct lsa_QosInfo qos; struct lsa_OpenPolicy r; struct lsa_Close c; struct lsa_QuerySecurity qsec; struct sec_desc_buf *sdbuf = NULL; uint16_t system_name = '\\'; TALLOC_CTX *mem_ctx = talloc_new(torture); enum dcerpc_transport_t transport; uint32_t assoc_group_id; torture_comment(torture, "RPC-HANDLE-LSARPC-SHARED\n"); torture_comment(torture, "connect lsa pipe1\n"); status = torture_rpc_connection(torture, &p1, &ndr_table_lsarpc); torture_assert_ntstatus_ok(torture, status, "opening lsa pipe1"); b1 = p1->binding_handle; transport = p1->conn->transport.transport; assoc_group_id = dcerpc_binding_get_assoc_group_id(p1->binding); torture_comment(torture, "use assoc_group_id[0x%08X] for new connections\n", assoc_group_id); torture_comment(torture, "connect lsa pipe2\n"); status = torture_rpc_connection_transport(torture, &p2, &ndr_table_lsarpc, transport, assoc_group_id); torture_assert_ntstatus_ok(torture, status, "opening lsa pipe2"); b2 = p2->binding_handle; torture_comment(torture, "got assoc_group_id[0x%08X] for p2\n", dcerpc_binding_get_assoc_group_id(p2->binding)); qos.len = 0; qos.impersonation_level = 2; qos.context_mode = 1; qos.effective_only = 0; attr.len = 0; attr.root_dir = NULL; attr.object_name = NULL; attr.attributes = 0; attr.sec_desc = NULL; attr.sec_qos = &qos; r.in.system_name = &system_name; r.in.attr = &attr; r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; r.out.handle = &handle; torture_comment(torture, "open lsa policy handle\n"); torture_assert_ntstatus_ok(torture, dcerpc_lsa_OpenPolicy_r(b1, mem_ctx, &r), "OpenPolicy failed"); if (!NT_STATUS_IS_OK(r.out.result)) { torture_comment(torture, "lsa_OpenPolicy not supported - skipping\n"); talloc_free(mem_ctx); return true; } /* * connect p3 after the policy handle is opened */ torture_comment(torture, "connect lsa pipe3 after the policy handle is opened\n"); status = torture_rpc_connection_transport(torture, &p3, &ndr_table_lsarpc, transport, assoc_group_id); torture_assert_ntstatus_ok(torture, status, "opening lsa pipe3"); b3 = p3->binding_handle; qsec.in.handle = &handle; qsec.in.sec_info = 0; qsec.out.sdbuf = &sdbuf; c.in.handle = &handle; c.out.handle = &handle2; /* * use policy handle on all 3 connections */ torture_comment(torture, "use the policy handle on p1,p2,p3\n"); torture_assert_ntstatus_ok(torture, dcerpc_lsa_QuerySecurity_r(b1, mem_ctx, &qsec), "QuerySecurity failed"); torture_assert_ntstatus_equal(torture, qsec.out.result, NT_STATUS_OK, "use policy handle on p1"); torture_assert_ntstatus_ok(torture, dcerpc_lsa_QuerySecurity_r(b2, mem_ctx, &qsec), "QuerySecurity failed"); torture_assert_ntstatus_equal(torture, qsec.out.result, NT_STATUS_OK, "use policy handle on p2"); torture_assert_ntstatus_ok(torture, dcerpc_lsa_QuerySecurity_r(b3, mem_ctx, &qsec), "QuerySecurity failed"); torture_assert_ntstatus_equal(torture, qsec.out.result, NT_STATUS_OK, "use policy handle on p3"); /* * close policy handle on connection 2 and the others get a fault */ torture_comment(torture, "close the policy handle on p2 others get a fault\n"); torture_assert_ntstatus_ok(torture, dcerpc_lsa_Close_r(b2, mem_ctx, &c), "Close failed"); torture_assert_ntstatus_equal(torture, c.out.result, NT_STATUS_OK, "closing policy handle on p2"); status = dcerpc_lsa_Close_r(b1, mem_ctx, &c); torture_assert_ntstatus_equal(torture, status, NT_STATUS_RPC_SS_CONTEXT_MISMATCH, "closing policy handle on p1 again"); status = dcerpc_lsa_Close_r(b3, mem_ctx, &c); torture_assert_ntstatus_equal(torture, status, NT_STATUS_RPC_SS_CONTEXT_MISMATCH, "closing policy handle on p3"); status = dcerpc_lsa_Close_r(b2, mem_ctx, &c); torture_assert_ntstatus_equal(torture, status, NT_STATUS_RPC_SS_CONTEXT_MISMATCH, "closing policy handle on p2 again"); /* * open a new policy handle on p3 */ torture_comment(torture, "open a new policy handle on p3\n"); torture_assert_ntstatus_ok(torture, dcerpc_lsa_OpenPolicy_r(b3, mem_ctx, &r), "OpenPolicy failed"); torture_assert_ntstatus_equal(torture, r.out.result, NT_STATUS_OK, "open policy handle on p3"); /* * use policy handle on all 3 connections */ torture_comment(torture, "use the policy handle on p1,p2,p3\n"); torture_assert_ntstatus_ok(torture, dcerpc_lsa_QuerySecurity_r(b1, mem_ctx, &qsec), "Query Security failed"); torture_assert_ntstatus_equal(torture, status, NT_STATUS_OK, "use policy handle on p1"); torture_assert_ntstatus_ok(torture, dcerpc_lsa_QuerySecurity_r(b2, mem_ctx, &qsec), "Query Security failed"); torture_assert_ntstatus_equal(torture, status, NT_STATUS_OK, "use policy handle on p2"); torture_assert_ntstatus_ok(torture, dcerpc_lsa_QuerySecurity_r(b3, mem_ctx, &qsec), "Query Security failed"); torture_assert_ntstatus_equal(torture, status, NT_STATUS_OK, "use policy handle on p3"); /* * close policy handle on connection 2 and the others get a fault */ torture_comment(torture, "close the policy handle on p2 others get a fault\n"); torture_assert_ntstatus_ok(torture, dcerpc_lsa_Close_r(b2, mem_ctx, &c), "Close failed"); torture_assert_ntstatus_equal(torture, c.out.result, NT_STATUS_OK, "closing policy handle on p2"); status = dcerpc_lsa_Close_r(b1, mem_ctx, &c); torture_assert_ntstatus_equal(torture, status, NT_STATUS_RPC_SS_CONTEXT_MISMATCH, "closing policy handle on p1 again"); status = dcerpc_lsa_Close_r(b3, mem_ctx, &c); torture_assert_ntstatus_equal(torture, status, NT_STATUS_RPC_SS_CONTEXT_MISMATCH, "closing policy handle on p3"); status = dcerpc_lsa_Close_r(b2, mem_ctx, &c); torture_assert_ntstatus_equal(torture, status, NT_STATUS_RPC_SS_CONTEXT_MISMATCH, "closing policy handle on p2 again"); /* * open a new policy handle */ torture_comment(torture, "open a new policy handle on p1 and use it\n"); torture_assert_ntstatus_ok(torture, dcerpc_lsa_OpenPolicy_r(b1, mem_ctx, &r), "OpenPolicy failed"); torture_assert_ntstatus_equal(torture, r.out.result, NT_STATUS_OK, "open 2nd policy handle on p1"); torture_assert_ntstatus_ok(torture, dcerpc_lsa_QuerySecurity_r(b1, mem_ctx, &qsec), "QuerySecurity failed"); torture_assert_ntstatus_equal(torture, qsec.out.result, NT_STATUS_OK, "QuerySecurity handle on p1"); /* close first connection */ torture_comment(torture, "disconnect p1\n"); talloc_free(p1); smb_msleep(5); /* * and it's still available on p2,p3 */ torture_comment(torture, "use policy handle on p2,p3\n"); torture_assert_ntstatus_ok(torture, dcerpc_lsa_QuerySecurity_r(b2, mem_ctx, &qsec), "QuerySecurity failed"); torture_assert_ntstatus_equal(torture, qsec.out.result, NT_STATUS_OK, "QuerySecurity handle on p2 after p1 was disconnected"); torture_assert_ntstatus_ok(torture, dcerpc_lsa_QuerySecurity_r(b3, mem_ctx, &qsec), "QuerySecurity failed"); torture_assert_ntstatus_equal(torture, qsec.out.result, NT_STATUS_OK, "QuerySecurity handle on p3 after p1 was disconnected"); /* * now open p4 * and use the handle on it */ torture_comment(torture, "connect lsa pipe4 and use policy handle\n"); status = torture_rpc_connection_transport(torture, &p4, &ndr_table_lsarpc, transport, assoc_group_id); torture_assert_ntstatus_ok(torture, status, "opening lsa pipe4"); b4 = p4->binding_handle; torture_assert_ntstatus_ok(torture, dcerpc_lsa_QuerySecurity_r(b4, mem_ctx, &qsec), "QuerySecurity failed"); torture_assert_ntstatus_equal(torture, qsec.out.result, NT_STATUS_OK, "using policy handle on p4"); /* * now close p2,p3,p4 * without closing the policy handle */ torture_comment(torture, "disconnect p2,p3,p4\n"); talloc_free(p2); talloc_free(p3); talloc_free(p4); smb_msleep(10); /* * now open p5 */ torture_comment(torture, "connect lsa pipe5 - should fail\n"); status = torture_rpc_connection_transport(torture, &p5, &ndr_table_lsarpc, transport, assoc_group_id); torture_assert_ntstatus_equal(torture, status, NT_STATUS_UNSUCCESSFUL, "opening lsa pipe5"); talloc_free(mem_ctx); return true; }
static bool test_handles_lsa_shared(struct torture_context *torture) { NTSTATUS status; struct dcerpc_pipe *p1, *p2, *p3, *p4, *p5; struct policy_handle handle; struct policy_handle handle2; struct lsa_ObjectAttribute attr; struct lsa_QosInfo qos; struct lsa_OpenPolicy r; struct lsa_Close c; struct lsa_QuerySecurity qsec; uint16_t system_name = '\\'; TALLOC_CTX *mem_ctx = talloc_new(torture); enum dcerpc_transport_t transport; uint32_t assoc_group_id; torture_comment(torture, "RPC-HANDLE-LSARPC-SHARED\n"); if (lp_parm_bool(-1, "torture", "samba4", False)) { torture_comment(torture, "LSA shared-policy-handle test against Samba4 - skipping\n"); return true; } torture_comment(torture, "connect lsa pipe1\n"); status = torture_rpc_connection(mem_ctx, &p1, &dcerpc_table_lsarpc); torture_assert_ntstatus_ok(torture, status, "opening lsa pipe1"); transport = p1->conn->transport.transport, assoc_group_id = p1->assoc_group_id; torture_comment(torture, "use assoc_group_id[0x%08X] for new connections\n", assoc_group_id); torture_comment(torture, "connect lsa pipe2\n"); status = torture_rpc_connection_transport(mem_ctx, &p2, &dcerpc_table_lsarpc, transport, assoc_group_id); torture_assert_ntstatus_ok(torture, status, "opening lsa pipe2"); qos.len = 0; qos.impersonation_level = 2; qos.context_mode = 1; qos.effective_only = 0; attr.len = 0; attr.root_dir = NULL; attr.object_name = NULL; attr.attributes = 0; attr.sec_desc = NULL; attr.sec_qos = &qos; r.in.system_name = &system_name; r.in.attr = &attr; r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; r.out.handle = &handle; torture_comment(torture, "open lsa policy handle\n"); status = dcerpc_lsa_OpenPolicy(p1, mem_ctx, &r); if (!NT_STATUS_IS_OK(status)) { torture_comment(torture, "lsa_OpenPolicy not supported - skipping\n"); talloc_free(mem_ctx); return true; } /* * connect p3 after the policy handle is opened */ torture_comment(torture, "connect lsa pipe3 after the policy handle is opened\n"); status = torture_rpc_connection_transport(mem_ctx, &p3, &dcerpc_table_lsarpc, transport, assoc_group_id); torture_assert_ntstatus_ok(torture, status, "opening lsa pipe3"); qsec.in.handle = &handle; qsec.in.sec_info = 0; c.in.handle = &handle; c.out.handle = &handle2; /* * use policy handle on all 3 connections */ torture_comment(torture, "use the policy handle on p1,p2,p3\n"); status = dcerpc_lsa_QuerySecurity(p1, mem_ctx, &qsec); torture_assert_ntstatus_equal(torture, status, NT_STATUS_OK, "use policy handle on p1"); status = dcerpc_lsa_QuerySecurity(p2, mem_ctx, &qsec); torture_assert_ntstatus_equal(torture, status, NT_STATUS_OK, "use policy handle on p2"); status = dcerpc_lsa_QuerySecurity(p3, mem_ctx, &qsec); torture_assert_ntstatus_equal(torture, status, NT_STATUS_OK, "use policy handle on p3"); /* * close policy handle on connection 2 and the others get a fault */ torture_comment(torture, "close the policy handle on p2 others get a fault\n"); status = dcerpc_lsa_Close(p2, mem_ctx, &c); torture_assert_ntstatus_equal(torture, status, NT_STATUS_OK, "closing policy handle on p2"); status = dcerpc_lsa_Close(p1, mem_ctx, &c); torture_assert_ntstatus_equal(torture, status, NT_STATUS_NET_WRITE_FAULT, "closing policy handle on p1 again"); torture_assert_int_equal(torture, p1->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH, "closing policy handle on p1 again"); status = dcerpc_lsa_Close(p3, mem_ctx, &c); torture_assert_ntstatus_equal(torture, status, NT_STATUS_NET_WRITE_FAULT, "closing policy handle on p3"); torture_assert_int_equal(torture, p1->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH, "closing policy handle on p3"); status = dcerpc_lsa_Close(p2, mem_ctx, &c); torture_assert_ntstatus_equal(torture, status, NT_STATUS_NET_WRITE_FAULT, "closing policy handle on p2 again"); torture_assert_int_equal(torture, p1->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH, "closing policy handle on p2 again"); /* * open a new policy handle on p3 */ torture_comment(torture, "open a new policy handle on p3\n"); status = dcerpc_lsa_OpenPolicy(p3, mem_ctx, &r); torture_assert_ntstatus_equal(torture, status, NT_STATUS_OK, "open policy handle on p3"); /* * use policy handle on all 3 connections */ torture_comment(torture, "use the policy handle on p1,p2,p3\n"); status = dcerpc_lsa_QuerySecurity(p1, mem_ctx, &qsec); torture_assert_ntstatus_equal(torture, status, NT_STATUS_OK, "use policy handle on p1"); status = dcerpc_lsa_QuerySecurity(p2, mem_ctx, &qsec); torture_assert_ntstatus_equal(torture, status, NT_STATUS_OK, "use policy handle on p2"); status = dcerpc_lsa_QuerySecurity(p3, mem_ctx, &qsec); torture_assert_ntstatus_equal(torture, status, NT_STATUS_OK, "use policy handle on p3"); /* * close policy handle on connection 2 and the others get a fault */ torture_comment(torture, "close the policy handle on p2 others get a fault\n"); status = dcerpc_lsa_Close(p2, mem_ctx, &c); torture_assert_ntstatus_equal(torture, status, NT_STATUS_OK, "closing policy handle on p2"); status = dcerpc_lsa_Close(p1, mem_ctx, &c); torture_assert_ntstatus_equal(torture, status, NT_STATUS_NET_WRITE_FAULT, "closing policy handle on p1 again"); torture_assert_int_equal(torture, p1->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH, "closing policy handle on p1 again"); status = dcerpc_lsa_Close(p3, mem_ctx, &c); torture_assert_ntstatus_equal(torture, status, NT_STATUS_NET_WRITE_FAULT, "closing policy handle on p3"); torture_assert_int_equal(torture, p1->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH, "closing policy handle on p3"); status = dcerpc_lsa_Close(p2, mem_ctx, &c); torture_assert_ntstatus_equal(torture, status, NT_STATUS_NET_WRITE_FAULT, "closing policy handle on p2 again"); torture_assert_int_equal(torture, p1->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH, "closing policy handle on p2 again"); /* * open a new policy handle */ torture_comment(torture, "open a new policy handle on p1 and use it\n"); status = dcerpc_lsa_OpenPolicy(p1, mem_ctx, &r); torture_assert_ntstatus_equal(torture, status, NT_STATUS_OK, "open 2nd policy handle on p1"); status = dcerpc_lsa_QuerySecurity(p1, mem_ctx, &qsec); torture_assert_ntstatus_equal(torture, status, NT_STATUS_OK, "QuerySecurity handle on p1"); /* close first connection */ torture_comment(torture, "disconnect p1\n"); talloc_free(p1); msleep(5); /* * and it's still available on p2,p3 */ torture_comment(torture, "use policy handle on p2,p3\n"); status = dcerpc_lsa_QuerySecurity(p2, mem_ctx, &qsec); torture_assert_ntstatus_equal(torture, status, NT_STATUS_OK, "QuerySecurity handle on p2 after p1 was disconnected"); status = dcerpc_lsa_QuerySecurity(p3, mem_ctx, &qsec); torture_assert_ntstatus_equal(torture, status, NT_STATUS_OK, "QuerySecurity handle on p3 after p1 was disconnected"); /* * now open p4 * and use the handle on it */ torture_comment(torture, "connect lsa pipe4 and use policy handle\n"); status = torture_rpc_connection_transport(mem_ctx, &p4, &dcerpc_table_lsarpc, transport, assoc_group_id); torture_assert_ntstatus_ok(torture, status, "opening lsa pipe4"); status = dcerpc_lsa_QuerySecurity(p4, mem_ctx, &qsec); torture_assert_ntstatus_equal(torture, status, NT_STATUS_OK, "using policy handle on p4"); /* * now close p2,p3,p4 * without closing the policy handle */ torture_comment(torture, "disconnect p2,p3,p4\n"); talloc_free(p2); talloc_free(p3); talloc_free(p4); msleep(10); /* * now open p5 */ torture_comment(torture, "connect lsa pipe5 - should fail\n"); status = torture_rpc_connection_transport(mem_ctx, &p5, &dcerpc_table_lsarpc, transport, assoc_group_id); torture_assert_ntstatus_equal(torture, status, NT_STATUS_UNSUCCESSFUL, "opening lsa pipe5"); talloc_free(mem_ctx); return true; }
bool torture_openattrtest(struct torture_context *tctx, struct smbcli_state *cli1) { const char *fname = "\\openattr.file"; int fnum1; uint16_t attr; unsigned int i, j, k, l; int failures = 0; for (k = 0, i = 0; i < sizeof(open_attrs_table)/sizeof(uint32_t); i++) { smbcli_setatr(cli1->tree, fname, 0, 0); smbcli_unlink(cli1->tree, fname); fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_FILE_WRITE_DATA, open_attrs_table[i], NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0); torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx, "open %d (1) of %s failed (%s)", i, fname, smbcli_errstr(cli1->tree))); torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1), talloc_asprintf(tctx, "close %d (1) of %s failed (%s)", i, fname, smbcli_errstr(cli1->tree))); for (j = 0; j < ARRAY_SIZE(open_attrs_table); j++) { fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_FILE_READ_DATA| SEC_FILE_WRITE_DATA, open_attrs_table[j], NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE, 0, 0); if (fnum1 == -1) { for (l = 0; l < ARRAY_SIZE(attr_results); l++) { if (attr_results[l].num == k) { torture_comment(tctx, "[%d] trunc open 0x%x -> 0x%x of %s failed - should have succeeded !(%s)\n", k, open_attrs_table[i], open_attrs_table[j], fname, smbcli_errstr(cli1->tree)); CHECK_MAX_FAILURES(error_exit); } } torture_assert_ntstatus_equal(tctx, smbcli_nt_error(cli1->tree), NT_STATUS_ACCESS_DENIED, talloc_asprintf(tctx, "[%d] trunc open 0x%x -> 0x%x failed with wrong error code %s", k, open_attrs_table[i], open_attrs_table[j], smbcli_errstr(cli1->tree))); CHECK_MAX_FAILURES(error_exit); #if 0 torture_comment(tctx, "[%d] trunc open 0x%x -> 0x%x failed\n", k, open_attrs_table[i], open_attrs_table[j]); #endif k++; continue; } torture_assert_ntstatus_ok(tctx, smbcli_close(cli1->tree, fnum1), talloc_asprintf(tctx, "close %d (2) of %s failed (%s)", j, fname, smbcli_errstr(cli1->tree))); torture_assert_ntstatus_ok(tctx, smbcli_getatr(cli1->tree, fname, &attr, NULL, NULL), talloc_asprintf(tctx, "getatr(2) failed (%s)", smbcli_errstr(cli1->tree))); #if 0 torture_comment(tctx, "[%d] getatr check [0x%x] trunc [0x%x] got attr 0x%x\n", k, open_attrs_table[i], open_attrs_table[j], attr ); #endif for (l = 0; l < ARRAY_SIZE(attr_results); l++) { if (attr_results[l].num == k) { if (attr != attr_results[l].result_attr || open_attrs_table[i] != attr_results[l].init_attr || open_attrs_table[j] != attr_results[l].trunc_attr) { torture_comment(tctx, "[%d] getatr check failed. [0x%x] trunc [0x%x] got attr 0x%x, should be 0x%x\n", k, open_attrs_table[i], open_attrs_table[j], (unsigned int)attr, attr_results[l].result_attr); CHECK_MAX_FAILURES(error_exit); } break; } } k++; } } error_exit: smbcli_setatr(cli1->tree, fname, 0, 0); smbcli_unlink(cli1->tree, fname); return true; }
static bool test_ReadEventLog(struct torture_context *tctx, struct dcerpc_pipe *p) { NTSTATUS status; struct eventlog_ReadEventLogW r; struct eventlog_CloseEventLog cr; struct policy_handle handle; if (!get_policy_handle(tctx, p, &handle)) return false; r.in.offset = 0; r.in.handle = &handle; r.in.flags = EVENTLOG_BACKWARDS_READ|EVENTLOG_SEQUENTIAL_READ; while (1) { DATA_BLOB blob; struct eventlog_Record rec; struct ndr_pull *ndr; /* Read first for number of bytes in record */ r.in.number_of_bytes = 0; r.out.data = NULL; status = dcerpc_eventlog_ReadEventLogW(p, tctx, &r); if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_END_OF_FILE)) { break; } torture_assert_ntstatus_ok(tctx, status, "ReadEventLog failed"); torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_BUFFER_TOO_SMALL, "ReadEventLog failed"); /* Now read the actual record */ r.in.number_of_bytes = *r.out.real_size; r.out.data = talloc_size(tctx, r.in.number_of_bytes); status = dcerpc_eventlog_ReadEventLogW(p, tctx, &r); torture_assert_ntstatus_ok(tctx, status, "ReadEventLog failed"); /* Decode a user-marshalled record */ blob.length = *r.out.sent_size; blob.data = talloc_steal(tctx, r.out.data); ndr = ndr_pull_init_blob(&blob, tctx); status = ndr_pull_eventlog_Record( ndr, NDR_SCALARS|NDR_BUFFERS, &rec); NDR_PRINT_DEBUG(eventlog_Record, &rec); torture_assert_ntstatus_ok(tctx, status, "ReadEventLog failed parsing event log record"); r.in.offset++; } cr.in.handle = cr.out.handle = &handle; torture_assert_ntstatus_ok(tctx, dcerpc_eventlog_CloseEventLog(p, tctx, &cr), "CloseEventLog failed"); return true; }
static bool test_handles_mixed_shared(struct torture_context *torture) { NTSTATUS status; struct dcerpc_pipe *p1, *p2, *p3, *p4, *p5, *p6; struct policy_handle handle; struct policy_handle handle2; struct samr_Connect r; struct lsa_Close lc; struct samr_Close sc; TALLOC_CTX *mem_ctx = talloc_new(torture); enum dcerpc_transport_t transport; uint32_t assoc_group_id; torture_comment(torture, "RPC-HANDLE-MIXED-SHARED\n"); if (lp_parm_bool(-1, "torture", "samba4", False)) { torture_comment(torture, "Mixed shared-policy-handle test against Samba4 - skipping\n"); return true; } torture_comment(torture, "connect samr pipe1\n"); status = torture_rpc_connection(mem_ctx, &p1, &dcerpc_table_samr); torture_assert_ntstatus_ok(torture, status, "opening samr pipe1"); transport = p1->conn->transport.transport, assoc_group_id = p1->assoc_group_id; torture_comment(torture, "use assoc_group_id[0x%08X] for new connections\n", assoc_group_id); torture_comment(torture, "connect lsa pipe2\n"); status = torture_rpc_connection_transport(mem_ctx, &p2, &dcerpc_table_lsarpc, transport, assoc_group_id); torture_assert_ntstatus_ok(torture, status, "opening lsa pipe2"); r.in.system_name = 0; r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; r.out.connect_handle = &handle; torture_comment(torture, "samr_Connect to open a policy handle on samr p1\n"); status = dcerpc_samr_Connect(p1, mem_ctx, &r); torture_assert_ntstatus_ok(torture, status, "opening policy handle on p1"); lc.in.handle = &handle; lc.out.handle = &handle2; sc.in.handle = &handle; sc.out.handle = &handle2; torture_comment(torture, "use policy handle on lsa p2 - should fail\n"); status = dcerpc_lsa_Close(p2, mem_ctx, &lc); torture_assert_ntstatus_equal(torture, status, NT_STATUS_NET_WRITE_FAULT, "closing handle on lsa p2"); torture_assert_int_equal(torture, p2->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH, "closing handle on lsa p2"); torture_comment(torture, "closing policy handle on samr p1\n"); status = dcerpc_samr_Close(p1, mem_ctx, &sc); torture_assert_ntstatus_ok(torture, status, "closing policy handle on p1"); talloc_free(p1); talloc_free(p2); msleep(10); torture_comment(torture, "connect samr pipe3 - should fail\n"); status = torture_rpc_connection_transport(mem_ctx, &p3, &dcerpc_table_samr, transport, assoc_group_id); torture_assert_ntstatus_equal(torture, status, NT_STATUS_UNSUCCESSFUL, "opening samr pipe3"); torture_comment(torture, "connect lsa pipe4 - should fail\n"); status = torture_rpc_connection_transport(mem_ctx, &p4, &dcerpc_table_lsarpc, transport, assoc_group_id); torture_assert_ntstatus_equal(torture, status, NT_STATUS_UNSUCCESSFUL, "opening lsa pipe4"); torture_comment(torture, "connect samr pipe5 with assoc_group_id[0x%08X]- should fail\n", ++assoc_group_id); status = torture_rpc_connection_transport(mem_ctx, &p5, &dcerpc_table_samr, transport, assoc_group_id); torture_assert_ntstatus_equal(torture, status, NT_STATUS_UNSUCCESSFUL, "opening samr pipe5"); torture_comment(torture, "connect lsa pipe6 with assoc_group_id[0x%08X]- should fail\n", ++assoc_group_id); status = torture_rpc_connection_transport(mem_ctx, &p6, &dcerpc_table_lsarpc, transport, assoc_group_id); torture_assert_ntstatus_equal(torture, status, NT_STATUS_UNSUCCESSFUL, "opening lsa pipe6"); talloc_free(mem_ctx); return true; }
bool torture_samba3_checkfsp(struct torture_context *torture, struct smbcli_state *cli) { const char *fname = "test.txt"; const char *dirname = "testdir"; int fnum; NTSTATUS status; bool ret = true; TALLOC_CTX *mem_ctx; ssize_t nread; char buf[16]; struct smbcli_tree *tree2; torture_assert(torture, mem_ctx = talloc_init("torture_samba3_checkfsp"), "talloc_init failed\n"); torture_assert_ntstatus_equal(torture, torture_second_tcon(torture, cli->session, torture_setting_string(torture, "share", NULL), &tree2), NT_STATUS_OK, "creating second tcon"); /* Try a read on an invalid FID */ nread = smbcli_read(cli->tree, 4711, buf, 0, sizeof(buf)); CHECK_STATUS(torture, smbcli_nt_error(cli->tree), NT_STATUS_INVALID_HANDLE); /* Try a read on a directory handle */ torture_assert(torture, torture_setup_dir(cli, dirname), "creating test directory"); /* Open the directory */ { union smb_open io; io.generic.level = RAW_OPEN_NTCREATEX; io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED; io.ntcreatex.in.root_fid.fnum = 0; io.ntcreatex.in.security_flags = 0; io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE; io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL; io.ntcreatex.in.alloc_size = 0; io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY; io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE; io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN; io.ntcreatex.in.create_options = 0; io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS; io.ntcreatex.in.fname = dirname; status = smb_raw_open(cli->tree, mem_ctx, &io); if (!NT_STATUS_IS_OK(status)) { torture_result(torture, TORTURE_FAIL, "smb_open on the directory failed: %s\n", nt_errstr(status)); ret = false; goto done; } fnum = io.ntcreatex.out.file.fnum; } /* Try a read on the directory */ nread = smbcli_read(cli->tree, fnum, buf, 0, sizeof(buf)); if (nread >= 0) { torture_result(torture, TORTURE_FAIL, "smbcli_read on a directory succeeded, expected " "failure\n"); ret = false; } CHECK_STATUS(torture, smbcli_nt_error(cli->tree), NT_STATUS_INVALID_DEVICE_REQUEST); /* Same test on the second tcon */ nread = smbcli_read(tree2, fnum, buf, 0, sizeof(buf)); if (nread >= 0) { torture_result(torture, TORTURE_FAIL, "smbcli_read on a directory succeeded, expected " "failure\n"); ret = false; } CHECK_STATUS(torture, smbcli_nt_error(tree2), NT_STATUS_INVALID_HANDLE); smbcli_close(cli->tree, fnum); /* Try a normal file read on a second tcon */ fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE); if (fnum == -1) { torture_result(torture, TORTURE_FAIL, "Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree)); ret = false; goto done; } nread = smbcli_read(tree2, fnum, buf, 0, sizeof(buf)); CHECK_STATUS(torture, smbcli_nt_error(tree2), NT_STATUS_INVALID_HANDLE); smbcli_close(cli->tree, fnum); done: smbcli_deltree(cli->tree, dirname); talloc_free(mem_ctx); return ret; }
static BOOL smb_raw_query_posix_whoami(void *mem_ctx, struct torture_context *torture, struct smbcli_state *cli, struct smb_whoami *whoami, unsigned max_data) { struct smb_trans2 tp; NTSTATUS status; size_t offset; int i; uint16_t setup = TRANSACT2_QFSINFO; uint16_t info_level; ZERO_STRUCTP(whoami); tp.in.max_setup = 0; tp.in.flags = 0; tp.in.timeout = 0; tp.in.setup_count = 1; tp.in.max_param = 10; tp.in.max_data = (uint16_t)max_data; tp.in.setup = &setup; tp.in.trans_name = NULL; SSVAL(&info_level, 0, SMB_QFS_POSIX_WHOAMI); tp.in.params = data_blob_talloc(mem_ctx, &info_level, 2); tp.in.data = data_blob_talloc(mem_ctx, NULL, 0); status = smb_raw_trans2(cli->tree, mem_ctx, &tp); torture_assert_ntstatus_equal(torture, status, NT_STATUS_OK, "doing SMB_QFS_POSIX_WHOAMI"); /* Make sure we got back all the required fields. */ torture_assert(torture, tp.out.params.length == 0, "trans2 params should be empty"); torture_assert(torture, tp.out.data.length >= WHOAMI_REQUIRED_SIZE, "checking for required response fields"); whoami->mapping_flags = IVAL(tp.out.data.data, 0); whoami->mapping_mask = IVAL(tp.out.data.data, 4); whoami->server_uid = BVAL(tp.out.data.data, 8); whoami->server_gid = BVAL(tp.out.data.data, 16); whoami->num_gids = IVAL(tp.out.data.data, 24); whoami->num_sids = IVAL(tp.out.data.data, 28); whoami->num_sid_bytes = IVAL(tp.out.data.data, 32); whoami->reserved = IVAL(tp.out.data.data, 36); /* The GID list and SID list are optional, depending on the count * and length fields. */ if (whoami->num_sids != 0) { torture_assert(torture, whoami->num_sid_bytes != 0, "SID count does not match byte count"); } printf("\tmapping_flags=0x%08x mapping_mask=0x%08x\n", whoami->mapping_flags, whoami->mapping_mask); printf("\tserver UID=%lld GID=%lld\n", whoami->server_uid, whoami->server_gid); printf("\t%u GIDs, %u SIDs, %u SID bytes\n", whoami->num_gids, whoami->num_sids, whoami->num_sid_bytes); offset = WHOAMI_REQUIRED_SIZE; torture_assert_int_equal(torture, whoami->reserved, 0, "invalid reserved field"); if (tp.out.data.length == offset) { /* No SIDs or GIDs returned */ torture_assert_int_equal(torture, whoami->num_gids, 0, "invalid GID count"); torture_assert_int_equal(torture, whoami->num_sids, 0, "invalid SID count"); torture_assert_int_equal(torture, whoami->num_sid_bytes, 0, "invalid SID byte count"); return True; } if (whoami->num_gids != 0) { int remain = tp.out.data.length - offset; int gid_bytes = whoami->num_gids * 8; if (whoami->num_sids == 0) { torture_assert_int_equal(torture, remain, gid_bytes, "GID count does not match data length"); } else { torture_assert(torture, remain > gid_bytes, "invalid GID count"); } whoami->gid_list = talloc_array(mem_ctx, uint64_t, whoami->num_gids); torture_assert(torture, whoami->gid_list != NULL, "out of memory"); for (i = 0; i < whoami->num_gids; ++i) { whoami->gid_list[i] = BVAL(tp.out.data.data, offset); offset += 8; } } /* Check if there should be data left for the SID list. */ if (tp.out.data.length == offset) { torture_assert_int_equal(torture, whoami->num_sids, 0, "invalid SID count"); return True; } /* All the remaining bytes must be the SID list. */ torture_assert_int_equal(torture, whoami->num_sid_bytes, (tp.out.data.length - offset), "invalid SID byte count"); if (whoami->num_sids != 0) { whoami->sid_list = talloc_array(mem_ctx, struct dom_sid *, whoami->num_sids); torture_assert(torture, whoami->sid_list != NULL, "out of memory"); for (i = 0; i < whoami->num_sids; ++i) { if (!sid_parse(mem_ctx, torture, &tp.out.data, &offset, &whoami->sid_list[i])) { return False; } } }
static bool verify_setinfo_flags(void *mem_ctx, struct torture_context *torture, struct smbcli_state *cli, const char *fname) { struct unix_info2 info2; uint32_t smb_fmask; int i; bool ret = true; NTSTATUS status; if (!query_path_info2(mem_ctx, torture, cli, fname, &info2)) { return false; } smb_fmask = info2.flags_mask; /* For each possible flag, ask to set exactly 1 flag, making sure * that flag is in our requested mask. */ for (i = 0; i < 32; ++i) { info2.file_flags = (1 << i); info2.flags_mask = smb_fmask | info2.file_flags; set_no_metadata_change(&info2); status = set_path_info2(mem_ctx, cli, fname, &info2); if (info2.file_flags & smb_fmask) { torture_assert_ntstatus_equal(torture, status, NT_STATUS_OK, "setting valid UNIX_INFO2 flag"); if (!query_path_info2(mem_ctx, torture, cli, fname, &info2)) { return false; } ASSERT_FLAGS_MATCH(&info2, 1 << i); } else { /* We tried to set a flag the server doesn't * understand. */ torture_assert_ntstatus_equal(torture, status, NT_STATUS_INVALID_PARAMETER, "setting invalid UNIX_INFO2 flag"); } } /* Make sure that a zero flags field does nothing. */ set_no_metadata_change(&info2); info2.file_flags = 0xFFFFFFFF; info2.flags_mask = 0; status = set_path_info2(mem_ctx, cli, fname, &info2); torture_assert_ntstatus_equal(torture, status, NT_STATUS_OK, "setting empty flags mask"); return ret; }