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 "../libcli/security/security.h"
29 #include "../librpc/gen_ndr/ndr_security.h"
30 #include "services/services.h"
31 #include "services/svc_winreg_glue.h"
33 #include "rpc_server/svcctl/srv_svcctl_nt.h"
35 #include "rpc_server/rpc_server.h"
36 #include "librpc/rpc/dcesrv_core.h"
37 #include "librpc/gen_ndr/ndr_svcctl.h"
38 #include "librpc/gen_ndr/ndr_svcctl_scompat.h"
39 #include "srv_svcctl_reg.h"
42 #define DBGC_CLASS DBGC_RPC_SRV
44 struct service_control_op {
46 SERVICE_CONTROL_OPS *ops;
49 /* handle external services */
50 extern SERVICE_CONTROL_OPS rcinit_svc_ops;
52 /* builtin services (see service_db.c and services/svc_*.c */
53 extern SERVICE_CONTROL_OPS spoolss_svc_ops;
54 extern SERVICE_CONTROL_OPS netlogon_svc_ops;
55 extern SERVICE_CONTROL_OPS winreg_svc_ops;
56 extern SERVICE_CONTROL_OPS wins_svc_ops;
58 /* make sure this number patches the number of builtin
59 SERVICE_CONTROL_OPS structure listed above */
61 #define SVCCTL_NUM_INTERNAL_SERVICES 4
63 struct service_control_op *svcctl_ops;
65 static const struct generic_mapping scm_generic_map =
66 { SC_MANAGER_READ_ACCESS, SC_MANAGER_WRITE_ACCESS, SC_MANAGER_EXECUTE_ACCESS, SC_MANAGER_ALL_ACCESS };
67 static const struct generic_mapping svc_generic_map =
68 { SERVICE_READ_ACCESS, SERVICE_WRITE_ACCESS, SERVICE_EXECUTE_ACCESS, SERVICE_ALL_ACCESS };
71 /********************************************************************
72 ********************************************************************/
74 bool init_service_op_table( void )
76 const char **service_list = lp_svcctl_list();
77 int num_services = SVCCTL_NUM_INTERNAL_SERVICES + str_list_length( service_list );
80 if ( !(svcctl_ops = talloc_array( NULL, struct service_control_op, num_services+1)) ) {
81 DEBUG(0,("init_service_op_table: talloc() failed!\n"));
85 /* services listed in smb.conf get the rc.init interface */
87 for ( i=0; service_list && service_list[i]; i++ ) {
88 svcctl_ops[i].name = talloc_strdup( svcctl_ops, service_list[i] );
89 svcctl_ops[i].ops = &rcinit_svc_ops;
92 /* add builtin services */
94 svcctl_ops[i].name = talloc_strdup( svcctl_ops, "Spooler" );
95 svcctl_ops[i].ops = &spoolss_svc_ops;
98 svcctl_ops[i].name = talloc_strdup( svcctl_ops, "NETLOGON" );
99 svcctl_ops[i].ops = &netlogon_svc_ops;
102 svcctl_ops[i].name = talloc_strdup( svcctl_ops, "RemoteRegistry" );
103 svcctl_ops[i].ops = &winreg_svc_ops;
106 svcctl_ops[i].name = talloc_strdup( svcctl_ops, "WINS" );
107 svcctl_ops[i].ops = &wins_svc_ops;
110 /* NULL terminate the array */
112 svcctl_ops[i].name = NULL;
113 svcctl_ops[i].ops = NULL;
118 bool shutdown_service_op_table(void)
120 TALLOC_FREE(svcctl_ops);
125 /********************************************************************
126 ********************************************************************/
128 static struct service_control_op* find_service_by_name( const char *name )
132 for ( i=0; svcctl_ops[i].name; i++ ) {
133 if ( strequal( name, svcctl_ops[i].name ) )
134 return &svcctl_ops[i];
139 /********************************************************************
140 ********************************************************************/
142 static NTSTATUS svcctl_access_check( struct security_descriptor *sec_desc, struct security_token *token,
143 uint32_t access_desired, uint32_t *access_granted )
146 if ( geteuid() == sec_initial_uid() ) {
147 DEBUG(5,("svcctl_access_check: using root's token\n"));
148 status = get_root_nt_token(&token);
149 if(!NT_STATUS_IS_OK(status)) {
154 return se_access_check( sec_desc, token, access_desired, access_granted);
157 /********************************************************************
158 ********************************************************************/
160 static struct security_descriptor* construct_scm_sd( TALLOC_CTX *ctx )
162 struct security_ace ace[2];
164 struct security_descriptor *sd;
165 struct security_acl *theacl;
168 /* basic access for Everyone */
170 init_sec_ace(&ace[i++], &global_sid_World,
171 SEC_ACE_TYPE_ACCESS_ALLOWED, SC_MANAGER_READ_ACCESS, 0);
173 /* Full Access 'BUILTIN\Administrators' */
175 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
176 SEC_ACE_TYPE_ACCESS_ALLOWED, SC_MANAGER_ALL_ACCESS, 0);
179 /* create the security descriptor */
181 if ( !(theacl = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) )
184 if ( !(sd = make_sec_desc(ctx, SECURITY_DESCRIPTOR_REVISION_1,
185 SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL,
192 /******************************************************************
193 Find a registry key handle and return a SERVICE_INFO
194 *****************************************************************/
196 static SERVICE_INFO *find_service_info_by_hnd(struct pipes_struct *p,
197 struct policy_handle *hnd)
199 SERVICE_INFO *service_info = NULL;
202 service_info = find_policy_by_hnd(p,
207 if (!NT_STATUS_IS_OK(status)) {
208 DEBUG(2,("find_service_info_by_hnd: handle not found\n"));
215 /******************************************************************
216 *****************************************************************/
218 static WERROR create_open_service_handle(struct pipes_struct *p,
219 struct policy_handle *handle,
222 uint32_t access_granted)
224 SERVICE_INFO *info = NULL;
225 WERROR result = WERR_OK;
226 struct service_control_op *s_op;
228 if ( !(info = talloc_zero( NULL, SERVICE_INFO )) )
229 return WERR_NOT_ENOUGH_MEMORY;
231 /* the Service Manager has a NULL name */
233 info->type = SVC_HANDLE_IS_SCM;
236 case SVC_HANDLE_IS_SCM:
237 info->type = SVC_HANDLE_IS_SCM;
240 case SVC_HANDLE_IS_DBLOCK:
241 info->type = SVC_HANDLE_IS_DBLOCK;
244 case SVC_HANDLE_IS_SERVICE:
245 info->type = SVC_HANDLE_IS_SERVICE;
247 /* lookup the SERVICE_CONTROL_OPS */
249 if ( !(s_op = find_service_by_name( service )) ) {
250 result = WERR_SERVICE_DOES_NOT_EXIST;
254 info->ops = s_op->ops;
256 if ( !(info->name = talloc_strdup( info, s_op->name )) ) {
257 result = WERR_NOT_ENOUGH_MEMORY;
263 result = WERR_SERVICE_DOES_NOT_EXIST;
267 info->access_granted = access_granted;
269 /* store the SERVICE_INFO and create an open handle */
271 if ( !create_policy_hnd( p, handle, 0, info ) ) {
272 result = WERR_ACCESS_DENIED;
277 if ( !W_ERROR_IS_OK(result) )
283 /********************************************************************
284 _svcctl_OpenSCManagerW
285 ********************************************************************/
287 WERROR _svcctl_OpenSCManagerW(struct pipes_struct *p,
288 struct svcctl_OpenSCManagerW *r)
290 struct security_descriptor *sec_desc;
291 uint32_t access_granted = 0;
294 /* perform access checks */
296 if ( !(sec_desc = construct_scm_sd( p->mem_ctx )) )
297 return WERR_NOT_ENOUGH_MEMORY;
299 se_map_generic( &r->in.access_mask, &scm_generic_map );
300 status = svcctl_access_check( sec_desc, p->session_info->security_token,
301 r->in.access_mask, &access_granted );
302 if ( !NT_STATUS_IS_OK(status) )
303 return ntstatus_to_werror( status );
305 return create_open_service_handle( p, r->out.handle, SVC_HANDLE_IS_SCM, NULL, access_granted );
308 /********************************************************************
310 ********************************************************************/
312 WERROR _svcctl_OpenServiceW(struct pipes_struct *p,
313 struct svcctl_OpenServiceW *r)
315 struct security_descriptor *sec_desc;
316 uint32_t access_granted = 0;
318 const char *service = NULL;
321 service = r->in.ServiceName;
323 return WERR_NOT_ENOUGH_MEMORY;
325 DEBUG(5, ("_svcctl_OpenServiceW: Attempting to open Service [%s], \n", service));
327 /* based on my tests you can open a service if you have a valid scm handle */
329 if ( !find_service_info_by_hnd( p, r->in.scmanager_handle) )
330 return WERR_INVALID_HANDLE;
333 * Perform access checks. Use the system session_info in order to ensure
334 * that we retrieve the security descriptor
336 err = svcctl_get_secdesc(p->msg_ctx,
337 get_session_info_system(),
341 if (W_ERROR_EQUAL(err, WERR_FILE_NOT_FOUND)) {
342 DBG_NOTICE("service %s does not exist\n", service);
343 return WERR_SERVICE_DOES_NOT_EXIST;
345 if (!W_ERROR_IS_OK(err)) {
346 DBG_NOTICE("Failed to get a valid secdesc for %s: %s\n",
347 service, win_errstr(err));
351 se_map_generic( &r->in.access_mask, &svc_generic_map );
352 status = svcctl_access_check( sec_desc, p->session_info->security_token,
353 r->in.access_mask, &access_granted );
354 if ( !NT_STATUS_IS_OK(status) )
355 return ntstatus_to_werror( status );
357 return create_open_service_handle( p, r->out.handle, SVC_HANDLE_IS_SERVICE, service, access_granted );
360 /********************************************************************
361 _svcctl_CloseServiceHandle
362 ********************************************************************/
364 WERROR _svcctl_CloseServiceHandle(struct pipes_struct *p,
365 struct svcctl_CloseServiceHandle *r)
367 if ( !close_policy_hnd( p, r->in.handle ) )
368 return WERR_INVALID_HANDLE;
370 ZERO_STRUCTP(r->out.handle);
375 /********************************************************************
376 _svcctl_GetServiceDisplayNameW
377 ********************************************************************/
379 WERROR _svcctl_GetServiceDisplayNameW(struct pipes_struct *p,
380 struct svcctl_GetServiceDisplayNameW *r)
383 const char *display_name;
384 SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
386 /* can only use an SCM handle here */
388 if ( !info || (info->type != SVC_HANDLE_IS_SCM) )
389 return WERR_INVALID_HANDLE;
391 service = r->in.service_name;
393 display_name = svcctl_lookup_dispname(p->mem_ctx,
401 *r->out.display_name = display_name;
402 *r->out.display_name_length = strlen(display_name);
407 /********************************************************************
408 _svcctl_QueryServiceStatus
409 ********************************************************************/
411 WERROR _svcctl_QueryServiceStatus(struct pipes_struct *p,
412 struct svcctl_QueryServiceStatus *r)
414 SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
416 /* perform access checks */
418 if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
419 return WERR_INVALID_HANDLE;
421 if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_STATUS) )
422 return WERR_ACCESS_DENIED;
424 /* try the service specific status call */
426 return info->ops->service_status( info->name, r->out.service_status );
429 /********************************************************************
430 ********************************************************************/
432 static int enumerate_status(TALLOC_CTX *ctx,
433 struct messaging_context *msg_ctx,
434 struct auth_session_info *session_info,
435 struct ENUM_SERVICE_STATUSW **status)
437 int num_services = 0;
439 struct ENUM_SERVICE_STATUSW *st;
440 const char *display_name;
443 while ( svcctl_ops[num_services].name )
446 if ( !(st = talloc_array( ctx, struct ENUM_SERVICE_STATUSW, num_services )) ) {
447 DEBUG(0,("enumerate_status: talloc() failed!\n"));
451 for ( i=0; i<num_services; i++ ) {
452 st[i].service_name = talloc_strdup(st, svcctl_ops[i].name );
454 display_name = svcctl_lookup_dispname(ctx,
458 st[i].display_name = talloc_strdup(st, display_name ? display_name : "");
460 svcctl_ops[i].ops->service_status( svcctl_ops[i].name, &st[i].status );
468 /********************************************************************
469 _svcctl_EnumServicesStatusW
470 ********************************************************************/
472 WERROR _svcctl_EnumServicesStatusW(struct pipes_struct *p,
473 struct svcctl_EnumServicesStatusW *r)
475 struct ENUM_SERVICE_STATUSW *services = NULL;
478 size_t buffer_size = 0;
479 WERROR result = WERR_OK;
480 SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
481 DATA_BLOB blob = data_blob_null;
483 /* perform access checks */
485 if ( !info || (info->type != SVC_HANDLE_IS_SCM) )
486 return WERR_INVALID_HANDLE;
488 if ( !(info->access_granted & SC_RIGHT_MGR_ENUMERATE_SERVICE) ) {
489 return WERR_ACCESS_DENIED;
492 num_services = enumerate_status(p->mem_ctx,
496 if (num_services == -1 ) {
497 return WERR_NOT_ENOUGH_MEMORY;
500 for ( i=0; i<num_services; i++ ) {
501 buffer_size += ndr_size_ENUM_SERVICE_STATUSW(&services[i], 0);
504 buffer_size += buffer_size % 4;
506 if (buffer_size > r->in.offered) {
508 result = WERR_MORE_DATA;
511 if ( W_ERROR_IS_OK(result) ) {
513 enum ndr_err_code ndr_err;
514 struct ndr_push *ndr;
516 ndr = ndr_push_init_ctx(p->mem_ctx);
518 return WERR_INVALID_PARAMETER;
521 ndr_err = ndr_push_ENUM_SERVICE_STATUSW_array(
522 ndr, num_services, services);
523 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
524 return ntstatus_to_werror(ndr_map_error2ntstatus(ndr_err));
526 blob = ndr_push_blob(ndr);
527 memcpy(r->out.service, blob.data, MIN(blob.length, r->in.offered));
530 *r->out.needed = (buffer_size > r->in.offered) ? buffer_size : r->in.offered;
531 *r->out.services_returned = (uint32_t)num_services;
532 if (r->out.resume_handle) {
533 *r->out.resume_handle = 0;
539 /********************************************************************
540 _svcctl_StartServiceW
541 ********************************************************************/
543 WERROR _svcctl_StartServiceW(struct pipes_struct *p,
544 struct svcctl_StartServiceW *r)
546 SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
548 /* perform access checks */
550 if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
551 return WERR_INVALID_HANDLE;
553 if ( !(info->access_granted & SC_RIGHT_SVC_START) )
554 return WERR_ACCESS_DENIED;
556 return info->ops->start_service( info->name );
559 /********************************************************************
560 _svcctl_ControlService
561 ********************************************************************/
563 WERROR _svcctl_ControlService(struct pipes_struct *p,
564 struct svcctl_ControlService *r)
566 SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
568 /* perform access checks */
570 if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
571 return WERR_INVALID_HANDLE;
573 switch ( r->in.control ) {
574 case SVCCTL_CONTROL_STOP:
575 if ( !(info->access_granted & SC_RIGHT_SVC_STOP) )
576 return WERR_ACCESS_DENIED;
578 return info->ops->stop_service( info->name,
579 r->out.service_status );
581 case SVCCTL_CONTROL_INTERROGATE:
582 if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_STATUS) )
583 return WERR_ACCESS_DENIED;
585 return info->ops->service_status( info->name,
586 r->out.service_status );
588 return WERR_INVALID_PARAMETER;
592 /********************************************************************
593 _svcctl_EnumDependentServicesW
594 ********************************************************************/
596 WERROR _svcctl_EnumDependentServicesW(struct pipes_struct *p,
597 struct svcctl_EnumDependentServicesW *r)
599 SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.service );
601 /* perform access checks */
603 if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
604 return WERR_INVALID_HANDLE;
606 if ( !(info->access_granted & SC_RIGHT_SVC_ENUMERATE_DEPENDENTS) )
607 return WERR_ACCESS_DENIED;
609 switch (r->in.state) {
610 case SERVICE_STATE_ACTIVE:
611 case SERVICE_STATE_INACTIVE:
612 case SERVICE_STATE_ALL:
615 return WERR_INVALID_PARAMETER;
618 /* we have to set the outgoing buffer size to the same as the
619 incoming buffer size (even in the case of failure */
620 /* this is done in the autogenerated server already - gd */
622 *r->out.needed = r->in.offered;
624 /* no dependent services...basically a stub function */
625 *r->out.services_returned = 0;
630 /********************************************************************
631 _svcctl_QueryServiceStatusEx
632 ********************************************************************/
634 WERROR _svcctl_QueryServiceStatusEx(struct pipes_struct *p,
635 struct svcctl_QueryServiceStatusEx *r)
637 SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
638 uint32_t buffer_size;
640 /* perform access checks */
642 if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
643 return WERR_INVALID_HANDLE;
645 if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_STATUS) )
646 return WERR_ACCESS_DENIED;
648 /* we have to set the outgoing buffer size to the same as the
649 incoming buffer size (even in the case of failure) */
650 *r->out.needed = r->in.offered;
652 switch ( r->in.info_level ) {
653 case SVC_STATUS_PROCESS_INFO:
655 struct SERVICE_STATUS_PROCESS svc_stat_proc;
656 enum ndr_err_code ndr_err;
659 /* Get the status of the service.. */
660 info->ops->service_status( info->name, &svc_stat_proc.status );
661 svc_stat_proc.process_id = getpid();
662 svc_stat_proc.service_flags = 0x0;
664 ndr_err = ndr_push_struct_blob(&blob, p->mem_ctx, &svc_stat_proc,
665 (ndr_push_flags_fn_t)ndr_push_SERVICE_STATUS_PROCESS);
666 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
667 return WERR_INVALID_PARAMETER;
670 r->out.buffer = blob.data;
671 buffer_size = sizeof(struct SERVICE_STATUS_PROCESS);
676 return WERR_INVALID_LEVEL;
680 buffer_size += buffer_size % 4;
681 *r->out.needed = (buffer_size > r->in.offered) ? buffer_size : r->in.offered;
683 if (buffer_size > r->in.offered ) {
684 return WERR_INSUFFICIENT_BUFFER;
690 /********************************************************************
691 ********************************************************************/
693 static WERROR fill_svc_config(TALLOC_CTX *mem_ctx,
694 struct messaging_context *msg_ctx,
695 struct auth_session_info *session_info,
697 struct QUERY_SERVICE_CONFIG *config)
699 const char *result = NULL;
701 /* now fill in the individual values */
703 ZERO_STRUCTP(config);
705 config->displayname = svcctl_lookup_dispname(mem_ctx,
710 result = svcctl_get_string_value(mem_ctx,
715 if (result != NULL) {
716 config->startname = result;
719 result = svcctl_get_string_value(mem_ctx,
724 if (result != NULL) {
725 config->executablepath = result;
728 /* a few hard coded values */
729 /* loadordergroup and dependencies are empty */
731 config->tag_id = 0x00000000; /* unassigned loadorder group */
732 config->service_type = SERVICE_TYPE_WIN32_OWN_PROCESS;
733 config->error_control = SVCCTL_SVC_ERROR_NORMAL;
735 /* set the start type. NetLogon and WINS are disabled to prevent
736 the client from showing the "Start" button (if of course the services
739 if ( strequal( name, "NETLOGON" ) && ( lp_servicenumber(name) == -1 ) )
740 config->start_type = SVCCTL_DISABLED;
741 else if ( strequal( name, "WINS" ) && ( !lp_we_are_a_wins_server() ))
742 config->start_type = SVCCTL_DISABLED;
744 config->start_type = SVCCTL_DEMAND_START;
749 /********************************************************************
750 _svcctl_QueryServiceConfigW
751 ********************************************************************/
753 WERROR _svcctl_QueryServiceConfigW(struct pipes_struct *p,
754 struct svcctl_QueryServiceConfigW *r)
756 SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
757 uint32_t buffer_size;
760 /* perform access checks */
762 if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
763 return WERR_INVALID_HANDLE;
765 if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_CONFIG) )
766 return WERR_ACCESS_DENIED;
768 /* we have to set the outgoing buffer size to the same as the
769 incoming buffer size (even in the case of failure */
771 *r->out.needed = r->in.offered;
773 wresult = fill_svc_config(p->mem_ctx,
778 if ( !W_ERROR_IS_OK(wresult) )
781 buffer_size = ndr_size_QUERY_SERVICE_CONFIG(r->out.query, 0);
782 *r->out.needed = (buffer_size > r->in.offered) ? buffer_size : r->in.offered;
784 if (buffer_size > r->in.offered ) {
785 ZERO_STRUCTP(r->out.query);
786 return WERR_INSUFFICIENT_BUFFER;
792 /********************************************************************
793 _svcctl_QueryServiceConfig2W
794 ********************************************************************/
796 WERROR _svcctl_QueryServiceConfig2W(struct pipes_struct *p,
797 struct svcctl_QueryServiceConfig2W *r)
799 SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
800 uint32_t buffer_size;
801 DATA_BLOB blob = data_blob_null;
803 /* perform access checks */
805 if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
806 return WERR_INVALID_HANDLE;
808 if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_CONFIG) )
809 return WERR_ACCESS_DENIED;
811 /* we have to set the outgoing buffer size to the same as the
812 incoming buffer size (even in the case of failure */
813 *r->out.needed = r->in.offered;
815 switch ( r->in.info_level ) {
816 case SERVICE_CONFIG_DESCRIPTION:
818 struct SERVICE_DESCRIPTION desc_buf;
819 const char *description;
820 enum ndr_err_code ndr_err;
822 description = svcctl_lookup_description(p->mem_ctx,
827 desc_buf.description = description;
829 ndr_err = ndr_push_struct_blob(&blob, p->mem_ctx, &desc_buf,
830 (ndr_push_flags_fn_t)ndr_push_SERVICE_DESCRIPTION);
831 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
832 return WERR_INVALID_PARAMETER;
838 case SERVICE_CONFIG_FAILURE_ACTIONS:
840 struct SERVICE_FAILURE_ACTIONS actions;
841 enum ndr_err_code ndr_err;
843 /* nothing to say...just service the request */
845 ZERO_STRUCT( actions );
847 ndr_err = ndr_push_struct_blob(&blob, p->mem_ctx, &actions,
848 (ndr_push_flags_fn_t)ndr_push_SERVICE_FAILURE_ACTIONS);
849 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
850 return WERR_INVALID_PARAMETER;
858 return WERR_INVALID_LEVEL;
861 buffer_size = blob.length;
862 buffer_size += buffer_size % 4;
863 *r->out.needed = (buffer_size > r->in.offered) ? buffer_size : r->in.offered;
865 if (buffer_size > r->in.offered)
866 return WERR_INSUFFICIENT_BUFFER;
868 memcpy(r->out.buffer, blob.data, blob.length);
873 /********************************************************************
874 _svcctl_LockServiceDatabase
875 ********************************************************************/
877 WERROR _svcctl_LockServiceDatabase(struct pipes_struct *p,
878 struct svcctl_LockServiceDatabase *r)
880 SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
882 /* perform access checks */
884 if ( !info || (info->type != SVC_HANDLE_IS_SCM) )
885 return WERR_INVALID_HANDLE;
887 if ( !(info->access_granted & SC_RIGHT_MGR_LOCK) )
888 return WERR_ACCESS_DENIED;
890 /* Just open a handle. Doesn't actually lock anything */
892 return create_open_service_handle( p, r->out.lock, SVC_HANDLE_IS_DBLOCK, NULL, 0 );
895 /********************************************************************
896 _svcctl_UnlockServiceDatabase
897 ********************************************************************/
899 WERROR _svcctl_UnlockServiceDatabase(struct pipes_struct *p,
900 struct svcctl_UnlockServiceDatabase *r)
902 SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.lock );
905 if ( !info || (info->type != SVC_HANDLE_IS_DBLOCK) )
906 return WERR_INVALID_HANDLE;
908 return close_policy_hnd( p, r->out.lock) ? WERR_OK : WERR_INVALID_HANDLE;
911 /********************************************************************
912 _svcctl_QueryServiceObjectSecurity
913 ********************************************************************/
915 WERROR _svcctl_QueryServiceObjectSecurity(struct pipes_struct *p,
916 struct svcctl_QueryServiceObjectSecurity *r)
918 SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
919 struct security_descriptor *sec_desc;
921 uint8_t *buffer = NULL;
926 /* only support the SCM and individual services */
928 if ( !info || !(info->type & (SVC_HANDLE_IS_SERVICE|SVC_HANDLE_IS_SCM)) )
929 return WERR_INVALID_HANDLE;
931 /* check access reights (according to MSDN) */
933 if ( !(info->access_granted & SEC_STD_READ_CONTROL) )
934 return WERR_ACCESS_DENIED;
936 /* TODO: handle something besides SECINFO_DACL */
938 if ( (r->in.security_flags & SECINFO_DACL) != SECINFO_DACL )
939 return WERR_INVALID_PARAMETER;
941 /* Lookup the security descriptor and marshall it up for a reply */
942 err = svcctl_get_secdesc(p->msg_ctx,
943 get_session_info_system(),
947 if (W_ERROR_EQUAL(err, WERR_FILE_NOT_FOUND)) {
948 DBG_NOTICE("service %s does not exist\n", info->name);
949 return WERR_SERVICE_DOES_NOT_EXIST;
951 if (!W_ERROR_IS_OK(err)) {
952 DBG_NOTICE("Failed to get a valid secdesc for %s: %s\n",
953 info->name, win_errstr(err));
957 *r->out.needed = ndr_size_security_descriptor(sec_desc, 0);
959 if ( *r->out.needed > r->in.offered) {
960 return WERR_INSUFFICIENT_BUFFER;
963 status = marshall_sec_desc(p->mem_ctx, sec_desc, &buffer, &len);
964 if (!NT_STATUS_IS_OK(status)) {
965 return ntstatus_to_werror(status);
968 *r->out.needed = len;
969 memcpy(r->out.buffer, buffer, len);
974 /********************************************************************
975 _svcctl_SetServiceObjectSecurity
976 ********************************************************************/
978 WERROR _svcctl_SetServiceObjectSecurity(struct pipes_struct *p,
979 struct svcctl_SetServiceObjectSecurity *r)
981 SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
982 struct security_descriptor *sec_desc = NULL;
983 uint32_t required_access;
986 if ( !info || !(info->type & (SVC_HANDLE_IS_SERVICE|SVC_HANDLE_IS_SCM)) )
987 return WERR_INVALID_HANDLE;
989 /* can't set the security de4scriptor on the ServiceControlManager */
991 if ( info->type == SVC_HANDLE_IS_SCM )
992 return WERR_ACCESS_DENIED;
994 /* check the access on the open handle */
996 switch ( r->in.security_flags ) {
998 required_access = SEC_STD_WRITE_DAC;
1003 required_access = SEC_STD_WRITE_OWNER;
1007 return WERR_INVALID_PARAMETER;
1009 return WERR_INVALID_PARAMETER;
1012 if ( !(info->access_granted & required_access) )
1013 return WERR_ACCESS_DENIED;
1015 /* read the security descfriptor */
1017 status = unmarshall_sec_desc(p->mem_ctx,
1021 if (!NT_STATUS_IS_OK(status)) {
1022 return ntstatus_to_werror(status);
1025 /* store the new SD */
1027 if (!svcctl_set_secdesc(p->msg_ctx, p->session_info, info->name, sec_desc))
1028 return WERR_ACCESS_DENIED;
1034 WERROR _svcctl_DeleteService(struct pipes_struct *p,
1035 struct svcctl_DeleteService *r)
1037 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1038 return WERR_NOT_SUPPORTED;
1041 WERROR _svcctl_SetServiceStatus(struct pipes_struct *p,
1042 struct svcctl_SetServiceStatus *r)
1044 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1045 return WERR_NOT_SUPPORTED;
1048 WERROR _svcctl_NotifyBootConfigStatus(struct pipes_struct *p,
1049 struct svcctl_NotifyBootConfigStatus *r)
1051 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1052 return WERR_NOT_SUPPORTED;
1055 WERROR _svcctl_SCSetServiceBitsW(struct pipes_struct *p,
1056 struct svcctl_SCSetServiceBitsW *r)
1058 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1059 return WERR_NOT_SUPPORTED;
1062 WERROR _svcctl_ChangeServiceConfigW(struct pipes_struct *p,
1063 struct svcctl_ChangeServiceConfigW *r)
1065 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1066 return WERR_NOT_SUPPORTED;
1069 WERROR _svcctl_CreateServiceW(struct pipes_struct *p,
1070 struct svcctl_CreateServiceW *r)
1072 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1073 return WERR_NOT_SUPPORTED;
1076 WERROR _svcctl_QueryServiceLockStatusW(struct pipes_struct *p,
1077 struct svcctl_QueryServiceLockStatusW *r)
1079 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1080 return WERR_NOT_SUPPORTED;
1083 WERROR _svcctl_GetServiceKeyNameW(struct pipes_struct *p,
1084 struct svcctl_GetServiceKeyNameW *r)
1086 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1087 return WERR_NOT_SUPPORTED;
1090 WERROR _svcctl_SCSetServiceBitsA(struct pipes_struct *p,
1091 struct svcctl_SCSetServiceBitsA *r)
1093 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1094 return WERR_NOT_SUPPORTED;
1097 WERROR _svcctl_ChangeServiceConfigA(struct pipes_struct *p,
1098 struct svcctl_ChangeServiceConfigA *r)
1100 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1101 return WERR_NOT_SUPPORTED;
1104 WERROR _svcctl_CreateServiceA(struct pipes_struct *p,
1105 struct svcctl_CreateServiceA *r)
1107 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1108 return WERR_NOT_SUPPORTED;
1111 WERROR _svcctl_EnumDependentServicesA(struct pipes_struct *p,
1112 struct svcctl_EnumDependentServicesA *r)
1114 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1115 return WERR_NOT_SUPPORTED;
1118 WERROR _svcctl_EnumServicesStatusA(struct pipes_struct *p,
1119 struct svcctl_EnumServicesStatusA *r)
1121 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1122 return WERR_NOT_SUPPORTED;
1125 WERROR _svcctl_OpenSCManagerA(struct pipes_struct *p,
1126 struct svcctl_OpenSCManagerA *r)
1128 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1129 return WERR_NOT_SUPPORTED;
1132 WERROR _svcctl_OpenServiceA(struct pipes_struct *p,
1133 struct svcctl_OpenServiceA *r)
1135 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1136 return WERR_NOT_SUPPORTED;
1139 WERROR _svcctl_QueryServiceConfigA(struct pipes_struct *p,
1140 struct svcctl_QueryServiceConfigA *r)
1142 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1143 return WERR_NOT_SUPPORTED;
1146 WERROR _svcctl_QueryServiceLockStatusA(struct pipes_struct *p,
1147 struct svcctl_QueryServiceLockStatusA *r)
1149 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1150 return WERR_NOT_SUPPORTED;
1153 WERROR _svcctl_StartServiceA(struct pipes_struct *p,
1154 struct svcctl_StartServiceA *r)
1156 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1157 return WERR_NOT_SUPPORTED;
1160 WERROR _svcctl_GetServiceDisplayNameA(struct pipes_struct *p,
1161 struct svcctl_GetServiceDisplayNameA *r)
1163 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1164 return WERR_NOT_SUPPORTED;
1167 WERROR _svcctl_GetServiceKeyNameA(struct pipes_struct *p,
1168 struct svcctl_GetServiceKeyNameA *r)
1170 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1171 return WERR_NOT_SUPPORTED;
1174 WERROR _svcctl_GetCurrentGroupeStateW(struct pipes_struct *p,
1175 struct svcctl_GetCurrentGroupeStateW *r)
1177 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1178 return WERR_NOT_SUPPORTED;
1181 WERROR _svcctl_EnumServiceGroupW(struct pipes_struct *p,
1182 struct svcctl_EnumServiceGroupW *r)
1184 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1185 return WERR_NOT_SUPPORTED;
1188 WERROR _svcctl_ChangeServiceConfig2A(struct pipes_struct *p,
1189 struct svcctl_ChangeServiceConfig2A *r)
1191 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1192 return WERR_NOT_SUPPORTED;
1195 WERROR _svcctl_ChangeServiceConfig2W(struct pipes_struct *p,
1196 struct svcctl_ChangeServiceConfig2W *r)
1198 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1199 return WERR_NOT_SUPPORTED;
1202 WERROR _svcctl_QueryServiceConfig2A(struct pipes_struct *p,
1203 struct svcctl_QueryServiceConfig2A *r)
1205 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1206 return WERR_NOT_SUPPORTED;
1209 WERROR _EnumServicesStatusExA(struct pipes_struct *p,
1210 struct EnumServicesStatusExA *r)
1212 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1213 return WERR_NOT_SUPPORTED;
1216 WERROR _EnumServicesStatusExW(struct pipes_struct *p,
1217 struct EnumServicesStatusExW *r)
1219 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1220 return WERR_NOT_SUPPORTED;
1223 WERROR _svcctl_SCSendTSMessage(struct pipes_struct *p,
1224 struct svcctl_SCSendTSMessage *r)
1226 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1227 return WERR_NOT_SUPPORTED;
1230 static NTSTATUS svcctl__op_init_server(struct dcesrv_context *dce_ctx,
1231 const struct dcesrv_endpoint_server *ep_server);
1233 static NTSTATUS svcctl__op_shutdown_server(struct dcesrv_context *dce_ctx,
1234 const struct dcesrv_endpoint_server *ep_server);
1236 #define DCESRV_INTERFACE_SVCCTL_INIT_SERVER \
1239 #define DCESRV_INTERFACE_SVCCTL_SHUTDOWN_SERVER \
1240 svcctl_shutdown_server
1242 static NTSTATUS svcctl_init_server(struct dcesrv_context *dce_ctx,
1243 const struct dcesrv_endpoint_server *ep_server)
1245 struct messaging_context *msg_ctx = global_messaging_context();
1249 status = dcesrv_init_ep_server(dce_ctx, "winreg");
1250 if (!NT_STATUS_IS_OK(status)) {
1254 /* initialize the control hooks */
1255 init_service_op_table();
1257 ok = svcctl_init_winreg(msg_ctx);
1259 return NT_STATUS_UNSUCCESSFUL;
1262 return svcctl__op_init_server(dce_ctx, ep_server);
1265 static NTSTATUS svcctl_shutdown_server(struct dcesrv_context *dce_ctx,
1266 const struct dcesrv_endpoint_server *ep_server)
1268 shutdown_service_op_table();
1270 return svcctl__op_shutdown_server(dce_ctx, ep_server);
1273 /* include the generated boilerplate */
1274 #include "librpc/gen_ndr/ndr_svcctl_scompat.c"