s3: rpc_server: Avoid casts calling to find_policy_by_hnd()
[metze/samba-autobuild/.git] / source3 / rpc_server / svcctl / srv_svcctl_nt.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *
5  *  Copyright (C) Marcin Krzysztof Porwit           2005.
6  *
7  *  Largely Rewritten (Again) by:
8  *  Copyright (C) Gerald (Jerry) Carter             2005.
9  *  Copyright (C) Guenther Deschner                 2008,2009.
10  *
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.
15  *
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.
20  *
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/>.
23  */
24
25 #include "includes.h"
26 #include "system/passwd.h" /* uid_wrapper */
27 #include "ntdomain.h"
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"
32 #include "auth.h"
33 #include "rpc_server/svcctl/srv_svcctl_nt.h"
34
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"
40
41 #undef DBGC_CLASS
42 #define DBGC_CLASS DBGC_RPC_SRV
43
44 struct service_control_op {
45         const char *name;
46         SERVICE_CONTROL_OPS *ops;
47 };
48
49 /* handle external services */
50 extern SERVICE_CONTROL_OPS rcinit_svc_ops;
51
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;
57
58 /* make sure this number patches the number of builtin
59    SERVICE_CONTROL_OPS structure listed above */
60
61 #define SVCCTL_NUM_INTERNAL_SERVICES    4
62
63 struct service_control_op *svcctl_ops;
64
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 };
69
70
71 /********************************************************************
72 ********************************************************************/
73
74 bool init_service_op_table( void )
75 {
76         const char **service_list = lp_svcctl_list();
77         int num_services = SVCCTL_NUM_INTERNAL_SERVICES + str_list_length( service_list );
78         int i;
79
80         if ( !(svcctl_ops = talloc_array( NULL, struct service_control_op, num_services+1)) ) {
81                 DEBUG(0,("init_service_op_table: talloc() failed!\n"));
82                 return False;
83         }
84
85         /* services listed in smb.conf get the rc.init interface */
86
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;
90         }
91
92         /* add builtin services */
93
94         svcctl_ops[i].name = talloc_strdup( svcctl_ops, "Spooler" );
95         svcctl_ops[i].ops  = &spoolss_svc_ops;
96         i++;
97
98         svcctl_ops[i].name = talloc_strdup( svcctl_ops, "NETLOGON" );
99         svcctl_ops[i].ops  = &netlogon_svc_ops;
100         i++;
101
102         svcctl_ops[i].name = talloc_strdup( svcctl_ops, "RemoteRegistry" );
103         svcctl_ops[i].ops  = &winreg_svc_ops;
104         i++;
105
106         svcctl_ops[i].name = talloc_strdup( svcctl_ops, "WINS" );
107         svcctl_ops[i].ops  = &wins_svc_ops;
108         i++;
109
110         /* NULL terminate the array */
111
112         svcctl_ops[i].name = NULL;
113         svcctl_ops[i].ops  = NULL;
114
115         return True;
116 }
117
118 bool shutdown_service_op_table(void)
119 {
120         TALLOC_FREE(svcctl_ops);
121
122         return true;
123 }
124
125 /********************************************************************
126 ********************************************************************/
127
128 static struct service_control_op* find_service_by_name( const char *name )
129 {
130         int i;
131
132         for ( i=0; svcctl_ops[i].name; i++ ) {
133                 if ( strequal( name, svcctl_ops[i].name ) )
134                         return &svcctl_ops[i];
135         }
136
137         return NULL;
138 }
139 /********************************************************************
140 ********************************************************************/
141
142 static NTSTATUS svcctl_access_check( struct security_descriptor *sec_desc, struct security_token *token,
143                                      uint32_t access_desired, uint32_t *access_granted )
144 {
145         NTSTATUS status;
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)) {
150                         return status;
151                 }
152         }
153
154         return se_access_check( sec_desc, token, access_desired, access_granted);
155 }
156
157 /********************************************************************
158 ********************************************************************/
159
160 static struct security_descriptor* construct_scm_sd( TALLOC_CTX *ctx )
161 {
162         struct security_ace ace[2];
163         size_t i = 0;
164         struct security_descriptor *sd;
165         struct security_acl *theacl;
166         size_t sd_size;
167
168         /* basic access for Everyone */
169
170         init_sec_ace(&ace[i++], &global_sid_World,
171                 SEC_ACE_TYPE_ACCESS_ALLOWED, SC_MANAGER_READ_ACCESS, 0);
172
173         /* Full Access 'BUILTIN\Administrators' */
174
175         init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
176                 SEC_ACE_TYPE_ACCESS_ALLOWED, SC_MANAGER_ALL_ACCESS, 0);
177
178
179         /* create the security descriptor */
180
181         if ( !(theacl = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) )
182                 return NULL;
183
184         if ( !(sd = make_sec_desc(ctx, SECURITY_DESCRIPTOR_REVISION_1,
185                                   SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL,
186                                   theacl, &sd_size)) )
187                 return NULL;
188
189         return sd;
190 }
191
192 /******************************************************************
193  Find a registry key handle and return a SERVICE_INFO
194  *****************************************************************/
195
196 static SERVICE_INFO *find_service_info_by_hnd(struct pipes_struct *p,
197                                               struct policy_handle *hnd)
198 {
199         SERVICE_INFO *service_info = NULL;
200         NTSTATUS status;
201
202         service_info = find_policy_by_hnd(p,
203                                           hnd,
204                                           DCESRV_HANDLE_ANY,
205                                           SERVICE_INFO,
206                                           &status);
207         if (!NT_STATUS_IS_OK(status)) {
208                 DEBUG(2,("find_service_info_by_hnd: handle not found\n"));
209                 return NULL;
210         }
211
212         return service_info;
213 }
214
215 /******************************************************************
216  *****************************************************************/
217
218 static WERROR create_open_service_handle(struct pipes_struct *p,
219                                          struct policy_handle *handle,
220                                          uint32_t type,
221                                          const char *service,
222                                          uint32_t access_granted)
223 {
224         SERVICE_INFO *info = NULL;
225         WERROR result = WERR_OK;
226         struct service_control_op *s_op;
227
228         if ( !(info = talloc_zero( NULL, SERVICE_INFO )) )
229                 return WERR_NOT_ENOUGH_MEMORY;
230
231         /* the Service Manager has a NULL name */
232
233         info->type = SVC_HANDLE_IS_SCM;
234
235         switch ( type ) {
236         case SVC_HANDLE_IS_SCM:
237                 info->type = SVC_HANDLE_IS_SCM;
238                 break;
239
240         case SVC_HANDLE_IS_DBLOCK:
241                 info->type = SVC_HANDLE_IS_DBLOCK;
242                 break;
243
244         case SVC_HANDLE_IS_SERVICE:
245                 info->type = SVC_HANDLE_IS_SERVICE;
246
247                 /* lookup the SERVICE_CONTROL_OPS */
248
249                 if ( !(s_op = find_service_by_name( service )) ) {
250                         result = WERR_SERVICE_DOES_NOT_EXIST;
251                         goto done;
252                 }
253
254                 info->ops = s_op->ops;
255
256                 if ( !(info->name  = talloc_strdup( info, s_op->name )) ) {
257                         result = WERR_NOT_ENOUGH_MEMORY;
258                         goto done;
259                 }
260                 break;
261
262         default:
263                 result = WERR_SERVICE_DOES_NOT_EXIST;
264                 goto done;
265         }
266
267         info->access_granted = access_granted;
268
269         /* store the SERVICE_INFO and create an open handle */
270
271         if ( !create_policy_hnd( p, handle, 0, info ) ) {
272                 result = WERR_ACCESS_DENIED;
273                 goto done;
274         }
275
276 done:
277         if ( !W_ERROR_IS_OK(result) )
278                 TALLOC_FREE(info);
279
280         return result;
281 }
282
283 /********************************************************************
284  _svcctl_OpenSCManagerW
285 ********************************************************************/
286
287 WERROR _svcctl_OpenSCManagerW(struct pipes_struct *p,
288                               struct svcctl_OpenSCManagerW *r)
289 {
290         struct security_descriptor *sec_desc;
291         uint32_t access_granted = 0;
292         NTSTATUS status;
293
294         /* perform access checks */
295
296         if ( !(sec_desc = construct_scm_sd( p->mem_ctx )) )
297                 return WERR_NOT_ENOUGH_MEMORY;
298
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 );
304
305         return create_open_service_handle( p, r->out.handle, SVC_HANDLE_IS_SCM, NULL, access_granted );
306 }
307
308 /********************************************************************
309  _svcctl_OpenServiceW
310 ********************************************************************/
311
312 WERROR _svcctl_OpenServiceW(struct pipes_struct *p,
313                             struct svcctl_OpenServiceW *r)
314 {
315         struct security_descriptor *sec_desc;
316         uint32_t access_granted = 0;
317         NTSTATUS status;
318         const char *service = NULL;
319         WERROR err;
320
321         service = r->in.ServiceName;
322         if (!service) {
323                 return WERR_NOT_ENOUGH_MEMORY;
324         }
325         DEBUG(5, ("_svcctl_OpenServiceW: Attempting to open Service [%s], \n", service));
326
327         /* based on my tests you can open a service if you have a valid scm handle */
328
329         if ( !find_service_info_by_hnd( p, r->in.scmanager_handle) )
330                 return WERR_INVALID_HANDLE;
331
332         /*
333          * Perform access checks. Use the system session_info in order to ensure
334          * that we retrieve the security descriptor
335          */
336         err = svcctl_get_secdesc(p->msg_ctx,
337                                  get_session_info_system(),
338                                  service,
339                                  p->mem_ctx,
340                                  &sec_desc);
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;
344         }
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));
348                 return err;
349         }
350
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 );
356
357         return create_open_service_handle( p, r->out.handle, SVC_HANDLE_IS_SERVICE, service, access_granted );
358 }
359
360 /********************************************************************
361  _svcctl_CloseServiceHandle
362 ********************************************************************/
363
364 WERROR _svcctl_CloseServiceHandle(struct pipes_struct *p,
365                                   struct svcctl_CloseServiceHandle *r)
366 {
367         if ( !close_policy_hnd( p, r->in.handle ) )
368                 return  WERR_INVALID_HANDLE;
369
370         ZERO_STRUCTP(r->out.handle);
371
372         return WERR_OK;
373 }
374
375 /********************************************************************
376  _svcctl_GetServiceDisplayNameW
377 ********************************************************************/
378
379 WERROR _svcctl_GetServiceDisplayNameW(struct pipes_struct *p,
380                                       struct svcctl_GetServiceDisplayNameW *r)
381 {
382         const char *service;
383         const char *display_name;
384         SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
385
386         /* can only use an SCM handle here */
387
388         if ( !info || (info->type != SVC_HANDLE_IS_SCM) )
389                 return WERR_INVALID_HANDLE;
390
391         service = r->in.service_name;
392
393         display_name = svcctl_lookup_dispname(p->mem_ctx,
394                                               p->msg_ctx,
395                                               p->session_info,
396                                               service);
397         if (!display_name) {
398                 display_name = "";
399         }
400
401         *r->out.display_name = display_name;
402         *r->out.display_name_length = strlen(display_name);
403
404         return WERR_OK;
405 }
406
407 /********************************************************************
408  _svcctl_QueryServiceStatus
409 ********************************************************************/
410
411 WERROR _svcctl_QueryServiceStatus(struct pipes_struct *p,
412                                   struct svcctl_QueryServiceStatus *r)
413 {
414         SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
415
416         /* perform access checks */
417
418         if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
419                 return WERR_INVALID_HANDLE;
420
421         if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_STATUS) )
422                 return WERR_ACCESS_DENIED;
423
424         /* try the service specific status call */
425
426         return info->ops->service_status( info->name, r->out.service_status );
427 }
428
429 /********************************************************************
430 ********************************************************************/
431
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)
436 {
437         int num_services = 0;
438         int i;
439         struct ENUM_SERVICE_STATUSW *st;
440         const char *display_name;
441
442         /* just count */
443         while ( svcctl_ops[num_services].name )
444                 num_services++;
445
446         if ( !(st = talloc_array( ctx, struct ENUM_SERVICE_STATUSW, num_services )) ) {
447                 DEBUG(0,("enumerate_status: talloc() failed!\n"));
448                 return -1;
449         }
450
451         for ( i=0; i<num_services; i++ ) {
452                 st[i].service_name = talloc_strdup(st, svcctl_ops[i].name );
453
454                 display_name = svcctl_lookup_dispname(ctx,
455                                                       msg_ctx,
456                                                       session_info,
457                                                       svcctl_ops[i].name);
458                 st[i].display_name = talloc_strdup(st, display_name ? display_name : "");
459
460                 svcctl_ops[i].ops->service_status( svcctl_ops[i].name, &st[i].status );
461         }
462
463         *status = st;
464
465         return num_services;
466 }
467
468 /********************************************************************
469  _svcctl_EnumServicesStatusW
470 ********************************************************************/
471
472 WERROR _svcctl_EnumServicesStatusW(struct pipes_struct *p,
473                                    struct svcctl_EnumServicesStatusW *r)
474 {
475         struct ENUM_SERVICE_STATUSW *services = NULL;
476         int num_services;
477         int i = 0;
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;
482
483         /* perform access checks */
484
485         if ( !info || (info->type != SVC_HANDLE_IS_SCM) )
486                 return WERR_INVALID_HANDLE;
487
488         if ( !(info->access_granted & SC_RIGHT_MGR_ENUMERATE_SERVICE) ) {
489                 return WERR_ACCESS_DENIED;
490         }
491
492         num_services = enumerate_status(p->mem_ctx,
493                                         p->msg_ctx,
494                                         p->session_info,
495                                         &services);
496         if (num_services == -1 ) {
497                 return WERR_NOT_ENOUGH_MEMORY;
498         }
499
500         for ( i=0; i<num_services; i++ ) {
501                 buffer_size += ndr_size_ENUM_SERVICE_STATUSW(&services[i], 0);
502         }
503
504         buffer_size += buffer_size % 4;
505
506         if (buffer_size > r->in.offered) {
507                 num_services = 0;
508                 result = WERR_MORE_DATA;
509         }
510
511         if ( W_ERROR_IS_OK(result) ) {
512
513                 enum ndr_err_code ndr_err;
514                 struct ndr_push *ndr;
515
516                 ndr = ndr_push_init_ctx(p->mem_ctx);
517                 if (ndr == NULL) {
518                         return WERR_INVALID_PARAMETER;
519                 }
520
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));
525                 }
526                 blob = ndr_push_blob(ndr);
527                 memcpy(r->out.service, blob.data, MIN(blob.length, r->in.offered));
528         }
529
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;
534         }
535
536         return result;
537 }
538
539 /********************************************************************
540  _svcctl_StartServiceW
541 ********************************************************************/
542
543 WERROR _svcctl_StartServiceW(struct pipes_struct *p,
544                              struct svcctl_StartServiceW *r)
545 {
546         SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
547
548         /* perform access checks */
549
550         if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
551                 return WERR_INVALID_HANDLE;
552
553         if ( !(info->access_granted & SC_RIGHT_SVC_START) )
554                 return WERR_ACCESS_DENIED;
555
556         return info->ops->start_service( info->name );
557 }
558
559 /********************************************************************
560  _svcctl_ControlService
561 ********************************************************************/
562
563 WERROR _svcctl_ControlService(struct pipes_struct *p,
564                               struct svcctl_ControlService *r)
565 {
566         SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
567
568         /* perform access checks */
569
570         if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
571                 return WERR_INVALID_HANDLE;
572
573         switch ( r->in.control ) {
574         case SVCCTL_CONTROL_STOP:
575                 if ( !(info->access_granted & SC_RIGHT_SVC_STOP) )
576                         return WERR_ACCESS_DENIED;
577
578                 return info->ops->stop_service( info->name,
579                                                 r->out.service_status );
580
581         case SVCCTL_CONTROL_INTERROGATE:
582                 if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_STATUS) )
583                         return WERR_ACCESS_DENIED;
584
585                 return info->ops->service_status( info->name,
586                                                   r->out.service_status );
587         default:
588                 return WERR_INVALID_PARAMETER;
589         }
590 }
591
592 /********************************************************************
593  _svcctl_EnumDependentServicesW
594 ********************************************************************/
595
596 WERROR _svcctl_EnumDependentServicesW(struct pipes_struct *p,
597                                       struct svcctl_EnumDependentServicesW *r)
598 {
599         SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.service );
600
601         /* perform access checks */
602
603         if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
604                 return WERR_INVALID_HANDLE;
605
606         if ( !(info->access_granted & SC_RIGHT_SVC_ENUMERATE_DEPENDENTS) )
607                 return WERR_ACCESS_DENIED;
608
609         switch (r->in.state) {
610         case SERVICE_STATE_ACTIVE:
611         case SERVICE_STATE_INACTIVE:
612         case SERVICE_STATE_ALL:
613                 break;
614         default:
615                 return WERR_INVALID_PARAMETER;
616         }
617
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 */
621
622         *r->out.needed = r->in.offered;
623
624         /* no dependent services...basically a stub function */
625         *r->out.services_returned = 0;
626
627         return WERR_OK;
628 }
629
630 /********************************************************************
631  _svcctl_QueryServiceStatusEx
632 ********************************************************************/
633
634 WERROR _svcctl_QueryServiceStatusEx(struct pipes_struct *p,
635                                     struct svcctl_QueryServiceStatusEx *r)
636 {
637         SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
638         uint32_t buffer_size;
639
640         /* perform access checks */
641
642         if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
643                 return WERR_INVALID_HANDLE;
644
645         if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_STATUS) )
646                 return WERR_ACCESS_DENIED;
647
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;
651
652         switch ( r->in.info_level ) {
653                 case SVC_STATUS_PROCESS_INFO:
654                 {
655                         struct SERVICE_STATUS_PROCESS svc_stat_proc;
656                         enum ndr_err_code ndr_err;
657                         DATA_BLOB blob;
658
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;
663
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;
668                         }
669
670                         r->out.buffer = blob.data;
671                         buffer_size = sizeof(struct SERVICE_STATUS_PROCESS);
672                         break;
673                 }
674
675                 default:
676                         return WERR_INVALID_LEVEL;
677         }
678
679
680         buffer_size += buffer_size % 4;
681         *r->out.needed = (buffer_size > r->in.offered) ? buffer_size : r->in.offered;
682
683         if (buffer_size > r->in.offered ) {
684                 return WERR_INSUFFICIENT_BUFFER;
685         }
686
687         return WERR_OK;
688 }
689
690 /********************************************************************
691 ********************************************************************/
692
693 static WERROR fill_svc_config(TALLOC_CTX *mem_ctx,
694                               struct messaging_context *msg_ctx,
695                               struct auth_session_info *session_info,
696                               const char *name,
697                               struct QUERY_SERVICE_CONFIG *config)
698 {
699         const char *result = NULL;
700
701         /* now fill in the individual values */
702
703         ZERO_STRUCTP(config);
704
705         config->displayname = svcctl_lookup_dispname(mem_ctx,
706                                                      msg_ctx,
707                                                      session_info,
708                                                      name);
709
710         result = svcctl_get_string_value(mem_ctx,
711                                          msg_ctx,
712                                          session_info,
713                                          name,
714                                          "ObjectName");
715         if (result != NULL) {
716                 config->startname = result;
717         }
718
719         result = svcctl_get_string_value(mem_ctx,
720                                          msg_ctx,
721                                          session_info,
722                                          name,
723                                          "ImagePath");
724         if (result != NULL) {
725                 config->executablepath = result;
726         }
727
728         /* a few hard coded values */
729         /* loadordergroup and dependencies are empty */
730
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;
734
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
737            are not running */
738
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;
743         else
744                 config->start_type = SVCCTL_DEMAND_START;
745
746         return WERR_OK;
747 }
748
749 /********************************************************************
750  _svcctl_QueryServiceConfigW
751 ********************************************************************/
752
753 WERROR _svcctl_QueryServiceConfigW(struct pipes_struct *p,
754                                    struct svcctl_QueryServiceConfigW *r)
755 {
756         SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
757         uint32_t buffer_size;
758         WERROR wresult;
759
760         /* perform access checks */
761
762         if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
763                 return WERR_INVALID_HANDLE;
764
765         if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_CONFIG) )
766                 return WERR_ACCESS_DENIED;
767
768         /* we have to set the outgoing buffer size to the same as the
769            incoming buffer size (even in the case of failure */
770
771         *r->out.needed = r->in.offered;
772
773         wresult = fill_svc_config(p->mem_ctx,
774                                   p->msg_ctx,
775                                   p->session_info,
776                                   info->name,
777                                   r->out.query);
778         if ( !W_ERROR_IS_OK(wresult) )
779                 return wresult;
780
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;
783
784         if (buffer_size > r->in.offered ) {
785                 ZERO_STRUCTP(r->out.query);
786                 return WERR_INSUFFICIENT_BUFFER;
787         }
788
789         return WERR_OK;
790 }
791
792 /********************************************************************
793  _svcctl_QueryServiceConfig2W
794 ********************************************************************/
795
796 WERROR _svcctl_QueryServiceConfig2W(struct pipes_struct *p,
797                                     struct svcctl_QueryServiceConfig2W *r)
798 {
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;
802
803         /* perform access checks */
804
805         if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
806                 return WERR_INVALID_HANDLE;
807
808         if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_CONFIG) )
809                 return WERR_ACCESS_DENIED;
810
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;
814
815         switch ( r->in.info_level ) {
816         case SERVICE_CONFIG_DESCRIPTION:
817                 {
818                         struct SERVICE_DESCRIPTION desc_buf;
819                         const char *description;
820                         enum ndr_err_code ndr_err;
821
822                         description = svcctl_lookup_description(p->mem_ctx,
823                                                                 p->msg_ctx,
824                                                                 p->session_info,
825                                                                 info->name);
826
827                         desc_buf.description = description;
828
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;
833                         }
834
835                         break;
836                 }
837                 break;
838         case SERVICE_CONFIG_FAILURE_ACTIONS:
839                 {
840                         struct SERVICE_FAILURE_ACTIONS actions;
841                         enum ndr_err_code ndr_err;
842
843                         /* nothing to say...just service the request */
844
845                         ZERO_STRUCT( actions );
846
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;
851                         }
852
853                         break;
854                 }
855                 break;
856
857         default:
858                 return WERR_INVALID_LEVEL;
859         }
860
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;
864
865         if (buffer_size > r->in.offered)
866                 return WERR_INSUFFICIENT_BUFFER;
867
868         memcpy(r->out.buffer, blob.data, blob.length);
869
870         return WERR_OK;
871 }
872
873 /********************************************************************
874  _svcctl_LockServiceDatabase
875 ********************************************************************/
876
877 WERROR _svcctl_LockServiceDatabase(struct pipes_struct *p,
878                                    struct svcctl_LockServiceDatabase *r)
879 {
880         SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
881
882         /* perform access checks */
883
884         if ( !info || (info->type != SVC_HANDLE_IS_SCM) )
885                 return WERR_INVALID_HANDLE;
886
887         if ( !(info->access_granted & SC_RIGHT_MGR_LOCK) )
888                 return WERR_ACCESS_DENIED;
889
890         /* Just open a handle.  Doesn't actually lock anything */
891
892         return create_open_service_handle( p, r->out.lock, SVC_HANDLE_IS_DBLOCK, NULL, 0 );
893 }
894
895 /********************************************************************
896  _svcctl_UnlockServiceDatabase
897 ********************************************************************/
898
899 WERROR _svcctl_UnlockServiceDatabase(struct pipes_struct *p,
900                                      struct svcctl_UnlockServiceDatabase *r)
901 {
902         SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.lock );
903
904
905         if ( !info || (info->type != SVC_HANDLE_IS_DBLOCK) )
906                 return WERR_INVALID_HANDLE;
907
908         return close_policy_hnd( p, r->out.lock) ? WERR_OK : WERR_INVALID_HANDLE;
909 }
910
911 /********************************************************************
912  _svcctl_QueryServiceObjectSecurity
913 ********************************************************************/
914
915 WERROR _svcctl_QueryServiceObjectSecurity(struct pipes_struct *p,
916                                           struct svcctl_QueryServiceObjectSecurity *r)
917 {
918         SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
919         struct security_descriptor *sec_desc;
920         NTSTATUS status;
921         uint8_t *buffer = NULL;
922         size_t len = 0;
923         WERROR err;
924
925
926         /* only support the SCM and individual services */
927
928         if ( !info || !(info->type & (SVC_HANDLE_IS_SERVICE|SVC_HANDLE_IS_SCM)) )
929                 return WERR_INVALID_HANDLE;
930
931         /* check access reights (according to MSDN) */
932
933         if ( !(info->access_granted & SEC_STD_READ_CONTROL) )
934                 return WERR_ACCESS_DENIED;
935
936         /* TODO: handle something besides SECINFO_DACL */
937
938         if ( (r->in.security_flags & SECINFO_DACL) != SECINFO_DACL )
939                 return WERR_INVALID_PARAMETER;
940
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(),
944                                  info->name,
945                                  p->mem_ctx,
946                                  &sec_desc);
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;
950         }
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));
954                 return err;
955         }
956
957         *r->out.needed = ndr_size_security_descriptor(sec_desc, 0);
958
959         if ( *r->out.needed > r->in.offered) {
960                 return WERR_INSUFFICIENT_BUFFER;
961         }
962
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);
966         }
967
968         *r->out.needed = len;
969         memcpy(r->out.buffer, buffer, len);
970
971         return WERR_OK;
972 }
973
974 /********************************************************************
975  _svcctl_SetServiceObjectSecurity
976 ********************************************************************/
977
978 WERROR _svcctl_SetServiceObjectSecurity(struct pipes_struct *p,
979                                         struct svcctl_SetServiceObjectSecurity *r)
980 {
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;
984         NTSTATUS status;
985
986         if ( !info || !(info->type & (SVC_HANDLE_IS_SERVICE|SVC_HANDLE_IS_SCM))  )
987                 return WERR_INVALID_HANDLE;
988
989         /* can't set the security de4scriptor on the ServiceControlManager */
990
991         if ( info->type == SVC_HANDLE_IS_SCM )
992                 return WERR_ACCESS_DENIED;
993
994         /* check the access on the open handle */
995
996         switch ( r->in.security_flags ) {
997                 case SECINFO_DACL:
998                         required_access = SEC_STD_WRITE_DAC;
999                         break;
1000
1001                 case SECINFO_OWNER:
1002                 case SECINFO_GROUP:
1003                         required_access = SEC_STD_WRITE_OWNER;
1004                         break;
1005
1006                 case SECINFO_SACL:
1007                         return WERR_INVALID_PARAMETER;
1008                 default:
1009                         return WERR_INVALID_PARAMETER;
1010         }
1011
1012         if ( !(info->access_granted & required_access) )
1013                 return WERR_ACCESS_DENIED;
1014
1015         /* read the security descfriptor */
1016
1017         status = unmarshall_sec_desc(p->mem_ctx,
1018                                      r->in.buffer,
1019                                      r->in.offered,
1020                                      &sec_desc);
1021         if (!NT_STATUS_IS_OK(status)) {
1022                 return ntstatus_to_werror(status);
1023         }
1024
1025         /* store the new SD */
1026
1027         if (!svcctl_set_secdesc(p->msg_ctx, p->session_info, info->name, sec_desc))
1028                 return WERR_ACCESS_DENIED;
1029
1030         return WERR_OK;
1031 }
1032
1033
1034 WERROR _svcctl_DeleteService(struct pipes_struct *p,
1035                              struct svcctl_DeleteService *r)
1036 {
1037         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1038         return WERR_NOT_SUPPORTED;
1039 }
1040
1041 WERROR _svcctl_SetServiceStatus(struct pipes_struct *p,
1042                                 struct svcctl_SetServiceStatus *r)
1043 {
1044         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1045         return WERR_NOT_SUPPORTED;
1046 }
1047
1048 WERROR _svcctl_NotifyBootConfigStatus(struct pipes_struct *p,
1049                                       struct svcctl_NotifyBootConfigStatus *r)
1050 {
1051         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1052         return WERR_NOT_SUPPORTED;
1053 }
1054
1055 WERROR _svcctl_SCSetServiceBitsW(struct pipes_struct *p,
1056                                  struct svcctl_SCSetServiceBitsW *r)
1057 {
1058         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1059         return WERR_NOT_SUPPORTED;
1060 }
1061
1062 WERROR _svcctl_ChangeServiceConfigW(struct pipes_struct *p,
1063                                     struct svcctl_ChangeServiceConfigW *r)
1064 {
1065         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1066         return WERR_NOT_SUPPORTED;
1067 }
1068
1069 WERROR _svcctl_CreateServiceW(struct pipes_struct *p,
1070                               struct svcctl_CreateServiceW *r)
1071 {
1072         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1073         return WERR_NOT_SUPPORTED;
1074 }
1075
1076 WERROR _svcctl_QueryServiceLockStatusW(struct pipes_struct *p,
1077                                        struct svcctl_QueryServiceLockStatusW *r)
1078 {
1079         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1080         return WERR_NOT_SUPPORTED;
1081 }
1082
1083 WERROR _svcctl_GetServiceKeyNameW(struct pipes_struct *p,
1084                                   struct svcctl_GetServiceKeyNameW *r)
1085 {
1086         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1087         return WERR_NOT_SUPPORTED;
1088 }
1089
1090 WERROR _svcctl_SCSetServiceBitsA(struct pipes_struct *p,
1091                                  struct svcctl_SCSetServiceBitsA *r)
1092 {
1093         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1094         return WERR_NOT_SUPPORTED;
1095 }
1096
1097 WERROR _svcctl_ChangeServiceConfigA(struct pipes_struct *p,
1098                                     struct svcctl_ChangeServiceConfigA *r)
1099 {
1100         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1101         return WERR_NOT_SUPPORTED;
1102 }
1103
1104 WERROR _svcctl_CreateServiceA(struct pipes_struct *p,
1105                               struct svcctl_CreateServiceA *r)
1106 {
1107         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1108         return WERR_NOT_SUPPORTED;
1109 }
1110
1111 WERROR _svcctl_EnumDependentServicesA(struct pipes_struct *p,
1112                                       struct svcctl_EnumDependentServicesA *r)
1113 {
1114         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1115         return WERR_NOT_SUPPORTED;
1116 }
1117
1118 WERROR _svcctl_EnumServicesStatusA(struct pipes_struct *p,
1119                                    struct svcctl_EnumServicesStatusA *r)
1120 {
1121         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1122         return WERR_NOT_SUPPORTED;
1123 }
1124
1125 WERROR _svcctl_OpenSCManagerA(struct pipes_struct *p,
1126                               struct svcctl_OpenSCManagerA *r)
1127 {
1128         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1129         return WERR_NOT_SUPPORTED;
1130 }
1131
1132 WERROR _svcctl_OpenServiceA(struct pipes_struct *p,
1133                             struct svcctl_OpenServiceA *r)
1134 {
1135         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1136         return WERR_NOT_SUPPORTED;
1137 }
1138
1139 WERROR _svcctl_QueryServiceConfigA(struct pipes_struct *p,
1140                                    struct svcctl_QueryServiceConfigA *r)
1141 {
1142         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1143         return WERR_NOT_SUPPORTED;
1144 }
1145
1146 WERROR _svcctl_QueryServiceLockStatusA(struct pipes_struct *p,
1147                                        struct svcctl_QueryServiceLockStatusA *r)
1148 {
1149         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1150         return WERR_NOT_SUPPORTED;
1151 }
1152
1153 WERROR _svcctl_StartServiceA(struct pipes_struct *p,
1154                              struct svcctl_StartServiceA *r)
1155 {
1156         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1157         return WERR_NOT_SUPPORTED;
1158 }
1159
1160 WERROR _svcctl_GetServiceDisplayNameA(struct pipes_struct *p,
1161                                       struct svcctl_GetServiceDisplayNameA *r)
1162 {
1163         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1164         return WERR_NOT_SUPPORTED;
1165 }
1166
1167 WERROR _svcctl_GetServiceKeyNameA(struct pipes_struct *p,
1168                                   struct svcctl_GetServiceKeyNameA *r)
1169 {
1170         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1171         return WERR_NOT_SUPPORTED;
1172 }
1173
1174 WERROR _svcctl_GetCurrentGroupeStateW(struct pipes_struct *p,
1175                                       struct svcctl_GetCurrentGroupeStateW *r)
1176 {
1177         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1178         return WERR_NOT_SUPPORTED;
1179 }
1180
1181 WERROR _svcctl_EnumServiceGroupW(struct pipes_struct *p,
1182                                  struct svcctl_EnumServiceGroupW *r)
1183 {
1184         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1185         return WERR_NOT_SUPPORTED;
1186 }
1187
1188 WERROR _svcctl_ChangeServiceConfig2A(struct pipes_struct *p,
1189                                      struct svcctl_ChangeServiceConfig2A *r)
1190 {
1191         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1192         return WERR_NOT_SUPPORTED;
1193 }
1194
1195 WERROR _svcctl_ChangeServiceConfig2W(struct pipes_struct *p,
1196                                      struct svcctl_ChangeServiceConfig2W *r)
1197 {
1198         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1199         return WERR_NOT_SUPPORTED;
1200 }
1201
1202 WERROR _svcctl_QueryServiceConfig2A(struct pipes_struct *p,
1203                                     struct svcctl_QueryServiceConfig2A *r)
1204 {
1205         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1206         return WERR_NOT_SUPPORTED;
1207 }
1208
1209 WERROR _EnumServicesStatusExA(struct pipes_struct *p,
1210                               struct EnumServicesStatusExA *r)
1211 {
1212         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1213         return WERR_NOT_SUPPORTED;
1214 }
1215
1216 WERROR _EnumServicesStatusExW(struct pipes_struct *p,
1217                               struct EnumServicesStatusExW *r)
1218 {
1219         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1220         return WERR_NOT_SUPPORTED;
1221 }
1222
1223 WERROR _svcctl_SCSendTSMessage(struct pipes_struct *p,
1224                                struct svcctl_SCSendTSMessage *r)
1225 {
1226         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1227         return WERR_NOT_SUPPORTED;
1228 }
1229
1230 static NTSTATUS svcctl__op_init_server(struct dcesrv_context *dce_ctx,
1231                 const struct dcesrv_endpoint_server *ep_server);
1232
1233 static NTSTATUS svcctl__op_shutdown_server(struct dcesrv_context *dce_ctx,
1234                 const struct dcesrv_endpoint_server *ep_server);
1235
1236 #define DCESRV_INTERFACE_SVCCTL_INIT_SERVER \
1237         svcctl_init_server
1238
1239 #define DCESRV_INTERFACE_SVCCTL_SHUTDOWN_SERVER \
1240         svcctl_shutdown_server
1241
1242 static NTSTATUS svcctl_init_server(struct dcesrv_context *dce_ctx,
1243                 const struct dcesrv_endpoint_server *ep_server)
1244 {
1245         struct messaging_context *msg_ctx = global_messaging_context();
1246         NTSTATUS status;
1247         bool ok;
1248
1249         status = dcesrv_init_ep_server(dce_ctx, "winreg");
1250         if (!NT_STATUS_IS_OK(status)) {
1251                 return status;
1252         }
1253
1254         /* initialize the control hooks */
1255         init_service_op_table();
1256
1257         ok = svcctl_init_winreg(msg_ctx);
1258         if (!ok) {
1259                 return NT_STATUS_UNSUCCESSFUL;
1260         }
1261
1262         return svcctl__op_init_server(dce_ctx, ep_server);
1263 }
1264
1265 static NTSTATUS svcctl_shutdown_server(struct dcesrv_context *dce_ctx,
1266                 const struct dcesrv_endpoint_server *ep_server)
1267 {
1268         shutdown_service_op_table();
1269
1270         return svcctl__op_shutdown_server(dce_ctx, ep_server);
1271 }
1272
1273 /* include the generated boilerplate */
1274 #include "librpc/gen_ndr/ndr_svcctl_scompat.c"