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 "torture/torture.h"
24 #include "librpc/gen_ndr/ndr_svcctl_c.h"
25 #include "librpc/gen_ndr/ndr_svcctl.h"
26 #include "torture/rpc/rpc.h"
27 #include "param/param.h"
29 #define TORTURE_DEFAULT_SERVICE "Spooler"
31 static bool test_OpenSCManager(struct dcerpc_pipe
*p
, struct torture_context
*tctx
, struct policy_handle
*h
)
33 struct svcctl_OpenSCManagerW r
;
35 r
.in
.MachineName
= NULL
;
36 r
.in
.DatabaseName
= NULL
;
37 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
40 torture_assert_ntstatus_ok(tctx
,
41 dcerpc_svcctl_OpenSCManagerW(p
, tctx
, &r
),
42 "OpenSCManager failed!");
47 static bool test_CloseServiceHandle(struct dcerpc_pipe
*p
, struct torture_context
*tctx
, struct policy_handle
*h
)
49 struct svcctl_CloseServiceHandle r
;
53 torture_assert_ntstatus_ok(tctx
,
54 dcerpc_svcctl_CloseServiceHandle(p
, tctx
, &r
),
55 "CloseServiceHandle failed");
60 static bool test_OpenService(struct dcerpc_pipe
*p
, struct torture_context
*tctx
,
61 struct policy_handle
*h
, const char *name
, struct policy_handle
*s
)
63 struct svcctl_OpenServiceW r
;
65 r
.in
.scmanager_handle
= h
;
66 r
.in
.ServiceName
= name
;
67 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
70 torture_assert_ntstatus_ok(tctx
,
71 dcerpc_svcctl_OpenServiceW(p
, tctx
, &r
),
72 "OpenServiceW failed!");
73 torture_assert_werr_ok(tctx
, r
.out
.result
, "OpenServiceW failed!");
79 static bool test_QueryServiceStatus(struct torture_context
*tctx
,
80 struct dcerpc_pipe
*p
)
82 struct svcctl_QueryServiceStatus r
;
83 struct policy_handle h
, s
;
84 struct SERVICE_STATUS service_status
;
87 if (!test_OpenSCManager(p
, tctx
, &h
))
90 if (!test_OpenService(p
, tctx
, &h
, TORTURE_DEFAULT_SERVICE
, &s
))
94 r
.out
.service_status
= &service_status
;
96 status
= dcerpc_svcctl_QueryServiceStatus(p
, tctx
, &r
);
97 torture_assert_ntstatus_ok(tctx
, status
, "QueryServiceStatus failed!");
98 torture_assert_werr_ok(tctx
, r
.out
.result
, "QueryServiceStatus failed!");
100 if (!test_CloseServiceHandle(p
, tctx
, &s
))
103 if (!test_CloseServiceHandle(p
, tctx
, &h
))
109 static bool test_QueryServiceStatusEx(struct torture_context
*tctx
, struct dcerpc_pipe
*p
)
111 struct svcctl_QueryServiceStatusEx r
;
112 struct policy_handle h
, s
;
115 uint32_t info_level
= SVC_STATUS_PROCESS_INFO
;
117 uint32_t offered
= 0;
120 if (!test_OpenSCManager(p
, tctx
, &h
))
123 if (!test_OpenService(p
, tctx
, &h
, TORTURE_DEFAULT_SERVICE
, &s
))
126 buffer
= talloc(tctx
, uint8_t);
129 r
.in
.info_level
= info_level
;
130 r
.in
.offered
= offered
;
131 r
.out
.buffer
= buffer
;
132 r
.out
.needed
= &needed
;
134 status
= dcerpc_svcctl_QueryServiceStatusEx(p
, tctx
, &r
);
135 torture_assert_ntstatus_ok(tctx
, status
, "QueryServiceStatusEx failed!");
137 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
138 r
.in
.offered
= needed
;
139 buffer
= talloc_array(tctx
, uint8_t, needed
);
140 r
.out
.buffer
= buffer
;
142 status
= dcerpc_svcctl_QueryServiceStatusEx(p
, tctx
, &r
);
143 torture_assert_ntstatus_ok(tctx
, status
, "QueryServiceStatusEx failed!");
144 torture_assert_werr_ok(tctx
, r
.out
.result
, "QueryServiceStatusEx failed!");
147 if (!test_CloseServiceHandle(p
, tctx
, &s
))
150 if (!test_CloseServiceHandle(p
, tctx
, &h
))
156 static bool test_QueryServiceConfigW(struct torture_context
*tctx
,
157 struct dcerpc_pipe
*p
)
159 struct svcctl_QueryServiceConfigW r
;
160 struct QUERY_SERVICE_CONFIG query
;
161 struct policy_handle h
, s
;
164 uint32_t offered
= 0;
167 if (!test_OpenSCManager(p
, tctx
, &h
))
170 if (!test_OpenService(p
, tctx
, &h
, TORTURE_DEFAULT_SERVICE
, &s
))
174 r
.in
.offered
= offered
;
175 r
.out
.query
= &query
;
176 r
.out
.needed
= &needed
;
178 status
= dcerpc_svcctl_QueryServiceConfigW(p
, tctx
, &r
);
179 torture_assert_ntstatus_ok(tctx
, status
, "QueryServiceConfigW failed!");
181 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
182 r
.in
.offered
= needed
;
183 status
= dcerpc_svcctl_QueryServiceConfigW(p
, tctx
, &r
);
184 torture_assert_ntstatus_ok(tctx
, status
, "QueryServiceConfigW failed!");
187 torture_assert_werr_ok(tctx
, r
.out
.result
, "QueryServiceConfigW failed!");
189 if (!test_CloseServiceHandle(p
, tctx
, &s
))
192 if (!test_CloseServiceHandle(p
, tctx
, &h
))
198 static bool test_QueryServiceConfig2W(struct torture_context
*tctx
, struct dcerpc_pipe
*p
)
200 struct svcctl_QueryServiceConfig2W r
;
201 struct policy_handle h
, s
;
204 uint32_t info_level
= SERVICE_CONFIG_DESCRIPTION
;
206 uint32_t offered
= 0;
209 if (!test_OpenSCManager(p
, tctx
, &h
))
212 if (!test_OpenService(p
, tctx
, &h
, TORTURE_DEFAULT_SERVICE
, &s
))
215 buffer
= talloc(tctx
, uint8_t);
218 r
.in
.info_level
= info_level
;
219 r
.in
.offered
= offered
;
220 r
.out
.buffer
= buffer
;
221 r
.out
.needed
= &needed
;
223 status
= dcerpc_svcctl_QueryServiceConfig2W(p
, tctx
, &r
);
224 torture_assert_ntstatus_ok(tctx
, status
, "QueryServiceConfig2W failed!");
226 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
227 r
.in
.offered
= needed
;
228 buffer
= talloc_array(tctx
, uint8_t, needed
);
229 r
.out
.buffer
= buffer
;
231 status
= dcerpc_svcctl_QueryServiceConfig2W(p
, tctx
, &r
);
232 torture_assert_ntstatus_ok(tctx
, status
, "QueryServiceConfig2W failed!");
233 torture_assert_werr_ok(tctx
, r
.out
.result
, "QueryServiceConfig2W failed!");
236 r
.in
.info_level
= SERVICE_CONFIG_FAILURE_ACTIONS
;
237 r
.in
.offered
= offered
;
238 r
.out
.buffer
= buffer
;
239 r
.out
.needed
= &needed
;
241 status
= dcerpc_svcctl_QueryServiceConfig2W(p
, tctx
, &r
);
242 torture_assert_ntstatus_ok(tctx
, status
, "QueryServiceConfig2W failed!");
244 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
245 r
.in
.offered
= needed
;
246 buffer
= talloc_array(tctx
, uint8_t, needed
);
247 r
.out
.buffer
= buffer
;
249 status
= dcerpc_svcctl_QueryServiceConfig2W(p
, tctx
, &r
);
250 torture_assert_ntstatus_ok(tctx
, status
, "QueryServiceConfig2W failed!");
251 torture_assert_werr_ok(tctx
, r
.out
.result
, "QueryServiceConfig2W failed!");
254 if (!test_CloseServiceHandle(p
, tctx
, &s
))
257 if (!test_CloseServiceHandle(p
, tctx
, &h
))
263 static bool test_QueryServiceObjectSecurity(struct torture_context
*tctx
,
264 struct dcerpc_pipe
*p
)
266 struct svcctl_QueryServiceObjectSecurity r
;
267 struct policy_handle h
, s
;
272 if (!test_OpenSCManager(p
, tctx
, &h
))
275 if (!test_OpenService(p
, tctx
, &h
, TORTURE_DEFAULT_SERVICE
, &s
))
279 r
.in
.security_flags
= 0;
282 r
.out
.needed
= &needed
;
284 torture_assert_ntstatus_ok(tctx
,
285 dcerpc_svcctl_QueryServiceObjectSecurity(p
, tctx
, &r
),
286 "QueryServiceObjectSecurity failed!");
287 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PARAM
,
288 "QueryServiceObjectSecurity failed!");
290 r
.in
.security_flags
= SECINFO_DACL
;
292 torture_assert_ntstatus_ok(tctx
,
293 dcerpc_svcctl_QueryServiceObjectSecurity(p
, tctx
, &r
),
294 "QueryServiceObjectSecurity failed!");
296 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
297 r
.in
.offered
= needed
;
298 buffer
= talloc_array(tctx
, uint8_t, needed
);
299 r
.out
.buffer
= buffer
;
300 torture_assert_ntstatus_ok(tctx
,
301 dcerpc_svcctl_QueryServiceObjectSecurity(p
, tctx
, &r
),
302 "QueryServiceObjectSecurity failed!");
305 torture_assert_werr_ok(tctx
, r
.out
.result
, "QueryServiceObjectSecurity failed!");
307 if (!test_CloseServiceHandle(p
, tctx
, &s
))
310 if (!test_CloseServiceHandle(p
, tctx
, &h
))
316 static bool test_StartServiceW(struct torture_context
*tctx
,
317 struct dcerpc_pipe
*p
)
319 struct svcctl_StartServiceW r
;
320 struct policy_handle h
, s
;
322 if (!test_OpenSCManager(p
, tctx
, &h
))
325 if (!test_OpenService(p
, tctx
, &h
, TORTURE_DEFAULT_SERVICE
, &s
))
330 r
.in
.Arguments
= NULL
;
332 torture_assert_ntstatus_ok(tctx
,
333 dcerpc_svcctl_StartServiceW(p
, tctx
, &r
),
334 "StartServiceW failed!");
335 torture_assert_werr_equal(tctx
, r
.out
.result
,
336 WERR_SERVICE_ALREADY_RUNNING
,
337 "StartServiceW failed!");
339 if (!test_CloseServiceHandle(p
, tctx
, &s
))
342 if (!test_CloseServiceHandle(p
, tctx
, &h
))
348 static bool test_ControlService(struct torture_context
*tctx
,
349 struct dcerpc_pipe
*p
)
351 struct svcctl_ControlService r
;
352 struct policy_handle h
, s
;
353 struct SERVICE_STATUS service_status
;
355 if (!test_OpenSCManager(p
, tctx
, &h
))
358 if (!test_OpenService(p
, tctx
, &h
, TORTURE_DEFAULT_SERVICE
, &s
))
363 r
.out
.service_status
= &service_status
;
365 torture_assert_ntstatus_ok(tctx
,
366 dcerpc_svcctl_ControlService(p
, tctx
, &r
),
367 "ControlService failed!");
368 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PARAM
,
369 "ControlService failed!");
371 if (!test_CloseServiceHandle(p
, tctx
, &s
))
374 if (!test_CloseServiceHandle(p
, tctx
, &h
))
380 static bool test_EnumServicesStatus(struct torture_context
*tctx
, struct dcerpc_pipe
*p
)
382 struct svcctl_EnumServicesStatusW r
;
383 struct policy_handle h
;
386 uint32_t resume_handle
= 0;
387 struct ENUM_SERVICE_STATUSW
*service
= NULL
;
389 uint32_t services_returned
= 0;
391 if (!test_OpenSCManager(p
, tctx
, &h
))
395 r
.in
.type
= SERVICE_TYPE_WIN32
;
396 r
.in
.state
= SERVICE_STATE_ALL
;
398 r
.in
.resume_handle
= &resume_handle
;
399 r
.out
.service
= NULL
;
400 r
.out
.resume_handle
= &resume_handle
;
401 r
.out
.services_returned
= &services_returned
;
402 r
.out
.needed
= &needed
;
404 status
= dcerpc_svcctl_EnumServicesStatusW(p
, tctx
, &r
);
406 torture_assert_ntstatus_ok(tctx
, status
, "EnumServicesStatus failed!");
408 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
409 r
.in
.offered
= needed
;
410 r
.out
.service
= talloc_array(tctx
, uint8_t, needed
);
412 status
= dcerpc_svcctl_EnumServicesStatusW(p
, tctx
, &r
);
414 torture_assert_ntstatus_ok(tctx
, status
, "EnumServicesStatus failed!");
415 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumServicesStatus failed");
418 if (services_returned
> 0) {
420 enum ndr_err_code ndr_err
;
422 struct ndr_pull
*ndr
;
424 blob
.length
= r
.in
.offered
;
425 blob
.data
= talloc_steal(tctx
, r
.out
.service
);
427 ndr
= ndr_pull_init_blob(&blob
, tctx
, lp_iconv_convenience(tctx
->lp_ctx
));
429 service
= talloc_array(tctx
, struct ENUM_SERVICE_STATUSW
, services_returned
);
434 ndr_err
= ndr_pull_ENUM_SERVICE_STATUSW_array(
435 ndr
, services_returned
, service
);
436 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
441 for(i
= 0; i
< services_returned
; i
++) {
443 torture_assert(tctx
, service
[i
].service_name
,
444 "Service without name returned!");
446 printf("%-20s \"%s\", Type: %d, State: %d\n",
447 service
[i
].service_name
, service
[i
].display_name
,
448 service
[i
].status
.type
, service
[i
].status
.state
);
451 if (!test_CloseServiceHandle(p
, tctx
, &h
))
457 static bool test_EnumDependentServicesW(struct torture_context
*tctx
,
458 struct dcerpc_pipe
*p
)
460 struct svcctl_EnumDependentServicesW r
;
461 struct policy_handle h
, s
;
463 uint32_t services_returned
;
465 uint32_t states
[] = { SERVICE_STATE_ACTIVE
,
466 SERVICE_STATE_INACTIVE
,
469 if (!test_OpenSCManager(p
, tctx
, &h
))
472 if (!test_OpenService(p
, tctx
, &h
, TORTURE_DEFAULT_SERVICE
, &s
))
478 r
.out
.service_status
= NULL
;
479 r
.out
.services_returned
= &services_returned
;
480 r
.out
.needed
= &needed
;
482 torture_assert_ntstatus_ok(tctx
,
483 dcerpc_svcctl_EnumDependentServicesW(p
, tctx
, &r
),
484 "EnumDependentServicesW failed!");
486 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PARAM
,
487 "EnumDependentServicesW failed!");
489 for (i
=0; i
<ARRAY_SIZE(states
); i
++) {
491 r
.in
.state
= states
[i
];
493 torture_assert_ntstatus_ok(tctx
,
494 dcerpc_svcctl_EnumDependentServicesW(p
, tctx
, &r
),
495 "EnumDependentServicesW failed!");
497 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
498 r
.in
.offered
= needed
;
499 r
.out
.service_status
= talloc_array(tctx
, uint8_t, needed
);
501 torture_assert_ntstatus_ok(tctx
,
502 dcerpc_svcctl_EnumDependentServicesW(p
, tctx
, &r
),
503 "EnumDependentServicesW failed!");
507 torture_assert_werr_ok(tctx
, r
.out
.result
,
508 "EnumDependentServicesW failed");
511 if (!test_CloseServiceHandle(p
, tctx
, &s
))
514 if (!test_CloseServiceHandle(p
, tctx
, &h
))
520 static bool test_SCManager(struct torture_context
*tctx
,
521 struct dcerpc_pipe
*p
)
523 struct policy_handle h
;
525 if (!test_OpenSCManager(p
, tctx
, &h
))
528 if (!test_CloseServiceHandle(p
, tctx
, &h
))
534 struct torture_suite
*torture_rpc_svcctl(TALLOC_CTX
*mem_ctx
)
536 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "SVCCTL");
537 struct torture_rpc_tcase
*tcase
;
539 tcase
= torture_suite_add_rpc_iface_tcase(suite
, "svcctl", &ndr_table_svcctl
);
541 torture_rpc_tcase_add_test(tcase
, "SCManager",
543 torture_rpc_tcase_add_test(tcase
, "EnumServicesStatus",
544 test_EnumServicesStatus
);
545 torture_rpc_tcase_add_test(tcase
, "EnumDependentServicesW",
546 test_EnumDependentServicesW
);
547 torture_rpc_tcase_add_test(tcase
, "QueryServiceStatus",
548 test_QueryServiceStatus
);
549 torture_rpc_tcase_add_test(tcase
, "QueryServiceStatusEx",
550 test_QueryServiceStatusEx
);
551 torture_rpc_tcase_add_test(tcase
, "QueryServiceConfigW",
552 test_QueryServiceConfigW
);
553 torture_rpc_tcase_add_test(tcase
, "QueryServiceConfig2W",
554 test_QueryServiceConfig2W
);
555 torture_rpc_tcase_add_test(tcase
, "QueryServiceObjectSecurity",
556 test_QueryServiceObjectSecurity
);
557 torture_rpc_tcase_add_test(tcase
, "StartServiceW",
559 torture_rpc_tcase_add_test(tcase
, "ControlService",
560 test_ControlService
);