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/>.
26 #include "system/passwd.h" /* uid_wrapper */
28 #include "../librpc/gen_ndr/srv_svcctl.h"
29 #include "../libcli/security/security.h"
30 #include "../librpc/gen_ndr/ndr_security.h"
31 #include "services/services.h"
32 #include "services/svc_winreg_glue.h"
34 #include "rpc_server/svcctl/srv_svcctl_nt.h"
37 #define DBGC_CLASS DBGC_RPC_SRV
39 struct service_control_op
{
41 SERVICE_CONTROL_OPS
*ops
;
44 /* handle external services */
45 extern SERVICE_CONTROL_OPS rcinit_svc_ops
;
47 /* builtin services (see service_db.c and services/svc_*.c */
48 extern SERVICE_CONTROL_OPS spoolss_svc_ops
;
49 extern SERVICE_CONTROL_OPS netlogon_svc_ops
;
50 extern SERVICE_CONTROL_OPS winreg_svc_ops
;
51 extern SERVICE_CONTROL_OPS wins_svc_ops
;
53 /* make sure this number patches the number of builtin
54 SERVICE_CONTROL_OPS structure listed above */
56 #define SVCCTL_NUM_INTERNAL_SERVICES 4
58 struct service_control_op
*svcctl_ops
;
60 static const struct generic_mapping scm_generic_map
=
61 { SC_MANAGER_READ_ACCESS
, SC_MANAGER_WRITE_ACCESS
, SC_MANAGER_EXECUTE_ACCESS
, SC_MANAGER_ALL_ACCESS
};
62 static const struct generic_mapping svc_generic_map
=
63 { SERVICE_READ_ACCESS
, SERVICE_WRITE_ACCESS
, SERVICE_EXECUTE_ACCESS
, SERVICE_ALL_ACCESS
};
66 /********************************************************************
67 ********************************************************************/
69 bool init_service_op_table( void )
71 const char **service_list
= lp_svcctl_list();
72 int num_services
= SVCCTL_NUM_INTERNAL_SERVICES
+ str_list_length( service_list
);
75 if ( !(svcctl_ops
= talloc_array( NULL
, struct service_control_op
, num_services
+1)) ) {
76 DEBUG(0,("init_service_op_table: talloc() failed!\n"));
80 /* services listed in smb.conf get the rc.init interface */
82 for ( i
=0; service_list
&& service_list
[i
]; i
++ ) {
83 svcctl_ops
[i
].name
= talloc_strdup( svcctl_ops
, service_list
[i
] );
84 svcctl_ops
[i
].ops
= &rcinit_svc_ops
;
87 /* add builtin services */
89 svcctl_ops
[i
].name
= talloc_strdup( svcctl_ops
, "Spooler" );
90 svcctl_ops
[i
].ops
= &spoolss_svc_ops
;
93 svcctl_ops
[i
].name
= talloc_strdup( svcctl_ops
, "NETLOGON" );
94 svcctl_ops
[i
].ops
= &netlogon_svc_ops
;
97 svcctl_ops
[i
].name
= talloc_strdup( svcctl_ops
, "RemoteRegistry" );
98 svcctl_ops
[i
].ops
= &winreg_svc_ops
;
101 svcctl_ops
[i
].name
= talloc_strdup( svcctl_ops
, "WINS" );
102 svcctl_ops
[i
].ops
= &wins_svc_ops
;
105 /* NULL terminate the array */
107 svcctl_ops
[i
].name
= NULL
;
108 svcctl_ops
[i
].ops
= NULL
;
113 bool shutdown_service_op_table(void)
115 TALLOC_FREE(svcctl_ops
);
120 /********************************************************************
121 ********************************************************************/
123 static struct service_control_op
* find_service_by_name( const char *name
)
127 for ( i
=0; svcctl_ops
[i
].name
; i
++ ) {
128 if ( strequal( name
, svcctl_ops
[i
].name
) )
129 return &svcctl_ops
[i
];
134 /********************************************************************
135 ********************************************************************/
137 static NTSTATUS
svcctl_access_check( struct security_descriptor
*sec_desc
, struct security_token
*token
,
138 uint32 access_desired
, uint32
*access_granted
)
140 if ( geteuid() == sec_initial_uid() ) {
141 DEBUG(5,("svcctl_access_check: using root's token\n"));
142 token
= get_root_nt_token();
145 return se_access_check( sec_desc
, token
, access_desired
, access_granted
);
148 /********************************************************************
149 ********************************************************************/
151 static struct security_descriptor
* construct_scm_sd( TALLOC_CTX
*ctx
)
153 struct security_ace ace
[2];
155 struct security_descriptor
*sd
;
156 struct security_acl
*theacl
;
159 /* basic access for Everyone */
161 init_sec_ace(&ace
[i
++], &global_sid_World
,
162 SEC_ACE_TYPE_ACCESS_ALLOWED
, SC_MANAGER_READ_ACCESS
, 0);
164 /* Full Access 'BUILTIN\Administrators' */
166 init_sec_ace(&ace
[i
++], &global_sid_Builtin_Administrators
,
167 SEC_ACE_TYPE_ACCESS_ALLOWED
, SC_MANAGER_ALL_ACCESS
, 0);
170 /* create the security descriptor */
172 if ( !(theacl
= make_sec_acl(ctx
, NT4_ACL_REVISION
, i
, ace
)) )
175 if ( !(sd
= make_sec_desc(ctx
, SECURITY_DESCRIPTOR_REVISION_1
,
176 SEC_DESC_SELF_RELATIVE
, NULL
, NULL
, NULL
,
183 /******************************************************************
184 Find a registry key handle and return a SERVICE_INFO
185 *****************************************************************/
187 static SERVICE_INFO
*find_service_info_by_hnd(struct pipes_struct
*p
,
188 struct policy_handle
*hnd
)
190 SERVICE_INFO
*service_info
= NULL
;
192 if( !find_policy_by_hnd( p
, hnd
, (void **)(void *)&service_info
) ) {
193 DEBUG(2,("find_service_info_by_hnd: handle not found\n"));
200 /******************************************************************
201 *****************************************************************/
203 static WERROR
create_open_service_handle(struct pipes_struct
*p
,
204 struct policy_handle
*handle
,
207 uint32_t access_granted
)
209 SERVICE_INFO
*info
= NULL
;
210 WERROR result
= WERR_OK
;
211 struct service_control_op
*s_op
;
213 if ( !(info
= talloc_zero( NULL
, SERVICE_INFO
)) )
216 /* the Service Manager has a NULL name */
218 info
->type
= SVC_HANDLE_IS_SCM
;
221 case SVC_HANDLE_IS_SCM
:
222 info
->type
= SVC_HANDLE_IS_SCM
;
225 case SVC_HANDLE_IS_DBLOCK
:
226 info
->type
= SVC_HANDLE_IS_DBLOCK
;
229 case SVC_HANDLE_IS_SERVICE
:
230 info
->type
= SVC_HANDLE_IS_SERVICE
;
232 /* lookup the SERVICE_CONTROL_OPS */
234 if ( !(s_op
= find_service_by_name( service
)) ) {
235 result
= WERR_NO_SUCH_SERVICE
;
239 info
->ops
= s_op
->ops
;
241 if ( !(info
->name
= talloc_strdup( info
, s_op
->name
)) ) {
248 result
= WERR_NO_SUCH_SERVICE
;
252 info
->access_granted
= access_granted
;
254 /* store the SERVICE_INFO and create an open handle */
256 if ( !create_policy_hnd( p
, handle
, info
) ) {
257 result
= WERR_ACCESS_DENIED
;
262 if ( !W_ERROR_IS_OK(result
) )
268 /********************************************************************
269 _svcctl_OpenSCManagerW
270 ********************************************************************/
272 WERROR
_svcctl_OpenSCManagerW(struct pipes_struct
*p
,
273 struct svcctl_OpenSCManagerW
*r
)
275 struct security_descriptor
*sec_desc
;
276 uint32 access_granted
= 0;
279 /* perform access checks */
281 if ( !(sec_desc
= construct_scm_sd( p
->mem_ctx
)) )
284 se_map_generic( &r
->in
.access_mask
, &scm_generic_map
);
285 status
= svcctl_access_check( sec_desc
, p
->session_info
->security_token
,
286 r
->in
.access_mask
, &access_granted
);
287 if ( !NT_STATUS_IS_OK(status
) )
288 return ntstatus_to_werror( status
);
290 return create_open_service_handle( p
, r
->out
.handle
, SVC_HANDLE_IS_SCM
, NULL
, access_granted
);
293 /********************************************************************
295 ********************************************************************/
297 WERROR
_svcctl_OpenServiceW(struct pipes_struct
*p
,
298 struct svcctl_OpenServiceW
*r
)
300 struct security_descriptor
*sec_desc
;
301 uint32 access_granted
= 0;
303 const char *service
= NULL
;
305 service
= r
->in
.ServiceName
;
309 DEBUG(5, ("_svcctl_OpenServiceW: Attempting to open Service [%s], \n", service
));
311 /* based on my tests you can open a service if you have a valid scm handle */
313 if ( !find_service_info_by_hnd( p
, r
->in
.scmanager_handle
) )
317 * Perform access checks. Use the system session_info in order to ensure
318 * that we retrieve the security descriptor
320 sec_desc
= svcctl_get_secdesc(p
->mem_ctx
,
322 get_session_info_system(),
324 if (sec_desc
== NULL
) {
325 DEBUG(0, ("_svcctl_OpenServiceW: Failed to get a valid security "
330 se_map_generic( &r
->in
.access_mask
, &svc_generic_map
);
331 status
= svcctl_access_check( sec_desc
, p
->session_info
->security_token
,
332 r
->in
.access_mask
, &access_granted
);
333 if ( !NT_STATUS_IS_OK(status
) )
334 return ntstatus_to_werror( status
);
336 return create_open_service_handle( p
, r
->out
.handle
, SVC_HANDLE_IS_SERVICE
, service
, access_granted
);
339 /********************************************************************
340 _svcctl_CloseServiceHandle
341 ********************************************************************/
343 WERROR
_svcctl_CloseServiceHandle(struct pipes_struct
*p
,
344 struct svcctl_CloseServiceHandle
*r
)
346 if ( !close_policy_hnd( p
, r
->in
.handle
) )
349 ZERO_STRUCTP(r
->out
.handle
);
354 /********************************************************************
355 _svcctl_GetServiceDisplayNameW
356 ********************************************************************/
358 WERROR
_svcctl_GetServiceDisplayNameW(struct pipes_struct
*p
,
359 struct svcctl_GetServiceDisplayNameW
*r
)
362 const char *display_name
;
363 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.handle
);
365 /* can only use an SCM handle here */
367 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_SCM
) )
370 service
= r
->in
.service_name
;
372 display_name
= svcctl_lookup_dispname(p
->mem_ctx
,
380 *r
->out
.display_name
= display_name
;
381 *r
->out
.display_name_length
= strlen(display_name
);
386 /********************************************************************
387 _svcctl_QueryServiceStatus
388 ********************************************************************/
390 WERROR
_svcctl_QueryServiceStatus(struct pipes_struct
*p
,
391 struct svcctl_QueryServiceStatus
*r
)
393 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.handle
);
395 /* perform access checks */
397 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_SERVICE
) )
400 if ( !(info
->access_granted
& SC_RIGHT_SVC_QUERY_STATUS
) )
401 return WERR_ACCESS_DENIED
;
403 /* try the service specific status call */
405 return info
->ops
->service_status( info
->name
, r
->out
.service_status
);
408 /********************************************************************
409 ********************************************************************/
411 static int enumerate_status(TALLOC_CTX
*ctx
,
412 struct messaging_context
*msg_ctx
,
413 struct auth_session_info
*session_info
,
414 struct ENUM_SERVICE_STATUSW
**status
)
416 int num_services
= 0;
418 struct ENUM_SERVICE_STATUSW
*st
;
419 const char *display_name
;
422 while ( svcctl_ops
[num_services
].name
)
425 if ( !(st
= talloc_array( ctx
, struct ENUM_SERVICE_STATUSW
, num_services
)) ) {
426 DEBUG(0,("enumerate_status: talloc() failed!\n"));
430 for ( i
=0; i
<num_services
; i
++ ) {
431 st
[i
].service_name
= talloc_strdup(st
, svcctl_ops
[i
].name
);
433 display_name
= svcctl_lookup_dispname(ctx
,
437 st
[i
].display_name
= talloc_strdup(st
, display_name
? display_name
: "");
439 svcctl_ops
[i
].ops
->service_status( svcctl_ops
[i
].name
, &st
[i
].status
);
447 /********************************************************************
448 _svcctl_EnumServicesStatusW
449 ********************************************************************/
451 WERROR
_svcctl_EnumServicesStatusW(struct pipes_struct
*p
,
452 struct svcctl_EnumServicesStatusW
*r
)
454 struct ENUM_SERVICE_STATUSW
*services
= NULL
;
457 size_t buffer_size
= 0;
458 WERROR result
= WERR_OK
;
459 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.handle
);
460 DATA_BLOB blob
= data_blob_null
;
462 /* perform access checks */
464 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_SCM
) )
467 if ( !(info
->access_granted
& SC_RIGHT_MGR_ENUMERATE_SERVICE
) ) {
468 return WERR_ACCESS_DENIED
;
471 num_services
= enumerate_status(p
->mem_ctx
,
475 if (num_services
== -1 ) {
479 for ( i
=0; i
<num_services
; i
++ ) {
480 buffer_size
+= ndr_size_ENUM_SERVICE_STATUSW(&services
[i
], 0);
483 buffer_size
+= buffer_size
% 4;
485 if (buffer_size
> r
->in
.offered
) {
487 result
= WERR_MORE_DATA
;
490 if ( W_ERROR_IS_OK(result
) ) {
492 enum ndr_err_code ndr_err
;
493 struct ndr_push
*ndr
;
495 ndr
= ndr_push_init_ctx(p
->mem_ctx
);
497 return WERR_INVALID_PARAM
;
500 ndr_err
= ndr_push_ENUM_SERVICE_STATUSW_array(
501 ndr
, num_services
, services
);
502 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
503 return ntstatus_to_werror(ndr_map_error2ntstatus(ndr_err
));
505 blob
= ndr_push_blob(ndr
);
506 memcpy(r
->out
.service
, blob
.data
, MIN(blob
.length
, r
->in
.offered
));
509 *r
->out
.needed
= (buffer_size
> r
->in
.offered
) ? buffer_size
: r
->in
.offered
;
510 *r
->out
.services_returned
= (uint32
)num_services
;
511 if (r
->out
.resume_handle
) {
512 *r
->out
.resume_handle
= 0;
518 /********************************************************************
519 _svcctl_StartServiceW
520 ********************************************************************/
522 WERROR
_svcctl_StartServiceW(struct pipes_struct
*p
,
523 struct svcctl_StartServiceW
*r
)
525 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.handle
);
527 /* perform access checks */
529 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_SERVICE
) )
532 if ( !(info
->access_granted
& SC_RIGHT_SVC_START
) )
533 return WERR_ACCESS_DENIED
;
535 return info
->ops
->start_service( info
->name
);
538 /********************************************************************
539 _svcctl_ControlService
540 ********************************************************************/
542 WERROR
_svcctl_ControlService(struct pipes_struct
*p
,
543 struct svcctl_ControlService
*r
)
545 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.handle
);
547 /* perform access checks */
549 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_SERVICE
) )
552 switch ( r
->in
.control
) {
553 case SVCCTL_CONTROL_STOP
:
554 if ( !(info
->access_granted
& SC_RIGHT_SVC_STOP
) )
555 return WERR_ACCESS_DENIED
;
557 return info
->ops
->stop_service( info
->name
,
558 r
->out
.service_status
);
560 case SVCCTL_CONTROL_INTERROGATE
:
561 if ( !(info
->access_granted
& SC_RIGHT_SVC_QUERY_STATUS
) )
562 return WERR_ACCESS_DENIED
;
564 return info
->ops
->service_status( info
->name
,
565 r
->out
.service_status
);
567 return WERR_INVALID_PARAM
;
571 /********************************************************************
572 _svcctl_EnumDependentServicesW
573 ********************************************************************/
575 WERROR
_svcctl_EnumDependentServicesW(struct pipes_struct
*p
,
576 struct svcctl_EnumDependentServicesW
*r
)
578 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.service
);
580 /* perform access checks */
582 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_SERVICE
) )
585 if ( !(info
->access_granted
& SC_RIGHT_SVC_ENUMERATE_DEPENDENTS
) )
586 return WERR_ACCESS_DENIED
;
588 switch (r
->in
.state
) {
589 case SERVICE_STATE_ACTIVE
:
590 case SERVICE_STATE_INACTIVE
:
591 case SERVICE_STATE_ALL
:
594 return WERR_INVALID_PARAM
;
597 /* we have to set the outgoing buffer size to the same as the
598 incoming buffer size (even in the case of failure */
599 /* this is done in the autogenerated server already - gd */
601 *r
->out
.needed
= r
->in
.offered
;
603 /* no dependent services...basically a stub function */
604 *r
->out
.services_returned
= 0;
609 /********************************************************************
610 _svcctl_QueryServiceStatusEx
611 ********************************************************************/
613 WERROR
_svcctl_QueryServiceStatusEx(struct pipes_struct
*p
,
614 struct svcctl_QueryServiceStatusEx
*r
)
616 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.handle
);
619 /* perform access checks */
621 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_SERVICE
) )
624 if ( !(info
->access_granted
& SC_RIGHT_SVC_QUERY_STATUS
) )
625 return WERR_ACCESS_DENIED
;
627 /* we have to set the outgoing buffer size to the same as the
628 incoming buffer size (even in the case of failure) */
629 *r
->out
.needed
= r
->in
.offered
;
631 switch ( r
->in
.info_level
) {
632 case SVC_STATUS_PROCESS_INFO
:
634 struct SERVICE_STATUS_PROCESS svc_stat_proc
;
635 enum ndr_err_code ndr_err
;
638 /* Get the status of the service.. */
639 info
->ops
->service_status( info
->name
, &svc_stat_proc
.status
);
640 svc_stat_proc
.process_id
= getpid();
641 svc_stat_proc
.service_flags
= 0x0;
643 ndr_err
= ndr_push_struct_blob(&blob
, p
->mem_ctx
, &svc_stat_proc
,
644 (ndr_push_flags_fn_t
)ndr_push_SERVICE_STATUS_PROCESS
);
645 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
646 return WERR_INVALID_PARAM
;
649 r
->out
.buffer
= blob
.data
;
650 buffer_size
= sizeof(struct SERVICE_STATUS_PROCESS
);
655 return WERR_UNKNOWN_LEVEL
;
659 buffer_size
+= buffer_size
% 4;
660 *r
->out
.needed
= (buffer_size
> r
->in
.offered
) ? buffer_size
: r
->in
.offered
;
662 if (buffer_size
> r
->in
.offered
) {
663 return WERR_INSUFFICIENT_BUFFER
;
669 /********************************************************************
670 ********************************************************************/
672 static WERROR
fill_svc_config(TALLOC_CTX
*mem_ctx
,
673 struct messaging_context
*msg_ctx
,
674 struct auth_session_info
*session_info
,
676 struct QUERY_SERVICE_CONFIG
*config
)
678 const char *result
= NULL
;
680 /* now fill in the individual values */
682 ZERO_STRUCTP(config
);
684 config
->displayname
= svcctl_lookup_dispname(mem_ctx
,
689 result
= svcctl_get_string_value(mem_ctx
,
694 if (result
!= NULL
) {
695 config
->startname
= result
;
698 result
= svcctl_get_string_value(mem_ctx
,
703 if (result
!= NULL
) {
704 config
->executablepath
= result
;
707 /* a few hard coded values */
708 /* loadordergroup and dependencies are empty */
710 config
->tag_id
= 0x00000000; /* unassigned loadorder group */
711 config
->service_type
= SERVICE_TYPE_WIN32_OWN_PROCESS
;
712 config
->error_control
= SVCCTL_SVC_ERROR_NORMAL
;
714 /* set the start type. NetLogon and WINS are disabled to prevent
715 the client from showing the "Start" button (if of course the services
718 if ( strequal( name
, "NETLOGON" ) && ( lp_servicenumber(name
) == -1 ) )
719 config
->start_type
= SVCCTL_DISABLED
;
720 else if ( strequal( name
, "WINS" ) && ( !lp_we_are_a_wins_server() ))
721 config
->start_type
= SVCCTL_DISABLED
;
723 config
->start_type
= SVCCTL_DEMAND_START
;
728 /********************************************************************
729 _svcctl_QueryServiceConfigW
730 ********************************************************************/
732 WERROR
_svcctl_QueryServiceConfigW(struct pipes_struct
*p
,
733 struct svcctl_QueryServiceConfigW
*r
)
735 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.handle
);
739 /* perform access checks */
741 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_SERVICE
) )
744 if ( !(info
->access_granted
& SC_RIGHT_SVC_QUERY_CONFIG
) )
745 return WERR_ACCESS_DENIED
;
747 /* we have to set the outgoing buffer size to the same as the
748 incoming buffer size (even in the case of failure */
750 *r
->out
.needed
= r
->in
.offered
;
752 wresult
= fill_svc_config(p
->mem_ctx
,
757 if ( !W_ERROR_IS_OK(wresult
) )
760 buffer_size
= ndr_size_QUERY_SERVICE_CONFIG(r
->out
.query
, 0);
761 *r
->out
.needed
= (buffer_size
> r
->in
.offered
) ? buffer_size
: r
->in
.offered
;
763 if (buffer_size
> r
->in
.offered
) {
764 ZERO_STRUCTP(r
->out
.query
);
765 return WERR_INSUFFICIENT_BUFFER
;
771 /********************************************************************
772 _svcctl_QueryServiceConfig2W
773 ********************************************************************/
775 WERROR
_svcctl_QueryServiceConfig2W(struct pipes_struct
*p
,
776 struct svcctl_QueryServiceConfig2W
*r
)
778 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.handle
);
779 uint32_t buffer_size
;
780 DATA_BLOB blob
= data_blob_null
;
782 /* perform access checks */
784 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_SERVICE
) )
787 if ( !(info
->access_granted
& SC_RIGHT_SVC_QUERY_CONFIG
) )
788 return WERR_ACCESS_DENIED
;
790 /* we have to set the outgoing buffer size to the same as the
791 incoming buffer size (even in the case of failure */
792 *r
->out
.needed
= r
->in
.offered
;
794 switch ( r
->in
.info_level
) {
795 case SERVICE_CONFIG_DESCRIPTION
:
797 struct SERVICE_DESCRIPTION desc_buf
;
798 const char *description
;
799 enum ndr_err_code ndr_err
;
801 description
= svcctl_lookup_description(p
->mem_ctx
,
806 desc_buf
.description
= description
;
808 ndr_err
= ndr_push_struct_blob(&blob
, p
->mem_ctx
, &desc_buf
,
809 (ndr_push_flags_fn_t
)ndr_push_SERVICE_DESCRIPTION
);
810 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
811 return WERR_INVALID_PARAM
;
817 case SERVICE_CONFIG_FAILURE_ACTIONS
:
819 struct SERVICE_FAILURE_ACTIONS actions
;
820 enum ndr_err_code ndr_err
;
822 /* nothing to say...just service the request */
824 ZERO_STRUCT( actions
);
826 ndr_err
= ndr_push_struct_blob(&blob
, p
->mem_ctx
, &actions
,
827 (ndr_push_flags_fn_t
)ndr_push_SERVICE_FAILURE_ACTIONS
);
828 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
829 return WERR_INVALID_PARAM
;
837 return WERR_UNKNOWN_LEVEL
;
840 buffer_size
= blob
.length
;
841 buffer_size
+= buffer_size
% 4;
842 *r
->out
.needed
= (buffer_size
> r
->in
.offered
) ? buffer_size
: r
->in
.offered
;
844 if (buffer_size
> r
->in
.offered
)
845 return WERR_INSUFFICIENT_BUFFER
;
847 memcpy(r
->out
.buffer
, blob
.data
, blob
.length
);
852 /********************************************************************
853 _svcctl_LockServiceDatabase
854 ********************************************************************/
856 WERROR
_svcctl_LockServiceDatabase(struct pipes_struct
*p
,
857 struct svcctl_LockServiceDatabase
*r
)
859 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.handle
);
861 /* perform access checks */
863 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_SCM
) )
866 if ( !(info
->access_granted
& SC_RIGHT_MGR_LOCK
) )
867 return WERR_ACCESS_DENIED
;
869 /* Just open a handle. Doesn't actually lock anything */
871 return create_open_service_handle( p
, r
->out
.lock
, SVC_HANDLE_IS_DBLOCK
, NULL
, 0 );
874 /********************************************************************
875 _svcctl_UnlockServiceDatabase
876 ********************************************************************/
878 WERROR
_svcctl_UnlockServiceDatabase(struct pipes_struct
*p
,
879 struct svcctl_UnlockServiceDatabase
*r
)
881 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.lock
);
884 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_DBLOCK
) )
887 return close_policy_hnd( p
, r
->out
.lock
) ? WERR_OK
: WERR_BADFID
;
890 /********************************************************************
891 _svcctl_QueryServiceObjectSecurity
892 ********************************************************************/
894 WERROR
_svcctl_QueryServiceObjectSecurity(struct pipes_struct
*p
,
895 struct svcctl_QueryServiceObjectSecurity
*r
)
897 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.handle
);
898 struct security_descriptor
*sec_desc
;
900 uint8_t *buffer
= NULL
;
904 /* only support the SCM and individual services */
906 if ( !info
|| !(info
->type
& (SVC_HANDLE_IS_SERVICE
|SVC_HANDLE_IS_SCM
)) )
909 /* check access reights (according to MSDN) */
911 if ( !(info
->access_granted
& SEC_STD_READ_CONTROL
) )
912 return WERR_ACCESS_DENIED
;
914 /* TODO: handle something besides SECINFO_DACL */
916 if ( (r
->in
.security_flags
& SECINFO_DACL
) != SECINFO_DACL
)
917 return WERR_INVALID_PARAM
;
919 /* Lookup the security descriptor and marshall it up for a reply */
920 sec_desc
= svcctl_get_secdesc(p
->mem_ctx
,
922 get_session_info_system(),
924 if (sec_desc
== NULL
) {
928 *r
->out
.needed
= ndr_size_security_descriptor(sec_desc
, 0);
930 if ( *r
->out
.needed
> r
->in
.offered
) {
931 return WERR_INSUFFICIENT_BUFFER
;
934 status
= marshall_sec_desc(p
->mem_ctx
, sec_desc
, &buffer
, &len
);
935 if (!NT_STATUS_IS_OK(status
)) {
936 return ntstatus_to_werror(status
);
939 *r
->out
.needed
= len
;
940 memcpy(r
->out
.buffer
, buffer
, len
);
945 /********************************************************************
946 _svcctl_SetServiceObjectSecurity
947 ********************************************************************/
949 WERROR
_svcctl_SetServiceObjectSecurity(struct pipes_struct
*p
,
950 struct svcctl_SetServiceObjectSecurity
*r
)
952 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.handle
);
953 struct security_descriptor
*sec_desc
= NULL
;
954 uint32 required_access
;
957 if ( !info
|| !(info
->type
& (SVC_HANDLE_IS_SERVICE
|SVC_HANDLE_IS_SCM
)) )
960 /* can't set the security de4scriptor on the ServiceControlManager */
962 if ( info
->type
== SVC_HANDLE_IS_SCM
)
963 return WERR_ACCESS_DENIED
;
965 /* check the access on the open handle */
967 switch ( r
->in
.security_flags
) {
969 required_access
= SEC_STD_WRITE_DAC
;
974 required_access
= SEC_STD_WRITE_OWNER
;
978 return WERR_INVALID_PARAM
;
980 return WERR_INVALID_PARAM
;
983 if ( !(info
->access_granted
& required_access
) )
984 return WERR_ACCESS_DENIED
;
986 /* read the security descfriptor */
988 status
= unmarshall_sec_desc(p
->mem_ctx
,
992 if (!NT_STATUS_IS_OK(status
)) {
993 return ntstatus_to_werror(status
);
996 /* store the new SD */
998 if (!svcctl_set_secdesc(p
->msg_ctx
, p
->session_info
, info
->name
, sec_desc
))
999 return WERR_ACCESS_DENIED
;
1005 WERROR
_svcctl_DeleteService(struct pipes_struct
*p
,
1006 struct svcctl_DeleteService
*r
)
1008 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1009 return WERR_NOT_SUPPORTED
;
1012 WERROR
_svcctl_SetServiceStatus(struct pipes_struct
*p
,
1013 struct svcctl_SetServiceStatus
*r
)
1015 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1016 return WERR_NOT_SUPPORTED
;
1019 WERROR
_svcctl_NotifyBootConfigStatus(struct pipes_struct
*p
,
1020 struct svcctl_NotifyBootConfigStatus
*r
)
1022 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1023 return WERR_NOT_SUPPORTED
;
1026 WERROR
_svcctl_SCSetServiceBitsW(struct pipes_struct
*p
,
1027 struct svcctl_SCSetServiceBitsW
*r
)
1029 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1030 return WERR_NOT_SUPPORTED
;
1033 WERROR
_svcctl_ChangeServiceConfigW(struct pipes_struct
*p
,
1034 struct svcctl_ChangeServiceConfigW
*r
)
1036 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1037 return WERR_NOT_SUPPORTED
;
1040 WERROR
_svcctl_CreateServiceW(struct pipes_struct
*p
,
1041 struct svcctl_CreateServiceW
*r
)
1043 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1044 return WERR_NOT_SUPPORTED
;
1047 WERROR
_svcctl_QueryServiceLockStatusW(struct pipes_struct
*p
,
1048 struct svcctl_QueryServiceLockStatusW
*r
)
1050 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1051 return WERR_NOT_SUPPORTED
;
1054 WERROR
_svcctl_GetServiceKeyNameW(struct pipes_struct
*p
,
1055 struct svcctl_GetServiceKeyNameW
*r
)
1057 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1058 return WERR_NOT_SUPPORTED
;
1061 WERROR
_svcctl_SCSetServiceBitsA(struct pipes_struct
*p
,
1062 struct svcctl_SCSetServiceBitsA
*r
)
1064 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1065 return WERR_NOT_SUPPORTED
;
1068 WERROR
_svcctl_ChangeServiceConfigA(struct pipes_struct
*p
,
1069 struct svcctl_ChangeServiceConfigA
*r
)
1071 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1072 return WERR_NOT_SUPPORTED
;
1075 WERROR
_svcctl_CreateServiceA(struct pipes_struct
*p
,
1076 struct svcctl_CreateServiceA
*r
)
1078 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1079 return WERR_NOT_SUPPORTED
;
1082 WERROR
_svcctl_EnumDependentServicesA(struct pipes_struct
*p
,
1083 struct svcctl_EnumDependentServicesA
*r
)
1085 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1086 return WERR_NOT_SUPPORTED
;
1089 WERROR
_svcctl_EnumServicesStatusA(struct pipes_struct
*p
,
1090 struct svcctl_EnumServicesStatusA
*r
)
1092 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1093 return WERR_NOT_SUPPORTED
;
1096 WERROR
_svcctl_OpenSCManagerA(struct pipes_struct
*p
,
1097 struct svcctl_OpenSCManagerA
*r
)
1099 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1100 return WERR_NOT_SUPPORTED
;
1103 WERROR
_svcctl_OpenServiceA(struct pipes_struct
*p
,
1104 struct svcctl_OpenServiceA
*r
)
1106 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1107 return WERR_NOT_SUPPORTED
;
1110 WERROR
_svcctl_QueryServiceConfigA(struct pipes_struct
*p
,
1111 struct svcctl_QueryServiceConfigA
*r
)
1113 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1114 return WERR_NOT_SUPPORTED
;
1117 WERROR
_svcctl_QueryServiceLockStatusA(struct pipes_struct
*p
,
1118 struct svcctl_QueryServiceLockStatusA
*r
)
1120 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1121 return WERR_NOT_SUPPORTED
;
1124 WERROR
_svcctl_StartServiceA(struct pipes_struct
*p
,
1125 struct svcctl_StartServiceA
*r
)
1127 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1128 return WERR_NOT_SUPPORTED
;
1131 WERROR
_svcctl_GetServiceDisplayNameA(struct pipes_struct
*p
,
1132 struct svcctl_GetServiceDisplayNameA
*r
)
1134 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1135 return WERR_NOT_SUPPORTED
;
1138 WERROR
_svcctl_GetServiceKeyNameA(struct pipes_struct
*p
,
1139 struct svcctl_GetServiceKeyNameA
*r
)
1141 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1142 return WERR_NOT_SUPPORTED
;
1145 WERROR
_svcctl_GetCurrentGroupeStateW(struct pipes_struct
*p
,
1146 struct svcctl_GetCurrentGroupeStateW
*r
)
1148 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1149 return WERR_NOT_SUPPORTED
;
1152 WERROR
_svcctl_EnumServiceGroupW(struct pipes_struct
*p
,
1153 struct svcctl_EnumServiceGroupW
*r
)
1155 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1156 return WERR_NOT_SUPPORTED
;
1159 WERROR
_svcctl_ChangeServiceConfig2A(struct pipes_struct
*p
,
1160 struct svcctl_ChangeServiceConfig2A
*r
)
1162 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1163 return WERR_NOT_SUPPORTED
;
1166 WERROR
_svcctl_ChangeServiceConfig2W(struct pipes_struct
*p
,
1167 struct svcctl_ChangeServiceConfig2W
*r
)
1169 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1170 return WERR_NOT_SUPPORTED
;
1173 WERROR
_svcctl_QueryServiceConfig2A(struct pipes_struct
*p
,
1174 struct svcctl_QueryServiceConfig2A
*r
)
1176 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1177 return WERR_NOT_SUPPORTED
;
1180 WERROR
_EnumServicesStatusExA(struct pipes_struct
*p
,
1181 struct EnumServicesStatusExA
*r
)
1183 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1184 return WERR_NOT_SUPPORTED
;
1187 WERROR
_EnumServicesStatusExW(struct pipes_struct
*p
,
1188 struct EnumServicesStatusExW
*r
)
1190 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1191 return WERR_NOT_SUPPORTED
;
1194 WERROR
_svcctl_SCSendTSMessage(struct pipes_struct
*p
,
1195 struct svcctl_SCSendTSMessage
*r
)
1197 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
1198 return WERR_NOT_SUPPORTED
;