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 static bool test_OpenSCManager(struct dcerpc_pipe
*p
, struct torture_context
*tctx
, struct policy_handle
*h
)
31 struct svcctl_OpenSCManagerW r
;
33 r
.in
.MachineName
= NULL
;
34 r
.in
.DatabaseName
= NULL
;
35 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
38 torture_assert_ntstatus_ok(tctx
,
39 dcerpc_svcctl_OpenSCManagerW(p
, tctx
, &r
),
40 "OpenSCManager failed!");
45 static bool test_CloseServiceHandle(struct dcerpc_pipe
*p
, struct torture_context
*tctx
, struct policy_handle
*h
)
47 struct svcctl_CloseServiceHandle r
;
51 torture_assert_ntstatus_ok(tctx
,
52 dcerpc_svcctl_CloseServiceHandle(p
, tctx
, &r
),
53 "CloseServiceHandle failed");
58 static bool test_OpenService(struct dcerpc_pipe
*p
, struct torture_context
*tctx
,
59 struct policy_handle
*h
, const char *name
, struct policy_handle
*s
)
61 struct svcctl_OpenServiceW r
;
63 r
.in
.scmanager_handle
= h
;
64 r
.in
.ServiceName
= name
;
65 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
68 torture_assert_ntstatus_ok(tctx
,
69 dcerpc_svcctl_OpenServiceW(p
, tctx
, &r
),
70 "OpenServiceW failed!");
71 torture_assert_werr_ok(tctx
, r
.out
.result
, "OpenServiceW failed!");
77 static bool test_QueryServiceStatus(struct torture_context
*tctx
,
78 struct dcerpc_pipe
*p
)
80 struct svcctl_QueryServiceStatus r
;
81 struct policy_handle h
, s
;
82 struct SERVICE_STATUS service_status
;
85 if (!test_OpenSCManager(p
, tctx
, &h
))
88 if (!test_OpenService(p
, tctx
, &h
, "Netlogon", &s
))
92 r
.out
.service_status
= &service_status
;
94 status
= dcerpc_svcctl_QueryServiceStatus(p
, tctx
, &r
);
95 torture_assert_ntstatus_ok(tctx
, status
, "QueryServiceStatus failed!");
96 torture_assert_werr_ok(tctx
, r
.out
.result
, "QueryServiceStatus failed!");
98 if (!test_CloseServiceHandle(p
, tctx
, &s
))
101 if (!test_CloseServiceHandle(p
, tctx
, &h
))
107 static bool test_QueryServiceStatusEx(struct torture_context
*tctx
, struct dcerpc_pipe
*p
)
109 struct svcctl_QueryServiceStatusEx r
;
110 struct policy_handle h
, s
;
113 uint32_t info_level
= SVC_STATUS_PROCESS_INFO
;
115 uint32_t offered
= 0;
118 if (!test_OpenSCManager(p
, tctx
, &h
))
121 if (!test_OpenService(p
, tctx
, &h
, "Netlogon", &s
))
124 buffer
= talloc(tctx
, uint8_t);
127 r
.in
.info_level
= info_level
;
128 r
.in
.offered
= offered
;
129 r
.out
.buffer
= buffer
;
130 r
.out
.needed
= &needed
;
132 status
= dcerpc_svcctl_QueryServiceStatusEx(p
, tctx
, &r
);
133 torture_assert_ntstatus_ok(tctx
, status
, "QueryServiceStatusEx failed!");
135 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
136 r
.in
.offered
= needed
;
137 buffer
= talloc_array(tctx
, uint8_t, needed
);
138 r
.out
.buffer
= buffer
;
140 status
= dcerpc_svcctl_QueryServiceStatusEx(p
, tctx
, &r
);
141 torture_assert_ntstatus_ok(tctx
, status
, "QueryServiceStatusEx failed!");
142 torture_assert_werr_ok(tctx
, r
.out
.result
, "QueryServiceStatusEx failed!");
145 if (!test_CloseServiceHandle(p
, tctx
, &s
))
148 if (!test_CloseServiceHandle(p
, tctx
, &h
))
154 static bool test_QueryServiceConfigW(struct torture_context
*tctx
,
155 struct dcerpc_pipe
*p
)
157 struct svcctl_QueryServiceConfigW r
;
158 struct QUERY_SERVICE_CONFIG query
;
159 struct policy_handle h
, s
;
162 uint32_t offered
= 0;
165 if (!test_OpenSCManager(p
, tctx
, &h
))
168 if (!test_OpenService(p
, tctx
, &h
, "Netlogon", &s
))
172 r
.in
.offered
= offered
;
173 r
.out
.query
= &query
;
174 r
.out
.needed
= &needed
;
176 status
= dcerpc_svcctl_QueryServiceConfigW(p
, tctx
, &r
);
177 torture_assert_ntstatus_ok(tctx
, status
, "QueryServiceConfigW failed!");
179 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
180 r
.in
.offered
= needed
;
181 status
= dcerpc_svcctl_QueryServiceConfigW(p
, tctx
, &r
);
182 torture_assert_ntstatus_ok(tctx
, status
, "QueryServiceConfigW failed!");
185 torture_assert_werr_ok(tctx
, r
.out
.result
, "QueryServiceConfigW failed!");
187 if (!test_CloseServiceHandle(p
, tctx
, &s
))
190 if (!test_CloseServiceHandle(p
, tctx
, &h
))
196 static bool test_QueryServiceConfig2W(struct torture_context
*tctx
, struct dcerpc_pipe
*p
)
198 struct svcctl_QueryServiceConfig2W r
;
199 struct policy_handle h
, s
;
202 uint32_t info_level
= SERVICE_CONFIG_DESCRIPTION
;
204 uint32_t offered
= 0;
207 if (!test_OpenSCManager(p
, tctx
, &h
))
210 if (!test_OpenService(p
, tctx
, &h
, "Netlogon", &s
))
213 buffer
= talloc(tctx
, uint8_t);
216 r
.in
.info_level
= info_level
;
217 r
.in
.offered
= offered
;
218 r
.out
.buffer
= buffer
;
219 r
.out
.needed
= &needed
;
221 status
= dcerpc_svcctl_QueryServiceConfig2W(p
, tctx
, &r
);
222 torture_assert_ntstatus_ok(tctx
, status
, "QueryServiceConfig2W failed!");
224 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
225 r
.in
.offered
= needed
;
226 buffer
= talloc_array(tctx
, uint8_t, needed
);
227 r
.out
.buffer
= buffer
;
229 status
= dcerpc_svcctl_QueryServiceConfig2W(p
, tctx
, &r
);
230 torture_assert_ntstatus_ok(tctx
, status
, "QueryServiceConfig2W failed!");
231 torture_assert_werr_ok(tctx
, r
.out
.result
, "QueryServiceConfig2W failed!");
234 r
.in
.info_level
= SERVICE_CONFIG_FAILURE_ACTIONS
;
235 r
.in
.offered
= offered
;
236 r
.out
.buffer
= buffer
;
237 r
.out
.needed
= &needed
;
239 status
= dcerpc_svcctl_QueryServiceConfig2W(p
, tctx
, &r
);
240 torture_assert_ntstatus_ok(tctx
, status
, "QueryServiceConfig2W failed!");
242 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
243 r
.in
.offered
= needed
;
244 buffer
= talloc_array(tctx
, uint8_t, needed
);
245 r
.out
.buffer
= buffer
;
247 status
= dcerpc_svcctl_QueryServiceConfig2W(p
, tctx
, &r
);
248 torture_assert_ntstatus_ok(tctx
, status
, "QueryServiceConfig2W failed!");
249 torture_assert_werr_ok(tctx
, r
.out
.result
, "QueryServiceConfig2W failed!");
252 if (!test_CloseServiceHandle(p
, tctx
, &s
))
255 if (!test_CloseServiceHandle(p
, tctx
, &h
))
261 static bool test_QueryServiceObjectSecurity(struct torture_context
*tctx
,
262 struct dcerpc_pipe
*p
)
264 struct svcctl_QueryServiceObjectSecurity r
;
265 struct policy_handle h
, s
;
270 if (!test_OpenSCManager(p
, tctx
, &h
))
273 if (!test_OpenService(p
, tctx
, &h
, "Netlogon", &s
))
277 r
.in
.security_flags
= 0;
280 r
.out
.needed
= &needed
;
282 torture_assert_ntstatus_ok(tctx
,
283 dcerpc_svcctl_QueryServiceObjectSecurity(p
, tctx
, &r
),
284 "QueryServiceObjectSecurity failed!");
285 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PARAM
,
286 "QueryServiceObjectSecurity failed!");
288 r
.in
.security_flags
= SECINFO_DACL
;
290 torture_assert_ntstatus_ok(tctx
,
291 dcerpc_svcctl_QueryServiceObjectSecurity(p
, tctx
, &r
),
292 "QueryServiceObjectSecurity failed!");
294 if (W_ERROR_EQUAL(r
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
295 r
.in
.offered
= needed
;
296 buffer
= talloc_array(tctx
, uint8_t, needed
);
297 r
.out
.buffer
= buffer
;
298 torture_assert_ntstatus_ok(tctx
,
299 dcerpc_svcctl_QueryServiceObjectSecurity(p
, tctx
, &r
),
300 "QueryServiceObjectSecurity failed!");
303 torture_assert_werr_ok(tctx
, r
.out
.result
, "QueryServiceObjectSecurity failed!");
305 if (!test_CloseServiceHandle(p
, tctx
, &s
))
308 if (!test_CloseServiceHandle(p
, tctx
, &h
))
314 static bool test_EnumServicesStatus(struct torture_context
*tctx
, struct dcerpc_pipe
*p
)
316 struct svcctl_EnumServicesStatusW r
;
317 struct policy_handle h
;
320 uint32_t resume_handle
= 0;
321 struct ENUM_SERVICE_STATUSW
*service
= NULL
;
323 uint32_t services_returned
= 0;
325 if (!test_OpenSCManager(p
, tctx
, &h
))
329 r
.in
.type
= SERVICE_TYPE_WIN32
;
330 r
.in
.state
= SERVICE_STATE_ALL
;
332 r
.in
.resume_handle
= &resume_handle
;
333 r
.out
.service
= NULL
;
334 r
.out
.resume_handle
= &resume_handle
;
335 r
.out
.services_returned
= &services_returned
;
336 r
.out
.needed
= &needed
;
338 status
= dcerpc_svcctl_EnumServicesStatusW(p
, tctx
, &r
);
340 torture_assert_ntstatus_ok(tctx
, status
, "EnumServicesStatus failed!");
342 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
343 r
.in
.offered
= needed
;
344 r
.out
.service
= talloc_array(tctx
, uint8_t, needed
);
346 status
= dcerpc_svcctl_EnumServicesStatusW(p
, tctx
, &r
);
348 torture_assert_ntstatus_ok(tctx
, status
, "EnumServicesStatus failed!");
349 torture_assert_werr_ok(tctx
, r
.out
.result
, "EnumServicesStatus failed");
352 if (services_returned
> 0) {
354 enum ndr_err_code ndr_err
;
356 struct ndr_pull
*ndr
;
358 blob
.length
= r
.in
.offered
;
359 blob
.data
= talloc_steal(tctx
, r
.out
.service
);
361 ndr
= ndr_pull_init_blob(&blob
, tctx
, lp_iconv_convenience(tctx
->lp_ctx
));
363 service
= talloc_array(tctx
, struct ENUM_SERVICE_STATUSW
, services_returned
);
368 ndr_err
= ndr_pull_ENUM_SERVICE_STATUSW_array(
369 ndr
, services_returned
, service
);
370 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
375 for(i
= 0; i
< services_returned
; i
++) {
377 torture_assert(tctx
, service
[i
].service_name
,
378 "Service without name returned!");
380 printf("%-20s \"%s\", Type: %d, State: %d\n",
381 service
[i
].service_name
, service
[i
].display_name
,
382 service
[i
].status
.type
, service
[i
].status
.state
);
385 if (!test_CloseServiceHandle(p
, tctx
, &h
))
391 static bool test_EnumDependentServicesW(struct torture_context
*tctx
,
392 struct dcerpc_pipe
*p
)
394 struct svcctl_EnumDependentServicesW r
;
395 struct policy_handle h
, s
;
397 uint32_t services_returned
;
399 uint32_t states
[] = { SERVICE_STATE_ACTIVE
,
400 SERVICE_STATE_INACTIVE
,
403 if (!test_OpenSCManager(p
, tctx
, &h
))
406 if (!test_OpenService(p
, tctx
, &h
, "Netlogon", &s
))
412 r
.out
.service_status
= NULL
;
413 r
.out
.services_returned
= &services_returned
;
414 r
.out
.needed
= &needed
;
416 torture_assert_ntstatus_ok(tctx
,
417 dcerpc_svcctl_EnumDependentServicesW(p
, tctx
, &r
),
418 "EnumDependentServicesW failed!");
420 torture_assert_werr_equal(tctx
, r
.out
.result
, WERR_INVALID_PARAM
,
421 "EnumDependentServicesW failed!");
423 for (i
=0; i
<ARRAY_SIZE(states
); i
++) {
425 r
.in
.state
= states
[i
];
427 torture_assert_ntstatus_ok(tctx
,
428 dcerpc_svcctl_EnumDependentServicesW(p
, tctx
, &r
),
429 "EnumDependentServicesW failed!");
431 if (W_ERROR_EQUAL(r
.out
.result
, WERR_MORE_DATA
)) {
432 r
.in
.offered
= needed
;
433 r
.out
.service_status
= talloc_array(tctx
, uint8_t, needed
);
435 torture_assert_ntstatus_ok(tctx
,
436 dcerpc_svcctl_EnumDependentServicesW(p
, tctx
, &r
),
437 "EnumDependentServicesW failed!");
441 torture_assert_werr_ok(tctx
, r
.out
.result
,
442 "EnumDependentServicesW failed");
445 if (!test_CloseServiceHandle(p
, tctx
, &s
))
448 if (!test_CloseServiceHandle(p
, tctx
, &h
))
454 static bool test_SCManager(struct torture_context
*tctx
,
455 struct dcerpc_pipe
*p
)
457 struct policy_handle h
;
459 if (!test_OpenSCManager(p
, tctx
, &h
))
462 if (!test_CloseServiceHandle(p
, tctx
, &h
))
468 struct torture_suite
*torture_rpc_svcctl(TALLOC_CTX
*mem_ctx
)
470 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "SVCCTL");
471 struct torture_rpc_tcase
*tcase
;
473 tcase
= torture_suite_add_rpc_iface_tcase(suite
, "svcctl", &ndr_table_svcctl
);
475 torture_rpc_tcase_add_test(tcase
, "SCManager",
477 torture_rpc_tcase_add_test(tcase
, "EnumServicesStatus",
478 test_EnumServicesStatus
);
479 torture_rpc_tcase_add_test(tcase
, "EnumDependentServicesW",
480 test_EnumDependentServicesW
);
481 torture_rpc_tcase_add_test(tcase
, "QueryServiceStatus",
482 test_QueryServiceStatus
);
483 torture_rpc_tcase_add_test(tcase
, "QueryServiceStatusEx",
484 test_QueryServiceStatusEx
);
485 torture_rpc_tcase_add_test(tcase
, "QueryServiceConfigW",
486 test_QueryServiceConfigW
);
487 torture_rpc_tcase_add_test(tcase
, "QueryServiceConfig2W",
488 test_QueryServiceConfig2W
);
489 torture_rpc_tcase_add_test(tcase
, "QueryServiceObjectSecurity",
490 test_QueryServiceObjectSecurity
);