auth/credentials: don't ignore "client use kerberos" and --use-kerberos for machine...
[Samba.git] / source4 / torture / rpc / svcctl.c
blob2962f15b5a3d7ec7e97a53f55ad98e57a1e5a1fe
1 /*
2 Unix SMB/CIFS implementation.
3 test suite for svcctl rpc operations
5 Copyright (C) Jelmer Vernooij 2004
6 Copyright (C) Guenther Deschner 2008,2009,2020
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 "librpc/gen_ndr/ndr_security.h"
26 #include "torture/rpc/torture_rpc.h"
27 #include "param/param.h"
29 #define TORTURE_DEFAULT_SERVICE "Spooler"
31 static bool test_OpenSCManager(struct dcerpc_binding_handle *b,
32 struct torture_context *tctx,
33 struct policy_handle *h)
35 struct svcctl_OpenSCManagerW r;
37 r.in.MachineName = NULL;
38 r.in.DatabaseName = NULL;
39 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
40 r.out.handle = h;
42 torture_assert_ntstatus_ok(tctx,
43 dcerpc_svcctl_OpenSCManagerW_r(b, tctx, &r),
44 "OpenSCManager failed!");
46 return true;
49 static bool test_CloseServiceHandle(struct dcerpc_binding_handle *b,
50 struct torture_context *tctx,
51 struct policy_handle *h)
53 struct svcctl_CloseServiceHandle r;
55 r.in.handle = h;
56 r.out.handle = h;
57 torture_assert_ntstatus_ok(tctx,
58 dcerpc_svcctl_CloseServiceHandle_r(b, tctx, &r),
59 "CloseServiceHandle failed");
61 return true;
64 static bool test_OpenService(struct dcerpc_binding_handle *b,
65 struct torture_context *tctx,
66 struct policy_handle *h,
67 const char *name,
68 struct policy_handle *s)
70 struct svcctl_OpenServiceW r;
72 r.in.scmanager_handle = h;
73 r.in.ServiceName = name;
74 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
75 r.out.handle = s;
77 torture_assert_ntstatus_ok(tctx,
78 dcerpc_svcctl_OpenServiceW_r(b, tctx, &r),
79 "OpenServiceW failed!");
80 torture_assert_werr_ok(tctx, r.out.result, "OpenServiceW failed!");
82 return true;
86 static bool test_QueryServiceStatus(struct torture_context *tctx,
87 struct dcerpc_pipe *p)
89 struct svcctl_QueryServiceStatus r;
90 struct policy_handle h, s;
91 struct SERVICE_STATUS service_status;
92 NTSTATUS status;
93 struct dcerpc_binding_handle *b = p->binding_handle;
95 if (!test_OpenSCManager(b, tctx, &h))
96 return false;
98 if (!test_OpenService(b, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
99 return false;
101 r.in.handle = &s;
102 r.out.service_status = &service_status;
104 status = dcerpc_svcctl_QueryServiceStatus_r(b, tctx, &r);
105 torture_assert_ntstatus_ok(tctx, status, "QueryServiceStatus failed!");
106 torture_assert_werr_ok(tctx, r.out.result, "QueryServiceStatus failed!");
108 if (!test_CloseServiceHandle(b, tctx, &s))
109 return false;
111 if (!test_CloseServiceHandle(b, tctx, &h))
112 return false;
114 return true;
117 static bool test_QueryServiceStatusEx(struct torture_context *tctx, struct dcerpc_pipe *p)
119 struct svcctl_QueryServiceStatusEx r;
120 struct policy_handle h, s;
121 NTSTATUS status;
122 struct dcerpc_binding_handle *b = p->binding_handle;
124 uint32_t info_level = SVC_STATUS_PROCESS_INFO;
125 uint8_t *buffer;
126 uint32_t offered = 0;
127 uint32_t needed = 0;
129 if (!test_OpenSCManager(b, tctx, &h))
130 return false;
132 if (!test_OpenService(b, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
133 return false;
135 buffer = talloc(tctx, uint8_t);
137 r.in.handle = &s;
138 r.in.info_level = info_level;
139 r.in.offered = offered;
140 r.out.buffer = buffer;
141 r.out.needed = &needed;
143 status = dcerpc_svcctl_QueryServiceStatusEx_r(b, tctx, &r);
144 torture_assert_ntstatus_ok(tctx, status, "QueryServiceStatusEx failed!");
146 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
147 r.in.offered = needed;
148 buffer = talloc_array(tctx, uint8_t, needed);
149 r.out.buffer = buffer;
151 status = dcerpc_svcctl_QueryServiceStatusEx_r(b, tctx, &r);
152 torture_assert_ntstatus_ok(tctx, status, "QueryServiceStatusEx failed!");
153 torture_assert_werr_ok(tctx, r.out.result, "QueryServiceStatusEx failed!");
156 if (!test_CloseServiceHandle(b, tctx, &s))
157 return false;
159 if (!test_CloseServiceHandle(b, tctx, &h))
160 return false;
162 return true;
165 static bool test_QueryServiceConfigW(struct torture_context *tctx,
166 struct dcerpc_pipe *p)
168 struct svcctl_QueryServiceConfigW r;
169 struct QUERY_SERVICE_CONFIG query;
170 struct policy_handle h, s;
171 NTSTATUS status;
172 struct dcerpc_binding_handle *b = p->binding_handle;
174 uint32_t offered = 0;
175 uint32_t needed = 0;
177 if (!test_OpenSCManager(b, tctx, &h))
178 return false;
180 if (!test_OpenService(b, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
181 return false;
183 r.in.handle = &s;
184 r.in.offered = offered;
185 r.out.query = &query;
186 r.out.needed = &needed;
188 status = dcerpc_svcctl_QueryServiceConfigW_r(b, tctx, &r);
189 torture_assert_ntstatus_ok(tctx, status, "QueryServiceConfigW failed!");
191 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
192 r.in.offered = needed;
193 status = dcerpc_svcctl_QueryServiceConfigW_r(b, tctx, &r);
194 torture_assert_ntstatus_ok(tctx, status, "QueryServiceConfigW failed!");
197 torture_assert_werr_ok(tctx, r.out.result, "QueryServiceConfigW failed!");
199 if (!test_CloseServiceHandle(b, tctx, &s))
200 return false;
202 if (!test_CloseServiceHandle(b, tctx, &h))
203 return false;
205 return true;
208 static bool test_QueryServiceConfig2W(struct torture_context *tctx, struct dcerpc_pipe *p)
210 struct svcctl_QueryServiceConfig2W r;
211 struct policy_handle h, s;
212 NTSTATUS status;
213 struct dcerpc_binding_handle *b = p->binding_handle;
215 uint32_t info_level = SERVICE_CONFIG_DESCRIPTION;
216 uint8_t *buffer;
217 uint32_t offered = 0;
218 uint32_t needed = 0;
220 if (!test_OpenSCManager(b, tctx, &h))
221 return false;
223 if (!test_OpenService(b, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
224 return false;
226 buffer = talloc(tctx, uint8_t);
228 r.in.handle = &s;
229 r.in.info_level = info_level;
230 r.in.offered = offered;
231 r.out.buffer = buffer;
232 r.out.needed = &needed;
234 status = dcerpc_svcctl_QueryServiceConfig2W_r(b, tctx, &r);
235 torture_assert_ntstatus_ok(tctx, status, "QueryServiceConfig2W failed!");
237 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
238 r.in.offered = needed;
239 buffer = talloc_array(tctx, uint8_t, needed);
240 r.out.buffer = buffer;
242 status = dcerpc_svcctl_QueryServiceConfig2W_r(b, tctx, &r);
243 torture_assert_ntstatus_ok(tctx, status, "QueryServiceConfig2W failed!");
244 torture_assert_werr_ok(tctx, r.out.result, "QueryServiceConfig2W failed!");
247 r.in.info_level = SERVICE_CONFIG_FAILURE_ACTIONS;
248 r.in.offered = offered;
249 r.out.buffer = buffer;
250 r.out.needed = &needed;
252 status = dcerpc_svcctl_QueryServiceConfig2W_r(b, tctx, &r);
253 torture_assert_ntstatus_ok(tctx, status, "QueryServiceConfig2W failed!");
255 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
256 r.in.offered = needed;
257 buffer = talloc_array(tctx, uint8_t, needed);
258 r.out.buffer = buffer;
260 status = dcerpc_svcctl_QueryServiceConfig2W_r(b, tctx, &r);
261 torture_assert_ntstatus_ok(tctx, status, "QueryServiceConfig2W failed!");
262 torture_assert_werr_ok(tctx, r.out.result, "QueryServiceConfig2W failed!");
265 if (!test_CloseServiceHandle(b, tctx, &s))
266 return false;
268 if (!test_CloseServiceHandle(b, tctx, &h))
269 return false;
271 return true;
274 static bool test_QueryServiceConfigEx(struct torture_context *tctx, struct dcerpc_pipe *p)
276 struct svcctl_QueryServiceConfigEx r;
277 struct policy_handle h, s;
278 NTSTATUS status;
279 struct dcerpc_binding_handle *b = p->binding_handle;
280 struct SC_RPC_CONFIG_INFOW info;
281 int i;
283 if (!test_OpenSCManager(b, tctx, &h))
284 return false;
286 if (!test_OpenService(b, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
287 return false;
289 for (i=0; i < 16; i++) {
291 r.in.hService = s;
292 r.in.dwInfoLevel = i;
293 r.out.pInfo = &info;
295 status = dcerpc_svcctl_QueryServiceConfigEx_r(b, tctx, &r);
296 if (i == 8) {
297 torture_assert_ntstatus_ok(tctx, status, "QueryServiceConfigEx failed!");
298 torture_assert_werr_ok(tctx, r.out.result, "QueryServiceConfigEx failed!");
299 } else {
300 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_RPC_ENUM_VALUE_OUT_OF_RANGE, "QueryServiceConfigEx failed!");
304 if (!test_CloseServiceHandle(b, tctx, &s))
305 return false;
307 if (!test_CloseServiceHandle(b, tctx, &h))
308 return false;
310 return true;
313 static bool test_QueryServiceObjectSecurity(struct torture_context *tctx,
314 struct dcerpc_pipe *p)
316 struct svcctl_QueryServiceObjectSecurity r;
317 struct policy_handle h, s;
318 struct dcerpc_binding_handle *b = p->binding_handle;
320 uint8_t *buffer = NULL;
321 uint32_t needed;
323 enum ndr_err_code ndr_err;
324 struct security_descriptor sd;
325 DATA_BLOB blob;
327 if (!test_OpenSCManager(b, tctx, &h))
328 return false;
330 if (!test_OpenService(b, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
331 return false;
333 r.in.handle = &s;
334 r.in.security_flags = 0;
335 r.in.offered = 0;
336 r.out.buffer = NULL;
337 r.out.needed = &needed;
339 torture_assert_ntstatus_ok(tctx,
340 dcerpc_svcctl_QueryServiceObjectSecurity_r(b, tctx, &r),
341 "QueryServiceObjectSecurity failed!");
342 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAMETER,
343 "QueryServiceObjectSecurity failed!");
345 r.in.security_flags = SECINFO_DACL;
347 torture_assert_ntstatus_ok(tctx,
348 dcerpc_svcctl_QueryServiceObjectSecurity_r(b, tctx, &r),
349 "QueryServiceObjectSecurity failed!");
351 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
352 r.in.offered = needed;
353 buffer = talloc_array(tctx, uint8_t, needed);
354 r.out.buffer = buffer;
355 torture_assert_ntstatus_ok(tctx,
356 dcerpc_svcctl_QueryServiceObjectSecurity_r(b, tctx, &r),
357 "QueryServiceObjectSecurity failed!");
360 torture_assert_werr_ok(tctx, r.out.result, "QueryServiceObjectSecurity failed!");
362 blob = data_blob_const(buffer, needed);
364 ndr_err = ndr_pull_struct_blob(&blob, tctx, &sd,
365 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
366 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
367 return false;
370 if (DEBUGLEVEL >= 1) {
371 NDR_PRINT_DEBUG(security_descriptor, &sd);
374 if (!test_CloseServiceHandle(b, tctx, &s))
375 return false;
377 if (!test_CloseServiceHandle(b, tctx, &h))
378 return false;
380 return true;
383 static bool test_SetServiceObjectSecurity(struct torture_context *tctx,
384 struct dcerpc_pipe *p)
386 struct svcctl_QueryServiceObjectSecurity q;
387 struct svcctl_SetServiceObjectSecurity r;
388 struct policy_handle h, s;
389 struct dcerpc_binding_handle *b = p->binding_handle;
391 uint8_t *buffer;
392 uint32_t needed;
394 if (!test_OpenSCManager(b, tctx, &h))
395 return false;
397 if (!test_OpenService(b, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
398 return false;
400 q.in.handle = &s;
401 q.in.security_flags = SECINFO_DACL;
402 q.in.offered = 0;
403 q.out.buffer = NULL;
404 q.out.needed = &needed;
406 torture_assert_ntstatus_ok(tctx,
407 dcerpc_svcctl_QueryServiceObjectSecurity_r(b, tctx, &q),
408 "QueryServiceObjectSecurity failed!");
410 if (W_ERROR_EQUAL(q.out.result, WERR_INSUFFICIENT_BUFFER)) {
411 q.in.offered = needed;
412 buffer = talloc_array(tctx, uint8_t, needed);
413 q.out.buffer = buffer;
414 torture_assert_ntstatus_ok(tctx,
415 dcerpc_svcctl_QueryServiceObjectSecurity_r(b, tctx, &q),
416 "QueryServiceObjectSecurity failed!");
419 torture_assert_werr_ok(tctx, q.out.result,
420 "QueryServiceObjectSecurity failed!");
422 r.in.handle = &s;
423 r.in.security_flags = SECINFO_DACL;
424 r.in.buffer = q.out.buffer;
425 r.in.offered = *q.out.needed;
427 torture_assert_ntstatus_ok(tctx,
428 dcerpc_svcctl_SetServiceObjectSecurity_r(b, tctx, &r),
429 "SetServiceObjectSecurity failed!");
430 torture_assert_werr_ok(tctx, r.out.result,
431 "SetServiceObjectSecurity failed!");
433 if (!test_CloseServiceHandle(b, tctx, &s))
434 return false;
436 if (!test_CloseServiceHandle(b, tctx, &h))
437 return false;
439 return true;
442 static bool test_StartServiceW(struct torture_context *tctx,
443 struct dcerpc_pipe *p)
445 struct svcctl_StartServiceW r;
446 struct policy_handle h, s;
447 struct dcerpc_binding_handle *b = p->binding_handle;
449 if (!test_OpenSCManager(b, tctx, &h))
450 return false;
452 if (!test_OpenService(b, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
453 return false;
455 r.in.handle = &s;
456 r.in.NumArgs = 0;
457 r.in.Arguments = NULL;
459 torture_assert_ntstatus_ok(tctx,
460 dcerpc_svcctl_StartServiceW_r(b, tctx, &r),
461 "StartServiceW failed!");
462 torture_assert_werr_equal(tctx, r.out.result,
463 WERR_SERVICE_ALREADY_RUNNING,
464 "StartServiceW failed!");
466 if (!test_CloseServiceHandle(b, tctx, &s))
467 return false;
469 if (!test_CloseServiceHandle(b, tctx, &h))
470 return false;
472 return true;
475 static bool test_ControlService(struct torture_context *tctx,
476 struct dcerpc_pipe *p)
478 struct svcctl_ControlService r;
479 struct policy_handle h, s;
480 struct SERVICE_STATUS service_status;
481 struct dcerpc_binding_handle *b = p->binding_handle;
483 if (!test_OpenSCManager(b, tctx, &h))
484 return false;
486 if (!test_OpenService(b, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
487 return false;
489 r.in.handle = &s;
490 r.in.control = 0;
491 r.out.service_status = &service_status;
493 torture_assert_ntstatus_ok(tctx,
494 dcerpc_svcctl_ControlService_r(b, tctx, &r),
495 "ControlService failed!");
496 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAMETER,
497 "ControlService failed!");
499 if (!test_CloseServiceHandle(b, tctx, &s))
500 return false;
502 if (!test_CloseServiceHandle(b, tctx, &h))
503 return false;
505 return true;
508 static bool test_ControlServiceExW(struct torture_context *tctx,
509 struct dcerpc_pipe *p)
511 struct svcctl_ControlServiceExW r;
512 struct policy_handle h, s;
513 struct dcerpc_binding_handle *b = p->binding_handle;
514 union SC_RPC_SERVICE_CONTROL_IN_PARAMSW ControlInParams;
515 union SC_RPC_SERVICE_CONTROL_OUT_PARAMSW ControlOutParams;
516 struct SERVICE_CONTROL_STATUS_REASON_OUT_PARAMS psrOutParams;
517 struct SERVICE_CONTROL_STATUS_REASON_IN_PARAMSW psrInParams;
519 if (!test_OpenSCManager(b, tctx, &h))
520 return false;
522 if (!test_OpenService(b, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
523 return false;
525 ZERO_STRUCT(psrInParams);
526 ZERO_STRUCT(psrOutParams);
528 psrInParams.dwReason = SERVICE_STOP_CUSTOM |
529 SERVICE_STOP_REASON_MAJOR_APPLICATION |
530 SERVICE_STOP_REASON_MINOR_ENVIRONMENT;
531 psrInParams.pszComment = "wurst";
533 ControlInParams.psrInParams = &psrInParams;
534 ControlOutParams.psrOutParams = &psrOutParams;
536 r.in.hService = s;
537 r.in.dwControl = SVCCTL_CONTROL_STOP;
538 r.in.dwInfoLevel = 1;
539 r.in.pControlInParams = &ControlInParams;
540 r.out.pControlOutParams = &ControlOutParams;
542 torture_assert_ntstatus_ok(tctx,
543 dcerpc_svcctl_ControlServiceExW_r(b, tctx, &r),
544 "ControlServiceExW failed!");
545 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAMETER,
546 "ControlServiceExW failed!");
548 if (!test_CloseServiceHandle(b, tctx, &s))
549 return false;
551 if (!test_CloseServiceHandle(b, tctx, &h))
552 return false;
554 return true;
557 static bool test_EnumServicesStatus(struct torture_context *tctx, struct dcerpc_pipe *p)
559 struct svcctl_EnumServicesStatusW r;
560 struct policy_handle h;
561 int i;
562 NTSTATUS status;
563 uint32_t resume_handle = 0;
564 struct ENUM_SERVICE_STATUSW *service = NULL;
565 uint32_t needed = 0;
566 uint32_t services_returned = 0;
567 struct dcerpc_binding_handle *b = p->binding_handle;
569 if (!test_OpenSCManager(b, tctx, &h))
570 return false;
572 r.in.handle = &h;
573 r.in.type = SERVICE_TYPE_WIN32;
574 r.in.state = SERVICE_STATE_ALL;
575 r.in.offered = 0;
576 r.in.resume_handle = &resume_handle;
577 r.out.service = NULL;
578 r.out.resume_handle = &resume_handle;
579 r.out.services_returned = &services_returned;
580 r.out.needed = &needed;
582 status = dcerpc_svcctl_EnumServicesStatusW_r(b, tctx, &r);
584 torture_assert_ntstatus_ok(tctx, status, "EnumServicesStatus failed!");
586 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
587 r.in.offered = needed;
588 r.out.service = talloc_array(tctx, uint8_t, needed);
590 status = dcerpc_svcctl_EnumServicesStatusW_r(b, tctx, &r);
592 torture_assert_ntstatus_ok(tctx, status, "EnumServicesStatus failed!");
593 torture_assert_werr_ok(tctx, r.out.result, "EnumServicesStatus failed");
596 if (services_returned > 0) {
598 enum ndr_err_code ndr_err;
599 DATA_BLOB blob;
600 struct ndr_pull *ndr;
602 blob.length = r.in.offered;
603 blob.data = talloc_steal(tctx, r.out.service);
605 ndr = ndr_pull_init_blob(&blob, tctx);
607 service = talloc_array(tctx, struct ENUM_SERVICE_STATUSW, services_returned);
608 if (!service) {
609 return false;
612 ndr_err = ndr_pull_ENUM_SERVICE_STATUSW_array(
613 ndr, services_returned, service);
614 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
615 return false;
619 for(i = 0; i < services_returned; i++) {
621 torture_assert(tctx, service[i].service_name,
622 "Service without name returned!");
624 printf("%-20s \"%s\", Type: %d, State: %d\n",
625 service[i].service_name, service[i].display_name,
626 service[i].status.type, service[i].status.state);
629 if (!test_CloseServiceHandle(b, tctx, &h))
630 return false;
632 return true;
635 static bool test_EnumDependentServicesW(struct torture_context *tctx,
636 struct dcerpc_pipe *p)
638 struct svcctl_EnumDependentServicesW r;
639 struct policy_handle h, s;
640 uint32_t needed;
641 uint32_t services_returned;
642 uint32_t i;
643 uint32_t states[] = { SERVICE_STATE_ACTIVE,
644 SERVICE_STATE_INACTIVE,
645 SERVICE_STATE_ALL };
646 struct dcerpc_binding_handle *b = p->binding_handle;
648 if (!test_OpenSCManager(b, tctx, &h))
649 return false;
651 if (!test_OpenService(b, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
652 return false;
654 r.in.service = &s;
655 r.in.offered = 0;
656 r.in.state = 0;
657 r.out.service_status = NULL;
658 r.out.services_returned = &services_returned;
659 r.out.needed = &needed;
661 torture_assert_ntstatus_ok(tctx,
662 dcerpc_svcctl_EnumDependentServicesW_r(b, tctx, &r),
663 "EnumDependentServicesW failed!");
665 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAMETER,
666 "EnumDependentServicesW failed!");
668 for (i=0; i<ARRAY_SIZE(states); i++) {
670 r.in.state = states[i];
672 torture_assert_ntstatus_ok(tctx,
673 dcerpc_svcctl_EnumDependentServicesW_r(b, tctx, &r),
674 "EnumDependentServicesW failed!");
676 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
677 r.in.offered = needed;
678 r.out.service_status = talloc_array(tctx, uint8_t, needed);
680 torture_assert_ntstatus_ok(tctx,
681 dcerpc_svcctl_EnumDependentServicesW_r(b, tctx, &r),
682 "EnumDependentServicesW failed!");
686 torture_assert_werr_ok(tctx, r.out.result,
687 "EnumDependentServicesW failed");
690 if (!test_CloseServiceHandle(b, tctx, &s))
691 return false;
693 if (!test_CloseServiceHandle(b, tctx, &h))
694 return false;
696 return true;
699 static bool test_SCManager(struct torture_context *tctx,
700 struct dcerpc_pipe *p)
702 struct policy_handle h;
703 struct dcerpc_binding_handle *b = p->binding_handle;
705 if (!test_OpenSCManager(b, tctx, &h))
706 return false;
708 if (!test_CloseServiceHandle(b, tctx, &h))
709 return false;
711 return true;
714 static bool test_ChangeServiceConfigW(struct torture_context *tctx,
715 struct dcerpc_pipe *p)
717 struct svcctl_ChangeServiceConfigW r;
718 struct svcctl_QueryServiceConfigW q;
719 struct policy_handle h, s;
720 NTSTATUS status;
721 struct dcerpc_binding_handle *b = p->binding_handle;
722 struct QUERY_SERVICE_CONFIG query;
723 bool ok;
725 uint32_t offered = 0;
726 uint32_t needed = 0;
728 ok = test_OpenSCManager(b, tctx, &h);
729 if (!ok) {
730 return false;
733 ok = test_OpenService(b, tctx, &h, TORTURE_DEFAULT_SERVICE, &s);
734 if (!ok) {
735 return false;
738 q.in.handle = &s;
739 q.in.offered = offered;
740 q.out.query = &query;
741 q.out.needed = &needed;
743 status = dcerpc_svcctl_QueryServiceConfigW_r(b, tctx, &q);
744 torture_assert_ntstatus_ok(tctx, status, "QueryServiceConfigW failed!");
746 if (W_ERROR_EQUAL(q.out.result, WERR_INSUFFICIENT_BUFFER)) {
747 q.in.offered = needed;
748 status = dcerpc_svcctl_QueryServiceConfigW_r(b, tctx, &q);
749 torture_assert_ntstatus_ok(tctx, status, "QueryServiceConfigW failed!");
751 torture_assert_werr_ok(tctx, q.out.result, "QueryServiceConfigW failed!");
753 r.in.handle = &s;
754 r.in.type = query.service_type;
755 r.in.start_type = query.start_type;
756 r.in.error_control = query.error_control;
759 * according to MS-SCMR 3.1.4.11 NULL params are supposed to leave the
760 * existing values intact.
763 r.in.binary_path = NULL;
764 r.in.load_order_group = NULL;
765 r.in.dependencies = NULL;
766 r.in.dwDependSize = 0;
767 r.in.service_start_name = NULL;
768 r.in.password = NULL;
769 r.in.dwPwSize = 0;
770 r.in.display_name = NULL;
771 r.in.tag_id = NULL;
772 r.out.tag_id = NULL;
774 status = dcerpc_svcctl_ChangeServiceConfigW_r(b, tctx, &r);
775 torture_assert_ntstatus_ok(tctx, status, "ChangeServiceConfigW failed!");
776 torture_assert_werr_ok(tctx, r.out.result, "ChangeServiceConfigW failed!");
778 ok = test_CloseServiceHandle(b, tctx, &s);
779 if (!ok) {
780 return false;
783 ok = test_CloseServiceHandle(b, tctx, &h);
784 if (!ok) {
785 return false;
788 return true;
791 struct torture_suite *torture_rpc_svcctl(TALLOC_CTX *mem_ctx)
793 struct torture_suite *suite = torture_suite_create(mem_ctx, "svcctl");
794 struct torture_rpc_tcase *tcase;
796 tcase = torture_suite_add_rpc_iface_tcase(suite, "svcctl", &ndr_table_svcctl);
798 torture_rpc_tcase_add_test(tcase, "SCManager",
799 test_SCManager);
800 torture_rpc_tcase_add_test(tcase, "EnumServicesStatus",
801 test_EnumServicesStatus);
802 torture_rpc_tcase_add_test(tcase, "EnumDependentServicesW",
803 test_EnumDependentServicesW);
804 torture_rpc_tcase_add_test(tcase, "QueryServiceStatus",
805 test_QueryServiceStatus);
806 torture_rpc_tcase_add_test(tcase, "QueryServiceStatusEx",
807 test_QueryServiceStatusEx);
808 torture_rpc_tcase_add_test(tcase, "QueryServiceConfigW",
809 test_QueryServiceConfigW);
810 torture_rpc_tcase_add_test(tcase, "QueryServiceConfig2W",
811 test_QueryServiceConfig2W);
812 torture_rpc_tcase_add_test(tcase, "QueryServiceConfigEx",
813 test_QueryServiceConfigEx);
814 torture_rpc_tcase_add_test(tcase, "QueryServiceObjectSecurity",
815 test_QueryServiceObjectSecurity);
816 torture_rpc_tcase_add_test(tcase, "SetServiceObjectSecurity",
817 test_SetServiceObjectSecurity);
818 torture_rpc_tcase_add_test(tcase, "StartServiceW",
819 test_StartServiceW);
820 torture_rpc_tcase_add_test(tcase, "ControlService",
821 test_ControlService);
822 torture_rpc_tcase_add_test(tcase, "ControlServiceExW",
823 test_ControlServiceExW);
824 torture_rpc_tcase_add_test(tcase, "ChangeServiceConfigW",
825 test_ChangeServiceConfigW);
827 return suite;