Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : test suite for the mdssvc RPC service
4 :
5 : Copyright (C) Ralph Boehme 2019
6 :
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.
11 :
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.
16 :
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.
20 : */
21 :
22 : #include "includes.h"
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"
29 :
30 : struct torture_mdsscv_state {
31 : struct dcerpc_pipe *p;
32 : struct policy_handle ph;
33 :
34 : /* Known fields used across multiple commands */
35 : uint32_t dev;
36 : uint32_t flags;
37 :
38 : /* cmd specific or unknown fields */
39 : struct {
40 : const char share_path[1025];
41 : uint32_t unkn2;
42 : uint32_t unkn3;
43 : } mdscmd_open;
44 : struct {
45 : uint32_t status;
46 : uint32_t unkn7;
47 : } mdscmd_unknown1;
48 : struct {
49 : uint32_t fragment;
50 : uint32_t unkn9;
51 : } mdscmd_cmd;
52 : struct {
53 : uint32_t status;
54 : } mdscmd_close;
55 : };
56 :
57 2 : static bool torture_rpc_mdssvc_setup(struct torture_context *tctx,
58 : void **data)
59 : {
60 2 : struct torture_mdsscv_state *state = NULL;
61 0 : NTSTATUS status;
62 :
63 2 : state = talloc_zero(tctx, struct torture_mdsscv_state);
64 2 : if (state == NULL) {
65 0 : return false;
66 : }
67 2 : *data = state;
68 :
69 2 : status = torture_rpc_connection(tctx, &state->p, &ndr_table_mdssvc);
70 2 : torture_assert_ntstatus_ok(tctx, status, "Error connecting to server");
71 :
72 2 : return true;
73 : }
74 :
75 2 : static bool torture_rpc_mdssvc_teardown(struct torture_context *tctx,
76 : void *data)
77 : {
78 2 : struct torture_mdsscv_state *state = talloc_get_type_abort(
79 : data, struct torture_mdsscv_state);
80 :
81 2 : TALLOC_FREE(state->p);
82 2 : TALLOC_FREE(state);
83 2 : return true;
84 : }
85 :
86 8 : static bool torture_rpc_mdssvc_open(struct torture_context *tctx,
87 : void **data)
88 : {
89 8 : struct torture_mdsscv_state *state = NULL;
90 8 : struct dcerpc_binding_handle *b = NULL;
91 8 : const char *share_name = NULL;
92 8 : const char *share_mount_path = NULL;
93 0 : NTSTATUS status;
94 8 : bool ok = true;
95 :
96 8 : state = talloc_zero(tctx, struct torture_mdsscv_state);
97 8 : if (state == NULL) {
98 0 : return false;
99 : }
100 8 : *data = state;
101 :
102 8 : status = torture_rpc_connection(tctx, &state->p, &ndr_table_mdssvc);
103 8 : torture_assert_ntstatus_ok(tctx, status, "Error connecting to server");
104 8 : b = state->p->binding_handle;
105 :
106 8 : share_name = torture_setting_string(
107 : tctx, "spotlight_share", "spotlight");
108 8 : share_mount_path = torture_setting_string(
109 : tctx, "share_mount_path", "/foo/bar");
110 :
111 8 : state->dev = generate_random();
112 8 : state->mdscmd_open.unkn2 = 23;
113 8 : state->mdscmd_open.unkn3 = 0;
114 :
115 8 : ZERO_STRUCT(state->ph);
116 :
117 8 : status = dcerpc_mdssvc_open(b,
118 : state,
119 : &state->dev,
120 : &state->mdscmd_open.unkn2,
121 : &state->mdscmd_open.unkn3,
122 : share_mount_path,
123 : share_name,
124 8 : state->mdscmd_open.share_path,
125 : &state->ph);
126 8 : torture_assert_ntstatus_ok_goto(tctx, status, ok, done,
127 : "dcerpc_mdssvc_open failed\n");
128 :
129 8 : status = dcerpc_mdssvc_unknown1(b,
130 : state,
131 : &state->ph,
132 : 0,
133 : state->dev,
134 : state->mdscmd_open.unkn2,
135 : 0,
136 : geteuid(),
137 : getegid(),
138 : &state->mdscmd_unknown1.status,
139 : &state->flags,
140 : &state->mdscmd_unknown1.unkn7);
141 8 : torture_assert_ntstatus_ok_goto(tctx, status, ok, done,
142 : "dcerpc_mdssvc_unknown1 failed\n");
143 :
144 8 : done:
145 8 : if (!ok) {
146 0 : (void)dcerpc_mdssvc_close(b,
147 : state,
148 : &state->ph,
149 : 0,
150 : state->dev,
151 : state->mdscmd_open.unkn2,
152 : 0,
153 : &state->ph,
154 : &state->mdscmd_close.status);
155 0 : ZERO_STRUCTP(state);
156 : }
157 8 : return ok;
158 : }
159 :
160 8 : static bool torture_rpc_mdssvc_close(struct torture_context *tctx,
161 : void *data)
162 : {
163 8 : struct torture_mdsscv_state *state = talloc_get_type_abort(
164 : data, struct torture_mdsscv_state);
165 0 : NTSTATUS status;
166 8 : bool ok = true;
167 :
168 8 : torture_comment(tctx, "test_teardown_mdssvc_disconnect\n");
169 :
170 8 : if (state->p == NULL) {
171 : /* We have already been disconnected. */
172 6 : goto done;
173 : }
174 :
175 2 : status = dcerpc_mdssvc_close(state->p->binding_handle,
176 : state,
177 : &state->ph,
178 : 0,
179 : state->dev,
180 : state->mdscmd_open.unkn2,
181 : 0,
182 : &state->ph,
183 : &state->mdscmd_close.status);
184 2 : torture_assert_ntstatus_ok_goto(tctx, status, ok, done,
185 : "dcerpc_mdssvc_close failed\n");
186 :
187 2 : ZERO_STRUCTP(state);
188 :
189 0 : done:
190 8 : return ok;
191 : }
192 :
193 : /*
194 : * Test unknown share name
195 : */
196 2 : static bool test_mdssvc_open_unknown_share(struct torture_context *tctx,
197 : void *data)
198 : {
199 2 : struct torture_mdsscv_state *state = talloc_get_type_abort(
200 : data, struct torture_mdsscv_state);
201 2 : struct dcerpc_binding_handle *b = state->p->binding_handle;
202 0 : struct policy_handle ph;
203 0 : struct policy_handle nullh;
204 0 : uint32_t device_id;
205 0 : uint32_t unkn2;
206 0 : uint32_t unkn3;
207 0 : uint32_t device_id_out;
208 0 : uint32_t unkn2_out;
209 0 : uint32_t unkn3_out;
210 2 : const char *share_mount_path = NULL;
211 2 : const char *share_name = NULL;
212 2 : const char share_path[1025] = "X";
213 0 : NTSTATUS status;
214 2 : bool ok = true;
215 :
216 2 : share_name = torture_setting_string(
217 : tctx, "unknown_share", "choukawoohoo");
218 2 : share_mount_path = torture_setting_string(
219 : tctx, "share_mount_path", "/foo/bar");
220 :
221 2 : device_id_out = device_id = generate_random();
222 2 : unkn2_out = unkn2 = generate_random();
223 2 : unkn3_out = unkn3 = generate_random();
224 :
225 2 : ZERO_STRUCT(ph);
226 2 : ZERO_STRUCT(nullh);
227 :
228 2 : status = dcerpc_mdssvc_open(b,
229 : tctx,
230 : &device_id_out,
231 : &unkn2_out,
232 : &unkn3_out,
233 : share_mount_path,
234 : share_name,
235 : share_path,
236 : &ph);
237 :
238 2 : torture_assert_ntstatus_ok_goto(tctx, status, ok, done,
239 : "dcerpc_mdssvc_open failed\n");
240 :
241 2 : torture_assert_u32_equal_goto(tctx, device_id_out, device_id, ok, done,
242 : "Bad device_id\n");
243 :
244 2 : torture_assert_u32_equal_goto(tctx, unkn2_out, unkn2, ok, done,
245 : "Bad unkn2\n");
246 :
247 2 : torture_assert_u32_equal_goto(tctx, unkn3_out, unkn3, ok, done,
248 : "Bad unkn3\n");
249 :
250 2 : torture_assert_goto(tctx, share_path[0] == '\0', ok, done,
251 : "Expected empty string as share path\n");
252 :
253 2 : torture_assert_mem_equal_goto(tctx, &ph, &nullh,
254 : sizeof(ph), ok, done,
255 : "Expected all-zero policy handle\n");
256 :
257 2 : done:
258 2 : return ok;
259 : }
260 :
261 : /*
262 : * Test on a share where Spotlight is not enabled
263 : */
264 2 : static bool test_mdssvc_open_spotlight_disabled(struct torture_context *tctx,
265 : void *data)
266 : {
267 2 : struct torture_mdsscv_state *state = talloc_get_type_abort(
268 : data, struct torture_mdsscv_state);
269 2 : struct dcerpc_binding_handle *b = state->p->binding_handle;
270 0 : struct policy_handle ph;
271 0 : struct policy_handle nullh;
272 0 : uint32_t device_id;
273 0 : uint32_t unkn2;
274 0 : uint32_t unkn3;
275 0 : uint32_t device_id_out;
276 0 : uint32_t unkn2_out;
277 0 : uint32_t unkn3_out;
278 2 : const char *share_mount_path = NULL;
279 2 : const char *share_name = NULL;
280 2 : const char share_path[1025] = "";
281 0 : NTSTATUS status;
282 2 : bool ok = true;
283 :
284 2 : share_name = torture_setting_string(
285 : tctx, "no_spotlight_share", "no_spotlight");
286 2 : share_mount_path = torture_setting_string(
287 : tctx, "share_mount_path", "/foo/bar");
288 :
289 2 : device_id_out = device_id = generate_random();
290 2 : unkn2_out = unkn2 = 23;
291 2 : unkn3_out = unkn3 = 0;
292 :
293 2 : ZERO_STRUCT(ph);
294 2 : ZERO_STRUCT(nullh);
295 :
296 2 : status = dcerpc_mdssvc_open(b,
297 : tctx,
298 : &device_id_out,
299 : &unkn2_out,
300 : &unkn3_out,
301 : share_mount_path,
302 : share_name,
303 : share_path,
304 : &ph);
305 2 : torture_assert_ntstatus_ok_goto(tctx, status, ok, done,
306 : "dcerpc_mdssvc_open failed\n");
307 :
308 2 : torture_assert_u32_equal_goto(tctx, device_id, device_id_out, ok, done,
309 : "Bad device_id\n");
310 :
311 2 : torture_assert_u32_equal_goto(tctx, unkn2, unkn2_out,
312 : ok, done, "Bad unkn2\n");
313 :
314 2 : torture_assert_u32_equal_goto(tctx, unkn3, unkn3_out,
315 : ok, done, "Bad unkn3\n");
316 :
317 2 : torture_assert_goto(tctx, share_path[0] == '\0', ok, done,
318 : "Expected empty string as share path\n");
319 :
320 2 : torture_assert_mem_equal_goto(tctx, &ph, &nullh,
321 : sizeof(ph), ok, done,
322 : "Expected all-zero policy handle\n");
323 :
324 2 : done:
325 2 : return ok;
326 : }
327 :
328 2 : static bool test_mdssvc_close(struct torture_context *tctx,
329 : void *data)
330 : {
331 2 : struct torture_mdsscv_state *state = talloc_get_type_abort(
332 : data, struct torture_mdsscv_state);
333 2 : struct dcerpc_binding_handle *b = state->p->binding_handle;
334 0 : struct policy_handle ph;
335 0 : struct policy_handle close_ph;
336 0 : uint32_t device_id;
337 0 : uint32_t unkn2;
338 0 : uint32_t unkn3;
339 2 : const char *share_mount_path = NULL;
340 2 : const char *share_name = NULL;
341 2 : const char share_path[1025] = "";
342 0 : uint32_t close_status;
343 0 : DATA_BLOB ph_blob;
344 0 : DATA_BLOB close_ph_blob;
345 0 : NTSTATUS status;
346 2 : bool ok = true;
347 :
348 2 : share_name = torture_setting_string(
349 : tctx, "spotlight_share", "spotlight");
350 2 : share_mount_path = torture_setting_string(
351 : tctx, "share_mount_path", "/foo/bar");
352 :
353 2 : device_id = generate_random();
354 2 : unkn2 = 23;
355 2 : unkn3 = 0;
356 :
357 2 : ZERO_STRUCT(ph);
358 2 : ZERO_STRUCT(close_ph);
359 :
360 2 : status = dcerpc_mdssvc_open(b,
361 : tctx,
362 : &device_id,
363 : &unkn2,
364 : &unkn3,
365 : share_mount_path,
366 : share_name,
367 : share_path,
368 : &ph);
369 2 : torture_assert_ntstatus_ok_goto(tctx, status, ok, done,
370 : "dcerpc_mdssvc_open failed\n");
371 :
372 2 : status = dcerpc_mdssvc_close(b,
373 : tctx,
374 : &ph,
375 : 0,
376 : device_id,
377 : unkn2,
378 : 0,
379 : &close_ph,
380 : &close_status);
381 2 : torture_assert_ntstatus_ok_goto(tctx, status, ok, done,
382 : "dcerpc_mdssvc_open failed\n");
383 :
384 2 : ph_blob = (DATA_BLOB) {
385 : .data = (uint8_t *)&ph,
386 : .length = sizeof(struct policy_handle)
387 : };
388 2 : close_ph_blob = (DATA_BLOB) {
389 : .data = (uint8_t *)&close_ph,
390 : .length = sizeof(struct policy_handle),
391 : };
392 :
393 2 : torture_assert_data_blob_equal(tctx, close_ph_blob, ph_blob,
394 : "bad blob");
395 :
396 2 : torture_comment(tctx, "Test close with a all-zero handle\n");
397 :
398 2 : ZERO_STRUCT(ph);
399 2 : status = dcerpc_mdssvc_close(b,
400 : tctx,
401 : &ph,
402 : 0,
403 : device_id,
404 : unkn2,
405 : 0,
406 : &close_ph,
407 : &close_status);
408 2 : torture_assert_ntstatus_ok_goto(tctx, status, ok, done,
409 : "dcerpc_mdssvc_close failed\n");
410 :
411 2 : torture_assert_data_blob_equal(tctx, close_ph_blob, ph_blob,
412 : "bad blob");
413 :
414 2 : done:
415 2 : return ok;
416 : }
417 :
418 2 : static bool test_mdssvc_null_ph(struct torture_context *tctx,
419 : void *data)
420 : {
421 2 : struct torture_mdsscv_state *state = talloc_get_type_abort(
422 : data, struct torture_mdsscv_state);
423 2 : struct dcerpc_binding_handle *b = state->p->binding_handle;
424 0 : struct policy_handle nullh;
425 0 : struct policy_handle ph;
426 0 : uint32_t device_id;
427 0 : uint32_t unkn2;
428 0 : uint32_t unkn7;
429 0 : uint32_t cmd_status;
430 0 : uint32_t flags;
431 0 : NTSTATUS status;
432 2 : bool ok = true;
433 :
434 2 : device_id = generate_random();
435 2 : unkn2 = 23;
436 2 : unkn7 = 0;
437 2 : cmd_status = 0;
438 :
439 2 : ZERO_STRUCT(nullh);
440 2 : ZERO_STRUCT(ph);
441 :
442 2 : status = dcerpc_mdssvc_unknown1(b,
443 : tctx,
444 : &ph,
445 : 0,
446 : device_id,
447 : unkn2,
448 : 0,
449 : geteuid(),
450 : getegid(),
451 : &cmd_status,
452 : &flags,
453 : &unkn7);
454 2 : torture_assert_ntstatus_ok_goto(tctx, status, ok, done,
455 : "dcerpc_mdssvc_unknown1 failed\n");
456 :
457 2 : torture_assert_mem_equal_goto(tctx, &ph, &nullh,
458 : sizeof(ph), ok, done,
459 : "Expected all-zero policy handle\n");
460 :
461 2 : done:
462 2 : return ok;
463 : }
464 :
465 2 : static bool test_mdssvc_invalid_ph_unknown1(struct torture_context *tctx,
466 : void *data)
467 : {
468 2 : struct torture_mdsscv_state *state = talloc_get_type_abort(
469 : data, struct torture_mdsscv_state);
470 2 : struct dcerpc_binding_handle *b = state->p->binding_handle;
471 0 : struct policy_handle ph;
472 0 : uint32_t device_id;
473 0 : uint32_t unkn2;
474 0 : uint32_t unkn7;
475 0 : uint32_t cmd_status;
476 0 : uint32_t flags;
477 0 : NTSTATUS status;
478 2 : bool ok = true;
479 :
480 2 : device_id = generate_random();
481 2 : unkn2 = 23;
482 2 : unkn7 = 0;
483 2 : cmd_status = 0;
484 :
485 2 : ZERO_STRUCT(ph);
486 2 : ph.uuid = GUID_random();
487 :
488 2 : status = dcerpc_mdssvc_unknown1(b,
489 : tctx,
490 : &ph,
491 : 0,
492 : device_id,
493 : unkn2,
494 : 0,
495 : geteuid(),
496 : getegid(),
497 : &cmd_status,
498 : &flags,
499 : &unkn7);
500 2 : torture_assert_ntstatus_equal_goto(
501 : tctx, status, NT_STATUS_RPC_PROTOCOL_ERROR, ok, done,
502 : "dcerpc_mdssvc_unknown1 failed\n");
503 :
504 : /* Free and set to NULL the no-longer-usable pipe. */
505 2 : b = NULL;
506 2 : TALLOC_FREE(state->p);
507 :
508 0 : done:
509 2 : return ok;
510 : }
511 :
512 2 : static bool test_mdssvc_invalid_ph_cmd(struct torture_context *tctx,
513 : void *data)
514 : {
515 2 : struct torture_mdsscv_state *state = talloc_get_type_abort(
516 : data, struct torture_mdsscv_state);
517 2 : struct dcerpc_binding_handle *b = state->p->binding_handle;
518 0 : struct policy_handle ph;
519 0 : struct mdssvc_blob request_blob;
520 0 : struct mdssvc_blob response_blob;
521 0 : uint32_t device_id;
522 0 : uint32_t unkn2;
523 0 : uint32_t unkn9;
524 0 : uint32_t fragment;
525 0 : uint32_t flags;
526 0 : NTSTATUS status;
527 2 : bool ok = true;
528 :
529 2 : device_id = generate_random();
530 2 : unkn2 = 23;
531 2 : unkn9 = 0;
532 2 : fragment = 0;
533 2 : flags = UINT32_C(0x6b000001);
534 :
535 2 : ZERO_STRUCT(ph);
536 2 : ph.uuid = GUID_random();
537 :
538 2 : request_blob.spotlight_blob = talloc_array(state,
539 : uint8_t,
540 : 0);
541 2 : torture_assert_not_null_goto(tctx, request_blob.spotlight_blob,
542 : ok, done, "dalloc_zero failed\n");
543 2 : request_blob.size = 0;
544 2 : request_blob.length = 0;
545 2 : request_blob.size = 0;
546 :
547 2 : status = dcerpc_mdssvc_cmd(b,
548 : state,
549 : &ph,
550 : 0,
551 : device_id,
552 : unkn2,
553 : 0,
554 : flags,
555 : request_blob,
556 : 0,
557 : 64 * 1024,
558 : 1,
559 : 64 * 1024,
560 : 0,
561 : 0,
562 : &fragment,
563 : &response_blob,
564 : &unkn9);
565 2 : torture_assert_ntstatus_equal_goto(
566 : tctx, status, NT_STATUS_RPC_PROTOCOL_ERROR, ok, done,
567 : "dcerpc_mdssvc_unknown1 failed\n");
568 :
569 : /* Free and set to NULL the no-longer-usable pipe. */
570 2 : b = NULL;
571 2 : TALLOC_FREE(state->p);
572 :
573 0 : done:
574 2 : return ok;
575 : }
576 :
577 : static uint8_t test_sl_unpack_loop_buf[] = {
578 : 0x34, 0x33, 0x32, 0x31, 0x33, 0x30, 0x64, 0x6d,
579 : 0x1d, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
580 : 0x01, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00,
581 : 0x01, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00,
582 : 0x01, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x00,
583 : 0x06, 0x00, 0x00, 0x07, 0x04, 0x00, 0x00, 0x00,
584 : 0x66, 0x65, 0x74, 0x63, 0x68, 0x41, 0x74, 0x74,
585 : 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x3a,
586 : 0x66, 0x6f, 0x72, 0x4f, 0x49, 0x44, 0x41, 0x72,
587 : 0x72, 0x61, 0x79, 0x3a, 0x63, 0x6f, 0x6e, 0x74,
588 : 0x65, 0x78, 0x74, 0x3a, 0x00, 0x00, 0x00, 0xea,
589 : 0x02, 0x00, 0x00, 0x84, 0x02, 0x00, 0x00, 0x00,
590 : 0x0a, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
591 : 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
592 : 0x01, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x00,
593 : 0x01, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x00,
594 : 0x03, 0x00, 0x00, 0x07, 0x03, 0x00, 0x00, 0x00,
595 : 0x6b, 0x4d, 0x44, 0x49, 0x74, 0x65, 0x6d, 0x50,
596 : 0x61, 0x74, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00,
597 : 0x01, 0x00, 0x00, 0x02, 0x06, 0x00, 0x00, 0x00,
598 : 0x03, 0x00, 0x00, 0x87, 0x08, 0x00, 0x00, 0x00,
599 : 0x01, 0x00, 0xdd, 0x0a, 0x20, 0x00, 0x00, 0x6b,
600 : 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
601 : 0x07, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x00,
602 : 0x02, 0x00, 0x00, 0x0a, 0x03, 0x00, 0x00, 0x00,
603 : 0x03, 0x00, 0x00, 0x0a, 0x03, 0x00, 0x00, 0x00,
604 : 0x04, 0x00, 0x00, 0x0c, 0x04, 0x00, 0x00, 0x00,
605 : 0x0e, 0x00, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x00,
606 : 0x0f, 0x00, 0x00, 0x0c, 0x03, 0x00, 0x00, 0x00,
607 : 0x13, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00,
608 : 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
609 : 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
610 : 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
611 : 0x00, 0x00, 0x00, 0x00
612 : };
613 :
614 2 : static bool test_mdssvc_sl_unpack_loop(struct torture_context *tctx,
615 : void *data)
616 : {
617 2 : struct torture_mdsscv_state *state = talloc_get_type_abort(
618 : data, struct torture_mdsscv_state);
619 2 : struct dcerpc_binding_handle *b = state->p->binding_handle;
620 0 : struct mdssvc_blob request_blob;
621 0 : struct mdssvc_blob response_blob;
622 0 : uint32_t device_id;
623 0 : uint32_t unkn2;
624 0 : uint32_t unkn9;
625 0 : uint32_t fragment;
626 0 : uint32_t flags;
627 0 : NTSTATUS status;
628 2 : bool ok = true;
629 :
630 2 : device_id = UINT32_C(0x2f000045);
631 2 : unkn2 = 23;
632 2 : unkn9 = 0;
633 2 : fragment = 0;
634 2 : flags = UINT32_C(0x6b000001);
635 :
636 2 : request_blob.spotlight_blob = test_sl_unpack_loop_buf;
637 2 : request_blob.size = sizeof(test_sl_unpack_loop_buf);
638 2 : request_blob.length = sizeof(test_sl_unpack_loop_buf);
639 :
640 2 : status = dcerpc_mdssvc_cmd(b,
641 : state,
642 : &state->ph,
643 : 0,
644 : device_id,
645 : unkn2,
646 : 0,
647 : flags,
648 : request_blob,
649 : 0,
650 : 64 * 1024,
651 : 1,
652 : 64 * 1024,
653 : 0,
654 : 0,
655 : &fragment,
656 : &response_blob,
657 : &unkn9);
658 2 : torture_assert_ntstatus_ok_goto(
659 : tctx, status, ok, done,
660 : "dcerpc_mdssvc_unknown1 failed\n");
661 :
662 2 : done:
663 2 : return ok;
664 : }
665 :
666 2 : static bool test_sl_dict_type_safety(struct torture_context *tctx,
667 : void *data)
668 : {
669 2 : struct torture_mdsscv_state *state = talloc_get_type_abort(
670 : data, struct torture_mdsscv_state);
671 2 : struct dcerpc_binding_handle *b = state->p->binding_handle;
672 0 : struct mdssvc_blob request_blob;
673 0 : struct mdssvc_blob response_blob;
674 2 : uint64_t ctx1 = 0xdeadbeef;
675 2 : uint64_t ctx2 = 0xcafebabe;
676 0 : uint32_t device_id;
677 0 : uint32_t unkn2;
678 0 : uint32_t unkn9;
679 0 : uint32_t fragment;
680 0 : uint32_t flags;
681 2 : DALLOC_CTX *d = NULL;
682 2 : sl_array_t *array1 = NULL, *array2 = NULL;
683 2 : sl_dict_t *arg = NULL;
684 0 : int result;
685 0 : NTSTATUS status;
686 2 : bool ok = true;
687 :
688 2 : device_id = UINT32_C(0x2f000045);
689 2 : unkn2 = 23;
690 2 : unkn9 = 0;
691 2 : fragment = 0;
692 2 : flags = UINT32_C(0x6b000001);
693 :
694 2 : d = dalloc_new(tctx);
695 2 : torture_assert_not_null_goto(tctx, d,
696 : ok, done, "dalloc_new failed\n");
697 :
698 2 : array1 = dalloc_zero(d, sl_array_t);
699 2 : torture_assert_not_null_goto(tctx, array1,
700 : ok, done, "dalloc_zero failed\n");
701 :
702 2 : array2 = dalloc_zero(d, sl_array_t);
703 2 : torture_assert_not_null_goto(tctx, array2,
704 : ok, done, "dalloc_new failed\n");
705 :
706 2 : result = dalloc_stradd(array2, "openQueryWithParams:forContext:");
707 2 : torture_assert_goto(tctx, result == 0,
708 : ok, done, "dalloc_stradd failed\n");
709 :
710 2 : result = dalloc_add_copy(array2, &ctx1, uint64_t);
711 2 : torture_assert_goto(tctx, result == 0,
712 : ok, done, "dalloc_stradd failed\n");
713 :
714 2 : result = dalloc_add_copy(array2, &ctx2, uint64_t);
715 2 : torture_assert_goto(tctx, result == 0,
716 : ok, done, "dalloc_stradd failed\n");
717 :
718 2 : arg = dalloc_zero(array1, sl_dict_t);
719 2 : torture_assert_not_null_goto(tctx, d,
720 : ok, done, "dalloc_zero failed\n");
721 :
722 2 : result = dalloc_stradd(arg, "kMDQueryString");
723 2 : torture_assert_goto(tctx, result == 0,
724 : ok, done, "dalloc_stradd failed\n");
725 :
726 2 : result = dalloc_stradd(arg, "*");
727 2 : torture_assert_goto(tctx, result == 0,
728 : ok, done, "dalloc_stradd failed\n");
729 :
730 2 : result = dalloc_stradd(arg, "kMDScopeArray");
731 2 : torture_assert_goto(tctx, result == 0,
732 : ok, done, "dalloc_stradd failed\n");
733 :
734 2 : result = dalloc_stradd(arg, "AAAABBBB");
735 2 : torture_assert_goto(tctx, result == 0,
736 : ok, done, "dalloc_stradd failed\n");
737 :
738 2 : result = dalloc_add(array1, array2, sl_array_t);
739 2 : torture_assert_goto(tctx, result == 0,
740 : ok, done, "dalloc_add failed\n");
741 :
742 2 : result = dalloc_add(array1, arg, sl_dict_t);
743 2 : torture_assert_goto(tctx, result == 0,
744 : ok, done, "dalloc_add failed\n");
745 :
746 2 : result = dalloc_add(d, array1, sl_array_t);
747 2 : torture_assert_goto(tctx, result == 0,
748 : ok, done, "dalloc_add failed\n");
749 :
750 2 : torture_comment(tctx, "%s", dalloc_dump(d, 0));
751 :
752 2 : request_blob.spotlight_blob = talloc_array(tctx,
753 : uint8_t,
754 : 64 * 1024);
755 2 : torture_assert_not_null_goto(tctx, request_blob.spotlight_blob,
756 : ok, done, "dalloc_new failed\n");
757 2 : request_blob.size = 64 * 1024;
758 :
759 2 : status = sl_pack_alloc(tctx, d, &request_blob, 64 * 1024);
760 2 : torture_assert_ntstatus_ok_goto(tctx, status, ok, done,
761 : "sl_pack_alloc() failed\n");
762 :
763 2 : status = dcerpc_mdssvc_cmd(b,
764 : state,
765 : &state->ph,
766 : 0,
767 : device_id,
768 : unkn2,
769 : 0,
770 : flags,
771 : request_blob,
772 : 0,
773 : 64 * 1024,
774 : 1,
775 : 64 * 1024,
776 : 0,
777 : 0,
778 : &fragment,
779 : &response_blob,
780 : &unkn9);
781 2 : torture_assert_ntstatus_ok_goto(
782 : tctx, status, ok, done,
783 : "dcerpc_mdssvc_cmd failed\n");
784 :
785 2 : done:
786 2 : return ok;
787 : }
788 :
789 2 : static bool test_mdssvc_invalid_ph_close(struct torture_context *tctx,
790 : void *data)
791 : {
792 2 : struct torture_mdsscv_state *state = talloc_get_type_abort(
793 : data, struct torture_mdsscv_state);
794 2 : struct dcerpc_binding_handle *b = state->p->binding_handle;
795 0 : struct policy_handle ph;
796 0 : uint32_t device_id;
797 0 : uint32_t unkn2;
798 0 : uint32_t close_status;
799 0 : NTSTATUS status;
800 2 : bool ok = true;
801 :
802 2 : device_id = generate_random();
803 2 : unkn2 = 23;
804 2 : close_status = 0;
805 :
806 2 : ZERO_STRUCT(ph);
807 2 : ph.uuid = GUID_random();
808 :
809 2 : status = dcerpc_mdssvc_close(b,
810 : state,
811 : &ph,
812 : 0,
813 : device_id,
814 : unkn2,
815 : 0,
816 : &ph,
817 : &close_status);
818 2 : torture_assert_ntstatus_equal_goto(
819 : tctx, status, NT_STATUS_RPC_PROTOCOL_ERROR, ok, done,
820 : "dcerpc_mdssvc_unknown1 failed\n");
821 :
822 : /* Free and set to NULL the no-longer-usable pipe. */
823 2 : b = NULL;
824 2 : TALLOC_FREE(state->p);
825 :
826 0 : done:
827 2 : return ok;
828 : }
829 :
830 : /*
831 : * Test fetchAttributes with unknown CNID
832 : */
833 2 : static bool test_mdssvc_fetch_attr_unknown_cnid(struct torture_context *tctx,
834 : void *data)
835 : {
836 2 : struct torture_mdsscv_state *state = talloc_get_type_abort(
837 : data, struct torture_mdsscv_state);
838 2 : struct dcerpc_binding_handle *b = state->p->binding_handle;
839 2 : uint32_t max_fragment_size = 64 * 1024;
840 0 : struct mdssvc_blob request_blob;
841 0 : struct mdssvc_blob response_blob;
842 2 : DALLOC_CTX *d = NULL, *mds_reply = NULL;
843 2 : uint64_t *uint64var = NULL;
844 2 : sl_array_t *array = NULL;
845 2 : sl_array_t *cmd_array = NULL;
846 2 : sl_array_t *attr_array = NULL;
847 2 : sl_cnids_t *cnids = NULL;
848 2 : void *path = NULL;
849 2 : const char *path_type = NULL;
850 0 : uint64_t ino64;
851 0 : NTSTATUS status;
852 0 : int ret;
853 2 : bool ok = true;
854 :
855 2 : d = dalloc_new(state);
856 2 : torture_assert_not_null_goto(tctx, d, ret, done, "dalloc_new failed\n");
857 :
858 2 : array = dalloc_zero(d, sl_array_t);
859 2 : torture_assert_not_null_goto(tctx, array, ret, done,
860 : "dalloc_zero failed\n");
861 :
862 2 : ret = dalloc_add(d, array, sl_array_t);
863 2 : torture_assert_goto(tctx, ret == 0, ret, done, "dalloc_add failed\n");
864 :
865 2 : cmd_array = dalloc_zero(d, sl_array_t);
866 2 : torture_assert_not_null_goto(tctx, cmd_array, ret, done,
867 : "dalloc_zero failed\n");
868 :
869 2 : ret = dalloc_add(array, cmd_array, sl_array_t);
870 2 : torture_assert_goto(tctx, ret == 0, ret, done, "dalloc_add failed\n");
871 :
872 2 : ret = dalloc_stradd(cmd_array, "fetchAttributes:forOIDArray:context:");
873 2 : torture_assert_goto(tctx, ret == 0, ret, done, "dalloc_stradd failed\n");
874 :
875 2 : uint64var = talloc_zero_array(cmd_array, uint64_t, 2);
876 2 : torture_assert_not_null_goto(tctx, uint64var, ret, done,
877 : "talloc_zero_array failed\n");
878 2 : talloc_set_name(uint64var, "uint64_t *");
879 :
880 2 : uint64var[0] = 0x500a;
881 2 : uint64var[1] = 0;
882 :
883 2 : ret = dalloc_add(cmd_array, &uint64var[0], uint64_t *);
884 2 : torture_assert_goto(tctx, ret == 0, ret, done, "dalloc_add failed\n");
885 :
886 2 : attr_array = dalloc_zero(d, sl_array_t);
887 2 : torture_assert_not_null_goto(tctx, attr_array, ret, done,
888 : "dalloc_zero failed\n");
889 :
890 2 : ret = dalloc_add(array, attr_array, sl_array_t);
891 2 : torture_assert_goto(tctx, ret == 0, ret, done, "dalloc_add failed\n");
892 :
893 2 : ret = dalloc_stradd(attr_array, "kMDItemPath");
894 2 : torture_assert_goto(tctx, ret == 0, ret, done, "dalloc_stradd failed\n");
895 :
896 : /* CNIDs */
897 2 : cnids = talloc_zero(array, sl_cnids_t);
898 2 : torture_assert_not_null_goto(tctx, cnids, ret, done,
899 : "talloc_zero failed\n");
900 :
901 2 : cnids->ca_cnids = dalloc_new(cnids);
902 2 : torture_assert_not_null_goto(tctx, cnids->ca_cnids, ret, done,
903 : "dalloc_new failed\n");
904 :
905 2 : cnids->ca_unkn1 = 0xadd;
906 2 : cnids->ca_context = 0x6b000020;
907 :
908 2 : ino64 = UINT64_C(64382947389618974);
909 2 : ret = dalloc_add_copy(cnids->ca_cnids, &ino64, uint64_t);
910 2 : torture_assert_goto(tctx, ret == 0, ret, done,
911 : "dalloc_add_copy failed\n");
912 :
913 2 : ret = dalloc_add(array, cnids, sl_cnids_t);
914 2 : torture_assert_goto(tctx, ret == 0, ret, done, "dalloc_add failed\n");
915 :
916 2 : status = sl_pack_alloc(tctx, d, &request_blob, max_fragment_size);
917 2 : torture_assert_ntstatus_ok_goto(tctx, status, ok, done,
918 : "sl_pack_alloc() failed\n");
919 :
920 2 : status = dcerpc_mdssvc_cmd(b,
921 : state,
922 : &state->ph,
923 : 0,
924 : state->dev,
925 : state->mdscmd_open.unkn2,
926 : 0,
927 : state->flags,
928 : request_blob,
929 : 0,
930 : max_fragment_size,
931 : 1,
932 : max_fragment_size,
933 : 0,
934 : 0,
935 : &state->mdscmd_cmd.fragment,
936 : &response_blob,
937 : &state->mdscmd_cmd.unkn9);
938 2 : torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
939 : "dcerpc_mdssvc_cmd failed\n");
940 :
941 2 : mds_reply = dalloc_new(state);
942 2 : torture_assert_not_null_goto(tctx, mds_reply, ret, done,
943 : "dalloc_zero failed\n");
944 :
945 2 : ok = sl_unpack(mds_reply,
946 2 : (char *)response_blob.spotlight_blob,
947 2 : response_blob.length);
948 2 : torture_assert_goto(tctx, ok, ret, done, "dalloc_add failed\n");
949 :
950 2 : torture_comment(tctx, "%s", dalloc_dump(mds_reply, 0));
951 :
952 2 : path = dalloc_get(mds_reply,
953 : "DALLOC_CTX", 0,
954 : "DALLOC_CTX", 2,
955 : "DALLOC_CTX", 0,
956 : "sl_nil_t", 1);
957 2 : torture_assert_not_null_goto(tctx, path, ret, done,
958 : "dalloc_get path failed\n");
959 :
960 2 : path_type = talloc_get_name(path);
961 :
962 2 : torture_assert_str_equal_goto(tctx, path_type, "sl_nil_t", ret, done,
963 : "Wrong dalloc object type\n");
964 :
965 2 : done:
966 2 : return ok;
967 : }
968 :
969 2354 : struct torture_suite *torture_rpc_mdssvc(TALLOC_CTX *mem_ctx)
970 : {
971 2354 : struct torture_suite *suite = torture_suite_create(
972 : mem_ctx, "mdssvc");
973 2354 : struct torture_tcase *tcase = NULL;
974 :
975 2354 : tcase = torture_suite_add_tcase(suite, "rpccmd");
976 2354 : if (tcase == NULL) {
977 0 : return NULL;
978 : }
979 2354 : torture_tcase_set_fixture(tcase,
980 : torture_rpc_mdssvc_setup,
981 : torture_rpc_mdssvc_teardown);
982 :
983 2354 : torture_tcase_add_simple_test(tcase,
984 : "open_unknown_share",
985 : test_mdssvc_open_unknown_share);
986 :
987 2354 : torture_tcase_add_simple_test(tcase,
988 : "open_spotlight_disabled",
989 : test_mdssvc_open_spotlight_disabled);
990 :
991 2354 : torture_tcase_add_simple_test(tcase,
992 : "close",
993 : test_mdssvc_close);
994 :
995 2354 : torture_tcase_add_simple_test(tcase,
996 : "null_ph",
997 : test_mdssvc_null_ph);
998 :
999 2354 : tcase = torture_suite_add_tcase(suite, "disconnect1");
1000 2354 : if (tcase == NULL) {
1001 0 : return NULL;
1002 : }
1003 2354 : torture_tcase_set_fixture(tcase,
1004 : torture_rpc_mdssvc_open,
1005 : torture_rpc_mdssvc_close);
1006 :
1007 2354 : torture_tcase_add_simple_test(tcase,
1008 : "invalid_ph_unknown1",
1009 : test_mdssvc_invalid_ph_unknown1);
1010 :
1011 2354 : tcase = torture_suite_add_tcase(suite, "disconnect2");
1012 2354 : if (tcase == NULL) {
1013 0 : return NULL;
1014 : }
1015 2354 : torture_tcase_set_fixture(tcase,
1016 : torture_rpc_mdssvc_open,
1017 : torture_rpc_mdssvc_close);
1018 :
1019 2354 : torture_tcase_add_simple_test(tcase,
1020 : "invalid_ph_cmd",
1021 : test_mdssvc_invalid_ph_cmd);
1022 :
1023 2354 : tcase = torture_suite_add_tcase(suite, "disconnect3");
1024 2354 : if (tcase == NULL) {
1025 0 : return NULL;
1026 : }
1027 2354 : torture_tcase_set_fixture(tcase,
1028 : torture_rpc_mdssvc_open,
1029 : torture_rpc_mdssvc_close);
1030 :
1031 2354 : torture_tcase_add_simple_test(tcase,
1032 : "invalid_ph_close",
1033 : test_mdssvc_invalid_ph_close);
1034 :
1035 2354 : tcase = torture_suite_add_tcase(suite, "mdscmd");
1036 2354 : if (tcase == NULL) {
1037 0 : return NULL;
1038 : }
1039 2354 : torture_tcase_set_fixture(tcase,
1040 : torture_rpc_mdssvc_open,
1041 : torture_rpc_mdssvc_close);
1042 :
1043 2354 : torture_tcase_add_simple_test(tcase,
1044 : "fetch_unknown_cnid",
1045 : test_mdssvc_fetch_attr_unknown_cnid);
1046 :
1047 2354 : torture_tcase_add_simple_test(tcase,
1048 : "mdssvc_sl_unpack_loop",
1049 : test_mdssvc_sl_unpack_loop);
1050 :
1051 2354 : torture_tcase_add_simple_test(tcase,
1052 : "sl_dict_type_safety",
1053 : test_sl_dict_type_safety);
1054 :
1055 2354 : return suite;
1056 : }
|