ad27060659d3c1802c0120509f37dbb4e26e9f65
[ira/wip.git] / source4 / torture / rpc / svcctl.c
1 /*
2    Unix SMB/CIFS implementation.
3    test suite for srvsvc rpc operations
4
5    Copyright (C) Jelmer Vernooij 2004
6    Copyright (C) Guenther Deschner 2008,2009
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 "torture/torture.h"
24 #include "librpc/gen_ndr/ndr_svcctl_c.h"
25 #include "librpc/gen_ndr/ndr_svcctl.h"
26 #include "torture/rpc/rpc.h"
27 #include "param/param.h"
28
29 #define TORTURE_DEFAULT_SERVICE "Spooler"
30
31 static bool test_OpenSCManager(struct dcerpc_pipe *p, struct torture_context *tctx, struct policy_handle *h)
32 {
33         struct svcctl_OpenSCManagerW r;
34
35         r.in.MachineName = NULL;
36         r.in.DatabaseName = NULL;
37         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
38         r.out.handle = h;
39
40         torture_assert_ntstatus_ok(tctx,
41                                    dcerpc_svcctl_OpenSCManagerW(p, tctx, &r),
42                                    "OpenSCManager failed!");
43
44         return true;
45 }
46
47 static bool test_CloseServiceHandle(struct dcerpc_pipe *p, struct torture_context *tctx, struct policy_handle *h)
48 {
49         struct svcctl_CloseServiceHandle r;
50
51         r.in.handle = h;
52         r.out.handle = h;
53         torture_assert_ntstatus_ok(tctx,
54                                    dcerpc_svcctl_CloseServiceHandle(p, tctx, &r),
55                                    "CloseServiceHandle failed");
56
57         return true;
58 }
59
60 static bool test_OpenService(struct dcerpc_pipe *p, struct torture_context *tctx,
61                              struct policy_handle *h, const char *name, struct policy_handle *s)
62 {
63         struct svcctl_OpenServiceW r;
64
65         r.in.scmanager_handle = h;
66         r.in.ServiceName = name;
67         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
68         r.out.handle = s;
69
70         torture_assert_ntstatus_ok(tctx,
71                                    dcerpc_svcctl_OpenServiceW(p, tctx, &r),
72                                    "OpenServiceW failed!");
73         torture_assert_werr_ok(tctx, r.out.result, "OpenServiceW failed!");
74
75         return true;
76
77 }
78
79 static bool test_QueryServiceStatus(struct torture_context *tctx,
80                                     struct dcerpc_pipe *p)
81 {
82         struct svcctl_QueryServiceStatus r;
83         struct policy_handle h, s;
84         struct SERVICE_STATUS service_status;
85         NTSTATUS status;
86
87         if (!test_OpenSCManager(p, tctx, &h))
88                 return false;
89
90         if (!test_OpenService(p, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
91                 return false;
92
93         r.in.handle = &s;
94         r.out.service_status = &service_status;
95
96         status = dcerpc_svcctl_QueryServiceStatus(p, tctx, &r);
97         torture_assert_ntstatus_ok(tctx, status, "QueryServiceStatus failed!");
98         torture_assert_werr_ok(tctx, r.out.result, "QueryServiceStatus failed!");
99
100         if (!test_CloseServiceHandle(p, tctx, &s))
101                 return false;
102
103         if (!test_CloseServiceHandle(p, tctx, &h))
104                 return false;
105
106         return true;
107 }
108
109 static bool test_QueryServiceStatusEx(struct torture_context *tctx, struct dcerpc_pipe *p)
110 {
111         struct svcctl_QueryServiceStatusEx r;
112         struct policy_handle h, s;
113         NTSTATUS status;
114
115         uint32_t info_level = SVC_STATUS_PROCESS_INFO;
116         uint8_t *buffer;
117         uint32_t offered = 0;
118         uint32_t needed = 0;
119
120         if (!test_OpenSCManager(p, tctx, &h))
121                 return false;
122
123         if (!test_OpenService(p, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
124                 return false;
125
126         buffer = talloc(tctx, uint8_t);
127
128         r.in.handle = &s;
129         r.in.info_level = info_level;
130         r.in.offered = offered;
131         r.out.buffer = buffer;
132         r.out.needed = &needed;
133
134         status = dcerpc_svcctl_QueryServiceStatusEx(p, tctx, &r);
135         torture_assert_ntstatus_ok(tctx, status, "QueryServiceStatusEx failed!");
136
137         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
138                 r.in.offered = needed;
139                 buffer = talloc_array(tctx, uint8_t, needed);
140                 r.out.buffer = buffer;
141
142                 status = dcerpc_svcctl_QueryServiceStatusEx(p, tctx, &r);
143                 torture_assert_ntstatus_ok(tctx, status, "QueryServiceStatusEx failed!");
144                 torture_assert_werr_ok(tctx, r.out.result, "QueryServiceStatusEx failed!");
145         }
146
147         if (!test_CloseServiceHandle(p, tctx, &s))
148                 return false;
149
150         if (!test_CloseServiceHandle(p, tctx, &h))
151                 return false;
152
153         return true;
154 }
155
156 static bool test_QueryServiceConfigW(struct torture_context *tctx,
157                                      struct dcerpc_pipe *p)
158 {
159         struct svcctl_QueryServiceConfigW r;
160         struct QUERY_SERVICE_CONFIG query;
161         struct policy_handle h, s;
162         NTSTATUS status;
163
164         uint32_t offered = 0;
165         uint32_t needed = 0;
166
167         if (!test_OpenSCManager(p, tctx, &h))
168                 return false;
169
170         if (!test_OpenService(p, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
171                 return false;
172
173         r.in.handle = &s;
174         r.in.offered = offered;
175         r.out.query = &query;
176         r.out.needed = &needed;
177
178         status = dcerpc_svcctl_QueryServiceConfigW(p, tctx, &r);
179         torture_assert_ntstatus_ok(tctx, status, "QueryServiceConfigW failed!");
180
181         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
182                 r.in.offered = needed;
183                 status = dcerpc_svcctl_QueryServiceConfigW(p, tctx, &r);
184                 torture_assert_ntstatus_ok(tctx, status, "QueryServiceConfigW failed!");
185         }
186
187         torture_assert_werr_ok(tctx, r.out.result, "QueryServiceConfigW failed!");
188
189         if (!test_CloseServiceHandle(p, tctx, &s))
190                 return false;
191
192         if (!test_CloseServiceHandle(p, tctx, &h))
193                 return false;
194
195         return true;
196 }
197
198 static bool test_QueryServiceConfig2W(struct torture_context *tctx, struct dcerpc_pipe *p)
199 {
200         struct svcctl_QueryServiceConfig2W r;
201         struct policy_handle h, s;
202         NTSTATUS status;
203
204         uint32_t info_level = SERVICE_CONFIG_DESCRIPTION;
205         uint8_t *buffer;
206         uint32_t offered = 0;
207         uint32_t needed = 0;
208
209         if (!test_OpenSCManager(p, tctx, &h))
210                 return false;
211
212         if (!test_OpenService(p, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
213                 return false;
214
215         buffer = talloc(tctx, uint8_t);
216
217         r.in.handle = &s;
218         r.in.info_level = info_level;
219         r.in.offered = offered;
220         r.out.buffer = buffer;
221         r.out.needed = &needed;
222
223         status = dcerpc_svcctl_QueryServiceConfig2W(p, tctx, &r);
224         torture_assert_ntstatus_ok(tctx, status, "QueryServiceConfig2W failed!");
225
226         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
227                 r.in.offered = needed;
228                 buffer = talloc_array(tctx, uint8_t, needed);
229                 r.out.buffer = buffer;
230
231                 status = dcerpc_svcctl_QueryServiceConfig2W(p, tctx, &r);
232                 torture_assert_ntstatus_ok(tctx, status, "QueryServiceConfig2W failed!");
233                 torture_assert_werr_ok(tctx, r.out.result, "QueryServiceConfig2W failed!");
234         }
235
236         r.in.info_level = SERVICE_CONFIG_FAILURE_ACTIONS;
237         r.in.offered = offered;
238         r.out.buffer = buffer;
239         r.out.needed = &needed;
240
241         status = dcerpc_svcctl_QueryServiceConfig2W(p, tctx, &r);
242         torture_assert_ntstatus_ok(tctx, status, "QueryServiceConfig2W failed!");
243
244         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
245                 r.in.offered = needed;
246                 buffer = talloc_array(tctx, uint8_t, needed);
247                 r.out.buffer = buffer;
248
249                 status = dcerpc_svcctl_QueryServiceConfig2W(p, tctx, &r);
250                 torture_assert_ntstatus_ok(tctx, status, "QueryServiceConfig2W failed!");
251                 torture_assert_werr_ok(tctx, r.out.result, "QueryServiceConfig2W failed!");
252         }
253
254         if (!test_CloseServiceHandle(p, tctx, &s))
255                 return false;
256
257         if (!test_CloseServiceHandle(p, tctx, &h))
258                 return false;
259
260         return true;
261 }
262
263 static bool test_QueryServiceObjectSecurity(struct torture_context *tctx,
264                                             struct dcerpc_pipe *p)
265 {
266         struct svcctl_QueryServiceObjectSecurity r;
267         struct policy_handle h, s;
268
269         uint8_t *buffer;
270         uint32_t needed;
271
272         if (!test_OpenSCManager(p, tctx, &h))
273                 return false;
274
275         if (!test_OpenService(p, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
276                 return false;
277
278         r.in.handle = &s;
279         r.in.security_flags = 0;
280         r.in.offered = 0;
281         r.out.buffer = NULL;
282         r.out.needed = &needed;
283
284         torture_assert_ntstatus_ok(tctx,
285                 dcerpc_svcctl_QueryServiceObjectSecurity(p, tctx, &r),
286                 "QueryServiceObjectSecurity failed!");
287         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
288                 "QueryServiceObjectSecurity failed!");
289
290         r.in.security_flags = SECINFO_DACL;
291
292         torture_assert_ntstatus_ok(tctx,
293                 dcerpc_svcctl_QueryServiceObjectSecurity(p, tctx, &r),
294                 "QueryServiceObjectSecurity failed!");
295
296         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
297                 r.in.offered = needed;
298                 buffer = talloc_array(tctx, uint8_t, needed);
299                 r.out.buffer = buffer;
300                 torture_assert_ntstatus_ok(tctx,
301                         dcerpc_svcctl_QueryServiceObjectSecurity(p, tctx, &r),
302                         "QueryServiceObjectSecurity failed!");
303         }
304
305         torture_assert_werr_ok(tctx, r.out.result, "QueryServiceObjectSecurity failed!");
306
307         if (!test_CloseServiceHandle(p, tctx, &s))
308                 return false;
309
310         if (!test_CloseServiceHandle(p, tctx, &h))
311                 return false;
312
313         return true;
314 }
315
316 static bool test_StartServiceW(struct torture_context *tctx,
317                                struct dcerpc_pipe *p)
318 {
319         struct svcctl_StartServiceW r;
320         struct policy_handle h, s;
321
322         if (!test_OpenSCManager(p, tctx, &h))
323                 return false;
324
325         if (!test_OpenService(p, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
326                 return false;
327
328         r.in.handle = &s;
329         r.in.NumArgs = 0;
330         r.in.Arguments = NULL;
331
332         torture_assert_ntstatus_ok(tctx,
333                 dcerpc_svcctl_StartServiceW(p, tctx, &r),
334                 "StartServiceW failed!");
335         torture_assert_werr_equal(tctx, r.out.result,
336                 WERR_SERVICE_ALREADY_RUNNING,
337                 "StartServiceW failed!");
338
339         if (!test_CloseServiceHandle(p, tctx, &s))
340                 return false;
341
342         if (!test_CloseServiceHandle(p, tctx, &h))
343                 return false;
344
345         return true;
346 }
347
348 static bool test_ControlService(struct torture_context *tctx,
349                                 struct dcerpc_pipe *p)
350 {
351         struct svcctl_ControlService r;
352         struct policy_handle h, s;
353         struct SERVICE_STATUS service_status;
354
355         if (!test_OpenSCManager(p, tctx, &h))
356                 return false;
357
358         if (!test_OpenService(p, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
359                 return false;
360
361         r.in.handle = &s;
362         r.in.control = 0;
363         r.out.service_status = &service_status;
364
365         torture_assert_ntstatus_ok(tctx,
366                 dcerpc_svcctl_ControlService(p, tctx, &r),
367                 "ControlService failed!");
368         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
369                 "ControlService failed!");
370
371         if (!test_CloseServiceHandle(p, tctx, &s))
372                 return false;
373
374         if (!test_CloseServiceHandle(p, tctx, &h))
375                 return false;
376
377         return true;
378 }
379
380 static bool test_EnumServicesStatus(struct torture_context *tctx, struct dcerpc_pipe *p)
381 {
382         struct svcctl_EnumServicesStatusW r;
383         struct policy_handle h;
384         int i;
385         NTSTATUS status;
386         uint32_t resume_handle = 0;
387         struct ENUM_SERVICE_STATUSW *service = NULL;
388         uint32_t needed = 0;
389         uint32_t services_returned = 0;
390
391         if (!test_OpenSCManager(p, tctx, &h))
392                 return false;
393
394         r.in.handle = &h;
395         r.in.type = SERVICE_TYPE_WIN32;
396         r.in.state = SERVICE_STATE_ALL;
397         r.in.offered = 0;
398         r.in.resume_handle = &resume_handle;
399         r.out.service = NULL;
400         r.out.resume_handle = &resume_handle;
401         r.out.services_returned = &services_returned;
402         r.out.needed = &needed;
403
404         status = dcerpc_svcctl_EnumServicesStatusW(p, tctx, &r);
405
406         torture_assert_ntstatus_ok(tctx, status, "EnumServicesStatus failed!");
407
408         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
409                 r.in.offered = needed;
410                 r.out.service = talloc_array(tctx, uint8_t, needed);
411
412                 status = dcerpc_svcctl_EnumServicesStatusW(p, tctx, &r);
413
414                 torture_assert_ntstatus_ok(tctx, status, "EnumServicesStatus failed!");
415                 torture_assert_werr_ok(tctx, r.out.result, "EnumServicesStatus failed");
416         }
417
418         if (services_returned > 0) {
419
420                 enum ndr_err_code ndr_err;
421                 DATA_BLOB blob;
422                 struct ndr_pull *ndr;
423
424                 blob.length = r.in.offered;
425                 blob.data = talloc_steal(tctx, r.out.service);
426
427                 ndr = ndr_pull_init_blob(&blob, tctx, lp_iconv_convenience(tctx->lp_ctx));
428
429                 service = talloc_array(tctx, struct ENUM_SERVICE_STATUSW, services_returned);
430                 if (!service) {
431                         return false;
432                 }
433
434                 ndr_err = ndr_pull_ENUM_SERVICE_STATUSW_array(
435                                 ndr, services_returned, service);
436                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
437                         return false;
438                 }
439         }
440
441         for(i = 0; i < services_returned; i++) {
442
443                 torture_assert(tctx, service[i].service_name,
444                         "Service without name returned!");
445
446                 printf("%-20s   \"%s\", Type: %d, State: %d\n",
447                         service[i].service_name, service[i].display_name,
448                         service[i].status.type, service[i].status.state);
449         }
450
451         if (!test_CloseServiceHandle(p, tctx, &h))
452                 return false;
453
454         return true;
455 }
456
457 static bool test_EnumDependentServicesW(struct torture_context *tctx,
458                                         struct dcerpc_pipe *p)
459 {
460         struct svcctl_EnumDependentServicesW r;
461         struct policy_handle h, s;
462         uint32_t needed;
463         uint32_t services_returned;
464         uint32_t i;
465         uint32_t states[] = { SERVICE_STATE_ACTIVE,
466                               SERVICE_STATE_INACTIVE,
467                               SERVICE_STATE_ALL };
468
469         if (!test_OpenSCManager(p, tctx, &h))
470                 return false;
471
472         if (!test_OpenService(p, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
473                 return false;
474
475         r.in.service = &s;
476         r.in.offered = 0;
477         r.in.state = 0;
478         r.out.service_status = NULL;
479         r.out.services_returned = &services_returned;
480         r.out.needed = &needed;
481
482         torture_assert_ntstatus_ok(tctx,
483                 dcerpc_svcctl_EnumDependentServicesW(p, tctx, &r),
484                 "EnumDependentServicesW failed!");
485
486         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
487                 "EnumDependentServicesW failed!");
488
489         for (i=0; i<ARRAY_SIZE(states); i++) {
490
491                 r.in.state = states[i];
492
493                 torture_assert_ntstatus_ok(tctx,
494                         dcerpc_svcctl_EnumDependentServicesW(p, tctx, &r),
495                         "EnumDependentServicesW failed!");
496
497                 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
498                         r.in.offered = needed;
499                         r.out.service_status = talloc_array(tctx, uint8_t, needed);
500
501                         torture_assert_ntstatus_ok(tctx,
502                                 dcerpc_svcctl_EnumDependentServicesW(p, tctx, &r),
503                                 "EnumDependentServicesW failed!");
504
505                 }
506
507                 torture_assert_werr_ok(tctx, r.out.result,
508                         "EnumDependentServicesW failed");
509         }
510
511         if (!test_CloseServiceHandle(p, tctx, &s))
512                 return false;
513
514         if (!test_CloseServiceHandle(p, tctx, &h))
515                 return false;
516
517         return true;
518 }
519
520 static bool test_SCManager(struct torture_context *tctx,
521                                                    struct dcerpc_pipe *p)
522 {
523         struct policy_handle h;
524
525         if (!test_OpenSCManager(p, tctx, &h))
526                 return false;
527
528         if (!test_CloseServiceHandle(p, tctx, &h))
529                 return false;
530
531         return true;
532 }
533
534 struct torture_suite *torture_rpc_svcctl(TALLOC_CTX *mem_ctx)
535 {
536         struct torture_suite *suite = torture_suite_create(mem_ctx, "SVCCTL");
537         struct torture_rpc_tcase *tcase;
538
539         tcase = torture_suite_add_rpc_iface_tcase(suite, "svcctl", &ndr_table_svcctl);
540
541         torture_rpc_tcase_add_test(tcase, "SCManager",
542                                    test_SCManager);
543         torture_rpc_tcase_add_test(tcase, "EnumServicesStatus",
544                                    test_EnumServicesStatus);
545         torture_rpc_tcase_add_test(tcase, "EnumDependentServicesW",
546                                    test_EnumDependentServicesW);
547         torture_rpc_tcase_add_test(tcase, "QueryServiceStatus",
548                                    test_QueryServiceStatus);
549         torture_rpc_tcase_add_test(tcase, "QueryServiceStatusEx",
550                                    test_QueryServiceStatusEx);
551         torture_rpc_tcase_add_test(tcase, "QueryServiceConfigW",
552                                    test_QueryServiceConfigW);
553         torture_rpc_tcase_add_test(tcase, "QueryServiceConfig2W",
554                                    test_QueryServiceConfig2W);
555         torture_rpc_tcase_add_test(tcase, "QueryServiceObjectSecurity",
556                                    test_QueryServiceObjectSecurity);
557         torture_rpc_tcase_add_test(tcase, "StartServiceW",
558                                    test_StartServiceW);
559         torture_rpc_tcase_add_test(tcase, "ControlService",
560                                    test_ControlService);
561
562         return suite;
563 }