Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : test suite for svcctl rpc operations
4 :
5 : Copyright (C) Jelmer Vernooij 2004
6 : Copyright (C) Guenther Deschner 2008,2009,2020
7 :
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.
12 :
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.
17 :
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/>.
20 : */
21 :
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"
28 :
29 : #define TORTURE_DEFAULT_SERVICE "Spooler"
30 :
31 0 : static bool test_OpenSCManager(struct dcerpc_binding_handle *b,
32 : struct torture_context *tctx,
33 : struct policy_handle *h)
34 : {
35 : struct svcctl_OpenSCManagerW r;
36 :
37 0 : r.in.MachineName = NULL;
38 0 : r.in.DatabaseName = NULL;
39 0 : r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
40 0 : r.out.handle = h;
41 :
42 0 : torture_assert_ntstatus_ok(tctx,
43 : dcerpc_svcctl_OpenSCManagerW_r(b, tctx, &r),
44 : "OpenSCManager failed!");
45 :
46 0 : return true;
47 : }
48 :
49 0 : static bool test_CloseServiceHandle(struct dcerpc_binding_handle *b,
50 : struct torture_context *tctx,
51 : struct policy_handle *h)
52 : {
53 : struct svcctl_CloseServiceHandle r;
54 :
55 0 : r.in.handle = h;
56 0 : r.out.handle = h;
57 0 : torture_assert_ntstatus_ok(tctx,
58 : dcerpc_svcctl_CloseServiceHandle_r(b, tctx, &r),
59 : "CloseServiceHandle failed");
60 :
61 0 : return true;
62 : }
63 :
64 0 : 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)
69 : {
70 : struct svcctl_OpenServiceW r;
71 :
72 0 : r.in.scmanager_handle = h;
73 0 : r.in.ServiceName = name;
74 0 : r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
75 0 : r.out.handle = s;
76 :
77 0 : torture_assert_ntstatus_ok(tctx,
78 : dcerpc_svcctl_OpenServiceW_r(b, tctx, &r),
79 : "OpenServiceW failed!");
80 0 : torture_assert_werr_ok(tctx, r.out.result, "OpenServiceW failed!");
81 :
82 0 : return true;
83 :
84 : }
85 :
86 0 : static bool test_QueryServiceStatus(struct torture_context *tctx,
87 : struct dcerpc_pipe *p)
88 : {
89 : struct svcctl_QueryServiceStatus r;
90 : struct policy_handle h, s;
91 : struct SERVICE_STATUS service_status;
92 : NTSTATUS status;
93 0 : struct dcerpc_binding_handle *b = p->binding_handle;
94 :
95 0 : if (!test_OpenSCManager(b, tctx, &h))
96 0 : return false;
97 :
98 0 : if (!test_OpenService(b, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
99 0 : return false;
100 :
101 0 : r.in.handle = &s;
102 0 : r.out.service_status = &service_status;
103 :
104 0 : status = dcerpc_svcctl_QueryServiceStatus_r(b, tctx, &r);
105 0 : torture_assert_ntstatus_ok(tctx, status, "QueryServiceStatus failed!");
106 0 : torture_assert_werr_ok(tctx, r.out.result, "QueryServiceStatus failed!");
107 :
108 0 : if (!test_CloseServiceHandle(b, tctx, &s))
109 0 : return false;
110 :
111 0 : if (!test_CloseServiceHandle(b, tctx, &h))
112 0 : return false;
113 :
114 0 : return true;
115 : }
116 :
117 0 : static bool test_QueryServiceStatusEx(struct torture_context *tctx, struct dcerpc_pipe *p)
118 : {
119 : struct svcctl_QueryServiceStatusEx r;
120 : struct policy_handle h, s;
121 : NTSTATUS status;
122 0 : struct dcerpc_binding_handle *b = p->binding_handle;
123 :
124 0 : uint32_t info_level = SVC_STATUS_PROCESS_INFO;
125 : uint8_t *buffer;
126 0 : uint32_t offered = 0;
127 0 : uint32_t needed = 0;
128 :
129 0 : if (!test_OpenSCManager(b, tctx, &h))
130 0 : return false;
131 :
132 0 : if (!test_OpenService(b, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
133 0 : return false;
134 :
135 0 : buffer = talloc(tctx, uint8_t);
136 :
137 0 : r.in.handle = &s;
138 0 : r.in.info_level = info_level;
139 0 : r.in.offered = offered;
140 0 : r.out.buffer = buffer;
141 0 : r.out.needed = &needed;
142 :
143 0 : status = dcerpc_svcctl_QueryServiceStatusEx_r(b, tctx, &r);
144 0 : torture_assert_ntstatus_ok(tctx, status, "QueryServiceStatusEx failed!");
145 :
146 0 : if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
147 0 : r.in.offered = needed;
148 0 : buffer = talloc_array(tctx, uint8_t, needed);
149 0 : r.out.buffer = buffer;
150 :
151 0 : status = dcerpc_svcctl_QueryServiceStatusEx_r(b, tctx, &r);
152 0 : torture_assert_ntstatus_ok(tctx, status, "QueryServiceStatusEx failed!");
153 0 : torture_assert_werr_ok(tctx, r.out.result, "QueryServiceStatusEx failed!");
154 : }
155 :
156 0 : if (!test_CloseServiceHandle(b, tctx, &s))
157 0 : return false;
158 :
159 0 : if (!test_CloseServiceHandle(b, tctx, &h))
160 0 : return false;
161 :
162 0 : return true;
163 : }
164 :
165 0 : static bool test_QueryServiceConfigW(struct torture_context *tctx,
166 : struct dcerpc_pipe *p)
167 : {
168 : struct svcctl_QueryServiceConfigW r;
169 : struct QUERY_SERVICE_CONFIG query;
170 : struct policy_handle h, s;
171 : NTSTATUS status;
172 0 : struct dcerpc_binding_handle *b = p->binding_handle;
173 :
174 0 : uint32_t offered = 0;
175 0 : uint32_t needed = 0;
176 :
177 0 : if (!test_OpenSCManager(b, tctx, &h))
178 0 : return false;
179 :
180 0 : if (!test_OpenService(b, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
181 0 : return false;
182 :
183 0 : r.in.handle = &s;
184 0 : r.in.offered = offered;
185 0 : r.out.query = &query;
186 0 : r.out.needed = &needed;
187 :
188 0 : status = dcerpc_svcctl_QueryServiceConfigW_r(b, tctx, &r);
189 0 : torture_assert_ntstatus_ok(tctx, status, "QueryServiceConfigW failed!");
190 :
191 0 : if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
192 0 : r.in.offered = needed;
193 0 : status = dcerpc_svcctl_QueryServiceConfigW_r(b, tctx, &r);
194 0 : torture_assert_ntstatus_ok(tctx, status, "QueryServiceConfigW failed!");
195 : }
196 :
197 0 : torture_assert_werr_ok(tctx, r.out.result, "QueryServiceConfigW failed!");
198 :
199 0 : if (!test_CloseServiceHandle(b, tctx, &s))
200 0 : return false;
201 :
202 0 : if (!test_CloseServiceHandle(b, tctx, &h))
203 0 : return false;
204 :
205 0 : return true;
206 : }
207 :
208 0 : static bool test_QueryServiceConfig2W(struct torture_context *tctx, struct dcerpc_pipe *p)
209 : {
210 : struct svcctl_QueryServiceConfig2W r;
211 : struct policy_handle h, s;
212 : NTSTATUS status;
213 0 : struct dcerpc_binding_handle *b = p->binding_handle;
214 :
215 0 : uint32_t info_level = SERVICE_CONFIG_DESCRIPTION;
216 : uint8_t *buffer;
217 0 : uint32_t offered = 0;
218 0 : uint32_t needed = 0;
219 :
220 0 : if (!test_OpenSCManager(b, tctx, &h))
221 0 : return false;
222 :
223 0 : if (!test_OpenService(b, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
224 0 : return false;
225 :
226 0 : buffer = talloc(tctx, uint8_t);
227 :
228 0 : r.in.handle = &s;
229 0 : r.in.info_level = info_level;
230 0 : r.in.offered = offered;
231 0 : r.out.buffer = buffer;
232 0 : r.out.needed = &needed;
233 :
234 0 : status = dcerpc_svcctl_QueryServiceConfig2W_r(b, tctx, &r);
235 0 : torture_assert_ntstatus_ok(tctx, status, "QueryServiceConfig2W failed!");
236 :
237 0 : if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
238 0 : r.in.offered = needed;
239 0 : buffer = talloc_array(tctx, uint8_t, needed);
240 0 : r.out.buffer = buffer;
241 :
242 0 : status = dcerpc_svcctl_QueryServiceConfig2W_r(b, tctx, &r);
243 0 : torture_assert_ntstatus_ok(tctx, status, "QueryServiceConfig2W failed!");
244 0 : torture_assert_werr_ok(tctx, r.out.result, "QueryServiceConfig2W failed!");
245 : }
246 :
247 0 : r.in.info_level = SERVICE_CONFIG_FAILURE_ACTIONS;
248 0 : r.in.offered = offered;
249 0 : r.out.buffer = buffer;
250 0 : r.out.needed = &needed;
251 :
252 0 : status = dcerpc_svcctl_QueryServiceConfig2W_r(b, tctx, &r);
253 0 : torture_assert_ntstatus_ok(tctx, status, "QueryServiceConfig2W failed!");
254 :
255 0 : if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
256 0 : r.in.offered = needed;
257 0 : buffer = talloc_array(tctx, uint8_t, needed);
258 0 : r.out.buffer = buffer;
259 :
260 0 : status = dcerpc_svcctl_QueryServiceConfig2W_r(b, tctx, &r);
261 0 : torture_assert_ntstatus_ok(tctx, status, "QueryServiceConfig2W failed!");
262 0 : torture_assert_werr_ok(tctx, r.out.result, "QueryServiceConfig2W failed!");
263 : }
264 :
265 0 : if (!test_CloseServiceHandle(b, tctx, &s))
266 0 : return false;
267 :
268 0 : if (!test_CloseServiceHandle(b, tctx, &h))
269 0 : return false;
270 :
271 0 : return true;
272 : }
273 :
274 0 : static bool test_QueryServiceObjectSecurity(struct torture_context *tctx,
275 : struct dcerpc_pipe *p)
276 : {
277 : struct svcctl_QueryServiceObjectSecurity r;
278 : struct policy_handle h, s;
279 0 : struct dcerpc_binding_handle *b = p->binding_handle;
280 :
281 0 : uint8_t *buffer = NULL;
282 : uint32_t needed;
283 :
284 : enum ndr_err_code ndr_err;
285 : struct security_descriptor sd;
286 : DATA_BLOB blob;
287 :
288 0 : if (!test_OpenSCManager(b, tctx, &h))
289 0 : return false;
290 :
291 0 : if (!test_OpenService(b, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
292 0 : return false;
293 :
294 0 : r.in.handle = &s;
295 0 : r.in.security_flags = 0;
296 0 : r.in.offered = 0;
297 0 : r.out.buffer = NULL;
298 0 : r.out.needed = &needed;
299 :
300 0 : torture_assert_ntstatus_ok(tctx,
301 : dcerpc_svcctl_QueryServiceObjectSecurity_r(b, tctx, &r),
302 : "QueryServiceObjectSecurity failed!");
303 0 : torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAMETER,
304 : "QueryServiceObjectSecurity failed!");
305 :
306 0 : r.in.security_flags = SECINFO_DACL;
307 :
308 0 : torture_assert_ntstatus_ok(tctx,
309 : dcerpc_svcctl_QueryServiceObjectSecurity_r(b, tctx, &r),
310 : "QueryServiceObjectSecurity failed!");
311 :
312 0 : if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
313 0 : r.in.offered = needed;
314 0 : buffer = talloc_array(tctx, uint8_t, needed);
315 0 : r.out.buffer = buffer;
316 0 : torture_assert_ntstatus_ok(tctx,
317 : dcerpc_svcctl_QueryServiceObjectSecurity_r(b, tctx, &r),
318 : "QueryServiceObjectSecurity failed!");
319 : }
320 :
321 0 : torture_assert_werr_ok(tctx, r.out.result, "QueryServiceObjectSecurity failed!");
322 :
323 0 : blob = data_blob_const(buffer, needed);
324 :
325 0 : ndr_err = ndr_pull_struct_blob(&blob, tctx, &sd,
326 : (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
327 0 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
328 0 : return false;
329 : }
330 :
331 0 : if (DEBUGLEVEL >= 1) {
332 0 : NDR_PRINT_DEBUG(security_descriptor, &sd);
333 : }
334 :
335 0 : if (!test_CloseServiceHandle(b, tctx, &s))
336 0 : return false;
337 :
338 0 : if (!test_CloseServiceHandle(b, tctx, &h))
339 0 : return false;
340 :
341 0 : return true;
342 : }
343 :
344 0 : static bool test_SetServiceObjectSecurity(struct torture_context *tctx,
345 : struct dcerpc_pipe *p)
346 : {
347 : struct svcctl_QueryServiceObjectSecurity q;
348 : struct svcctl_SetServiceObjectSecurity r;
349 : struct policy_handle h, s;
350 0 : struct dcerpc_binding_handle *b = p->binding_handle;
351 :
352 : uint8_t *buffer;
353 : uint32_t needed;
354 :
355 0 : if (!test_OpenSCManager(b, tctx, &h))
356 0 : return false;
357 :
358 0 : if (!test_OpenService(b, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
359 0 : return false;
360 :
361 0 : q.in.handle = &s;
362 0 : q.in.security_flags = SECINFO_DACL;
363 0 : q.in.offered = 0;
364 0 : q.out.buffer = NULL;
365 0 : q.out.needed = &needed;
366 :
367 0 : torture_assert_ntstatus_ok(tctx,
368 : dcerpc_svcctl_QueryServiceObjectSecurity_r(b, tctx, &q),
369 : "QueryServiceObjectSecurity failed!");
370 :
371 0 : if (W_ERROR_EQUAL(q.out.result, WERR_INSUFFICIENT_BUFFER)) {
372 0 : q.in.offered = needed;
373 0 : buffer = talloc_array(tctx, uint8_t, needed);
374 0 : q.out.buffer = buffer;
375 0 : torture_assert_ntstatus_ok(tctx,
376 : dcerpc_svcctl_QueryServiceObjectSecurity_r(b, tctx, &q),
377 : "QueryServiceObjectSecurity failed!");
378 : }
379 :
380 0 : torture_assert_werr_ok(tctx, q.out.result,
381 : "QueryServiceObjectSecurity failed!");
382 :
383 0 : r.in.handle = &s;
384 0 : r.in.security_flags = SECINFO_DACL;
385 0 : r.in.buffer = q.out.buffer;
386 0 : r.in.offered = *q.out.needed;
387 :
388 0 : torture_assert_ntstatus_ok(tctx,
389 : dcerpc_svcctl_SetServiceObjectSecurity_r(b, tctx, &r),
390 : "SetServiceObjectSecurity failed!");
391 0 : torture_assert_werr_ok(tctx, r.out.result,
392 : "SetServiceObjectSecurity failed!");
393 :
394 0 : if (!test_CloseServiceHandle(b, tctx, &s))
395 0 : return false;
396 :
397 0 : if (!test_CloseServiceHandle(b, tctx, &h))
398 0 : return false;
399 :
400 0 : return true;
401 : }
402 :
403 0 : static bool test_StartServiceW(struct torture_context *tctx,
404 : struct dcerpc_pipe *p)
405 : {
406 : struct svcctl_StartServiceW r;
407 : struct policy_handle h, s;
408 0 : struct dcerpc_binding_handle *b = p->binding_handle;
409 :
410 0 : if (!test_OpenSCManager(b, tctx, &h))
411 0 : return false;
412 :
413 0 : if (!test_OpenService(b, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
414 0 : return false;
415 :
416 0 : r.in.handle = &s;
417 0 : r.in.NumArgs = 0;
418 0 : r.in.Arguments = NULL;
419 :
420 0 : torture_assert_ntstatus_ok(tctx,
421 : dcerpc_svcctl_StartServiceW_r(b, tctx, &r),
422 : "StartServiceW failed!");
423 0 : torture_assert_werr_equal(tctx, r.out.result,
424 : WERR_SERVICE_ALREADY_RUNNING,
425 : "StartServiceW failed!");
426 :
427 0 : if (!test_CloseServiceHandle(b, tctx, &s))
428 0 : return false;
429 :
430 0 : if (!test_CloseServiceHandle(b, tctx, &h))
431 0 : return false;
432 :
433 0 : return true;
434 : }
435 :
436 0 : static bool test_ControlService(struct torture_context *tctx,
437 : struct dcerpc_pipe *p)
438 : {
439 : struct svcctl_ControlService r;
440 : struct policy_handle h, s;
441 : struct SERVICE_STATUS service_status;
442 0 : struct dcerpc_binding_handle *b = p->binding_handle;
443 :
444 0 : if (!test_OpenSCManager(b, tctx, &h))
445 0 : return false;
446 :
447 0 : if (!test_OpenService(b, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
448 0 : return false;
449 :
450 0 : r.in.handle = &s;
451 0 : r.in.control = 0;
452 0 : r.out.service_status = &service_status;
453 :
454 0 : torture_assert_ntstatus_ok(tctx,
455 : dcerpc_svcctl_ControlService_r(b, tctx, &r),
456 : "ControlService failed!");
457 0 : torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAMETER,
458 : "ControlService failed!");
459 :
460 0 : if (!test_CloseServiceHandle(b, tctx, &s))
461 0 : return false;
462 :
463 0 : if (!test_CloseServiceHandle(b, tctx, &h))
464 0 : return false;
465 :
466 0 : return true;
467 : }
468 :
469 0 : static bool test_EnumServicesStatus(struct torture_context *tctx, struct dcerpc_pipe *p)
470 : {
471 : struct svcctl_EnumServicesStatusW r;
472 : struct policy_handle h;
473 : int i;
474 : NTSTATUS status;
475 0 : uint32_t resume_handle = 0;
476 0 : struct ENUM_SERVICE_STATUSW *service = NULL;
477 0 : uint32_t needed = 0;
478 0 : uint32_t services_returned = 0;
479 0 : struct dcerpc_binding_handle *b = p->binding_handle;
480 :
481 0 : if (!test_OpenSCManager(b, tctx, &h))
482 0 : return false;
483 :
484 0 : r.in.handle = &h;
485 0 : r.in.type = SERVICE_TYPE_WIN32;
486 0 : r.in.state = SERVICE_STATE_ALL;
487 0 : r.in.offered = 0;
488 0 : r.in.resume_handle = &resume_handle;
489 0 : r.out.service = NULL;
490 0 : r.out.resume_handle = &resume_handle;
491 0 : r.out.services_returned = &services_returned;
492 0 : r.out.needed = &needed;
493 :
494 0 : status = dcerpc_svcctl_EnumServicesStatusW_r(b, tctx, &r);
495 :
496 0 : torture_assert_ntstatus_ok(tctx, status, "EnumServicesStatus failed!");
497 :
498 0 : if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
499 0 : r.in.offered = needed;
500 0 : r.out.service = talloc_array(tctx, uint8_t, needed);
501 :
502 0 : status = dcerpc_svcctl_EnumServicesStatusW_r(b, tctx, &r);
503 :
504 0 : torture_assert_ntstatus_ok(tctx, status, "EnumServicesStatus failed!");
505 0 : torture_assert_werr_ok(tctx, r.out.result, "EnumServicesStatus failed");
506 : }
507 :
508 0 : if (services_returned > 0) {
509 :
510 : enum ndr_err_code ndr_err;
511 : DATA_BLOB blob;
512 : struct ndr_pull *ndr;
513 :
514 0 : blob.length = r.in.offered;
515 0 : blob.data = talloc_steal(tctx, r.out.service);
516 :
517 0 : ndr = ndr_pull_init_blob(&blob, tctx);
518 :
519 0 : service = talloc_array(tctx, struct ENUM_SERVICE_STATUSW, services_returned);
520 0 : if (!service) {
521 0 : return false;
522 : }
523 :
524 0 : ndr_err = ndr_pull_ENUM_SERVICE_STATUSW_array(
525 : ndr, services_returned, service);
526 0 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
527 0 : return false;
528 : }
529 : }
530 :
531 0 : for(i = 0; i < services_returned; i++) {
532 :
533 0 : torture_assert(tctx, service[i].service_name,
534 : "Service without name returned!");
535 :
536 0 : printf("%-20s \"%s\", Type: %d, State: %d\n",
537 0 : service[i].service_name, service[i].display_name,
538 0 : service[i].status.type, service[i].status.state);
539 : }
540 :
541 0 : if (!test_CloseServiceHandle(b, tctx, &h))
542 0 : return false;
543 :
544 0 : return true;
545 : }
546 :
547 0 : static bool test_EnumDependentServicesW(struct torture_context *tctx,
548 : struct dcerpc_pipe *p)
549 : {
550 : struct svcctl_EnumDependentServicesW r;
551 : struct policy_handle h, s;
552 : uint32_t needed;
553 : uint32_t services_returned;
554 : uint32_t i;
555 0 : uint32_t states[] = { SERVICE_STATE_ACTIVE,
556 : SERVICE_STATE_INACTIVE,
557 : SERVICE_STATE_ALL };
558 0 : struct dcerpc_binding_handle *b = p->binding_handle;
559 :
560 0 : if (!test_OpenSCManager(b, tctx, &h))
561 0 : return false;
562 :
563 0 : if (!test_OpenService(b, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
564 0 : return false;
565 :
566 0 : r.in.service = &s;
567 0 : r.in.offered = 0;
568 0 : r.in.state = 0;
569 0 : r.out.service_status = NULL;
570 0 : r.out.services_returned = &services_returned;
571 0 : r.out.needed = &needed;
572 :
573 0 : torture_assert_ntstatus_ok(tctx,
574 : dcerpc_svcctl_EnumDependentServicesW_r(b, tctx, &r),
575 : "EnumDependentServicesW failed!");
576 :
577 0 : torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAMETER,
578 : "EnumDependentServicesW failed!");
579 :
580 0 : for (i=0; i<ARRAY_SIZE(states); i++) {
581 :
582 0 : r.in.state = states[i];
583 :
584 0 : torture_assert_ntstatus_ok(tctx,
585 : dcerpc_svcctl_EnumDependentServicesW_r(b, tctx, &r),
586 : "EnumDependentServicesW failed!");
587 :
588 0 : if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
589 0 : r.in.offered = needed;
590 0 : r.out.service_status = talloc_array(tctx, uint8_t, needed);
591 :
592 0 : torture_assert_ntstatus_ok(tctx,
593 : dcerpc_svcctl_EnumDependentServicesW_r(b, tctx, &r),
594 : "EnumDependentServicesW failed!");
595 :
596 : }
597 :
598 0 : torture_assert_werr_ok(tctx, r.out.result,
599 : "EnumDependentServicesW failed");
600 : }
601 :
602 0 : if (!test_CloseServiceHandle(b, tctx, &s))
603 0 : return false;
604 :
605 0 : if (!test_CloseServiceHandle(b, tctx, &h))
606 0 : return false;
607 :
608 0 : return true;
609 : }
610 :
611 0 : static bool test_SCManager(struct torture_context *tctx,
612 : struct dcerpc_pipe *p)
613 : {
614 : struct policy_handle h;
615 0 : struct dcerpc_binding_handle *b = p->binding_handle;
616 :
617 0 : if (!test_OpenSCManager(b, tctx, &h))
618 0 : return false;
619 :
620 0 : if (!test_CloseServiceHandle(b, tctx, &h))
621 0 : return false;
622 :
623 0 : return true;
624 : }
625 :
626 0 : static bool test_ChangeServiceConfigW(struct torture_context *tctx,
627 : struct dcerpc_pipe *p)
628 : {
629 : struct svcctl_ChangeServiceConfigW r;
630 : struct svcctl_QueryServiceConfigW q;
631 : struct policy_handle h, s;
632 : NTSTATUS status;
633 0 : struct dcerpc_binding_handle *b = p->binding_handle;
634 : struct QUERY_SERVICE_CONFIG query;
635 : bool ok;
636 :
637 0 : uint32_t offered = 0;
638 0 : uint32_t needed = 0;
639 :
640 0 : ok = test_OpenSCManager(b, tctx, &h);
641 0 : if (!ok) {
642 0 : return false;
643 : }
644 :
645 0 : ok = test_OpenService(b, tctx, &h, TORTURE_DEFAULT_SERVICE, &s);
646 0 : if (!ok) {
647 0 : return false;
648 : }
649 :
650 0 : q.in.handle = &s;
651 0 : q.in.offered = offered;
652 0 : q.out.query = &query;
653 0 : q.out.needed = &needed;
654 :
655 0 : status = dcerpc_svcctl_QueryServiceConfigW_r(b, tctx, &q);
656 0 : torture_assert_ntstatus_ok(tctx, status, "QueryServiceConfigW failed!");
657 :
658 0 : if (W_ERROR_EQUAL(q.out.result, WERR_INSUFFICIENT_BUFFER)) {
659 0 : q.in.offered = needed;
660 0 : status = dcerpc_svcctl_QueryServiceConfigW_r(b, tctx, &q);
661 0 : torture_assert_ntstatus_ok(tctx, status, "QueryServiceConfigW failed!");
662 : }
663 0 : torture_assert_werr_ok(tctx, q.out.result, "QueryServiceConfigW failed!");
664 :
665 0 : r.in.handle = &s;
666 0 : r.in.type = query.service_type;
667 0 : r.in.start_type = query.start_type;
668 0 : r.in.error_control = query.error_control;
669 :
670 : /*
671 : * according to MS-SCMR 3.1.4.11 NULL params are supposed to leave the
672 : * existing values intact.
673 : */
674 :
675 0 : r.in.binary_path = NULL;
676 0 : r.in.load_order_group = NULL;
677 0 : r.in.dependencies = NULL;
678 0 : r.in.dwDependSize = 0;
679 0 : r.in.service_start_name = NULL;
680 0 : r.in.password = NULL;
681 0 : r.in.dwPwSize = 0;
682 0 : r.in.display_name = NULL;
683 0 : r.in.tag_id = NULL;
684 0 : r.out.tag_id = NULL;
685 :
686 0 : status = dcerpc_svcctl_ChangeServiceConfigW_r(b, tctx, &r);
687 0 : torture_assert_ntstatus_ok(tctx, status, "ChangeServiceConfigW failed!");
688 0 : torture_assert_werr_ok(tctx, r.out.result, "ChangeServiceConfigW failed!");
689 :
690 0 : ok = test_CloseServiceHandle(b, tctx, &s);
691 0 : if (!ok) {
692 0 : return false;
693 : }
694 :
695 0 : ok = test_CloseServiceHandle(b, tctx, &h);
696 0 : if (!ok) {
697 0 : return false;
698 : }
699 :
700 0 : return true;
701 : }
702 :
703 964 : struct torture_suite *torture_rpc_svcctl(TALLOC_CTX *mem_ctx)
704 : {
705 964 : struct torture_suite *suite = torture_suite_create(mem_ctx, "svcctl");
706 : struct torture_rpc_tcase *tcase;
707 :
708 964 : tcase = torture_suite_add_rpc_iface_tcase(suite, "svcctl", &ndr_table_svcctl);
709 :
710 964 : torture_rpc_tcase_add_test(tcase, "SCManager",
711 : test_SCManager);
712 964 : torture_rpc_tcase_add_test(tcase, "EnumServicesStatus",
713 : test_EnumServicesStatus);
714 964 : torture_rpc_tcase_add_test(tcase, "EnumDependentServicesW",
715 : test_EnumDependentServicesW);
716 964 : torture_rpc_tcase_add_test(tcase, "QueryServiceStatus",
717 : test_QueryServiceStatus);
718 964 : torture_rpc_tcase_add_test(tcase, "QueryServiceStatusEx",
719 : test_QueryServiceStatusEx);
720 964 : torture_rpc_tcase_add_test(tcase, "QueryServiceConfigW",
721 : test_QueryServiceConfigW);
722 964 : torture_rpc_tcase_add_test(tcase, "QueryServiceConfig2W",
723 : test_QueryServiceConfig2W);
724 964 : torture_rpc_tcase_add_test(tcase, "QueryServiceObjectSecurity",
725 : test_QueryServiceObjectSecurity);
726 964 : torture_rpc_tcase_add_test(tcase, "SetServiceObjectSecurity",
727 : test_SetServiceObjectSecurity);
728 964 : torture_rpc_tcase_add_test(tcase, "StartServiceW",
729 : test_StartServiceW);
730 964 : torture_rpc_tcase_add_test(tcase, "ControlService",
731 : test_ControlService);
732 964 : torture_rpc_tcase_add_test(tcase, "ChangeServiceConfigW",
733 : test_ChangeServiceConfigW);
734 :
735 964 : return suite;
736 : }
|