s4:ldb Change ldb_request_add_control to the normal 'for loop' pattern
[Samba/cd1.git] / source4 / torture / rpc / svcctl.c
blobce6a0853ab325cd252beac2eacb4a0d1c9b4e1a0
1 /*
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/>.
22 #include "includes.h"
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;
37 r.out.handle = h;
39 torture_assert_ntstatus_ok(tctx,
40 dcerpc_svcctl_OpenSCManagerW(p, tctx, &r),
41 "OpenSCManager failed!");
43 return true;
46 static bool test_CloseServiceHandle(struct dcerpc_pipe *p, struct torture_context *tctx, struct policy_handle *h)
48 struct svcctl_CloseServiceHandle r;
50 r.in.handle = h;
51 r.out.handle = h;
52 torture_assert_ntstatus_ok(tctx,
53 dcerpc_svcctl_CloseServiceHandle(p, tctx, &r),
54 "CloseServiceHandle failed");
56 return true;
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;
67 r.out.handle = s;
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!");
74 return true;
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;
84 NTSTATUS status;
86 if (!test_OpenSCManager(p, tctx, &h))
87 return false;
89 if (!test_OpenService(p, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
90 return false;
92 r.in.handle = &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))
100 return false;
102 if (!test_CloseServiceHandle(p, tctx, &h))
103 return false;
105 return true;
108 static bool test_QueryServiceStatusEx(struct torture_context *tctx, struct dcerpc_pipe *p)
110 struct svcctl_QueryServiceStatusEx r;
111 struct policy_handle h, s;
112 NTSTATUS status;
114 uint32_t info_level = SVC_STATUS_PROCESS_INFO;
115 uint8_t *buffer;
116 uint32_t offered = 0;
117 uint32_t needed = 0;
119 if (!test_OpenSCManager(p, tctx, &h))
120 return false;
122 if (!test_OpenService(p, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
123 return false;
125 buffer = talloc(tctx, uint8_t);
127 r.in.handle = &s;
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))
147 return false;
149 if (!test_CloseServiceHandle(p, tctx, &h))
150 return false;
152 return true;
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;
161 NTSTATUS status;
163 uint32_t offered = 0;
164 uint32_t needed = 0;
166 if (!test_OpenSCManager(p, tctx, &h))
167 return false;
169 if (!test_OpenService(p, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
170 return false;
172 r.in.handle = &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))
189 return false;
191 if (!test_CloseServiceHandle(p, tctx, &h))
192 return false;
194 return true;
197 static bool test_QueryServiceConfig2W(struct torture_context *tctx, struct dcerpc_pipe *p)
199 struct svcctl_QueryServiceConfig2W r;
200 struct policy_handle h, s;
201 NTSTATUS status;
203 uint32_t info_level = SERVICE_CONFIG_DESCRIPTION;
204 uint8_t *buffer;
205 uint32_t offered = 0;
206 uint32_t needed = 0;
208 if (!test_OpenSCManager(p, tctx, &h))
209 return false;
211 if (!test_OpenService(p, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
212 return false;
214 buffer = talloc(tctx, uint8_t);
216 r.in.handle = &s;
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))
254 return false;
256 if (!test_CloseServiceHandle(p, tctx, &h))
257 return false;
259 return true;
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;
268 uint8_t *buffer;
269 uint32_t needed;
271 if (!test_OpenSCManager(p, tctx, &h))
272 return false;
274 if (!test_OpenService(p, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
275 return false;
277 r.in.handle = &s;
278 r.in.security_flags = 0;
279 r.in.offered = 0;
280 r.out.buffer = NULL;
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))
307 return false;
309 if (!test_CloseServiceHandle(p, tctx, &h))
310 return false;
312 return true;
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))
322 return false;
324 if (!test_OpenService(p, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
325 return false;
327 r.in.handle = &s;
328 r.in.NumArgs = 0;
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))
339 return false;
341 if (!test_CloseServiceHandle(p, tctx, &h))
342 return false;
344 return true;
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))
355 return false;
357 if (!test_OpenService(p, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
358 return false;
360 r.in.handle = &s;
361 r.in.control = 0;
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))
371 return false;
373 if (!test_CloseServiceHandle(p, tctx, &h))
374 return false;
376 return true;
379 static bool test_EnumServicesStatus(struct torture_context *tctx, struct dcerpc_pipe *p)
381 struct svcctl_EnumServicesStatusW r;
382 struct policy_handle h;
383 int i;
384 NTSTATUS status;
385 uint32_t resume_handle = 0;
386 struct ENUM_SERVICE_STATUSW *service = NULL;
387 uint32_t needed = 0;
388 uint32_t services_returned = 0;
390 if (!test_OpenSCManager(p, tctx, &h))
391 return false;
393 r.in.handle = &h;
394 r.in.type = SERVICE_TYPE_WIN32;
395 r.in.state = SERVICE_STATE_ALL;
396 r.in.offered = 0;
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;
420 DATA_BLOB blob;
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);
429 if (!service) {
430 return false;
433 ndr_err = ndr_pull_ENUM_SERVICE_STATUSW_array(
434 ndr, services_returned, service);
435 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
436 return false;
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))
451 return false;
453 return true;
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;
461 uint32_t needed;
462 uint32_t services_returned;
463 uint32_t i;
464 uint32_t states[] = { SERVICE_STATE_ACTIVE,
465 SERVICE_STATE_INACTIVE,
466 SERVICE_STATE_ALL };
468 if (!test_OpenSCManager(p, tctx, &h))
469 return false;
471 if (!test_OpenService(p, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
472 return false;
474 r.in.service = &s;
475 r.in.offered = 0;
476 r.in.state = 0;
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))
511 return false;
513 if (!test_CloseServiceHandle(p, tctx, &h))
514 return false;
516 return true;
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))
525 return false;
527 if (!test_CloseServiceHandle(p, tctx, &h))
528 return false;
530 return true;
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",
541 test_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",
557 test_StartServiceW);
558 torture_rpc_tcase_add_test(tcase, "ControlService",
559 test_ControlService);
561 return suite;