root/source4/torture/rpc/svcctl.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. test_OpenSCManager
  2. test_CloseServiceHandle
  3. test_OpenService
  4. test_QueryServiceStatus
  5. test_QueryServiceStatusEx
  6. test_QueryServiceConfigW
  7. test_QueryServiceConfig2W
  8. test_QueryServiceObjectSecurity
  9. test_StartServiceW
  10. test_ControlService
  11. test_EnumServicesStatus
  12. test_EnumDependentServicesW
  13. test_SCManager
  14. torture_rpc_svcctl

   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)
     /* [<][>][^][v][top][bottom][index][help] */
  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)
     /* [<][>][^][v][top][bottom][index][help] */
  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,
     /* [<][>][^][v][top][bottom][index][help] */
  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,
     /* [<][>][^][v][top][bottom][index][help] */
  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)
     /* [<][>][^][v][top][bottom][index][help] */
 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,
     /* [<][>][^][v][top][bottom][index][help] */
 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)
     /* [<][>][^][v][top][bottom][index][help] */
 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,
     /* [<][>][^][v][top][bottom][index][help] */
 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,
     /* [<][>][^][v][top][bottom][index][help] */
 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,
     /* [<][>][^][v][top][bottom][index][help] */
 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)
     /* [<][>][^][v][top][bottom][index][help] */
 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,
     /* [<][>][^][v][top][bottom][index][help] */
 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,
     /* [<][>][^][v][top][bottom][index][help] */
 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)
     /* [<][>][^][v][top][bottom][index][help] */
 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 }

/* [<][>][^][v][top][bottom][index][help] */