2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
5 * Copyright (C) Marcin Krzysztof Porwit 2005.
7 * Largely Rewritten by:
8 * Copyright (C) Gerald (Jerry) Carter 2005.
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.
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.
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.
28 #define DBGC_CLASS DBGC_RPC_SRV
30 struct service_control_op
{
32 SERVICE_CONTROL_OPS
*ops
;
35 extern SERVICE_CONTROL_OPS spoolss_svc_ops
;
36 extern SERVICE_CONTROL_OPS rcinit_svc_ops
;
37 extern SERVICE_CONTROL_OPS netlogon_svc_ops
;
38 extern SERVICE_CONTROL_OPS winreg_svc_ops
;
40 struct service_control_op
*svcctl_ops
;
43 /********************************************************************
44 ********************************************************************/
46 BOOL
init_service_op_table( void )
48 const char **service_list
= lp_svcctl_list();
49 int num_services
= 3 + str_list_count( service_list
);
52 if ( !(svcctl_ops
= TALLOC_ARRAY( NULL
, struct service_control_op
, num_services
+1)) ) {
53 DEBUG(0,("init_service_op_table: talloc() failed!\n"));
57 /* services listed in smb.conf get the rc.init interface */
59 for ( i
=0; service_list
[i
]; i
++ ) {
60 svcctl_ops
[i
].name
= talloc_strdup( svcctl_ops
, service_list
[i
] );
61 svcctl_ops
[i
].ops
= &rcinit_svc_ops
;
64 /* add builtin services */
66 svcctl_ops
[i
].name
= talloc_strdup( svcctl_ops
, "Spooler" );
67 svcctl_ops
[i
].ops
= &spoolss_svc_ops
;
70 svcctl_ops
[i
].name
= talloc_strdup( svcctl_ops
, "NETLOGON" );
71 svcctl_ops
[i
].ops
= &netlogon_svc_ops
;
74 svcctl_ops
[i
].name
= talloc_strdup( svcctl_ops
, "RemoteRegistry" );
75 svcctl_ops
[i
].ops
= &winreg_svc_ops
;
78 /* NULL terminate the array */
80 svcctl_ops
[i
].name
= NULL
;
81 svcctl_ops
[i
].ops
= NULL
;
86 /********************************************************************
87 ********************************************************************/
89 static struct service_control_op
* find_service_by_name( const char *name
)
93 for ( i
=0; svcctl_ops
[i
].name
; i
++ ) {
94 if ( strequal( name
, svcctl_ops
[i
].name
) )
95 return &svcctl_ops
[i
];
100 /********************************************************************
101 ********************************************************************/
103 static NTSTATUS
svcctl_access_check( SEC_DESC
*sec_desc
, NT_USER_TOKEN
*token
,
104 uint32 access_desired
, uint32
*access_granted
)
108 /* maybe add privilege checks in here later */
110 se_access_check( sec_desc
, token
, access_desired
, access_granted
, &result
);
115 /********************************************************************
116 ********************************************************************/
118 static SEC_DESC
* construct_scm_sd( TALLOC_CTX
*ctx
)
127 /* basic access for Everyone */
129 init_sec_access(&mask
, SC_MANAGER_READ_ACCESS
);
130 init_sec_ace(&ace
[i
++], &global_sid_World
, SEC_ACE_TYPE_ACCESS_ALLOWED
, mask
, 0);
132 /* Full Access 'BUILTIN\Administrators' */
134 init_sec_access(&mask
,SC_MANAGER_ALL_ACCESS
);
135 init_sec_ace(&ace
[i
++], &global_sid_Builtin_Administrators
, SEC_ACE_TYPE_ACCESS_ALLOWED
, mask
, 0);
138 /* create the security descriptor */
140 if ( !(acl
= make_sec_acl(ctx
, NT4_ACL_REVISION
, i
, ace
)) )
143 if ( !(sd
= make_sec_desc(ctx
, SEC_DESC_REVISION
, SEC_DESC_SELF_RELATIVE
, NULL
, NULL
, NULL
, acl
, &sd_size
)) )
149 /******************************************************************
150 free() function for REGISTRY_KEY
151 *****************************************************************/
153 static void free_service_handle_info(void *ptr
)
158 /******************************************************************
159 Find a registry key handle and return a SERVICE_INFO
160 *****************************************************************/
162 static SERVICE_INFO
*find_service_info_by_hnd(pipes_struct
*p
, POLICY_HND
*hnd
)
164 SERVICE_INFO
*service_info
= NULL
;
166 if( !find_policy_by_hnd( p
, hnd
, (void **)&service_info
) ) {
167 DEBUG(2,("find_service_info_by_hnd: handle not found"));
174 /******************************************************************
175 *****************************************************************/
177 static WERROR
create_open_service_handle( pipes_struct
*p
, POLICY_HND
*handle
,
178 const char *service
, uint32 access_granted
)
180 SERVICE_INFO
*info
= NULL
;
181 WERROR result
= WERR_OK
;
183 if ( !(info
= TALLOC_ZERO_P( NULL
, SERVICE_INFO
)) )
186 /* the Service Manager has a NULL name */
188 info
->type
= SVC_HANDLE_IS_SCM
;
193 struct service_control_op
*s_op
;
195 info
->type
= SVC_HANDLE_IS_SERVICE
;
197 /* lookup the SERVICE_CONTROL_OPS */
199 if ( !(s_op
= find_service_by_name( service
)) ) {
200 result
= WERR_NO_SUCH_SERVICE
;
204 info
->ops
= s_op
->ops
;
206 if ( !(info
->name
= talloc_strdup( info
, s_op
->name
)) ) {
212 info
->access_granted
= access_granted
;
214 /* store the SERVICE_INFO and create an open handle */
216 if ( !create_policy_hnd( p
, handle
, free_service_handle_info
, info
) ) {
217 result
= WERR_ACCESS_DENIED
;
222 if ( !W_ERROR_IS_OK(result
) )
223 free_service_handle_info( info
);
228 /********************************************************************
229 ********************************************************************/
231 WERROR
_svcctl_open_scmanager(pipes_struct
*p
, SVCCTL_Q_OPEN_SCMANAGER
*q_u
, SVCCTL_R_OPEN_SCMANAGER
*r_u
)
234 uint32 access_granted
= 0;
237 /* perform access checks */
239 if ( !(sec_desc
= construct_scm_sd( p
->mem_ctx
)) )
242 status
= svcctl_access_check( sec_desc
, p
->pipe_user
.nt_user_token
, q_u
->access
, &access_granted
);
243 if ( !NT_STATUS_IS_OK(status
) )
244 return ntstatus_to_werror( status
);
246 return create_open_service_handle( p
, &r_u
->handle
, NULL
, access_granted
);
249 /********************************************************************
250 ********************************************************************/
252 WERROR
_svcctl_open_service(pipes_struct
*p
, SVCCTL_Q_OPEN_SERVICE
*q_u
, SVCCTL_R_OPEN_SERVICE
*r_u
)
255 uint32 access_granted
= 0;
259 rpcstr_pull(service
, q_u
->servicename
.buffer
, sizeof(service
), q_u
->servicename
.uni_str_len
*2, 0);
261 DEBUG(5, ("_svcctl_open_service: Attempting to open Service [%s], \n", service
));
264 /* based on my tests you can open a service if you have a valid scm handle */
266 if ( !find_service_info_by_hnd( p
, &q_u
->handle
) )
269 /* perform access checks. Use the root token in order to ensure that we
270 retreive the security descriptor */
272 if ( !(sec_desc
= svcctl_get_secdesc( p
->mem_ctx
, service
, get_root_nt_token() )) )
275 status
= svcctl_access_check( sec_desc
, p
->pipe_user
.nt_user_token
, q_u
->access
, &access_granted
);
276 if ( !NT_STATUS_IS_OK(status
) )
277 return ntstatus_to_werror( status
);
279 return create_open_service_handle( p
, &r_u
->handle
, service
, access_granted
);
282 /********************************************************************
283 ********************************************************************/
285 WERROR
_svcctl_close_service(pipes_struct
*p
, SVCCTL_Q_CLOSE_SERVICE
*q_u
, SVCCTL_R_CLOSE_SERVICE
*r_u
)
287 return close_policy_hnd( p
, &q_u
->handle
) ? WERR_OK
: WERR_BADFID
;
290 /********************************************************************
291 ********************************************************************/
293 WERROR
_svcctl_get_display_name(pipes_struct
*p
, SVCCTL_Q_GET_DISPLAY_NAME
*q_u
, SVCCTL_R_GET_DISPLAY_NAME
*r_u
)
296 const char *display_name
;
297 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, &q_u
->handle
);
299 /* can only use an SCM handle here */
301 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_SCM
) )
304 rpcstr_pull(service
, q_u
->servicename
.buffer
, sizeof(service
), q_u
->servicename
.uni_str_len
*2, 0);
306 display_name
= svcctl_lookup_dispname( service
, p
->pipe_user
.nt_user_token
);
307 init_svcctl_r_get_display_name( r_u
, display_name
);
312 /********************************************************************
313 ********************************************************************/
315 WERROR
_svcctl_query_status(pipes_struct
*p
, SVCCTL_Q_QUERY_STATUS
*q_u
, SVCCTL_R_QUERY_STATUS
*r_u
)
317 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, &q_u
->handle
);
319 /* perform access checks */
321 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_SERVICE
) )
324 if ( !(info
->access_granted
& SC_RIGHT_SVC_QUERY_STATUS
) )
325 return WERR_ACCESS_DENIED
;
327 /* try the service specific status call */
329 return info
->ops
->service_status( &r_u
->svc_status
);
332 /********************************************************************
333 ********************************************************************/
335 static int enumerate_status( TALLOC_CTX
*ctx
, ENUM_SERVICES_STATUS
**status
, NT_USER_TOKEN
*token
)
337 int num_services
= 0;
339 ENUM_SERVICES_STATUS
*st
;
340 const char *display_name
;
343 while ( svcctl_ops
[num_services
].name
)
346 if ( !(st
= TALLOC_ARRAY( ctx
, ENUM_SERVICES_STATUS
, num_services
)) ) {
347 DEBUG(0,("enumerate_status: talloc() failed!\n"));
351 for ( i
=0; i
<num_services
; i
++ ) {
352 init_unistr( &st
[i
].servicename
, svcctl_ops
[i
].name
);
354 display_name
= svcctl_lookup_dispname( svcctl_ops
[i
].name
, token
);
355 init_unistr( &st
[i
].displayname
, display_name
);
357 svcctl_ops
[i
].ops
->service_status( &st
[i
].status
);
365 /********************************************************************
366 ********************************************************************/
368 WERROR
_svcctl_enum_services_status(pipes_struct
*p
, SVCCTL_Q_ENUM_SERVICES_STATUS
*q_u
, SVCCTL_R_ENUM_SERVICES_STATUS
*r_u
)
370 ENUM_SERVICES_STATUS
*services
= NULL
;
373 size_t buffer_size
= 0;
374 WERROR result
= WERR_OK
;
375 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, &q_u
->handle
);
376 NT_USER_TOKEN
*token
= p
->pipe_user
.nt_user_token
;
378 /* perform access checks */
380 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_SCM
) )
383 if ( !(info
->access_granted
& SC_RIGHT_MGR_ENUMERATE_SERVICE
) )
384 return WERR_ACCESS_DENIED
;
386 if ( (num_services
= enumerate_status( p
->mem_ctx
, &services
, token
)) == -1 )
389 for ( i
=0; i
<num_services
; i
++ ) {
390 buffer_size
+= svcctl_sizeof_enum_services_status(&services
[i
]);
393 buffer_size
+= buffer_size
% 4;
395 if (buffer_size
> q_u
->buffer_size
) {
397 result
= WERR_MORE_DATA
;
400 rpcbuf_init(&r_u
->buffer
, q_u
->buffer_size
, p
->mem_ctx
);
402 if ( W_ERROR_IS_OK(result
) ) {
403 for ( i
=0; i
<num_services
; i
++ )
404 svcctl_io_enum_services_status( "", &services
[i
], &r_u
->buffer
, 0 );
407 r_u
->needed
= (buffer_size
> q_u
->buffer_size
) ? buffer_size
: q_u
->buffer_size
;
408 r_u
->returned
= num_services
;
410 if ( !(r_u
->resume
= TALLOC_P( p
->mem_ctx
, uint32
)) )
418 /********************************************************************
419 ********************************************************************/
421 WERROR
_svcctl_start_service(pipes_struct
*p
, SVCCTL_Q_START_SERVICE
*q_u
, SVCCTL_R_START_SERVICE
*r_u
)
423 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, &q_u
->handle
);
425 /* perform access checks */
427 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_SERVICE
) )
430 if ( !(info
->access_granted
& SC_RIGHT_SVC_START
) )
431 return WERR_ACCESS_DENIED
;
433 return info
->ops
->start_service();
436 /********************************************************************
437 ********************************************************************/
439 WERROR
_svcctl_control_service(pipes_struct
*p
, SVCCTL_Q_CONTROL_SERVICE
*q_u
, SVCCTL_R_CONTROL_SERVICE
*r_u
)
441 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, &q_u
->handle
);
443 /* perform access checks */
445 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_SERVICE
) )
448 switch ( q_u
->control
) {
449 case SVCCTL_CONTROL_STOP
:
450 if ( !(info
->access_granted
& SC_RIGHT_SVC_STOP
) )
451 return WERR_ACCESS_DENIED
;
453 return info
->ops
->stop_service( &r_u
->svc_status
);
455 case SVCCTL_CONTROL_INTERROGATE
:
456 if ( !(info
->access_granted
& SC_RIGHT_SVC_QUERY_STATUS
) )
457 return WERR_ACCESS_DENIED
;
459 return info
->ops
->service_status( &r_u
->svc_status
);
462 /* default control action */
464 return WERR_ACCESS_DENIED
;
467 /********************************************************************
468 ********************************************************************/
470 WERROR
_svcctl_enum_dependent_services( pipes_struct
*p
, SVCCTL_Q_ENUM_DEPENDENT_SERVICES
*q_u
, SVCCTL_R_ENUM_DEPENDENT_SERVICES
*r_u
)
472 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, &q_u
->handle
);
474 /* perform access checks */
476 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_SERVICE
) )
479 if ( !(info
->access_granted
& SC_RIGHT_SVC_ENUMERATE_DEPENDENTS
) )
480 return WERR_ACCESS_DENIED
;
482 /* we have to set the outgoing buffer size to the same as the
483 incoming buffer size (even in the case of failure */
485 rpcbuf_init( &r_u
->buffer
, q_u
->buffer_size
, p
->mem_ctx
);
487 r_u
->needed
= q_u
->buffer_size
;
489 /* no dependent services...basically a stub function */
495 /********************************************************************
496 ********************************************************************/
498 WERROR
_svcctl_query_service_status_ex( pipes_struct
*p
, SVCCTL_Q_QUERY_SERVICE_STATUSEX
*q_u
, SVCCTL_R_QUERY_SERVICE_STATUSEX
*r_u
)
500 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, &q_u
->handle
);
503 /* perform access checks */
505 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_SERVICE
) )
508 if ( !(info
->access_granted
& SC_RIGHT_SVC_QUERY_STATUS
) )
509 return WERR_ACCESS_DENIED
;
511 /* we have to set the outgoing buffer size to the same as the
512 incoming buffer size (even in the case of failure) */
514 rpcbuf_init( &r_u
->buffer
, q_u
->buffer_size
, p
->mem_ctx
);
515 r_u
->needed
= q_u
->buffer_size
;
517 switch ( q_u
->level
) {
518 case SVC_STATUS_PROCESS_INFO
:
520 SERVICE_STATUS_PROCESS svc_stat_proc
;
522 /* Get the status of the service.. */
523 info
->ops
->service_status( &svc_stat_proc
.status
);
524 svc_stat_proc
.process_id
= sys_getpid();
525 svc_stat_proc
.service_flags
= 0x0;
527 svcctl_io_service_status_process( "", &svc_stat_proc
, &r_u
->buffer
, 0 );
528 buffer_size
= sizeof(SERVICE_STATUS_PROCESS
);
533 return WERR_UNKNOWN_LEVEL
;
537 buffer_size
+= buffer_size
% 4;
538 r_u
->needed
= (buffer_size
> q_u
->buffer_size
) ? buffer_size
: q_u
->buffer_size
;
540 if (buffer_size
> q_u
->buffer_size
)
541 return WERR_MORE_DATA
;
546 /********************************************************************
547 ********************************************************************/
549 static WERROR
fill_svc_config( TALLOC_CTX
*ctx
, const char *name
, SERVICE_CONFIG
*config
, NT_USER_TOKEN
*token
)
554 /* retrieve the registry values for this service */
556 if ( !(values
= svcctl_fetch_regvalues( name
, token
)) )
557 return WERR_REG_CORRUPT
;
559 /* now fill in the individual values */
561 config
->displayname
= TALLOC_ZERO_P( ctx
, UNISTR2
);
562 if ( (val
= regval_ctr_getvalue( values
, "DisplayName" )) != NULL
)
563 init_unistr2( config
->displayname
, regval_sz( val
), UNI_STR_TERMINATE
);
565 init_unistr2( config
->displayname
, name
, UNI_STR_TERMINATE
);
567 if ( (val
= regval_ctr_getvalue( values
, "ObjectName" )) != NULL
) {
568 config
->startname
= TALLOC_ZERO_P( ctx
, UNISTR2
);
569 init_unistr2( config
->startname
, regval_sz( val
), UNI_STR_TERMINATE
);
572 if ( (val
= regval_ctr_getvalue( values
, "ImagePath" )) != NULL
) {
573 config
->executablepath
= TALLOC_ZERO_P( ctx
, UNISTR2
);
574 init_unistr2( config
->executablepath
, regval_sz( val
), UNI_STR_TERMINATE
);
577 /* a few hard coded values */
578 /* loadordergroup and dependencies are empty */
580 config
->tag_id
= 0x00000000; /* unassigned loadorder group */
581 config
->service_type
= SVCCTL_WIN32_OWN_PROC
;
582 config
->start_type
= SVCCTL_DEMAND_START
;
583 config
->error_control
= SVCCTL_SVC_ERROR_NORMAL
;
585 TALLOC_FREE( values
);
590 /********************************************************************
591 ********************************************************************/
593 WERROR
_svcctl_query_service_config( pipes_struct
*p
, SVCCTL_Q_QUERY_SERVICE_CONFIG
*q_u
, SVCCTL_R_QUERY_SERVICE_CONFIG
*r_u
)
595 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, &q_u
->handle
);
599 /* perform access checks */
601 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_SERVICE
) )
604 if ( !(info
->access_granted
& SC_RIGHT_SVC_QUERY_CONFIG
) )
605 return WERR_ACCESS_DENIED
;
607 /* we have to set the outgoing buffer size to the same as the
608 incoming buffer size (even in the case of failure */
610 r_u
->needed
= q_u
->buffer_size
;
612 wresult
= fill_svc_config( p
->mem_ctx
, info
->name
, &r_u
->config
, p
->pipe_user
.nt_user_token
);
613 if ( !W_ERROR_IS_OK(wresult
) )
616 buffer_size
= svcctl_sizeof_service_config( &r_u
->config
);
617 r_u
->needed
= (buffer_size
> q_u
->buffer_size
) ? buffer_size
: q_u
->buffer_size
;
619 if (buffer_size
> q_u
->buffer_size
) {
620 ZERO_STRUCTP( &r_u
->config
);
621 return WERR_INSUFFICIENT_BUFFER
;
627 /********************************************************************
628 ********************************************************************/
630 WERROR
_svcctl_query_service_config2( pipes_struct
*p
, SVCCTL_Q_QUERY_SERVICE_CONFIG2
*q_u
, SVCCTL_R_QUERY_SERVICE_CONFIG2
*r_u
)
632 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, &q_u
->handle
);
635 /* perform access checks */
637 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_SERVICE
) )
640 if ( !(info
->access_granted
& SC_RIGHT_SVC_QUERY_CONFIG
) )
641 return WERR_ACCESS_DENIED
;
643 /* we have to set the outgoing buffer size to the same as the
644 incoming buffer size (even in the case of failure */
646 rpcbuf_init( &r_u
->buffer
, q_u
->buffer_size
, p
->mem_ctx
);
647 r_u
->needed
= q_u
->buffer_size
;
649 switch ( q_u
->level
) {
650 case SERVICE_CONFIG_DESCRIPTION
:
652 SERVICE_DESCRIPTION desc_buf
;
653 const char *description
;
655 description
= svcctl_lookup_description( info
->name
, p
->pipe_user
.nt_user_token
);
657 ZERO_STRUCTP( &desc_buf
);
658 init_service_description_buffer( &desc_buf
, description
);
659 svcctl_io_service_description( "", &desc_buf
, &r_u
->buffer
, 0 );
660 buffer_size
= svcctl_sizeof_service_description( &desc_buf
);
666 return WERR_UNKNOWN_LEVEL
;
669 r_u
->needed
= (buffer_size
> q_u
->buffer_size
) ? buffer_size
: q_u
->buffer_size
;
671 if (buffer_size
> q_u
->buffer_size
)
672 return WERR_INSUFFICIENT_BUFFER
;