9fd7278c8e8625e17c6b8a3ec7c0cf02c5c33e27
[samba.git] / source4 / torture / rpc / mdssvc.c
1 /*
2    Unix SMB/CIFS implementation.
3    test suite for the mdssvc RPC serice
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/popt_common.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 static bool torture_rpc_mdssvc_setup(struct torture_context *tctx,
58                                      void **data)
59 {
60         struct torture_mdsscv_state *state = NULL;
61         NTSTATUS status;
62
63         state = talloc_zero(tctx, struct torture_mdsscv_state);
64         if (state == NULL) {
65                 return false;
66         }
67         *data = state;
68
69         status = torture_rpc_connection(tctx, &state->p, &ndr_table_mdssvc);
70         torture_assert_ntstatus_ok(tctx, status,  "Error connecting to server");
71
72         return true;
73 }
74
75 static bool torture_rpc_mdssvc_teardown(struct torture_context *tctx,
76                                         void *data)
77 {
78         struct torture_mdsscv_state *state = talloc_get_type_abort(
79                 data, struct torture_mdsscv_state);
80
81         TALLOC_FREE(state->p);
82         TALLOC_FREE(state);
83         return true;
84 }
85
86 static bool torture_rpc_mdssvc_open(struct torture_context *tctx,
87                                     void **data)
88 {
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;
93         NTSTATUS status;
94         bool ok = true;
95
96         state = talloc_zero(tctx, struct torture_mdsscv_state);
97         if (state == NULL) {
98                 return false;
99         }
100         *data = state;
101
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;
105
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");
110
111         state->dev = generate_random();
112         state->mdscmd_open.unkn2 = 23;
113         state->mdscmd_open.unkn3 = 0;
114
115         ZERO_STRUCT(state->ph);
116
117         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                                     state->mdscmd_open.share_path,
125                                     &state->ph);
126         torture_assert_ntstatus_ok_goto(tctx, status, ok, done,
127                                         "dcerpc_mdssvc_open failed\n");
128
129         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         torture_assert_ntstatus_ok_goto(tctx, status, ok, done,
142                                         "dcerpc_mdssvc_unknown1 failed\n");
143
144 done:
145         if (!ok) {
146                 (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                 ZERO_STRUCT(state);
156         }
157         return ok;
158 }
159
160 static bool torture_rpc_mdssvc_close(struct torture_context *tctx,
161                                      void *data)
162 {
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;
166         NTSTATUS status;
167         bool ok = true;
168
169         torture_comment(tctx, "test_teardown_mdssvc_disconnect\n");
170
171         status = dcerpc_mdssvc_close(b,
172                                      state,
173                                      state->ph,
174                                      0,
175                                      state->dev,
176                                      state->mdscmd_open.unkn2,
177                                      0,
178                                      &state->ph,
179                                      &state->mdscmd_close.status);
180         torture_assert_ntstatus_ok_goto(tctx, status, ok, done,
181                                         "dcerpc_mdssvc_close failed\n");
182
183         ZERO_STRUCT(state);
184
185 done:
186         return ok;
187 }
188
189 /*
190  * Test unknown share name
191  */
192 static bool test_mdssvc_open_unknown_share(struct torture_context *tctx,
193                                            void *data)
194 {
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;
200         uint32_t device_id;
201         uint32_t unkn2;
202         uint32_t unkn3;
203         uint32_t device_id_out;
204         uint32_t unkn2_out;
205         uint32_t unkn3_out;
206         const char *share_mount_path = NULL;
207         const char *share_name = NULL;
208         const char share_path[1025] = "X";
209         NTSTATUS status;
210         bool ok = true;
211
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");
216
217         device_id_out = device_id = generate_random();
218         unkn2_out = unkn2 = generate_random();
219         unkn3_out = unkn3 = generate_random();
220
221         ZERO_STRUCT(ph);
222         ZERO_STRUCT(nullh);
223
224         status = dcerpc_mdssvc_open(b,
225                                     tctx,
226                                     &device_id_out,
227                                     &unkn2_out,
228                                     &unkn3_out,
229                                     share_mount_path,
230                                     share_name,
231                                     share_path,
232                                     &ph);
233
234         torture_assert_ntstatus_ok_goto(tctx, status, ok, done,
235                                         "dcerpc_mdssvc_open failed\n");
236
237         torture_assert_u32_equal_goto(tctx, device_id_out, device_id, ok, done,
238                                       "Bad device_id\n");
239
240         torture_assert_u32_equal_goto(tctx, unkn2_out, unkn2, ok, done,
241                                       "Bad unkn2\n");
242
243         torture_assert_u32_equal_goto(tctx, unkn3_out, unkn3, ok, done,
244                                       "Bad unkn3\n");
245
246         torture_assert_goto(tctx, share_path[0] == '\0', ok, done,
247                             "Expected empty string as share path\n");
248
249         torture_assert_mem_equal_goto(tctx, &ph, &nullh,
250                                       sizeof(ph), ok, done,
251                                       "Expected all-zero policy handle\n");
252
253 done:
254         return ok;
255 }
256
257 /*
258  * Test on a share where Spotlight is not enabled
259  */
260 static bool test_mdssvc_open_spotlight_disabled(struct torture_context *tctx,
261                                                 void *data)
262 {
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         const char *localdir = NULL;
268         uint32_t device_id;
269         uint32_t unkn2;
270         uint32_t unkn3;
271         uint32_t device_id_out;
272         uint32_t unkn2_out;
273         uint32_t unkn3_out;
274         const char *share_mount_path = NULL;
275         const char *share_name = NULL;
276         const char share_path[1025] = "";
277         NTSTATUS status;
278         bool ok = true;
279
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");
284
285         localdir = torture_setting_string(
286                 tctx, "no_spotlight_localdir", NULL);
287         torture_assert_not_null_goto(
288                 tctx, localdir, ok, done,
289                 "need 'no_spotlight_localdir' torture option \n");
290
291         device_id_out = device_id = generate_random();
292         unkn2_out = unkn2 = 23;
293         unkn3_out = unkn3 = 0;
294
295         ZERO_STRUCT(ph);
296
297         status = dcerpc_mdssvc_open(b,
298                                     tctx,
299                                     &device_id_out,
300                                     &unkn2_out,
301                                     &unkn3_out,
302                                     share_mount_path,
303                                     share_name,
304                                     share_path,
305                                     &ph);
306         torture_assert_ntstatus_ok_goto(tctx, status, ok, done,
307                                         "dcerpc_mdssvc_open failed\n");
308
309         torture_assert_u32_equal_goto(tctx, device_id, device_id_out, ok, done,
310                                       "Bad device_id\n");
311
312         torture_assert_u32_equal_goto(tctx, unkn2, unkn2_out,
313                                       ok, done, "Bad unkn2\n");
314
315         torture_assert_u32_equal_goto(tctx, unkn3, unkn3_out,
316                                       ok, done, "Bad unkn3\n");
317
318         torture_assert_str_equal_goto(tctx, share_path, localdir, ok, done,
319                                       "Wrong share path\n");
320
321 done:
322         return ok;
323 }
324
325 static bool test_mdssvc_close(struct torture_context *tctx,
326                               void *data)
327 {
328         struct torture_mdsscv_state *state = talloc_get_type_abort(
329                 data, struct torture_mdsscv_state);
330         struct dcerpc_binding_handle *b = state->p->binding_handle;
331         struct policy_handle ph;
332         struct policy_handle close_ph;
333         uint32_t device_id;
334         uint32_t unkn2;
335         uint32_t unkn3;
336         const char *share_mount_path = NULL;
337         const char *share_name = NULL;
338         const char share_path[1025] = "";
339         uint32_t close_status;
340         DATA_BLOB ph_blob;
341         DATA_BLOB close_ph_blob;
342         NTSTATUS status;
343         bool ok = true;
344
345         share_name = torture_setting_string(
346                 tctx, "spotlight_share", "spotlight");
347         share_mount_path = torture_setting_string(
348                 tctx, "share_mount_path", "/foo/bar");
349
350         device_id = generate_random();
351         unkn2 = 23;
352         unkn3 = 0;
353
354         ZERO_STRUCT(ph);
355         ZERO_STRUCT(close_ph);
356
357         status = dcerpc_mdssvc_open(b,
358                                     tctx,
359                                     &device_id,
360                                     &unkn2,
361                                     &unkn3,
362                                     share_mount_path,
363                                     share_name,
364                                     share_path,
365                                     &ph);
366         torture_assert_ntstatus_ok_goto(tctx, status, ok, done,
367                                         "dcerpc_mdssvc_open failed\n");
368
369         status = dcerpc_mdssvc_close(b,
370                                      tctx,
371                                      ph,
372                                      0,
373                                      device_id,
374                                      unkn2,
375                                      0,
376                                      &close_ph,
377                                      &close_status);
378         torture_assert_ntstatus_ok_goto(tctx, status, ok, done,
379                                         "dcerpc_mdssvc_open failed\n");
380
381         ph_blob = (DATA_BLOB) {
382                 .data = (uint8_t *)&ph,
383                 .length = sizeof(struct policy_handle)
384         };
385         close_ph_blob = (DATA_BLOB) {
386                 .data = (uint8_t *)&close_ph,
387                 .length = sizeof(struct policy_handle),
388         };
389
390         torture_assert_data_blob_equal(tctx, close_ph_blob, ph_blob,
391                                        "bad blob");
392
393         torture_comment(tctx, "Test close with a all-zero handle\n");
394
395         ZERO_STRUCT(ph);
396         status = dcerpc_mdssvc_close(b,
397                                      tctx,
398                                      ph,
399                                      0,
400                                      device_id,
401                                      unkn2,
402                                      0,
403                                      &close_ph,
404                                      &close_status);
405         torture_assert_ntstatus_ok_goto(tctx, status, ok, done,
406                                         "dcerpc_mdssvc_open failed\n");
407
408         torture_assert_data_blob_equal(tctx, close_ph_blob, ph_blob,
409                                        "bad blob");
410
411 done:
412         return ok;
413 }
414
415 static bool test_mdssvc_null_ph(struct torture_context *tctx,
416                                 void *data)
417 {
418         struct torture_mdsscv_state *state = talloc_get_type_abort(
419                 data, struct torture_mdsscv_state);
420         struct dcerpc_binding_handle *b = state->p->binding_handle;
421         struct policy_handle nullh;
422         struct policy_handle ph;
423         uint32_t device_id;
424         uint32_t unkn2;
425         uint32_t unkn7;
426         uint32_t cmd_status;
427         uint32_t flags;
428         NTSTATUS status;
429         bool ok = true;
430
431         device_id = generate_random();
432         unkn2 = 23;
433         unkn7 = 0;
434         cmd_status = 0;
435
436         ZERO_STRUCT(nullh);
437         ZERO_STRUCT(ph);
438
439         status = dcerpc_mdssvc_unknown1(b,
440                                         tctx,
441                                         ph,
442                                         0,
443                                         device_id,
444                                         unkn2,
445                                         0,
446                                         geteuid(),
447                                         getegid(),
448                                         &cmd_status,
449                                         &flags,
450                                         &unkn7);
451         torture_assert_ntstatus_ok_goto(tctx, status, ok, done,
452                                         "dcerpc_mdssvc_unknown1 failed\n");
453
454         torture_assert_mem_equal_goto(tctx, &ph, &nullh,
455                                       sizeof(ph), ok, done,
456                                       "Expected all-zero policy handle\n");
457
458 done:
459         return ok;
460 }
461
462 static bool test_mdssvc_invalid_ph_unknown1(struct torture_context *tctx,
463                                             void *data)
464 {
465         struct torture_mdsscv_state *state = talloc_get_type_abort(
466                 data, struct torture_mdsscv_state);
467         struct dcerpc_binding_handle *b = state->p->binding_handle;
468         struct policy_handle ph;
469         uint32_t device_id;
470         uint32_t unkn2;
471         uint32_t unkn7;
472         uint32_t cmd_status;
473         uint32_t flags;
474         NTSTATUS status;
475         bool ok = true;
476
477         device_id = generate_random();
478         unkn2 = 23;
479         unkn7 = 0;
480         cmd_status = 0;
481
482         ZERO_STRUCT(ph);
483         ph.uuid = GUID_random();
484
485         status = dcerpc_mdssvc_unknown1(b,
486                                         tctx,
487                                         ph,
488                                         0,
489                                         device_id,
490                                         unkn2,
491                                         0,
492                                         geteuid(),
493                                         getegid(),
494                                         &cmd_status,
495                                         &flags,
496                                         &unkn7);
497         torture_assert_ntstatus_equal_goto(
498                 tctx, status, NT_STATUS_RPC_PROTOCOL_ERROR, ok, done,
499                 "dcerpc_mdssvc_unknown1 failed\n");
500
501 done:
502         return ok;
503 }
504
505 static bool test_mdssvc_invalid_ph_cmd(struct torture_context *tctx,
506                                        void *data)
507 {
508         struct torture_mdsscv_state *state = talloc_get_type_abort(
509                 data, struct torture_mdsscv_state);
510         struct dcerpc_binding_handle *b = state->p->binding_handle;
511         struct policy_handle ph;
512         struct mdssvc_blob request_blob;
513         struct mdssvc_blob response_blob;
514         uint32_t device_id;
515         uint32_t unkn2;
516         uint32_t unkn9;
517         uint32_t fragment;
518         uint32_t flags;
519         NTSTATUS status;
520         bool ok = true;
521
522         device_id = generate_random();
523         unkn2 = 23;
524         unkn9 = 0;
525         fragment = 0;
526         flags = UINT32_C(0x6b000001);
527
528         ZERO_STRUCT(ph);
529         ph.uuid = GUID_random();
530
531         request_blob.spotlight_blob = talloc_array(state,
532                                                    uint8_t,
533                                                    0);
534         torture_assert_not_null_goto(tctx, request_blob.spotlight_blob,
535                                      ok, done, "dalloc_zero failed\n");
536         request_blob.size = 0;
537         request_blob.length = 0;
538         request_blob.size = 0;
539
540         response_blob.spotlight_blob = talloc_array(state,
541                                                     uint8_t,
542                                                     0);
543         torture_assert_not_null_goto(tctx, response_blob.spotlight_blob,
544                                      ok, done, "dalloc_zero failed\n");
545         response_blob.size = 0;
546
547         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         torture_assert_ntstatus_equal_goto(
566                 tctx, status, NT_STATUS_RPC_PROTOCOL_ERROR, ok, done,
567                 "dcerpc_mdssvc_unknown1 failed\n");
568
569 done:
570         return ok;
571 }
572
573 static bool test_mdssvc_invalid_ph_close(struct torture_context *tctx,
574                                          void *data)
575 {
576         struct torture_mdsscv_state *state = talloc_get_type_abort(
577                 data, struct torture_mdsscv_state);
578         struct dcerpc_binding_handle *b = state->p->binding_handle;
579         struct policy_handle ph;
580         uint32_t device_id;
581         uint32_t unkn2;
582         uint32_t close_status;
583         NTSTATUS status;
584         bool ok = true;
585
586         device_id = generate_random();
587         unkn2 = 23;
588         close_status = 0;
589
590         ZERO_STRUCT(ph);
591         ph.uuid = GUID_random();
592
593         status = dcerpc_mdssvc_close(b,
594                                      state,
595                                      ph,
596                                      0,
597                                      device_id,
598                                      unkn2,
599                                      0,
600                                      &ph,
601                                      &close_status);
602         torture_assert_ntstatus_equal_goto(
603                 tctx, status, NT_STATUS_RPC_PROTOCOL_ERROR, ok, done,
604                 "dcerpc_mdssvc_unknown1 failed\n");
605
606 done:
607         return ok;
608 }
609
610 /*
611  * Test fetchAttributes with unknown CNID
612  */
613 static bool test_mdssvc_fetch_attr_unknown_cnid(struct torture_context *tctx,
614                                                 void *data)
615 {
616         struct torture_mdsscv_state *state = talloc_get_type_abort(
617                 data, struct torture_mdsscv_state);
618         struct dcerpc_binding_handle *b = state->p->binding_handle;
619         uint32_t max_fragment_size = 64 * 1024;
620         struct mdssvc_blob request_blob;
621         struct mdssvc_blob response_blob;
622         DALLOC_CTX *d = NULL, *mds_reply = NULL;
623         uint64_t *uint64var = NULL;
624         sl_array_t *array = NULL;
625         sl_array_t *cmd_array = NULL;
626         sl_array_t *attr_array = NULL;
627         sl_cnids_t *cnids = NULL;
628         void *path = NULL;
629         const char *path_type = NULL;
630         uint64_t ino64;
631         NTSTATUS status;
632         ssize_t len;
633         int ret;
634         bool ok = true;
635
636         d = dalloc_new(state);
637         torture_assert_not_null_goto(tctx, d, ret, done, "dalloc_new failed\n");
638
639         array = dalloc_zero(d, sl_array_t);
640         torture_assert_not_null_goto(tctx, array, ret, done,
641                                      "dalloc_zero failed\n");
642
643         ret = dalloc_add(d, array, sl_array_t);
644         torture_assert_goto(tctx, ret == 0, ret, done, "dalloc_add failed\n");
645
646         cmd_array = dalloc_zero(d, sl_array_t);
647         torture_assert_not_null_goto(tctx, cmd_array, ret, done,
648                                      "dalloc_zero failed\n");
649
650         ret = dalloc_add(array, cmd_array, sl_array_t);
651         torture_assert_goto(tctx, ret == 0, ret, done, "dalloc_add failed\n");
652
653         ret = dalloc_stradd(cmd_array, "fetchAttributes:forOIDArray:context:");
654         torture_assert_goto(tctx, ret == 0, ret, done, "dalloc_stradd failed\n");
655
656         uint64var = talloc_zero_array(cmd_array, uint64_t, 2);
657         torture_assert_not_null_goto(tctx, uint64var, ret, done,
658                                      "talloc_zero_array failed\n");
659         talloc_set_name(uint64var, "uint64_t *");
660
661         uint64var[0] = 0x500a;
662         uint64var[1] = 0;
663
664         ret = dalloc_add(cmd_array, &uint64var[0], uint64_t *);
665         torture_assert_goto(tctx, ret == 0, ret, done, "dalloc_add failed\n");
666
667         attr_array = dalloc_zero(d, sl_array_t);
668         torture_assert_not_null_goto(tctx, attr_array, ret, done,
669                                      "dalloc_zero failed\n");
670
671         ret = dalloc_add(array, attr_array, sl_array_t);
672         torture_assert_goto(tctx, ret == 0, ret, done, "dalloc_add failed\n");
673
674         ret = dalloc_stradd(attr_array, "kMDItemPath");
675         torture_assert_goto(tctx, ret == 0, ret, done, "dalloc_stradd failed\n");
676
677         /* CNIDs */
678         cnids = talloc_zero(array, sl_cnids_t);
679         torture_assert_not_null_goto(tctx, cnids, ret, done,
680                                      "talloc_zero failed\n");
681
682         cnids->ca_cnids = dalloc_new(cnids);
683         torture_assert_not_null_goto(tctx, cnids->ca_cnids, ret, done,
684                                      "dalloc_new failed\n");
685
686         cnids->ca_unkn1 = 0xadd;
687         cnids->ca_context = 0x6b000020;
688
689         ino64 = UINT64_C(64382947389618974);
690         ret = dalloc_add_copy(cnids->ca_cnids, &ino64, uint64_t);
691         torture_assert_goto(tctx, ret == 0, ret, done,
692                             "dalloc_add_copy failed\n");
693
694         ret = dalloc_add(array, cnids, sl_cnids_t);
695         torture_assert_goto(tctx, ret == 0, ret, done, "dalloc_add failed\n");
696
697         request_blob.spotlight_blob = talloc_array(state,
698                                                    uint8_t,
699                                                    max_fragment_size);
700         torture_assert_not_null_goto(tctx, request_blob.spotlight_blob,
701                                      ret, done, "dalloc_zero failed\n");
702         request_blob.size = max_fragment_size;
703
704         response_blob.spotlight_blob = talloc_array(state,
705                                                     uint8_t,
706                                                     max_fragment_size);
707         torture_assert_not_null_goto(tctx, response_blob.spotlight_blob,
708                                      ret, done, "dalloc_zero failed\n");
709         response_blob.size = max_fragment_size;
710
711         len = sl_pack(d, (char *)request_blob.spotlight_blob, request_blob.size);
712         torture_assert_goto(tctx, len != -1, ret, done, "sl_pack failed\n");
713
714         request_blob.length = len;
715         request_blob.size = len;
716
717         status =  dcerpc_mdssvc_cmd(b,
718                                     state,
719                                     state->ph,
720                                     0,
721                                     state->dev,
722                                     state->mdscmd_open.unkn2,
723                                     0,
724                                     state->flags,
725                                     request_blob,
726                                     0,
727                                     max_fragment_size,
728                                     1,
729                                     max_fragment_size,
730                                     0,
731                                     0,
732                                     &state->mdscmd_cmd.fragment,
733                                     &response_blob,
734                                     &state->mdscmd_cmd.unkn9);
735         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
736                                         "dcerpc_mdssvc_cmd failed\n");
737
738         mds_reply = dalloc_new(state);
739         torture_assert_not_null_goto(tctx, mds_reply, ret, done,
740                                      "dalloc_zero failed\n");
741
742         ok = sl_unpack(mds_reply,
743                        (char *)response_blob.spotlight_blob,
744                        response_blob.length);
745         torture_assert_goto(tctx, ok, ret, done, "dalloc_add failed\n");
746
747         torture_comment(tctx, "%s", dalloc_dump(mds_reply, 0));
748
749         path = dalloc_get(mds_reply,
750                           "DALLOC_CTX", 0,
751                           "DALLOC_CTX", 2,
752                           "DALLOC_CTX", 0,
753                           "sl_nil_t", 1);
754         torture_assert_not_null_goto(tctx, path, ret, done,
755                                      "dalloc_get path failed\n");
756
757         path_type = talloc_get_name(path);
758
759         torture_assert_str_equal_goto(tctx, path_type, "sl_nil_t", ret, done,
760                                       "Wrong dalloc object type\n");
761
762 done:
763         return ok;
764 }
765
766 struct torture_suite *torture_rpc_mdssvc(TALLOC_CTX *mem_ctx)
767 {
768         struct torture_suite *suite = torture_suite_create(
769                 mem_ctx, "mdssvc");
770         struct torture_tcase *tcase = NULL;
771
772         tcase = torture_suite_add_tcase(suite, "rpccmd");
773         if (tcase == NULL) {
774                 return NULL;
775         }
776         torture_tcase_set_fixture(tcase,
777                                   torture_rpc_mdssvc_setup,
778                                   torture_rpc_mdssvc_teardown);
779
780         torture_tcase_add_simple_test(tcase,
781                                       "open_unknown_share",
782                                       test_mdssvc_open_unknown_share);
783
784         torture_tcase_add_simple_test(tcase,
785                                       "open_spotlight_disabled",
786                                       test_mdssvc_open_spotlight_disabled);
787
788         torture_tcase_add_simple_test(tcase,
789                                       "close",
790                                       test_mdssvc_close);
791
792         torture_tcase_add_simple_test(tcase,
793                                       "null_ph",
794                                       test_mdssvc_null_ph);
795
796         tcase = torture_suite_add_tcase(suite, "disconnect1");
797         if (tcase == NULL) {
798                 return NULL;
799         }
800         torture_tcase_set_fixture(tcase,
801                                   torture_rpc_mdssvc_open,
802                                   torture_rpc_mdssvc_close);
803
804         torture_tcase_add_simple_test(tcase,
805                                       "invalid_ph_unknown1",
806                                       test_mdssvc_invalid_ph_unknown1);
807
808         tcase = torture_suite_add_tcase(suite, "disconnect2");
809         if (tcase == NULL) {
810                 return NULL;
811         }
812         torture_tcase_set_fixture(tcase,
813                                   torture_rpc_mdssvc_open,
814                                   torture_rpc_mdssvc_close);
815
816         torture_tcase_add_simple_test(tcase,
817                                       "invalid_ph_cmd",
818                                       test_mdssvc_invalid_ph_cmd);
819
820         tcase = torture_suite_add_tcase(suite, "disconnect3");
821         if (tcase == NULL) {
822                 return NULL;
823         }
824         torture_tcase_set_fixture(tcase,
825                                   torture_rpc_mdssvc_open,
826                                   torture_rpc_mdssvc_close);
827
828         torture_tcase_add_simple_test(tcase,
829                                       "invalid_ph_close",
830                                       test_mdssvc_invalid_ph_close);
831
832         tcase = torture_suite_add_tcase(suite, "mdscmd");
833         if (tcase == NULL) {
834                 return NULL;
835         }
836         torture_tcase_set_fixture(tcase,
837                                   torture_rpc_mdssvc_open,
838                                   torture_rpc_mdssvc_close);
839
840         torture_tcase_add_simple_test(tcase,
841                                       "fetch_unknown_cnid",
842                                       test_mdssvc_fetch_attr_unknown_cnid);
843
844         return suite;
845 }