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 "../librpc/gen_ndr/srv_svcctl.h"
27 #include "services/services.h"
28 #include "../libcli/security/security.h"
29 #include "../librpc/gen_ndr/ndr_security.h"
32 #define DBGC_CLASS DBGC_RPC_SRV
34 struct service_control_op
{
36 SERVICE_CONTROL_OPS
*ops
;
39 /* handle external services */
40 extern SERVICE_CONTROL_OPS rcinit_svc_ops
;
42 /* builtin services (see service_db.c and services/svc_*.c */
43 extern SERVICE_CONTROL_OPS spoolss_svc_ops
;
44 extern SERVICE_CONTROL_OPS netlogon_svc_ops
;
45 extern SERVICE_CONTROL_OPS winreg_svc_ops
;
46 extern SERVICE_CONTROL_OPS wins_svc_ops
;
48 /* make sure this number patches the number of builtin
49 SERVICE_CONTROL_OPS structure listed above */
51 #define SVCCTL_NUM_INTERNAL_SERVICES 4
53 struct service_control_op
*svcctl_ops
;
55 static const struct generic_mapping scm_generic_map
=
56 { SC_MANAGER_READ_ACCESS
, SC_MANAGER_WRITE_ACCESS
, SC_MANAGER_EXECUTE_ACCESS
, SC_MANAGER_ALL_ACCESS
};
57 static const struct generic_mapping svc_generic_map
=
58 { SERVICE_READ_ACCESS
, SERVICE_WRITE_ACCESS
, SERVICE_EXECUTE_ACCESS
, SERVICE_ALL_ACCESS
};
61 /********************************************************************
62 ********************************************************************/
64 bool init_service_op_table( void )
66 const char **service_list
= lp_svcctl_list();
67 int num_services
= SVCCTL_NUM_INTERNAL_SERVICES
+ str_list_length( service_list
);
70 if ( !(svcctl_ops
= TALLOC_ARRAY( NULL
, struct service_control_op
, num_services
+1)) ) {
71 DEBUG(0,("init_service_op_table: talloc() failed!\n"));
75 /* services listed in smb.conf get the rc.init interface */
77 for ( i
=0; service_list
&& service_list
[i
]; i
++ ) {
78 svcctl_ops
[i
].name
= talloc_strdup( svcctl_ops
, service_list
[i
] );
79 svcctl_ops
[i
].ops
= &rcinit_svc_ops
;
82 /* add builtin services */
84 svcctl_ops
[i
].name
= talloc_strdup( svcctl_ops
, "Spooler" );
85 svcctl_ops
[i
].ops
= &spoolss_svc_ops
;
88 svcctl_ops
[i
].name
= talloc_strdup( svcctl_ops
, "NETLOGON" );
89 svcctl_ops
[i
].ops
= &netlogon_svc_ops
;
92 svcctl_ops
[i
].name
= talloc_strdup( svcctl_ops
, "RemoteRegistry" );
93 svcctl_ops
[i
].ops
= &winreg_svc_ops
;
96 svcctl_ops
[i
].name
= talloc_strdup( svcctl_ops
, "WINS" );
97 svcctl_ops
[i
].ops
= &wins_svc_ops
;
100 /* NULL terminate the array */
102 svcctl_ops
[i
].name
= NULL
;
103 svcctl_ops
[i
].ops
= NULL
;
108 /********************************************************************
109 ********************************************************************/
111 static struct service_control_op
* find_service_by_name( const char *name
)
115 for ( i
=0; svcctl_ops
[i
].name
; i
++ ) {
116 if ( strequal( name
, svcctl_ops
[i
].name
) )
117 return &svcctl_ops
[i
];
122 /********************************************************************
123 ********************************************************************/
125 static NTSTATUS
svcctl_access_check( struct security_descriptor
*sec_desc
, struct security_token
*token
,
126 uint32 access_desired
, uint32
*access_granted
)
128 if ( geteuid() == sec_initial_uid() ) {
129 DEBUG(5,("svcctl_access_check: using root's token\n"));
130 token
= get_root_nt_token();
133 return se_access_check( sec_desc
, token
, access_desired
, access_granted
);
136 /********************************************************************
137 ********************************************************************/
139 static struct security_descriptor
* construct_scm_sd( TALLOC_CTX
*ctx
)
141 struct security_ace ace
[2];
143 struct security_descriptor
*sd
;
144 struct security_acl
*theacl
;
147 /* basic access for Everyone */
149 init_sec_ace(&ace
[i
++], &global_sid_World
,
150 SEC_ACE_TYPE_ACCESS_ALLOWED
, SC_MANAGER_READ_ACCESS
, 0);
152 /* Full Access 'BUILTIN\Administrators' */
154 init_sec_ace(&ace
[i
++], &global_sid_Builtin_Administrators
,
155 SEC_ACE_TYPE_ACCESS_ALLOWED
, SC_MANAGER_ALL_ACCESS
, 0);
158 /* create the security descriptor */
160 if ( !(theacl
= make_sec_acl(ctx
, NT4_ACL_REVISION
, i
, ace
)) )
163 if ( !(sd
= make_sec_desc(ctx
, SECURITY_DESCRIPTOR_REVISION_1
,
164 SEC_DESC_SELF_RELATIVE
, NULL
, NULL
, NULL
,
171 /******************************************************************
172 Find a registry key handle and return a SERVICE_INFO
173 *****************************************************************/
175 static SERVICE_INFO
*find_service_info_by_hnd(struct pipes_struct
*p
,
176 struct policy_handle
*hnd
)
178 SERVICE_INFO
*service_info
= NULL
;
180 if( !find_policy_by_hnd( p
, hnd
, (void **)(void *)&service_info
) ) {
181 DEBUG(2,("find_service_info_by_hnd: handle not found\n"));
188 /******************************************************************
189 *****************************************************************/
191 static WERROR
create_open_service_handle(struct pipes_struct
*p
,
192 struct policy_handle
*handle
,
195 uint32_t access_granted
)
197 SERVICE_INFO
*info
= NULL
;
198 WERROR result
= WERR_OK
;
199 struct service_control_op
*s_op
;
201 if ( !(info
= TALLOC_ZERO_P( NULL
, SERVICE_INFO
)) )
204 /* the Service Manager has a NULL name */
206 info
->type
= SVC_HANDLE_IS_SCM
;
209 case SVC_HANDLE_IS_SCM
:
210 info
->type
= SVC_HANDLE_IS_SCM
;
213 case SVC_HANDLE_IS_DBLOCK
:
214 info
->type
= SVC_HANDLE_IS_DBLOCK
;
217 case SVC_HANDLE_IS_SERVICE
:
218 info
->type
= SVC_HANDLE_IS_SERVICE
;
220 /* lookup the SERVICE_CONTROL_OPS */
222 if ( !(s_op
= find_service_by_name( service
)) ) {
223 result
= WERR_NO_SUCH_SERVICE
;
227 info
->ops
= s_op
->ops
;
229 if ( !(info
->name
= talloc_strdup( info
, s_op
->name
)) ) {
236 result
= WERR_NO_SUCH_SERVICE
;
240 info
->access_granted
= access_granted
;
242 /* store the SERVICE_INFO and create an open handle */
244 if ( !create_policy_hnd( p
, handle
, info
) ) {
245 result
= WERR_ACCESS_DENIED
;
250 if ( !W_ERROR_IS_OK(result
) )
256 /********************************************************************
257 _svcctl_OpenSCManagerW
258 ********************************************************************/
260 WERROR
_svcctl_OpenSCManagerW(struct pipes_struct
*p
,
261 struct svcctl_OpenSCManagerW
*r
)
263 struct security_descriptor
*sec_desc
;
264 uint32 access_granted
= 0;
267 /* perform access checks */
269 if ( !(sec_desc
= construct_scm_sd( p
->mem_ctx
)) )
272 se_map_generic( &r
->in
.access_mask
, &scm_generic_map
);
273 status
= svcctl_access_check( sec_desc
, p
->server_info
->ptok
,
274 r
->in
.access_mask
, &access_granted
);
275 if ( !NT_STATUS_IS_OK(status
) )
276 return ntstatus_to_werror( status
);
278 return create_open_service_handle( p
, r
->out
.handle
, SVC_HANDLE_IS_SCM
, NULL
, access_granted
);
281 /********************************************************************
283 ********************************************************************/
285 WERROR
_svcctl_OpenServiceW(struct pipes_struct
*p
,
286 struct svcctl_OpenServiceW
*r
)
288 struct security_descriptor
*sec_desc
;
289 uint32 access_granted
= 0;
291 const char *service
= NULL
;
293 service
= r
->in
.ServiceName
;
297 DEBUG(5, ("_svcctl_OpenServiceW: Attempting to open Service [%s], \n", service
));
299 /* based on my tests you can open a service if you have a valid scm handle */
301 if ( !find_service_info_by_hnd( p
, r
->in
.scmanager_handle
) )
304 /* perform access checks. Use the root token in order to ensure that we
305 retrieve the security descriptor */
307 if ( !(sec_desc
= svcctl_get_secdesc( p
->mem_ctx
, service
, get_root_nt_token() )) )
310 se_map_generic( &r
->in
.access_mask
, &svc_generic_map
);
311 status
= svcctl_access_check( sec_desc
, p
->server_info
->ptok
,
312 r
->in
.access_mask
, &access_granted
);
313 if ( !NT_STATUS_IS_OK(status
) )
314 return ntstatus_to_werror( status
);
316 return create_open_service_handle( p
, r
->out
.handle
, SVC_HANDLE_IS_SERVICE
, service
, access_granted
);
319 /********************************************************************
320 _svcctl_CloseServiceHandle
321 ********************************************************************/
323 WERROR
_svcctl_CloseServiceHandle(struct pipes_struct
*p
,
324 struct svcctl_CloseServiceHandle
*r
)
326 if ( !close_policy_hnd( p
, r
->in
.handle
) )
329 ZERO_STRUCTP(r
->out
.handle
);
334 /********************************************************************
335 _svcctl_GetServiceDisplayNameW
336 ********************************************************************/
338 WERROR
_svcctl_GetServiceDisplayNameW(struct pipes_struct
*p
,
339 struct svcctl_GetServiceDisplayNameW
*r
)
342 const char *display_name
;
343 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.handle
);
345 /* can only use an SCM handle here */
347 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_SCM
) )
350 service
= r
->in
.service_name
;
352 display_name
= svcctl_lookup_dispname(p
->mem_ctx
, service
,
353 p
->server_info
->ptok
);
358 *r
->out
.display_name
= display_name
;
359 *r
->out
.display_name_length
= strlen(display_name
);
364 /********************************************************************
365 _svcctl_QueryServiceStatus
366 ********************************************************************/
368 WERROR
_svcctl_QueryServiceStatus(struct pipes_struct
*p
,
369 struct svcctl_QueryServiceStatus
*r
)
371 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.handle
);
373 /* perform access checks */
375 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_SERVICE
) )
378 if ( !(info
->access_granted
& SC_RIGHT_SVC_QUERY_STATUS
) )
379 return WERR_ACCESS_DENIED
;
381 /* try the service specific status call */
383 return info
->ops
->service_status( info
->name
, r
->out
.service_status
);
386 /********************************************************************
387 ********************************************************************/
389 static int enumerate_status( TALLOC_CTX
*ctx
, struct ENUM_SERVICE_STATUSW
**status
, struct security_token
*token
)
391 int num_services
= 0;
393 struct ENUM_SERVICE_STATUSW
*st
;
394 const char *display_name
;
397 while ( svcctl_ops
[num_services
].name
)
400 if ( !(st
= TALLOC_ARRAY( ctx
, struct ENUM_SERVICE_STATUSW
, num_services
)) ) {
401 DEBUG(0,("enumerate_status: talloc() failed!\n"));
405 for ( i
=0; i
<num_services
; i
++ ) {
406 st
[i
].service_name
= talloc_strdup(st
, svcctl_ops
[i
].name
);
408 display_name
= svcctl_lookup_dispname(ctx
, svcctl_ops
[i
].name
, token
);
409 st
[i
].display_name
= talloc_strdup(st
, display_name
? display_name
: "");
411 svcctl_ops
[i
].ops
->service_status( svcctl_ops
[i
].name
, &st
[i
].status
);
419 /********************************************************************
420 _svcctl_EnumServicesStatusW
421 ********************************************************************/
423 WERROR
_svcctl_EnumServicesStatusW(struct pipes_struct
*p
,
424 struct svcctl_EnumServicesStatusW
*r
)
426 struct ENUM_SERVICE_STATUSW
*services
= NULL
;
429 size_t buffer_size
= 0;
430 WERROR result
= WERR_OK
;
431 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.handle
);
432 struct security_token
*token
= p
->server_info
->ptok
;
433 DATA_BLOB blob
= data_blob_null
;
435 /* perform access checks */
437 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_SCM
) )
440 if ( !(info
->access_granted
& SC_RIGHT_MGR_ENUMERATE_SERVICE
) ) {
441 return WERR_ACCESS_DENIED
;
444 num_services
= enumerate_status( p
->mem_ctx
, &services
, token
);
445 if (num_services
== -1 ) {
449 for ( i
=0; i
<num_services
; i
++ ) {
450 buffer_size
+= ndr_size_ENUM_SERVICE_STATUSW(&services
[i
], 0);
453 buffer_size
+= buffer_size
% 4;
455 if (buffer_size
> r
->in
.offered
) {
457 result
= WERR_MORE_DATA
;
460 if ( W_ERROR_IS_OK(result
) ) {
462 enum ndr_err_code ndr_err
;
463 struct ndr_push
*ndr
;
465 ndr
= ndr_push_init_ctx(p
->mem_ctx
);
467 return WERR_INVALID_PARAM
;
470 ndr_err
= ndr_push_ENUM_SERVICE_STATUSW_array(
471 ndr
, num_services
, services
);
472 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
473 return ntstatus_to_werror(ndr_map_error2ntstatus(ndr_err
));
475 blob
= ndr_push_blob(ndr
);
476 memcpy(r
->out
.service
, blob
.data
, MIN(blob
.length
, r
->in
.offered
));
479 *r
->out
.needed
= (buffer_size
> r
->in
.offered
) ? buffer_size
: r
->in
.offered
;
480 *r
->out
.services_returned
= (uint32
)num_services
;
481 if (r
->out
.resume_handle
) {
482 *r
->out
.resume_handle
= 0;
488 /********************************************************************
489 _svcctl_StartServiceW
490 ********************************************************************/
492 WERROR
_svcctl_StartServiceW(struct pipes_struct
*p
,
493 struct svcctl_StartServiceW
*r
)
495 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.handle
);
497 /* perform access checks */
499 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_SERVICE
) )
502 if ( !(info
->access_granted
& SC_RIGHT_SVC_START
) )
503 return WERR_ACCESS_DENIED
;
505 return info
->ops
->start_service( info
->name
);
508 /********************************************************************
509 _svcctl_ControlService
510 ********************************************************************/
512 WERROR
_svcctl_ControlService(struct pipes_struct
*p
,
513 struct svcctl_ControlService
*r
)
515 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.handle
);
517 /* perform access checks */
519 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_SERVICE
) )
522 switch ( r
->in
.control
) {
523 case SVCCTL_CONTROL_STOP
:
524 if ( !(info
->access_granted
& SC_RIGHT_SVC_STOP
) )
525 return WERR_ACCESS_DENIED
;
527 return info
->ops
->stop_service( info
->name
,
528 r
->out
.service_status
);
530 case SVCCTL_CONTROL_INTERROGATE
:
531 if ( !(info
->access_granted
& SC_RIGHT_SVC_QUERY_STATUS
) )
532 return WERR_ACCESS_DENIED
;
534 return info
->ops
->service_status( info
->name
,
535 r
->out
.service_status
);
537 return WERR_INVALID_PARAM
;
541 /********************************************************************
542 _svcctl_EnumDependentServicesW
543 ********************************************************************/
545 WERROR
_svcctl_EnumDependentServicesW(struct pipes_struct
*p
,
546 struct svcctl_EnumDependentServicesW
*r
)
548 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.service
);
550 /* perform access checks */
552 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_SERVICE
) )
555 if ( !(info
->access_granted
& SC_RIGHT_SVC_ENUMERATE_DEPENDENTS
) )
556 return WERR_ACCESS_DENIED
;
558 switch (r
->in
.state
) {
559 case SERVICE_STATE_ACTIVE
:
560 case SERVICE_STATE_INACTIVE
:
561 case SERVICE_STATE_ALL
:
564 return WERR_INVALID_PARAM
;
567 /* we have to set the outgoing buffer size to the same as the
568 incoming buffer size (even in the case of failure */
569 /* this is done in the autogenerated server already - gd */
571 *r
->out
.needed
= r
->in
.offered
;
573 /* no dependent services...basically a stub function */
574 *r
->out
.services_returned
= 0;
579 /********************************************************************
580 _svcctl_QueryServiceStatusEx
581 ********************************************************************/
583 WERROR
_svcctl_QueryServiceStatusEx(struct pipes_struct
*p
,
584 struct svcctl_QueryServiceStatusEx
*r
)
586 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.handle
);
589 /* perform access checks */
591 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_SERVICE
) )
594 if ( !(info
->access_granted
& SC_RIGHT_SVC_QUERY_STATUS
) )
595 return WERR_ACCESS_DENIED
;
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 *r
->out
.needed
= r
->in
.offered
;
601 switch ( r
->in
.info_level
) {
602 case SVC_STATUS_PROCESS_INFO
:
604 struct SERVICE_STATUS_PROCESS svc_stat_proc
;
605 enum ndr_err_code ndr_err
;
608 /* Get the status of the service.. */
609 info
->ops
->service_status( info
->name
, &svc_stat_proc
.status
);
610 svc_stat_proc
.process_id
= sys_getpid();
611 svc_stat_proc
.service_flags
= 0x0;
613 ndr_err
= ndr_push_struct_blob(&blob
, p
->mem_ctx
, &svc_stat_proc
,
614 (ndr_push_flags_fn_t
)ndr_push_SERVICE_STATUS_PROCESS
);
615 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
616 return WERR_INVALID_PARAM
;
619 r
->out
.buffer
= blob
.data
;
620 buffer_size
= sizeof(struct SERVICE_STATUS_PROCESS
);
625 return WERR_UNKNOWN_LEVEL
;
629 buffer_size
+= buffer_size
% 4;
630 *r
->out
.needed
= (buffer_size
> r
->in
.offered
) ? buffer_size
: r
->in
.offered
;
632 if (buffer_size
> r
->in
.offered
) {
633 return WERR_INSUFFICIENT_BUFFER
;
639 /********************************************************************
640 ********************************************************************/
642 static WERROR
fill_svc_config( TALLOC_CTX
*ctx
, const char *name
,
643 struct QUERY_SERVICE_CONFIG
*config
,
644 struct security_token
*token
)
646 TALLOC_CTX
*mem_ctx
= talloc_stackframe();
647 const char *result
= NULL
;
649 /* now fill in the individual values */
651 config
->displayname
= svcctl_lookup_dispname(mem_ctx
, name
, token
);
653 result
= svcctl_get_string_value(mem_ctx
, name
, "ObjectName", token
);
654 if (result
!= NULL
) {
655 config
->startname
= result
;
658 result
= svcctl_get_string_value(mem_ctx
, name
, "ImagePath", token
);
659 if (result
!= NULL
) {
660 config
->executablepath
= result
;
663 /* a few hard coded values */
664 /* loadordergroup and dependencies are empty */
666 config
->tag_id
= 0x00000000; /* unassigned loadorder group */
667 config
->service_type
= SERVICE_TYPE_WIN32_OWN_PROCESS
;
668 config
->error_control
= SVCCTL_SVC_ERROR_NORMAL
;
670 /* set the start type. NetLogon and WINS are disabled to prevent
671 the client from showing the "Start" button (if of course the services
674 if ( strequal( name
, "NETLOGON" ) && ( lp_servicenumber(name
) == -1 ) )
675 config
->start_type
= SVCCTL_DISABLED
;
676 else if ( strequal( name
, "WINS" ) && ( !lp_wins_support() ))
677 config
->start_type
= SVCCTL_DISABLED
;
679 config
->start_type
= SVCCTL_DEMAND_START
;
682 talloc_free(mem_ctx
);
687 /********************************************************************
688 _svcctl_QueryServiceConfigW
689 ********************************************************************/
691 WERROR
_svcctl_QueryServiceConfigW(struct pipes_struct
*p
,
692 struct svcctl_QueryServiceConfigW
*r
)
694 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.handle
);
698 /* perform access checks */
700 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_SERVICE
) )
703 if ( !(info
->access_granted
& SC_RIGHT_SVC_QUERY_CONFIG
) )
704 return WERR_ACCESS_DENIED
;
706 /* we have to set the outgoing buffer size to the same as the
707 incoming buffer size (even in the case of failure */
709 *r
->out
.needed
= r
->in
.offered
;
711 wresult
= fill_svc_config( p
->mem_ctx
, info
->name
, r
->out
.query
,
712 p
->server_info
->ptok
);
713 if ( !W_ERROR_IS_OK(wresult
) )
716 buffer_size
= ndr_size_QUERY_SERVICE_CONFIG(r
->out
.query
, 0);
717 *r
->out
.needed
= (buffer_size
> r
->in
.offered
) ? buffer_size
: r
->in
.offered
;
719 if (buffer_size
> r
->in
.offered
) {
720 ZERO_STRUCTP(r
->out
.query
);
721 return WERR_INSUFFICIENT_BUFFER
;
727 /********************************************************************
728 _svcctl_QueryServiceConfig2W
729 ********************************************************************/
731 WERROR
_svcctl_QueryServiceConfig2W(struct pipes_struct
*p
,
732 struct svcctl_QueryServiceConfig2W
*r
)
734 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.handle
);
737 /* perform access checks */
739 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_SERVICE
) )
742 if ( !(info
->access_granted
& SC_RIGHT_SVC_QUERY_CONFIG
) )
743 return WERR_ACCESS_DENIED
;
745 /* we have to set the outgoing buffer size to the same as the
746 incoming buffer size (even in the case of failure */
747 *r
->out
.needed
= r
->in
.offered
;
749 switch ( r
->in
.info_level
) {
750 case SERVICE_CONFIG_DESCRIPTION
:
752 struct SERVICE_DESCRIPTION desc_buf
;
753 const char *description
;
754 enum ndr_err_code ndr_err
;
757 description
= svcctl_lookup_description(
758 p
->mem_ctx
, info
->name
, p
->server_info
->ptok
);
760 desc_buf
.description
= description
;
762 ndr_err
= ndr_push_struct_blob(&blob
, p
->mem_ctx
, &desc_buf
,
763 (ndr_push_flags_fn_t
)ndr_push_SERVICE_DESCRIPTION
);
764 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
765 return WERR_INVALID_PARAM
;
768 buffer_size
= ndr_size_SERVICE_DESCRIPTION(&desc_buf
, 0);
769 r
->out
.buffer
= blob
.data
;
774 case SERVICE_CONFIG_FAILURE_ACTIONS
:
776 struct SERVICE_FAILURE_ACTIONS actions
;
777 enum ndr_err_code ndr_err
;
780 /* nothing to say...just service the request */
782 ZERO_STRUCT( actions
);
784 ndr_err
= ndr_push_struct_blob(&blob
, p
->mem_ctx
, &actions
,
785 (ndr_push_flags_fn_t
)ndr_push_SERVICE_FAILURE_ACTIONS
);
786 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
787 return WERR_INVALID_PARAM
;
790 buffer_size
= ndr_size_SERVICE_FAILURE_ACTIONS(&actions
, 0);
791 r
->out
.buffer
= blob
.data
;
798 return WERR_UNKNOWN_LEVEL
;
801 buffer_size
+= buffer_size
% 4;
802 *r
->out
.needed
= (buffer_size
> r
->in
.offered
) ? buffer_size
: r
->in
.offered
;
804 if (buffer_size
> r
->in
.offered
)
805 return WERR_INSUFFICIENT_BUFFER
;
810 /********************************************************************
811 _svcctl_LockServiceDatabase
812 ********************************************************************/
814 WERROR
_svcctl_LockServiceDatabase(struct pipes_struct
*p
,
815 struct svcctl_LockServiceDatabase
*r
)
817 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.handle
);
819 /* perform access checks */
821 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_SCM
) )
824 if ( !(info
->access_granted
& SC_RIGHT_MGR_LOCK
) )
825 return WERR_ACCESS_DENIED
;
827 /* Just open a handle. Doesn't actually lock anything */
829 return create_open_service_handle( p
, r
->out
.lock
, SVC_HANDLE_IS_DBLOCK
, NULL
, 0 );
832 /********************************************************************
833 _svcctl_UnlockServiceDatabase
834 ********************************************************************/
836 WERROR
_svcctl_UnlockServiceDatabase(struct pipes_struct
*p
,
837 struct svcctl_UnlockServiceDatabase
*r
)
839 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.lock
);
842 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_DBLOCK
) )
845 return close_policy_hnd( p
, r
->out
.lock
) ? WERR_OK
: WERR_BADFID
;
848 /********************************************************************
849 _svcctl_QueryServiceObjectSecurity
850 ********************************************************************/
852 WERROR
_svcctl_QueryServiceObjectSecurity(struct pipes_struct
*p
,
853 struct svcctl_QueryServiceObjectSecurity
*r
)
855 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.handle
);
856 struct security_descriptor
*sec_desc
;
858 uint8_t *buffer
= NULL
;
862 /* only support the SCM and individual services */
864 if ( !info
|| !(info
->type
& (SVC_HANDLE_IS_SERVICE
|SVC_HANDLE_IS_SCM
)) )
867 /* check access reights (according to MSDN) */
869 if ( !(info
->access_granted
& SEC_STD_READ_CONTROL
) )
870 return WERR_ACCESS_DENIED
;
872 /* TODO: handle something besides SECINFO_DACL */
874 if ( (r
->in
.security_flags
& SECINFO_DACL
) != SECINFO_DACL
)
875 return WERR_INVALID_PARAM
;
877 /* lookup the security descriptor and marshall it up for a reply */
879 if ( !(sec_desc
= svcctl_get_secdesc( p
->mem_ctx
, info
->name
, get_root_nt_token() )) )
882 *r
->out
.needed
= ndr_size_security_descriptor(sec_desc
, 0);
884 if ( *r
->out
.needed
> r
->in
.offered
) {
885 return WERR_INSUFFICIENT_BUFFER
;
888 status
= marshall_sec_desc(p
->mem_ctx
, sec_desc
, &buffer
, &len
);
889 if (!NT_STATUS_IS_OK(status
)) {
890 return ntstatus_to_werror(status
);
893 *r
->out
.needed
= len
;
894 r
->out
.buffer
= buffer
;
899 /********************************************************************
900 _svcctl_SetServiceObjectSecurity
901 ********************************************************************/
903 WERROR
_svcctl_SetServiceObjectSecurity(struct pipes_struct
*p
,
904 struct svcctl_SetServiceObjectSecurity
*r
)
906 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.handle
);
907 struct security_descriptor
*sec_desc
= NULL
;
908 uint32 required_access
;
911 if ( !info
|| !(info
->type
& (SVC_HANDLE_IS_SERVICE
|SVC_HANDLE_IS_SCM
)) )
914 /* can't set the security de4scriptor on the ServiceControlManager */
916 if ( info
->type
== SVC_HANDLE_IS_SCM
)
917 return WERR_ACCESS_DENIED
;
919 /* check the access on the open handle */
921 switch ( r
->in
.security_flags
) {
923 required_access
= SEC_STD_WRITE_DAC
;
928 required_access
= SEC_STD_WRITE_OWNER
;
932 return WERR_INVALID_PARAM
;
934 return WERR_INVALID_PARAM
;
937 if ( !(info
->access_granted
& required_access
) )
938 return WERR_ACCESS_DENIED
;
940 /* read the security descfriptor */
942 status
= unmarshall_sec_desc(p
->mem_ctx
,
946 if (!NT_STATUS_IS_OK(status
)) {
947 return ntstatus_to_werror(status
);
950 /* store the new SD */
952 if (!svcctl_set_secdesc(info
->name
, sec_desc
, p
->server_info
->ptok
))
953 return WERR_ACCESS_DENIED
;
959 WERROR
_svcctl_DeleteService(struct pipes_struct
*p
,
960 struct svcctl_DeleteService
*r
)
962 p
->rng_fault_state
= True
;
963 return WERR_NOT_SUPPORTED
;
966 WERROR
_svcctl_SetServiceStatus(struct pipes_struct
*p
,
967 struct svcctl_SetServiceStatus
*r
)
969 p
->rng_fault_state
= True
;
970 return WERR_NOT_SUPPORTED
;
973 WERROR
_svcctl_NotifyBootConfigStatus(struct pipes_struct
*p
,
974 struct svcctl_NotifyBootConfigStatus
*r
)
976 p
->rng_fault_state
= True
;
977 return WERR_NOT_SUPPORTED
;
980 WERROR
_svcctl_SCSetServiceBitsW(struct pipes_struct
*p
,
981 struct svcctl_SCSetServiceBitsW
*r
)
983 p
->rng_fault_state
= True
;
984 return WERR_NOT_SUPPORTED
;
987 WERROR
_svcctl_ChangeServiceConfigW(struct pipes_struct
*p
,
988 struct svcctl_ChangeServiceConfigW
*r
)
990 p
->rng_fault_state
= True
;
991 return WERR_NOT_SUPPORTED
;
994 WERROR
_svcctl_CreateServiceW(struct pipes_struct
*p
,
995 struct svcctl_CreateServiceW
*r
)
997 p
->rng_fault_state
= True
;
998 return WERR_NOT_SUPPORTED
;
1001 WERROR
_svcctl_QueryServiceLockStatusW(struct pipes_struct
*p
,
1002 struct svcctl_QueryServiceLockStatusW
*r
)
1004 p
->rng_fault_state
= True
;
1005 return WERR_NOT_SUPPORTED
;
1008 WERROR
_svcctl_GetServiceKeyNameW(struct pipes_struct
*p
,
1009 struct svcctl_GetServiceKeyNameW
*r
)
1011 p
->rng_fault_state
= True
;
1012 return WERR_NOT_SUPPORTED
;
1015 WERROR
_svcctl_SCSetServiceBitsA(struct pipes_struct
*p
,
1016 struct svcctl_SCSetServiceBitsA
*r
)
1018 p
->rng_fault_state
= True
;
1019 return WERR_NOT_SUPPORTED
;
1022 WERROR
_svcctl_ChangeServiceConfigA(struct pipes_struct
*p
,
1023 struct svcctl_ChangeServiceConfigA
*r
)
1025 p
->rng_fault_state
= True
;
1026 return WERR_NOT_SUPPORTED
;
1029 WERROR
_svcctl_CreateServiceA(struct pipes_struct
*p
,
1030 struct svcctl_CreateServiceA
*r
)
1032 p
->rng_fault_state
= True
;
1033 return WERR_NOT_SUPPORTED
;
1036 WERROR
_svcctl_EnumDependentServicesA(struct pipes_struct
*p
,
1037 struct svcctl_EnumDependentServicesA
*r
)
1039 p
->rng_fault_state
= True
;
1040 return WERR_NOT_SUPPORTED
;
1043 WERROR
_svcctl_EnumServicesStatusA(struct pipes_struct
*p
,
1044 struct svcctl_EnumServicesStatusA
*r
)
1046 p
->rng_fault_state
= True
;
1047 return WERR_NOT_SUPPORTED
;
1050 WERROR
_svcctl_OpenSCManagerA(struct pipes_struct
*p
,
1051 struct svcctl_OpenSCManagerA
*r
)
1053 p
->rng_fault_state
= True
;
1054 return WERR_NOT_SUPPORTED
;
1057 WERROR
_svcctl_OpenServiceA(struct pipes_struct
*p
,
1058 struct svcctl_OpenServiceA
*r
)
1060 p
->rng_fault_state
= True
;
1061 return WERR_NOT_SUPPORTED
;
1064 WERROR
_svcctl_QueryServiceConfigA(struct pipes_struct
*p
,
1065 struct svcctl_QueryServiceConfigA
*r
)
1067 p
->rng_fault_state
= True
;
1068 return WERR_NOT_SUPPORTED
;
1071 WERROR
_svcctl_QueryServiceLockStatusA(struct pipes_struct
*p
,
1072 struct svcctl_QueryServiceLockStatusA
*r
)
1074 p
->rng_fault_state
= True
;
1075 return WERR_NOT_SUPPORTED
;
1078 WERROR
_svcctl_StartServiceA(struct pipes_struct
*p
,
1079 struct svcctl_StartServiceA
*r
)
1081 p
->rng_fault_state
= True
;
1082 return WERR_NOT_SUPPORTED
;
1085 WERROR
_svcctl_GetServiceDisplayNameA(struct pipes_struct
*p
,
1086 struct svcctl_GetServiceDisplayNameA
*r
)
1088 p
->rng_fault_state
= True
;
1089 return WERR_NOT_SUPPORTED
;
1092 WERROR
_svcctl_GetServiceKeyNameA(struct pipes_struct
*p
,
1093 struct svcctl_GetServiceKeyNameA
*r
)
1095 p
->rng_fault_state
= True
;
1096 return WERR_NOT_SUPPORTED
;
1099 WERROR
_svcctl_GetCurrentGroupeStateW(struct pipes_struct
*p
,
1100 struct svcctl_GetCurrentGroupeStateW
*r
)
1102 p
->rng_fault_state
= True
;
1103 return WERR_NOT_SUPPORTED
;
1106 WERROR
_svcctl_EnumServiceGroupW(struct pipes_struct
*p
,
1107 struct svcctl_EnumServiceGroupW
*r
)
1109 p
->rng_fault_state
= True
;
1110 return WERR_NOT_SUPPORTED
;
1113 WERROR
_svcctl_ChangeServiceConfig2A(struct pipes_struct
*p
,
1114 struct svcctl_ChangeServiceConfig2A
*r
)
1116 p
->rng_fault_state
= True
;
1117 return WERR_NOT_SUPPORTED
;
1120 WERROR
_svcctl_ChangeServiceConfig2W(struct pipes_struct
*p
,
1121 struct svcctl_ChangeServiceConfig2W
*r
)
1123 p
->rng_fault_state
= True
;
1124 return WERR_NOT_SUPPORTED
;
1127 WERROR
_svcctl_QueryServiceConfig2A(struct pipes_struct
*p
,
1128 struct svcctl_QueryServiceConfig2A
*r
)
1130 p
->rng_fault_state
= True
;
1131 return WERR_NOT_SUPPORTED
;
1134 WERROR
_EnumServicesStatusExA(struct pipes_struct
*p
,
1135 struct EnumServicesStatusExA
*r
)
1137 p
->rng_fault_state
= True
;
1138 return WERR_NOT_SUPPORTED
;
1141 WERROR
_EnumServicesStatusExW(struct pipes_struct
*p
,
1142 struct EnumServicesStatusExW
*r
)
1144 p
->rng_fault_state
= True
;
1145 return WERR_NOT_SUPPORTED
;
1148 WERROR
_svcctl_SCSendTSMessage(struct pipes_struct
*p
,
1149 struct svcctl_SCSendTSMessage
*r
)
1151 p
->rng_fault_state
= True
;
1152 return WERR_NOT_SUPPORTED
;