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_pipe
*p
, struct torture_context
*tctx
, struct policy_handle
*h
)
32 struct svcctl_OpenSCManagerW r
;
34 r
.in
.MachineName
= NULL
;
35 r
.in
.DatabaseName
= NULL
;
36 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
39 torture_assert_ntstatus_ok(tctx
,
40 dcerpc_svcctl_OpenSCManagerW(p
, tctx
, &r
),
41 "OpenSCManager failed!");
46 static bool test_CloseServiceHandle(struct dcerpc_pipe
*p
, struct torture_context
*tctx
, struct policy_handle
*h
)
48 struct svcctl_CloseServiceHandle r
;
52 torture_assert_ntstatus_ok(tctx
,
53 dcerpc_svcctl_CloseServiceHandle(p
, tctx
, &r
),
54 "CloseServiceHandle failed");
59 static bool test_OpenService(struct dcerpc_pipe
*p
, struct torture_context
*tctx
,
60 struct policy_handle
*h
, const char *name
, struct policy_handle
*s
)
62 struct svcctl_OpenServiceW r
;
64 r
.in
.scmanager_handle
= h
;
65 r
.in
.ServiceName
= name
;
66 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
69 torture_assert_ntstatus_ok(tctx
,
70 dcerpc_svcctl_OpenServiceW(p
, tctx
, &r
),
71 "OpenServiceW failed!");
72 torture_assert_werr_ok(tctx
, r
.out
.result
, "OpenServiceW failed!");
78 static bool test_QueryServiceStatus(struct torture_context
*tctx
,
79 struct dcerpc_pipe
*p
)
81 struct svcctl_QueryServiceStatus r
;
82 struct policy_handle h
, s
;
83 struct SERVICE_STATUS service_status
;
86 if (!test_OpenSCManager(p
, tctx
, &h
))
89 if (!test_OpenService(p
, tctx
, &h
, TORTURE_DEFAULT_SERVICE
, &s
))
93 r
.out
.service_status
= &service_status
;
95 status
= dcerpc_svcctl_QueryServiceStatus(p
, tctx
, &r
);
96 torture_assert_ntstatus_ok(tctx
, status
, "QueryServiceStatus failed!");
97 torture_assert_werr_ok(tctx
, r
.out
.result
, "QueryServiceStatus failed!");
99 if (!test_CloseServiceHandle(p
, tctx
, &s
))
102 if (!test_CloseServiceHandle(p
, tctx
, &h
))
108 static bool test_QueryServiceStatusEx(struct torture_context
*tctx
, struct dcerpc_pipe
*p
)
110 struct svcctl_QueryServiceStatusEx r
;
111 struct policy_handle h
, s
;
114 uint32_t info_level
= SVC_STATUS_PROCESS_INFO
;
116 uint32_t offered
= 0;
119 if (!test_OpenSCManager(p
, tctx
, &h
))
122 if (!test_OpenService(p
, tctx
, &h
, TORTURE_DEFAULT_SERVICE
, &s
))
125 buffer
= talloc(tctx
, uint8_t);
128 r
.in
.info_level
= info_level
;
129 r
.in
.offered
= offered
;
130 r
.out
.buffer
= buffer
;
131 r
.out
.needed
= &needed
;
133 status
= dcerpc_svcctl_QueryServiceStatusEx(p
, tctx
, &r
);
134 torture_assert_ntstatus_ok(tctx
, status
, "QueryServiceStatusEx failed!");
136 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
137 r
.in
.offered
= needed
;
138 buffer
= talloc_array(tctx
, uint8_t, needed
);
139 r
.out
.buffer
= buffer
;
141 status
= dcerpc_svcctl_QueryServiceStatusEx(p
, tctx
, &r
);
142 torture_assert_ntstatus_ok(tctx
, status
, "QueryServiceStatusEx failed!");
143 torture_assert_werr_ok(tctx
, r
.out
.result
, "QueryServiceStatusEx failed!");
146 if (!test_CloseServiceHandle(p
, tctx
, &s
))
149 if (!test_CloseServiceHandle(p
, tctx
, &h
))
155 static bool test_QueryServiceConfigW(struct torture_context
*tctx
,
156 struct dcerpc_pipe
*p
)
158 struct svcctl_QueryServiceConfigW r
;
159 struct QUERY_SERVICE_CONFIG query
;
160 struct policy_handle h
, s
;
163 uint32_t offered
= 0;
166 if (!test_OpenSCManager(p
, tctx
, &h
))
169 if (!test_OpenService(p
, tctx
, &h
, TORTURE_DEFAULT_SERVICE
, &s
))
173 r
.in
.offered
= offered
;
174 r
.out
.query
= &query
;
175 r
.out
.needed
= &needed
;
177 status
= dcerpc_svcctl_QueryServiceConfigW(p
, tctx
, &r
);
178 torture_assert_ntstatus_ok(tctx
, status
, "QueryServiceConfigW failed!");
180 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
181 r
.in
.offered
= needed
;
182 status
= dcerpc_svcctl_QueryServiceConfigW(p
, tctx
, &r
);
183 torture_assert_ntstatus_ok(tctx
, status
, "QueryServiceConfigW failed!");
186 torture_assert_werr_ok(tctx
, r
.out
.result
, "QueryServiceConfigW failed!");
188 if (!test_CloseServiceHandle(p
, tctx
, &s
))
191 if (!test_CloseServiceHandle(p
, tctx
, &h
))
197 static bool test_QueryServiceConfig2W(struct torture_context
*tctx
, struct dcerpc_pipe
*p
)
199 struct svcctl_QueryServiceConfig2W r
;
200 struct policy_handle h
, s
;
203 uint32_t info_level
= SERVICE_CONFIG_DESCRIPTION
;
205 uint32_t offered
= 0;
208 if (!test_OpenSCManager(p
, tctx
, &h
))
211 if (!test_OpenService(p
, tctx
, &h
, TORTURE_DEFAULT_SERVICE
, &s
))
214 buffer
= talloc(tctx
, uint8_t);
217 r
.in
.info_level
= info_level
;
218 r
.in
.offered
= offered
;
219 r
.out
.buffer
= buffer
;
220 r
.out
.needed
= &needed
;
222 status
= dcerpc_svcctl_QueryServiceConfig2W(p
, tctx
, &r
);
223 torture_assert_ntstatus_ok(tctx
, status
, "QueryServiceConfig2W failed!");
225 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
226 r
.in
.offered
= needed
;
227 buffer
= talloc_array(tctx
, uint8_t, needed
);
228 r
.out
.buffer
= buffer
;
230 status
= dcerpc_svcctl_QueryServiceConfig2W(p
, tctx
, &r
);
231 torture_assert_ntstatus_ok(tctx
, status
, "QueryServiceConfig2W failed!");
232 torture_assert_werr_ok(tctx
, r
.out
.result
, "QueryServiceConfig2W failed!");
235 r
.in
.info_level
= SERVICE_CONFIG_FAILURE_ACTIONS
;
236 r
.in
.offered
= offered
;
237 r
.out
.buffer
= buffer
;
238 r
.out
.needed
= &needed
;
240 status
= dcerpc_svcctl_QueryServiceConfig2W(p
, tctx
, &r
);
241 torture_assert_ntstatus_ok(tctx
, status
, "QueryServiceConfig2W failed!");
243 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
244 r
.in
.offered
= needed
;
245 buffer
= talloc_array(tctx
, uint8_t, needed
);
246 r
.out
.buffer
= buffer
;
248 status
= dcerpc_svcctl_QueryServiceConfig2W(p
, tctx
, &r
);
249 torture_assert_ntstatus_ok(tctx
, status
, "QueryServiceConfig2W failed!");
250 torture_assert_werr_ok(tctx
, r
.out
.result
, "QueryServiceConfig2W failed!");
253 if (!test_CloseServiceHandle(p
, tctx
, &s
))
256 if (!test_CloseServiceHandle(p
, tctx
, &h
))
262 static bool test_QueryServiceObjectSecurity(struct torture_context
*tctx
,
263 struct dcerpc_pipe
*p
)
265 struct svcctl_QueryServiceObjectSecurity r
;
266 struct policy_handle h
, s
;
271 if (!test_OpenSCManager(p
, tctx
, &h
))
274 if (!test_OpenService(p
, tctx
, &h
, TORTURE_DEFAULT_SERVICE
, &s
))
278 r
.in
.security_flags
= 0;
281 r
.out
.needed
= &needed
;
283 torture_assert_ntstatus_ok(tctx
,
284 dcerpc_svcctl_QueryServiceObjectSecurity(p
, tctx
, &r
),
285 "QueryServiceObjectSecurity failed!");
286 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PARAM
,
287 "QueryServiceObjectSecurity failed!");
289 r
.in
.security_flags
= SECINFO_DACL
;
291 torture_assert_ntstatus_ok(tctx
,
292 dcerpc_svcctl_QueryServiceObjectSecurity(p
, tctx
, &r
),
293 "QueryServiceObjectSecurity failed!");
295 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
296 r
.in
.offered
= needed
;
297 buffer
= talloc_array(tctx
, uint8_t, needed
);
298 r
.out
.buffer
= buffer
;
299 torture_assert_ntstatus_ok(tctx
,
300 dcerpc_svcctl_QueryServiceObjectSecurity(p
, tctx
, &r
),
301 "QueryServiceObjectSecurity failed!");
304 torture_assert_werr_ok(tctx
, r
.out
.result
, "QueryServiceObjectSecurity failed!");
306 if (!test_CloseServiceHandle(p
, tctx
, &s
))
309 if (!test_CloseServiceHandle(p
, tctx
, &h
))
315 static bool test_StartServiceW(struct torture_context
*tctx
,
316 struct dcerpc_pipe
*p
)
318 struct svcctl_StartServiceW r
;
319 struct policy_handle h
, s
;
321 if (!test_OpenSCManager(p
, tctx
, &h
))
324 if (!test_OpenService(p
, tctx
, &h
, TORTURE_DEFAULT_SERVICE
, &s
))
329 r
.in
.Arguments
= NULL
;
331 torture_assert_ntstatus_ok(tctx
,
332 dcerpc_svcctl_StartServiceW(p
, tctx
, &r
),
333 "StartServiceW failed!");
334 torture_assert_werr_equal(tctx
, r
.out
.result
,
335 WERR_SERVICE_ALREADY_RUNNING
,
336 "StartServiceW failed!");
338 if (!test_CloseServiceHandle(p
, tctx
, &s
))
341 if (!test_CloseServiceHandle(p
, tctx
, &h
))
347 static bool test_ControlService(struct torture_context
*tctx
,
348 struct dcerpc_pipe
*p
)
350 struct svcctl_ControlService r
;
351 struct policy_handle h
, s
;
352 struct SERVICE_STATUS service_status
;
354 if (!test_OpenSCManager(p
, tctx
, &h
))
357 if (!test_OpenService(p
, tctx
, &h
, TORTURE_DEFAULT_SERVICE
, &s
))
362 r
.out
.service_status
= &service_status
;
364 torture_assert_ntstatus_ok(tctx
,
365 dcerpc_svcctl_ControlService(p
, tctx
, &r
),
366 "ControlService failed!");
367 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PARAM
,
368 "ControlService failed!");
370 if (!test_CloseServiceHandle(p
, tctx
, &s
))
373 if (!test_CloseServiceHandle(p
, tctx
, &h
))
379 static bool test_EnumServicesStatus(struct torture_context
*tctx
, struct dcerpc_pipe
*p
)
381 struct svcctl_EnumServicesStatusW r
;
382 struct policy_handle h
;
385 uint32_t resume_handle
= 0;
386 struct ENUM_SERVICE_STATUSW
*service
= NULL
;
388 uint32_t services_returned
= 0;
390 if (!test_OpenSCManager(p
, tctx
, &h
))
394 r
.in
.type
= SERVICE_TYPE_WIN32
;
395 r
.in
.state
= SERVICE_STATE_ALL
;
397 r
.in
.resume_handle
= &resume_handle
;
398 r
.out
.service
= NULL
;
399 r
.out
.resume_handle
= &resume_handle
;
400 r
.out
.services_returned
= &services_returned
;
401 r
.out
.needed
= &needed
;
403 status
= dcerpc_svcctl_EnumServicesStatusW(p
, tctx
, &r
);
405 torture_assert_ntstatus_ok(tctx
, status
, "EnumServicesStatus failed!");
407 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
408 r
.in
.offered
= needed
;
409 r
.out
.service
= talloc_array(tctx
, uint8_t, needed
);
411 status
= dcerpc_svcctl_EnumServicesStatusW(p
, tctx
, &r
);
413 torture_assert_ntstatus_ok(tctx
, status
, "EnumServicesStatus failed!");
414 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumServicesStatus failed");
417 if (services_returned
> 0) {
419 enum ndr_err_code ndr_err
;
421 struct ndr_pull
*ndr
;
423 blob
.length
= r
.in
.offered
;
424 blob
.data
= talloc_steal(tctx
, r
.out
.service
);
426 ndr
= ndr_pull_init_blob(&blob
, tctx
, lp_iconv_convenience(tctx
->lp_ctx
));
428 service
= talloc_array(tctx
, struct ENUM_SERVICE_STATUSW
, services_returned
);
433 ndr_err
= ndr_pull_ENUM_SERVICE_STATUSW_array(
434 ndr
, services_returned
, service
);
435 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
440 for(i
= 0; i
< services_returned
; i
++) {
442 torture_assert(tctx
, service
[i
].service_name
,
443 "Service without name returned!");
445 printf("%-20s \"%s\", Type: %d, State: %d\n",
446 service
[i
].service_name
, service
[i
].display_name
,
447 service
[i
].status
.type
, service
[i
].status
.state
);
450 if (!test_CloseServiceHandle(p
, tctx
, &h
))
456 static bool test_EnumDependentServicesW(struct torture_context
*tctx
,
457 struct dcerpc_pipe
*p
)
459 struct svcctl_EnumDependentServicesW r
;
460 struct policy_handle h
, s
;
462 uint32_t services_returned
;
464 uint32_t states
[] = { SERVICE_STATE_ACTIVE
,
465 SERVICE_STATE_INACTIVE
,
468 if (!test_OpenSCManager(p
, tctx
, &h
))
471 if (!test_OpenService(p
, tctx
, &h
, TORTURE_DEFAULT_SERVICE
, &s
))
477 r
.out
.service_status
= NULL
;
478 r
.out
.services_returned
= &services_returned
;
479 r
.out
.needed
= &needed
;
481 torture_assert_ntstatus_ok(tctx
,
482 dcerpc_svcctl_EnumDependentServicesW(p
, tctx
, &r
),
483 "EnumDependentServicesW failed!");
485 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PARAM
,
486 "EnumDependentServicesW failed!");
488 for (i
=0; i
<ARRAY_SIZE(states
); i
++) {
490 r
.in
.state
= states
[i
];
492 torture_assert_ntstatus_ok(tctx
,
493 dcerpc_svcctl_EnumDependentServicesW(p
, tctx
, &r
),
494 "EnumDependentServicesW failed!");
496 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
497 r
.in
.offered
= needed
;
498 r
.out
.service_status
= talloc_array(tctx
, uint8_t, needed
);
500 torture_assert_ntstatus_ok(tctx
,
501 dcerpc_svcctl_EnumDependentServicesW(p
, tctx
, &r
),
502 "EnumDependentServicesW failed!");
506 torture_assert_werr_ok(tctx
, r
.out
.result
,
507 "EnumDependentServicesW failed");
510 if (!test_CloseServiceHandle(p
, tctx
, &s
))
513 if (!test_CloseServiceHandle(p
, tctx
, &h
))
519 static bool test_SCManager(struct torture_context
*tctx
,
520 struct dcerpc_pipe
*p
)
522 struct policy_handle h
;
524 if (!test_OpenSCManager(p
, tctx
, &h
))
527 if (!test_CloseServiceHandle(p
, tctx
, &h
))
533 struct torture_suite
*torture_rpc_svcctl(TALLOC_CTX
*mem_ctx
)
535 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "SVCCTL");
536 struct torture_rpc_tcase
*tcase
;
538 tcase
= torture_suite_add_rpc_iface_tcase(suite
, "svcctl", &ndr_table_svcctl
);
540 torture_rpc_tcase_add_test(tcase
, "SCManager",
542 torture_rpc_tcase_add_test(tcase
, "EnumServicesStatus",
543 test_EnumServicesStatus
);
544 torture_rpc_tcase_add_test(tcase
, "EnumDependentServicesW",
545 test_EnumDependentServicesW
);
546 torture_rpc_tcase_add_test(tcase
, "QueryServiceStatus",
547 test_QueryServiceStatus
);
548 torture_rpc_tcase_add_test(tcase
, "QueryServiceStatusEx",
549 test_QueryServiceStatusEx
);
550 torture_rpc_tcase_add_test(tcase
, "QueryServiceConfigW",
551 test_QueryServiceConfigW
);
552 torture_rpc_tcase_add_test(tcase
, "QueryServiceConfig2W",
553 test_QueryServiceConfig2W
);
554 torture_rpc_tcase_add_test(tcase
, "QueryServiceObjectSecurity",
555 test_QueryServiceObjectSecurity
);
556 torture_rpc_tcase_add_test(tcase
, "StartServiceW",
558 torture_rpc_tcase_add_test(tcase
, "ControlService",
559 test_ControlService
);