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