8f16af664766434235ca912c09bcb6b008249705
[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/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 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         struct policy_handle nullh;
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         device_id_out = device_id = generate_random();
286         unkn2_out = unkn2 = 23;
287         unkn3_out = unkn3 = 0;
288
289         ZERO_STRUCT(ph);
290         ZERO_STRUCT(nullh);
291
292         status = dcerpc_mdssvc_open(b,
293                                     tctx,
294                                     &device_id_out,
295                                     &unkn2_out,
296                                     &unkn3_out,
297                                     share_mount_path,
298                                     share_name,
299                                     share_path,
300                                     &ph);
301         torture_assert_ntstatus_ok_goto(tctx, status, ok, done,
302                                         "dcerpc_mdssvc_open failed\n");
303
304         torture_assert_u32_equal_goto(tctx, device_id, device_id_out, ok, done,
305                                       "Bad device_id\n");
306
307         torture_assert_u32_equal_goto(tctx, unkn2, unkn2_out,
308                                       ok, done, "Bad unkn2\n");
309
310         torture_assert_u32_equal_goto(tctx, unkn3, unkn3_out,
311                                       ok, done, "Bad unkn3\n");
312
313         torture_assert_goto(tctx, share_path[0] == '\0', ok, done,
314                             "Expected empty string as share path\n");
315
316         torture_assert_mem_equal_goto(tctx, &ph, &nullh,
317                                       sizeof(ph), ok, done,
318                                       "Expected all-zero policy handle\n");
319
320 done:
321         return ok;
322 }
323
324 static bool test_mdssvc_close(struct torture_context *tctx,
325                               void *data)
326 {
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;
332         uint32_t device_id;
333         uint32_t unkn2;
334         uint32_t unkn3;
335         const char *share_mount_path = NULL;
336         const char *share_name = NULL;
337         const char share_path[1025] = "";
338         uint32_t close_status;
339         DATA_BLOB ph_blob;
340         DATA_BLOB close_ph_blob;
341         NTSTATUS status;
342         bool ok = true;
343
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");
348
349         device_id = generate_random();
350         unkn2 = 23;
351         unkn3 = 0;
352
353         ZERO_STRUCT(ph);
354         ZERO_STRUCT(close_ph);
355
356         status = dcerpc_mdssvc_open(b,
357                                     tctx,
358                                     &device_id,
359                                     &unkn2,
360                                     &unkn3,
361                                     share_mount_path,
362                                     share_name,
363                                     share_path,
364                                     &ph);
365         torture_assert_ntstatus_ok_goto(tctx, status, ok, done,
366                                         "dcerpc_mdssvc_open failed\n");
367
368         status = dcerpc_mdssvc_close(b,
369                                      tctx,
370                                      &ph,
371                                      0,
372                                      device_id,
373                                      unkn2,
374                                      0,
375                                      &close_ph,
376                                      &close_status);
377         torture_assert_ntstatus_ok_goto(tctx, status, ok, done,
378                                         "dcerpc_mdssvc_open failed\n");
379
380         ph_blob = (DATA_BLOB) {
381                 .data = (uint8_t *)&ph,
382                 .length = sizeof(struct policy_handle)
383         };
384         close_ph_blob = (DATA_BLOB) {
385                 .data = (uint8_t *)&close_ph,
386                 .length = sizeof(struct policy_handle),
387         };
388
389         torture_assert_data_blob_equal(tctx, close_ph_blob, ph_blob,
390                                        "bad blob");
391
392         torture_comment(tctx, "Test close with a all-zero handle\n");
393
394         ZERO_STRUCT(ph);
395         status = dcerpc_mdssvc_close(b,
396                                      tctx,
397                                      &ph,
398                                      0,
399                                      device_id,
400                                      unkn2,
401                                      0,
402                                      &close_ph,
403                                      &close_status);
404         torture_assert_ntstatus_ok_goto(tctx, status, ok, done,
405                                         "dcerpc_mdssvc_close failed\n");
406
407         torture_assert_data_blob_equal(tctx, close_ph_blob, ph_blob,
408                                        "bad blob");
409
410 done:
411         return ok;
412 }
413
414 static bool test_mdssvc_null_ph(struct torture_context *tctx,
415                                 void *data)
416 {
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;
422         uint32_t device_id;
423         uint32_t unkn2;
424         uint32_t unkn7;
425         uint32_t cmd_status;
426         uint32_t flags;
427         NTSTATUS status;
428         bool ok = true;
429
430         device_id = generate_random();
431         unkn2 = 23;
432         unkn7 = 0;
433         cmd_status = 0;
434
435         ZERO_STRUCT(nullh);
436         ZERO_STRUCT(ph);
437
438         status = dcerpc_mdssvc_unknown1(b,
439                                         tctx,
440                                         &ph,
441                                         0,
442                                         device_id,
443                                         unkn2,
444                                         0,
445                                         geteuid(),
446                                         getegid(),
447                                         &cmd_status,
448                                         &flags,
449                                         &unkn7);
450         torture_assert_ntstatus_ok_goto(tctx, status, ok, done,
451                                         "dcerpc_mdssvc_unknown1 failed\n");
452
453         torture_assert_mem_equal_goto(tctx, &ph, &nullh,
454                                       sizeof(ph), ok, done,
455                                       "Expected all-zero policy handle\n");
456
457 done:
458         return ok;
459 }
460
461 static bool test_mdssvc_invalid_ph_unknown1(struct torture_context *tctx,
462                                             void *data)
463 {
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;
468         uint32_t device_id;
469         uint32_t unkn2;
470         uint32_t unkn7;
471         uint32_t cmd_status;
472         uint32_t flags;
473         NTSTATUS status;
474         bool ok = true;
475
476         device_id = generate_random();
477         unkn2 = 23;
478         unkn7 = 0;
479         cmd_status = 0;
480
481         ZERO_STRUCT(ph);
482         ph.uuid = GUID_random();
483
484         status = dcerpc_mdssvc_unknown1(b,
485                                         tctx,
486                                         &ph,
487                                         0,
488                                         device_id,
489                                         unkn2,
490                                         0,
491                                         geteuid(),
492                                         getegid(),
493                                         &cmd_status,
494                                         &flags,
495                                         &unkn7);
496         torture_assert_ntstatus_equal_goto(
497                 tctx, status, NT_STATUS_RPC_PROTOCOL_ERROR, ok, done,
498                 "dcerpc_mdssvc_unknown1 failed\n");
499
500 done:
501         return ok;
502 }
503
504 static bool test_mdssvc_invalid_ph_cmd(struct torture_context *tctx,
505                                        void *data)
506 {
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;
513         uint32_t device_id;
514         uint32_t unkn2;
515         uint32_t unkn9;
516         uint32_t fragment;
517         uint32_t flags;
518         NTSTATUS status;
519         bool ok = true;
520
521         device_id = generate_random();
522         unkn2 = 23;
523         unkn9 = 0;
524         fragment = 0;
525         flags = UINT32_C(0x6b000001);
526
527         ZERO_STRUCT(ph);
528         ph.uuid = GUID_random();
529
530         request_blob.spotlight_blob = talloc_array(state,
531                                                    uint8_t,
532                                                    0);
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;
538
539         response_blob.spotlight_blob = talloc_array(state,
540                                                     uint8_t,
541                                                     0);
542         torture_assert_not_null_goto(tctx, response_blob.spotlight_blob,
543                                      ok, done, "dalloc_zero failed\n");
544         response_blob.size = 0;
545
546         status =  dcerpc_mdssvc_cmd(b,
547                                     state,
548                                     &ph,
549                                     0,
550                                     device_id,
551                                     unkn2,
552                                     0,
553                                     flags,
554                                     request_blob,
555                                     0,
556                                     64 * 1024,
557                                     1,
558                                     64 * 1024,
559                                     0,
560                                     0,
561                                     &fragment,
562                                     &response_blob,
563                                     &unkn9);
564         torture_assert_ntstatus_equal_goto(
565                 tctx, status, NT_STATUS_RPC_PROTOCOL_ERROR, ok, done,
566                 "dcerpc_mdssvc_unknown1 failed\n");
567
568 done:
569         return ok;
570 }
571
572 static bool test_mdssvc_invalid_ph_close(struct torture_context *tctx,
573                                          void *data)
574 {
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;
579         uint32_t device_id;
580         uint32_t unkn2;
581         uint32_t close_status;
582         NTSTATUS status;
583         bool ok = true;
584
585         device_id = generate_random();
586         unkn2 = 23;
587         close_status = 0;
588
589         ZERO_STRUCT(ph);
590         ph.uuid = GUID_random();
591
592         status = dcerpc_mdssvc_close(b,
593                                      state,
594                                      &ph,
595                                      0,
596                                      device_id,
597                                      unkn2,
598                                      0,
599                                      &ph,
600                                      &close_status);
601         torture_assert_ntstatus_equal_goto(
602                 tctx, status, NT_STATUS_RPC_PROTOCOL_ERROR, ok, done,
603                 "dcerpc_mdssvc_unknown1 failed\n");
604
605 done:
606         return ok;
607 }
608
609 /*
610  * Test fetchAttributes with unknown CNID
611  */
612 static bool test_mdssvc_fetch_attr_unknown_cnid(struct torture_context *tctx,
613                                                 void *data)
614 {
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;
627         void *path = NULL;
628         const char *path_type = NULL;
629         uint64_t ino64;
630         NTSTATUS status;
631         ssize_t len;
632         int ret;
633         bool ok = true;
634
635         d = dalloc_new(state);
636         torture_assert_not_null_goto(tctx, d, ret, done, "dalloc_new failed\n");
637
638         array = dalloc_zero(d, sl_array_t);
639         torture_assert_not_null_goto(tctx, array, ret, done,
640                                      "dalloc_zero failed\n");
641
642         ret = dalloc_add(d, array, sl_array_t);
643         torture_assert_goto(tctx, ret == 0, ret, done, "dalloc_add failed\n");
644
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");
648
649         ret = dalloc_add(array, cmd_array, sl_array_t);
650         torture_assert_goto(tctx, ret == 0, ret, done, "dalloc_add failed\n");
651
652         ret = dalloc_stradd(cmd_array, "fetchAttributes:forOIDArray:context:");
653         torture_assert_goto(tctx, ret == 0, ret, done, "dalloc_stradd failed\n");
654
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 *");
659
660         uint64var[0] = 0x500a;
661         uint64var[1] = 0;
662
663         ret = dalloc_add(cmd_array, &uint64var[0], uint64_t *);
664         torture_assert_goto(tctx, ret == 0, ret, done, "dalloc_add failed\n");
665
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");
669
670         ret = dalloc_add(array, attr_array, sl_array_t);
671         torture_assert_goto(tctx, ret == 0, ret, done, "dalloc_add failed\n");
672
673         ret = dalloc_stradd(attr_array, "kMDItemPath");
674         torture_assert_goto(tctx, ret == 0, ret, done, "dalloc_stradd failed\n");
675
676         /* CNIDs */
677         cnids = talloc_zero(array, sl_cnids_t);
678         torture_assert_not_null_goto(tctx, cnids, ret, done,
679                                      "talloc_zero failed\n");
680
681         cnids->ca_cnids = dalloc_new(cnids);
682         torture_assert_not_null_goto(tctx, cnids->ca_cnids, ret, done,
683                                      "dalloc_new failed\n");
684
685         cnids->ca_unkn1 = 0xadd;
686         cnids->ca_context = 0x6b000020;
687
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");
692
693         ret = dalloc_add(array, cnids, sl_cnids_t);
694         torture_assert_goto(tctx, ret == 0, ret, done, "dalloc_add failed\n");
695
696         request_blob.spotlight_blob = talloc_array(state,
697                                                    uint8_t,
698                                                    max_fragment_size);
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;
702
703         response_blob.spotlight_blob = talloc_array(state,
704                                                     uint8_t,
705                                                     max_fragment_size);
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;
709
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");
712
713         request_blob.length = len;
714         request_blob.size = len;
715
716         status =  dcerpc_mdssvc_cmd(b,
717                                     state,
718                                     &state->ph,
719                                     0,
720                                     state->dev,
721                                     state->mdscmd_open.unkn2,
722                                     0,
723                                     state->flags,
724                                     request_blob,
725                                     0,
726                                     max_fragment_size,
727                                     1,
728                                     max_fragment_size,
729                                     0,
730                                     0,
731                                     &state->mdscmd_cmd.fragment,
732                                     &response_blob,
733                                     &state->mdscmd_cmd.unkn9);
734         torture_assert_ntstatus_ok_goto(tctx, status, ret, done,
735                                         "dcerpc_mdssvc_cmd failed\n");
736
737         mds_reply = dalloc_new(state);
738         torture_assert_not_null_goto(tctx, mds_reply, ret, done,
739                                      "dalloc_zero failed\n");
740
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");
745
746         torture_comment(tctx, "%s", dalloc_dump(mds_reply, 0));
747
748         path = dalloc_get(mds_reply,
749                           "DALLOC_CTX", 0,
750                           "DALLOC_CTX", 2,
751                           "DALLOC_CTX", 0,
752                           "sl_nil_t", 1);
753         torture_assert_not_null_goto(tctx, path, ret, done,
754                                      "dalloc_get path failed\n");
755
756         path_type = talloc_get_name(path);
757
758         torture_assert_str_equal_goto(tctx, path_type, "sl_nil_t", ret, done,
759                                       "Wrong dalloc object type\n");
760
761 done:
762         return ok;
763 }
764
765 struct torture_suite *torture_rpc_mdssvc(TALLOC_CTX *mem_ctx)
766 {
767         struct torture_suite *suite = torture_suite_create(
768                 mem_ctx, "mdssvc");
769         struct torture_tcase *tcase = NULL;
770
771         tcase = torture_suite_add_tcase(suite, "rpccmd");
772         if (tcase == NULL) {
773                 return NULL;
774         }
775         torture_tcase_set_fixture(tcase,
776                                   torture_rpc_mdssvc_setup,
777                                   torture_rpc_mdssvc_teardown);
778
779         torture_tcase_add_simple_test(tcase,
780                                       "open_unknown_share",
781                                       test_mdssvc_open_unknown_share);
782
783         torture_tcase_add_simple_test(tcase,
784                                       "open_spotlight_disabled",
785                                       test_mdssvc_open_spotlight_disabled);
786
787         torture_tcase_add_simple_test(tcase,
788                                       "close",
789                                       test_mdssvc_close);
790
791         torture_tcase_add_simple_test(tcase,
792                                       "null_ph",
793                                       test_mdssvc_null_ph);
794
795         tcase = torture_suite_add_tcase(suite, "disconnect1");
796         if (tcase == NULL) {
797                 return NULL;
798         }
799         torture_tcase_set_fixture(tcase,
800                                   torture_rpc_mdssvc_open,
801                                   torture_rpc_mdssvc_close);
802
803         torture_tcase_add_simple_test(tcase,
804                                       "invalid_ph_unknown1",
805                                       test_mdssvc_invalid_ph_unknown1);
806
807         tcase = torture_suite_add_tcase(suite, "disconnect2");
808         if (tcase == NULL) {
809                 return NULL;
810         }
811         torture_tcase_set_fixture(tcase,
812                                   torture_rpc_mdssvc_open,
813                                   torture_rpc_mdssvc_close);
814
815         torture_tcase_add_simple_test(tcase,
816                                       "invalid_ph_cmd",
817                                       test_mdssvc_invalid_ph_cmd);
818
819         tcase = torture_suite_add_tcase(suite, "disconnect3");
820         if (tcase == NULL) {
821                 return NULL;
822         }
823         torture_tcase_set_fixture(tcase,
824                                   torture_rpc_mdssvc_open,
825                                   torture_rpc_mdssvc_close);
826
827         torture_tcase_add_simple_test(tcase,
828                                       "invalid_ph_close",
829                                       test_mdssvc_invalid_ph_close);
830
831         tcase = torture_suite_add_tcase(suite, "mdscmd");
832         if (tcase == NULL) {
833                 return NULL;
834         }
835         torture_tcase_set_fixture(tcase,
836                                   torture_rpc_mdssvc_open,
837                                   torture_rpc_mdssvc_close);
838
839         torture_tcase_add_simple_test(tcase,
840                                       "fetch_unknown_cnid",
841                                       test_mdssvc_fetch_attr_unknown_cnid);
842
843         return suite;
844 }