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 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License as published by 12 * the Free Software Foundation; either version 2 of the License, or 13 * (at your option) any later version. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program; if not, write to the Free Software 22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 23 */ 24 25#include "includes.h" 26 27#undef DBGC_CLASS 28#define DBGC_CLASS DBGC_RPC_SRV 29 30struct service_control_op { 31 const char *name; 32 SERVICE_CONTROL_OPS *ops; 33}; 34 35#define SVCCTL_NUM_INTERNAL_SERVICES 4 36 37/* handle external services */ 38extern SERVICE_CONTROL_OPS rcinit_svc_ops; 39 40/* builtin services (see service_db.c and services/svc_*.c */ 41extern SERVICE_CONTROL_OPS spoolss_svc_ops; 42extern SERVICE_CONTROL_OPS netlogon_svc_ops; 43extern SERVICE_CONTROL_OPS winreg_svc_ops; 44extern SERVICE_CONTROL_OPS wins_svc_ops; 45 46/* make sure this number patches the number of builtin 47 SERVICE_CONTROL_OPS structure listed above */ 48 49#define SVCCTL_NUM_INTERNAL_SERVICES 4 50 51struct service_control_op *svcctl_ops; 52 53static struct generic_mapping scm_generic_map = 54 { SC_MANAGER_READ_ACCESS, SC_MANAGER_WRITE_ACCESS, SC_MANAGER_EXECUTE_ACCESS, SC_MANAGER_ALL_ACCESS }; 55static struct generic_mapping svc_generic_map = 56 { SERVICE_READ_ACCESS, SERVICE_WRITE_ACCESS, SERVICE_EXECUTE_ACCESS, SERVICE_ALL_ACCESS }; 57 58 59/******************************************************************** 60********************************************************************/ 61 62BOOL init_service_op_table( void ) 63{ 64 const char **service_list = lp_svcctl_list(); 65 int num_services = SVCCTL_NUM_INTERNAL_SERVICES + str_list_count( service_list ); 66 int i; 67 68 if ( !(svcctl_ops = TALLOC_ARRAY( NULL, struct service_control_op, num_services+1)) ) { 69 DEBUG(0,("init_service_op_table: talloc() failed!\n")); 70 return False; 71 } 72 73 /* services listed in smb.conf get the rc.init interface */ 74 75 for ( i=0; service_list && service_list[i]; i++ ) { 76 svcctl_ops[i].name = talloc_strdup( svcctl_ops, service_list[i] ); 77 svcctl_ops[i].ops = &rcinit_svc_ops; 78 } 79 80 /* add builtin services */ 81 82 svcctl_ops[i].name = talloc_strdup( svcctl_ops, "Spooler" ); 83 svcctl_ops[i].ops = &spoolss_svc_ops; 84 i++; 85 86 svcctl_ops[i].name = talloc_strdup( svcctl_ops, "NETLOGON" ); 87 svcctl_ops[i].ops = &netlogon_svc_ops; 88 i++; 89 90 svcctl_ops[i].name = talloc_strdup( svcctl_ops, "RemoteRegistry" ); 91 svcctl_ops[i].ops = &winreg_svc_ops; 92 i++; 93 94 svcctl_ops[i].name = talloc_strdup( svcctl_ops, "WINS" ); 95 svcctl_ops[i].ops = &wins_svc_ops; 96 i++; 97 98 /* NULL terminate the array */ 99 100 svcctl_ops[i].name = NULL; 101 svcctl_ops[i].ops = NULL; 102 103 return True; 104} 105 106/******************************************************************** 107********************************************************************/ 108 109static struct service_control_op* find_service_by_name( const char *name ) 110{ 111 int i; 112 113 for ( i=0; svcctl_ops[i].name; i++ ) { 114 if ( strequal( name, svcctl_ops[i].name ) ) 115 return &svcctl_ops[i]; 116 } 117 118 return NULL; 119} 120/******************************************************************** 121********************************************************************/ 122 123static NTSTATUS svcctl_access_check( SEC_DESC *sec_desc, NT_USER_TOKEN *token, 124 uint32 access_desired, uint32 *access_granted ) 125{ 126 NTSTATUS result; 127 128 if ( geteuid() == sec_initial_uid() ) { 129 DEBUG(5,("svcctl_access_check: using root's token\n")); 130 token = get_root_nt_token(); 131 } 132 133 se_access_check( sec_desc, token, access_desired, access_granted, &result ); 134 135 return result; 136} 137 138/******************************************************************** 139********************************************************************/ 140 141static SEC_DESC* construct_scm_sd( TALLOC_CTX *ctx ) 142{ 143 SEC_ACE ace[2]; 144 SEC_ACCESS mask; 145 size_t i = 0; 146 SEC_DESC *sd; 147 SEC_ACL *acl; 148 size_t sd_size; 149 150 /* basic access for Everyone */ 151 152 init_sec_access(&mask, SC_MANAGER_READ_ACCESS ); 153 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); 154 155 /* Full Access 'BUILTIN\Administrators' */ 156 157 init_sec_access(&mask,SC_MANAGER_ALL_ACCESS ); 158 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); 159 160 161 /* create the security descriptor */ 162 163 if ( !(acl = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) ) 164 return NULL; 165 166 if ( !(sd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, acl, &sd_size)) ) 167 return NULL; 168 169 return sd; 170} 171 172/****************************************************************** 173 free() function for REGISTRY_KEY 174 *****************************************************************/ 175 176static void free_service_handle_info(void *ptr) 177{ 178 TALLOC_FREE( ptr ); 179} 180 181/****************************************************************** 182 Find a registry key handle and return a SERVICE_INFO 183 *****************************************************************/ 184 185static SERVICE_INFO *find_service_info_by_hnd(pipes_struct *p, POLICY_HND *hnd) 186{ 187 SERVICE_INFO *service_info = NULL; 188 189 if( !find_policy_by_hnd( p, hnd, (void **)(void *)&service_info) ) { 190 DEBUG(2,("find_service_info_by_hnd: handle not found")); 191 return NULL; 192 } 193 194 return service_info; 195} 196 197/****************************************************************** 198 *****************************************************************/ 199 200static WERROR create_open_service_handle( pipes_struct *p, POLICY_HND *handle, uint32 type, 201 const char *service, uint32 access_granted ) 202{ 203 SERVICE_INFO *info = NULL; 204 WERROR result = WERR_OK; 205 struct service_control_op *s_op; 206 207 if ( !(info = TALLOC_ZERO_P( NULL, SERVICE_INFO )) ) 208 return WERR_NOMEM; 209 210 /* the Service Manager has a NULL name */ 211 212 info->type = SVC_HANDLE_IS_SCM; 213 214 switch ( type ) { 215 case SVC_HANDLE_IS_SCM: 216 info->type = SVC_HANDLE_IS_SCM; 217 break; 218 219 case SVC_HANDLE_IS_DBLOCK: 220 info->type = SVC_HANDLE_IS_DBLOCK; 221 break; 222 223 case SVC_HANDLE_IS_SERVICE: 224 info->type = SVC_HANDLE_IS_SERVICE; 225 226 /* lookup the SERVICE_CONTROL_OPS */ 227 228 if ( !(s_op = find_service_by_name( service )) ) { 229 result = WERR_NO_SUCH_SERVICE; 230 goto done; 231 } 232 233 info->ops = s_op->ops; 234 235 if ( !(info->name = talloc_strdup( info, s_op->name )) ) { 236 result = WERR_NOMEM; 237 goto done; 238 } 239 break; 240 241 default: 242 result = WERR_NO_SUCH_SERVICE; 243 goto done; 244 } 245 246 info->access_granted = access_granted; 247 248 /* store the SERVICE_INFO and create an open handle */ 249 250 if ( !create_policy_hnd( p, handle, free_service_handle_info, info ) ) { 251 result = WERR_ACCESS_DENIED; 252 goto done; 253 } 254 255done: 256 if ( !W_ERROR_IS_OK(result) ) 257 free_service_handle_info( info ); 258 259 return result; 260} 261 262/******************************************************************** 263********************************************************************/ 264 265WERROR _svcctl_open_scmanager(pipes_struct *p, SVCCTL_Q_OPEN_SCMANAGER *q_u, SVCCTL_R_OPEN_SCMANAGER *r_u) 266{ 267 SEC_DESC *sec_desc; 268 uint32 access_granted = 0; 269 NTSTATUS status; 270 271 /* perform access checks */ 272 273 if ( !(sec_desc = construct_scm_sd( p->mem_ctx )) ) 274 return WERR_NOMEM; 275 276 se_map_generic( &q_u->access, &scm_generic_map ); 277 status = svcctl_access_check( sec_desc, p->pipe_user.nt_user_token, q_u->access, &access_granted ); 278 if ( !NT_STATUS_IS_OK(status) ) 279 return ntstatus_to_werror( status ); 280 281 return create_open_service_handle( p, &r_u->handle, SVC_HANDLE_IS_SCM, NULL, access_granted ); 282} 283 284/******************************************************************** 285********************************************************************/ 286 287WERROR _svcctl_open_service(pipes_struct *p, SVCCTL_Q_OPEN_SERVICE *q_u, SVCCTL_R_OPEN_SERVICE *r_u) 288{ 289 SEC_DESC *sec_desc; 290 uint32 access_granted = 0; 291 NTSTATUS status; 292 pstring service; 293 294 rpcstr_pull(service, q_u->servicename.buffer, sizeof(service), q_u->servicename.uni_str_len*2, 0); 295 296 DEBUG(5, ("_svcctl_open_service: Attempting to open Service [%s], \n", service)); 297 298 299 /* based on my tests you can open a service if you have a valid scm handle */ 300 301 if ( !find_service_info_by_hnd( p, &q_u->handle ) ) 302 return WERR_BADFID; 303 304 /* perform access checks. Use the root token in order to ensure that we 305 retrieve the security descriptor */ 306 307 if ( !(sec_desc = svcctl_get_secdesc( p->mem_ctx, service, get_root_nt_token() )) ) 308 return WERR_NOMEM; 309 310 se_map_generic( &q_u->access, &svc_generic_map ); 311 status = svcctl_access_check( sec_desc, p->pipe_user.nt_user_token, q_u->access, &access_granted ); 312 if ( !NT_STATUS_IS_OK(status) ) 313 return ntstatus_to_werror( status ); 314 315 return create_open_service_handle( p, &r_u->handle, SVC_HANDLE_IS_SERVICE, service, access_granted ); 316} 317 318/******************************************************************** 319********************************************************************/ 320 321WERROR _svcctl_close_service(pipes_struct *p, SVCCTL_Q_CLOSE_SERVICE *q_u, SVCCTL_R_CLOSE_SERVICE *r_u) 322{ 323 return close_policy_hnd( p, &q_u->handle ) ? WERR_OK : WERR_BADFID; 324} 325 326/******************************************************************** 327********************************************************************/ 328 329WERROR _svcctl_get_display_name(pipes_struct *p, SVCCTL_Q_GET_DISPLAY_NAME *q_u, SVCCTL_R_GET_DISPLAY_NAME *r_u) 330{ 331 fstring service; 332 const char *display_name; 333 SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle ); 334 335 /* can only use an SCM handle here */ 336 337 if ( !info || (info->type != SVC_HANDLE_IS_SCM) ) 338 return WERR_BADFID; 339 340 rpcstr_pull(service, q_u->servicename.buffer, sizeof(service), q_u->servicename.uni_str_len*2, 0); 341 342 display_name = svcctl_lookup_dispname( service, p->pipe_user.nt_user_token ); 343 init_svcctl_r_get_display_name( r_u, display_name ); 344 345 return WERR_OK; 346} 347 348/******************************************************************** 349********************************************************************/ 350 351WERROR _svcctl_query_status(pipes_struct *p, SVCCTL_Q_QUERY_STATUS *q_u, SVCCTL_R_QUERY_STATUS *r_u) 352{ 353 SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle ); 354 355 /* perform access checks */ 356 357 if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) ) 358 return WERR_BADFID; 359 360 if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_STATUS) ) 361 return WERR_ACCESS_DENIED; 362 363 /* try the service specific status call */ 364 365 return info->ops->service_status( info->name, &r_u->svc_status ); 366} 367 368/******************************************************************** 369********************************************************************/ 370 371static int enumerate_status( TALLOC_CTX *ctx, ENUM_SERVICES_STATUS **status, NT_USER_TOKEN *token ) 372{ 373 int num_services = 0; 374 int i; 375 ENUM_SERVICES_STATUS *st; 376 const char *display_name; 377 378 /* just count */ 379 while ( svcctl_ops[num_services].name ) 380 num_services++; 381 382 if ( !(st = TALLOC_ARRAY( ctx, ENUM_SERVICES_STATUS, num_services )) ) { 383 DEBUG(0,("enumerate_status: talloc() failed!\n")); 384 return -1; 385 } 386 387 for ( i=0; i<num_services; i++ ) { 388 init_unistr( &st[i].servicename, svcctl_ops[i].name ); 389 390 display_name = svcctl_lookup_dispname( svcctl_ops[i].name, token ); 391 init_unistr( &st[i].displayname, display_name ); 392 393 svcctl_ops[i].ops->service_status( svcctl_ops[i].name, &st[i].status ); 394 } 395 396 *status = st; 397 398 return num_services; 399} 400 401/******************************************************************** 402********************************************************************/ 403 404WERROR _svcctl_enum_services_status(pipes_struct *p, SVCCTL_Q_ENUM_SERVICES_STATUS *q_u, SVCCTL_R_ENUM_SERVICES_STATUS *r_u) 405{ 406 ENUM_SERVICES_STATUS *services = NULL; 407 int num_services; 408 int i = 0; 409 size_t buffer_size = 0; 410 WERROR result = WERR_OK; 411 SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle ); 412 NT_USER_TOKEN *token = p->pipe_user.nt_user_token; 413 414 /* perform access checks */ 415 416 if ( !info || (info->type != SVC_HANDLE_IS_SCM) ) 417 return WERR_BADFID; 418 419 if ( !(info->access_granted & SC_RIGHT_MGR_ENUMERATE_SERVICE) ) { 420 return WERR_ACCESS_DENIED; 421 } 422 423 num_services = enumerate_status( p->mem_ctx, &services, token ); 424 if (num_services == -1 ) { 425 return WERR_NOMEM; 426 } 427 428 for ( i=0; i<num_services; i++ ) { 429 buffer_size += svcctl_sizeof_enum_services_status(&services[i]); 430 } 431 432 buffer_size += buffer_size % 4; 433 434 if (buffer_size > q_u->buffer_size ) { 435 num_services = 0; 436 result = WERR_MORE_DATA; 437 } 438 439 rpcbuf_init(&r_u->buffer, q_u->buffer_size, p->mem_ctx); 440 441 if ( W_ERROR_IS_OK(result) ) { 442 for ( i=0; i<num_services; i++ ) 443 svcctl_io_enum_services_status( "", &services[i], &r_u->buffer, 0 ); 444 } 445 446 r_u->needed = (buffer_size > q_u->buffer_size) ? buffer_size : q_u->buffer_size; 447 r_u->returned = (uint32)num_services; 448 449 if ( !(r_u->resume = TALLOC_P( p->mem_ctx, uint32 )) ) 450 return WERR_NOMEM; 451 452 *r_u->resume = 0x0; 453 454 return result; 455} 456 457/******************************************************************** 458********************************************************************/ 459 460WERROR _svcctl_start_service(pipes_struct *p, SVCCTL_Q_START_SERVICE *q_u, SVCCTL_R_START_SERVICE *r_u) 461{ 462 SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle ); 463 464 /* perform access checks */ 465 466 if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) ) 467 return WERR_BADFID; 468 469 if ( !(info->access_granted & SC_RIGHT_SVC_START) ) 470 return WERR_ACCESS_DENIED; 471 472 return info->ops->start_service( info->name ); 473} 474 475/******************************************************************** 476********************************************************************/ 477 478WERROR _svcctl_control_service(pipes_struct *p, SVCCTL_Q_CONTROL_SERVICE *q_u, SVCCTL_R_CONTROL_SERVICE *r_u) 479{ 480 SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle ); 481 482 /* perform access checks */ 483 484 if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) ) 485 return WERR_BADFID; 486 487 switch ( q_u->control ) { 488 case SVCCTL_CONTROL_STOP: 489 if ( !(info->access_granted & SC_RIGHT_SVC_STOP) ) 490 return WERR_ACCESS_DENIED; 491 492 return info->ops->stop_service( info->name, &r_u->svc_status ); 493 494 case SVCCTL_CONTROL_INTERROGATE: 495 if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_STATUS) ) 496 return WERR_ACCESS_DENIED; 497 498 return info->ops->service_status( info->name, &r_u->svc_status ); 499 } 500 501 /* default control action */ 502 503 return WERR_ACCESS_DENIED; 504} 505 506/******************************************************************** 507********************************************************************/ 508 509WERROR _svcctl_enum_dependent_services( pipes_struct *p, SVCCTL_Q_ENUM_DEPENDENT_SERVICES *q_u, SVCCTL_R_ENUM_DEPENDENT_SERVICES *r_u ) 510{ 511 SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle ); 512 513 /* perform access checks */ 514 515 if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) ) 516 return WERR_BADFID; 517 518 if ( !(info->access_granted & SC_RIGHT_SVC_ENUMERATE_DEPENDENTS) ) 519 return WERR_ACCESS_DENIED; 520 521 /* we have to set the outgoing buffer size to the same as the 522 incoming buffer size (even in the case of failure */ 523 524 rpcbuf_init( &r_u->buffer, q_u->buffer_size, p->mem_ctx ); 525 526 r_u->needed = q_u->buffer_size; 527 528 /* no dependent services...basically a stub function */ 529 r_u->returned = 0; 530 531 return WERR_OK; 532} 533 534/******************************************************************** 535********************************************************************/ 536 537WERROR _svcctl_query_service_status_ex( pipes_struct *p, SVCCTL_Q_QUERY_SERVICE_STATUSEX *q_u, SVCCTL_R_QUERY_SERVICE_STATUSEX *r_u ) 538{ 539 SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle ); 540 uint32 buffer_size; 541 542 /* perform access checks */ 543 544 if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) ) 545 return WERR_BADFID; 546 547 if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_STATUS) ) 548 return WERR_ACCESS_DENIED; 549 550 /* we have to set the outgoing buffer size to the same as the 551 incoming buffer size (even in the case of failure) */ 552 553 rpcbuf_init( &r_u->buffer, q_u->buffer_size, p->mem_ctx ); 554 r_u->needed = q_u->buffer_size; 555 556 switch ( q_u->level ) { 557 case SVC_STATUS_PROCESS_INFO: 558 { 559 SERVICE_STATUS_PROCESS svc_stat_proc; 560 561 /* Get the status of the service.. */ 562 info->ops->service_status( info->name, &svc_stat_proc.status ); 563 svc_stat_proc.process_id = sys_getpid(); 564 svc_stat_proc.service_flags = 0x0; 565 566 svcctl_io_service_status_process( "", &svc_stat_proc, &r_u->buffer, 0 ); 567 buffer_size = sizeof(SERVICE_STATUS_PROCESS); 568 break; 569 } 570 571 default: 572 return WERR_UNKNOWN_LEVEL; 573 } 574 575 576 buffer_size += buffer_size % 4; 577 r_u->needed = (buffer_size > q_u->buffer_size) ? buffer_size : q_u->buffer_size; 578 579 if (buffer_size > q_u->buffer_size ) 580 return WERR_MORE_DATA; 581 582 return WERR_OK; 583} 584 585/******************************************************************** 586********************************************************************/ 587 588static WERROR fill_svc_config( TALLOC_CTX *ctx, const char *name, SERVICE_CONFIG *config, NT_USER_TOKEN *token ) 589{ 590 REGVAL_CTR *values; 591 REGISTRY_VALUE *val; 592 593 /* retrieve the registry values for this service */ 594 595 if ( !(values = svcctl_fetch_regvalues( name, token )) ) 596 return WERR_REG_CORRUPT; 597 598 /* now fill in the individual values */ 599 600 config->displayname = TALLOC_ZERO_P( ctx, UNISTR2 ); 601 if ( (val = regval_ctr_getvalue( values, "DisplayName" )) != NULL ) 602 init_unistr2( config->displayname, regval_sz( val ), UNI_STR_TERMINATE ); 603 else 604 init_unistr2( config->displayname, name, UNI_STR_TERMINATE ); 605 606 if ( (val = regval_ctr_getvalue( values, "ObjectName" )) != NULL ) { 607 config->startname = TALLOC_ZERO_P( ctx, UNISTR2 ); 608 init_unistr2( config->startname, regval_sz( val ), UNI_STR_TERMINATE ); 609 } 610 611 if ( (val = regval_ctr_getvalue( values, "ImagePath" )) != NULL ) { 612 config->executablepath = TALLOC_ZERO_P( ctx, UNISTR2 ); 613 init_unistr2( config->executablepath, regval_sz( val ), UNI_STR_TERMINATE ); 614 } 615 616 /* a few hard coded values */ 617 /* loadordergroup and dependencies are empty */ 618 619 config->tag_id = 0x00000000; /* unassigned loadorder group */ 620 config->service_type = SVCCTL_WIN32_OWN_PROC; 621 config->error_control = SVCCTL_SVC_ERROR_NORMAL; 622 623 /* set the start type. NetLogon and WINS are disabled to prevent 624 the client from showing the "Start" button (if of course the services 625 are not running */ 626 627 if ( strequal( name, "NETLOGON" ) && ( lp_servicenumber(name) == -1 ) ) 628 config->start_type = SVCCTL_DISABLED; 629 else if ( strequal( name, "WINS" ) && ( !lp_wins_support() )) 630 config->start_type = SVCCTL_DISABLED; 631 else 632 config->start_type = SVCCTL_DEMAND_START; 633 634 635 TALLOC_FREE( values ); 636 637 return WERR_OK; 638} 639 640/******************************************************************** 641********************************************************************/ 642 643WERROR _svcctl_query_service_config( pipes_struct *p, SVCCTL_Q_QUERY_SERVICE_CONFIG *q_u, SVCCTL_R_QUERY_SERVICE_CONFIG *r_u ) 644{ 645 SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle ); 646 uint32 buffer_size; 647 WERROR wresult; 648 649 /* perform access checks */ 650 651 if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) ) 652 return WERR_BADFID; 653 654 if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_CONFIG) ) 655 return WERR_ACCESS_DENIED; 656 657 /* we have to set the outgoing buffer size to the same as the 658 incoming buffer size (even in the case of failure */ 659 660 r_u->needed = q_u->buffer_size; 661 662 wresult = fill_svc_config( p->mem_ctx, info->name, &r_u->config, p->pipe_user.nt_user_token ); 663 if ( !W_ERROR_IS_OK(wresult) ) 664 return wresult; 665 666 buffer_size = svcctl_sizeof_service_config( &r_u->config ); 667 r_u->needed = (buffer_size > q_u->buffer_size) ? buffer_size : q_u->buffer_size; 668 669 if (buffer_size > q_u->buffer_size ) { 670 ZERO_STRUCTP( &r_u->config ); 671 return WERR_INSUFFICIENT_BUFFER; 672 } 673 674 return WERR_OK; 675} 676 677/******************************************************************** 678********************************************************************/ 679 680WERROR _svcctl_query_service_config2( pipes_struct *p, SVCCTL_Q_QUERY_SERVICE_CONFIG2 *q_u, SVCCTL_R_QUERY_SERVICE_CONFIG2 *r_u ) 681{ 682 SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle ); 683 uint32 buffer_size; 684 685 /* perform access checks */ 686 687 if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) ) 688 return WERR_BADFID; 689 690 if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_CONFIG) ) 691 return WERR_ACCESS_DENIED; 692 693 /* we have to set the outgoing buffer size to the same as the 694 incoming buffer size (even in the case of failure */ 695 696 rpcbuf_init( &r_u->buffer, q_u->buffer_size, p->mem_ctx ); 697 r_u->needed = q_u->buffer_size; 698 699 switch ( q_u->level ) { 700 case SERVICE_CONFIG_DESCRIPTION: 701 { 702 SERVICE_DESCRIPTION desc_buf; 703 const char *description; 704 705 description = svcctl_lookup_description( info->name, p->pipe_user.nt_user_token ); 706 707 ZERO_STRUCTP( &desc_buf ); 708 709 init_service_description_buffer( &desc_buf, description ); 710 svcctl_io_service_description( "", &desc_buf, &r_u->buffer, 0 ); 711 buffer_size = svcctl_sizeof_service_description( &desc_buf ); 712 713 break; 714 } 715 break; 716 case SERVICE_CONFIG_FAILURE_ACTIONS: 717 { 718 SERVICE_FAILURE_ACTIONS actions; 719 720 /* nothing to say...just service the request */ 721 722 ZERO_STRUCTP( &actions ); 723 svcctl_io_service_fa( "", &actions, &r_u->buffer, 0 ); 724 buffer_size = svcctl_sizeof_service_fa( &actions ); 725 726 break; 727 } 728 break; 729 730 default: 731 return WERR_UNKNOWN_LEVEL; 732 } 733 734 buffer_size += buffer_size % 4; 735 r_u->needed = (buffer_size > q_u->buffer_size) ? buffer_size : q_u->buffer_size; 736 737 if (buffer_size > q_u->buffer_size ) 738 return WERR_INSUFFICIENT_BUFFER; 739 740 return WERR_OK; 741} 742 743/******************************************************************** 744********************************************************************/ 745 746WERROR _svcctl_lock_service_db( pipes_struct *p, SVCCTL_Q_LOCK_SERVICE_DB *q_u, SVCCTL_R_LOCK_SERVICE_DB *r_u ) 747{ 748 SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle ); 749 750 /* perform access checks */ 751 752 if ( !info || (info->type != SVC_HANDLE_IS_SCM) ) 753 return WERR_BADFID; 754 755 if ( !(info->access_granted & SC_RIGHT_MGR_LOCK) ) 756 return WERR_ACCESS_DENIED; 757 758 /* Just open a handle. Doesn't actually lock anything */ 759 760 return create_open_service_handle( p, &r_u->h_lock, SVC_HANDLE_IS_DBLOCK, NULL, 0 ); 761; 762} 763 764/******************************************************************** 765********************************************************************/ 766 767WERROR _svcctl_unlock_service_db( pipes_struct *p, SVCCTL_Q_UNLOCK_SERVICE_DB *q_u, SVCCTL_R_UNLOCK_SERVICE_DB *r_u ) 768{ 769 SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->h_lock ); 770 771 772 if ( !info || (info->type != SVC_HANDLE_IS_DBLOCK) ) 773 return WERR_BADFID; 774 775 return close_policy_hnd( p, &q_u->h_lock) ? WERR_OK : WERR_BADFID; 776} 777 778/******************************************************************** 779********************************************************************/ 780 781WERROR _svcctl_query_service_sec( pipes_struct *p, SVCCTL_Q_QUERY_SERVICE_SEC *q_u, SVCCTL_R_QUERY_SERVICE_SEC *r_u ) 782{ 783 SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle ); 784 SEC_DESC *sec_desc; 785 786 787 /* only support the SCM and individual services */ 788 789 if ( !info || !(info->type & (SVC_HANDLE_IS_SERVICE|SVC_HANDLE_IS_SCM)) ) 790 return WERR_BADFID; 791 792 /* check access reights (according to MSDN) */ 793 794 if ( !(info->access_granted & STD_RIGHT_READ_CONTROL_ACCESS) ) 795 return WERR_ACCESS_DENIED; 796 797 /* TODO: handle something besides DACL_SECURITY_INFORMATION */ 798 799 if ( (q_u->security_flags & DACL_SECURITY_INFORMATION) != DACL_SECURITY_INFORMATION ) 800 return WERR_INVALID_PARAM; 801 802 /* lookup the security descriptor and marshall it up for a reply */ 803 804 if ( !(sec_desc = svcctl_get_secdesc( p->mem_ctx, info->name, get_root_nt_token() )) ) 805 return WERR_NOMEM; 806 807 r_u->needed = sec_desc_size( sec_desc ); 808 809 if ( r_u->needed > q_u->buffer_size ) { 810 ZERO_STRUCTP( &r_u->buffer ); 811 return WERR_INSUFFICIENT_BUFFER; 812 } 813 814 rpcbuf_init( &r_u->buffer, q_u->buffer_size, p->mem_ctx ); 815 816 if ( !sec_io_desc("", &sec_desc, &r_u->buffer.prs, 0 ) ) 817 return WERR_NOMEM; 818 819 return WERR_OK; 820} 821 822/******************************************************************** 823********************************************************************/ 824 825WERROR _svcctl_set_service_sec( pipes_struct *p, SVCCTL_Q_SET_SERVICE_SEC *q_u, SVCCTL_R_SET_SERVICE_SEC *r_u ) 826{ 827 SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle ); 828 SEC_DESC *sec_desc = NULL; 829 uint32 required_access; 830 831 if ( !info || !(info->type & (SVC_HANDLE_IS_SERVICE|SVC_HANDLE_IS_SCM)) ) 832 return WERR_BADFID; 833 834 /* can't set the security de4scriptor on the ServiceControlManager */ 835 836 if ( info->type == SVC_HANDLE_IS_SCM ) 837 return WERR_ACCESS_DENIED; 838 839 /* check the access on the open handle */ 840 841 switch ( q_u->security_flags ) { 842 case DACL_SECURITY_INFORMATION: 843 required_access = STD_RIGHT_WRITE_DAC_ACCESS; 844 break; 845 846 case OWNER_SECURITY_INFORMATION: 847 case GROUP_SECURITY_INFORMATION: 848 required_access = STD_RIGHT_WRITE_OWNER_ACCESS; 849 break; 850 851 case SACL_SECURITY_INFORMATION: 852 return WERR_INVALID_PARAM; 853 default: 854 return WERR_INVALID_PARAM; 855 } 856 857 if ( !(info->access_granted & required_access) ) 858 return WERR_ACCESS_DENIED; 859 860 /* read the security descfriptor */ 861 862 if ( !sec_io_desc("", &sec_desc, &q_u->buffer.prs, 0 ) ) 863 return WERR_NOMEM; 864 865 /* store the new SD */ 866 867 if ( !svcctl_set_secdesc( p->mem_ctx, info->name, sec_desc, p->pipe_user.nt_user_token ) ) 868 return WERR_ACCESS_DENIED; 869 870 return WERR_OK; 871} 872 873 874