2 Unix SMB/CIFS implementation.
3 test suite for srvsvc rpc operations
5 Copyright (C) Jelmer Vernooij 2004
6 Copyright (C) Guenther Deschner 2008,2009
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.
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.
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/>.
23 #include "librpc/gen_ndr/ndr_svcctl_c.h"
24 #include "librpc/gen_ndr/ndr_svcctl.h"
25 #include "torture/rpc/rpc.h"
26 #include "param/param.h"
28 #define TORTURE_DEFAULT_SERVICE "Spooler"
30 static bool test_OpenSCManager(struct dcerpc_binding_handle
*b
,
31 struct torture_context
*tctx
,
32 struct policy_handle
*h
)
34 struct svcctl_OpenSCManagerW r
;
36 r
.in
.MachineName
= NULL
;
37 r
.in
.DatabaseName
= NULL
;
38 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
41 torture_assert_ntstatus_ok(tctx
,
42 dcerpc_svcctl_OpenSCManagerW_r(b
, tctx
, &r
),
43 "OpenSCManager failed!");
48 static bool test_CloseServiceHandle(struct dcerpc_binding_handle
*b
,
49 struct torture_context
*tctx
,
50 struct policy_handle
*h
)
52 struct svcctl_CloseServiceHandle r
;
56 torture_assert_ntstatus_ok(tctx
,
57 dcerpc_svcctl_CloseServiceHandle_r(b
, tctx
, &r
),
58 "CloseServiceHandle failed");
63 static bool test_OpenService(struct dcerpc_binding_handle
*b
,
64 struct torture_context
*tctx
,
65 struct policy_handle
*h
,
67 struct policy_handle
*s
)
69 struct svcctl_OpenServiceW r
;
71 r
.in
.scmanager_handle
= h
;
72 r
.in
.ServiceName
= name
;
73 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
76 torture_assert_ntstatus_ok(tctx
,
77 dcerpc_svcctl_OpenServiceW_r(b
, tctx
, &r
),
78 "OpenServiceW failed!");
79 torture_assert_werr_ok(tctx
, r
.out
.result
, "OpenServiceW failed!");
85 static bool test_QueryServiceStatus(struct torture_context
*tctx
,
86 struct dcerpc_pipe
*p
)
88 struct svcctl_QueryServiceStatus r
;
89 struct policy_handle h
, s
;
90 struct SERVICE_STATUS service_status
;
92 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
94 if (!test_OpenSCManager(b
, tctx
, &h
))
97 if (!test_OpenService(b
, tctx
, &h
, TORTURE_DEFAULT_SERVICE
, &s
))
101 r
.out
.service_status
= &service_status
;
103 status
= dcerpc_svcctl_QueryServiceStatus_r(b
, tctx
, &r
);
104 torture_assert_ntstatus_ok(tctx
, status
, "QueryServiceStatus failed!");
105 torture_assert_werr_ok(tctx
, r
.out
.result
, "QueryServiceStatus failed!");
107 if (!test_CloseServiceHandle(b
, tctx
, &s
))
110 if (!test_CloseServiceHandle(b
, tctx
, &h
))
116 static bool test_QueryServiceStatusEx(struct torture_context
*tctx
, struct dcerpc_pipe
*p
)
118 struct svcctl_QueryServiceStatusEx r
;
119 struct policy_handle h
, s
;
121 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
123 uint32_t info_level
= SVC_STATUS_PROCESS_INFO
;
125 uint32_t offered
= 0;
128 if (!test_OpenSCManager(b
, tctx
, &h
))
131 if (!test_OpenService(b
, tctx
, &h
, TORTURE_DEFAULT_SERVICE
, &s
))
134 buffer
= talloc(tctx
, uint8_t);
137 r
.in
.info_level
= info_level
;
138 r
.in
.offered
= offered
;
139 r
.out
.buffer
= buffer
;
140 r
.out
.needed
= &needed
;
142 status
= dcerpc_svcctl_QueryServiceStatusEx_r(b
, tctx
, &r
);
143 torture_assert_ntstatus_ok(tctx
, status
, "QueryServiceStatusEx failed!");
145 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
146 r
.in
.offered
= needed
;
147 buffer
= talloc_array(tctx
, uint8_t, needed
);
148 r
.out
.buffer
= buffer
;
150 status
= dcerpc_svcctl_QueryServiceStatusEx_r(b
, tctx
, &r
);
151 torture_assert_ntstatus_ok(tctx
, status
, "QueryServiceStatusEx failed!");
152 torture_assert_werr_ok(tctx
, r
.out
.result
, "QueryServiceStatusEx failed!");
155 if (!test_CloseServiceHandle(b
, tctx
, &s
))
158 if (!test_CloseServiceHandle(b
, tctx
, &h
))
164 static bool test_QueryServiceConfigW(struct torture_context
*tctx
,
165 struct dcerpc_pipe
*p
)
167 struct svcctl_QueryServiceConfigW r
;
168 struct QUERY_SERVICE_CONFIG query
;
169 struct policy_handle h
, s
;
171 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
173 uint32_t offered
= 0;
176 if (!test_OpenSCManager(b
, tctx
, &h
))
179 if (!test_OpenService(b
, tctx
, &h
, TORTURE_DEFAULT_SERVICE
, &s
))
183 r
.in
.offered
= offered
;
184 r
.out
.query
= &query
;
185 r
.out
.needed
= &needed
;
187 status
= dcerpc_svcctl_QueryServiceConfigW_r(b
, tctx
, &r
);
188 torture_assert_ntstatus_ok(tctx
, status
, "QueryServiceConfigW failed!");
190 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
191 r
.in
.offered
= needed
;
192 status
= dcerpc_svcctl_QueryServiceConfigW_r(b
, tctx
, &r
);
193 torture_assert_ntstatus_ok(tctx
, status
, "QueryServiceConfigW failed!");
196 torture_assert_werr_ok(tctx
, r
.out
.result
, "QueryServiceConfigW failed!");
198 if (!test_CloseServiceHandle(b
, tctx
, &s
))
201 if (!test_CloseServiceHandle(b
, tctx
, &h
))
207 static bool test_QueryServiceConfig2W(struct torture_context
*tctx
, struct dcerpc_pipe
*p
)
209 struct svcctl_QueryServiceConfig2W r
;
210 struct policy_handle h
, s
;
212 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
214 uint32_t info_level
= SERVICE_CONFIG_DESCRIPTION
;
216 uint32_t offered
= 0;
219 if (!test_OpenSCManager(b
, tctx
, &h
))
222 if (!test_OpenService(b
, tctx
, &h
, TORTURE_DEFAULT_SERVICE
, &s
))
225 buffer
= talloc(tctx
, uint8_t);
228 r
.in
.info_level
= info_level
;
229 r
.in
.offered
= offered
;
230 r
.out
.buffer
= buffer
;
231 r
.out
.needed
= &needed
;
233 status
= dcerpc_svcctl_QueryServiceConfig2W_r(b
, tctx
, &r
);
234 torture_assert_ntstatus_ok(tctx
, status
, "QueryServiceConfig2W failed!");
236 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
237 r
.in
.offered
= needed
;
238 buffer
= talloc_array(tctx
, uint8_t, needed
);
239 r
.out
.buffer
= buffer
;
241 status
= dcerpc_svcctl_QueryServiceConfig2W_r(b
, tctx
, &r
);
242 torture_assert_ntstatus_ok(tctx
, status
, "QueryServiceConfig2W failed!");
243 torture_assert_werr_ok(tctx
, r
.out
.result
, "QueryServiceConfig2W failed!");
246 r
.in
.info_level
= SERVICE_CONFIG_FAILURE_ACTIONS
;
247 r
.in
.offered
= offered
;
248 r
.out
.buffer
= buffer
;
249 r
.out
.needed
= &needed
;
251 status
= dcerpc_svcctl_QueryServiceConfig2W_r(b
, tctx
, &r
);
252 torture_assert_ntstatus_ok(tctx
, status
, "QueryServiceConfig2W failed!");
254 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
255 r
.in
.offered
= needed
;
256 buffer
= talloc_array(tctx
, uint8_t, needed
);
257 r
.out
.buffer
= buffer
;
259 status
= dcerpc_svcctl_QueryServiceConfig2W_r(b
, tctx
, &r
);
260 torture_assert_ntstatus_ok(tctx
, status
, "QueryServiceConfig2W failed!");
261 torture_assert_werr_ok(tctx
, r
.out
.result
, "QueryServiceConfig2W failed!");
264 if (!test_CloseServiceHandle(b
, tctx
, &s
))
267 if (!test_CloseServiceHandle(b
, tctx
, &h
))
273 static bool test_QueryServiceObjectSecurity(struct torture_context
*tctx
,
274 struct dcerpc_pipe
*p
)
276 struct svcctl_QueryServiceObjectSecurity r
;
277 struct policy_handle h
, s
;
278 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
283 if (!test_OpenSCManager(b
, tctx
, &h
))
286 if (!test_OpenService(b
, tctx
, &h
, TORTURE_DEFAULT_SERVICE
, &s
))
290 r
.in
.security_flags
= 0;
293 r
.out
.needed
= &needed
;
295 torture_assert_ntstatus_ok(tctx
,
296 dcerpc_svcctl_QueryServiceObjectSecurity_r(b
, tctx
, &r
),
297 "QueryServiceObjectSecurity failed!");
298 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PARAM
,
299 "QueryServiceObjectSecurity failed!");
301 r
.in
.security_flags
= SECINFO_DACL
;
303 torture_assert_ntstatus_ok(tctx
,
304 dcerpc_svcctl_QueryServiceObjectSecurity_r(b
, tctx
, &r
),
305 "QueryServiceObjectSecurity failed!");
307 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
308 r
.in
.offered
= needed
;
309 buffer
= talloc_array(tctx
, uint8_t, needed
);
310 r
.out
.buffer
= buffer
;
311 torture_assert_ntstatus_ok(tctx
,
312 dcerpc_svcctl_QueryServiceObjectSecurity_r(b
, tctx
, &r
),
313 "QueryServiceObjectSecurity failed!");
316 torture_assert_werr_ok(tctx
, r
.out
.result
, "QueryServiceObjectSecurity failed!");
318 if (!test_CloseServiceHandle(b
, tctx
, &s
))
321 if (!test_CloseServiceHandle(b
, tctx
, &h
))
327 static bool test_StartServiceW(struct torture_context
*tctx
,
328 struct dcerpc_pipe
*p
)
330 struct svcctl_StartServiceW r
;
331 struct policy_handle h
, s
;
332 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
334 if (!test_OpenSCManager(b
, tctx
, &h
))
337 if (!test_OpenService(b
, tctx
, &h
, TORTURE_DEFAULT_SERVICE
, &s
))
342 r
.in
.Arguments
= NULL
;
344 torture_assert_ntstatus_ok(tctx
,
345 dcerpc_svcctl_StartServiceW_r(b
, tctx
, &r
),
346 "StartServiceW failed!");
347 torture_assert_werr_equal(tctx
, r
.out
.result
,
348 WERR_SERVICE_ALREADY_RUNNING
,
349 "StartServiceW failed!");
351 if (!test_CloseServiceHandle(b
, tctx
, &s
))
354 if (!test_CloseServiceHandle(b
, tctx
, &h
))
360 static bool test_ControlService(struct torture_context
*tctx
,
361 struct dcerpc_pipe
*p
)
363 struct svcctl_ControlService r
;
364 struct policy_handle h
, s
;
365 struct SERVICE_STATUS service_status
;
366 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
368 if (!test_OpenSCManager(b
, tctx
, &h
))
371 if (!test_OpenService(b
, tctx
, &h
, TORTURE_DEFAULT_SERVICE
, &s
))
376 r
.out
.service_status
= &service_status
;
378 torture_assert_ntstatus_ok(tctx
,
379 dcerpc_svcctl_ControlService_r(b
, tctx
, &r
),
380 "ControlService failed!");
381 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PARAM
,
382 "ControlService failed!");
384 if (!test_CloseServiceHandle(b
, tctx
, &s
))
387 if (!test_CloseServiceHandle(b
, tctx
, &h
))
393 static bool test_EnumServicesStatus(struct torture_context
*tctx
, struct dcerpc_pipe
*p
)
395 struct svcctl_EnumServicesStatusW r
;
396 struct policy_handle h
;
399 uint32_t resume_handle
= 0;
400 struct ENUM_SERVICE_STATUSW
*service
= NULL
;
402 uint32_t services_returned
= 0;
403 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
405 if (!test_OpenSCManager(b
, tctx
, &h
))
409 r
.in
.type
= SERVICE_TYPE_WIN32
;
410 r
.in
.state
= SERVICE_STATE_ALL
;
412 r
.in
.resume_handle
= &resume_handle
;
413 r
.out
.service
= NULL
;
414 r
.out
.resume_handle
= &resume_handle
;
415 r
.out
.services_returned
= &services_returned
;
416 r
.out
.needed
= &needed
;
418 status
= dcerpc_svcctl_EnumServicesStatusW_r(b
, tctx
, &r
);
420 torture_assert_ntstatus_ok(tctx
, status
, "EnumServicesStatus failed!");
422 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
423 r
.in
.offered
= needed
;
424 r
.out
.service
= talloc_array(tctx
, uint8_t, needed
);
426 status
= dcerpc_svcctl_EnumServicesStatusW_r(b
, tctx
, &r
);
428 torture_assert_ntstatus_ok(tctx
, status
, "EnumServicesStatus failed!");
429 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumServicesStatus failed");
432 if (services_returned
> 0) {
434 enum ndr_err_code ndr_err
;
436 struct ndr_pull
*ndr
;
438 blob
.length
= r
.in
.offered
;
439 blob
.data
= talloc_steal(tctx
, r
.out
.service
);
441 ndr
= ndr_pull_init_blob(&blob
, tctx
, lp_iconv_convenience(tctx
->lp_ctx
));
443 service
= talloc_array(tctx
, struct ENUM_SERVICE_STATUSW
, services_returned
);
448 ndr_err
= ndr_pull_ENUM_SERVICE_STATUSW_array(
449 ndr
, services_returned
, service
);
450 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
455 for(i
= 0; i
< services_returned
; i
++) {
457 torture_assert(tctx
, service
[i
].service_name
,
458 "Service without name returned!");
460 printf("%-20s \"%s\", Type: %d, State: %d\n",
461 service
[i
].service_name
, service
[i
].display_name
,
462 service
[i
].status
.type
, service
[i
].status
.state
);
465 if (!test_CloseServiceHandle(b
, tctx
, &h
))
471 static bool test_EnumDependentServicesW(struct torture_context
*tctx
,
472 struct dcerpc_pipe
*p
)
474 struct svcctl_EnumDependentServicesW r
;
475 struct policy_handle h
, s
;
477 uint32_t services_returned
;
479 uint32_t states
[] = { SERVICE_STATE_ACTIVE
,
480 SERVICE_STATE_INACTIVE
,
482 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
484 if (!test_OpenSCManager(b
, tctx
, &h
))
487 if (!test_OpenService(b
, tctx
, &h
, TORTURE_DEFAULT_SERVICE
, &s
))
493 r
.out
.service_status
= NULL
;
494 r
.out
.services_returned
= &services_returned
;
495 r
.out
.needed
= &needed
;
497 torture_assert_ntstatus_ok(tctx
,
498 dcerpc_svcctl_EnumDependentServicesW_r(b
, tctx
, &r
),
499 "EnumDependentServicesW failed!");
501 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PARAM
,
502 "EnumDependentServicesW failed!");
504 for (i
=0; i
<ARRAY_SIZE(states
); i
++) {
506 r
.in
.state
= states
[i
];
508 torture_assert_ntstatus_ok(tctx
,
509 dcerpc_svcctl_EnumDependentServicesW_r(b
, tctx
, &r
),
510 "EnumDependentServicesW failed!");
512 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
513 r
.in
.offered
= needed
;
514 r
.out
.service_status
= talloc_array(tctx
, uint8_t, needed
);
516 torture_assert_ntstatus_ok(tctx
,
517 dcerpc_svcctl_EnumDependentServicesW_r(b
, tctx
, &r
),
518 "EnumDependentServicesW failed!");
522 torture_assert_werr_ok(tctx
, r
.out
.result
,
523 "EnumDependentServicesW failed");
526 if (!test_CloseServiceHandle(b
, tctx
, &s
))
529 if (!test_CloseServiceHandle(b
, tctx
, &h
))
535 static bool test_SCManager(struct torture_context
*tctx
,
536 struct dcerpc_pipe
*p
)
538 struct policy_handle h
;
539 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
541 if (!test_OpenSCManager(b
, tctx
, &h
))
544 if (!test_CloseServiceHandle(b
, tctx
, &h
))
550 struct torture_suite
*torture_rpc_svcctl(TALLOC_CTX
*mem_ctx
)
552 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "SVCCTL");
553 struct torture_rpc_tcase
*tcase
;
555 tcase
= torture_suite_add_rpc_iface_tcase(suite
, "svcctl", &ndr_table_svcctl
);
557 torture_rpc_tcase_add_test(tcase
, "SCManager",
559 torture_rpc_tcase_add_test(tcase
, "EnumServicesStatus",
560 test_EnumServicesStatus
);
561 torture_rpc_tcase_add_test(tcase
, "EnumDependentServicesW",
562 test_EnumDependentServicesW
);
563 torture_rpc_tcase_add_test(tcase
, "QueryServiceStatus",
564 test_QueryServiceStatus
);
565 torture_rpc_tcase_add_test(tcase
, "QueryServiceStatusEx",
566 test_QueryServiceStatusEx
);
567 torture_rpc_tcase_add_test(tcase
, "QueryServiceConfigW",
568 test_QueryServiceConfigW
);
569 torture_rpc_tcase_add_test(tcase
, "QueryServiceConfig2W",
570 test_QueryServiceConfig2W
);
571 torture_rpc_tcase_add_test(tcase
, "QueryServiceObjectSecurity",
572 test_QueryServiceObjectSecurity
);
573 torture_rpc_tcase_add_test(tcase
, "StartServiceW",
575 torture_rpc_tcase_add_test(tcase
, "ControlService",
576 test_ControlService
);