LCOV - code coverage report
Current view: top level - source4/torture/rpc - mdssvc.c (source / functions) Hit Total Coverage
Test: coverage report for master 70ed9daf Lines: 351 445 78.9 %
Date: 2024-01-11 09:59:51 Functions: 15 15 100.0 %

          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        2358 : struct torture_suite *torture_rpc_mdssvc(TALLOC_CTX *mem_ctx)
     970             : {
     971        2358 :         struct torture_suite *suite = torture_suite_create(
     972             :                 mem_ctx, "mdssvc");
     973        2358 :         struct torture_tcase *tcase = NULL;
     974             : 
     975        2358 :         tcase = torture_suite_add_tcase(suite, "rpccmd");
     976        2358 :         if (tcase == NULL) {
     977           0 :                 return NULL;
     978             :         }
     979        2358 :         torture_tcase_set_fixture(tcase,
     980             :                                   torture_rpc_mdssvc_setup,
     981             :                                   torture_rpc_mdssvc_teardown);
     982             : 
     983        2358 :         torture_tcase_add_simple_test(tcase,
     984             :                                       "open_unknown_share",
     985             :                                       test_mdssvc_open_unknown_share);
     986             : 
     987        2358 :         torture_tcase_add_simple_test(tcase,
     988             :                                       "open_spotlight_disabled",
     989             :                                       test_mdssvc_open_spotlight_disabled);
     990             : 
     991        2358 :         torture_tcase_add_simple_test(tcase,
     992             :                                       "close",
     993             :                                       test_mdssvc_close);
     994             : 
     995        2358 :         torture_tcase_add_simple_test(tcase,
     996             :                                       "null_ph",
     997             :                                       test_mdssvc_null_ph);
     998             : 
     999        2358 :         tcase = torture_suite_add_tcase(suite, "disconnect1");
    1000        2358 :         if (tcase == NULL) {
    1001           0 :                 return NULL;
    1002             :         }
    1003        2358 :         torture_tcase_set_fixture(tcase,
    1004             :                                   torture_rpc_mdssvc_open,
    1005             :                                   torture_rpc_mdssvc_close);
    1006             : 
    1007        2358 :         torture_tcase_add_simple_test(tcase,
    1008             :                                       "invalid_ph_unknown1",
    1009             :                                       test_mdssvc_invalid_ph_unknown1);
    1010             : 
    1011        2358 :         tcase = torture_suite_add_tcase(suite, "disconnect2");
    1012        2358 :         if (tcase == NULL) {
    1013           0 :                 return NULL;
    1014             :         }
    1015        2358 :         torture_tcase_set_fixture(tcase,
    1016             :                                   torture_rpc_mdssvc_open,
    1017             :                                   torture_rpc_mdssvc_close);
    1018             : 
    1019        2358 :         torture_tcase_add_simple_test(tcase,
    1020             :                                       "invalid_ph_cmd",
    1021             :                                       test_mdssvc_invalid_ph_cmd);
    1022             : 
    1023        2358 :         tcase = torture_suite_add_tcase(suite, "disconnect3");
    1024        2358 :         if (tcase == NULL) {
    1025           0 :                 return NULL;
    1026             :         }
    1027        2358 :         torture_tcase_set_fixture(tcase,
    1028             :                                   torture_rpc_mdssvc_open,
    1029             :                                   torture_rpc_mdssvc_close);
    1030             : 
    1031        2358 :         torture_tcase_add_simple_test(tcase,
    1032             :                                       "invalid_ph_close",
    1033             :                                       test_mdssvc_invalid_ph_close);
    1034             : 
    1035        2358 :         tcase = torture_suite_add_tcase(suite, "mdscmd");
    1036        2358 :         if (tcase == NULL) {
    1037           0 :                 return NULL;
    1038             :         }
    1039        2358 :         torture_tcase_set_fixture(tcase,
    1040             :                                   torture_rpc_mdssvc_open,
    1041             :                                   torture_rpc_mdssvc_close);
    1042             : 
    1043        2358 :         torture_tcase_add_simple_test(tcase,
    1044             :                                       "fetch_unknown_cnid",
    1045             :                                       test_mdssvc_fetch_attr_unknown_cnid);
    1046             : 
    1047        2358 :         torture_tcase_add_simple_test(tcase,
    1048             :                                       "mdssvc_sl_unpack_loop",
    1049             :                                       test_mdssvc_sl_unpack_loop);
    1050             : 
    1051        2358 :         torture_tcase_add_simple_test(tcase,
    1052             :                                       "sl_dict_type_safety",
    1053             :                                       test_sl_dict_type_safety);
    1054             : 
    1055        2358 :         return suite;
    1056             : }

Generated by: LCOV version 1.14