2
Unix SMB/CIFS implementation.
3
test suite for srvsvc rpc operations
5
Copyright (C) Jelmer Vernooij 2004
6
Copyright (C) Guenther Deschner 2008,2009
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.
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.
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/>.
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"
29
#define TORTURE_DEFAULT_SERVICE "Spooler"
31
static bool test_OpenSCManager(struct dcerpc_pipe *p, struct torture_context *tctx, struct policy_handle *h)
33
struct svcctl_OpenSCManagerW r;
35
r.in.MachineName = NULL;
36
r.in.DatabaseName = NULL;
37
r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
40
torture_assert_ntstatus_ok(tctx,
41
dcerpc_svcctl_OpenSCManagerW(p, tctx, &r),
42
"OpenSCManager failed!");
47
static bool test_CloseServiceHandle(struct dcerpc_pipe *p, struct torture_context *tctx, struct policy_handle *h)
49
struct svcctl_CloseServiceHandle r;
53
torture_assert_ntstatus_ok(tctx,
54
dcerpc_svcctl_CloseServiceHandle(p, tctx, &r),
55
"CloseServiceHandle failed");
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)
63
struct svcctl_OpenServiceW r;
65
r.in.scmanager_handle = h;
66
r.in.ServiceName = name;
67
r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
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!");
79
static bool test_QueryServiceStatus(struct torture_context *tctx,
80
struct dcerpc_pipe *p)
82
struct svcctl_QueryServiceStatus r;
83
struct policy_handle h, s;
84
struct SERVICE_STATUS service_status;
87
if (!test_OpenSCManager(p, tctx, &h))
90
if (!test_OpenService(p, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
94
r.out.service_status = &service_status;
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!");
100
if (!test_CloseServiceHandle(p, tctx, &s))
103
if (!test_CloseServiceHandle(p, tctx, &h))
109
static bool test_QueryServiceStatusEx(struct torture_context *tctx, struct dcerpc_pipe *p)
111
struct svcctl_QueryServiceStatusEx r;
112
struct policy_handle h, s;
115
uint32_t info_level = SVC_STATUS_PROCESS_INFO;
117
uint32_t offered = 0;
120
if (!test_OpenSCManager(p, tctx, &h))
123
if (!test_OpenService(p, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
126
buffer = talloc(tctx, uint8_t);
129
r.in.info_level = info_level;
130
r.in.offered = offered;
131
r.out.buffer = buffer;
132
r.out.needed = &needed;
134
status = dcerpc_svcctl_QueryServiceStatusEx(p, tctx, &r);
135
torture_assert_ntstatus_ok(tctx, status, "QueryServiceStatusEx failed!");
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;
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!");
147
if (!test_CloseServiceHandle(p, tctx, &s))
150
if (!test_CloseServiceHandle(p, tctx, &h))
156
static bool test_QueryServiceConfigW(struct torture_context *tctx,
157
struct dcerpc_pipe *p)
159
struct svcctl_QueryServiceConfigW r;
160
struct QUERY_SERVICE_CONFIG query;
161
struct policy_handle h, s;
164
uint32_t offered = 0;
167
if (!test_OpenSCManager(p, tctx, &h))
170
if (!test_OpenService(p, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
174
r.in.offered = offered;
175
r.out.query = &query;
176
r.out.needed = &needed;
178
status = dcerpc_svcctl_QueryServiceConfigW(p, tctx, &r);
179
torture_assert_ntstatus_ok(tctx, status, "QueryServiceConfigW failed!");
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!");
187
torture_assert_werr_ok(tctx, r.out.result, "QueryServiceConfigW failed!");
189
if (!test_CloseServiceHandle(p, tctx, &s))
192
if (!test_CloseServiceHandle(p, tctx, &h))
198
static bool test_QueryServiceConfig2W(struct torture_context *tctx, struct dcerpc_pipe *p)
200
struct svcctl_QueryServiceConfig2W r;
201
struct policy_handle h, s;
204
uint32_t info_level = SERVICE_CONFIG_DESCRIPTION;
206
uint32_t offered = 0;
209
if (!test_OpenSCManager(p, tctx, &h))
212
if (!test_OpenService(p, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
215
buffer = talloc(tctx, uint8_t);
218
r.in.info_level = info_level;
219
r.in.offered = offered;
220
r.out.buffer = buffer;
221
r.out.needed = &needed;
223
status = dcerpc_svcctl_QueryServiceConfig2W(p, tctx, &r);
224
torture_assert_ntstatus_ok(tctx, status, "QueryServiceConfig2W failed!");
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;
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!");
236
r.in.info_level = SERVICE_CONFIG_FAILURE_ACTIONS;
237
r.in.offered = offered;
238
r.out.buffer = buffer;
239
r.out.needed = &needed;
241
status = dcerpc_svcctl_QueryServiceConfig2W(p, tctx, &r);
242
torture_assert_ntstatus_ok(tctx, status, "QueryServiceConfig2W failed!");
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;
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!");
254
if (!test_CloseServiceHandle(p, tctx, &s))
257
if (!test_CloseServiceHandle(p, tctx, &h))
263
static bool test_QueryServiceObjectSecurity(struct torture_context *tctx,
264
struct dcerpc_pipe *p)
266
struct svcctl_QueryServiceObjectSecurity r;
267
struct policy_handle h, s;
272
if (!test_OpenSCManager(p, tctx, &h))
275
if (!test_OpenService(p, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
279
r.in.security_flags = 0;
282
r.out.needed = &needed;
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!");
290
r.in.security_flags = SECINFO_DACL;
292
torture_assert_ntstatus_ok(tctx,
293
dcerpc_svcctl_QueryServiceObjectSecurity(p, tctx, &r),
294
"QueryServiceObjectSecurity failed!");
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!");
305
torture_assert_werr_ok(tctx, r.out.result, "QueryServiceObjectSecurity failed!");
307
if (!test_CloseServiceHandle(p, tctx, &s))
310
if (!test_CloseServiceHandle(p, tctx, &h))
316
static bool test_StartServiceW(struct torture_context *tctx,
317
struct dcerpc_pipe *p)
319
struct svcctl_StartServiceW r;
320
struct policy_handle h, s;
322
if (!test_OpenSCManager(p, tctx, &h))
325
if (!test_OpenService(p, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
330
r.in.Arguments = NULL;
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!");
339
if (!test_CloseServiceHandle(p, tctx, &s))
342
if (!test_CloseServiceHandle(p, tctx, &h))
348
static bool test_ControlService(struct torture_context *tctx,
349
struct dcerpc_pipe *p)
351
struct svcctl_ControlService r;
352
struct policy_handle h, s;
353
struct SERVICE_STATUS service_status;
355
if (!test_OpenSCManager(p, tctx, &h))
358
if (!test_OpenService(p, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
363
r.out.service_status = &service_status;
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!");
371
if (!test_CloseServiceHandle(p, tctx, &s))
374
if (!test_CloseServiceHandle(p, tctx, &h))
380
static bool test_EnumServicesStatus(struct torture_context *tctx, struct dcerpc_pipe *p)
382
struct svcctl_EnumServicesStatusW r;
383
struct policy_handle h;
386
uint32_t resume_handle = 0;
387
struct ENUM_SERVICE_STATUSW *service = NULL;
389
uint32_t services_returned = 0;
391
if (!test_OpenSCManager(p, tctx, &h))
395
r.in.type = SERVICE_TYPE_WIN32;
396
r.in.state = SERVICE_STATE_ALL;
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;
404
status = dcerpc_svcctl_EnumServicesStatusW(p, tctx, &r);
406
torture_assert_ntstatus_ok(tctx, status, "EnumServicesStatus failed!");
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);
412
status = dcerpc_svcctl_EnumServicesStatusW(p, tctx, &r);
414
torture_assert_ntstatus_ok(tctx, status, "EnumServicesStatus failed!");
415
torture_assert_werr_ok(tctx, r.out.result, "EnumServicesStatus failed");
418
if (services_returned > 0) {
420
enum ndr_err_code ndr_err;
422
struct ndr_pull *ndr;
424
blob.length = r.in.offered;
425
blob.data = talloc_steal(tctx, r.out.service);
427
ndr = ndr_pull_init_blob(&blob, tctx, lp_iconv_convenience(tctx->lp_ctx));
429
service = talloc_array(tctx, struct ENUM_SERVICE_STATUSW, services_returned);
434
ndr_err = ndr_pull_ENUM_SERVICE_STATUSW_array(
435
ndr, services_returned, service);
436
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
441
for(i = 0; i < services_returned; i++) {
443
torture_assert(tctx, service[i].service_name,
444
"Service without name returned!");
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);
451
if (!test_CloseServiceHandle(p, tctx, &h))
457
static bool test_EnumDependentServicesW(struct torture_context *tctx,
458
struct dcerpc_pipe *p)
460
struct svcctl_EnumDependentServicesW r;
461
struct policy_handle h, s;
463
uint32_t services_returned;
465
uint32_t states[] = { SERVICE_STATE_ACTIVE,
466
SERVICE_STATE_INACTIVE,
469
if (!test_OpenSCManager(p, tctx, &h))
472
if (!test_OpenService(p, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
478
r.out.service_status = NULL;
479
r.out.services_returned = &services_returned;
480
r.out.needed = &needed;
482
torture_assert_ntstatus_ok(tctx,
483
dcerpc_svcctl_EnumDependentServicesW(p, tctx, &r),
484
"EnumDependentServicesW failed!");
486
torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
487
"EnumDependentServicesW failed!");
489
for (i=0; i<ARRAY_SIZE(states); i++) {
491
r.in.state = states[i];
493
torture_assert_ntstatus_ok(tctx,
494
dcerpc_svcctl_EnumDependentServicesW(p, tctx, &r),
495
"EnumDependentServicesW failed!");
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);
501
torture_assert_ntstatus_ok(tctx,
502
dcerpc_svcctl_EnumDependentServicesW(p, tctx, &r),
503
"EnumDependentServicesW failed!");
507
torture_assert_werr_ok(tctx, r.out.result,
508
"EnumDependentServicesW failed");
511
if (!test_CloseServiceHandle(p, tctx, &s))
514
if (!test_CloseServiceHandle(p, tctx, &h))
520
static bool test_SCManager(struct torture_context *tctx,
521
struct dcerpc_pipe *p)
523
struct policy_handle h;
525
if (!test_OpenSCManager(p, tctx, &h))
528
if (!test_CloseServiceHandle(p, tctx, &h))
534
struct torture_suite *torture_rpc_svcctl(TALLOC_CTX *mem_ctx)
536
struct torture_suite *suite = torture_suite_create(mem_ctx, "SVCCTL");
537
struct torture_rpc_tcase *tcase;
539
tcase = torture_suite_add_rpc_iface_tcase(suite, "svcctl", &ndr_table_svcctl);
541
torture_rpc_tcase_add_test(tcase, "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",
559
torture_rpc_tcase_add_test(tcase, "ControlService",
560
test_ControlService);