1/* 2 * Unix SMB/CIFS implementation. 3 * RPC Pipe client / server routines 4 * 5 * Copyright (C) Marcin Krzysztof Porwit 2005. 6 * 7 * Largely Rewritten (Again) by: 8 * Copyright (C) Gerald (Jerry) Carter 2005. 9 * Copyright (C) Guenther Deschner 2008,2009. 10 * 11 * This program is free software; you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License as published by 13 * the Free Software Foundation; either version 3 of the License, or 14 * (at your option) any later version. 15 * 16 * This program is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU General Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License 22 * along with this program; if not, see <http://www.gnu.org/licenses/>. 23 */ 24 25#include "includes.h" 26#include "../librpc/gen_ndr/srv_svcctl.h" 27 28#undef DBGC_CLASS 29#define DBGC_CLASS DBGC_RPC_SRV 30 31struct service_control_op { 32 const char *name; 33 SERVICE_CONTROL_OPS *ops; 34}; 35 36/* handle external services */ 37extern SERVICE_CONTROL_OPS rcinit_svc_ops; 38 39/* builtin services (see service_db.c and services/svc_*.c */ 40extern SERVICE_CONTROL_OPS spoolss_svc_ops; 41extern SERVICE_CONTROL_OPS netlogon_svc_ops; 42extern SERVICE_CONTROL_OPS winreg_svc_ops; 43extern SERVICE_CONTROL_OPS wins_svc_ops; 44 45/* make sure this number patches the number of builtin 46 SERVICE_CONTROL_OPS structure listed above */ 47 48#define SVCCTL_NUM_INTERNAL_SERVICES 4 49 50struct service_control_op *svcctl_ops; 51 52static const struct generic_mapping scm_generic_map = 53 { SC_MANAGER_READ_ACCESS, SC_MANAGER_WRITE_ACCESS, SC_MANAGER_EXECUTE_ACCESS, SC_MANAGER_ALL_ACCESS }; 54static const struct generic_mapping svc_generic_map = 55 { SERVICE_READ_ACCESS, SERVICE_WRITE_ACCESS, SERVICE_EXECUTE_ACCESS, SERVICE_ALL_ACCESS }; 56 57 58/******************************************************************** 59********************************************************************/ 60 61bool init_service_op_table( void ) 62{ 63 const char **service_list = lp_svcctl_list(); 64 int num_services = SVCCTL_NUM_INTERNAL_SERVICES + str_list_length( service_list ); 65 int i; 66 67 if ( !(svcctl_ops = TALLOC_ARRAY( NULL, struct service_control_op, num_services+1)) ) { 68 DEBUG(0,("init_service_op_table: talloc() failed!\n")); 69 return False; 70 } 71 72 /* services listed in smb.conf get the rc.init interface */ 73 74 for ( i=0; service_list && service_list[i]; i++ ) { 75 svcctl_ops[i].name = talloc_strdup( svcctl_ops, service_list[i] ); 76 svcctl_ops[i].ops = &rcinit_svc_ops; 77 } 78 79 /* add builtin services */ 80 81 svcctl_ops[i].name = talloc_strdup( svcctl_ops, "Spooler" ); 82 svcctl_ops[i].ops = &spoolss_svc_ops; 83 i++; 84 85 svcctl_ops[i].name = talloc_strdup( svcctl_ops, "NETLOGON" ); 86 svcctl_ops[i].ops = &netlogon_svc_ops; 87 i++; 88 89 svcctl_ops[i].name = talloc_strdup( svcctl_ops, "RemoteRegistry" ); 90 svcctl_ops[i].ops = &winreg_svc_ops; 91 i++; 92 93 svcctl_ops[i].name = talloc_strdup( svcctl_ops, "WINS" ); 94 svcctl_ops[i].ops = &wins_svc_ops; 95 i++; 96 97 /* NULL terminate the array */ 98 99 svcctl_ops[i].name = NULL; 100 svcctl_ops[i].ops = NULL; 101 102 return True; 103} 104 105/******************************************************************** 106********************************************************************/ 107 108static struct service_control_op* find_service_by_name( const char *name ) 109{ 110 int i; 111 112 for ( i=0; svcctl_ops[i].name; i++ ) { 113 if ( strequal( name, svcctl_ops[i].name ) ) 114 return &svcctl_ops[i]; 115 } 116 117 return NULL; 118} 119/******************************************************************** 120********************************************************************/ 121 122static NTSTATUS svcctl_access_check( SEC_DESC *sec_desc, NT_USER_TOKEN *token, 123 uint32 access_desired, uint32 *access_granted ) 124{ 125 if ( geteuid() == sec_initial_uid() ) { 126 DEBUG(5,("svcctl_access_check: using root's token\n")); 127 token = get_root_nt_token(); 128 } 129 130 return se_access_check( sec_desc, token, access_desired, access_granted); 131} 132 133/******************************************************************** 134********************************************************************/ 135 136static SEC_DESC* construct_scm_sd( TALLOC_CTX *ctx ) 137{ 138 SEC_ACE ace[2]; 139 size_t i = 0; 140 SEC_DESC *sd; 141 SEC_ACL *theacl; 142 size_t sd_size; 143 144 /* basic access for Everyone */ 145 146 init_sec_ace(&ace[i++], &global_sid_World, 147 SEC_ACE_TYPE_ACCESS_ALLOWED, SC_MANAGER_READ_ACCESS, 0); 148 149 /* Full Access 'BUILTIN\Administrators' */ 150 151 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators, 152 SEC_ACE_TYPE_ACCESS_ALLOWED, SC_MANAGER_ALL_ACCESS, 0); 153 154 155 /* create the security descriptor */ 156 157 if ( !(theacl = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) ) 158 return NULL; 159 160 if ( !(sd = make_sec_desc(ctx, SECURITY_DESCRIPTOR_REVISION_1, 161 SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, 162 theacl, &sd_size)) ) 163 return NULL; 164 165 return sd; 166} 167 168/****************************************************************** 169 Find a registry key handle and return a SERVICE_INFO 170 *****************************************************************/ 171 172static SERVICE_INFO *find_service_info_by_hnd(pipes_struct *p, struct policy_handle *hnd) 173{ 174 SERVICE_INFO *service_info = NULL; 175 176 if( !find_policy_by_hnd( p, hnd, (void **)(void *)&service_info) ) { 177 DEBUG(2,("find_service_info_by_hnd: handle not found\n")); 178 return NULL; 179 } 180 181 return service_info; 182} 183 184/****************************************************************** 185 *****************************************************************/ 186 187static WERROR create_open_service_handle( pipes_struct *p, struct policy_handle *handle, uint32 type, 188 const char *service, uint32 access_granted ) 189{ 190 SERVICE_INFO *info = NULL; 191 WERROR result = WERR_OK; 192 struct service_control_op *s_op; 193 194 if ( !(info = TALLOC_ZERO_P( NULL, SERVICE_INFO )) ) 195 return WERR_NOMEM; 196 197 /* the Service Manager has a NULL name */ 198 199 info->type = SVC_HANDLE_IS_SCM; 200 201 switch ( type ) { 202 case SVC_HANDLE_IS_SCM: 203 info->type = SVC_HANDLE_IS_SCM; 204 break; 205 206 case SVC_HANDLE_IS_DBLOCK: 207 info->type = SVC_HANDLE_IS_DBLOCK; 208 break; 209 210 case SVC_HANDLE_IS_SERVICE: 211 info->type = SVC_HANDLE_IS_SERVICE; 212 213 /* lookup the SERVICE_CONTROL_OPS */ 214 215 if ( !(s_op = find_service_by_name( service )) ) { 216 result = WERR_NO_SUCH_SERVICE; 217 goto done; 218 } 219 220 info->ops = s_op->ops; 221 222 if ( !(info->name = talloc_strdup( info, s_op->name )) ) { 223 result = WERR_NOMEM; 224 goto done; 225 } 226 break; 227 228 default: 229 result = WERR_NO_SUCH_SERVICE; 230 goto done; 231 } 232 233 info->access_granted = access_granted; 234 235 /* store the SERVICE_INFO and create an open handle */ 236 237 if ( !create_policy_hnd( p, handle, info ) ) { 238 result = WERR_ACCESS_DENIED; 239 goto done; 240 } 241 242done: 243 if ( !W_ERROR_IS_OK(result) ) 244 TALLOC_FREE(info); 245 246 return result; 247} 248 249/******************************************************************** 250 _svcctl_OpenSCManagerW 251********************************************************************/ 252 253WERROR _svcctl_OpenSCManagerW(pipes_struct *p, 254 struct svcctl_OpenSCManagerW *r) 255{ 256 SEC_DESC *sec_desc; 257 uint32 access_granted = 0; 258 NTSTATUS status; 259 260 /* perform access checks */ 261 262 if ( !(sec_desc = construct_scm_sd( p->mem_ctx )) ) 263 return WERR_NOMEM; 264 265 se_map_generic( &r->in.access_mask, &scm_generic_map ); 266 status = svcctl_access_check( sec_desc, p->server_info->ptok, 267 r->in.access_mask, &access_granted ); 268 if ( !NT_STATUS_IS_OK(status) ) 269 return ntstatus_to_werror( status ); 270 271 return create_open_service_handle( p, r->out.handle, SVC_HANDLE_IS_SCM, NULL, access_granted ); 272} 273 274/******************************************************************** 275 _svcctl_OpenServiceW 276********************************************************************/ 277 278WERROR _svcctl_OpenServiceW(pipes_struct *p, 279 struct svcctl_OpenServiceW *r) 280{ 281 SEC_DESC *sec_desc; 282 uint32 access_granted = 0; 283 NTSTATUS status; 284 const char *service = NULL; 285 286 service = r->in.ServiceName; 287 if (!service) { 288 return WERR_NOMEM; 289 } 290 DEBUG(5, ("_svcctl_OpenServiceW: Attempting to open Service [%s], \n", service)); 291 292 /* based on my tests you can open a service if you have a valid scm handle */ 293 294 if ( !find_service_info_by_hnd( p, r->in.scmanager_handle) ) 295 return WERR_BADFID; 296 297 /* perform access checks. Use the root token in order to ensure that we 298 retrieve the security descriptor */ 299 300 if ( !(sec_desc = svcctl_get_secdesc( p->mem_ctx, service, get_root_nt_token() )) ) 301 return WERR_NOMEM; 302 303 se_map_generic( &r->in.access_mask, &svc_generic_map ); 304 status = svcctl_access_check( sec_desc, p->server_info->ptok, 305 r->in.access_mask, &access_granted ); 306 if ( !NT_STATUS_IS_OK(status) ) 307 return ntstatus_to_werror( status ); 308 309 return create_open_service_handle( p, r->out.handle, SVC_HANDLE_IS_SERVICE, service, access_granted ); 310} 311 312/******************************************************************** 313 _svcctl_CloseServiceHandle 314********************************************************************/ 315 316WERROR _svcctl_CloseServiceHandle(pipes_struct *p, 317 struct svcctl_CloseServiceHandle *r) 318{ 319 if ( !close_policy_hnd( p, r->in.handle ) ) 320 return WERR_BADFID; 321 322 ZERO_STRUCTP(r->out.handle); 323 324 return WERR_OK; 325} 326 327/******************************************************************** 328 _svcctl_GetServiceDisplayNameW 329********************************************************************/ 330 331WERROR _svcctl_GetServiceDisplayNameW(pipes_struct *p, 332 struct svcctl_GetServiceDisplayNameW *r) 333{ 334 const char *service; 335 const char *display_name; 336 SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle ); 337 338 /* can only use an SCM handle here */ 339 340 if ( !info || (info->type != SVC_HANDLE_IS_SCM) ) 341 return WERR_BADFID; 342 343 service = r->in.service_name; 344 345 display_name = svcctl_lookup_dispname(p->mem_ctx, service, 346 p->server_info->ptok); 347 if (!display_name) { 348 display_name = ""; 349 } 350 351 *r->out.display_name = display_name; 352 *r->out.display_name_length = strlen(display_name); 353 354 return WERR_OK; 355} 356 357/******************************************************************** 358 _svcctl_QueryServiceStatus 359********************************************************************/ 360 361WERROR _svcctl_QueryServiceStatus(pipes_struct *p, 362 struct svcctl_QueryServiceStatus *r) 363{ 364 SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle ); 365 366 /* perform access checks */ 367 368 if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) ) 369 return WERR_BADFID; 370 371 if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_STATUS) ) 372 return WERR_ACCESS_DENIED; 373 374 /* try the service specific status call */ 375 376 return info->ops->service_status( info->name, r->out.service_status ); 377} 378 379/******************************************************************** 380********************************************************************/ 381 382static int enumerate_status( TALLOC_CTX *ctx, struct ENUM_SERVICE_STATUSW **status, NT_USER_TOKEN *token ) 383{ 384 int num_services = 0; 385 int i; 386 struct ENUM_SERVICE_STATUSW *st; 387 const char *display_name; 388 389 /* just count */ 390 while ( svcctl_ops[num_services].name ) 391 num_services++; 392 393 if ( !(st = TALLOC_ARRAY( ctx, struct ENUM_SERVICE_STATUSW, num_services )) ) { 394 DEBUG(0,("enumerate_status: talloc() failed!\n")); 395 return -1; 396 } 397 398 for ( i=0; i<num_services; i++ ) { 399 st[i].service_name = talloc_strdup(st, svcctl_ops[i].name ); 400 401 display_name = svcctl_lookup_dispname(ctx, svcctl_ops[i].name, token ); 402 st[i].display_name = talloc_strdup(st, display_name ? display_name : ""); 403 404 svcctl_ops[i].ops->service_status( svcctl_ops[i].name, &st[i].status ); 405 } 406 407 *status = st; 408 409 return num_services; 410} 411 412/******************************************************************** 413 _svcctl_EnumServicesStatusW 414********************************************************************/ 415 416WERROR _svcctl_EnumServicesStatusW(pipes_struct *p, 417 struct svcctl_EnumServicesStatusW *r) 418{ 419 struct ENUM_SERVICE_STATUSW *services = NULL; 420 int num_services; 421 int i = 0; 422 size_t buffer_size = 0; 423 WERROR result = WERR_OK; 424 SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle ); 425 NT_USER_TOKEN *token = p->server_info->ptok; 426 DATA_BLOB blob = data_blob_null; 427 428 /* perform access checks */ 429 430 if ( !info || (info->type != SVC_HANDLE_IS_SCM) ) 431 return WERR_BADFID; 432 433 if ( !(info->access_granted & SC_RIGHT_MGR_ENUMERATE_SERVICE) ) { 434 return WERR_ACCESS_DENIED; 435 } 436 437 num_services = enumerate_status( p->mem_ctx, &services, token ); 438 if (num_services == -1 ) { 439 return WERR_NOMEM; 440 } 441 442 for ( i=0; i<num_services; i++ ) { 443 buffer_size += ndr_size_ENUM_SERVICE_STATUSW(&services[i], NULL, 0); 444 } 445 446 buffer_size += buffer_size % 4; 447 448 if (buffer_size > r->in.offered) { 449 num_services = 0; 450 result = WERR_MORE_DATA; 451 } 452 453 if ( W_ERROR_IS_OK(result) ) { 454 455 enum ndr_err_code ndr_err; 456 struct ndr_push *ndr; 457 458 ndr = ndr_push_init_ctx(p->mem_ctx, NULL); 459 if (ndr == NULL) { 460 return WERR_INVALID_PARAM; 461 } 462 463 ndr_err = ndr_push_ENUM_SERVICE_STATUSW_array( 464 ndr, num_services, services); 465 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 466 return ntstatus_to_werror(ndr_map_error2ntstatus(ndr_err)); 467 } 468 blob = ndr_push_blob(ndr); 469 memcpy(r->out.service, blob.data, MIN(blob.length, r->in.offered)); 470 } 471 472 *r->out.needed = (buffer_size > r->in.offered) ? buffer_size : r->in.offered; 473 *r->out.services_returned = (uint32)num_services; 474 if (r->out.resume_handle) { 475 *r->out.resume_handle = 0; 476 } 477 478 return result; 479} 480 481/******************************************************************** 482 _svcctl_StartServiceW 483********************************************************************/ 484 485WERROR _svcctl_StartServiceW(pipes_struct *p, 486 struct svcctl_StartServiceW *r) 487{ 488 SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle ); 489 490 /* perform access checks */ 491 492 if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) ) 493 return WERR_BADFID; 494 495 if ( !(info->access_granted & SC_RIGHT_SVC_START) ) 496 return WERR_ACCESS_DENIED; 497 498 return info->ops->start_service( info->name ); 499} 500 501/******************************************************************** 502 _svcctl_ControlService 503********************************************************************/ 504 505WERROR _svcctl_ControlService(pipes_struct *p, 506 struct svcctl_ControlService *r) 507{ 508 SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle ); 509 510 /* perform access checks */ 511 512 if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) ) 513 return WERR_BADFID; 514 515 switch ( r->in.control ) { 516 case SVCCTL_CONTROL_STOP: 517 if ( !(info->access_granted & SC_RIGHT_SVC_STOP) ) 518 return WERR_ACCESS_DENIED; 519 520 return info->ops->stop_service( info->name, 521 r->out.service_status ); 522 523 case SVCCTL_CONTROL_INTERROGATE: 524 if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_STATUS) ) 525 return WERR_ACCESS_DENIED; 526 527 return info->ops->service_status( info->name, 528 r->out.service_status ); 529 default: 530 return WERR_INVALID_PARAM; 531 } 532} 533 534/******************************************************************** 535 _svcctl_EnumDependentServicesW 536********************************************************************/ 537 538WERROR _svcctl_EnumDependentServicesW(pipes_struct *p, 539 struct svcctl_EnumDependentServicesW *r) 540{ 541 SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.service ); 542 543 /* perform access checks */ 544 545 if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) ) 546 return WERR_BADFID; 547 548 if ( !(info->access_granted & SC_RIGHT_SVC_ENUMERATE_DEPENDENTS) ) 549 return WERR_ACCESS_DENIED; 550 551 switch (r->in.state) { 552 case SERVICE_STATE_ACTIVE: 553 case SERVICE_STATE_INACTIVE: 554 case SERVICE_STATE_ALL: 555 break; 556 default: 557 return WERR_INVALID_PARAM; 558 } 559 560 /* we have to set the outgoing buffer size to the same as the 561 incoming buffer size (even in the case of failure */ 562 /* this is done in the autogenerated server already - gd */ 563 564 *r->out.needed = r->in.offered; 565 566 /* no dependent services...basically a stub function */ 567 *r->out.services_returned = 0; 568 569 return WERR_OK; 570} 571 572/******************************************************************** 573 _svcctl_QueryServiceStatusEx 574********************************************************************/ 575 576WERROR _svcctl_QueryServiceStatusEx(pipes_struct *p, 577 struct svcctl_QueryServiceStatusEx *r) 578{ 579 SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle ); 580 uint32 buffer_size; 581 582 /* perform access checks */ 583 584 if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) ) 585 return WERR_BADFID; 586 587 if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_STATUS) ) 588 return WERR_ACCESS_DENIED; 589 590 /* we have to set the outgoing buffer size to the same as the 591 incoming buffer size (even in the case of failure) */ 592 *r->out.needed = r->in.offered; 593 594 switch ( r->in.info_level ) { 595 case SVC_STATUS_PROCESS_INFO: 596 { 597 struct SERVICE_STATUS_PROCESS svc_stat_proc; 598 enum ndr_err_code ndr_err; 599 DATA_BLOB blob; 600 601 /* Get the status of the service.. */ 602 info->ops->service_status( info->name, &svc_stat_proc.status ); 603 svc_stat_proc.process_id = sys_getpid(); 604 svc_stat_proc.service_flags = 0x0; 605 606 ndr_err = ndr_push_struct_blob(&blob, p->mem_ctx, NULL, 607 &svc_stat_proc, 608 (ndr_push_flags_fn_t)ndr_push_SERVICE_STATUS_PROCESS); 609 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 610 return WERR_INVALID_PARAM; 611 } 612 613 r->out.buffer = blob.data; 614 buffer_size = sizeof(struct SERVICE_STATUS_PROCESS); 615 break; 616 } 617 618 default: 619 return WERR_UNKNOWN_LEVEL; 620 } 621 622 623 buffer_size += buffer_size % 4; 624 *r->out.needed = (buffer_size > r->in.offered) ? buffer_size : r->in.offered; 625 626 if (buffer_size > r->in.offered ) { 627 return WERR_INSUFFICIENT_BUFFER; 628 } 629 630 return WERR_OK; 631} 632 633/******************************************************************** 634********************************************************************/ 635 636static WERROR fill_svc_config( TALLOC_CTX *ctx, const char *name, 637 struct QUERY_SERVICE_CONFIG *config, 638 NT_USER_TOKEN *token ) 639{ 640 struct regval_ctr *values; 641 struct regval_blob *val; 642 643 /* retrieve the registry values for this service */ 644 645 if ( !(values = svcctl_fetch_regvalues( name, token )) ) 646 return WERR_REG_CORRUPT; 647 648 /* now fill in the individual values */ 649 650 if ( (val = regval_ctr_getvalue( values, "DisplayName" )) != NULL ) 651 config->displayname = regval_sz(val); 652 else 653 config->displayname = name; 654 655 if ( (val = regval_ctr_getvalue( values, "ObjectName" )) != NULL ) { 656 config->startname = regval_sz(val); 657 } 658 659 if ( (val = regval_ctr_getvalue( values, "ImagePath" )) != NULL ) { 660 config->executablepath = regval_sz(val); 661 } 662 663 /* a few hard coded values */ 664 /* loadordergroup and dependencies are empty */ 665 666 config->tag_id = 0x00000000; /* unassigned loadorder group */ 667 config->service_type = SERVICE_TYPE_WIN32_OWN_PROCESS; 668 config->error_control = SVCCTL_SVC_ERROR_NORMAL; 669 670 /* set the start type. NetLogon and WINS are disabled to prevent 671 the client from showing the "Start" button (if of course the services 672 are not running */ 673 674 if ( strequal( name, "NETLOGON" ) && ( lp_servicenumber(name) == -1 ) ) 675 config->start_type = SVCCTL_DISABLED; 676 else if ( strequal( name, "WINS" ) && ( !lp_wins_support() )) 677 config->start_type = SVCCTL_DISABLED; 678 else 679 config->start_type = SVCCTL_DEMAND_START; 680 681 682 TALLOC_FREE( values ); 683 684 return WERR_OK; 685} 686 687/******************************************************************** 688 _svcctl_QueryServiceConfigW 689********************************************************************/ 690 691WERROR _svcctl_QueryServiceConfigW(pipes_struct *p, 692 struct svcctl_QueryServiceConfigW *r) 693{ 694 SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle ); 695 uint32 buffer_size; 696 WERROR wresult; 697 698 /* perform access checks */ 699 700 if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) ) 701 return WERR_BADFID; 702 703 if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_CONFIG) ) 704 return WERR_ACCESS_DENIED; 705 706 /* we have to set the outgoing buffer size to the same as the 707 incoming buffer size (even in the case of failure */ 708 709 *r->out.needed = r->in.offered; 710 711 wresult = fill_svc_config( p->mem_ctx, info->name, r->out.query, 712 p->server_info->ptok); 713 if ( !W_ERROR_IS_OK(wresult) ) 714 return wresult; 715 716 buffer_size = ndr_size_QUERY_SERVICE_CONFIG(r->out.query, NULL, 0); 717 *r->out.needed = (buffer_size > r->in.offered) ? buffer_size : r->in.offered; 718 719 if (buffer_size > r->in.offered ) { 720 ZERO_STRUCTP(r->out.query); 721 return WERR_INSUFFICIENT_BUFFER; 722 } 723 724 return WERR_OK; 725} 726 727/******************************************************************** 728 _svcctl_QueryServiceConfig2W 729********************************************************************/ 730 731WERROR _svcctl_QueryServiceConfig2W(pipes_struct *p, 732 struct svcctl_QueryServiceConfig2W *r) 733{ 734 SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle ); 735 uint32 buffer_size; 736 737 /* perform access checks */ 738 739 if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) ) 740 return WERR_BADFID; 741 742 if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_CONFIG) ) 743 return WERR_ACCESS_DENIED; 744 745 /* we have to set the outgoing buffer size to the same as the 746 incoming buffer size (even in the case of failure */ 747 *r->out.needed = r->in.offered; 748 749 switch ( r->in.info_level ) { 750 case SERVICE_CONFIG_DESCRIPTION: 751 { 752 struct SERVICE_DESCRIPTION desc_buf; 753 const char *description; 754 enum ndr_err_code ndr_err; 755 DATA_BLOB blob; 756 757 description = svcctl_lookup_description( 758 p->mem_ctx, info->name, p->server_info->ptok); 759 760 desc_buf.description = description; 761 762 ndr_err = ndr_push_struct_blob(&blob, p->mem_ctx, NULL, 763 &desc_buf, 764 (ndr_push_flags_fn_t)ndr_push_SERVICE_DESCRIPTION); 765 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 766 return WERR_INVALID_PARAM; 767 } 768 769 buffer_size = ndr_size_SERVICE_DESCRIPTION(&desc_buf, NULL, 0); 770 r->out.buffer = blob.data; 771 772 break; 773 } 774 break; 775 case SERVICE_CONFIG_FAILURE_ACTIONS: 776 { 777 struct SERVICE_FAILURE_ACTIONS actions; 778 enum ndr_err_code ndr_err; 779 DATA_BLOB blob; 780 781 /* nothing to say...just service the request */ 782 783 ZERO_STRUCT( actions ); 784 785 ndr_err = ndr_push_struct_blob(&blob, p->mem_ctx, NULL, 786 &actions, 787 (ndr_push_flags_fn_t)ndr_push_SERVICE_FAILURE_ACTIONS); 788 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 789 return WERR_INVALID_PARAM; 790 } 791 792 buffer_size = ndr_size_SERVICE_FAILURE_ACTIONS(&actions, NULL, 0); 793 r->out.buffer = blob.data; 794 795 break; 796 } 797 break; 798 799 default: 800 return WERR_UNKNOWN_LEVEL; 801 } 802 803 buffer_size += buffer_size % 4; 804 *r->out.needed = (buffer_size > r->in.offered) ? buffer_size : r->in.offered; 805 806 if (buffer_size > r->in.offered) 807 return WERR_INSUFFICIENT_BUFFER; 808 809 return WERR_OK; 810} 811 812/******************************************************************** 813 _svcctl_LockServiceDatabase 814********************************************************************/ 815 816WERROR _svcctl_LockServiceDatabase(pipes_struct *p, 817 struct svcctl_LockServiceDatabase *r) 818{ 819 SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle ); 820 821 /* perform access checks */ 822 823 if ( !info || (info->type != SVC_HANDLE_IS_SCM) ) 824 return WERR_BADFID; 825 826 if ( !(info->access_granted & SC_RIGHT_MGR_LOCK) ) 827 return WERR_ACCESS_DENIED; 828 829 /* Just open a handle. Doesn't actually lock anything */ 830 831 return create_open_service_handle( p, r->out.lock, SVC_HANDLE_IS_DBLOCK, NULL, 0 ); 832} 833 834/******************************************************************** 835 _svcctl_UnlockServiceDatabase 836********************************************************************/ 837 838WERROR _svcctl_UnlockServiceDatabase(pipes_struct *p, 839 struct svcctl_UnlockServiceDatabase *r) 840{ 841 SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.lock ); 842 843 844 if ( !info || (info->type != SVC_HANDLE_IS_DBLOCK) ) 845 return WERR_BADFID; 846 847 return close_policy_hnd( p, r->out.lock) ? WERR_OK : WERR_BADFID; 848} 849 850/******************************************************************** 851 _svcctl_QueryServiceObjectSecurity 852********************************************************************/ 853 854WERROR _svcctl_QueryServiceObjectSecurity(pipes_struct *p, 855 struct svcctl_QueryServiceObjectSecurity *r) 856{ 857 SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle ); 858 SEC_DESC *sec_desc; 859 NTSTATUS status; 860 uint8_t *buffer = NULL; 861 size_t len = 0; 862 863 864 /* only support the SCM and individual services */ 865 866 if ( !info || !(info->type & (SVC_HANDLE_IS_SERVICE|SVC_HANDLE_IS_SCM)) ) 867 return WERR_BADFID; 868 869 /* check access reights (according to MSDN) */ 870 871 if ( !(info->access_granted & STD_RIGHT_READ_CONTROL_ACCESS) ) 872 return WERR_ACCESS_DENIED; 873 874 /* TODO: handle something besides DACL_SECURITY_INFORMATION */ 875 876 if ( (r->in.security_flags & DACL_SECURITY_INFORMATION) != DACL_SECURITY_INFORMATION ) 877 return WERR_INVALID_PARAM; 878 879 /* lookup the security descriptor and marshall it up for a reply */ 880 881 if ( !(sec_desc = svcctl_get_secdesc( p->mem_ctx, info->name, get_root_nt_token() )) ) 882 return WERR_NOMEM; 883 884 *r->out.needed = ndr_size_security_descriptor( sec_desc, NULL, 0 ); 885 886 if ( *r->out.needed > r->in.offered) { 887 return WERR_INSUFFICIENT_BUFFER; 888 } 889 890 status = marshall_sec_desc(p->mem_ctx, sec_desc, &buffer, &len); 891 if (!NT_STATUS_IS_OK(status)) { 892 return ntstatus_to_werror(status); 893 } 894 895 *r->out.needed = len; 896 r->out.buffer = buffer; 897 898 return WERR_OK; 899} 900 901/******************************************************************** 902 _svcctl_SetServiceObjectSecurity 903********************************************************************/ 904 905WERROR _svcctl_SetServiceObjectSecurity(pipes_struct *p, 906 struct svcctl_SetServiceObjectSecurity *r) 907{ 908 SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle ); 909 SEC_DESC *sec_desc = NULL; 910 uint32 required_access; 911 NTSTATUS status; 912 913 if ( !info || !(info->type & (SVC_HANDLE_IS_SERVICE|SVC_HANDLE_IS_SCM)) ) 914 return WERR_BADFID; 915 916 /* can't set the security de4scriptor on the ServiceControlManager */ 917 918 if ( info->type == SVC_HANDLE_IS_SCM ) 919 return WERR_ACCESS_DENIED; 920 921 /* check the access on the open handle */ 922 923 switch ( r->in.security_flags ) { 924 case DACL_SECURITY_INFORMATION: 925 required_access = STD_RIGHT_WRITE_DAC_ACCESS; 926 break; 927 928 case OWNER_SECURITY_INFORMATION: 929 case GROUP_SECURITY_INFORMATION: 930 required_access = STD_RIGHT_WRITE_OWNER_ACCESS; 931 break; 932 933 case SACL_SECURITY_INFORMATION: 934 return WERR_INVALID_PARAM; 935 default: 936 return WERR_INVALID_PARAM; 937 } 938 939 if ( !(info->access_granted & required_access) ) 940 return WERR_ACCESS_DENIED; 941 942 /* read the security descfriptor */ 943 944 status = unmarshall_sec_desc(p->mem_ctx, 945 r->in.buffer, 946 r->in.offered, 947 &sec_desc); 948 if (!NT_STATUS_IS_OK(status)) { 949 return ntstatus_to_werror(status); 950 } 951 952 /* store the new SD */ 953 954 if ( !svcctl_set_secdesc( p->mem_ctx, info->name, sec_desc, 955 p->server_info->ptok) ) 956 return WERR_ACCESS_DENIED; 957 958 return WERR_OK; 959} 960 961 962WERROR _svcctl_DeleteService(pipes_struct *p, struct svcctl_DeleteService *r) 963{ 964 p->rng_fault_state = True; 965 return WERR_NOT_SUPPORTED; 966} 967 968WERROR _svcctl_SetServiceStatus(pipes_struct *p, struct svcctl_SetServiceStatus *r) 969{ 970 p->rng_fault_state = True; 971 return WERR_NOT_SUPPORTED; 972} 973 974WERROR _svcctl_NotifyBootConfigStatus(pipes_struct *p, struct svcctl_NotifyBootConfigStatus *r) 975{ 976 p->rng_fault_state = True; 977 return WERR_NOT_SUPPORTED; 978} 979 980WERROR _svcctl_SCSetServiceBitsW(pipes_struct *p, struct svcctl_SCSetServiceBitsW *r) 981{ 982 p->rng_fault_state = True; 983 return WERR_NOT_SUPPORTED; 984} 985 986WERROR _svcctl_ChangeServiceConfigW(pipes_struct *p, struct svcctl_ChangeServiceConfigW *r) 987{ 988 p->rng_fault_state = True; 989 return WERR_NOT_SUPPORTED; 990} 991 992WERROR _svcctl_CreateServiceW(pipes_struct *p, struct svcctl_CreateServiceW *r) 993{ 994 p->rng_fault_state = True; 995 return WERR_NOT_SUPPORTED; 996} 997 998WERROR _svcctl_QueryServiceLockStatusW(pipes_struct *p, struct svcctl_QueryServiceLockStatusW *r) 999{ 1000 p->rng_fault_state = True; 1001 return WERR_NOT_SUPPORTED; 1002} 1003 1004WERROR _svcctl_GetServiceKeyNameW(pipes_struct *p, struct svcctl_GetServiceKeyNameW *r) 1005{ 1006 p->rng_fault_state = True; 1007 return WERR_NOT_SUPPORTED; 1008} 1009 1010WERROR _svcctl_SCSetServiceBitsA(pipes_struct *p, struct svcctl_SCSetServiceBitsA *r) 1011{ 1012 p->rng_fault_state = True; 1013 return WERR_NOT_SUPPORTED; 1014} 1015 1016WERROR _svcctl_ChangeServiceConfigA(pipes_struct *p, struct svcctl_ChangeServiceConfigA *r) 1017{ 1018 p->rng_fault_state = True; 1019 return WERR_NOT_SUPPORTED; 1020} 1021 1022WERROR _svcctl_CreateServiceA(pipes_struct *p, struct svcctl_CreateServiceA *r) 1023{ 1024 p->rng_fault_state = True; 1025 return WERR_NOT_SUPPORTED; 1026} 1027 1028WERROR _svcctl_EnumDependentServicesA(pipes_struct *p, struct svcctl_EnumDependentServicesA *r) 1029{ 1030 p->rng_fault_state = True; 1031 return WERR_NOT_SUPPORTED; 1032} 1033 1034WERROR _svcctl_EnumServicesStatusA(pipes_struct *p, struct svcctl_EnumServicesStatusA *r) 1035{ 1036 p->rng_fault_state = True; 1037 return WERR_NOT_SUPPORTED; 1038} 1039 1040WERROR _svcctl_OpenSCManagerA(pipes_struct *p, struct svcctl_OpenSCManagerA *r) 1041{ 1042 p->rng_fault_state = True; 1043 return WERR_NOT_SUPPORTED; 1044} 1045 1046WERROR _svcctl_OpenServiceA(pipes_struct *p, struct svcctl_OpenServiceA *r) 1047{ 1048 p->rng_fault_state = True; 1049 return WERR_NOT_SUPPORTED; 1050} 1051 1052WERROR _svcctl_QueryServiceConfigA(pipes_struct *p, struct svcctl_QueryServiceConfigA *r) 1053{ 1054 p->rng_fault_state = True; 1055 return WERR_NOT_SUPPORTED; 1056} 1057 1058WERROR _svcctl_QueryServiceLockStatusA(pipes_struct *p, struct svcctl_QueryServiceLockStatusA *r) 1059{ 1060 p->rng_fault_state = True; 1061 return WERR_NOT_SUPPORTED; 1062} 1063 1064WERROR _svcctl_StartServiceA(pipes_struct *p, struct svcctl_StartServiceA *r) 1065{ 1066 p->rng_fault_state = True; 1067 return WERR_NOT_SUPPORTED; 1068} 1069 1070WERROR _svcctl_GetServiceDisplayNameA(pipes_struct *p, struct svcctl_GetServiceDisplayNameA *r) 1071{ 1072 p->rng_fault_state = True; 1073 return WERR_NOT_SUPPORTED; 1074} 1075 1076WERROR _svcctl_GetServiceKeyNameA(pipes_struct *p, struct svcctl_GetServiceKeyNameA *r) 1077{ 1078 p->rng_fault_state = True; 1079 return WERR_NOT_SUPPORTED; 1080} 1081 1082WERROR _svcctl_GetCurrentGroupeStateW(pipes_struct *p, struct svcctl_GetCurrentGroupeStateW *r) 1083{ 1084 p->rng_fault_state = True; 1085 return WERR_NOT_SUPPORTED; 1086} 1087 1088WERROR _svcctl_EnumServiceGroupW(pipes_struct *p, struct svcctl_EnumServiceGroupW *r) 1089{ 1090 p->rng_fault_state = True; 1091 return WERR_NOT_SUPPORTED; 1092} 1093 1094WERROR _svcctl_ChangeServiceConfig2A(pipes_struct *p, struct svcctl_ChangeServiceConfig2A *r) 1095{ 1096 p->rng_fault_state = True; 1097 return WERR_NOT_SUPPORTED; 1098} 1099 1100WERROR _svcctl_ChangeServiceConfig2W(pipes_struct *p, struct svcctl_ChangeServiceConfig2W *r) 1101{ 1102 p->rng_fault_state = True; 1103 return WERR_NOT_SUPPORTED; 1104} 1105 1106WERROR _svcctl_QueryServiceConfig2A(pipes_struct *p, struct svcctl_QueryServiceConfig2A *r) 1107{ 1108 p->rng_fault_state = True; 1109 return WERR_NOT_SUPPORTED; 1110} 1111 1112WERROR _EnumServicesStatusExA(pipes_struct *p, struct EnumServicesStatusExA *r) 1113{ 1114 p->rng_fault_state = True; 1115 return WERR_NOT_SUPPORTED; 1116} 1117 1118WERROR _EnumServicesStatusExW(pipes_struct *p, struct EnumServicesStatusExW *r) 1119{ 1120 p->rng_fault_state = True; 1121 return WERR_NOT_SUPPORTED; 1122} 1123 1124WERROR _svcctl_SCSendTSMessage(pipes_struct *p, struct svcctl_SCSendTSMessage *r) 1125{ 1126 p->rng_fault_state = True; 1127 return WERR_NOT_SUPPORTED; 1128} 1129 1130