00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "includes.h"
00026
00027 #undef DBGC_CLASS
00028 #define DBGC_CLASS DBGC_RPC_SRV
00029
00030 struct service_control_op {
00031 const char *name;
00032 SERVICE_CONTROL_OPS *ops;
00033 };
00034
00035 #define SVCCTL_NUM_INTERNAL_SERVICES 4
00036
00037
00038 extern SERVICE_CONTROL_OPS rcinit_svc_ops;
00039
00040
00041 extern SERVICE_CONTROL_OPS spoolss_svc_ops;
00042 extern SERVICE_CONTROL_OPS netlogon_svc_ops;
00043 extern SERVICE_CONTROL_OPS winreg_svc_ops;
00044 extern SERVICE_CONTROL_OPS wins_svc_ops;
00045
00046
00047
00048
00049 #define SVCCTL_NUM_INTERNAL_SERVICES 4
00050
00051 struct service_control_op *svcctl_ops;
00052
00053 static struct generic_mapping scm_generic_map =
00054 { SC_MANAGER_READ_ACCESS, SC_MANAGER_WRITE_ACCESS, SC_MANAGER_EXECUTE_ACCESS, SC_MANAGER_ALL_ACCESS };
00055 static struct generic_mapping svc_generic_map =
00056 { SERVICE_READ_ACCESS, SERVICE_WRITE_ACCESS, SERVICE_EXECUTE_ACCESS, SERVICE_ALL_ACCESS };
00057
00058
00059
00060
00061
00062 BOOL init_service_op_table( void )
00063 {
00064 const char **service_list = lp_svcctl_list();
00065 int num_services = SVCCTL_NUM_INTERNAL_SERVICES + str_list_count( service_list );
00066 int i;
00067
00068 if ( !(svcctl_ops = TALLOC_ARRAY( NULL, struct service_control_op, num_services+1)) ) {
00069 DEBUG(0,("init_service_op_table: talloc() failed!\n"));
00070 return False;
00071 }
00072
00073
00074
00075 for ( i=0; service_list && service_list[i]; i++ ) {
00076 svcctl_ops[i].name = talloc_strdup( svcctl_ops, service_list[i] );
00077 svcctl_ops[i].ops = &rcinit_svc_ops;
00078 }
00079
00080
00081
00082 svcctl_ops[i].name = talloc_strdup( svcctl_ops, "Spooler" );
00083 svcctl_ops[i].ops = &spoolss_svc_ops;
00084 i++;
00085
00086 svcctl_ops[i].name = talloc_strdup( svcctl_ops, "NETLOGON" );
00087 svcctl_ops[i].ops = &netlogon_svc_ops;
00088 i++;
00089
00090 svcctl_ops[i].name = talloc_strdup( svcctl_ops, "RemoteRegistry" );
00091 svcctl_ops[i].ops = &winreg_svc_ops;
00092 i++;
00093
00094 svcctl_ops[i].name = talloc_strdup( svcctl_ops, "WINS" );
00095 svcctl_ops[i].ops = &wins_svc_ops;
00096 i++;
00097
00098
00099
00100 svcctl_ops[i].name = NULL;
00101 svcctl_ops[i].ops = NULL;
00102
00103 return True;
00104 }
00105
00106
00107
00108
00109 static struct service_control_op* find_service_by_name( const char *name )
00110 {
00111 int i;
00112
00113 for ( i=0; svcctl_ops[i].name; i++ ) {
00114 if ( strequal( name, svcctl_ops[i].name ) )
00115 return &svcctl_ops[i];
00116 }
00117
00118 return NULL;
00119 }
00120
00121
00122
00123 static NTSTATUS svcctl_access_check( SEC_DESC *sec_desc, NT_USER_TOKEN *token,
00124 uint32 access_desired, uint32 *access_granted )
00125 {
00126 NTSTATUS result;
00127
00128 if ( geteuid() == sec_initial_uid() ) {
00129 DEBUG(5,("svcctl_access_check: using root's token\n"));
00130 token = get_root_nt_token();
00131 }
00132
00133 se_access_check( sec_desc, token, access_desired, access_granted, &result );
00134
00135 return result;
00136 }
00137
00138
00139
00140
00141 static SEC_DESC* construct_scm_sd( TALLOC_CTX *ctx )
00142 {
00143 SEC_ACE ace[2];
00144 SEC_ACCESS mask;
00145 size_t i = 0;
00146 SEC_DESC *sd;
00147 SEC_ACL *acl;
00148 size_t sd_size;
00149
00150
00151
00152 init_sec_access(&mask, SC_MANAGER_READ_ACCESS );
00153 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
00154
00155
00156
00157 init_sec_access(&mask,SC_MANAGER_ALL_ACCESS );
00158 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
00159
00160
00161
00162
00163 if ( !(acl = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) )
00164 return NULL;
00165
00166 if ( !(sd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, acl, &sd_size)) )
00167 return NULL;
00168
00169 return sd;
00170 }
00171
00172
00173
00174
00175
00176 static void free_service_handle_info(void *ptr)
00177 {
00178 TALLOC_FREE( ptr );
00179 }
00180
00181
00182
00183
00184
00185 static SERVICE_INFO *find_service_info_by_hnd(pipes_struct *p, POLICY_HND *hnd)
00186 {
00187 SERVICE_INFO *service_info = NULL;
00188
00189 if( !find_policy_by_hnd( p, hnd, (void **)(void *)&service_info) ) {
00190 DEBUG(2,("find_service_info_by_hnd: handle not found"));
00191 return NULL;
00192 }
00193
00194 return service_info;
00195 }
00196
00197
00198
00199
00200 static WERROR create_open_service_handle( pipes_struct *p, POLICY_HND *handle, uint32 type,
00201 const char *service, uint32 access_granted )
00202 {
00203 SERVICE_INFO *info = NULL;
00204 WERROR result = WERR_OK;
00205 struct service_control_op *s_op;
00206
00207 if ( !(info = TALLOC_ZERO_P( NULL, SERVICE_INFO )) )
00208 return WERR_NOMEM;
00209
00210
00211
00212 info->type = SVC_HANDLE_IS_SCM;
00213
00214 switch ( type ) {
00215 case SVC_HANDLE_IS_SCM:
00216 info->type = SVC_HANDLE_IS_SCM;
00217 break;
00218
00219 case SVC_HANDLE_IS_DBLOCK:
00220 info->type = SVC_HANDLE_IS_DBLOCK;
00221 break;
00222
00223 case SVC_HANDLE_IS_SERVICE:
00224 info->type = SVC_HANDLE_IS_SERVICE;
00225
00226
00227
00228 if ( !(s_op = find_service_by_name( service )) ) {
00229 result = WERR_NO_SUCH_SERVICE;
00230 goto done;
00231 }
00232
00233 info->ops = s_op->ops;
00234
00235 if ( !(info->name = talloc_strdup( info, s_op->name )) ) {
00236 result = WERR_NOMEM;
00237 goto done;
00238 }
00239 break;
00240
00241 default:
00242 result = WERR_NO_SUCH_SERVICE;
00243 goto done;
00244 }
00245
00246 info->access_granted = access_granted;
00247
00248
00249
00250 if ( !create_policy_hnd( p, handle, free_service_handle_info, info ) ) {
00251 result = WERR_ACCESS_DENIED;
00252 goto done;
00253 }
00254
00255 done:
00256 if ( !W_ERROR_IS_OK(result) )
00257 free_service_handle_info( info );
00258
00259 return result;
00260 }
00261
00262
00263
00264
00265 WERROR _svcctl_open_scmanager(pipes_struct *p, SVCCTL_Q_OPEN_SCMANAGER *q_u, SVCCTL_R_OPEN_SCMANAGER *r_u)
00266 {
00267 SEC_DESC *sec_desc;
00268 uint32 access_granted = 0;
00269 NTSTATUS status;
00270
00271
00272
00273 if ( !(sec_desc = construct_scm_sd( p->mem_ctx )) )
00274 return WERR_NOMEM;
00275
00276 se_map_generic( &q_u->access, &scm_generic_map );
00277 status = svcctl_access_check( sec_desc, p->pipe_user.nt_user_token, q_u->access, &access_granted );
00278 if ( !NT_STATUS_IS_OK(status) )
00279 return ntstatus_to_werror( status );
00280
00281 return create_open_service_handle( p, &r_u->handle, SVC_HANDLE_IS_SCM, NULL, access_granted );
00282 }
00283
00284
00285
00286
00287 WERROR _svcctl_open_service(pipes_struct *p, SVCCTL_Q_OPEN_SERVICE *q_u, SVCCTL_R_OPEN_SERVICE *r_u)
00288 {
00289 SEC_DESC *sec_desc;
00290 uint32 access_granted = 0;
00291 NTSTATUS status;
00292 pstring service;
00293
00294 rpcstr_pull(service, q_u->servicename.buffer, sizeof(service), q_u->servicename.uni_str_len*2, 0);
00295
00296 DEBUG(5, ("_svcctl_open_service: Attempting to open Service [%s], \n", service));
00297
00298
00299
00300
00301 if ( !find_service_info_by_hnd( p, &q_u->handle ) )
00302 return WERR_BADFID;
00303
00304
00305
00306
00307 if ( !(sec_desc = svcctl_get_secdesc( p->mem_ctx, service, get_root_nt_token() )) )
00308 return WERR_NOMEM;
00309
00310 se_map_generic( &q_u->access, &svc_generic_map );
00311 status = svcctl_access_check( sec_desc, p->pipe_user.nt_user_token, q_u->access, &access_granted );
00312 if ( !NT_STATUS_IS_OK(status) )
00313 return ntstatus_to_werror( status );
00314
00315 return create_open_service_handle( p, &r_u->handle, SVC_HANDLE_IS_SERVICE, service, access_granted );
00316 }
00317
00318
00319
00320
00321 WERROR _svcctl_close_service(pipes_struct *p, SVCCTL_Q_CLOSE_SERVICE *q_u, SVCCTL_R_CLOSE_SERVICE *r_u)
00322 {
00323 return close_policy_hnd( p, &q_u->handle ) ? WERR_OK : WERR_BADFID;
00324 }
00325
00326
00327
00328
00329 WERROR _svcctl_get_display_name(pipes_struct *p, SVCCTL_Q_GET_DISPLAY_NAME *q_u, SVCCTL_R_GET_DISPLAY_NAME *r_u)
00330 {
00331 fstring service;
00332 const char *display_name;
00333 SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle );
00334
00335
00336
00337 if ( !info || (info->type != SVC_HANDLE_IS_SCM) )
00338 return WERR_BADFID;
00339
00340 rpcstr_pull(service, q_u->servicename.buffer, sizeof(service), q_u->servicename.uni_str_len*2, 0);
00341
00342 display_name = svcctl_lookup_dispname( service, p->pipe_user.nt_user_token );
00343 init_svcctl_r_get_display_name( r_u, display_name );
00344
00345 return WERR_OK;
00346 }
00347
00348
00349
00350
00351 WERROR _svcctl_query_status(pipes_struct *p, SVCCTL_Q_QUERY_STATUS *q_u, SVCCTL_R_QUERY_STATUS *r_u)
00352 {
00353 SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle );
00354
00355
00356
00357 if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
00358 return WERR_BADFID;
00359
00360 if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_STATUS) )
00361 return WERR_ACCESS_DENIED;
00362
00363
00364
00365 return info->ops->service_status( info->name, &r_u->svc_status );
00366 }
00367
00368
00369
00370
00371 static int enumerate_status( TALLOC_CTX *ctx, ENUM_SERVICES_STATUS **status, NT_USER_TOKEN *token )
00372 {
00373 int num_services = 0;
00374 int i;
00375 ENUM_SERVICES_STATUS *st;
00376 const char *display_name;
00377
00378
00379 while ( svcctl_ops[num_services].name )
00380 num_services++;
00381
00382 if ( !(st = TALLOC_ARRAY( ctx, ENUM_SERVICES_STATUS, num_services )) ) {
00383 DEBUG(0,("enumerate_status: talloc() failed!\n"));
00384 return -1;
00385 }
00386
00387 for ( i=0; i<num_services; i++ ) {
00388 init_unistr( &st[i].servicename, svcctl_ops[i].name );
00389
00390 display_name = svcctl_lookup_dispname( svcctl_ops[i].name, token );
00391 init_unistr( &st[i].displayname, display_name );
00392
00393 svcctl_ops[i].ops->service_status( svcctl_ops[i].name, &st[i].status );
00394 }
00395
00396 *status = st;
00397
00398 return num_services;
00399 }
00400
00401
00402
00403
00404 WERROR _svcctl_enum_services_status(pipes_struct *p, SVCCTL_Q_ENUM_SERVICES_STATUS *q_u, SVCCTL_R_ENUM_SERVICES_STATUS *r_u)
00405 {
00406 ENUM_SERVICES_STATUS *services = NULL;
00407 int num_services;
00408 int i = 0;
00409 size_t buffer_size = 0;
00410 WERROR result = WERR_OK;
00411 SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle );
00412 NT_USER_TOKEN *token = p->pipe_user.nt_user_token;
00413
00414
00415
00416 if ( !info || (info->type != SVC_HANDLE_IS_SCM) )
00417 return WERR_BADFID;
00418
00419 if ( !(info->access_granted & SC_RIGHT_MGR_ENUMERATE_SERVICE) ) {
00420 return WERR_ACCESS_DENIED;
00421 }
00422
00423 num_services = enumerate_status( p->mem_ctx, &services, token );
00424 if (num_services == -1 ) {
00425 return WERR_NOMEM;
00426 }
00427
00428 for ( i=0; i<num_services; i++ ) {
00429 buffer_size += svcctl_sizeof_enum_services_status(&services[i]);
00430 }
00431
00432 buffer_size += buffer_size % 4;
00433
00434 if (buffer_size > q_u->buffer_size ) {
00435 num_services = 0;
00436 result = WERR_MORE_DATA;
00437 }
00438
00439 rpcbuf_init(&r_u->buffer, q_u->buffer_size, p->mem_ctx);
00440
00441 if ( W_ERROR_IS_OK(result) ) {
00442 for ( i=0; i<num_services; i++ )
00443 svcctl_io_enum_services_status( "", &services[i], &r_u->buffer, 0 );
00444 }
00445
00446 r_u->needed = (buffer_size > q_u->buffer_size) ? buffer_size : q_u->buffer_size;
00447 r_u->returned = (uint32)num_services;
00448
00449 if ( !(r_u->resume = TALLOC_P( p->mem_ctx, uint32 )) )
00450 return WERR_NOMEM;
00451
00452 *r_u->resume = 0x0;
00453
00454 return result;
00455 }
00456
00457
00458
00459
00460 WERROR _svcctl_start_service(pipes_struct *p, SVCCTL_Q_START_SERVICE *q_u, SVCCTL_R_START_SERVICE *r_u)
00461 {
00462 SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle );
00463
00464
00465
00466 if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
00467 return WERR_BADFID;
00468
00469 if ( !(info->access_granted & SC_RIGHT_SVC_START) )
00470 return WERR_ACCESS_DENIED;
00471
00472 return info->ops->start_service( info->name );
00473 }
00474
00475
00476
00477
00478 WERROR _svcctl_control_service(pipes_struct *p, SVCCTL_Q_CONTROL_SERVICE *q_u, SVCCTL_R_CONTROL_SERVICE *r_u)
00479 {
00480 SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle );
00481
00482
00483
00484 if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
00485 return WERR_BADFID;
00486
00487 switch ( q_u->control ) {
00488 case SVCCTL_CONTROL_STOP:
00489 if ( !(info->access_granted & SC_RIGHT_SVC_STOP) )
00490 return WERR_ACCESS_DENIED;
00491
00492 return info->ops->stop_service( info->name, &r_u->svc_status );
00493
00494 case SVCCTL_CONTROL_INTERROGATE:
00495 if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_STATUS) )
00496 return WERR_ACCESS_DENIED;
00497
00498 return info->ops->service_status( info->name, &r_u->svc_status );
00499 }
00500
00501
00502
00503 return WERR_ACCESS_DENIED;
00504 }
00505
00506
00507
00508
00509 WERROR _svcctl_enum_dependent_services( pipes_struct *p, SVCCTL_Q_ENUM_DEPENDENT_SERVICES *q_u, SVCCTL_R_ENUM_DEPENDENT_SERVICES *r_u )
00510 {
00511 SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle );
00512
00513
00514
00515 if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
00516 return WERR_BADFID;
00517
00518 if ( !(info->access_granted & SC_RIGHT_SVC_ENUMERATE_DEPENDENTS) )
00519 return WERR_ACCESS_DENIED;
00520
00521
00522
00523
00524 rpcbuf_init( &r_u->buffer, q_u->buffer_size, p->mem_ctx );
00525
00526 r_u->needed = q_u->buffer_size;
00527
00528
00529 r_u->returned = 0;
00530
00531 return WERR_OK;
00532 }
00533
00534
00535
00536
00537 WERROR _svcctl_query_service_status_ex( pipes_struct *p, SVCCTL_Q_QUERY_SERVICE_STATUSEX *q_u, SVCCTL_R_QUERY_SERVICE_STATUSEX *r_u )
00538 {
00539 SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle );
00540 uint32 buffer_size;
00541
00542
00543
00544 if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
00545 return WERR_BADFID;
00546
00547 if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_STATUS) )
00548 return WERR_ACCESS_DENIED;
00549
00550
00551
00552
00553 rpcbuf_init( &r_u->buffer, q_u->buffer_size, p->mem_ctx );
00554 r_u->needed = q_u->buffer_size;
00555
00556 switch ( q_u->level ) {
00557 case SVC_STATUS_PROCESS_INFO:
00558 {
00559 SERVICE_STATUS_PROCESS svc_stat_proc;
00560
00561
00562 info->ops->service_status( info->name, &svc_stat_proc.status );
00563 svc_stat_proc.process_id = sys_getpid();
00564 svc_stat_proc.service_flags = 0x0;
00565
00566 svcctl_io_service_status_process( "", &svc_stat_proc, &r_u->buffer, 0 );
00567 buffer_size = sizeof(SERVICE_STATUS_PROCESS);
00568 break;
00569 }
00570
00571 default:
00572 return WERR_UNKNOWN_LEVEL;
00573 }
00574
00575
00576 buffer_size += buffer_size % 4;
00577 r_u->needed = (buffer_size > q_u->buffer_size) ? buffer_size : q_u->buffer_size;
00578
00579 if (buffer_size > q_u->buffer_size )
00580 return WERR_MORE_DATA;
00581
00582 return WERR_OK;
00583 }
00584
00585
00586
00587
00588 static WERROR fill_svc_config( TALLOC_CTX *ctx, const char *name, SERVICE_CONFIG *config, NT_USER_TOKEN *token )
00589 {
00590 REGVAL_CTR *values;
00591 REGISTRY_VALUE *val;
00592
00593
00594
00595 if ( !(values = svcctl_fetch_regvalues( name, token )) )
00596 return WERR_REG_CORRUPT;
00597
00598
00599
00600 config->displayname = TALLOC_ZERO_P( ctx, UNISTR2 );
00601 if ( (val = regval_ctr_getvalue( values, "DisplayName" )) != NULL )
00602 init_unistr2( config->displayname, regval_sz( val ), UNI_STR_TERMINATE );
00603 else
00604 init_unistr2( config->displayname, name, UNI_STR_TERMINATE );
00605
00606 if ( (val = regval_ctr_getvalue( values, "ObjectName" )) != NULL ) {
00607 config->startname = TALLOC_ZERO_P( ctx, UNISTR2 );
00608 init_unistr2( config->startname, regval_sz( val ), UNI_STR_TERMINATE );
00609 }
00610
00611 if ( (val = regval_ctr_getvalue( values, "ImagePath" )) != NULL ) {
00612 config->executablepath = TALLOC_ZERO_P( ctx, UNISTR2 );
00613 init_unistr2( config->executablepath, regval_sz( val ), UNI_STR_TERMINATE );
00614 }
00615
00616
00617
00618
00619 config->tag_id = 0x00000000;
00620 config->service_type = SVCCTL_WIN32_OWN_PROC;
00621 config->error_control = SVCCTL_SVC_ERROR_NORMAL;
00622
00623
00624
00625
00626
00627 if ( strequal( name, "NETLOGON" ) && ( lp_servicenumber(name) == -1 ) )
00628 config->start_type = SVCCTL_DISABLED;
00629 else if ( strequal( name, "WINS" ) && ( !lp_wins_support() ))
00630 config->start_type = SVCCTL_DISABLED;
00631 else
00632 config->start_type = SVCCTL_DEMAND_START;
00633
00634
00635 TALLOC_FREE( values );
00636
00637 return WERR_OK;
00638 }
00639
00640
00641
00642
00643 WERROR _svcctl_query_service_config( pipes_struct *p, SVCCTL_Q_QUERY_SERVICE_CONFIG *q_u, SVCCTL_R_QUERY_SERVICE_CONFIG *r_u )
00644 {
00645 SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle );
00646 uint32 buffer_size;
00647 WERROR wresult;
00648
00649
00650
00651 if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
00652 return WERR_BADFID;
00653
00654 if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_CONFIG) )
00655 return WERR_ACCESS_DENIED;
00656
00657
00658
00659
00660 r_u->needed = q_u->buffer_size;
00661
00662 wresult = fill_svc_config( p->mem_ctx, info->name, &r_u->config, p->pipe_user.nt_user_token );
00663 if ( !W_ERROR_IS_OK(wresult) )
00664 return wresult;
00665
00666 buffer_size = svcctl_sizeof_service_config( &r_u->config );
00667 r_u->needed = (buffer_size > q_u->buffer_size) ? buffer_size : q_u->buffer_size;
00668
00669 if (buffer_size > q_u->buffer_size ) {
00670 ZERO_STRUCTP( &r_u->config );
00671 return WERR_INSUFFICIENT_BUFFER;
00672 }
00673
00674 return WERR_OK;
00675 }
00676
00677
00678
00679
00680 WERROR _svcctl_query_service_config2( pipes_struct *p, SVCCTL_Q_QUERY_SERVICE_CONFIG2 *q_u, SVCCTL_R_QUERY_SERVICE_CONFIG2 *r_u )
00681 {
00682 SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle );
00683 uint32 buffer_size;
00684
00685
00686
00687 if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
00688 return WERR_BADFID;
00689
00690 if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_CONFIG) )
00691 return WERR_ACCESS_DENIED;
00692
00693
00694
00695
00696 rpcbuf_init( &r_u->buffer, q_u->buffer_size, p->mem_ctx );
00697 r_u->needed = q_u->buffer_size;
00698
00699 switch ( q_u->level ) {
00700 case SERVICE_CONFIG_DESCRIPTION:
00701 {
00702 SERVICE_DESCRIPTION desc_buf;
00703 const char *description;
00704
00705 description = svcctl_lookup_description( info->name, p->pipe_user.nt_user_token );
00706
00707 ZERO_STRUCTP( &desc_buf );
00708
00709 init_service_description_buffer( &desc_buf, description );
00710 svcctl_io_service_description( "", &desc_buf, &r_u->buffer, 0 );
00711 buffer_size = svcctl_sizeof_service_description( &desc_buf );
00712
00713 break;
00714 }
00715 break;
00716 case SERVICE_CONFIG_FAILURE_ACTIONS:
00717 {
00718 SERVICE_FAILURE_ACTIONS actions;
00719
00720
00721
00722 ZERO_STRUCTP( &actions );
00723 svcctl_io_service_fa( "", &actions, &r_u->buffer, 0 );
00724 buffer_size = svcctl_sizeof_service_fa( &actions );
00725
00726 break;
00727 }
00728 break;
00729
00730 default:
00731 return WERR_UNKNOWN_LEVEL;
00732 }
00733
00734 buffer_size += buffer_size % 4;
00735 r_u->needed = (buffer_size > q_u->buffer_size) ? buffer_size : q_u->buffer_size;
00736
00737 if (buffer_size > q_u->buffer_size )
00738 return WERR_INSUFFICIENT_BUFFER;
00739
00740 return WERR_OK;
00741 }
00742
00743
00744
00745
00746 WERROR _svcctl_lock_service_db( pipes_struct *p, SVCCTL_Q_LOCK_SERVICE_DB *q_u, SVCCTL_R_LOCK_SERVICE_DB *r_u )
00747 {
00748 SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle );
00749
00750
00751
00752 if ( !info || (info->type != SVC_HANDLE_IS_SCM) )
00753 return WERR_BADFID;
00754
00755 if ( !(info->access_granted & SC_RIGHT_MGR_LOCK) )
00756 return WERR_ACCESS_DENIED;
00757
00758
00759
00760 return create_open_service_handle( p, &r_u->h_lock, SVC_HANDLE_IS_DBLOCK, NULL, 0 );
00761 ;
00762 }
00763
00764
00765
00766
00767 WERROR _svcctl_unlock_service_db( pipes_struct *p, SVCCTL_Q_UNLOCK_SERVICE_DB *q_u, SVCCTL_R_UNLOCK_SERVICE_DB *r_u )
00768 {
00769 SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->h_lock );
00770
00771
00772 if ( !info || (info->type != SVC_HANDLE_IS_DBLOCK) )
00773 return WERR_BADFID;
00774
00775 return close_policy_hnd( p, &q_u->h_lock) ? WERR_OK : WERR_BADFID;
00776 }
00777
00778
00779
00780
00781 WERROR _svcctl_query_service_sec( pipes_struct *p, SVCCTL_Q_QUERY_SERVICE_SEC *q_u, SVCCTL_R_QUERY_SERVICE_SEC *r_u )
00782 {
00783 SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle );
00784 SEC_DESC *sec_desc;
00785
00786
00787
00788
00789 if ( !info || !(info->type & (SVC_HANDLE_IS_SERVICE|SVC_HANDLE_IS_SCM)) )
00790 return WERR_BADFID;
00791
00792
00793
00794 if ( !(info->access_granted & STD_RIGHT_READ_CONTROL_ACCESS) )
00795 return WERR_ACCESS_DENIED;
00796
00797
00798
00799 if ( (q_u->security_flags & DACL_SECURITY_INFORMATION) != DACL_SECURITY_INFORMATION )
00800 return WERR_INVALID_PARAM;
00801
00802
00803
00804 if ( !(sec_desc = svcctl_get_secdesc( p->mem_ctx, info->name, get_root_nt_token() )) )
00805 return WERR_NOMEM;
00806
00807 r_u->needed = sec_desc_size( sec_desc );
00808
00809 if ( r_u->needed > q_u->buffer_size ) {
00810 ZERO_STRUCTP( &r_u->buffer );
00811 return WERR_INSUFFICIENT_BUFFER;
00812 }
00813
00814 rpcbuf_init( &r_u->buffer, q_u->buffer_size, p->mem_ctx );
00815
00816 if ( !sec_io_desc("", &sec_desc, &r_u->buffer.prs, 0 ) )
00817 return WERR_NOMEM;
00818
00819 return WERR_OK;
00820 }
00821
00822
00823
00824
00825 WERROR _svcctl_set_service_sec( pipes_struct *p, SVCCTL_Q_SET_SERVICE_SEC *q_u, SVCCTL_R_SET_SERVICE_SEC *r_u )
00826 {
00827 SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle );
00828 SEC_DESC *sec_desc = NULL;
00829 uint32 required_access;
00830
00831 if ( !info || !(info->type & (SVC_HANDLE_IS_SERVICE|SVC_HANDLE_IS_SCM)) )
00832 return WERR_BADFID;
00833
00834
00835
00836 if ( info->type == SVC_HANDLE_IS_SCM )
00837 return WERR_ACCESS_DENIED;
00838
00839
00840
00841 switch ( q_u->security_flags ) {
00842 case DACL_SECURITY_INFORMATION:
00843 required_access = STD_RIGHT_WRITE_DAC_ACCESS;
00844 break;
00845
00846 case OWNER_SECURITY_INFORMATION:
00847 case GROUP_SECURITY_INFORMATION:
00848 required_access = STD_RIGHT_WRITE_OWNER_ACCESS;
00849 break;
00850
00851 case SACL_SECURITY_INFORMATION:
00852 return WERR_INVALID_PARAM;
00853 default:
00854 return WERR_INVALID_PARAM;
00855 }
00856
00857 if ( !(info->access_granted & required_access) )
00858 return WERR_ACCESS_DENIED;
00859
00860
00861
00862 if ( !sec_io_desc("", &sec_desc, &q_u->buffer.prs, 0 ) )
00863 return WERR_NOMEM;
00864
00865
00866
00867 if ( !svcctl_set_secdesc( p->mem_ctx, info->name, sec_desc, p->pipe_user.nt_user_token ) )
00868 return WERR_ACCESS_DENIED;
00869
00870 return WERR_OK;
00871 }
00872
00873