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 "../libcli/security/security.h"
28 #include "../librpc/gen_ndr/ndr_security.h"
29 #include "services/services.h"
30 #include "services/svc_winreg_glue.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 bool shutdown_service_op_table(void)
111 TALLOC_FREE(svcctl_ops);
116 /********************************************************************
117 ********************************************************************/
119 static struct service_control_op* find_service_by_name( const char *name )
123 for ( i=0; svcctl_ops[i].name; i++ ) {
124 if ( strequal( name, svcctl_ops[i].name ) )
125 return &svcctl_ops[i];
130 /********************************************************************
131 ********************************************************************/
133 static NTSTATUS svcctl_access_check( struct security_descriptor *sec_desc, struct security_token *token,
134 uint32 access_desired, uint32 *access_granted )
136 if ( geteuid() == sec_initial_uid() ) {
137 DEBUG(5,("svcctl_access_check: using root's token\n"));
138 token = get_root_nt_token();
141 return se_access_check( sec_desc, token, access_desired, access_granted);
144 /********************************************************************
145 ********************************************************************/
147 static struct security_descriptor* construct_scm_sd( TALLOC_CTX *ctx )
149 struct security_ace ace[2];
151 struct security_descriptor *sd;
152 struct security_acl *theacl;
155 /* basic access for Everyone */
157 init_sec_ace(&ace[i++], &global_sid_World,
158 SEC_ACE_TYPE_ACCESS_ALLOWED, SC_MANAGER_READ_ACCESS, 0);
160 /* Full Access 'BUILTIN\Administrators' */
162 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
163 SEC_ACE_TYPE_ACCESS_ALLOWED, SC_MANAGER_ALL_ACCESS, 0);
166 /* create the security descriptor */
168 if ( !(theacl = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) )
171 if ( !(sd = make_sec_desc(ctx, SECURITY_DESCRIPTOR_REVISION_1,
172 SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL,
179 /******************************************************************
180 Find a registry key handle and return a SERVICE_INFO
181 *****************************************************************/
183 static SERVICE_INFO *find_service_info_by_hnd(struct pipes_struct *p,
184 struct policy_handle *hnd)
186 SERVICE_INFO *service_info = NULL;
188 if( !find_policy_by_hnd( p, hnd, (void **)(void *)&service_info) ) {
189 DEBUG(2,("find_service_info_by_hnd: handle not found\n"));
196 /******************************************************************
197 *****************************************************************/
199 static WERROR create_open_service_handle(struct pipes_struct *p,
200 struct policy_handle *handle,
203 uint32_t access_granted)
205 SERVICE_INFO *info = NULL;
206 WERROR result = WERR_OK;
207 struct service_control_op *s_op;
209 if ( !(info = TALLOC_ZERO_P( NULL, SERVICE_INFO )) )
212 /* the Service Manager has a NULL name */
214 info->type = SVC_HANDLE_IS_SCM;
217 case SVC_HANDLE_IS_SCM:
218 info->type = SVC_HANDLE_IS_SCM;
221 case SVC_HANDLE_IS_DBLOCK:
222 info->type = SVC_HANDLE_IS_DBLOCK;
225 case SVC_HANDLE_IS_SERVICE:
226 info->type = SVC_HANDLE_IS_SERVICE;
228 /* lookup the SERVICE_CONTROL_OPS */
230 if ( !(s_op = find_service_by_name( service )) ) {
231 result = WERR_NO_SUCH_SERVICE;
235 info->ops = s_op->ops;
237 if ( !(info->name = talloc_strdup( info, s_op->name )) ) {
244 result = WERR_NO_SUCH_SERVICE;
248 info->access_granted = access_granted;
250 /* store the SERVICE_INFO and create an open handle */
252 if ( !create_policy_hnd( p, handle, info ) ) {
253 result = WERR_ACCESS_DENIED;
258 if ( !W_ERROR_IS_OK(result) )
264 /********************************************************************
265 _svcctl_OpenSCManagerW
266 ********************************************************************/
268 WERROR _svcctl_OpenSCManagerW(struct pipes_struct *p,
269 struct svcctl_OpenSCManagerW *r)
271 struct security_descriptor *sec_desc;
272 uint32 access_granted = 0;
275 /* perform access checks */
277 if ( !(sec_desc = construct_scm_sd( p->mem_ctx )) )
280 se_map_generic( &r->in.access_mask, &scm_generic_map );
281 status = svcctl_access_check( sec_desc, p->server_info->security_token,
282 r->in.access_mask, &access_granted );
283 if ( !NT_STATUS_IS_OK(status) )
284 return ntstatus_to_werror( status );
286 return create_open_service_handle( p, r->out.handle, SVC_HANDLE_IS_SCM, NULL, access_granted );
289 /********************************************************************
291 ********************************************************************/
293 WERROR _svcctl_OpenServiceW(struct pipes_struct *p,
294 struct svcctl_OpenServiceW *r)
296 struct security_descriptor *sec_desc;
297 uint32 access_granted = 0;
299 const char *service = NULL;
301 service = r->in.ServiceName;
305 DEBUG(5, ("_svcctl_OpenServiceW: Attempting to open Service [%s], \n", service));
307 /* based on my tests you can open a service if you have a valid scm handle */
309 if ( !find_service_info_by_hnd( p, r->in.scmanager_handle) )
313 * Perform access checks. Use the system server_info in order to ensure
314 * that we retrieve the security descriptor
316 sec_desc = svcctl_get_secdesc(p->mem_ctx,
318 get_server_info_system(),
320 if (sec_desc == NULL) {
321 DEBUG(0, ("_svcctl_OpenServiceW: Failed to get a valid security "
326 se_map_generic( &r->in.access_mask, &svc_generic_map );
327 status = svcctl_access_check( sec_desc, p->server_info->security_token,
328 r->in.access_mask, &access_granted );
329 if ( !NT_STATUS_IS_OK(status) )
330 return ntstatus_to_werror( status );
332 return create_open_service_handle( p, r->out.handle, SVC_HANDLE_IS_SERVICE, service, access_granted );
335 /********************************************************************
336 _svcctl_CloseServiceHandle
337 ********************************************************************/
339 WERROR _svcctl_CloseServiceHandle(struct pipes_struct *p,
340 struct svcctl_CloseServiceHandle *r)
342 if ( !close_policy_hnd( p, r->in.handle ) )
345 ZERO_STRUCTP(r->out.handle);
350 /********************************************************************
351 _svcctl_GetServiceDisplayNameW
352 ********************************************************************/
354 WERROR _svcctl_GetServiceDisplayNameW(struct pipes_struct *p,
355 struct svcctl_GetServiceDisplayNameW *r)
358 const char *display_name;
359 SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
361 /* can only use an SCM handle here */
363 if ( !info || (info->type != SVC_HANDLE_IS_SCM) )
366 service = r->in.service_name;
368 display_name = svcctl_lookup_dispname(p->mem_ctx,
376 *r->out.display_name = display_name;
377 *r->out.display_name_length = strlen(display_name);
382 /********************************************************************
383 _svcctl_QueryServiceStatus
384 ********************************************************************/
386 WERROR _svcctl_QueryServiceStatus(struct pipes_struct *p,
387 struct svcctl_QueryServiceStatus *r)
389 SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
391 /* perform access checks */
393 if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
396 if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_STATUS) )
397 return WERR_ACCESS_DENIED;
399 /* try the service specific status call */
401 return info->ops->service_status( info->name, r->out.service_status );
404 /********************************************************************
405 ********************************************************************/
407 static int enumerate_status(TALLOC_CTX *ctx,
408 struct messaging_context *msg_ctx,
409 struct auth_serversupplied_info *server_info,
410 struct ENUM_SERVICE_STATUSW **status)
412 int num_services = 0;
414 struct ENUM_SERVICE_STATUSW *st;
415 const char *display_name;
418 while ( svcctl_ops[num_services].name )
421 if ( !(st = TALLOC_ARRAY( ctx, struct ENUM_SERVICE_STATUSW, num_services )) ) {
422 DEBUG(0,("enumerate_status: talloc() failed!\n"));
426 for ( i=0; i<num_services; i++ ) {
427 st[i].service_name = talloc_strdup(st, svcctl_ops[i].name );
429 display_name = svcctl_lookup_dispname(ctx,
433 st[i].display_name = talloc_strdup(st, display_name ? display_name : "");
435 svcctl_ops[i].ops->service_status( svcctl_ops[i].name, &st[i].status );
443 /********************************************************************
444 _svcctl_EnumServicesStatusW
445 ********************************************************************/
447 WERROR _svcctl_EnumServicesStatusW(struct pipes_struct *p,
448 struct svcctl_EnumServicesStatusW *r)
450 struct ENUM_SERVICE_STATUSW *services = NULL;
453 size_t buffer_size = 0;
454 WERROR result = WERR_OK;
455 SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
456 DATA_BLOB blob = data_blob_null;
458 /* perform access checks */
460 if ( !info || (info->type != SVC_HANDLE_IS_SCM) )
463 if ( !(info->access_granted & SC_RIGHT_MGR_ENUMERATE_SERVICE) ) {
464 return WERR_ACCESS_DENIED;
467 num_services = enumerate_status(p->mem_ctx,
471 if (num_services == -1 ) {
475 for ( i=0; i<num_services; i++ ) {
476 buffer_size += ndr_size_ENUM_SERVICE_STATUSW(&services[i], 0);
479 buffer_size += buffer_size % 4;
481 if (buffer_size > r->in.offered) {
483 result = WERR_MORE_DATA;
486 if ( W_ERROR_IS_OK(result) ) {
488 enum ndr_err_code ndr_err;
489 struct ndr_push *ndr;
491 ndr = ndr_push_init_ctx(p->mem_ctx);
493 return WERR_INVALID_PARAM;
496 ndr_err = ndr_push_ENUM_SERVICE_STATUSW_array(
497 ndr, num_services, services);
498 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
499 return ntstatus_to_werror(ndr_map_error2ntstatus(ndr_err));
501 blob = ndr_push_blob(ndr);
502 memcpy(r->out.service, blob.data, MIN(blob.length, r->in.offered));
505 *r->out.needed = (buffer_size > r->in.offered) ? buffer_size : r->in.offered;
506 *r->out.services_returned = (uint32)num_services;
507 if (r->out.resume_handle) {
508 *r->out.resume_handle = 0;
514 /********************************************************************
515 _svcctl_StartServiceW
516 ********************************************************************/
518 WERROR _svcctl_StartServiceW(struct pipes_struct *p,
519 struct svcctl_StartServiceW *r)
521 SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
523 /* perform access checks */
525 if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
528 if ( !(info->access_granted & SC_RIGHT_SVC_START) )
529 return WERR_ACCESS_DENIED;
531 return info->ops->start_service( info->name );
534 /********************************************************************
535 _svcctl_ControlService
536 ********************************************************************/
538 WERROR _svcctl_ControlService(struct pipes_struct *p,
539 struct svcctl_ControlService *r)
541 SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
543 /* perform access checks */
545 if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
548 switch ( r->in.control ) {
549 case SVCCTL_CONTROL_STOP:
550 if ( !(info->access_granted & SC_RIGHT_SVC_STOP) )
551 return WERR_ACCESS_DENIED;
553 return info->ops->stop_service( info->name,
554 r->out.service_status );
556 case SVCCTL_CONTROL_INTERROGATE:
557 if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_STATUS) )
558 return WERR_ACCESS_DENIED;
560 return info->ops->service_status( info->name,
561 r->out.service_status );
563 return WERR_INVALID_PARAM;
567 /********************************************************************
568 _svcctl_EnumDependentServicesW
569 ********************************************************************/
571 WERROR _svcctl_EnumDependentServicesW(struct pipes_struct *p,
572 struct svcctl_EnumDependentServicesW *r)
574 SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.service );
576 /* perform access checks */
578 if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
581 if ( !(info->access_granted & SC_RIGHT_SVC_ENUMERATE_DEPENDENTS) )
582 return WERR_ACCESS_DENIED;
584 switch (r->in.state) {
585 case SERVICE_STATE_ACTIVE:
586 case SERVICE_STATE_INACTIVE:
587 case SERVICE_STATE_ALL:
590 return WERR_INVALID_PARAM;
593 /* we have to set the outgoing buffer size to the same as the
594 incoming buffer size (even in the case of failure */
595 /* this is done in the autogenerated server already - gd */
597 *r->out.needed = r->in.offered;
599 /* no dependent services...basically a stub function */
600 *r->out.services_returned = 0;
605 /********************************************************************
606 _svcctl_QueryServiceStatusEx
607 ********************************************************************/
609 WERROR _svcctl_QueryServiceStatusEx(struct pipes_struct *p,
610 struct svcctl_QueryServiceStatusEx *r)
612 SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
615 /* perform access checks */
617 if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
620 if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_STATUS) )
621 return WERR_ACCESS_DENIED;
623 /* we have to set the outgoing buffer size to the same as the
624 incoming buffer size (even in the case of failure) */
625 *r->out.needed = r->in.offered;
627 switch ( r->in.info_level ) {
628 case SVC_STATUS_PROCESS_INFO:
630 struct SERVICE_STATUS_PROCESS svc_stat_proc;
631 enum ndr_err_code ndr_err;
634 /* Get the status of the service.. */
635 info->ops->service_status( info->name, &svc_stat_proc.status );
636 svc_stat_proc.process_id = sys_getpid();
637 svc_stat_proc.service_flags = 0x0;
639 ndr_err = ndr_push_struct_blob(&blob, p->mem_ctx, &svc_stat_proc,
640 (ndr_push_flags_fn_t)ndr_push_SERVICE_STATUS_PROCESS);
641 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
642 return WERR_INVALID_PARAM;
645 r->out.buffer = blob.data;
646 buffer_size = sizeof(struct SERVICE_STATUS_PROCESS);
651 return WERR_UNKNOWN_LEVEL;
655 buffer_size += buffer_size % 4;
656 *r->out.needed = (buffer_size > r->in.offered) ? buffer_size : r->in.offered;
658 if (buffer_size > r->in.offered ) {
659 return WERR_INSUFFICIENT_BUFFER;
665 /********************************************************************
666 ********************************************************************/
668 static WERROR fill_svc_config(TALLOC_CTX *ctx,
669 struct messaging_context *msg_ctx,
670 struct auth_serversupplied_info *server_info,
672 struct QUERY_SERVICE_CONFIG *config)
674 TALLOC_CTX *mem_ctx = talloc_stackframe();
675 const char *result = NULL;
677 /* now fill in the individual values */
679 config->displayname = svcctl_lookup_dispname(mem_ctx,
684 result = svcctl_get_string_value(mem_ctx,
689 if (result != NULL) {
690 config->startname = result;
693 result = svcctl_get_string_value(mem_ctx,
698 if (result != NULL) {
699 config->executablepath = result;
702 /* a few hard coded values */
703 /* loadordergroup and dependencies are empty */
705 config->tag_id = 0x00000000; /* unassigned loadorder group */
706 config->service_type = SERVICE_TYPE_WIN32_OWN_PROCESS;
707 config->error_control = SVCCTL_SVC_ERROR_NORMAL;
709 /* set the start type. NetLogon and WINS are disabled to prevent
710 the client from showing the "Start" button (if of course the services
713 if ( strequal( name, "NETLOGON" ) && ( lp_servicenumber(name) == -1 ) )
714 config->start_type = SVCCTL_DISABLED;
715 else if ( strequal( name, "WINS" ) && ( !lp_wins_support() ))
716 config->start_type = SVCCTL_DISABLED;
718 config->start_type = SVCCTL_DEMAND_START;
721 talloc_free(mem_ctx);
726 /********************************************************************
727 _svcctl_QueryServiceConfigW
728 ********************************************************************/
730 WERROR _svcctl_QueryServiceConfigW(struct pipes_struct *p,
731 struct svcctl_QueryServiceConfigW *r)
733 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 */
748 *r->out.needed = r->in.offered;
750 wresult = fill_svc_config(p->mem_ctx,
755 if ( !W_ERROR_IS_OK(wresult) )
758 buffer_size = ndr_size_QUERY_SERVICE_CONFIG(r->out.query, 0);
759 *r->out.needed = (buffer_size > r->in.offered) ? buffer_size : r->in.offered;
761 if (buffer_size > r->in.offered ) {
762 ZERO_STRUCTP(r->out.query);
763 return WERR_INSUFFICIENT_BUFFER;
769 /********************************************************************
770 _svcctl_QueryServiceConfig2W
771 ********************************************************************/
773 WERROR _svcctl_QueryServiceConfig2W(struct pipes_struct *p,
774 struct svcctl_QueryServiceConfig2W *r)
776 SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
779 /* perform access checks */
781 if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
784 if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_CONFIG) )
785 return WERR_ACCESS_DENIED;
787 /* we have to set the outgoing buffer size to the same as the
788 incoming buffer size (even in the case of failure */
789 *r->out.needed = r->in.offered;
791 switch ( r->in.info_level ) {
792 case SERVICE_CONFIG_DESCRIPTION:
794 struct SERVICE_DESCRIPTION desc_buf;
795 const char *description;
796 enum ndr_err_code ndr_err;
799 description = svcctl_lookup_description(p->mem_ctx,
804 desc_buf.description = description;
806 ndr_err = ndr_push_struct_blob(&blob, p->mem_ctx, &desc_buf,
807 (ndr_push_flags_fn_t)ndr_push_SERVICE_DESCRIPTION);
808 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
809 return WERR_INVALID_PARAM;
812 buffer_size = ndr_size_SERVICE_DESCRIPTION(&desc_buf, 0);
813 r->out.buffer = blob.data;
818 case SERVICE_CONFIG_FAILURE_ACTIONS:
820 struct SERVICE_FAILURE_ACTIONS actions;
821 enum ndr_err_code ndr_err;
824 /* nothing to say...just service the request */
826 ZERO_STRUCT( actions );
828 ndr_err = ndr_push_struct_blob(&blob, p->mem_ctx, &actions,
829 (ndr_push_flags_fn_t)ndr_push_SERVICE_FAILURE_ACTIONS);
830 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
831 return WERR_INVALID_PARAM;
834 buffer_size = ndr_size_SERVICE_FAILURE_ACTIONS(&actions, 0);
835 r->out.buffer = blob.data;
842 return WERR_UNKNOWN_LEVEL;
845 buffer_size += buffer_size % 4;
846 *r->out.needed = (buffer_size > r->in.offered) ? buffer_size : r->in.offered;
848 if (buffer_size > r->in.offered)
849 return WERR_INSUFFICIENT_BUFFER;
854 /********************************************************************
855 _svcctl_LockServiceDatabase
856 ********************************************************************/
858 WERROR _svcctl_LockServiceDatabase(struct pipes_struct *p,
859 struct svcctl_LockServiceDatabase *r)
861 SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
863 /* perform access checks */
865 if ( !info || (info->type != SVC_HANDLE_IS_SCM) )
868 if ( !(info->access_granted & SC_RIGHT_MGR_LOCK) )
869 return WERR_ACCESS_DENIED;
871 /* Just open a handle. Doesn't actually lock anything */
873 return create_open_service_handle( p, r->out.lock, SVC_HANDLE_IS_DBLOCK, NULL, 0 );
876 /********************************************************************
877 _svcctl_UnlockServiceDatabase
878 ********************************************************************/
880 WERROR _svcctl_UnlockServiceDatabase(struct pipes_struct *p,
881 struct svcctl_UnlockServiceDatabase *r)
883 SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.lock );
886 if ( !info || (info->type != SVC_HANDLE_IS_DBLOCK) )
889 return close_policy_hnd( p, r->out.lock) ? WERR_OK : WERR_BADFID;
892 /********************************************************************
893 _svcctl_QueryServiceObjectSecurity
894 ********************************************************************/
896 WERROR _svcctl_QueryServiceObjectSecurity(struct pipes_struct *p,
897 struct svcctl_QueryServiceObjectSecurity *r)
899 SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
900 struct security_descriptor *sec_desc;
902 uint8_t *buffer = NULL;
906 /* only support the SCM and individual services */
908 if ( !info || !(info->type & (SVC_HANDLE_IS_SERVICE|SVC_HANDLE_IS_SCM)) )
911 /* check access reights (according to MSDN) */
913 if ( !(info->access_granted & SEC_STD_READ_CONTROL) )
914 return WERR_ACCESS_DENIED;
916 /* TODO: handle something besides SECINFO_DACL */
918 if ( (r->in.security_flags & SECINFO_DACL) != SECINFO_DACL )
919 return WERR_INVALID_PARAM;
921 /* Lookup the security descriptor and marshall it up for a reply */
922 sec_desc = svcctl_get_secdesc(p->mem_ctx,
924 get_server_info_system(),
926 if (sec_desc == NULL) {
930 *r->out.needed = ndr_size_security_descriptor(sec_desc, 0);
932 if ( *r->out.needed > r->in.offered) {
933 return WERR_INSUFFICIENT_BUFFER;
936 status = marshall_sec_desc(p->mem_ctx, sec_desc, &buffer, &len);
937 if (!NT_STATUS_IS_OK(status)) {
938 return ntstatus_to_werror(status);
941 *r->out.needed = len;
942 r->out.buffer = buffer;
947 /********************************************************************
948 _svcctl_SetServiceObjectSecurity
949 ********************************************************************/
951 WERROR _svcctl_SetServiceObjectSecurity(struct pipes_struct *p,
952 struct svcctl_SetServiceObjectSecurity *r)
954 SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
955 struct security_descriptor *sec_desc = NULL;
956 uint32 required_access;
959 if ( !info || !(info->type & (SVC_HANDLE_IS_SERVICE|SVC_HANDLE_IS_SCM)) )
962 /* can't set the security de4scriptor on the ServiceControlManager */
964 if ( info->type == SVC_HANDLE_IS_SCM )
965 return WERR_ACCESS_DENIED;
967 /* check the access on the open handle */
969 switch ( r->in.security_flags ) {
971 required_access = SEC_STD_WRITE_DAC;
976 required_access = SEC_STD_WRITE_OWNER;
980 return WERR_INVALID_PARAM;
982 return WERR_INVALID_PARAM;
985 if ( !(info->access_granted & required_access) )
986 return WERR_ACCESS_DENIED;
988 /* read the security descfriptor */
990 status = unmarshall_sec_desc(p->mem_ctx,
994 if (!NT_STATUS_IS_OK(status)) {
995 return ntstatus_to_werror(status);
998 /* store the new SD */
1000 if (!svcctl_set_secdesc(p->msg_ctx, p->server_info, info->name, sec_desc))
1001 return WERR_ACCESS_DENIED;
1007 WERROR _svcctl_DeleteService(struct pipes_struct *p,
1008 struct svcctl_DeleteService *r)
1010 p->rng_fault_state = True;
1011 return WERR_NOT_SUPPORTED;
1014 WERROR _svcctl_SetServiceStatus(struct pipes_struct *p,
1015 struct svcctl_SetServiceStatus *r)
1017 p->rng_fault_state = True;
1018 return WERR_NOT_SUPPORTED;
1021 WERROR _svcctl_NotifyBootConfigStatus(struct pipes_struct *p,
1022 struct svcctl_NotifyBootConfigStatus *r)
1024 p->rng_fault_state = True;
1025 return WERR_NOT_SUPPORTED;
1028 WERROR _svcctl_SCSetServiceBitsW(struct pipes_struct *p,
1029 struct svcctl_SCSetServiceBitsW *r)
1031 p->rng_fault_state = True;
1032 return WERR_NOT_SUPPORTED;
1035 WERROR _svcctl_ChangeServiceConfigW(struct pipes_struct *p,
1036 struct svcctl_ChangeServiceConfigW *r)
1038 p->rng_fault_state = True;
1039 return WERR_NOT_SUPPORTED;
1042 WERROR _svcctl_CreateServiceW(struct pipes_struct *p,
1043 struct svcctl_CreateServiceW *r)
1045 p->rng_fault_state = True;
1046 return WERR_NOT_SUPPORTED;
1049 WERROR _svcctl_QueryServiceLockStatusW(struct pipes_struct *p,
1050 struct svcctl_QueryServiceLockStatusW *r)
1052 p->rng_fault_state = True;
1053 return WERR_NOT_SUPPORTED;
1056 WERROR _svcctl_GetServiceKeyNameW(struct pipes_struct *p,
1057 struct svcctl_GetServiceKeyNameW *r)
1059 p->rng_fault_state = True;
1060 return WERR_NOT_SUPPORTED;
1063 WERROR _svcctl_SCSetServiceBitsA(struct pipes_struct *p,
1064 struct svcctl_SCSetServiceBitsA *r)
1066 p->rng_fault_state = True;
1067 return WERR_NOT_SUPPORTED;
1070 WERROR _svcctl_ChangeServiceConfigA(struct pipes_struct *p,
1071 struct svcctl_ChangeServiceConfigA *r)
1073 p->rng_fault_state = True;
1074 return WERR_NOT_SUPPORTED;
1077 WERROR _svcctl_CreateServiceA(struct pipes_struct *p,
1078 struct svcctl_CreateServiceA *r)
1080 p->rng_fault_state = True;
1081 return WERR_NOT_SUPPORTED;
1084 WERROR _svcctl_EnumDependentServicesA(struct pipes_struct *p,
1085 struct svcctl_EnumDependentServicesA *r)
1087 p->rng_fault_state = True;
1088 return WERR_NOT_SUPPORTED;
1091 WERROR _svcctl_EnumServicesStatusA(struct pipes_struct *p,
1092 struct svcctl_EnumServicesStatusA *r)
1094 p->rng_fault_state = True;
1095 return WERR_NOT_SUPPORTED;
1098 WERROR _svcctl_OpenSCManagerA(struct pipes_struct *p,
1099 struct svcctl_OpenSCManagerA *r)
1101 p->rng_fault_state = True;
1102 return WERR_NOT_SUPPORTED;
1105 WERROR _svcctl_OpenServiceA(struct pipes_struct *p,
1106 struct svcctl_OpenServiceA *r)
1108 p->rng_fault_state = True;
1109 return WERR_NOT_SUPPORTED;
1112 WERROR _svcctl_QueryServiceConfigA(struct pipes_struct *p,
1113 struct svcctl_QueryServiceConfigA *r)
1115 p->rng_fault_state = True;
1116 return WERR_NOT_SUPPORTED;
1119 WERROR _svcctl_QueryServiceLockStatusA(struct pipes_struct *p,
1120 struct svcctl_QueryServiceLockStatusA *r)
1122 p->rng_fault_state = True;
1123 return WERR_NOT_SUPPORTED;
1126 WERROR _svcctl_StartServiceA(struct pipes_struct *p,
1127 struct svcctl_StartServiceA *r)
1129 p->rng_fault_state = True;
1130 return WERR_NOT_SUPPORTED;
1133 WERROR _svcctl_GetServiceDisplayNameA(struct pipes_struct *p,
1134 struct svcctl_GetServiceDisplayNameA *r)
1136 p->rng_fault_state = True;
1137 return WERR_NOT_SUPPORTED;
1140 WERROR _svcctl_GetServiceKeyNameA(struct pipes_struct *p,
1141 struct svcctl_GetServiceKeyNameA *r)
1143 p->rng_fault_state = True;
1144 return WERR_NOT_SUPPORTED;
1147 WERROR _svcctl_GetCurrentGroupeStateW(struct pipes_struct *p,
1148 struct svcctl_GetCurrentGroupeStateW *r)
1150 p->rng_fault_state = True;
1151 return WERR_NOT_SUPPORTED;
1154 WERROR _svcctl_EnumServiceGroupW(struct pipes_struct *p,
1155 struct svcctl_EnumServiceGroupW *r)
1157 p->rng_fault_state = True;
1158 return WERR_NOT_SUPPORTED;
1161 WERROR _svcctl_ChangeServiceConfig2A(struct pipes_struct *p,
1162 struct svcctl_ChangeServiceConfig2A *r)
1164 p->rng_fault_state = True;
1165 return WERR_NOT_SUPPORTED;
1168 WERROR _svcctl_ChangeServiceConfig2W(struct pipes_struct *p,
1169 struct svcctl_ChangeServiceConfig2W *r)
1171 p->rng_fault_state = True;
1172 return WERR_NOT_SUPPORTED;
1175 WERROR _svcctl_QueryServiceConfig2A(struct pipes_struct *p,
1176 struct svcctl_QueryServiceConfig2A *r)
1178 p->rng_fault_state = True;
1179 return WERR_NOT_SUPPORTED;
1182 WERROR _EnumServicesStatusExA(struct pipes_struct *p,
1183 struct EnumServicesStatusExA *r)
1185 p->rng_fault_state = True;
1186 return WERR_NOT_SUPPORTED;
1189 WERROR _EnumServicesStatusExW(struct pipes_struct *p,
1190 struct EnumServicesStatusExW *r)
1192 p->rng_fault_state = True;
1193 return WERR_NOT_SUPPORTED;
1196 WERROR _svcctl_SCSendTSMessage(struct pipes_struct *p,
1197 struct svcctl_SCSendTSMessage *r)
1199 p->rng_fault_state = True;
1200 return WERR_NOT_SUPPORTED;