2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
5 * Copyright (C) Marcin Krzysztof Porwit 2005.
7 * Largely Rewritten (Again) by:
8 * Copyright (C) Gerald (Jerry) Carter 2005.
9 * Copyright (C) Guenther Deschner 2008,2009.
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 3 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, see <http://www.gnu.org/licenses/>.
27 #include "../librpc/gen_ndr/srv_svcctl.h"
28 #include "../libcli/security/security.h"
29 #include "../librpc/gen_ndr/ndr_security.h"
30 #include "services/services.h"
31 #include "services/svc_winreg_glue.h"
33 #include "rpc_server/svcctl/srv_svcctl_nt.h"
36 #define DBGC_CLASS DBGC_RPC_SRV
38 struct service_control_op
{
40 SERVICE_CONTROL_OPS
*ops
;
43 /* handle external services */
44 extern SERVICE_CONTROL_OPS rcinit_svc_ops
;
46 /* builtin services (see service_db.c and services/svc_*.c */
47 extern SERVICE_CONTROL_OPS spoolss_svc_ops
;
48 extern SERVICE_CONTROL_OPS netlogon_svc_ops
;
49 extern SERVICE_CONTROL_OPS winreg_svc_ops
;
50 extern SERVICE_CONTROL_OPS wins_svc_ops
;
52 /* make sure this number patches the number of builtin
53 SERVICE_CONTROL_OPS structure listed above */
55 #define SVCCTL_NUM_INTERNAL_SERVICES 4
57 struct service_control_op
*svcctl_ops
;
59 static const struct generic_mapping scm_generic_map
=
60 { SC_MANAGER_READ_ACCESS
, SC_MANAGER_WRITE_ACCESS
, SC_MANAGER_EXECUTE_ACCESS
, SC_MANAGER_ALL_ACCESS
};
61 static const struct generic_mapping svc_generic_map
=
62 { SERVICE_READ_ACCESS
, SERVICE_WRITE_ACCESS
, SERVICE_EXECUTE_ACCESS
, SERVICE_ALL_ACCESS
};
65 /********************************************************************
66 ********************************************************************/
68 bool init_service_op_table( void )
70 const char **service_list
= lp_svcctl_list();
71 int num_services
= SVCCTL_NUM_INTERNAL_SERVICES
+ str_list_length( service_list
);
74 if ( !(svcctl_ops
= TALLOC_ARRAY( NULL
, struct service_control_op
, num_services
+1)) ) {
75 DEBUG(0,("init_service_op_table: talloc() failed!\n"));
79 /* services listed in smb.conf get the rc.init interface */
81 for ( i
=0; service_list
&& service_list
[i
]; i
++ ) {
82 svcctl_ops
[i
].name
= talloc_strdup( svcctl_ops
, service_list
[i
] );
83 svcctl_ops
[i
].ops
= &rcinit_svc_ops
;
86 /* add builtin services */
88 svcctl_ops
[i
].name
= talloc_strdup( svcctl_ops
, "Spooler" );
89 svcctl_ops
[i
].ops
= &spoolss_svc_ops
;
92 svcctl_ops
[i
].name
= talloc_strdup( svcctl_ops
, "NETLOGON" );
93 svcctl_ops
[i
].ops
= &netlogon_svc_ops
;
96 svcctl_ops
[i
].name
= talloc_strdup( svcctl_ops
, "RemoteRegistry" );
97 svcctl_ops
[i
].ops
= &winreg_svc_ops
;
100 svcctl_ops
[i
].name
= talloc_strdup( svcctl_ops
, "WINS" );
101 svcctl_ops
[i
].ops
= &wins_svc_ops
;
104 /* NULL terminate the array */
106 svcctl_ops
[i
].name
= NULL
;
107 svcctl_ops
[i
].ops
= NULL
;
112 bool shutdown_service_op_table(void)
114 TALLOC_FREE(svcctl_ops
);
119 /********************************************************************
120 ********************************************************************/
122 static struct service_control_op
* find_service_by_name( const char *name
)
126 for ( i
=0; svcctl_ops
[i
].name
; i
++ ) {
127 if ( strequal( name
, svcctl_ops
[i
].name
) )
128 return &svcctl_ops
[i
];
133 /********************************************************************
134 ********************************************************************/
136 static NTSTATUS
svcctl_access_check( struct security_descriptor
*sec_desc
, struct security_token
*token
,
137 uint32 access_desired
, uint32
*access_granted
)
139 if ( geteuid() == sec_initial_uid() ) {
140 DEBUG(5,("svcctl_access_check: using root's token\n"));
141 token
= get_root_nt_token();
144 return se_access_check( sec_desc
, token
, access_desired
, access_granted
);
147 /********************************************************************
148 ********************************************************************/
150 static struct security_descriptor
* construct_scm_sd( TALLOC_CTX
*ctx
)
152 struct security_ace ace
[2];
154 struct security_descriptor
*sd
;
155 struct security_acl
*theacl
;
158 /* basic access for Everyone */
160 init_sec_ace(&ace
[i
++], &global_sid_World
,
161 SEC_ACE_TYPE_ACCESS_ALLOWED
, SC_MANAGER_READ_ACCESS
, 0);
163 /* Full Access 'BUILTIN\Administrators' */
165 init_sec_ace(&ace
[i
++], &global_sid_Builtin_Administrators
,
166 SEC_ACE_TYPE_ACCESS_ALLOWED
, SC_MANAGER_ALL_ACCESS
, 0);
169 /* create the security descriptor */
171 if ( !(theacl
= make_sec_acl(ctx
, NT4_ACL_REVISION
, i
, ace
)) )
174 if ( !(sd
= make_sec_desc(ctx
, SECURITY_DESCRIPTOR_REVISION_1
,
175 SEC_DESC_SELF_RELATIVE
, NULL
, NULL
, NULL
,
182 /******************************************************************
183 Find a registry key handle and return a SERVICE_INFO
184 *****************************************************************/
186 static SERVICE_INFO
*find_service_info_by_hnd(struct pipes_struct
*p
,
187 struct policy_handle
*hnd
)
189 SERVICE_INFO
*service_info
= NULL
;
191 if( !find_policy_by_hnd( p
, hnd
, (void **)(void *)&service_info
) ) {
192 DEBUG(2,("find_service_info_by_hnd: handle not found\n"));
199 /******************************************************************
200 *****************************************************************/
202 static WERROR
create_open_service_handle(struct pipes_struct
*p
,
203 struct policy_handle
*handle
,
206 uint32_t access_granted
)
208 SERVICE_INFO
*info
= NULL
;
209 WERROR result
= WERR_OK
;
210 struct service_control_op
*s_op
;
212 if ( !(info
= TALLOC_ZERO_P( NULL
, SERVICE_INFO
)) )
215 /* the Service Manager has a NULL name */
217 info
->type
= SVC_HANDLE_IS_SCM
;
220 case SVC_HANDLE_IS_SCM
:
221 info
->type
= SVC_HANDLE_IS_SCM
;
224 case SVC_HANDLE_IS_DBLOCK
:
225 info
->type
= SVC_HANDLE_IS_DBLOCK
;
228 case SVC_HANDLE_IS_SERVICE
:
229 info
->type
= SVC_HANDLE_IS_SERVICE
;
231 /* lookup the SERVICE_CONTROL_OPS */
233 if ( !(s_op
= find_service_by_name( service
)) ) {
234 result
= WERR_NO_SUCH_SERVICE
;
238 info
->ops
= s_op
->ops
;
240 if ( !(info
->name
= talloc_strdup( info
, s_op
->name
)) ) {
247 result
= WERR_NO_SUCH_SERVICE
;
251 info
->access_granted
= access_granted
;
253 /* store the SERVICE_INFO and create an open handle */
255 if ( !create_policy_hnd( p
, handle
, info
) ) {
256 result
= WERR_ACCESS_DENIED
;
261 if ( !W_ERROR_IS_OK(result
) )
267 /********************************************************************
268 _svcctl_OpenSCManagerW
269 ********************************************************************/
271 WERROR
_svcctl_OpenSCManagerW(struct pipes_struct
*p
,
272 struct svcctl_OpenSCManagerW
*r
)
274 struct security_descriptor
*sec_desc
;
275 uint32 access_granted
= 0;
278 /* perform access checks */
280 if ( !(sec_desc
= construct_scm_sd( p
->mem_ctx
)) )
283 se_map_generic( &r
->in
.access_mask
, &scm_generic_map
);
284 status
= svcctl_access_check( sec_desc
, p
->session_info
->security_token
,
285 r
->in
.access_mask
, &access_granted
);
286 if ( !NT_STATUS_IS_OK(status
) )
287 return ntstatus_to_werror( status
);
289 return create_open_service_handle( p
, r
->out
.handle
, SVC_HANDLE_IS_SCM
, NULL
, access_granted
);
292 /********************************************************************
294 ********************************************************************/
296 WERROR
_svcctl_OpenServiceW(struct pipes_struct
*p
,
297 struct svcctl_OpenServiceW
*r
)
299 struct security_descriptor
*sec_desc
;
300 uint32 access_granted
= 0;
302 const char *service
= NULL
;
304 service
= r
->in
.ServiceName
;
308 DEBUG(5, ("_svcctl_OpenServiceW: Attempting to open Service [%s], \n", service
));
310 /* based on my tests you can open a service if you have a valid scm handle */
312 if ( !find_service_info_by_hnd( p
, r
->in
.scmanager_handle
) )
316 * Perform access checks. Use the system session_info in order to ensure
317 * that we retrieve the security descriptor
319 sec_desc
= svcctl_get_secdesc(p
->mem_ctx
,
321 get_session_info_system(),
323 if (sec_desc
== NULL
) {
324 DEBUG(0, ("_svcctl_OpenServiceW: Failed to get a valid security "
329 se_map_generic( &r
->in
.access_mask
, &svc_generic_map
);
330 status
= svcctl_access_check( sec_desc
, p
->session_info
->security_token
,
331 r
->in
.access_mask
, &access_granted
);
332 if ( !NT_STATUS_IS_OK(status
) )
333 return ntstatus_to_werror( status
);
335 return create_open_service_handle( p
, r
->out
.handle
, SVC_HANDLE_IS_SERVICE
, service
, access_granted
);
338 /********************************************************************
339 _svcctl_CloseServiceHandle
340 ********************************************************************/
342 WERROR
_svcctl_CloseServiceHandle(struct pipes_struct
*p
,
343 struct svcctl_CloseServiceHandle
*r
)
345 if ( !close_policy_hnd( p
, r
->in
.handle
) )
348 ZERO_STRUCTP(r
->out
.handle
);
353 /********************************************************************
354 _svcctl_GetServiceDisplayNameW
355 ********************************************************************/
357 WERROR
_svcctl_GetServiceDisplayNameW(struct pipes_struct
*p
,
358 struct svcctl_GetServiceDisplayNameW
*r
)
361 const char *display_name
;
362 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.handle
);
364 /* can only use an SCM handle here */
366 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_SCM
) )
369 service
= r
->in
.service_name
;
371 display_name
= svcctl_lookup_dispname(p
->mem_ctx
,
379 *r
->out
.display_name
= display_name
;
380 *r
->out
.display_name_length
= strlen(display_name
);
385 /********************************************************************
386 _svcctl_QueryServiceStatus
387 ********************************************************************/
389 WERROR
_svcctl_QueryServiceStatus(struct pipes_struct
*p
,
390 struct svcctl_QueryServiceStatus
*r
)
392 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.handle
);
394 /* perform access checks */
396 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_SERVICE
) )
399 if ( !(info
->access_granted
& SC_RIGHT_SVC_QUERY_STATUS
) )
400 return WERR_ACCESS_DENIED
;
402 /* try the service specific status call */
404 return info
->ops
->service_status( info
->name
, r
->out
.service_status
);
407 /********************************************************************
408 ********************************************************************/
410 static int enumerate_status(TALLOC_CTX
*ctx
,
411 struct messaging_context
*msg_ctx
,
412 struct auth_serversupplied_info
*session_info
,
413 struct ENUM_SERVICE_STATUSW
**status
)
415 int num_services
= 0;
417 struct ENUM_SERVICE_STATUSW
*st
;
418 const char *display_name
;
421 while ( svcctl_ops
[num_services
].name
)
424 if ( !(st
= TALLOC_ARRAY( ctx
, struct ENUM_SERVICE_STATUSW
, num_services
)) ) {
425 DEBUG(0,("enumerate_status: talloc() failed!\n"));
429 for ( i
=0; i
<num_services
; i
++ ) {
430 st
[i
].service_name
= talloc_strdup(st
, svcctl_ops
[i
].name
);
432 display_name
= svcctl_lookup_dispname(ctx
,
436 st
[i
].display_name
= talloc_strdup(st
, display_name
? display_name
: "");
438 svcctl_ops
[i
].ops
->service_status( svcctl_ops
[i
].name
, &st
[i
].status
);
446 /********************************************************************
447 _svcctl_EnumServicesStatusW
448 ********************************************************************/
450 WERROR
_svcctl_EnumServicesStatusW(struct pipes_struct
*p
,
451 struct svcctl_EnumServicesStatusW
*r
)
453 struct ENUM_SERVICE_STATUSW
*services
= NULL
;
456 size_t buffer_size
= 0;
457 WERROR result
= WERR_OK
;
458 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.handle
);
459 DATA_BLOB blob
= data_blob_null
;
461 /* perform access checks */
463 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_SCM
) )
466 if ( !(info
->access_granted
& SC_RIGHT_MGR_ENUMERATE_SERVICE
) ) {
467 return WERR_ACCESS_DENIED
;
470 num_services
= enumerate_status(p
->mem_ctx
,
474 if (num_services
== -1 ) {
478 for ( i
=0; i
<num_services
; i
++ ) {
479 buffer_size
+= ndr_size_ENUM_SERVICE_STATUSW(&services
[i
], 0);
482 buffer_size
+= buffer_size
% 4;
484 if (buffer_size
> r
->in
.offered
) {
486 result
= WERR_MORE_DATA
;
489 if ( W_ERROR_IS_OK(result
) ) {
491 enum ndr_err_code ndr_err
;
492 struct ndr_push
*ndr
;
494 ndr
= ndr_push_init_ctx(p
->mem_ctx
);
496 return WERR_INVALID_PARAM
;
499 ndr_err
= ndr_push_ENUM_SERVICE_STATUSW_array(
500 ndr
, num_services
, services
);
501 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
502 return ntstatus_to_werror(ndr_map_error2ntstatus(ndr_err
));
504 blob
= ndr_push_blob(ndr
);
505 memcpy(r
->out
.service
, blob
.data
, MIN(blob
.length
, r
->in
.offered
));
508 *r
->out
.needed
= (buffer_size
> r
->in
.offered
) ? buffer_size
: r
->in
.offered
;
509 *r
->out
.services_returned
= (uint32
)num_services
;
510 if (r
->out
.resume_handle
) {
511 *r
->out
.resume_handle
= 0;
517 /********************************************************************
518 _svcctl_StartServiceW
519 ********************************************************************/
521 WERROR
_svcctl_StartServiceW(struct pipes_struct
*p
,
522 struct svcctl_StartServiceW
*r
)
524 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.handle
);
526 /* perform access checks */
528 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_SERVICE
) )
531 if ( !(info
->access_granted
& SC_RIGHT_SVC_START
) )
532 return WERR_ACCESS_DENIED
;
534 return info
->ops
->start_service( info
->name
);
537 /********************************************************************
538 _svcctl_ControlService
539 ********************************************************************/
541 WERROR
_svcctl_ControlService(struct pipes_struct
*p
,
542 struct svcctl_ControlService
*r
)
544 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.handle
);
546 /* perform access checks */
548 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_SERVICE
) )
551 switch ( r
->in
.control
) {
552 case SVCCTL_CONTROL_STOP
:
553 if ( !(info
->access_granted
& SC_RIGHT_SVC_STOP
) )
554 return WERR_ACCESS_DENIED
;
556 return info
->ops
->stop_service( info
->name
,
557 r
->out
.service_status
);
559 case SVCCTL_CONTROL_INTERROGATE
:
560 if ( !(info
->access_granted
& SC_RIGHT_SVC_QUERY_STATUS
) )
561 return WERR_ACCESS_DENIED
;
563 return info
->ops
->service_status( info
->name
,
564 r
->out
.service_status
);
566 return WERR_INVALID_PARAM
;
570 /********************************************************************
571 _svcctl_EnumDependentServicesW
572 ********************************************************************/
574 WERROR
_svcctl_EnumDependentServicesW(struct pipes_struct
*p
,
575 struct svcctl_EnumDependentServicesW
*r
)
577 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.service
);
579 /* perform access checks */
581 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_SERVICE
) )
584 if ( !(info
->access_granted
& SC_RIGHT_SVC_ENUMERATE_DEPENDENTS
) )
585 return WERR_ACCESS_DENIED
;
587 switch (r
->in
.state
) {
588 case SERVICE_STATE_ACTIVE
:
589 case SERVICE_STATE_INACTIVE
:
590 case SERVICE_STATE_ALL
:
593 return WERR_INVALID_PARAM
;
596 /* we have to set the outgoing buffer size to the same as the
597 incoming buffer size (even in the case of failure */
598 /* this is done in the autogenerated server already - gd */
600 *r
->out
.needed
= r
->in
.offered
;
602 /* no dependent services...basically a stub function */
603 *r
->out
.services_returned
= 0;
608 /********************************************************************
609 _svcctl_QueryServiceStatusEx
610 ********************************************************************/
612 WERROR
_svcctl_QueryServiceStatusEx(struct pipes_struct
*p
,
613 struct svcctl_QueryServiceStatusEx
*r
)
615 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.handle
);
618 /* perform access checks */
620 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_SERVICE
) )
623 if ( !(info
->access_granted
& SC_RIGHT_SVC_QUERY_STATUS
) )
624 return WERR_ACCESS_DENIED
;
626 /* we have to set the outgoing buffer size to the same as the
627 incoming buffer size (even in the case of failure) */
628 *r
->out
.needed
= r
->in
.offered
;
630 switch ( r
->in
.info_level
) {
631 case SVC_STATUS_PROCESS_INFO
:
633 struct SERVICE_STATUS_PROCESS svc_stat_proc
;
634 enum ndr_err_code ndr_err
;
637 /* Get the status of the service.. */
638 info
->ops
->service_status( info
->name
, &svc_stat_proc
.status
);
639 svc_stat_proc
.process_id
= sys_getpid();
640 svc_stat_proc
.service_flags
= 0x0;
642 ndr_err
= ndr_push_struct_blob(&blob
, p
->mem_ctx
, &svc_stat_proc
,
643 (ndr_push_flags_fn_t
)ndr_push_SERVICE_STATUS_PROCESS
);
644 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
645 return WERR_INVALID_PARAM
;
648 r
->out
.buffer
= blob
.data
;
649 buffer_size
= sizeof(struct SERVICE_STATUS_PROCESS
);
654 return WERR_UNKNOWN_LEVEL
;
658 buffer_size
+= buffer_size
% 4;
659 *r
->out
.needed
= (buffer_size
> r
->in
.offered
) ? buffer_size
: r
->in
.offered
;
661 if (buffer_size
> r
->in
.offered
) {
662 return WERR_INSUFFICIENT_BUFFER
;
668 /********************************************************************
669 ********************************************************************/
671 static WERROR
fill_svc_config(TALLOC_CTX
*mem_ctx
,
672 struct messaging_context
*msg_ctx
,
673 struct auth_serversupplied_info
*session_info
,
675 struct QUERY_SERVICE_CONFIG
*config
)
677 const char *result
= NULL
;
679 /* now fill in the individual values */
681 ZERO_STRUCTP(config
);
683 config
->displayname
= svcctl_lookup_dispname(mem_ctx
,
688 result
= svcctl_get_string_value(mem_ctx
,
693 if (result
!= NULL
) {
694 config
->startname
= result
;
697 result
= svcctl_get_string_value(mem_ctx
,
702 if (result
!= NULL
) {
703 config
->executablepath
= result
;
706 /* a few hard coded values */
707 /* loadordergroup and dependencies are empty */
709 config
->tag_id
= 0x00000000; /* unassigned loadorder group */
710 config
->service_type
= SERVICE_TYPE_WIN32_OWN_PROCESS
;
711 config
->error_control
= SVCCTL_SVC_ERROR_NORMAL
;
713 /* set the start type. NetLogon and WINS are disabled to prevent
714 the client from showing the "Start" button (if of course the services
717 if ( strequal( name
, "NETLOGON" ) && ( lp_servicenumber(name
) == -1 ) )
718 config
->start_type
= SVCCTL_DISABLED
;
719 else if ( strequal( name
, "WINS" ) && ( !lp_wins_support() ))
720 config
->start_type
= SVCCTL_DISABLED
;
722 config
->start_type
= SVCCTL_DEMAND_START
;
727 /********************************************************************
728 _svcctl_QueryServiceConfigW
729 ********************************************************************/
731 WERROR
_svcctl_QueryServiceConfigW(struct pipes_struct
*p
,
732 struct svcctl_QueryServiceConfigW
*r
)
734 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.handle
);
738 /* perform access checks */
740 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_SERVICE
) )
743 if ( !(info
->access_granted
& SC_RIGHT_SVC_QUERY_CONFIG
) )
744 return WERR_ACCESS_DENIED
;
746 /* we have to set the outgoing buffer size to the same as the
747 incoming buffer size (even in the case of failure */
749 *r
->out
.needed
= r
->in
.offered
;
751 wresult
= fill_svc_config(p
->mem_ctx
,
756 if ( !W_ERROR_IS_OK(wresult
) )
759 buffer_size
= ndr_size_QUERY_SERVICE_CONFIG(r
->out
.query
, 0);
760 *r
->out
.needed
= (buffer_size
> r
->in
.offered
) ? buffer_size
: r
->in
.offered
;
762 if (buffer_size
> r
->in
.offered
) {
763 ZERO_STRUCTP(r
->out
.query
);
764 return WERR_INSUFFICIENT_BUFFER
;
770 /********************************************************************
771 _svcctl_QueryServiceConfig2W
772 ********************************************************************/
774 WERROR
_svcctl_QueryServiceConfig2W(struct pipes_struct
*p
,
775 struct svcctl_QueryServiceConfig2W
*r
)
777 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.handle
);
778 uint32_t buffer_size
;
779 DATA_BLOB blob
= data_blob_null
;
781 /* perform access checks */
783 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_SERVICE
) )
786 if ( !(info
->access_granted
& SC_RIGHT_SVC_QUERY_CONFIG
) )
787 return WERR_ACCESS_DENIED
;
789 /* we have to set the outgoing buffer size to the same as the
790 incoming buffer size (even in the case of failure */
791 *r
->out
.needed
= r
->in
.offered
;
793 switch ( r
->in
.info_level
) {
794 case SERVICE_CONFIG_DESCRIPTION
:
796 struct SERVICE_DESCRIPTION desc_buf
;
797 const char *description
;
798 enum ndr_err_code ndr_err
;
800 description
= svcctl_lookup_description(p
->mem_ctx
,
805 desc_buf
.description
= description
;
807 ndr_err
= ndr_push_struct_blob(&blob
, p
->mem_ctx
, &desc_buf
,
808 (ndr_push_flags_fn_t
)ndr_push_SERVICE_DESCRIPTION
);
809 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
810 return WERR_INVALID_PARAM
;
816 case SERVICE_CONFIG_FAILURE_ACTIONS
:
818 struct SERVICE_FAILURE_ACTIONS actions
;
819 enum ndr_err_code ndr_err
;
821 /* nothing to say...just service the request */
823 ZERO_STRUCT( actions
);
825 ndr_err
= ndr_push_struct_blob(&blob
, p
->mem_ctx
, &actions
,
826 (ndr_push_flags_fn_t
)ndr_push_SERVICE_FAILURE_ACTIONS
);
827 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
828 return WERR_INVALID_PARAM
;
836 return WERR_UNKNOWN_LEVEL
;
839 buffer_size
= blob
.length
;
840 buffer_size
+= buffer_size
% 4;
841 *r
->out
.needed
= (buffer_size
> r
->in
.offered
) ? buffer_size
: r
->in
.offered
;
843 if (buffer_size
> r
->in
.offered
)
844 return WERR_INSUFFICIENT_BUFFER
;
846 memcpy(r
->out
.buffer
, blob
.data
, blob
.length
);
851 /********************************************************************
852 _svcctl_LockServiceDatabase
853 ********************************************************************/
855 WERROR
_svcctl_LockServiceDatabase(struct pipes_struct
*p
,
856 struct svcctl_LockServiceDatabase
*r
)
858 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.handle
);
860 /* perform access checks */
862 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_SCM
) )
865 if ( !(info
->access_granted
& SC_RIGHT_MGR_LOCK
) )
866 return WERR_ACCESS_DENIED
;
868 /* Just open a handle. Doesn't actually lock anything */
870 return create_open_service_handle( p
, r
->out
.lock
, SVC_HANDLE_IS_DBLOCK
, NULL
, 0 );
873 /********************************************************************
874 _svcctl_UnlockServiceDatabase
875 ********************************************************************/
877 WERROR
_svcctl_UnlockServiceDatabase(struct pipes_struct
*p
,
878 struct svcctl_UnlockServiceDatabase
*r
)
880 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.lock
);
883 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_DBLOCK
) )
886 return close_policy_hnd( p
, r
->out
.lock
) ? WERR_OK
: WERR_BADFID
;
889 /********************************************************************
890 _svcctl_QueryServiceObjectSecurity
891 ********************************************************************/
893 WERROR
_svcctl_QueryServiceObjectSecurity(struct pipes_struct
*p
,
894 struct svcctl_QueryServiceObjectSecurity
*r
)
896 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.handle
);
897 struct security_descriptor
*sec_desc
;
899 uint8_t *buffer
= NULL
;
903 /* only support the SCM and individual services */
905 if ( !info
|| !(info
->type
& (SVC_HANDLE_IS_SERVICE
|SVC_HANDLE_IS_SCM
)) )
908 /* check access reights (according to MSDN) */
910 if ( !(info
->access_granted
& SEC_STD_READ_CONTROL
) )
911 return WERR_ACCESS_DENIED
;
913 /* TODO: handle something besides SECINFO_DACL */
915 if ( (r
->in
.security_flags
& SECINFO_DACL
) != SECINFO_DACL
)
916 return WERR_INVALID_PARAM
;
918 /* Lookup the security descriptor and marshall it up for a reply */
919 sec_desc
= svcctl_get_secdesc(p
->mem_ctx
,
921 get_session_info_system(),
923 if (sec_desc
== NULL
) {
927 *r
->out
.needed
= ndr_size_security_descriptor(sec_desc
, 0);
929 if ( *r
->out
.needed
> r
->in
.offered
) {
930 return WERR_INSUFFICIENT_BUFFER
;
933 status
= marshall_sec_desc(p
->mem_ctx
, sec_desc
, &buffer
, &len
);
934 if (!NT_STATUS_IS_OK(status
)) {
935 return ntstatus_to_werror(status
);
938 *r
->out
.needed
= len
;
939 r
->out
.buffer
= buffer
;
944 /********************************************************************
945 _svcctl_SetServiceObjectSecurity
946 ********************************************************************/
948 WERROR
_svcctl_SetServiceObjectSecurity(struct pipes_struct
*p
,
949 struct svcctl_SetServiceObjectSecurity
*r
)
951 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.handle
);
952 struct security_descriptor
*sec_desc
= NULL
;
953 uint32 required_access
;
956 if ( !info
|| !(info
->type
& (SVC_HANDLE_IS_SERVICE
|SVC_HANDLE_IS_SCM
)) )
959 /* can't set the security de4scriptor on the ServiceControlManager */
961 if ( info
->type
== SVC_HANDLE_IS_SCM
)
962 return WERR_ACCESS_DENIED
;
964 /* check the access on the open handle */
966 switch ( r
->in
.security_flags
) {
968 required_access
= SEC_STD_WRITE_DAC
;
973 required_access
= SEC_STD_WRITE_OWNER
;
977 return WERR_INVALID_PARAM
;
979 return WERR_INVALID_PARAM
;
982 if ( !(info
->access_granted
& required_access
) )
983 return WERR_ACCESS_DENIED
;
985 /* read the security descfriptor */
987 status
= unmarshall_sec_desc(p
->mem_ctx
,
991 if (!NT_STATUS_IS_OK(status
)) {
992 return ntstatus_to_werror(status
);
995 /* store the new SD */
997 if (!svcctl_set_secdesc(p
->msg_ctx
, p
->session_info
, info
->name
, sec_desc
))
998 return WERR_ACCESS_DENIED
;
1004 WERROR
_svcctl_DeleteService(struct pipes_struct
*p
,
1005 struct svcctl_DeleteService
*r
)
1007 p
->rng_fault_state
= True
;
1008 return WERR_NOT_SUPPORTED
;
1011 WERROR
_svcctl_SetServiceStatus(struct pipes_struct
*p
,
1012 struct svcctl_SetServiceStatus
*r
)
1014 p
->rng_fault_state
= True
;
1015 return WERR_NOT_SUPPORTED
;
1018 WERROR
_svcctl_NotifyBootConfigStatus(struct pipes_struct
*p
,
1019 struct svcctl_NotifyBootConfigStatus
*r
)
1021 p
->rng_fault_state
= True
;
1022 return WERR_NOT_SUPPORTED
;
1025 WERROR
_svcctl_SCSetServiceBitsW(struct pipes_struct
*p
,
1026 struct svcctl_SCSetServiceBitsW
*r
)
1028 p
->rng_fault_state
= True
;
1029 return WERR_NOT_SUPPORTED
;
1032 WERROR
_svcctl_ChangeServiceConfigW(struct pipes_struct
*p
,
1033 struct svcctl_ChangeServiceConfigW
*r
)
1035 p
->rng_fault_state
= True
;
1036 return WERR_NOT_SUPPORTED
;
1039 WERROR
_svcctl_CreateServiceW(struct pipes_struct
*p
,
1040 struct svcctl_CreateServiceW
*r
)
1042 p
->rng_fault_state
= True
;
1043 return WERR_NOT_SUPPORTED
;
1046 WERROR
_svcctl_QueryServiceLockStatusW(struct pipes_struct
*p
,
1047 struct svcctl_QueryServiceLockStatusW
*r
)
1049 p
->rng_fault_state
= True
;
1050 return WERR_NOT_SUPPORTED
;
1053 WERROR
_svcctl_GetServiceKeyNameW(struct pipes_struct
*p
,
1054 struct svcctl_GetServiceKeyNameW
*r
)
1056 p
->rng_fault_state
= True
;
1057 return WERR_NOT_SUPPORTED
;
1060 WERROR
_svcctl_SCSetServiceBitsA(struct pipes_struct
*p
,
1061 struct svcctl_SCSetServiceBitsA
*r
)
1063 p
->rng_fault_state
= True
;
1064 return WERR_NOT_SUPPORTED
;
1067 WERROR
_svcctl_ChangeServiceConfigA(struct pipes_struct
*p
,
1068 struct svcctl_ChangeServiceConfigA
*r
)
1070 p
->rng_fault_state
= True
;
1071 return WERR_NOT_SUPPORTED
;
1074 WERROR
_svcctl_CreateServiceA(struct pipes_struct
*p
,
1075 struct svcctl_CreateServiceA
*r
)
1077 p
->rng_fault_state
= True
;
1078 return WERR_NOT_SUPPORTED
;
1081 WERROR
_svcctl_EnumDependentServicesA(struct pipes_struct
*p
,
1082 struct svcctl_EnumDependentServicesA
*r
)
1084 p
->rng_fault_state
= True
;
1085 return WERR_NOT_SUPPORTED
;
1088 WERROR
_svcctl_EnumServicesStatusA(struct pipes_struct
*p
,
1089 struct svcctl_EnumServicesStatusA
*r
)
1091 p
->rng_fault_state
= True
;
1092 return WERR_NOT_SUPPORTED
;
1095 WERROR
_svcctl_OpenSCManagerA(struct pipes_struct
*p
,
1096 struct svcctl_OpenSCManagerA
*r
)
1098 p
->rng_fault_state
= True
;
1099 return WERR_NOT_SUPPORTED
;
1102 WERROR
_svcctl_OpenServiceA(struct pipes_struct
*p
,
1103 struct svcctl_OpenServiceA
*r
)
1105 p
->rng_fault_state
= True
;
1106 return WERR_NOT_SUPPORTED
;
1109 WERROR
_svcctl_QueryServiceConfigA(struct pipes_struct
*p
,
1110 struct svcctl_QueryServiceConfigA
*r
)
1112 p
->rng_fault_state
= True
;
1113 return WERR_NOT_SUPPORTED
;
1116 WERROR
_svcctl_QueryServiceLockStatusA(struct pipes_struct
*p
,
1117 struct svcctl_QueryServiceLockStatusA
*r
)
1119 p
->rng_fault_state
= True
;
1120 return WERR_NOT_SUPPORTED
;
1123 WERROR
_svcctl_StartServiceA(struct pipes_struct
*p
,
1124 struct svcctl_StartServiceA
*r
)
1126 p
->rng_fault_state
= True
;
1127 return WERR_NOT_SUPPORTED
;
1130 WERROR
_svcctl_GetServiceDisplayNameA(struct pipes_struct
*p
,
1131 struct svcctl_GetServiceDisplayNameA
*r
)
1133 p
->rng_fault_state
= True
;
1134 return WERR_NOT_SUPPORTED
;
1137 WERROR
_svcctl_GetServiceKeyNameA(struct pipes_struct
*p
,
1138 struct svcctl_GetServiceKeyNameA
*r
)
1140 p
->rng_fault_state
= True
;
1141 return WERR_NOT_SUPPORTED
;
1144 WERROR
_svcctl_GetCurrentGroupeStateW(struct pipes_struct
*p
,
1145 struct svcctl_GetCurrentGroupeStateW
*r
)
1147 p
->rng_fault_state
= True
;
1148 return WERR_NOT_SUPPORTED
;
1151 WERROR
_svcctl_EnumServiceGroupW(struct pipes_struct
*p
,
1152 struct svcctl_EnumServiceGroupW
*r
)
1154 p
->rng_fault_state
= True
;
1155 return WERR_NOT_SUPPORTED
;
1158 WERROR
_svcctl_ChangeServiceConfig2A(struct pipes_struct
*p
,
1159 struct svcctl_ChangeServiceConfig2A
*r
)
1161 p
->rng_fault_state
= True
;
1162 return WERR_NOT_SUPPORTED
;
1165 WERROR
_svcctl_ChangeServiceConfig2W(struct pipes_struct
*p
,
1166 struct svcctl_ChangeServiceConfig2W
*r
)
1168 p
->rng_fault_state
= True
;
1169 return WERR_NOT_SUPPORTED
;
1172 WERROR
_svcctl_QueryServiceConfig2A(struct pipes_struct
*p
,
1173 struct svcctl_QueryServiceConfig2A
*r
)
1175 p
->rng_fault_state
= True
;
1176 return WERR_NOT_SUPPORTED
;
1179 WERROR
_EnumServicesStatusExA(struct pipes_struct
*p
,
1180 struct EnumServicesStatusExA
*r
)
1182 p
->rng_fault_state
= True
;
1183 return WERR_NOT_SUPPORTED
;
1186 WERROR
_EnumServicesStatusExW(struct pipes_struct
*p
,
1187 struct EnumServicesStatusExW
*r
)
1189 p
->rng_fault_state
= True
;
1190 return WERR_NOT_SUPPORTED
;
1193 WERROR
_svcctl_SCSendTSMessage(struct pipes_struct
*p
,
1194 struct svcctl_SCSendTSMessage
*r
)
1196 p
->rng_fault_state
= True
;
1197 return WERR_NOT_SUPPORTED
;