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"
29 #include "registry/reg_objects.h"
30 #include "../librpc/gen_ndr/ndr_security.h"
33 #define DBGC_CLASS DBGC_RPC_SRV
35 struct service_control_op
{
37 SERVICE_CONTROL_OPS
*ops
;
40 /* handle external services */
41 extern SERVICE_CONTROL_OPS rcinit_svc_ops
;
43 /* builtin services (see service_db.c and services/svc_*.c */
44 extern SERVICE_CONTROL_OPS spoolss_svc_ops
;
45 extern SERVICE_CONTROL_OPS netlogon_svc_ops
;
46 extern SERVICE_CONTROL_OPS winreg_svc_ops
;
47 extern SERVICE_CONTROL_OPS wins_svc_ops
;
49 /* make sure this number patches the number of builtin
50 SERVICE_CONTROL_OPS structure listed above */
52 #define SVCCTL_NUM_INTERNAL_SERVICES 4
54 struct service_control_op
*svcctl_ops
;
56 static const struct generic_mapping scm_generic_map
=
57 { SC_MANAGER_READ_ACCESS
, SC_MANAGER_WRITE_ACCESS
, SC_MANAGER_EXECUTE_ACCESS
, SC_MANAGER_ALL_ACCESS
};
58 static const struct generic_mapping svc_generic_map
=
59 { SERVICE_READ_ACCESS
, SERVICE_WRITE_ACCESS
, SERVICE_EXECUTE_ACCESS
, SERVICE_ALL_ACCESS
};
62 /********************************************************************
63 ********************************************************************/
65 bool init_service_op_table( void )
67 const char **service_list
= lp_svcctl_list();
68 int num_services
= SVCCTL_NUM_INTERNAL_SERVICES
+ str_list_length( service_list
);
71 if ( !(svcctl_ops
= TALLOC_ARRAY( NULL
, struct service_control_op
, num_services
+1)) ) {
72 DEBUG(0,("init_service_op_table: talloc() failed!\n"));
76 /* services listed in smb.conf get the rc.init interface */
78 for ( i
=0; service_list
&& service_list
[i
]; i
++ ) {
79 svcctl_ops
[i
].name
= talloc_strdup( svcctl_ops
, service_list
[i
] );
80 svcctl_ops
[i
].ops
= &rcinit_svc_ops
;
83 /* add builtin services */
85 svcctl_ops
[i
].name
= talloc_strdup( svcctl_ops
, "Spooler" );
86 svcctl_ops
[i
].ops
= &spoolss_svc_ops
;
89 svcctl_ops
[i
].name
= talloc_strdup( svcctl_ops
, "NETLOGON" );
90 svcctl_ops
[i
].ops
= &netlogon_svc_ops
;
93 svcctl_ops
[i
].name
= talloc_strdup( svcctl_ops
, "RemoteRegistry" );
94 svcctl_ops
[i
].ops
= &winreg_svc_ops
;
97 svcctl_ops
[i
].name
= talloc_strdup( svcctl_ops
, "WINS" );
98 svcctl_ops
[i
].ops
= &wins_svc_ops
;
101 /* NULL terminate the array */
103 svcctl_ops
[i
].name
= NULL
;
104 svcctl_ops
[i
].ops
= NULL
;
109 /********************************************************************
110 ********************************************************************/
112 static struct service_control_op
* find_service_by_name( const char *name
)
116 for ( i
=0; svcctl_ops
[i
].name
; i
++ ) {
117 if ( strequal( name
, svcctl_ops
[i
].name
) )
118 return &svcctl_ops
[i
];
123 /********************************************************************
124 ********************************************************************/
126 static NTSTATUS
svcctl_access_check( struct security_descriptor
*sec_desc
, struct security_token
*token
,
127 uint32 access_desired
, uint32
*access_granted
)
129 if ( geteuid() == sec_initial_uid() ) {
130 DEBUG(5,("svcctl_access_check: using root's token\n"));
131 token
= get_root_nt_token();
134 return se_access_check( sec_desc
, token
, access_desired
, access_granted
);
137 /********************************************************************
138 ********************************************************************/
140 static struct security_descriptor
* construct_scm_sd( TALLOC_CTX
*ctx
)
142 struct security_ace ace
[2];
144 struct security_descriptor
*sd
;
145 struct security_acl
*theacl
;
148 /* basic access for Everyone */
150 init_sec_ace(&ace
[i
++], &global_sid_World
,
151 SEC_ACE_TYPE_ACCESS_ALLOWED
, SC_MANAGER_READ_ACCESS
, 0);
153 /* Full Access 'BUILTIN\Administrators' */
155 init_sec_ace(&ace
[i
++], &global_sid_Builtin_Administrators
,
156 SEC_ACE_TYPE_ACCESS_ALLOWED
, SC_MANAGER_ALL_ACCESS
, 0);
159 /* create the security descriptor */
161 if ( !(theacl
= make_sec_acl(ctx
, NT4_ACL_REVISION
, i
, ace
)) )
164 if ( !(sd
= make_sec_desc(ctx
, SECURITY_DESCRIPTOR_REVISION_1
,
165 SEC_DESC_SELF_RELATIVE
, NULL
, NULL
, NULL
,
172 /******************************************************************
173 Find a registry key handle and return a SERVICE_INFO
174 *****************************************************************/
176 static SERVICE_INFO
*find_service_info_by_hnd(struct pipes_struct
*p
,
177 struct policy_handle
*hnd
)
179 SERVICE_INFO
*service_info
= NULL
;
181 if( !find_policy_by_hnd( p
, hnd
, (void **)(void *)&service_info
) ) {
182 DEBUG(2,("find_service_info_by_hnd: handle not found\n"));
189 /******************************************************************
190 *****************************************************************/
192 static WERROR
create_open_service_handle(struct pipes_struct
*p
,
193 struct policy_handle
*handle
,
196 uint32_t access_granted
)
198 SERVICE_INFO
*info
= NULL
;
199 WERROR result
= WERR_OK
;
200 struct service_control_op
*s_op
;
202 if ( !(info
= TALLOC_ZERO_P( NULL
, SERVICE_INFO
)) )
205 /* the Service Manager has a NULL name */
207 info
->type
= SVC_HANDLE_IS_SCM
;
210 case SVC_HANDLE_IS_SCM
:
211 info
->type
= SVC_HANDLE_IS_SCM
;
214 case SVC_HANDLE_IS_DBLOCK
:
215 info
->type
= SVC_HANDLE_IS_DBLOCK
;
218 case SVC_HANDLE_IS_SERVICE
:
219 info
->type
= SVC_HANDLE_IS_SERVICE
;
221 /* lookup the SERVICE_CONTROL_OPS */
223 if ( !(s_op
= find_service_by_name( service
)) ) {
224 result
= WERR_NO_SUCH_SERVICE
;
228 info
->ops
= s_op
->ops
;
230 if ( !(info
->name
= talloc_strdup( info
, s_op
->name
)) ) {
237 result
= WERR_NO_SUCH_SERVICE
;
241 info
->access_granted
= access_granted
;
243 /* store the SERVICE_INFO and create an open handle */
245 if ( !create_policy_hnd( p
, handle
, info
) ) {
246 result
= WERR_ACCESS_DENIED
;
251 if ( !W_ERROR_IS_OK(result
) )
257 /********************************************************************
258 _svcctl_OpenSCManagerW
259 ********************************************************************/
261 WERROR
_svcctl_OpenSCManagerW(struct pipes_struct
*p
,
262 struct svcctl_OpenSCManagerW
*r
)
264 struct security_descriptor
*sec_desc
;
265 uint32 access_granted
= 0;
268 /* perform access checks */
270 if ( !(sec_desc
= construct_scm_sd( p
->mem_ctx
)) )
273 se_map_generic( &r
->in
.access_mask
, &scm_generic_map
);
274 status
= svcctl_access_check( sec_desc
, p
->server_info
->ptok
,
275 r
->in
.access_mask
, &access_granted
);
276 if ( !NT_STATUS_IS_OK(status
) )
277 return ntstatus_to_werror( status
);
279 return create_open_service_handle( p
, r
->out
.handle
, SVC_HANDLE_IS_SCM
, NULL
, access_granted
);
282 /********************************************************************
284 ********************************************************************/
286 WERROR
_svcctl_OpenServiceW(struct pipes_struct
*p
,
287 struct svcctl_OpenServiceW
*r
)
289 struct security_descriptor
*sec_desc
;
290 uint32 access_granted
= 0;
292 const char *service
= NULL
;
294 service
= r
->in
.ServiceName
;
298 DEBUG(5, ("_svcctl_OpenServiceW: Attempting to open Service [%s], \n", service
));
300 /* based on my tests you can open a service if you have a valid scm handle */
302 if ( !find_service_info_by_hnd( p
, r
->in
.scmanager_handle
) )
305 /* perform access checks. Use the root token in order to ensure that we
306 retrieve the security descriptor */
308 if ( !(sec_desc
= svcctl_get_secdesc( p
->mem_ctx
, service
, get_root_nt_token() )) )
311 se_map_generic( &r
->in
.access_mask
, &svc_generic_map
);
312 status
= svcctl_access_check( sec_desc
, p
->server_info
->ptok
,
313 r
->in
.access_mask
, &access_granted
);
314 if ( !NT_STATUS_IS_OK(status
) )
315 return ntstatus_to_werror( status
);
317 return create_open_service_handle( p
, r
->out
.handle
, SVC_HANDLE_IS_SERVICE
, service
, access_granted
);
320 /********************************************************************
321 _svcctl_CloseServiceHandle
322 ********************************************************************/
324 WERROR
_svcctl_CloseServiceHandle(struct pipes_struct
*p
,
325 struct svcctl_CloseServiceHandle
*r
)
327 if ( !close_policy_hnd( p
, r
->in
.handle
) )
330 ZERO_STRUCTP(r
->out
.handle
);
335 /********************************************************************
336 _svcctl_GetServiceDisplayNameW
337 ********************************************************************/
339 WERROR
_svcctl_GetServiceDisplayNameW(struct pipes_struct
*p
,
340 struct svcctl_GetServiceDisplayNameW
*r
)
343 const char *display_name
;
344 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.handle
);
346 /* can only use an SCM handle here */
348 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_SCM
) )
351 service
= r
->in
.service_name
;
353 display_name
= svcctl_lookup_dispname(p
->mem_ctx
, service
,
354 p
->server_info
->ptok
);
359 *r
->out
.display_name
= display_name
;
360 *r
->out
.display_name_length
= strlen(display_name
);
365 /********************************************************************
366 _svcctl_QueryServiceStatus
367 ********************************************************************/
369 WERROR
_svcctl_QueryServiceStatus(struct pipes_struct
*p
,
370 struct svcctl_QueryServiceStatus
*r
)
372 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.handle
);
374 /* perform access checks */
376 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_SERVICE
) )
379 if ( !(info
->access_granted
& SC_RIGHT_SVC_QUERY_STATUS
) )
380 return WERR_ACCESS_DENIED
;
382 /* try the service specific status call */
384 return info
->ops
->service_status( info
->name
, r
->out
.service_status
);
387 /********************************************************************
388 ********************************************************************/
390 static int enumerate_status( TALLOC_CTX
*ctx
, struct ENUM_SERVICE_STATUSW
**status
, struct security_token
*token
)
392 int num_services
= 0;
394 struct ENUM_SERVICE_STATUSW
*st
;
395 const char *display_name
;
398 while ( svcctl_ops
[num_services
].name
)
401 if ( !(st
= TALLOC_ARRAY( ctx
, struct ENUM_SERVICE_STATUSW
, num_services
)) ) {
402 DEBUG(0,("enumerate_status: talloc() failed!\n"));
406 for ( i
=0; i
<num_services
; i
++ ) {
407 st
[i
].service_name
= talloc_strdup(st
, svcctl_ops
[i
].name
);
409 display_name
= svcctl_lookup_dispname(ctx
, svcctl_ops
[i
].name
, token
);
410 st
[i
].display_name
= talloc_strdup(st
, display_name
? display_name
: "");
412 svcctl_ops
[i
].ops
->service_status( svcctl_ops
[i
].name
, &st
[i
].status
);
420 /********************************************************************
421 _svcctl_EnumServicesStatusW
422 ********************************************************************/
424 WERROR
_svcctl_EnumServicesStatusW(struct pipes_struct
*p
,
425 struct svcctl_EnumServicesStatusW
*r
)
427 struct ENUM_SERVICE_STATUSW
*services
= NULL
;
430 size_t buffer_size
= 0;
431 WERROR result
= WERR_OK
;
432 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.handle
);
433 struct security_token
*token
= p
->server_info
->ptok
;
434 DATA_BLOB blob
= data_blob_null
;
436 /* perform access checks */
438 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_SCM
) )
441 if ( !(info
->access_granted
& SC_RIGHT_MGR_ENUMERATE_SERVICE
) ) {
442 return WERR_ACCESS_DENIED
;
445 num_services
= enumerate_status( p
->mem_ctx
, &services
, token
);
446 if (num_services
== -1 ) {
450 for ( i
=0; i
<num_services
; i
++ ) {
451 buffer_size
+= ndr_size_ENUM_SERVICE_STATUSW(&services
[i
], 0);
454 buffer_size
+= buffer_size
% 4;
456 if (buffer_size
> r
->in
.offered
) {
458 result
= WERR_MORE_DATA
;
461 if ( W_ERROR_IS_OK(result
) ) {
463 enum ndr_err_code ndr_err
;
464 struct ndr_push
*ndr
;
466 ndr
= ndr_push_init_ctx(p
->mem_ctx
);
468 return WERR_INVALID_PARAM
;
471 ndr_err
= ndr_push_ENUM_SERVICE_STATUSW_array(
472 ndr
, num_services
, services
);
473 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
474 return ntstatus_to_werror(ndr_map_error2ntstatus(ndr_err
));
476 blob
= ndr_push_blob(ndr
);
477 memcpy(r
->out
.service
, blob
.data
, MIN(blob
.length
, r
->in
.offered
));
480 *r
->out
.needed
= (buffer_size
> r
->in
.offered
) ? buffer_size
: r
->in
.offered
;
481 *r
->out
.services_returned
= (uint32
)num_services
;
482 if (r
->out
.resume_handle
) {
483 *r
->out
.resume_handle
= 0;
489 /********************************************************************
490 _svcctl_StartServiceW
491 ********************************************************************/
493 WERROR
_svcctl_StartServiceW(struct pipes_struct
*p
,
494 struct svcctl_StartServiceW
*r
)
496 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.handle
);
498 /* perform access checks */
500 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_SERVICE
) )
503 if ( !(info
->access_granted
& SC_RIGHT_SVC_START
) )
504 return WERR_ACCESS_DENIED
;
506 return info
->ops
->start_service( info
->name
);
509 /********************************************************************
510 _svcctl_ControlService
511 ********************************************************************/
513 WERROR
_svcctl_ControlService(struct pipes_struct
*p
,
514 struct svcctl_ControlService
*r
)
516 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.handle
);
518 /* perform access checks */
520 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_SERVICE
) )
523 switch ( r
->in
.control
) {
524 case SVCCTL_CONTROL_STOP
:
525 if ( !(info
->access_granted
& SC_RIGHT_SVC_STOP
) )
526 return WERR_ACCESS_DENIED
;
528 return info
->ops
->stop_service( info
->name
,
529 r
->out
.service_status
);
531 case SVCCTL_CONTROL_INTERROGATE
:
532 if ( !(info
->access_granted
& SC_RIGHT_SVC_QUERY_STATUS
) )
533 return WERR_ACCESS_DENIED
;
535 return info
->ops
->service_status( info
->name
,
536 r
->out
.service_status
);
538 return WERR_INVALID_PARAM
;
542 /********************************************************************
543 _svcctl_EnumDependentServicesW
544 ********************************************************************/
546 WERROR
_svcctl_EnumDependentServicesW(struct pipes_struct
*p
,
547 struct svcctl_EnumDependentServicesW
*r
)
549 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.service
);
551 /* perform access checks */
553 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_SERVICE
) )
556 if ( !(info
->access_granted
& SC_RIGHT_SVC_ENUMERATE_DEPENDENTS
) )
557 return WERR_ACCESS_DENIED
;
559 switch (r
->in
.state
) {
560 case SERVICE_STATE_ACTIVE
:
561 case SERVICE_STATE_INACTIVE
:
562 case SERVICE_STATE_ALL
:
565 return WERR_INVALID_PARAM
;
568 /* we have to set the outgoing buffer size to the same as the
569 incoming buffer size (even in the case of failure */
570 /* this is done in the autogenerated server already - gd */
572 *r
->out
.needed
= r
->in
.offered
;
574 /* no dependent services...basically a stub function */
575 *r
->out
.services_returned
= 0;
580 /********************************************************************
581 _svcctl_QueryServiceStatusEx
582 ********************************************************************/
584 WERROR
_svcctl_QueryServiceStatusEx(struct pipes_struct
*p
,
585 struct svcctl_QueryServiceStatusEx
*r
)
587 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.handle
);
590 /* perform access checks */
592 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_SERVICE
) )
595 if ( !(info
->access_granted
& SC_RIGHT_SVC_QUERY_STATUS
) )
596 return WERR_ACCESS_DENIED
;
598 /* we have to set the outgoing buffer size to the same as the
599 incoming buffer size (even in the case of failure) */
600 *r
->out
.needed
= r
->in
.offered
;
602 switch ( r
->in
.info_level
) {
603 case SVC_STATUS_PROCESS_INFO
:
605 struct SERVICE_STATUS_PROCESS svc_stat_proc
;
606 enum ndr_err_code ndr_err
;
609 /* Get the status of the service.. */
610 info
->ops
->service_status( info
->name
, &svc_stat_proc
.status
);
611 svc_stat_proc
.process_id
= sys_getpid();
612 svc_stat_proc
.service_flags
= 0x0;
614 ndr_err
= ndr_push_struct_blob(&blob
, p
->mem_ctx
, &svc_stat_proc
,
615 (ndr_push_flags_fn_t
)ndr_push_SERVICE_STATUS_PROCESS
);
616 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
617 return WERR_INVALID_PARAM
;
620 r
->out
.buffer
= blob
.data
;
621 buffer_size
= sizeof(struct SERVICE_STATUS_PROCESS
);
626 return WERR_UNKNOWN_LEVEL
;
630 buffer_size
+= buffer_size
% 4;
631 *r
->out
.needed
= (buffer_size
> r
->in
.offered
) ? buffer_size
: r
->in
.offered
;
633 if (buffer_size
> r
->in
.offered
) {
634 return WERR_INSUFFICIENT_BUFFER
;
640 /********************************************************************
641 ********************************************************************/
643 static WERROR
fill_svc_config( TALLOC_CTX
*ctx
, const char *name
,
644 struct QUERY_SERVICE_CONFIG
*config
,
645 struct security_token
*token
)
647 struct regval_ctr
*values
;
648 struct regval_blob
*val
;
650 /* retrieve the registry values for this service */
652 if ( !(values
= svcctl_fetch_regvalues( name
, token
)) )
653 return WERR_REG_CORRUPT
;
655 /* now fill in the individual values */
657 if ( (val
= regval_ctr_getvalue( values
, "DisplayName" )) != NULL
)
658 config
->displayname
= regval_sz(val
);
660 config
->displayname
= name
;
662 if ( (val
= regval_ctr_getvalue( values
, "ObjectName" )) != NULL
) {
663 config
->startname
= regval_sz(val
);
666 if ( (val
= regval_ctr_getvalue( values
, "ImagePath" )) != NULL
) {
667 config
->executablepath
= regval_sz(val
);
670 /* a few hard coded values */
671 /* loadordergroup and dependencies are empty */
673 config
->tag_id
= 0x00000000; /* unassigned loadorder group */
674 config
->service_type
= SERVICE_TYPE_WIN32_OWN_PROCESS
;
675 config
->error_control
= SVCCTL_SVC_ERROR_NORMAL
;
677 /* set the start type. NetLogon and WINS are disabled to prevent
678 the client from showing the "Start" button (if of course the services
681 if ( strequal( name
, "NETLOGON" ) && ( lp_servicenumber(name
) == -1 ) )
682 config
->start_type
= SVCCTL_DISABLED
;
683 else if ( strequal( name
, "WINS" ) && ( !lp_wins_support() ))
684 config
->start_type
= SVCCTL_DISABLED
;
686 config
->start_type
= SVCCTL_DEMAND_START
;
689 TALLOC_FREE( values
);
694 /********************************************************************
695 _svcctl_QueryServiceConfigW
696 ********************************************************************/
698 WERROR
_svcctl_QueryServiceConfigW(struct pipes_struct
*p
,
699 struct svcctl_QueryServiceConfigW
*r
)
701 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.handle
);
705 /* perform access checks */
707 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_SERVICE
) )
710 if ( !(info
->access_granted
& SC_RIGHT_SVC_QUERY_CONFIG
) )
711 return WERR_ACCESS_DENIED
;
713 /* we have to set the outgoing buffer size to the same as the
714 incoming buffer size (even in the case of failure */
716 *r
->out
.needed
= r
->in
.offered
;
718 wresult
= fill_svc_config( p
->mem_ctx
, info
->name
, r
->out
.query
,
719 p
->server_info
->ptok
);
720 if ( !W_ERROR_IS_OK(wresult
) )
723 buffer_size
= ndr_size_QUERY_SERVICE_CONFIG(r
->out
.query
, 0);
724 *r
->out
.needed
= (buffer_size
> r
->in
.offered
) ? buffer_size
: r
->in
.offered
;
726 if (buffer_size
> r
->in
.offered
) {
727 ZERO_STRUCTP(r
->out
.query
);
728 return WERR_INSUFFICIENT_BUFFER
;
734 /********************************************************************
735 _svcctl_QueryServiceConfig2W
736 ********************************************************************/
738 WERROR
_svcctl_QueryServiceConfig2W(struct pipes_struct
*p
,
739 struct svcctl_QueryServiceConfig2W
*r
)
741 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.handle
);
744 /* perform access checks */
746 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_SERVICE
) )
749 if ( !(info
->access_granted
& SC_RIGHT_SVC_QUERY_CONFIG
) )
750 return WERR_ACCESS_DENIED
;
752 /* we have to set the outgoing buffer size to the same as the
753 incoming buffer size (even in the case of failure */
754 *r
->out
.needed
= r
->in
.offered
;
756 switch ( r
->in
.info_level
) {
757 case SERVICE_CONFIG_DESCRIPTION
:
759 struct SERVICE_DESCRIPTION desc_buf
;
760 const char *description
;
761 enum ndr_err_code ndr_err
;
764 description
= svcctl_lookup_description(
765 p
->mem_ctx
, info
->name
, p
->server_info
->ptok
);
767 desc_buf
.description
= description
;
769 ndr_err
= ndr_push_struct_blob(&blob
, p
->mem_ctx
, &desc_buf
,
770 (ndr_push_flags_fn_t
)ndr_push_SERVICE_DESCRIPTION
);
771 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
772 return WERR_INVALID_PARAM
;
775 buffer_size
= ndr_size_SERVICE_DESCRIPTION(&desc_buf
, 0);
776 r
->out
.buffer
= blob
.data
;
781 case SERVICE_CONFIG_FAILURE_ACTIONS
:
783 struct SERVICE_FAILURE_ACTIONS actions
;
784 enum ndr_err_code ndr_err
;
787 /* nothing to say...just service the request */
789 ZERO_STRUCT( actions
);
791 ndr_err
= ndr_push_struct_blob(&blob
, p
->mem_ctx
, &actions
,
792 (ndr_push_flags_fn_t
)ndr_push_SERVICE_FAILURE_ACTIONS
);
793 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
794 return WERR_INVALID_PARAM
;
797 buffer_size
= ndr_size_SERVICE_FAILURE_ACTIONS(&actions
, 0);
798 r
->out
.buffer
= blob
.data
;
805 return WERR_UNKNOWN_LEVEL
;
808 buffer_size
+= buffer_size
% 4;
809 *r
->out
.needed
= (buffer_size
> r
->in
.offered
) ? buffer_size
: r
->in
.offered
;
811 if (buffer_size
> r
->in
.offered
)
812 return WERR_INSUFFICIENT_BUFFER
;
817 /********************************************************************
818 _svcctl_LockServiceDatabase
819 ********************************************************************/
821 WERROR
_svcctl_LockServiceDatabase(struct pipes_struct
*p
,
822 struct svcctl_LockServiceDatabase
*r
)
824 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.handle
);
826 /* perform access checks */
828 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_SCM
) )
831 if ( !(info
->access_granted
& SC_RIGHT_MGR_LOCK
) )
832 return WERR_ACCESS_DENIED
;
834 /* Just open a handle. Doesn't actually lock anything */
836 return create_open_service_handle( p
, r
->out
.lock
, SVC_HANDLE_IS_DBLOCK
, NULL
, 0 );
839 /********************************************************************
840 _svcctl_UnlockServiceDatabase
841 ********************************************************************/
843 WERROR
_svcctl_UnlockServiceDatabase(struct pipes_struct
*p
,
844 struct svcctl_UnlockServiceDatabase
*r
)
846 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.lock
);
849 if ( !info
|| (info
->type
!= SVC_HANDLE_IS_DBLOCK
) )
852 return close_policy_hnd( p
, r
->out
.lock
) ? WERR_OK
: WERR_BADFID
;
855 /********************************************************************
856 _svcctl_QueryServiceObjectSecurity
857 ********************************************************************/
859 WERROR
_svcctl_QueryServiceObjectSecurity(struct pipes_struct
*p
,
860 struct svcctl_QueryServiceObjectSecurity
*r
)
862 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.handle
);
863 struct security_descriptor
*sec_desc
;
865 uint8_t *buffer
= NULL
;
869 /* only support the SCM and individual services */
871 if ( !info
|| !(info
->type
& (SVC_HANDLE_IS_SERVICE
|SVC_HANDLE_IS_SCM
)) )
874 /* check access reights (according to MSDN) */
876 if ( !(info
->access_granted
& SEC_STD_READ_CONTROL
) )
877 return WERR_ACCESS_DENIED
;
879 /* TODO: handle something besides SECINFO_DACL */
881 if ( (r
->in
.security_flags
& SECINFO_DACL
) != SECINFO_DACL
)
882 return WERR_INVALID_PARAM
;
884 /* lookup the security descriptor and marshall it up for a reply */
886 if ( !(sec_desc
= svcctl_get_secdesc( p
->mem_ctx
, info
->name
, get_root_nt_token() )) )
889 *r
->out
.needed
= ndr_size_security_descriptor(sec_desc
, 0);
891 if ( *r
->out
.needed
> r
->in
.offered
) {
892 return WERR_INSUFFICIENT_BUFFER
;
895 status
= marshall_sec_desc(p
->mem_ctx
, sec_desc
, &buffer
, &len
);
896 if (!NT_STATUS_IS_OK(status
)) {
897 return ntstatus_to_werror(status
);
900 *r
->out
.needed
= len
;
901 r
->out
.buffer
= buffer
;
906 /********************************************************************
907 _svcctl_SetServiceObjectSecurity
908 ********************************************************************/
910 WERROR
_svcctl_SetServiceObjectSecurity(struct pipes_struct
*p
,
911 struct svcctl_SetServiceObjectSecurity
*r
)
913 SERVICE_INFO
*info
= find_service_info_by_hnd( p
, r
->in
.handle
);
914 struct security_descriptor
*sec_desc
= NULL
;
915 uint32 required_access
;
918 if ( !info
|| !(info
->type
& (SVC_HANDLE_IS_SERVICE
|SVC_HANDLE_IS_SCM
)) )
921 /* can't set the security de4scriptor on the ServiceControlManager */
923 if ( info
->type
== SVC_HANDLE_IS_SCM
)
924 return WERR_ACCESS_DENIED
;
926 /* check the access on the open handle */
928 switch ( r
->in
.security_flags
) {
930 required_access
= SEC_STD_WRITE_DAC
;
935 required_access
= SEC_STD_WRITE_OWNER
;
939 return WERR_INVALID_PARAM
;
941 return WERR_INVALID_PARAM
;
944 if ( !(info
->access_granted
& required_access
) )
945 return WERR_ACCESS_DENIED
;
947 /* read the security descfriptor */
949 status
= unmarshall_sec_desc(p
->mem_ctx
,
953 if (!NT_STATUS_IS_OK(status
)) {
954 return ntstatus_to_werror(status
);
957 /* store the new SD */
959 if (!svcctl_set_secdesc(info
->name
, sec_desc
, p
->server_info
->ptok
))
960 return WERR_ACCESS_DENIED
;
966 WERROR
_svcctl_DeleteService(struct pipes_struct
*p
,
967 struct svcctl_DeleteService
*r
)
969 p
->rng_fault_state
= True
;
970 return WERR_NOT_SUPPORTED
;
973 WERROR
_svcctl_SetServiceStatus(struct pipes_struct
*p
,
974 struct svcctl_SetServiceStatus
*r
)
976 p
->rng_fault_state
= True
;
977 return WERR_NOT_SUPPORTED
;
980 WERROR
_svcctl_NotifyBootConfigStatus(struct pipes_struct
*p
,
981 struct svcctl_NotifyBootConfigStatus
*r
)
983 p
->rng_fault_state
= True
;
984 return WERR_NOT_SUPPORTED
;
987 WERROR
_svcctl_SCSetServiceBitsW(struct pipes_struct
*p
,
988 struct svcctl_SCSetServiceBitsW
*r
)
990 p
->rng_fault_state
= True
;
991 return WERR_NOT_SUPPORTED
;
994 WERROR
_svcctl_ChangeServiceConfigW(struct pipes_struct
*p
,
995 struct svcctl_ChangeServiceConfigW
*r
)
997 p
->rng_fault_state
= True
;
998 return WERR_NOT_SUPPORTED
;
1001 WERROR
_svcctl_CreateServiceW(struct pipes_struct
*p
,
1002 struct svcctl_CreateServiceW
*r
)
1004 p
->rng_fault_state
= True
;
1005 return WERR_NOT_SUPPORTED
;
1008 WERROR
_svcctl_QueryServiceLockStatusW(struct pipes_struct
*p
,
1009 struct svcctl_QueryServiceLockStatusW
*r
)
1011 p
->rng_fault_state
= True
;
1012 return WERR_NOT_SUPPORTED
;
1015 WERROR
_svcctl_GetServiceKeyNameW(struct pipes_struct
*p
,
1016 struct svcctl_GetServiceKeyNameW
*r
)
1018 p
->rng_fault_state
= True
;
1019 return WERR_NOT_SUPPORTED
;
1022 WERROR
_svcctl_SCSetServiceBitsA(struct pipes_struct
*p
,
1023 struct svcctl_SCSetServiceBitsA
*r
)
1025 p
->rng_fault_state
= True
;
1026 return WERR_NOT_SUPPORTED
;
1029 WERROR
_svcctl_ChangeServiceConfigA(struct pipes_struct
*p
,
1030 struct svcctl_ChangeServiceConfigA
*r
)
1032 p
->rng_fault_state
= True
;
1033 return WERR_NOT_SUPPORTED
;
1036 WERROR
_svcctl_CreateServiceA(struct pipes_struct
*p
,
1037 struct svcctl_CreateServiceA
*r
)
1039 p
->rng_fault_state
= True
;
1040 return WERR_NOT_SUPPORTED
;
1043 WERROR
_svcctl_EnumDependentServicesA(struct pipes_struct
*p
,
1044 struct svcctl_EnumDependentServicesA
*r
)
1046 p
->rng_fault_state
= True
;
1047 return WERR_NOT_SUPPORTED
;
1050 WERROR
_svcctl_EnumServicesStatusA(struct pipes_struct
*p
,
1051 struct svcctl_EnumServicesStatusA
*r
)
1053 p
->rng_fault_state
= True
;
1054 return WERR_NOT_SUPPORTED
;
1057 WERROR
_svcctl_OpenSCManagerA(struct pipes_struct
*p
,
1058 struct svcctl_OpenSCManagerA
*r
)
1060 p
->rng_fault_state
= True
;
1061 return WERR_NOT_SUPPORTED
;
1064 WERROR
_svcctl_OpenServiceA(struct pipes_struct
*p
,
1065 struct svcctl_OpenServiceA
*r
)
1067 p
->rng_fault_state
= True
;
1068 return WERR_NOT_SUPPORTED
;
1071 WERROR
_svcctl_QueryServiceConfigA(struct pipes_struct
*p
,
1072 struct svcctl_QueryServiceConfigA
*r
)
1074 p
->rng_fault_state
= True
;
1075 return WERR_NOT_SUPPORTED
;
1078 WERROR
_svcctl_QueryServiceLockStatusA(struct pipes_struct
*p
,
1079 struct svcctl_QueryServiceLockStatusA
*r
)
1081 p
->rng_fault_state
= True
;
1082 return WERR_NOT_SUPPORTED
;
1085 WERROR
_svcctl_StartServiceA(struct pipes_struct
*p
,
1086 struct svcctl_StartServiceA
*r
)
1088 p
->rng_fault_state
= True
;
1089 return WERR_NOT_SUPPORTED
;
1092 WERROR
_svcctl_GetServiceDisplayNameA(struct pipes_struct
*p
,
1093 struct svcctl_GetServiceDisplayNameA
*r
)
1095 p
->rng_fault_state
= True
;
1096 return WERR_NOT_SUPPORTED
;
1099 WERROR
_svcctl_GetServiceKeyNameA(struct pipes_struct
*p
,
1100 struct svcctl_GetServiceKeyNameA
*r
)
1102 p
->rng_fault_state
= True
;
1103 return WERR_NOT_SUPPORTED
;
1106 WERROR
_svcctl_GetCurrentGroupeStateW(struct pipes_struct
*p
,
1107 struct svcctl_GetCurrentGroupeStateW
*r
)
1109 p
->rng_fault_state
= True
;
1110 return WERR_NOT_SUPPORTED
;
1113 WERROR
_svcctl_EnumServiceGroupW(struct pipes_struct
*p
,
1114 struct svcctl_EnumServiceGroupW
*r
)
1116 p
->rng_fault_state
= True
;
1117 return WERR_NOT_SUPPORTED
;
1120 WERROR
_svcctl_ChangeServiceConfig2A(struct pipes_struct
*p
,
1121 struct svcctl_ChangeServiceConfig2A
*r
)
1123 p
->rng_fault_state
= True
;
1124 return WERR_NOT_SUPPORTED
;
1127 WERROR
_svcctl_ChangeServiceConfig2W(struct pipes_struct
*p
,
1128 struct svcctl_ChangeServiceConfig2W
*r
)
1130 p
->rng_fault_state
= True
;
1131 return WERR_NOT_SUPPORTED
;
1134 WERROR
_svcctl_QueryServiceConfig2A(struct pipes_struct
*p
,
1135 struct svcctl_QueryServiceConfig2A
*r
)
1137 p
->rng_fault_state
= True
;
1138 return WERR_NOT_SUPPORTED
;
1141 WERROR
_EnumServicesStatusExA(struct pipes_struct
*p
,
1142 struct EnumServicesStatusExA
*r
)
1144 p
->rng_fault_state
= True
;
1145 return WERR_NOT_SUPPORTED
;
1148 WERROR
_EnumServicesStatusExW(struct pipes_struct
*p
,
1149 struct EnumServicesStatusExW
*r
)
1151 p
->rng_fault_state
= True
;
1152 return WERR_NOT_SUPPORTED
;
1155 WERROR
_svcctl_SCSendTSMessage(struct pipes_struct
*p
,
1156 struct svcctl_SCSendTSMessage
*r
)
1158 p
->rng_fault_state
= True
;
1159 return WERR_NOT_SUPPORTED
;