LCOV - code coverage report
Current view: top level - source4/torture/rpc - svcctl.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 338 476 71.0 %
Date: 2024-02-28 12:06:22 Functions: 18 18 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    test suite for svcctl rpc operations
       4             : 
       5             :    Copyright (C) Jelmer Vernooij 2004
       6             :    Copyright (C) Guenther Deschner 2008,2009,2020
       7             : 
       8             :    This program is free software; you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation; either version 3 of the License, or
      11             :    (at your option) any later version.
      12             : 
      13             :    This program is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             : 
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             : */
      21             : 
      22             : #include "includes.h"
      23             : #include "librpc/gen_ndr/ndr_svcctl_c.h"
      24             : #include "librpc/gen_ndr/ndr_svcctl.h"
      25             : #include "librpc/gen_ndr/ndr_security.h"
      26             : #include "torture/rpc/torture_rpc.h"
      27             : #include "param/param.h"
      28             : 
      29             : #define TORTURE_DEFAULT_SERVICE "Spooler"
      30             : 
      31          56 : static bool test_OpenSCManager(struct dcerpc_binding_handle *b,
      32             :                                struct torture_context *tctx,
      33             :                                struct policy_handle *h)
      34             : {
      35           0 :         struct svcctl_OpenSCManagerW r;
      36             : 
      37          56 :         r.in.MachineName = NULL;
      38          56 :         r.in.DatabaseName = NULL;
      39          56 :         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
      40          56 :         r.out.handle = h;
      41             : 
      42          56 :         torture_assert_ntstatus_ok(tctx,
      43             :                                    dcerpc_svcctl_OpenSCManagerW_r(b, tctx, &r),
      44             :                                    "OpenSCManager failed!");
      45             : 
      46          56 :         return true;
      47             : }
      48             : 
      49          80 : static bool test_CloseServiceHandle(struct dcerpc_binding_handle *b,
      50             :                                     struct torture_context *tctx,
      51             :                                     struct policy_handle *h)
      52             : {
      53           0 :         struct svcctl_CloseServiceHandle r;
      54             : 
      55          80 :         r.in.handle = h;
      56          80 :         r.out.handle = h;
      57          80 :         torture_assert_ntstatus_ok(tctx,
      58             :                                    dcerpc_svcctl_CloseServiceHandle_r(b, tctx, &r),
      59             :                                    "CloseServiceHandle failed");
      60             : 
      61          80 :         return true;
      62             : }
      63             : 
      64          48 : static bool test_OpenService(struct dcerpc_binding_handle *b,
      65             :                              struct torture_context *tctx,
      66             :                              struct policy_handle *h,
      67             :                              const char *name,
      68             :                              struct policy_handle *s)
      69             : {
      70           0 :         struct svcctl_OpenServiceW r;
      71             : 
      72          48 :         r.in.scmanager_handle = h;
      73          48 :         r.in.ServiceName = name;
      74          48 :         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
      75          48 :         r.out.handle = s;
      76             : 
      77          48 :         torture_assert_ntstatus_ok(tctx,
      78             :                                    dcerpc_svcctl_OpenServiceW_r(b, tctx, &r),
      79             :                                    "OpenServiceW failed!");
      80          48 :         torture_assert_werr_ok(tctx, r.out.result, "OpenServiceW failed!");
      81             : 
      82          48 :         return true;
      83             : 
      84             : }
      85             : 
      86           4 : static bool test_QueryServiceStatus(struct torture_context *tctx,
      87             :                                     struct dcerpc_pipe *p)
      88             : {
      89           0 :         struct svcctl_QueryServiceStatus r;
      90           0 :         struct policy_handle h, s;
      91           0 :         struct SERVICE_STATUS service_status;
      92           0 :         NTSTATUS status;
      93           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
      94             : 
      95           4 :         if (!test_OpenSCManager(b, tctx, &h))
      96           0 :                 return false;
      97             : 
      98           4 :         if (!test_OpenService(b, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
      99           0 :                 return false;
     100             : 
     101           4 :         r.in.handle = &s;
     102           4 :         r.out.service_status = &service_status;
     103             : 
     104           4 :         status = dcerpc_svcctl_QueryServiceStatus_r(b, tctx, &r);
     105           4 :         torture_assert_ntstatus_ok(tctx, status, "QueryServiceStatus failed!");
     106           4 :         torture_assert_werr_ok(tctx, r.out.result, "QueryServiceStatus failed!");
     107             : 
     108           4 :         if (!test_CloseServiceHandle(b, tctx, &s))
     109           0 :                 return false;
     110             : 
     111           4 :         if (!test_CloseServiceHandle(b, tctx, &h))
     112           0 :                 return false;
     113             : 
     114           4 :         return true;
     115             : }
     116             : 
     117           4 : static bool test_QueryServiceStatusEx(struct torture_context *tctx, struct dcerpc_pipe *p)
     118             : {
     119           0 :         struct svcctl_QueryServiceStatusEx r;
     120           0 :         struct policy_handle h, s;
     121           0 :         NTSTATUS status;
     122           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
     123             : 
     124           4 :         uint32_t info_level = SVC_STATUS_PROCESS_INFO;
     125           0 :         uint8_t *buffer;
     126           4 :         uint32_t offered = 0;
     127           4 :         uint32_t needed = 0;
     128             : 
     129           4 :         if (!test_OpenSCManager(b, tctx, &h))
     130           0 :                 return false;
     131             : 
     132           4 :         if (!test_OpenService(b, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
     133           0 :                 return false;
     134             : 
     135           4 :         buffer = talloc(tctx, uint8_t);
     136             : 
     137           4 :         r.in.handle = &s;
     138           4 :         r.in.info_level = info_level;
     139           4 :         r.in.offered = offered;
     140           4 :         r.out.buffer = buffer;
     141           4 :         r.out.needed = &needed;
     142             : 
     143           4 :         status = dcerpc_svcctl_QueryServiceStatusEx_r(b, tctx, &r);
     144           4 :         torture_assert_ntstatus_ok(tctx, status, "QueryServiceStatusEx failed!");
     145             : 
     146           4 :         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
     147           4 :                 r.in.offered = needed;
     148           4 :                 buffer = talloc_array(tctx, uint8_t, needed);
     149           4 :                 r.out.buffer = buffer;
     150             : 
     151           4 :                 status = dcerpc_svcctl_QueryServiceStatusEx_r(b, tctx, &r);
     152           4 :                 torture_assert_ntstatus_ok(tctx, status, "QueryServiceStatusEx failed!");
     153           4 :                 torture_assert_werr_ok(tctx, r.out.result, "QueryServiceStatusEx failed!");
     154             :         }
     155             : 
     156           4 :         if (!test_CloseServiceHandle(b, tctx, &s))
     157           0 :                 return false;
     158             : 
     159           4 :         if (!test_CloseServiceHandle(b, tctx, &h))
     160           0 :                 return false;
     161             : 
     162           4 :         return true;
     163             : }
     164             : 
     165           4 : static bool test_QueryServiceConfigW(struct torture_context *tctx,
     166             :                                      struct dcerpc_pipe *p)
     167             : {
     168           0 :         struct svcctl_QueryServiceConfigW r;
     169           0 :         struct QUERY_SERVICE_CONFIG query;
     170           0 :         struct policy_handle h, s;
     171           0 :         NTSTATUS status;
     172           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
     173             : 
     174           4 :         uint32_t offered = 0;
     175           4 :         uint32_t needed = 0;
     176             : 
     177           4 :         if (!test_OpenSCManager(b, tctx, &h))
     178           0 :                 return false;
     179             : 
     180           4 :         if (!test_OpenService(b, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
     181           0 :                 return false;
     182             : 
     183           4 :         r.in.handle = &s;
     184           4 :         r.in.offered = offered;
     185           4 :         r.out.query = &query;
     186           4 :         r.out.needed = &needed;
     187             : 
     188           4 :         status = dcerpc_svcctl_QueryServiceConfigW_r(b, tctx, &r);
     189           4 :         torture_assert_ntstatus_ok(tctx, status, "QueryServiceConfigW failed!");
     190             : 
     191           4 :         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
     192           4 :                 r.in.offered = needed;
     193           4 :                 status = dcerpc_svcctl_QueryServiceConfigW_r(b, tctx, &r);
     194           4 :                 torture_assert_ntstatus_ok(tctx, status, "QueryServiceConfigW failed!");
     195             :         }
     196             : 
     197           4 :         torture_assert_werr_ok(tctx, r.out.result, "QueryServiceConfigW failed!");
     198             : 
     199           4 :         if (!test_CloseServiceHandle(b, tctx, &s))
     200           0 :                 return false;
     201             : 
     202           4 :         if (!test_CloseServiceHandle(b, tctx, &h))
     203           0 :                 return false;
     204             : 
     205           4 :         return true;
     206             : }
     207             : 
     208           4 : static bool test_QueryServiceConfig2W(struct torture_context *tctx, struct dcerpc_pipe *p)
     209             : {
     210           0 :         struct svcctl_QueryServiceConfig2W r;
     211           0 :         struct policy_handle h, s;
     212           0 :         NTSTATUS status;
     213           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
     214             : 
     215           4 :         uint32_t info_level = SERVICE_CONFIG_DESCRIPTION;
     216           0 :         uint8_t *buffer;
     217           4 :         uint32_t offered = 0;
     218           4 :         uint32_t needed = 0;
     219             : 
     220           4 :         if (!test_OpenSCManager(b, tctx, &h))
     221           0 :                 return false;
     222             : 
     223           4 :         if (!test_OpenService(b, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
     224           0 :                 return false;
     225             : 
     226           4 :         buffer = talloc(tctx, uint8_t);
     227             : 
     228           4 :         r.in.handle = &s;
     229           4 :         r.in.info_level = info_level;
     230           4 :         r.in.offered = offered;
     231           4 :         r.out.buffer = buffer;
     232           4 :         r.out.needed = &needed;
     233             : 
     234           4 :         status = dcerpc_svcctl_QueryServiceConfig2W_r(b, tctx, &r);
     235           4 :         torture_assert_ntstatus_ok(tctx, status, "QueryServiceConfig2W failed!");
     236             : 
     237           4 :         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
     238           4 :                 r.in.offered = needed;
     239           4 :                 buffer = talloc_array(tctx, uint8_t, needed);
     240           4 :                 r.out.buffer = buffer;
     241             : 
     242           4 :                 status = dcerpc_svcctl_QueryServiceConfig2W_r(b, tctx, &r);
     243           4 :                 torture_assert_ntstatus_ok(tctx, status, "QueryServiceConfig2W failed!");
     244           4 :                 torture_assert_werr_ok(tctx, r.out.result, "QueryServiceConfig2W failed!");
     245             :         }
     246             : 
     247           4 :         r.in.info_level = SERVICE_CONFIG_FAILURE_ACTIONS;
     248           4 :         r.in.offered = offered;
     249           4 :         r.out.buffer = buffer;
     250           4 :         r.out.needed = &needed;
     251             : 
     252           4 :         status = dcerpc_svcctl_QueryServiceConfig2W_r(b, tctx, &r);
     253           4 :         torture_assert_ntstatus_ok(tctx, status, "QueryServiceConfig2W failed!");
     254             : 
     255           4 :         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
     256           4 :                 r.in.offered = needed;
     257           4 :                 buffer = talloc_array(tctx, uint8_t, needed);
     258           4 :                 r.out.buffer = buffer;
     259             : 
     260           4 :                 status = dcerpc_svcctl_QueryServiceConfig2W_r(b, tctx, &r);
     261           4 :                 torture_assert_ntstatus_ok(tctx, status, "QueryServiceConfig2W failed!");
     262           4 :                 torture_assert_werr_ok(tctx, r.out.result, "QueryServiceConfig2W failed!");
     263             :         }
     264             : 
     265           4 :         if (!test_CloseServiceHandle(b, tctx, &s))
     266           0 :                 return false;
     267             : 
     268           4 :         if (!test_CloseServiceHandle(b, tctx, &h))
     269           0 :                 return false;
     270             : 
     271           4 :         return true;
     272             : }
     273             : 
     274           4 : static bool test_QueryServiceConfigEx(struct torture_context *tctx, struct dcerpc_pipe *p)
     275             : {
     276           0 :         struct svcctl_QueryServiceConfigEx r;
     277           0 :         struct policy_handle h, s;
     278           0 :         NTSTATUS status;
     279           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
     280           0 :         struct SC_RPC_CONFIG_INFOW info;
     281           0 :         int i;
     282             : 
     283           4 :         if (!test_OpenSCManager(b, tctx, &h))
     284           0 :                 return false;
     285             : 
     286           4 :         if (!test_OpenService(b, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
     287           0 :                 return false;
     288             : 
     289           4 :         for (i=0; i < 16; i++) {
     290             : 
     291           4 :                 r.in.hService = s;
     292           4 :                 r.in.dwInfoLevel = i;
     293           4 :                 r.out.pInfo = &info;
     294             : 
     295           4 :                 status = dcerpc_svcctl_QueryServiceConfigEx_r(b, tctx, &r);
     296           4 :                 if (i == 8) {
     297           0 :                         torture_assert_ntstatus_ok(tctx, status, "QueryServiceConfigEx failed!");
     298           0 :                         torture_assert_werr_ok(tctx, r.out.result, "QueryServiceConfigEx failed!");
     299             :                 } else {
     300           4 :                         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_RPC_ENUM_VALUE_OUT_OF_RANGE, "QueryServiceConfigEx failed!");
     301             :                 }
     302             :         }
     303             : 
     304           0 :         if (!test_CloseServiceHandle(b, tctx, &s))
     305           0 :                 return false;
     306             : 
     307           0 :         if (!test_CloseServiceHandle(b, tctx, &h))
     308           0 :                 return false;
     309             : 
     310           0 :         return true;
     311             : }
     312             : 
     313           4 : static bool test_QueryServiceObjectSecurity(struct torture_context *tctx,
     314             :                                             struct dcerpc_pipe *p)
     315             : {
     316           0 :         struct svcctl_QueryServiceObjectSecurity r;
     317           0 :         struct policy_handle h, s;
     318           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
     319             : 
     320           4 :         uint8_t *buffer = NULL;
     321           0 :         uint32_t needed;
     322             : 
     323           0 :         enum ndr_err_code ndr_err;
     324           0 :         struct security_descriptor sd;
     325           0 :         DATA_BLOB blob;
     326             : 
     327           4 :         if (!test_OpenSCManager(b, tctx, &h))
     328           0 :                 return false;
     329             : 
     330           4 :         if (!test_OpenService(b, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
     331           0 :                 return false;
     332             : 
     333           4 :         r.in.handle = &s;
     334           4 :         r.in.security_flags = 0;
     335           4 :         r.in.offered = 0;
     336           4 :         r.out.buffer = NULL;
     337           4 :         r.out.needed = &needed;
     338             : 
     339           4 :         torture_assert_ntstatus_ok(tctx,
     340             :                 dcerpc_svcctl_QueryServiceObjectSecurity_r(b, tctx, &r),
     341             :                 "QueryServiceObjectSecurity failed!");
     342           4 :         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAMETER,
     343             :                 "QueryServiceObjectSecurity failed!");
     344             : 
     345           4 :         r.in.security_flags = SECINFO_DACL;
     346             : 
     347           4 :         torture_assert_ntstatus_ok(tctx,
     348             :                 dcerpc_svcctl_QueryServiceObjectSecurity_r(b, tctx, &r),
     349             :                 "QueryServiceObjectSecurity failed!");
     350             : 
     351           4 :         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
     352           4 :                 r.in.offered = needed;
     353           4 :                 buffer = talloc_array(tctx, uint8_t, needed);
     354           4 :                 r.out.buffer = buffer;
     355           4 :                 torture_assert_ntstatus_ok(tctx,
     356             :                         dcerpc_svcctl_QueryServiceObjectSecurity_r(b, tctx, &r),
     357             :                         "QueryServiceObjectSecurity failed!");
     358             :         }
     359             : 
     360           4 :         torture_assert_werr_ok(tctx, r.out.result, "QueryServiceObjectSecurity failed!");
     361             : 
     362           4 :         blob = data_blob_const(buffer, needed);
     363             : 
     364           4 :         ndr_err = ndr_pull_struct_blob(&blob, tctx, &sd,
     365             :                 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
     366           4 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     367           0 :                 return false;
     368             :         }
     369             : 
     370           4 :         if (DEBUGLEVEL >= 1) {
     371           4 :                 NDR_PRINT_DEBUG(security_descriptor, &sd);
     372             :         }
     373             : 
     374           4 :         if (!test_CloseServiceHandle(b, tctx, &s))
     375           0 :                 return false;
     376             : 
     377           4 :         if (!test_CloseServiceHandle(b, tctx, &h))
     378           0 :                 return false;
     379             : 
     380           4 :         return true;
     381             : }
     382             : 
     383           4 : static bool test_SetServiceObjectSecurity(struct torture_context *tctx,
     384             :                                           struct dcerpc_pipe *p)
     385             : {
     386           0 :         struct svcctl_QueryServiceObjectSecurity q;
     387           0 :         struct svcctl_SetServiceObjectSecurity r;
     388           0 :         struct policy_handle h, s;
     389           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
     390             : 
     391           0 :         uint8_t *buffer;
     392           0 :         uint32_t needed;
     393             : 
     394           4 :         if (!test_OpenSCManager(b, tctx, &h))
     395           0 :                 return false;
     396             : 
     397           4 :         if (!test_OpenService(b, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
     398           0 :                 return false;
     399             : 
     400           4 :         q.in.handle = &s;
     401           4 :         q.in.security_flags = SECINFO_DACL;
     402           4 :         q.in.offered = 0;
     403           4 :         q.out.buffer = NULL;
     404           4 :         q.out.needed = &needed;
     405             : 
     406           4 :         torture_assert_ntstatus_ok(tctx,
     407             :                 dcerpc_svcctl_QueryServiceObjectSecurity_r(b, tctx, &q),
     408             :                 "QueryServiceObjectSecurity failed!");
     409             : 
     410           4 :         if (W_ERROR_EQUAL(q.out.result, WERR_INSUFFICIENT_BUFFER)) {
     411           4 :                 q.in.offered = needed;
     412           4 :                 buffer = talloc_array(tctx, uint8_t, needed);
     413           4 :                 q.out.buffer = buffer;
     414           4 :                 torture_assert_ntstatus_ok(tctx,
     415             :                         dcerpc_svcctl_QueryServiceObjectSecurity_r(b, tctx, &q),
     416             :                         "QueryServiceObjectSecurity failed!");
     417             :         }
     418             : 
     419           4 :         torture_assert_werr_ok(tctx, q.out.result,
     420             :                 "QueryServiceObjectSecurity failed!");
     421             : 
     422           4 :         r.in.handle = &s;
     423           4 :         r.in.security_flags = SECINFO_DACL;
     424           4 :         r.in.buffer = q.out.buffer;
     425           4 :         r.in.offered = *q.out.needed;
     426             : 
     427           4 :         torture_assert_ntstatus_ok(tctx,
     428             :                 dcerpc_svcctl_SetServiceObjectSecurity_r(b, tctx, &r),
     429             :                 "SetServiceObjectSecurity failed!");
     430           4 :         torture_assert_werr_ok(tctx, r.out.result,
     431             :                 "SetServiceObjectSecurity failed!");
     432             : 
     433           4 :         if (!test_CloseServiceHandle(b, tctx, &s))
     434           0 :                 return false;
     435             : 
     436           4 :         if (!test_CloseServiceHandle(b, tctx, &h))
     437           0 :                 return false;
     438             : 
     439           4 :         return true;
     440             : }
     441             : 
     442           4 : static bool test_StartServiceW(struct torture_context *tctx,
     443             :                                struct dcerpc_pipe *p)
     444             : {
     445           0 :         struct svcctl_StartServiceW r;
     446           0 :         struct policy_handle h, s;
     447           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
     448             : 
     449           4 :         if (!test_OpenSCManager(b, tctx, &h))
     450           0 :                 return false;
     451             : 
     452           4 :         if (!test_OpenService(b, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
     453           0 :                 return false;
     454             : 
     455           4 :         r.in.handle = &s;
     456           4 :         r.in.NumArgs = 0;
     457           4 :         r.in.Arguments = NULL;
     458             : 
     459           4 :         torture_assert_ntstatus_ok(tctx,
     460             :                 dcerpc_svcctl_StartServiceW_r(b, tctx, &r),
     461             :                 "StartServiceW failed!");
     462           4 :         torture_assert_werr_equal(tctx, r.out.result,
     463             :                 WERR_SERVICE_ALREADY_RUNNING,
     464             :                 "StartServiceW failed!");
     465             : 
     466           4 :         if (!test_CloseServiceHandle(b, tctx, &s))
     467           0 :                 return false;
     468             : 
     469           4 :         if (!test_CloseServiceHandle(b, tctx, &h))
     470           0 :                 return false;
     471             : 
     472           4 :         return true;
     473             : }
     474             : 
     475           4 : static bool test_ControlService(struct torture_context *tctx,
     476             :                                 struct dcerpc_pipe *p)
     477             : {
     478           0 :         struct svcctl_ControlService r;
     479           0 :         struct policy_handle h, s;
     480           0 :         struct SERVICE_STATUS service_status;
     481           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
     482             : 
     483           4 :         if (!test_OpenSCManager(b, tctx, &h))
     484           0 :                 return false;
     485             : 
     486           4 :         if (!test_OpenService(b, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
     487           0 :                 return false;
     488             : 
     489           4 :         r.in.handle = &s;
     490           4 :         r.in.control = 0;
     491           4 :         r.out.service_status = &service_status;
     492             : 
     493           4 :         torture_assert_ntstatus_ok(tctx,
     494             :                 dcerpc_svcctl_ControlService_r(b, tctx, &r),
     495             :                 "ControlService failed!");
     496           4 :         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAMETER,
     497             :                 "ControlService failed!");
     498             : 
     499           4 :         if (!test_CloseServiceHandle(b, tctx, &s))
     500           0 :                 return false;
     501             : 
     502           4 :         if (!test_CloseServiceHandle(b, tctx, &h))
     503           0 :                 return false;
     504             : 
     505           4 :         return true;
     506             : }
     507             : 
     508           4 : static bool test_ControlServiceExW(struct torture_context *tctx,
     509             :                                    struct dcerpc_pipe *p)
     510             : {
     511           0 :         struct svcctl_ControlServiceExW r;
     512           0 :         struct policy_handle h, s;
     513           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
     514           0 :         union SC_RPC_SERVICE_CONTROL_IN_PARAMSW ControlInParams;
     515           0 :         union SC_RPC_SERVICE_CONTROL_OUT_PARAMSW ControlOutParams;
     516           0 :         struct SERVICE_CONTROL_STATUS_REASON_OUT_PARAMS psrOutParams;
     517           0 :         struct SERVICE_CONTROL_STATUS_REASON_IN_PARAMSW psrInParams;
     518             : 
     519           4 :         if (!test_OpenSCManager(b, tctx, &h))
     520           0 :                 return false;
     521             : 
     522           4 :         if (!test_OpenService(b, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
     523           0 :                 return false;
     524             : 
     525           4 :         ZERO_STRUCT(psrInParams);
     526           4 :         ZERO_STRUCT(psrOutParams);
     527             : 
     528           4 :         psrInParams.dwReason =  SERVICE_STOP_CUSTOM |
     529             :                                 SERVICE_STOP_REASON_MAJOR_APPLICATION |
     530             :                                 SERVICE_STOP_REASON_MINOR_ENVIRONMENT;
     531           4 :         psrInParams.pszComment = "wurst";
     532             : 
     533           4 :         ControlInParams.psrInParams = &psrInParams;
     534           4 :         ControlOutParams.psrOutParams = &psrOutParams;
     535             : 
     536           4 :         r.in.hService = s;
     537           4 :         r.in.dwControl = SVCCTL_CONTROL_STOP;
     538           4 :         r.in.dwInfoLevel = 1;
     539           4 :         r.in.pControlInParams = &ControlInParams;
     540           4 :         r.out.pControlOutParams = &ControlOutParams;
     541             : 
     542           4 :         torture_assert_ntstatus_ok(tctx,
     543             :                 dcerpc_svcctl_ControlServiceExW_r(b, tctx, &r),
     544             :                 "ControlServiceExW failed!");
     545           0 :         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAMETER,
     546             :                 "ControlServiceExW failed!");
     547             : 
     548           0 :         if (!test_CloseServiceHandle(b, tctx, &s))
     549           0 :                 return false;
     550             : 
     551           0 :         if (!test_CloseServiceHandle(b, tctx, &h))
     552           0 :                 return false;
     553             : 
     554           0 :         return true;
     555             : }
     556             : 
     557           4 : static bool test_EnumServicesStatus(struct torture_context *tctx, struct dcerpc_pipe *p)
     558             : {
     559           0 :         struct svcctl_EnumServicesStatusW r;
     560           0 :         struct policy_handle h;
     561           0 :         int i;
     562           0 :         NTSTATUS status;
     563           4 :         uint32_t resume_handle = 0;
     564           4 :         struct ENUM_SERVICE_STATUSW *service = NULL;
     565           4 :         uint32_t needed = 0;
     566           4 :         uint32_t services_returned = 0;
     567           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
     568             : 
     569           4 :         if (!test_OpenSCManager(b, tctx, &h))
     570           0 :                 return false;
     571             : 
     572           4 :         r.in.handle = &h;
     573           4 :         r.in.type = SERVICE_TYPE_WIN32;
     574           4 :         r.in.state = SERVICE_STATE_ALL;
     575           4 :         r.in.offered = 0;
     576           4 :         r.in.resume_handle = &resume_handle;
     577           4 :         r.out.service = NULL;
     578           4 :         r.out.resume_handle = &resume_handle;
     579           4 :         r.out.services_returned = &services_returned;
     580           4 :         r.out.needed = &needed;
     581             : 
     582           4 :         status = dcerpc_svcctl_EnumServicesStatusW_r(b, tctx, &r);
     583             : 
     584           4 :         torture_assert_ntstatus_ok(tctx, status, "EnumServicesStatus failed!");
     585             : 
     586           4 :         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
     587           4 :                 r.in.offered = needed;
     588           4 :                 r.out.service = talloc_array(tctx, uint8_t, needed);
     589             : 
     590           4 :                 status = dcerpc_svcctl_EnumServicesStatusW_r(b, tctx, &r);
     591             : 
     592           4 :                 torture_assert_ntstatus_ok(tctx, status, "EnumServicesStatus failed!");
     593           4 :                 torture_assert_werr_ok(tctx, r.out.result, "EnumServicesStatus failed");
     594             :         }
     595             : 
     596           4 :         if (services_returned > 0) {
     597             : 
     598           0 :                 enum ndr_err_code ndr_err;
     599           0 :                 DATA_BLOB blob;
     600           0 :                 struct ndr_pull *ndr;
     601             : 
     602           4 :                 blob.length = r.in.offered;
     603           4 :                 blob.data = talloc_steal(tctx, r.out.service);
     604             : 
     605           4 :                 ndr = ndr_pull_init_blob(&blob, tctx);
     606             : 
     607           4 :                 service = talloc_array(tctx, struct ENUM_SERVICE_STATUSW, services_returned);
     608           4 :                 if (!service) {
     609           0 :                         return false;
     610             :                 }
     611             : 
     612           4 :                 ndr_err = ndr_pull_ENUM_SERVICE_STATUSW_array(
     613             :                                 ndr, services_returned, service);
     614           4 :                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     615           0 :                         return false;
     616             :                 }
     617             :         }
     618             : 
     619          20 :         for(i = 0; i < services_returned; i++) {
     620             : 
     621          16 :                 torture_assert(tctx, service[i].service_name,
     622             :                         "Service without name returned!");
     623             : 
     624          16 :                 printf("%-20s   \"%s\", Type: %d, State: %d\n",
     625          16 :                         service[i].service_name, service[i].display_name,
     626          16 :                         service[i].status.type, service[i].status.state);
     627             :         }
     628             : 
     629           4 :         if (!test_CloseServiceHandle(b, tctx, &h))
     630           0 :                 return false;
     631             : 
     632           4 :         return true;
     633             : }
     634             : 
     635           4 : static bool test_EnumDependentServicesW(struct torture_context *tctx,
     636             :                                         struct dcerpc_pipe *p)
     637             : {
     638           0 :         struct svcctl_EnumDependentServicesW r;
     639           0 :         struct policy_handle h, s;
     640           0 :         uint32_t needed;
     641           0 :         uint32_t services_returned;
     642           0 :         uint32_t i;
     643           4 :         uint32_t states[] = { SERVICE_STATE_ACTIVE,
     644             :                               SERVICE_STATE_INACTIVE,
     645             :                               SERVICE_STATE_ALL };
     646           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
     647             : 
     648           4 :         if (!test_OpenSCManager(b, tctx, &h))
     649           0 :                 return false;
     650             : 
     651           4 :         if (!test_OpenService(b, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
     652           0 :                 return false;
     653             : 
     654           4 :         r.in.service = &s;
     655           4 :         r.in.offered = 0;
     656           4 :         r.in.state = 0;
     657           4 :         r.out.service_status = NULL;
     658           4 :         r.out.services_returned = &services_returned;
     659           4 :         r.out.needed = &needed;
     660             : 
     661           4 :         torture_assert_ntstatus_ok(tctx,
     662             :                 dcerpc_svcctl_EnumDependentServicesW_r(b, tctx, &r),
     663             :                 "EnumDependentServicesW failed!");
     664             : 
     665           4 :         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAMETER,
     666             :                 "EnumDependentServicesW failed!");
     667             : 
     668          16 :         for (i=0; i<ARRAY_SIZE(states); i++) {
     669             : 
     670          12 :                 r.in.state = states[i];
     671             : 
     672          12 :                 torture_assert_ntstatus_ok(tctx,
     673             :                         dcerpc_svcctl_EnumDependentServicesW_r(b, tctx, &r),
     674             :                         "EnumDependentServicesW failed!");
     675             : 
     676          12 :                 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
     677           0 :                         r.in.offered = needed;
     678           0 :                         r.out.service_status = talloc_array(tctx, uint8_t, needed);
     679             : 
     680           0 :                         torture_assert_ntstatus_ok(tctx,
     681             :                                 dcerpc_svcctl_EnumDependentServicesW_r(b, tctx, &r),
     682             :                                 "EnumDependentServicesW failed!");
     683             : 
     684             :                 }
     685             : 
     686          12 :                 torture_assert_werr_ok(tctx, r.out.result,
     687             :                         "EnumDependentServicesW failed");
     688             :         }
     689             : 
     690           4 :         if (!test_CloseServiceHandle(b, tctx, &s))
     691           0 :                 return false;
     692             : 
     693           4 :         if (!test_CloseServiceHandle(b, tctx, &h))
     694           0 :                 return false;
     695             : 
     696           4 :         return true;
     697             : }
     698             : 
     699           4 : static bool test_SCManager(struct torture_context *tctx,
     700             :                            struct dcerpc_pipe *p)
     701             : {
     702           0 :         struct policy_handle h;
     703           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
     704             : 
     705           4 :         if (!test_OpenSCManager(b, tctx, &h))
     706           0 :                 return false;
     707             : 
     708           4 :         if (!test_CloseServiceHandle(b, tctx, &h))
     709           0 :                 return false;
     710             : 
     711           4 :         return true;
     712             : }
     713             : 
     714           4 : static bool test_ChangeServiceConfigW(struct torture_context *tctx,
     715             :                                       struct dcerpc_pipe *p)
     716             : {
     717           0 :         struct svcctl_ChangeServiceConfigW r;
     718           0 :         struct svcctl_QueryServiceConfigW q;
     719           0 :         struct policy_handle h, s;
     720           0 :         NTSTATUS status;
     721           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
     722           0 :         struct QUERY_SERVICE_CONFIG query;
     723           0 :         bool ok;
     724             : 
     725           4 :         uint32_t offered = 0;
     726           4 :         uint32_t needed = 0;
     727             : 
     728           4 :         ok = test_OpenSCManager(b, tctx, &h);
     729           4 :         if (!ok) {
     730           0 :                 return false;
     731             :         }
     732             : 
     733           4 :         ok = test_OpenService(b, tctx, &h, TORTURE_DEFAULT_SERVICE, &s);
     734           4 :         if (!ok) {
     735           0 :                 return false;
     736             :         }
     737             : 
     738           4 :         q.in.handle = &s;
     739           4 :         q.in.offered = offered;
     740           4 :         q.out.query = &query;
     741           4 :         q.out.needed = &needed;
     742             : 
     743           4 :         status = dcerpc_svcctl_QueryServiceConfigW_r(b, tctx, &q);
     744           4 :         torture_assert_ntstatus_ok(tctx, status, "QueryServiceConfigW failed!");
     745             : 
     746           4 :         if (W_ERROR_EQUAL(q.out.result, WERR_INSUFFICIENT_BUFFER)) {
     747           4 :                 q.in.offered = needed;
     748           4 :                 status = dcerpc_svcctl_QueryServiceConfigW_r(b, tctx, &q);
     749           4 :                 torture_assert_ntstatus_ok(tctx, status, "QueryServiceConfigW failed!");
     750             :         }
     751           4 :         torture_assert_werr_ok(tctx, q.out.result, "QueryServiceConfigW failed!");
     752             : 
     753           4 :         r.in.handle = &s;
     754           4 :         r.in.type               = query.service_type;
     755           4 :         r.in.start_type         = query.start_type;
     756           4 :         r.in.error_control      = query.error_control;
     757             : 
     758             :         /*
     759             :          * according to MS-SCMR 3.1.4.11 NULL params are supposed to leave the
     760             :          * existing values intact.
     761             :          */
     762             : 
     763           4 :         r.in.binary_path        = NULL;
     764           4 :         r.in.load_order_group   = NULL;
     765           4 :         r.in.dependencies       = NULL;
     766           4 :         r.in.dwDependSize       = 0;
     767           4 :         r.in.service_start_name = NULL;
     768           4 :         r.in.password           = NULL;
     769           4 :         r.in.dwPwSize           = 0;
     770           4 :         r.in.display_name       = NULL;
     771           4 :         r.in.tag_id             = NULL;
     772           4 :         r.out.tag_id            = NULL;
     773             : 
     774           4 :         status = dcerpc_svcctl_ChangeServiceConfigW_r(b, tctx, &r);
     775           4 :         torture_assert_ntstatus_ok(tctx, status, "ChangeServiceConfigW failed!");
     776           0 :         torture_assert_werr_ok(tctx, r.out.result, "ChangeServiceConfigW failed!");
     777             : 
     778           0 :         ok = test_CloseServiceHandle(b, tctx, &s);
     779           0 :         if (!ok) {
     780           0 :                 return false;
     781             :         }
     782             : 
     783           0 :         ok = test_CloseServiceHandle(b, tctx, &h);
     784           0 :         if (!ok) {
     785           0 :                 return false;
     786             :         }
     787             : 
     788           0 :         return true;
     789             : }
     790             : 
     791        2379 : struct torture_suite *torture_rpc_svcctl(TALLOC_CTX *mem_ctx)
     792             : {
     793        2379 :         struct torture_suite *suite = torture_suite_create(mem_ctx, "svcctl");
     794         125 :         struct torture_rpc_tcase *tcase;
     795             : 
     796        2379 :         tcase = torture_suite_add_rpc_iface_tcase(suite, "svcctl", &ndr_table_svcctl);
     797             : 
     798        2379 :         torture_rpc_tcase_add_test(tcase, "SCManager",
     799             :                                    test_SCManager);
     800        2379 :         torture_rpc_tcase_add_test(tcase, "EnumServicesStatus",
     801             :                                    test_EnumServicesStatus);
     802        2379 :         torture_rpc_tcase_add_test(tcase, "EnumDependentServicesW",
     803             :                                    test_EnumDependentServicesW);
     804        2379 :         torture_rpc_tcase_add_test(tcase, "QueryServiceStatus",
     805             :                                    test_QueryServiceStatus);
     806        2379 :         torture_rpc_tcase_add_test(tcase, "QueryServiceStatusEx",
     807             :                                    test_QueryServiceStatusEx);
     808        2379 :         torture_rpc_tcase_add_test(tcase, "QueryServiceConfigW",
     809             :                                    test_QueryServiceConfigW);
     810        2379 :         torture_rpc_tcase_add_test(tcase, "QueryServiceConfig2W",
     811             :                                    test_QueryServiceConfig2W);
     812        2379 :         torture_rpc_tcase_add_test(tcase, "QueryServiceConfigEx",
     813             :                                    test_QueryServiceConfigEx);
     814        2379 :         torture_rpc_tcase_add_test(tcase, "QueryServiceObjectSecurity",
     815             :                                    test_QueryServiceObjectSecurity);
     816        2379 :         torture_rpc_tcase_add_test(tcase, "SetServiceObjectSecurity",
     817             :                                    test_SetServiceObjectSecurity);
     818        2379 :         torture_rpc_tcase_add_test(tcase, "StartServiceW",
     819             :                                    test_StartServiceW);
     820        2379 :         torture_rpc_tcase_add_test(tcase, "ControlService",
     821             :                                    test_ControlService);
     822        2379 :         torture_rpc_tcase_add_test(tcase, "ControlServiceExW",
     823             :                                    test_ControlServiceExW);
     824        2379 :         torture_rpc_tcase_add_test(tcase, "ChangeServiceConfigW",
     825             :                                    test_ChangeServiceConfigW);
     826             : 
     827        2379 :         return suite;
     828             : }

Generated by: LCOV version 1.14