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