2 Unix SMB/CIFS implementation.
3 test suite for the mdssvc RPC serice
5 Copyright (C) Ralph Boehme 2019
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "torture/rpc/torture_rpc.h"
24 #include "librpc/gen_ndr/ndr_mdssvc_c.h"
25 #include "param/param.h"
26 #include "lib/cmdline/cmdline.h"
27 #include "rpc_server/mdssvc/dalloc.h"
28 #include "rpc_server/mdssvc/marshalling.h"
30 struct torture_mdsscv_state
{
31 struct dcerpc_pipe
*p
;
32 struct policy_handle ph
;
34 /* Known fields used across multiple commands */
38 /* cmd specific or unknown fields */
40 const char share_path
[1025];
57 static bool torture_rpc_mdssvc_setup(struct torture_context
*tctx
,
60 struct torture_mdsscv_state
*state
= NULL
;
63 state
= talloc_zero(tctx
, struct torture_mdsscv_state
);
69 status
= torture_rpc_connection(tctx
, &state
->p
, &ndr_table_mdssvc
);
70 torture_assert_ntstatus_ok(tctx
, status
, "Error connecting to server");
75 static bool torture_rpc_mdssvc_teardown(struct torture_context
*tctx
,
78 struct torture_mdsscv_state
*state
= talloc_get_type_abort(
79 data
, struct torture_mdsscv_state
);
81 TALLOC_FREE(state
->p
);
86 static bool torture_rpc_mdssvc_open(struct torture_context
*tctx
,
89 struct torture_mdsscv_state
*state
= NULL
;
90 struct dcerpc_binding_handle
*b
= NULL
;
91 const char *share_name
= NULL
;
92 const char *share_mount_path
= NULL
;
96 state
= talloc_zero(tctx
, struct torture_mdsscv_state
);
102 status
= torture_rpc_connection(tctx
, &state
->p
, &ndr_table_mdssvc
);
103 torture_assert_ntstatus_ok(tctx
, status
, "Error connecting to server");
104 b
= state
->p
->binding_handle
;
106 share_name
= torture_setting_string(
107 tctx
, "spotlight_share", "spotlight");
108 share_mount_path
= torture_setting_string(
109 tctx
, "share_mount_path", "/foo/bar");
111 state
->dev
= generate_random();
112 state
->mdscmd_open
.unkn2
= 23;
113 state
->mdscmd_open
.unkn3
= 0;
115 ZERO_STRUCT(state
->ph
);
117 status
= dcerpc_mdssvc_open(b
,
120 &state
->mdscmd_open
.unkn2
,
121 &state
->mdscmd_open
.unkn3
,
124 state
->mdscmd_open
.share_path
,
126 torture_assert_ntstatus_ok_goto(tctx
, status
, ok
, done
,
127 "dcerpc_mdssvc_open failed\n");
129 status
= dcerpc_mdssvc_unknown1(b
,
134 state
->mdscmd_open
.unkn2
,
138 &state
->mdscmd_unknown1
.status
,
140 &state
->mdscmd_unknown1
.unkn7
);
141 torture_assert_ntstatus_ok_goto(tctx
, status
, ok
, done
,
142 "dcerpc_mdssvc_unknown1 failed\n");
146 (void)dcerpc_mdssvc_close(b
,
151 state
->mdscmd_open
.unkn2
,
154 &state
->mdscmd_close
.status
);
160 static bool torture_rpc_mdssvc_close(struct torture_context
*tctx
,
163 struct torture_mdsscv_state
*state
= talloc_get_type_abort(
164 data
, struct torture_mdsscv_state
);
165 struct dcerpc_binding_handle
*b
= state
->p
->binding_handle
;
169 torture_comment(tctx
, "test_teardown_mdssvc_disconnect\n");
171 status
= dcerpc_mdssvc_close(b
,
176 state
->mdscmd_open
.unkn2
,
179 &state
->mdscmd_close
.status
);
180 torture_assert_ntstatus_ok_goto(tctx
, status
, ok
, done
,
181 "dcerpc_mdssvc_close failed\n");
190 * Test unknown share name
192 static bool test_mdssvc_open_unknown_share(struct torture_context
*tctx
,
195 struct torture_mdsscv_state
*state
= talloc_get_type_abort(
196 data
, struct torture_mdsscv_state
);
197 struct dcerpc_binding_handle
*b
= state
->p
->binding_handle
;
198 struct policy_handle ph
;
199 struct policy_handle nullh
;
203 uint32_t device_id_out
;
206 const char *share_mount_path
= NULL
;
207 const char *share_name
= NULL
;
208 const char share_path
[1025] = "X";
212 share_name
= torture_setting_string(
213 tctx
, "unknown_share", "choukawoohoo");
214 share_mount_path
= torture_setting_string(
215 tctx
, "share_mount_path", "/foo/bar");
217 device_id_out
= device_id
= generate_random();
218 unkn2_out
= unkn2
= generate_random();
219 unkn3_out
= unkn3
= generate_random();
224 status
= dcerpc_mdssvc_open(b
,
234 torture_assert_ntstatus_ok_goto(tctx
, status
, ok
, done
,
235 "dcerpc_mdssvc_open failed\n");
237 torture_assert_u32_equal_goto(tctx
, device_id_out
, device_id
, ok
, done
,
240 torture_assert_u32_equal_goto(tctx
, unkn2_out
, unkn2
, ok
, done
,
243 torture_assert_u32_equal_goto(tctx
, unkn3_out
, unkn3
, ok
, done
,
246 torture_assert_goto(tctx
, share_path
[0] == '\0', ok
, done
,
247 "Expected empty string as share path\n");
249 torture_assert_mem_equal_goto(tctx
, &ph
, &nullh
,
250 sizeof(ph
), ok
, done
,
251 "Expected all-zero policy handle\n");
258 * Test on a share where Spotlight is not enabled
260 static bool test_mdssvc_open_spotlight_disabled(struct torture_context
*tctx
,
263 struct torture_mdsscv_state
*state
= talloc_get_type_abort(
264 data
, struct torture_mdsscv_state
);
265 struct dcerpc_binding_handle
*b
= state
->p
->binding_handle
;
266 struct policy_handle ph
;
267 struct policy_handle nullh
;
271 uint32_t device_id_out
;
274 const char *share_mount_path
= NULL
;
275 const char *share_name
= NULL
;
276 const char share_path
[1025] = "";
280 share_name
= torture_setting_string(
281 tctx
, "no_spotlight_share", "no_spotlight");
282 share_mount_path
= torture_setting_string(
283 tctx
, "share_mount_path", "/foo/bar");
285 device_id_out
= device_id
= generate_random();
286 unkn2_out
= unkn2
= 23;
287 unkn3_out
= unkn3
= 0;
292 status
= dcerpc_mdssvc_open(b
,
301 torture_assert_ntstatus_ok_goto(tctx
, status
, ok
, done
,
302 "dcerpc_mdssvc_open failed\n");
304 torture_assert_u32_equal_goto(tctx
, device_id
, device_id_out
, ok
, done
,
307 torture_assert_u32_equal_goto(tctx
, unkn2
, unkn2_out
,
308 ok
, done
, "Bad unkn2\n");
310 torture_assert_u32_equal_goto(tctx
, unkn3
, unkn3_out
,
311 ok
, done
, "Bad unkn3\n");
313 torture_assert_goto(tctx
, share_path
[0] == '\0', ok
, done
,
314 "Expected empty string as share path\n");
316 torture_assert_mem_equal_goto(tctx
, &ph
, &nullh
,
317 sizeof(ph
), ok
, done
,
318 "Expected all-zero policy handle\n");
324 static bool test_mdssvc_close(struct torture_context
*tctx
,
327 struct torture_mdsscv_state
*state
= talloc_get_type_abort(
328 data
, struct torture_mdsscv_state
);
329 struct dcerpc_binding_handle
*b
= state
->p
->binding_handle
;
330 struct policy_handle ph
;
331 struct policy_handle close_ph
;
335 const char *share_mount_path
= NULL
;
336 const char *share_name
= NULL
;
337 const char share_path
[1025] = "";
338 uint32_t close_status
;
340 DATA_BLOB close_ph_blob
;
344 share_name
= torture_setting_string(
345 tctx
, "spotlight_share", "spotlight");
346 share_mount_path
= torture_setting_string(
347 tctx
, "share_mount_path", "/foo/bar");
349 device_id
= generate_random();
354 ZERO_STRUCT(close_ph
);
356 status
= dcerpc_mdssvc_open(b
,
365 torture_assert_ntstatus_ok_goto(tctx
, status
, ok
, done
,
366 "dcerpc_mdssvc_open failed\n");
368 status
= dcerpc_mdssvc_close(b
,
377 torture_assert_ntstatus_ok_goto(tctx
, status
, ok
, done
,
378 "dcerpc_mdssvc_open failed\n");
380 ph_blob
= (DATA_BLOB
) {
381 .data
= (uint8_t *)&ph
,
382 .length
= sizeof(struct policy_handle
)
384 close_ph_blob
= (DATA_BLOB
) {
385 .data
= (uint8_t *)&close_ph
,
386 .length
= sizeof(struct policy_handle
),
389 torture_assert_data_blob_equal(tctx
, close_ph_blob
, ph_blob
,
392 torture_comment(tctx
, "Test close with a all-zero handle\n");
395 status
= dcerpc_mdssvc_close(b
,
404 torture_assert_ntstatus_ok_goto(tctx
, status
, ok
, done
,
405 "dcerpc_mdssvc_close failed\n");
407 torture_assert_data_blob_equal(tctx
, close_ph_blob
, ph_blob
,
414 static bool test_mdssvc_null_ph(struct torture_context
*tctx
,
417 struct torture_mdsscv_state
*state
= talloc_get_type_abort(
418 data
, struct torture_mdsscv_state
);
419 struct dcerpc_binding_handle
*b
= state
->p
->binding_handle
;
420 struct policy_handle nullh
;
421 struct policy_handle ph
;
430 device_id
= generate_random();
438 status
= dcerpc_mdssvc_unknown1(b
,
450 torture_assert_ntstatus_ok_goto(tctx
, status
, ok
, done
,
451 "dcerpc_mdssvc_unknown1 failed\n");
453 torture_assert_mem_equal_goto(tctx
, &ph
, &nullh
,
454 sizeof(ph
), ok
, done
,
455 "Expected all-zero policy handle\n");
461 static bool test_mdssvc_invalid_ph_unknown1(struct torture_context
*tctx
,
464 struct torture_mdsscv_state
*state
= talloc_get_type_abort(
465 data
, struct torture_mdsscv_state
);
466 struct dcerpc_binding_handle
*b
= state
->p
->binding_handle
;
467 struct policy_handle ph
;
476 device_id
= generate_random();
482 ph
.uuid
= GUID_random();
484 status
= dcerpc_mdssvc_unknown1(b
,
496 torture_assert_ntstatus_equal_goto(
497 tctx
, status
, NT_STATUS_RPC_PROTOCOL_ERROR
, ok
, done
,
498 "dcerpc_mdssvc_unknown1 failed\n");
504 static bool test_mdssvc_invalid_ph_cmd(struct torture_context
*tctx
,
507 struct torture_mdsscv_state
*state
= talloc_get_type_abort(
508 data
, struct torture_mdsscv_state
);
509 struct dcerpc_binding_handle
*b
= state
->p
->binding_handle
;
510 struct policy_handle ph
;
511 struct mdssvc_blob request_blob
;
512 struct mdssvc_blob response_blob
;
521 device_id
= generate_random();
525 flags
= UINT32_C(0x6b000001);
528 ph
.uuid
= GUID_random();
530 request_blob
.spotlight_blob
= talloc_array(state
,
533 torture_assert_not_null_goto(tctx
, request_blob
.spotlight_blob
,
534 ok
, done
, "dalloc_zero failed\n");
535 request_blob
.size
= 0;
536 request_blob
.length
= 0;
537 request_blob
.size
= 0;
539 response_blob
.spotlight_blob
= talloc_array(state
,
542 torture_assert_not_null_goto(tctx
, response_blob
.spotlight_blob
,
543 ok
, done
, "dalloc_zero failed\n");
544 response_blob
.size
= 0;
546 status
= dcerpc_mdssvc_cmd(b
,
564 torture_assert_ntstatus_equal_goto(
565 tctx
, status
, NT_STATUS_RPC_PROTOCOL_ERROR
, ok
, done
,
566 "dcerpc_mdssvc_unknown1 failed\n");
572 static bool test_mdssvc_invalid_ph_close(struct torture_context
*tctx
,
575 struct torture_mdsscv_state
*state
= talloc_get_type_abort(
576 data
, struct torture_mdsscv_state
);
577 struct dcerpc_binding_handle
*b
= state
->p
->binding_handle
;
578 struct policy_handle ph
;
581 uint32_t close_status
;
585 device_id
= generate_random();
590 ph
.uuid
= GUID_random();
592 status
= dcerpc_mdssvc_close(b
,
601 torture_assert_ntstatus_equal_goto(
602 tctx
, status
, NT_STATUS_RPC_PROTOCOL_ERROR
, ok
, done
,
603 "dcerpc_mdssvc_unknown1 failed\n");
610 * Test fetchAttributes with unknown CNID
612 static bool test_mdssvc_fetch_attr_unknown_cnid(struct torture_context
*tctx
,
615 struct torture_mdsscv_state
*state
= talloc_get_type_abort(
616 data
, struct torture_mdsscv_state
);
617 struct dcerpc_binding_handle
*b
= state
->p
->binding_handle
;
618 uint32_t max_fragment_size
= 64 * 1024;
619 struct mdssvc_blob request_blob
;
620 struct mdssvc_blob response_blob
;
621 DALLOC_CTX
*d
= NULL
, *mds_reply
= NULL
;
622 uint64_t *uint64var
= NULL
;
623 sl_array_t
*array
= NULL
;
624 sl_array_t
*cmd_array
= NULL
;
625 sl_array_t
*attr_array
= NULL
;
626 sl_cnids_t
*cnids
= NULL
;
628 const char *path_type
= NULL
;
635 d
= dalloc_new(state
);
636 torture_assert_not_null_goto(tctx
, d
, ret
, done
, "dalloc_new failed\n");
638 array
= dalloc_zero(d
, sl_array_t
);
639 torture_assert_not_null_goto(tctx
, array
, ret
, done
,
640 "dalloc_zero failed\n");
642 ret
= dalloc_add(d
, array
, sl_array_t
);
643 torture_assert_goto(tctx
, ret
== 0, ret
, done
, "dalloc_add failed\n");
645 cmd_array
= dalloc_zero(d
, sl_array_t
);
646 torture_assert_not_null_goto(tctx
, cmd_array
, ret
, done
,
647 "dalloc_zero failed\n");
649 ret
= dalloc_add(array
, cmd_array
, sl_array_t
);
650 torture_assert_goto(tctx
, ret
== 0, ret
, done
, "dalloc_add failed\n");
652 ret
= dalloc_stradd(cmd_array
, "fetchAttributes:forOIDArray:context:");
653 torture_assert_goto(tctx
, ret
== 0, ret
, done
, "dalloc_stradd failed\n");
655 uint64var
= talloc_zero_array(cmd_array
, uint64_t, 2);
656 torture_assert_not_null_goto(tctx
, uint64var
, ret
, done
,
657 "talloc_zero_array failed\n");
658 talloc_set_name(uint64var
, "uint64_t *");
660 uint64var
[0] = 0x500a;
663 ret
= dalloc_add(cmd_array
, &uint64var
[0], uint64_t *);
664 torture_assert_goto(tctx
, ret
== 0, ret
, done
, "dalloc_add failed\n");
666 attr_array
= dalloc_zero(d
, sl_array_t
);
667 torture_assert_not_null_goto(tctx
, attr_array
, ret
, done
,
668 "dalloc_zero failed\n");
670 ret
= dalloc_add(array
, attr_array
, sl_array_t
);
671 torture_assert_goto(tctx
, ret
== 0, ret
, done
, "dalloc_add failed\n");
673 ret
= dalloc_stradd(attr_array
, "kMDItemPath");
674 torture_assert_goto(tctx
, ret
== 0, ret
, done
, "dalloc_stradd failed\n");
677 cnids
= talloc_zero(array
, sl_cnids_t
);
678 torture_assert_not_null_goto(tctx
, cnids
, ret
, done
,
679 "talloc_zero failed\n");
681 cnids
->ca_cnids
= dalloc_new(cnids
);
682 torture_assert_not_null_goto(tctx
, cnids
->ca_cnids
, ret
, done
,
683 "dalloc_new failed\n");
685 cnids
->ca_unkn1
= 0xadd;
686 cnids
->ca_context
= 0x6b000020;
688 ino64
= UINT64_C(64382947389618974);
689 ret
= dalloc_add_copy(cnids
->ca_cnids
, &ino64
, uint64_t);
690 torture_assert_goto(tctx
, ret
== 0, ret
, done
,
691 "dalloc_add_copy failed\n");
693 ret
= dalloc_add(array
, cnids
, sl_cnids_t
);
694 torture_assert_goto(tctx
, ret
== 0, ret
, done
, "dalloc_add failed\n");
696 request_blob
.spotlight_blob
= talloc_array(state
,
699 torture_assert_not_null_goto(tctx
, request_blob
.spotlight_blob
,
700 ret
, done
, "dalloc_zero failed\n");
701 request_blob
.size
= max_fragment_size
;
703 response_blob
.spotlight_blob
= talloc_array(state
,
706 torture_assert_not_null_goto(tctx
, response_blob
.spotlight_blob
,
707 ret
, done
, "dalloc_zero failed\n");
708 response_blob
.size
= max_fragment_size
;
710 len
= sl_pack(d
, (char *)request_blob
.spotlight_blob
, request_blob
.size
);
711 torture_assert_goto(tctx
, len
!= -1, ret
, done
, "sl_pack failed\n");
713 request_blob
.length
= len
;
714 request_blob
.size
= len
;
716 status
= dcerpc_mdssvc_cmd(b
,
721 state
->mdscmd_open
.unkn2
,
731 &state
->mdscmd_cmd
.fragment
,
733 &state
->mdscmd_cmd
.unkn9
);
734 torture_assert_ntstatus_ok_goto(tctx
, status
, ret
, done
,
735 "dcerpc_mdssvc_cmd failed\n");
737 mds_reply
= dalloc_new(state
);
738 torture_assert_not_null_goto(tctx
, mds_reply
, ret
, done
,
739 "dalloc_zero failed\n");
741 ok
= sl_unpack(mds_reply
,
742 (char *)response_blob
.spotlight_blob
,
743 response_blob
.length
);
744 torture_assert_goto(tctx
, ok
, ret
, done
, "dalloc_add failed\n");
746 torture_comment(tctx
, "%s", dalloc_dump(mds_reply
, 0));
748 path
= dalloc_get(mds_reply
,
753 torture_assert_not_null_goto(tctx
, path
, ret
, done
,
754 "dalloc_get path failed\n");
756 path_type
= talloc_get_name(path
);
758 torture_assert_str_equal_goto(tctx
, path_type
, "sl_nil_t", ret
, done
,
759 "Wrong dalloc object type\n");
765 struct torture_suite
*torture_rpc_mdssvc(TALLOC_CTX
*mem_ctx
)
767 struct torture_suite
*suite
= torture_suite_create(
769 struct torture_tcase
*tcase
= NULL
;
771 tcase
= torture_suite_add_tcase(suite
, "rpccmd");
775 torture_tcase_set_fixture(tcase
,
776 torture_rpc_mdssvc_setup
,
777 torture_rpc_mdssvc_teardown
);
779 torture_tcase_add_simple_test(tcase
,
780 "open_unknown_share",
781 test_mdssvc_open_unknown_share
);
783 torture_tcase_add_simple_test(tcase
,
784 "open_spotlight_disabled",
785 test_mdssvc_open_spotlight_disabled
);
787 torture_tcase_add_simple_test(tcase
,
791 torture_tcase_add_simple_test(tcase
,
793 test_mdssvc_null_ph
);
795 tcase
= torture_suite_add_tcase(suite
, "disconnect1");
799 torture_tcase_set_fixture(tcase
,
800 torture_rpc_mdssvc_open
,
801 torture_rpc_mdssvc_close
);
803 torture_tcase_add_simple_test(tcase
,
804 "invalid_ph_unknown1",
805 test_mdssvc_invalid_ph_unknown1
);
807 tcase
= torture_suite_add_tcase(suite
, "disconnect2");
811 torture_tcase_set_fixture(tcase
,
812 torture_rpc_mdssvc_open
,
813 torture_rpc_mdssvc_close
);
815 torture_tcase_add_simple_test(tcase
,
817 test_mdssvc_invalid_ph_cmd
);
819 tcase
= torture_suite_add_tcase(suite
, "disconnect3");
823 torture_tcase_set_fixture(tcase
,
824 torture_rpc_mdssvc_open
,
825 torture_rpc_mdssvc_close
);
827 torture_tcase_add_simple_test(tcase
,
829 test_mdssvc_invalid_ph_close
);
831 tcase
= torture_suite_add_tcase(suite
, "mdscmd");
835 torture_tcase_set_fixture(tcase
,
836 torture_rpc_mdssvc_open
,
837 torture_rpc_mdssvc_close
);
839 torture_tcase_add_simple_test(tcase
,
840 "fetch_unknown_cnid",
841 test_mdssvc_fetch_attr_unknown_cnid
);