rpc_server/srv_svcctl_nt.c

説明を見る。
00001 /* 
00002  *  Unix SMB/CIFS implementation.
00003  *  RPC Pipe client / server routines
00004  *
00005  *  Copyright (C) Marcin Krzysztof Porwit           2005.
00006  * 
00007  *  Largely Rewritten (Again) by:
00008  *  Copyright (C) Gerald (Jerry) Carter             2005.
00009  *  
00010  *  This program is free software; you can redistribute it and/or modify
00011  *  it under the terms of the GNU General Public License as published by
00012  *  the Free Software Foundation; either version 2 of the License, or
00013  *  (at your option) any later version.
00014  *  
00015  *  This program is distributed in the hope that it will be useful,
00016  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  *  GNU General Public License for more details.
00019  *  
00020  *  You should have received a copy of the GNU General Public License
00021  *  along with this program; if not, write to the Free Software
00022  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
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 /* handle external services */
00038 extern SERVICE_CONTROL_OPS rcinit_svc_ops;
00039 
00040 /* builtin services (see service_db.c and services/svc_*.c */
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 /* make sure this number patches the number of builtin
00047    SERVICE_CONTROL_OPS structure listed above */
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         /* services listed in smb.conf get the rc.init interface */
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         /* add builtin services */
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         /* NULL terminate the array */
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         /* basic access for Everyone */
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         /* Full Access 'BUILTIN\Administrators' */
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         /* create the security descriptor */
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  free() function for REGISTRY_KEY
00174  *****************************************************************/
00175  
00176 static void free_service_handle_info(void *ptr)
00177 {
00178         TALLOC_FREE( ptr );
00179 }
00180 
00181 /******************************************************************
00182  Find a registry key handle and return a SERVICE_INFO
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         /* the Service Manager has a NULL name */
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                 /* lookup the SERVICE_CONTROL_OPS */
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         /* store the SERVICE_INFO and create an open handle */
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         /* perform access checks */
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         /* based on my tests you can open a service if you have a valid scm handle */
00300         
00301         if ( !find_service_info_by_hnd( p, &q_u->handle ) )
00302                 return WERR_BADFID;
00303                         
00304         /* perform access checks.  Use the root token in order to ensure that we 
00305            retrieve the security descriptor */
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         /* can only use an SCM handle here */
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         /* perform access checks */
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         /* try the service specific status call */
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         /* just count */
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         /* perform access checks */
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         /* perform access checks */
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         /* perform access checks */
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         /* default control action */
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         /* perform access checks */
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         /* we have to set the outgoing buffer size to the same as the 
00522            incoming buffer size (even in the case of failure */
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         /* no dependent services...basically a stub function */
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         /* perform access checks */
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         /* we have to set the outgoing buffer size to the same as the 
00551            incoming buffer size (even in the case of failure) */
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                         /* Get the status of the service.. */
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         /* retrieve the registry values for this service */
00594         
00595         if ( !(values = svcctl_fetch_regvalues( name, token )) )
00596                 return WERR_REG_CORRUPT;
00597         
00598         /* now fill in the individual values */
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         /* a few hard coded values */
00617         /* loadordergroup and dependencies are empty */
00618         
00619         config->tag_id           = 0x00000000;                  /* unassigned loadorder group */
00620         config->service_type     = SVCCTL_WIN32_OWN_PROC;
00621         config->error_control    = SVCCTL_SVC_ERROR_NORMAL;
00622 
00623         /* set the start type.  NetLogon and WINS are disabled to prevent 
00624            the client from showing the "Start" button (if of course the services
00625            are not running */
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         /* perform access checks */
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         /* we have to set the outgoing buffer size to the same as the 
00658            incoming buffer size (even in the case of failure */
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         /* perform access checks */
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         /* we have to set the outgoing buffer size to the same as the 
00694            incoming buffer size (even in the case of failure */
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                         /* nothing to say...just service the request */
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         /* perform access checks */
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         /* Just open a handle.  Doesn't actually lock anything */
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         /* only support the SCM and individual services */
00788 
00789         if ( !info || !(info->type & (SVC_HANDLE_IS_SERVICE|SVC_HANDLE_IS_SCM)) )
00790                 return WERR_BADFID;     
00791 
00792         /* check access reights (according to MSDN) */
00793 
00794         if ( !(info->access_granted & STD_RIGHT_READ_CONTROL_ACCESS) )
00795                 return WERR_ACCESS_DENIED;
00796 
00797         /* TODO: handle something besides DACL_SECURITY_INFORMATION */
00798 
00799         if ( (q_u->security_flags & DACL_SECURITY_INFORMATION) != DACL_SECURITY_INFORMATION )
00800                 return WERR_INVALID_PARAM;
00801 
00802         /* lookup the security descriptor and marshall it up for a reply */
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         /* can't set the security de4scriptor on the ServiceControlManager */
00835 
00836         if ( info->type == SVC_HANDLE_IS_SCM )
00837                 return WERR_ACCESS_DENIED;      
00838 
00839         /* check the access on the open handle */
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         /* read the security descfriptor */
00861                 
00862         if ( !sec_io_desc("", &sec_desc, &q_u->buffer.prs, 0 ) )
00863                 return WERR_NOMEM;
00864                 
00865         /* store the new SD */
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 

Sambaに対してSat Aug 29 21:23:22 2009に生成されました。  doxygen 1.4.7