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 56 : 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 56 : r.in.MachineName = NULL;
38 56 : r.in.DatabaseName = NULL;
39 56 : r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
40 56 : r.out.handle = h;
41 :
42 56 : torture_assert_ntstatus_ok(tctx,
43 : dcerpc_svcctl_OpenSCManagerW_r(b, tctx, &r),
44 : "OpenSCManager failed!");
45 :
46 56 : 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 48 : 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 48 : r.in.scmanager_handle = h;
73 48 : r.in.ServiceName = name;
74 48 : r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
75 48 : r.out.handle = s;
76 :
77 48 : torture_assert_ntstatus_ok(tctx,
78 : dcerpc_svcctl_OpenServiceW_r(b, tctx, &r),
79 : "OpenServiceW failed!");
80 48 : torture_assert_werr_ok(tctx, r.out.result, "OpenServiceW failed!");
81 :
82 48 : 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_QueryServiceConfigEx(struct torture_context *tctx, struct dcerpc_pipe *p)
275 : {
276 0 : struct svcctl_QueryServiceConfigEx r;
277 0 : struct policy_handle h, s;
278 0 : NTSTATUS status;
279 4 : struct dcerpc_binding_handle *b = p->binding_handle;
280 0 : struct SC_RPC_CONFIG_INFOW info;
281 0 : int i;
282 :
283 4 : if (!test_OpenSCManager(b, tctx, &h))
284 0 : return false;
285 :
286 4 : if (!test_OpenService(b, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
287 0 : return false;
288 :
289 4 : for (i=0; i < 16; i++) {
290 :
291 4 : r.in.hService = s;
292 4 : r.in.dwInfoLevel = i;
293 4 : r.out.pInfo = &info;
294 :
295 4 : status = dcerpc_svcctl_QueryServiceConfigEx_r(b, tctx, &r);
296 4 : if (i == 8) {
297 0 : torture_assert_ntstatus_ok(tctx, status, "QueryServiceConfigEx failed!");
298 0 : torture_assert_werr_ok(tctx, r.out.result, "QueryServiceConfigEx failed!");
299 : } else {
300 4 : torture_assert_ntstatus_equal(tctx, status, NT_STATUS_RPC_ENUM_VALUE_OUT_OF_RANGE, "QueryServiceConfigEx failed!");
301 : }
302 : }
303 :
304 0 : if (!test_CloseServiceHandle(b, tctx, &s))
305 0 : return false;
306 :
307 0 : if (!test_CloseServiceHandle(b, tctx, &h))
308 0 : return false;
309 :
310 0 : return true;
311 : }
312 :
313 4 : static bool test_QueryServiceObjectSecurity(struct torture_context *tctx,
314 : struct dcerpc_pipe *p)
315 : {
316 0 : struct svcctl_QueryServiceObjectSecurity r;
317 0 : struct policy_handle h, s;
318 4 : struct dcerpc_binding_handle *b = p->binding_handle;
319 :
320 4 : uint8_t *buffer = NULL;
321 0 : uint32_t needed;
322 :
323 0 : enum ndr_err_code ndr_err;
324 0 : struct security_descriptor sd;
325 0 : DATA_BLOB blob;
326 :
327 4 : if (!test_OpenSCManager(b, tctx, &h))
328 0 : return false;
329 :
330 4 : if (!test_OpenService(b, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
331 0 : return false;
332 :
333 4 : r.in.handle = &s;
334 4 : r.in.security_flags = 0;
335 4 : r.in.offered = 0;
336 4 : r.out.buffer = NULL;
337 4 : r.out.needed = &needed;
338 :
339 4 : torture_assert_ntstatus_ok(tctx,
340 : dcerpc_svcctl_QueryServiceObjectSecurity_r(b, tctx, &r),
341 : "QueryServiceObjectSecurity failed!");
342 4 : torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAMETER,
343 : "QueryServiceObjectSecurity failed!");
344 :
345 4 : r.in.security_flags = SECINFO_DACL;
346 :
347 4 : torture_assert_ntstatus_ok(tctx,
348 : dcerpc_svcctl_QueryServiceObjectSecurity_r(b, tctx, &r),
349 : "QueryServiceObjectSecurity failed!");
350 :
351 4 : if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
352 4 : r.in.offered = needed;
353 4 : buffer = talloc_array(tctx, uint8_t, needed);
354 4 : r.out.buffer = buffer;
355 4 : torture_assert_ntstatus_ok(tctx,
356 : dcerpc_svcctl_QueryServiceObjectSecurity_r(b, tctx, &r),
357 : "QueryServiceObjectSecurity failed!");
358 : }
359 :
360 4 : torture_assert_werr_ok(tctx, r.out.result, "QueryServiceObjectSecurity failed!");
361 :
362 4 : blob = data_blob_const(buffer, needed);
363 :
364 4 : ndr_err = ndr_pull_struct_blob(&blob, tctx, &sd,
365 : (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
366 4 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
367 0 : return false;
368 : }
369 :
370 4 : if (DEBUGLEVEL >= 1) {
371 4 : NDR_PRINT_DEBUG(security_descriptor, &sd);
372 : }
373 :
374 4 : if (!test_CloseServiceHandle(b, tctx, &s))
375 0 : return false;
376 :
377 4 : if (!test_CloseServiceHandle(b, tctx, &h))
378 0 : return false;
379 :
380 4 : return true;
381 : }
382 :
383 4 : static bool test_SetServiceObjectSecurity(struct torture_context *tctx,
384 : struct dcerpc_pipe *p)
385 : {
386 0 : struct svcctl_QueryServiceObjectSecurity q;
387 0 : struct svcctl_SetServiceObjectSecurity r;
388 0 : struct policy_handle h, s;
389 4 : struct dcerpc_binding_handle *b = p->binding_handle;
390 :
391 0 : uint8_t *buffer;
392 0 : uint32_t needed;
393 :
394 4 : if (!test_OpenSCManager(b, tctx, &h))
395 0 : return false;
396 :
397 4 : if (!test_OpenService(b, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
398 0 : return false;
399 :
400 4 : q.in.handle = &s;
401 4 : q.in.security_flags = SECINFO_DACL;
402 4 : q.in.offered = 0;
403 4 : q.out.buffer = NULL;
404 4 : q.out.needed = &needed;
405 :
406 4 : torture_assert_ntstatus_ok(tctx,
407 : dcerpc_svcctl_QueryServiceObjectSecurity_r(b, tctx, &q),
408 : "QueryServiceObjectSecurity failed!");
409 :
410 4 : if (W_ERROR_EQUAL(q.out.result, WERR_INSUFFICIENT_BUFFER)) {
411 4 : q.in.offered = needed;
412 4 : buffer = talloc_array(tctx, uint8_t, needed);
413 4 : q.out.buffer = buffer;
414 4 : torture_assert_ntstatus_ok(tctx,
415 : dcerpc_svcctl_QueryServiceObjectSecurity_r(b, tctx, &q),
416 : "QueryServiceObjectSecurity failed!");
417 : }
418 :
419 4 : torture_assert_werr_ok(tctx, q.out.result,
420 : "QueryServiceObjectSecurity failed!");
421 :
422 4 : r.in.handle = &s;
423 4 : r.in.security_flags = SECINFO_DACL;
424 4 : r.in.buffer = q.out.buffer;
425 4 : r.in.offered = *q.out.needed;
426 :
427 4 : torture_assert_ntstatus_ok(tctx,
428 : dcerpc_svcctl_SetServiceObjectSecurity_r(b, tctx, &r),
429 : "SetServiceObjectSecurity failed!");
430 4 : torture_assert_werr_ok(tctx, r.out.result,
431 : "SetServiceObjectSecurity failed!");
432 :
433 4 : if (!test_CloseServiceHandle(b, tctx, &s))
434 0 : return false;
435 :
436 4 : if (!test_CloseServiceHandle(b, tctx, &h))
437 0 : return false;
438 :
439 4 : return true;
440 : }
441 :
442 4 : static bool test_StartServiceW(struct torture_context *tctx,
443 : struct dcerpc_pipe *p)
444 : {
445 0 : struct svcctl_StartServiceW r;
446 0 : struct policy_handle h, s;
447 4 : struct dcerpc_binding_handle *b = p->binding_handle;
448 :
449 4 : if (!test_OpenSCManager(b, tctx, &h))
450 0 : return false;
451 :
452 4 : if (!test_OpenService(b, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
453 0 : return false;
454 :
455 4 : r.in.handle = &s;
456 4 : r.in.NumArgs = 0;
457 4 : r.in.Arguments = NULL;
458 :
459 4 : torture_assert_ntstatus_ok(tctx,
460 : dcerpc_svcctl_StartServiceW_r(b, tctx, &r),
461 : "StartServiceW failed!");
462 4 : torture_assert_werr_equal(tctx, r.out.result,
463 : WERR_SERVICE_ALREADY_RUNNING,
464 : "StartServiceW failed!");
465 :
466 4 : if (!test_CloseServiceHandle(b, tctx, &s))
467 0 : return false;
468 :
469 4 : if (!test_CloseServiceHandle(b, tctx, &h))
470 0 : return false;
471 :
472 4 : return true;
473 : }
474 :
475 4 : static bool test_ControlService(struct torture_context *tctx,
476 : struct dcerpc_pipe *p)
477 : {
478 0 : struct svcctl_ControlService r;
479 0 : struct policy_handle h, s;
480 0 : struct SERVICE_STATUS service_status;
481 4 : struct dcerpc_binding_handle *b = p->binding_handle;
482 :
483 4 : if (!test_OpenSCManager(b, tctx, &h))
484 0 : return false;
485 :
486 4 : if (!test_OpenService(b, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
487 0 : return false;
488 :
489 4 : r.in.handle = &s;
490 4 : r.in.control = 0;
491 4 : r.out.service_status = &service_status;
492 :
493 4 : torture_assert_ntstatus_ok(tctx,
494 : dcerpc_svcctl_ControlService_r(b, tctx, &r),
495 : "ControlService failed!");
496 4 : torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAMETER,
497 : "ControlService failed!");
498 :
499 4 : if (!test_CloseServiceHandle(b, tctx, &s))
500 0 : return false;
501 :
502 4 : if (!test_CloseServiceHandle(b, tctx, &h))
503 0 : return false;
504 :
505 4 : return true;
506 : }
507 :
508 4 : static bool test_ControlServiceExW(struct torture_context *tctx,
509 : struct dcerpc_pipe *p)
510 : {
511 0 : struct svcctl_ControlServiceExW r;
512 0 : struct policy_handle h, s;
513 4 : struct dcerpc_binding_handle *b = p->binding_handle;
514 0 : union SC_RPC_SERVICE_CONTROL_IN_PARAMSW ControlInParams;
515 0 : union SC_RPC_SERVICE_CONTROL_OUT_PARAMSW ControlOutParams;
516 0 : struct SERVICE_CONTROL_STATUS_REASON_OUT_PARAMS psrOutParams;
517 0 : struct SERVICE_CONTROL_STATUS_REASON_IN_PARAMSW psrInParams;
518 :
519 4 : if (!test_OpenSCManager(b, tctx, &h))
520 0 : return false;
521 :
522 4 : if (!test_OpenService(b, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
523 0 : return false;
524 :
525 4 : ZERO_STRUCT(psrInParams);
526 4 : ZERO_STRUCT(psrOutParams);
527 :
528 4 : psrInParams.dwReason = SERVICE_STOP_CUSTOM |
529 : SERVICE_STOP_REASON_MAJOR_APPLICATION |
530 : SERVICE_STOP_REASON_MINOR_ENVIRONMENT;
531 4 : psrInParams.pszComment = "wurst";
532 :
533 4 : ControlInParams.psrInParams = &psrInParams;
534 4 : ControlOutParams.psrOutParams = &psrOutParams;
535 :
536 4 : r.in.hService = s;
537 4 : r.in.dwControl = SVCCTL_CONTROL_STOP;
538 4 : r.in.dwInfoLevel = 1;
539 4 : r.in.pControlInParams = &ControlInParams;
540 4 : r.out.pControlOutParams = &ControlOutParams;
541 :
542 4 : torture_assert_ntstatus_ok(tctx,
543 : dcerpc_svcctl_ControlServiceExW_r(b, tctx, &r),
544 : "ControlServiceExW failed!");
545 0 : torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAMETER,
546 : "ControlServiceExW failed!");
547 :
548 0 : if (!test_CloseServiceHandle(b, tctx, &s))
549 0 : return false;
550 :
551 0 : if (!test_CloseServiceHandle(b, tctx, &h))
552 0 : return false;
553 :
554 0 : return true;
555 : }
556 :
557 4 : static bool test_EnumServicesStatus(struct torture_context *tctx, struct dcerpc_pipe *p)
558 : {
559 0 : struct svcctl_EnumServicesStatusW r;
560 0 : struct policy_handle h;
561 0 : int i;
562 0 : NTSTATUS status;
563 4 : uint32_t resume_handle = 0;
564 4 : struct ENUM_SERVICE_STATUSW *service = NULL;
565 4 : uint32_t needed = 0;
566 4 : uint32_t services_returned = 0;
567 4 : struct dcerpc_binding_handle *b = p->binding_handle;
568 :
569 4 : if (!test_OpenSCManager(b, tctx, &h))
570 0 : return false;
571 :
572 4 : r.in.handle = &h;
573 4 : r.in.type = SERVICE_TYPE_WIN32;
574 4 : r.in.state = SERVICE_STATE_ALL;
575 4 : r.in.offered = 0;
576 4 : r.in.resume_handle = &resume_handle;
577 4 : r.out.service = NULL;
578 4 : r.out.resume_handle = &resume_handle;
579 4 : r.out.services_returned = &services_returned;
580 4 : r.out.needed = &needed;
581 :
582 4 : status = dcerpc_svcctl_EnumServicesStatusW_r(b, tctx, &r);
583 :
584 4 : torture_assert_ntstatus_ok(tctx, status, "EnumServicesStatus failed!");
585 :
586 4 : if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
587 4 : r.in.offered = needed;
588 4 : r.out.service = talloc_array(tctx, uint8_t, needed);
589 :
590 4 : status = dcerpc_svcctl_EnumServicesStatusW_r(b, tctx, &r);
591 :
592 4 : torture_assert_ntstatus_ok(tctx, status, "EnumServicesStatus failed!");
593 4 : torture_assert_werr_ok(tctx, r.out.result, "EnumServicesStatus failed");
594 : }
595 :
596 4 : if (services_returned > 0) {
597 :
598 0 : enum ndr_err_code ndr_err;
599 0 : DATA_BLOB blob;
600 0 : struct ndr_pull *ndr;
601 :
602 4 : blob.length = r.in.offered;
603 4 : blob.data = talloc_steal(tctx, r.out.service);
604 :
605 4 : ndr = ndr_pull_init_blob(&blob, tctx);
606 :
607 4 : service = talloc_array(tctx, struct ENUM_SERVICE_STATUSW, services_returned);
608 4 : if (!service) {
609 0 : return false;
610 : }
611 :
612 4 : ndr_err = ndr_pull_ENUM_SERVICE_STATUSW_array(
613 : ndr, services_returned, service);
614 4 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
615 0 : return false;
616 : }
617 : }
618 :
619 20 : for(i = 0; i < services_returned; i++) {
620 :
621 16 : torture_assert(tctx, service[i].service_name,
622 : "Service without name returned!");
623 :
624 16 : printf("%-20s \"%s\", Type: %d, State: %d\n",
625 16 : service[i].service_name, service[i].display_name,
626 16 : service[i].status.type, service[i].status.state);
627 : }
628 :
629 4 : if (!test_CloseServiceHandle(b, tctx, &h))
630 0 : return false;
631 :
632 4 : return true;
633 : }
634 :
635 4 : static bool test_EnumDependentServicesW(struct torture_context *tctx,
636 : struct dcerpc_pipe *p)
637 : {
638 0 : struct svcctl_EnumDependentServicesW r;
639 0 : struct policy_handle h, s;
640 0 : uint32_t needed;
641 0 : uint32_t services_returned;
642 0 : uint32_t i;
643 4 : uint32_t states[] = { SERVICE_STATE_ACTIVE,
644 : SERVICE_STATE_INACTIVE,
645 : SERVICE_STATE_ALL };
646 4 : struct dcerpc_binding_handle *b = p->binding_handle;
647 :
648 4 : if (!test_OpenSCManager(b, tctx, &h))
649 0 : return false;
650 :
651 4 : if (!test_OpenService(b, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
652 0 : return false;
653 :
654 4 : r.in.service = &s;
655 4 : r.in.offered = 0;
656 4 : r.in.state = 0;
657 4 : r.out.service_status = NULL;
658 4 : r.out.services_returned = &services_returned;
659 4 : r.out.needed = &needed;
660 :
661 4 : torture_assert_ntstatus_ok(tctx,
662 : dcerpc_svcctl_EnumDependentServicesW_r(b, tctx, &r),
663 : "EnumDependentServicesW failed!");
664 :
665 4 : torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAMETER,
666 : "EnumDependentServicesW failed!");
667 :
668 16 : for (i=0; i<ARRAY_SIZE(states); i++) {
669 :
670 12 : r.in.state = states[i];
671 :
672 12 : torture_assert_ntstatus_ok(tctx,
673 : dcerpc_svcctl_EnumDependentServicesW_r(b, tctx, &r),
674 : "EnumDependentServicesW failed!");
675 :
676 12 : if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
677 0 : r.in.offered = needed;
678 0 : r.out.service_status = talloc_array(tctx, uint8_t, needed);
679 :
680 0 : torture_assert_ntstatus_ok(tctx,
681 : dcerpc_svcctl_EnumDependentServicesW_r(b, tctx, &r),
682 : "EnumDependentServicesW failed!");
683 :
684 : }
685 :
686 12 : torture_assert_werr_ok(tctx, r.out.result,
687 : "EnumDependentServicesW failed");
688 : }
689 :
690 4 : if (!test_CloseServiceHandle(b, tctx, &s))
691 0 : return false;
692 :
693 4 : if (!test_CloseServiceHandle(b, tctx, &h))
694 0 : return false;
695 :
696 4 : return true;
697 : }
698 :
699 4 : static bool test_SCManager(struct torture_context *tctx,
700 : struct dcerpc_pipe *p)
701 : {
702 0 : struct policy_handle h;
703 4 : struct dcerpc_binding_handle *b = p->binding_handle;
704 :
705 4 : if (!test_OpenSCManager(b, tctx, &h))
706 0 : return false;
707 :
708 4 : if (!test_CloseServiceHandle(b, tctx, &h))
709 0 : return false;
710 :
711 4 : return true;
712 : }
713 :
714 4 : static bool test_ChangeServiceConfigW(struct torture_context *tctx,
715 : struct dcerpc_pipe *p)
716 : {
717 0 : struct svcctl_ChangeServiceConfigW r;
718 0 : struct svcctl_QueryServiceConfigW q;
719 0 : struct policy_handle h, s;
720 0 : NTSTATUS status;
721 4 : struct dcerpc_binding_handle *b = p->binding_handle;
722 0 : struct QUERY_SERVICE_CONFIG query;
723 0 : bool ok;
724 :
725 4 : uint32_t offered = 0;
726 4 : uint32_t needed = 0;
727 :
728 4 : ok = test_OpenSCManager(b, tctx, &h);
729 4 : if (!ok) {
730 0 : return false;
731 : }
732 :
733 4 : ok = test_OpenService(b, tctx, &h, TORTURE_DEFAULT_SERVICE, &s);
734 4 : if (!ok) {
735 0 : return false;
736 : }
737 :
738 4 : q.in.handle = &s;
739 4 : q.in.offered = offered;
740 4 : q.out.query = &query;
741 4 : q.out.needed = &needed;
742 :
743 4 : status = dcerpc_svcctl_QueryServiceConfigW_r(b, tctx, &q);
744 4 : torture_assert_ntstatus_ok(tctx, status, "QueryServiceConfigW failed!");
745 :
746 4 : if (W_ERROR_EQUAL(q.out.result, WERR_INSUFFICIENT_BUFFER)) {
747 4 : q.in.offered = needed;
748 4 : status = dcerpc_svcctl_QueryServiceConfigW_r(b, tctx, &q);
749 4 : torture_assert_ntstatus_ok(tctx, status, "QueryServiceConfigW failed!");
750 : }
751 4 : torture_assert_werr_ok(tctx, q.out.result, "QueryServiceConfigW failed!");
752 :
753 4 : r.in.handle = &s;
754 4 : r.in.type = query.service_type;
755 4 : r.in.start_type = query.start_type;
756 4 : r.in.error_control = query.error_control;
757 :
758 : /*
759 : * according to MS-SCMR 3.1.4.11 NULL params are supposed to leave the
760 : * existing values intact.
761 : */
762 :
763 4 : r.in.binary_path = NULL;
764 4 : r.in.load_order_group = NULL;
765 4 : r.in.dependencies = NULL;
766 4 : r.in.dwDependSize = 0;
767 4 : r.in.service_start_name = NULL;
768 4 : r.in.password = NULL;
769 4 : r.in.dwPwSize = 0;
770 4 : r.in.display_name = NULL;
771 4 : r.in.tag_id = NULL;
772 4 : r.out.tag_id = NULL;
773 :
774 4 : status = dcerpc_svcctl_ChangeServiceConfigW_r(b, tctx, &r);
775 4 : torture_assert_ntstatus_ok(tctx, status, "ChangeServiceConfigW failed!");
776 0 : torture_assert_werr_ok(tctx, r.out.result, "ChangeServiceConfigW failed!");
777 :
778 0 : ok = test_CloseServiceHandle(b, tctx, &s);
779 0 : if (!ok) {
780 0 : return false;
781 : }
782 :
783 0 : ok = test_CloseServiceHandle(b, tctx, &h);
784 0 : if (!ok) {
785 0 : return false;
786 : }
787 :
788 0 : return true;
789 : }
790 :
791 2354 : struct torture_suite *torture_rpc_svcctl(TALLOC_CTX *mem_ctx)
792 : {
793 2354 : struct torture_suite *suite = torture_suite_create(mem_ctx, "svcctl");
794 125 : struct torture_rpc_tcase *tcase;
795 :
796 2354 : tcase = torture_suite_add_rpc_iface_tcase(suite, "svcctl", &ndr_table_svcctl);
797 :
798 2354 : torture_rpc_tcase_add_test(tcase, "SCManager",
799 : test_SCManager);
800 2354 : torture_rpc_tcase_add_test(tcase, "EnumServicesStatus",
801 : test_EnumServicesStatus);
802 2354 : torture_rpc_tcase_add_test(tcase, "EnumDependentServicesW",
803 : test_EnumDependentServicesW);
804 2354 : torture_rpc_tcase_add_test(tcase, "QueryServiceStatus",
805 : test_QueryServiceStatus);
806 2354 : torture_rpc_tcase_add_test(tcase, "QueryServiceStatusEx",
807 : test_QueryServiceStatusEx);
808 2354 : torture_rpc_tcase_add_test(tcase, "QueryServiceConfigW",
809 : test_QueryServiceConfigW);
810 2354 : torture_rpc_tcase_add_test(tcase, "QueryServiceConfig2W",
811 : test_QueryServiceConfig2W);
812 2354 : torture_rpc_tcase_add_test(tcase, "QueryServiceConfigEx",
813 : test_QueryServiceConfigEx);
814 2354 : torture_rpc_tcase_add_test(tcase, "QueryServiceObjectSecurity",
815 : test_QueryServiceObjectSecurity);
816 2354 : torture_rpc_tcase_add_test(tcase, "SetServiceObjectSecurity",
817 : test_SetServiceObjectSecurity);
818 2354 : torture_rpc_tcase_add_test(tcase, "StartServiceW",
819 : test_StartServiceW);
820 2354 : torture_rpc_tcase_add_test(tcase, "ControlService",
821 : test_ControlService);
822 2354 : torture_rpc_tcase_add_test(tcase, "ControlServiceExW",
823 : test_ControlServiceExW);
824 2354 : torture_rpc_tcase_add_test(tcase, "ChangeServiceConfigW",
825 : test_ChangeServiceConfigW);
826 :
827 2354 : return suite;
828 : }
|