/* Unix SMB/CIFS implementation. test suite for the mdssvc RPC service Copyright (C) Ralph Boehme 2019 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "includes.h" #include "torture/rpc/torture_rpc.h" #include "librpc/gen_ndr/ndr_mdssvc_c.h" #include "param/param.h" #include "lib/cmdline/cmdline.h" #include "rpc_server/mdssvc/dalloc.h" #include "rpc_server/mdssvc/marshalling.h" struct torture_mdsscv_state { struct dcerpc_pipe *p; struct policy_handle ph; /* Known fields used across multiple commands */ uint32_t dev; uint32_t flags; /* cmd specific or unknown fields */ struct { const char share_path[1025]; uint32_t unkn2; uint32_t unkn3; } mdscmd_open; struct { uint32_t status; uint32_t unkn7; } mdscmd_unknown1; struct { uint32_t fragment; uint32_t unkn9; } mdscmd_cmd; struct { uint32_t status; } mdscmd_close; }; static bool torture_rpc_mdssvc_setup(struct torture_context *tctx, void **data) { struct torture_mdsscv_state *state = NULL; NTSTATUS status; state = talloc_zero(tctx, struct torture_mdsscv_state); if (state == NULL) { return false; } *data = state; status = torture_rpc_connection(tctx, &state->p, &ndr_table_mdssvc); torture_assert_ntstatus_ok(tctx, status, "Error connecting to server"); return true; } static bool torture_rpc_mdssvc_teardown(struct torture_context *tctx, void *data) { struct torture_mdsscv_state *state = talloc_get_type_abort( data, struct torture_mdsscv_state); TALLOC_FREE(state->p); TALLOC_FREE(state); return true; } static bool torture_rpc_mdssvc_open(struct torture_context *tctx, void **data) { struct torture_mdsscv_state *state = NULL; struct dcerpc_binding_handle *b = NULL; const char *share_name = NULL; const char *share_mount_path = NULL; NTSTATUS status; bool ok = true; state = talloc_zero(tctx, struct torture_mdsscv_state); if (state == NULL) { return false; } *data = state; status = torture_rpc_connection(tctx, &state->p, &ndr_table_mdssvc); torture_assert_ntstatus_ok(tctx, status, "Error connecting to server"); b = state->p->binding_handle; share_name = torture_setting_string( tctx, "spotlight_share", "spotlight"); share_mount_path = torture_setting_string( tctx, "share_mount_path", "/foo/bar"); state->dev = generate_random(); state->mdscmd_open.unkn2 = 23; state->mdscmd_open.unkn3 = 0; ZERO_STRUCT(state->ph); status = dcerpc_mdssvc_open(b, state, &state->dev, &state->mdscmd_open.unkn2, &state->mdscmd_open.unkn3, share_mount_path, share_name, state->mdscmd_open.share_path, &state->ph); torture_assert_ntstatus_ok_goto(tctx, status, ok, done, "dcerpc_mdssvc_open failed\n"); status = dcerpc_mdssvc_unknown1(b, state, &state->ph, 0, state->dev, state->mdscmd_open.unkn2, 0, geteuid(), getegid(), &state->mdscmd_unknown1.status, &state->flags, &state->mdscmd_unknown1.unkn7); torture_assert_ntstatus_ok_goto(tctx, status, ok, done, "dcerpc_mdssvc_unknown1 failed\n"); done: if (!ok) { (void)dcerpc_mdssvc_close(b, state, &state->ph, 0, state->dev, state->mdscmd_open.unkn2, 0, &state->ph, &state->mdscmd_close.status); ZERO_STRUCTP(state); } return ok; } static bool torture_rpc_mdssvc_close(struct torture_context *tctx, void *data) { struct torture_mdsscv_state *state = talloc_get_type_abort( data, struct torture_mdsscv_state); NTSTATUS status; bool ok = true; torture_comment(tctx, "test_teardown_mdssvc_disconnect\n"); if (state->p == NULL) { /* We have already been disconnected. */ goto done; } status = dcerpc_mdssvc_close(state->p->binding_handle, state, &state->ph, 0, state->dev, state->mdscmd_open.unkn2, 0, &state->ph, &state->mdscmd_close.status); torture_assert_ntstatus_ok_goto(tctx, status, ok, done, "dcerpc_mdssvc_close failed\n"); ZERO_STRUCTP(state); done: return ok; } /* * Test unknown share name */ static bool test_mdssvc_open_unknown_share(struct torture_context *tctx, void *data) { struct torture_mdsscv_state *state = talloc_get_type_abort( data, struct torture_mdsscv_state); struct dcerpc_binding_handle *b = state->p->binding_handle; struct policy_handle ph; struct policy_handle nullh; uint32_t device_id; uint32_t unkn2; uint32_t unkn3; uint32_t device_id_out; uint32_t unkn2_out; uint32_t unkn3_out; const char *share_mount_path = NULL; const char *share_name = NULL; const char share_path[1025] = "X"; NTSTATUS status; bool ok = true; share_name = torture_setting_string( tctx, "unknown_share", "choukawoohoo"); share_mount_path = torture_setting_string( tctx, "share_mount_path", "/foo/bar"); device_id_out = device_id = generate_random(); unkn2_out = unkn2 = generate_random(); unkn3_out = unkn3 = generate_random(); ZERO_STRUCT(ph); ZERO_STRUCT(nullh); status = dcerpc_mdssvc_open(b, tctx, &device_id_out, &unkn2_out, &unkn3_out, share_mount_path, share_name, share_path, &ph); torture_assert_ntstatus_ok_goto(tctx, status, ok, done, "dcerpc_mdssvc_open failed\n"); torture_assert_u32_equal_goto(tctx, device_id_out, device_id, ok, done, "Bad device_id\n"); torture_assert_u32_equal_goto(tctx, unkn2_out, unkn2, ok, done, "Bad unkn2\n"); torture_assert_u32_equal_goto(tctx, unkn3_out, unkn3, ok, done, "Bad unkn3\n"); torture_assert_goto(tctx, share_path[0] == '\0', ok, done, "Expected empty string as share path\n"); torture_assert_mem_equal_goto(tctx, &ph, &nullh, sizeof(ph), ok, done, "Expected all-zero policy handle\n"); done: return ok; } /* * Test on a share where Spotlight is not enabled */ static bool test_mdssvc_open_spotlight_disabled(struct torture_context *tctx, void *data) { struct torture_mdsscv_state *state = talloc_get_type_abort( data, struct torture_mdsscv_state); struct dcerpc_binding_handle *b = state->p->binding_handle; struct policy_handle ph; struct policy_handle nullh; uint32_t device_id; uint32_t unkn2; uint32_t unkn3; uint32_t device_id_out; uint32_t unkn2_out; uint32_t unkn3_out; const char *share_mount_path = NULL; const char *share_name = NULL; const char share_path[1025] = ""; NTSTATUS status; bool ok = true; share_name = torture_setting_string( tctx, "no_spotlight_share", "no_spotlight"); share_mount_path = torture_setting_string( tctx, "share_mount_path", "/foo/bar"); device_id_out = device_id = generate_random(); unkn2_out = unkn2 = 23; unkn3_out = unkn3 = 0; ZERO_STRUCT(ph); ZERO_STRUCT(nullh); status = dcerpc_mdssvc_open(b, tctx, &device_id_out, &unkn2_out, &unkn3_out, share_mount_path, share_name, share_path, &ph); torture_assert_ntstatus_ok_goto(tctx, status, ok, done, "dcerpc_mdssvc_open failed\n"); torture_assert_u32_equal_goto(tctx, device_id, device_id_out, ok, done, "Bad device_id\n"); torture_assert_u32_equal_goto(tctx, unkn2, unkn2_out, ok, done, "Bad unkn2\n"); torture_assert_u32_equal_goto(tctx, unkn3, unkn3_out, ok, done, "Bad unkn3\n"); torture_assert_goto(tctx, share_path[0] == '\0', ok, done, "Expected empty string as share path\n"); torture_assert_mem_equal_goto(tctx, &ph, &nullh, sizeof(ph), ok, done, "Expected all-zero policy handle\n"); done: return ok; } static bool test_mdssvc_close(struct torture_context *tctx, void *data) { struct torture_mdsscv_state *state = talloc_get_type_abort( data, struct torture_mdsscv_state); struct dcerpc_binding_handle *b = state->p->binding_handle; struct policy_handle ph; struct policy_handle close_ph; uint32_t device_id; uint32_t unkn2; uint32_t unkn3; const char *share_mount_path = NULL; const char *share_name = NULL; const char share_path[1025] = ""; uint32_t close_status; DATA_BLOB ph_blob; DATA_BLOB close_ph_blob; NTSTATUS status; bool ok = true; share_name = torture_setting_string( tctx, "spotlight_share", "spotlight"); share_mount_path = torture_setting_string( tctx, "share_mount_path", "/foo/bar"); device_id = generate_random(); unkn2 = 23; unkn3 = 0; ZERO_STRUCT(ph); ZERO_STRUCT(close_ph); status = dcerpc_mdssvc_open(b, tctx, &device_id, &unkn2, &unkn3, share_mount_path, share_name, share_path, &ph); torture_assert_ntstatus_ok_goto(tctx, status, ok, done, "dcerpc_mdssvc_open failed\n"); status = dcerpc_mdssvc_close(b, tctx, &ph, 0, device_id, unkn2, 0, &close_ph, &close_status); torture_assert_ntstatus_ok_goto(tctx, status, ok, done, "dcerpc_mdssvc_open failed\n"); ph_blob = (DATA_BLOB) { .data = (uint8_t *)&ph, .length = sizeof(struct policy_handle) }; close_ph_blob = (DATA_BLOB) { .data = (uint8_t *)&close_ph, .length = sizeof(struct policy_handle), }; torture_assert_data_blob_equal(tctx, close_ph_blob, ph_blob, "bad blob"); torture_comment(tctx, "Test close with a all-zero handle\n"); ZERO_STRUCT(ph); status = dcerpc_mdssvc_close(b, tctx, &ph, 0, device_id, unkn2, 0, &close_ph, &close_status); torture_assert_ntstatus_ok_goto(tctx, status, ok, done, "dcerpc_mdssvc_close failed\n"); torture_assert_data_blob_equal(tctx, close_ph_blob, ph_blob, "bad blob"); done: return ok; } static bool test_mdssvc_null_ph(struct torture_context *tctx, void *data) { struct torture_mdsscv_state *state = talloc_get_type_abort( data, struct torture_mdsscv_state); struct dcerpc_binding_handle *b = state->p->binding_handle; struct policy_handle nullh; struct policy_handle ph; uint32_t device_id; uint32_t unkn2; uint32_t unkn7; uint32_t cmd_status; uint32_t flags; NTSTATUS status; bool ok = true; device_id = generate_random(); unkn2 = 23; unkn7 = 0; cmd_status = 0; ZERO_STRUCT(nullh); ZERO_STRUCT(ph); status = dcerpc_mdssvc_unknown1(b, tctx, &ph, 0, device_id, unkn2, 0, geteuid(), getegid(), &cmd_status, &flags, &unkn7); torture_assert_ntstatus_ok_goto(tctx, status, ok, done, "dcerpc_mdssvc_unknown1 failed\n"); torture_assert_mem_equal_goto(tctx, &ph, &nullh, sizeof(ph), ok, done, "Expected all-zero policy handle\n"); done: return ok; } static bool test_mdssvc_invalid_ph_unknown1(struct torture_context *tctx, void *data) { struct torture_mdsscv_state *state = talloc_get_type_abort( data, struct torture_mdsscv_state); struct dcerpc_binding_handle *b = state->p->binding_handle; struct policy_handle ph; uint32_t device_id; uint32_t unkn2; uint32_t unkn7; uint32_t cmd_status; uint32_t flags; NTSTATUS status; bool ok = true; device_id = generate_random(); unkn2 = 23; unkn7 = 0; cmd_status = 0; ZERO_STRUCT(ph); ph.uuid = GUID_random(); status = dcerpc_mdssvc_unknown1(b, tctx, &ph, 0, device_id, unkn2, 0, geteuid(), getegid(), &cmd_status, &flags, &unkn7); torture_assert_ntstatus_equal_goto( tctx, status, NT_STATUS_RPC_PROTOCOL_ERROR, ok, done, "dcerpc_mdssvc_unknown1 failed\n"); /* Free and set to NULL the no-longer-usable pipe. */ b = NULL; TALLOC_FREE(state->p); done: return ok; } static bool test_mdssvc_invalid_ph_cmd(struct torture_context *tctx, void *data) { struct torture_mdsscv_state *state = talloc_get_type_abort( data, struct torture_mdsscv_state); struct dcerpc_binding_handle *b = state->p->binding_handle; struct policy_handle ph; struct mdssvc_blob request_blob; struct mdssvc_blob response_blob; uint32_t device_id; uint32_t unkn2; uint32_t unkn9; uint32_t fragment; uint32_t flags; NTSTATUS status; bool ok = true; device_id = generate_random(); unkn2 = 23; unkn9 = 0; fragment = 0; flags = UINT32_C(0x6b000001); ZERO_STRUCT(ph); ph.uuid = GUID_random(); request_blob.spotlight_blob = talloc_array(state, uint8_t, 0); torture_assert_not_null_goto(tctx, request_blob.spotlight_blob, ok, done, "dalloc_zero failed\n"); request_blob.size = 0; request_blob.length = 0; request_blob.size = 0; status = dcerpc_mdssvc_cmd(b, state, &ph, 0, device_id, unkn2, 0, flags, request_blob, 0, 64 * 1024, 1, 64 * 1024, 0, 0, &fragment, &response_blob, &unkn9); torture_assert_ntstatus_equal_goto( tctx, status, NT_STATUS_RPC_PROTOCOL_ERROR, ok, done, "dcerpc_mdssvc_unknown1 failed\n"); /* Free and set to NULL the no-longer-usable pipe. */ b = NULL; TALLOC_FREE(state->p); done: return ok; } static uint8_t test_sl_unpack_loop_buf[] = { 0x34, 0x33, 0x32, 0x31, 0x33, 0x30, 0x64, 0x6d, 0x1d, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x04, 0x00, 0x00, 0x00, 0x66, 0x65, 0x74, 0x63, 0x68, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x3a, 0x66, 0x6f, 0x72, 0x4f, 0x49, 0x44, 0x41, 0x72, 0x72, 0x61, 0x79, 0x3a, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x3a, 0x00, 0x00, 0x00, 0xea, 0x02, 0x00, 0x00, 0x84, 0x02, 0x00, 0x00, 0x00, 0x0a, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x07, 0x03, 0x00, 0x00, 0x00, 0x6b, 0x4d, 0x44, 0x49, 0x74, 0x65, 0x6d, 0x50, 0x61, 0x74, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x87, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0xdd, 0x0a, 0x20, 0x00, 0x00, 0x6b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x0a, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x0a, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x0c, 0x04, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x0c, 0x03, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static bool test_mdssvc_sl_unpack_loop(struct torture_context *tctx, void *data) { struct torture_mdsscv_state *state = talloc_get_type_abort( data, struct torture_mdsscv_state); struct dcerpc_binding_handle *b = state->p->binding_handle; struct mdssvc_blob request_blob; struct mdssvc_blob response_blob; uint32_t device_id; uint32_t unkn2; uint32_t unkn9; uint32_t fragment; uint32_t flags; NTSTATUS status; bool ok = true; device_id = UINT32_C(0x2f000045); unkn2 = 23; unkn9 = 0; fragment = 0; flags = UINT32_C(0x6b000001); request_blob.spotlight_blob = test_sl_unpack_loop_buf; request_blob.size = sizeof(test_sl_unpack_loop_buf); request_blob.length = sizeof(test_sl_unpack_loop_buf); status = dcerpc_mdssvc_cmd(b, state, &state->ph, 0, device_id, unkn2, 0, flags, request_blob, 0, 64 * 1024, 1, 64 * 1024, 0, 0, &fragment, &response_blob, &unkn9); torture_assert_ntstatus_ok_goto( tctx, status, ok, done, "dcerpc_mdssvc_unknown1 failed\n"); done: return ok; } static bool test_sl_dict_type_safety(struct torture_context *tctx, void *data) { struct torture_mdsscv_state *state = talloc_get_type_abort( data, struct torture_mdsscv_state); struct dcerpc_binding_handle *b = state->p->binding_handle; struct mdssvc_blob request_blob; struct mdssvc_blob response_blob; uint64_t ctx1 = 0xdeadbeef; uint64_t ctx2 = 0xcafebabe; uint32_t device_id; uint32_t unkn2; uint32_t unkn9; uint32_t fragment; uint32_t flags; DALLOC_CTX *d = NULL; sl_array_t *array1 = NULL, *array2 = NULL; sl_dict_t *arg = NULL; int result; NTSTATUS status; bool ok = true; device_id = UINT32_C(0x2f000045); unkn2 = 23; unkn9 = 0; fragment = 0; flags = UINT32_C(0x6b000001); d = dalloc_new(tctx); torture_assert_not_null_goto(tctx, d, ok, done, "dalloc_new failed\n"); array1 = dalloc_zero(d, sl_array_t); torture_assert_not_null_goto(tctx, array1, ok, done, "dalloc_zero failed\n"); array2 = dalloc_zero(d, sl_array_t); torture_assert_not_null_goto(tctx, array2, ok, done, "dalloc_new failed\n"); result = dalloc_stradd(array2, "openQueryWithParams:forContext:"); torture_assert_goto(tctx, result == 0, ok, done, "dalloc_stradd failed\n"); result = dalloc_add_copy(array2, &ctx1, uint64_t); torture_assert_goto(tctx, result == 0, ok, done, "dalloc_stradd failed\n"); result = dalloc_add_copy(array2, &ctx2, uint64_t); torture_assert_goto(tctx, result == 0, ok, done, "dalloc_stradd failed\n"); arg = dalloc_zero(array1, sl_dict_t); torture_assert_not_null_goto(tctx, d, ok, done, "dalloc_zero failed\n"); result = dalloc_stradd(arg, "kMDQueryString"); torture_assert_goto(tctx, result == 0, ok, done, "dalloc_stradd failed\n"); result = dalloc_stradd(arg, "*"); torture_assert_goto(tctx, result == 0, ok, done, "dalloc_stradd failed\n"); result = dalloc_stradd(arg, "kMDScopeArray"); torture_assert_goto(tctx, result == 0, ok, done, "dalloc_stradd failed\n"); result = dalloc_stradd(arg, "AAAABBBB"); torture_assert_goto(tctx, result == 0, ok, done, "dalloc_stradd failed\n"); result = dalloc_add(array1, array2, sl_array_t); torture_assert_goto(tctx, result == 0, ok, done, "dalloc_add failed\n"); result = dalloc_add(array1, arg, sl_dict_t); torture_assert_goto(tctx, result == 0, ok, done, "dalloc_add failed\n"); result = dalloc_add(d, array1, sl_array_t); torture_assert_goto(tctx, result == 0, ok, done, "dalloc_add failed\n"); torture_comment(tctx, "%s", dalloc_dump(d, 0)); request_blob.spotlight_blob = talloc_array(tctx, uint8_t, 64 * 1024); torture_assert_not_null_goto(tctx, request_blob.spotlight_blob, ok, done, "dalloc_new failed\n"); request_blob.size = 64 * 1024; status = sl_pack_alloc(tctx, d, &request_blob, 64 * 1024); torture_assert_ntstatus_ok_goto(tctx, status, ok, done, "sl_pack_alloc() failed\n"); status = dcerpc_mdssvc_cmd(b, state, &state->ph, 0, device_id, unkn2, 0, flags, request_blob, 0, 64 * 1024, 1, 64 * 1024, 0, 0, &fragment, &response_blob, &unkn9); torture_assert_ntstatus_ok_goto( tctx, status, ok, done, "dcerpc_mdssvc_cmd failed\n"); done: return ok; } static bool test_mdssvc_invalid_ph_close(struct torture_context *tctx, void *data) { struct torture_mdsscv_state *state = talloc_get_type_abort( data, struct torture_mdsscv_state); struct dcerpc_binding_handle *b = state->p->binding_handle; struct policy_handle ph; uint32_t device_id; uint32_t unkn2; uint32_t close_status; NTSTATUS status; bool ok = true; device_id = generate_random(); unkn2 = 23; close_status = 0; ZERO_STRUCT(ph); ph.uuid = GUID_random(); status = dcerpc_mdssvc_close(b, state, &ph, 0, device_id, unkn2, 0, &ph, &close_status); torture_assert_ntstatus_equal_goto( tctx, status, NT_STATUS_RPC_PROTOCOL_ERROR, ok, done, "dcerpc_mdssvc_unknown1 failed\n"); /* Free and set to NULL the no-longer-usable pipe. */ b = NULL; TALLOC_FREE(state->p); done: return ok; } /* * Test fetchAttributes with unknown CNID */ static bool test_mdssvc_fetch_attr_unknown_cnid(struct torture_context *tctx, void *data) { struct torture_mdsscv_state *state = talloc_get_type_abort( data, struct torture_mdsscv_state); struct dcerpc_binding_handle *b = state->p->binding_handle; uint32_t max_fragment_size = 64 * 1024; struct mdssvc_blob request_blob; struct mdssvc_blob response_blob; DALLOC_CTX *d = NULL, *mds_reply = NULL; uint64_t *uint64var = NULL; sl_array_t *array = NULL; sl_array_t *cmd_array = NULL; sl_array_t *attr_array = NULL; sl_cnids_t *cnids = NULL; void *path = NULL; const char *path_type = NULL; uint64_t ino64; NTSTATUS status; int ret; bool ok = true; d = dalloc_new(state); torture_assert_not_null_goto(tctx, d, ret, done, "dalloc_new failed\n"); array = dalloc_zero(d, sl_array_t); torture_assert_not_null_goto(tctx, array, ret, done, "dalloc_zero failed\n"); ret = dalloc_add(d, array, sl_array_t); torture_assert_goto(tctx, ret == 0, ret, done, "dalloc_add failed\n"); cmd_array = dalloc_zero(d, sl_array_t); torture_assert_not_null_goto(tctx, cmd_array, ret, done, "dalloc_zero failed\n"); ret = dalloc_add(array, cmd_array, sl_array_t); torture_assert_goto(tctx, ret == 0, ret, done, "dalloc_add failed\n"); ret = dalloc_stradd(cmd_array, "fetchAttributes:forOIDArray:context:"); torture_assert_goto(tctx, ret == 0, ret, done, "dalloc_stradd failed\n"); uint64var = talloc_zero_array(cmd_array, uint64_t, 2); torture_assert_not_null_goto(tctx, uint64var, ret, done, "talloc_zero_array failed\n"); talloc_set_name(uint64var, "uint64_t *"); uint64var[0] = 0x500a; uint64var[1] = 0; ret = dalloc_add(cmd_array, &uint64var[0], uint64_t *); torture_assert_goto(tctx, ret == 0, ret, done, "dalloc_add failed\n"); attr_array = dalloc_zero(d, sl_array_t); torture_assert_not_null_goto(tctx, attr_array, ret, done, "dalloc_zero failed\n"); ret = dalloc_add(array, attr_array, sl_array_t); torture_assert_goto(tctx, ret == 0, ret, done, "dalloc_add failed\n"); ret = dalloc_stradd(attr_array, "kMDItemPath"); torture_assert_goto(tctx, ret == 0, ret, done, "dalloc_stradd failed\n"); /* CNIDs */ cnids = talloc_zero(array, sl_cnids_t); torture_assert_not_null_goto(tctx, cnids, ret, done, "talloc_zero failed\n"); cnids->ca_cnids = dalloc_new(cnids); torture_assert_not_null_goto(tctx, cnids->ca_cnids, ret, done, "dalloc_new failed\n"); cnids->ca_unkn1 = 0xadd; cnids->ca_context = 0x6b000020; ino64 = UINT64_C(64382947389618974); ret = dalloc_add_copy(cnids->ca_cnids, &ino64, uint64_t); torture_assert_goto(tctx, ret == 0, ret, done, "dalloc_add_copy failed\n"); ret = dalloc_add(array, cnids, sl_cnids_t); torture_assert_goto(tctx, ret == 0, ret, done, "dalloc_add failed\n"); status = sl_pack_alloc(tctx, d, &request_blob, max_fragment_size); torture_assert_ntstatus_ok_goto(tctx, status, ok, done, "sl_pack_alloc() failed\n"); status = dcerpc_mdssvc_cmd(b, state, &state->ph, 0, state->dev, state->mdscmd_open.unkn2, 0, state->flags, request_blob, 0, max_fragment_size, 1, max_fragment_size, 0, 0, &state->mdscmd_cmd.fragment, &response_blob, &state->mdscmd_cmd.unkn9); torture_assert_ntstatus_ok_goto(tctx, status, ret, done, "dcerpc_mdssvc_cmd failed\n"); mds_reply = dalloc_new(state); torture_assert_not_null_goto(tctx, mds_reply, ret, done, "dalloc_zero failed\n"); ok = sl_unpack(mds_reply, (char *)response_blob.spotlight_blob, response_blob.length); torture_assert_goto(tctx, ok, ret, done, "dalloc_add failed\n"); torture_comment(tctx, "%s", dalloc_dump(mds_reply, 0)); path = dalloc_get(mds_reply, "DALLOC_CTX", 0, "DALLOC_CTX", 2, "DALLOC_CTX", 0, "sl_nil_t", 1); torture_assert_not_null_goto(tctx, path, ret, done, "dalloc_get path failed\n"); path_type = talloc_get_name(path); torture_assert_str_equal_goto(tctx, path_type, "sl_nil_t", ret, done, "Wrong dalloc object type\n"); done: return ok; } struct torture_suite *torture_rpc_mdssvc(TALLOC_CTX *mem_ctx) { struct torture_suite *suite = torture_suite_create( mem_ctx, "mdssvc"); struct torture_tcase *tcase = NULL; tcase = torture_suite_add_tcase(suite, "rpccmd"); if (tcase == NULL) { return NULL; } torture_tcase_set_fixture(tcase, torture_rpc_mdssvc_setup, torture_rpc_mdssvc_teardown); torture_tcase_add_simple_test(tcase, "open_unknown_share", test_mdssvc_open_unknown_share); torture_tcase_add_simple_test(tcase, "open_spotlight_disabled", test_mdssvc_open_spotlight_disabled); torture_tcase_add_simple_test(tcase, "close", test_mdssvc_close); torture_tcase_add_simple_test(tcase, "null_ph", test_mdssvc_null_ph); tcase = torture_suite_add_tcase(suite, "disconnect1"); if (tcase == NULL) { return NULL; } torture_tcase_set_fixture(tcase, torture_rpc_mdssvc_open, torture_rpc_mdssvc_close); torture_tcase_add_simple_test(tcase, "invalid_ph_unknown1", test_mdssvc_invalid_ph_unknown1); tcase = torture_suite_add_tcase(suite, "disconnect2"); if (tcase == NULL) { return NULL; } torture_tcase_set_fixture(tcase, torture_rpc_mdssvc_open, torture_rpc_mdssvc_close); torture_tcase_add_simple_test(tcase, "invalid_ph_cmd", test_mdssvc_invalid_ph_cmd); tcase = torture_suite_add_tcase(suite, "disconnect3"); if (tcase == NULL) { return NULL; } torture_tcase_set_fixture(tcase, torture_rpc_mdssvc_open, torture_rpc_mdssvc_close); torture_tcase_add_simple_test(tcase, "invalid_ph_close", test_mdssvc_invalid_ph_close); tcase = torture_suite_add_tcase(suite, "mdscmd"); if (tcase == NULL) { return NULL; } torture_tcase_set_fixture(tcase, torture_rpc_mdssvc_open, torture_rpc_mdssvc_close); torture_tcase_add_simple_test(tcase, "fetch_unknown_cnid", test_mdssvc_fetch_attr_unknown_cnid); torture_tcase_add_simple_test(tcase, "mdssvc_sl_unpack_loop", test_mdssvc_sl_unpack_loop); torture_tcase_add_simple_test(tcase, "sl_dict_type_safety", test_sl_dict_type_safety); return suite; }