a7af089e7e33c3c3f366d28d8c83eb721a6a626e
[samba.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 "../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"
31
32 #undef DBGC_CLASS
33 #define DBGC_CLASS DBGC_RPC_SRV
34
35 struct service_control_op {
36         const char *name;
37         SERVICE_CONTROL_OPS *ops;
38 };
39
40 /* handle external services */
41 extern SERVICE_CONTROL_OPS rcinit_svc_ops;
42
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;
48
49 /* make sure this number patches the number of builtin
50    SERVICE_CONTROL_OPS structure listed above */
51
52 #define SVCCTL_NUM_INTERNAL_SERVICES    4
53
54 struct service_control_op *svcctl_ops;
55
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 };
60
61
62 /********************************************************************
63 ********************************************************************/
64
65 bool init_service_op_table( void )
66 {
67         const char **service_list = lp_svcctl_list();
68         int num_services = SVCCTL_NUM_INTERNAL_SERVICES + str_list_length( service_list );
69         int i;
70
71         if ( !(svcctl_ops = TALLOC_ARRAY( NULL, struct service_control_op, num_services+1)) ) {
72                 DEBUG(0,("init_service_op_table: talloc() failed!\n"));
73                 return False;
74         }
75
76         /* services listed in smb.conf get the rc.init interface */
77
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;
81         }
82
83         /* add builtin services */
84
85         svcctl_ops[i].name = talloc_strdup( svcctl_ops, "Spooler" );
86         svcctl_ops[i].ops  = &spoolss_svc_ops;
87         i++;
88
89         svcctl_ops[i].name = talloc_strdup( svcctl_ops, "NETLOGON" );
90         svcctl_ops[i].ops  = &netlogon_svc_ops;
91         i++;
92
93         svcctl_ops[i].name = talloc_strdup( svcctl_ops, "RemoteRegistry" );
94         svcctl_ops[i].ops  = &winreg_svc_ops;
95         i++;
96
97         svcctl_ops[i].name = talloc_strdup( svcctl_ops, "WINS" );
98         svcctl_ops[i].ops  = &wins_svc_ops;
99         i++;
100
101         /* NULL terminate the array */
102
103         svcctl_ops[i].name = NULL;
104         svcctl_ops[i].ops  = NULL;
105
106         return True;
107 }
108
109 bool shutdown_service_op_table(void)
110 {
111         TALLOC_FREE(svcctl_ops);
112
113         return true;
114 }
115
116 /********************************************************************
117 ********************************************************************/
118
119 static struct service_control_op* find_service_by_name( const char *name )
120 {
121         int i;
122
123         for ( i=0; svcctl_ops[i].name; i++ ) {
124                 if ( strequal( name, svcctl_ops[i].name ) )
125                         return &svcctl_ops[i];
126         }
127
128         return NULL;
129 }
130 /********************************************************************
131 ********************************************************************/
132
133 static NTSTATUS svcctl_access_check( struct security_descriptor *sec_desc, struct security_token *token,
134                                      uint32 access_desired, uint32 *access_granted )
135 {
136         if ( geteuid() == sec_initial_uid() ) {
137                 DEBUG(5,("svcctl_access_check: using root's token\n"));
138                 token = get_root_nt_token();
139         }
140
141         return se_access_check( sec_desc, token, access_desired, access_granted);
142 }
143
144 /********************************************************************
145 ********************************************************************/
146
147 static struct security_descriptor* construct_scm_sd( TALLOC_CTX *ctx )
148 {
149         struct security_ace ace[2];
150         size_t i = 0;
151         struct security_descriptor *sd;
152         struct security_acl *theacl;
153         size_t sd_size;
154
155         /* basic access for Everyone */
156
157         init_sec_ace(&ace[i++], &global_sid_World,
158                 SEC_ACE_TYPE_ACCESS_ALLOWED, SC_MANAGER_READ_ACCESS, 0);
159
160         /* Full Access 'BUILTIN\Administrators' */
161
162         init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
163                 SEC_ACE_TYPE_ACCESS_ALLOWED, SC_MANAGER_ALL_ACCESS, 0);
164
165
166         /* create the security descriptor */
167
168         if ( !(theacl = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) )
169                 return NULL;
170
171         if ( !(sd = make_sec_desc(ctx, SECURITY_DESCRIPTOR_REVISION_1,
172                                   SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL,
173                                   theacl, &sd_size)) )
174                 return NULL;
175
176         return sd;
177 }
178
179 /******************************************************************
180  Find a registry key handle and return a SERVICE_INFO
181  *****************************************************************/
182
183 static SERVICE_INFO *find_service_info_by_hnd(struct pipes_struct *p,
184                                               struct policy_handle *hnd)
185 {
186         SERVICE_INFO *service_info = NULL;
187
188         if( !find_policy_by_hnd( p, hnd, (void **)(void *)&service_info) ) {
189                 DEBUG(2,("find_service_info_by_hnd: handle not found\n"));
190                 return NULL;
191         }
192
193         return service_info;
194 }
195
196 /******************************************************************
197  *****************************************************************/
198
199 static WERROR create_open_service_handle(struct pipes_struct *p,
200                                          struct policy_handle *handle,
201                                          uint32_t type,
202                                          const char *service,
203                                          uint32_t access_granted)
204 {
205         SERVICE_INFO *info = NULL;
206         WERROR result = WERR_OK;
207         struct service_control_op *s_op;
208
209         if ( !(info = TALLOC_ZERO_P( NULL, SERVICE_INFO )) )
210                 return WERR_NOMEM;
211
212         /* the Service Manager has a NULL name */
213
214         info->type = SVC_HANDLE_IS_SCM;
215
216         switch ( type ) {
217         case SVC_HANDLE_IS_SCM:
218                 info->type = SVC_HANDLE_IS_SCM;
219                 break;
220
221         case SVC_HANDLE_IS_DBLOCK:
222                 info->type = SVC_HANDLE_IS_DBLOCK;
223                 break;
224
225         case SVC_HANDLE_IS_SERVICE:
226                 info->type = SVC_HANDLE_IS_SERVICE;
227
228                 /* lookup the SERVICE_CONTROL_OPS */
229
230                 if ( !(s_op = find_service_by_name( service )) ) {
231                         result = WERR_NO_SUCH_SERVICE;
232                         goto done;
233                 }
234
235                 info->ops = s_op->ops;
236
237                 if ( !(info->name  = talloc_strdup( info, s_op->name )) ) {
238                         result = WERR_NOMEM;
239                         goto done;
240                 }
241                 break;
242
243         default:
244                 result = WERR_NO_SUCH_SERVICE;
245                 goto done;
246         }
247
248         info->access_granted = access_granted;
249
250         /* store the SERVICE_INFO and create an open handle */
251
252         if ( !create_policy_hnd( p, handle, info ) ) {
253                 result = WERR_ACCESS_DENIED;
254                 goto done;
255         }
256
257 done:
258         if ( !W_ERROR_IS_OK(result) )
259                 TALLOC_FREE(info);
260
261         return result;
262 }
263
264 /********************************************************************
265  _svcctl_OpenSCManagerW
266 ********************************************************************/
267
268 WERROR _svcctl_OpenSCManagerW(struct pipes_struct *p,
269                               struct svcctl_OpenSCManagerW *r)
270 {
271         struct security_descriptor *sec_desc;
272         uint32 access_granted = 0;
273         NTSTATUS status;
274
275         /* perform access checks */
276
277         if ( !(sec_desc = construct_scm_sd( p->mem_ctx )) )
278                 return WERR_NOMEM;
279
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 );
285
286         return create_open_service_handle( p, r->out.handle, SVC_HANDLE_IS_SCM, NULL, access_granted );
287 }
288
289 /********************************************************************
290  _svcctl_OpenServiceW
291 ********************************************************************/
292
293 WERROR _svcctl_OpenServiceW(struct pipes_struct *p,
294                             struct svcctl_OpenServiceW *r)
295 {
296         struct security_descriptor *sec_desc;
297         uint32 access_granted = 0;
298         NTSTATUS status;
299         const char *service = NULL;
300
301         service = r->in.ServiceName;
302         if (!service) {
303                 return WERR_NOMEM;
304         }
305         DEBUG(5, ("_svcctl_OpenServiceW: Attempting to open Service [%s], \n", service));
306
307         /* based on my tests you can open a service if you have a valid scm handle */
308
309         if ( !find_service_info_by_hnd( p, r->in.scmanager_handle) )
310                 return WERR_BADFID;
311
312         /*
313          * Perform access checks. Use the system server_info in order to ensure
314          * that we retrieve the security descriptor
315          */
316         sec_desc = svcctl_get_secdesc(p->mem_ctx,
317                                       p->msg_ctx,
318                                       get_server_info_system(),
319                                       service);
320         if (sec_desc == NULL) {
321                 DEBUG(0, ("_svcctl_OpenServiceW: Failed to get a valid security "
322                           "descriptor"));
323                 return WERR_NOMEM;
324         }
325
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 );
331
332         return create_open_service_handle( p, r->out.handle, SVC_HANDLE_IS_SERVICE, service, access_granted );
333 }
334
335 /********************************************************************
336  _svcctl_CloseServiceHandle
337 ********************************************************************/
338
339 WERROR _svcctl_CloseServiceHandle(struct pipes_struct *p,
340                                   struct svcctl_CloseServiceHandle *r)
341 {
342         if ( !close_policy_hnd( p, r->in.handle ) )
343                 return  WERR_BADFID;
344
345         ZERO_STRUCTP(r->out.handle);
346
347         return WERR_OK;
348 }
349
350 /********************************************************************
351  _svcctl_GetServiceDisplayNameW
352 ********************************************************************/
353
354 WERROR _svcctl_GetServiceDisplayNameW(struct pipes_struct *p,
355                                       struct svcctl_GetServiceDisplayNameW *r)
356 {
357         const char *service;
358         const char *display_name;
359         SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
360
361         /* can only use an SCM handle here */
362
363         if ( !info || (info->type != SVC_HANDLE_IS_SCM) )
364                 return WERR_BADFID;
365
366         service = r->in.service_name;
367
368         display_name = svcctl_lookup_dispname(p->mem_ctx,
369                                               p->msg_ctx,
370                                               p->server_info,
371                                               service);
372         if (!display_name) {
373                 display_name = "";
374         }
375
376         *r->out.display_name = display_name;
377         *r->out.display_name_length = strlen(display_name);
378
379         return WERR_OK;
380 }
381
382 /********************************************************************
383  _svcctl_QueryServiceStatus
384 ********************************************************************/
385
386 WERROR _svcctl_QueryServiceStatus(struct pipes_struct *p,
387                                   struct svcctl_QueryServiceStatus *r)
388 {
389         SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
390
391         /* perform access checks */
392
393         if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
394                 return WERR_BADFID;
395
396         if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_STATUS) )
397                 return WERR_ACCESS_DENIED;
398
399         /* try the service specific status call */
400
401         return info->ops->service_status( info->name, r->out.service_status );
402 }
403
404 /********************************************************************
405 ********************************************************************/
406
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)
411 {
412         int num_services = 0;
413         int i;
414         struct ENUM_SERVICE_STATUSW *st;
415         const char *display_name;
416
417         /* just count */
418         while ( svcctl_ops[num_services].name )
419                 num_services++;
420
421         if ( !(st = TALLOC_ARRAY( ctx, struct ENUM_SERVICE_STATUSW, num_services )) ) {
422                 DEBUG(0,("enumerate_status: talloc() failed!\n"));
423                 return -1;
424         }
425
426         for ( i=0; i<num_services; i++ ) {
427                 st[i].service_name = talloc_strdup(st, svcctl_ops[i].name );
428
429                 display_name = svcctl_lookup_dispname(ctx,
430                                                       msg_ctx,
431                                                       server_info,
432                                                       svcctl_ops[i].name);
433                 st[i].display_name = talloc_strdup(st, display_name ? display_name : "");
434
435                 svcctl_ops[i].ops->service_status( svcctl_ops[i].name, &st[i].status );
436         }
437
438         *status = st;
439
440         return num_services;
441 }
442
443 /********************************************************************
444  _svcctl_EnumServicesStatusW
445 ********************************************************************/
446
447 WERROR _svcctl_EnumServicesStatusW(struct pipes_struct *p,
448                                    struct svcctl_EnumServicesStatusW *r)
449 {
450         struct ENUM_SERVICE_STATUSW *services = NULL;
451         int num_services;
452         int i = 0;
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;
457
458         /* perform access checks */
459
460         if ( !info || (info->type != SVC_HANDLE_IS_SCM) )
461                 return WERR_BADFID;
462
463         if ( !(info->access_granted & SC_RIGHT_MGR_ENUMERATE_SERVICE) ) {
464                 return WERR_ACCESS_DENIED;
465         }
466
467         num_services = enumerate_status(p->mem_ctx,
468                                         p->msg_ctx,
469                                         p->server_info,
470                                         &services);
471         if (num_services == -1 ) {
472                 return WERR_NOMEM;
473         }
474
475         for ( i=0; i<num_services; i++ ) {
476                 buffer_size += ndr_size_ENUM_SERVICE_STATUSW(&services[i], 0);
477         }
478
479         buffer_size += buffer_size % 4;
480
481         if (buffer_size > r->in.offered) {
482                 num_services = 0;
483                 result = WERR_MORE_DATA;
484         }
485
486         if ( W_ERROR_IS_OK(result) ) {
487
488                 enum ndr_err_code ndr_err;
489                 struct ndr_push *ndr;
490
491                 ndr = ndr_push_init_ctx(p->mem_ctx);
492                 if (ndr == NULL) {
493                         return WERR_INVALID_PARAM;
494                 }
495
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));
500                 }
501                 blob = ndr_push_blob(ndr);
502                 memcpy(r->out.service, blob.data, MIN(blob.length, r->in.offered));
503         }
504
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;
509         }
510
511         return result;
512 }
513
514 /********************************************************************
515  _svcctl_StartServiceW
516 ********************************************************************/
517
518 WERROR _svcctl_StartServiceW(struct pipes_struct *p,
519                              struct svcctl_StartServiceW *r)
520 {
521         SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
522
523         /* perform access checks */
524
525         if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
526                 return WERR_BADFID;
527
528         if ( !(info->access_granted & SC_RIGHT_SVC_START) )
529                 return WERR_ACCESS_DENIED;
530
531         return info->ops->start_service( info->name );
532 }
533
534 /********************************************************************
535  _svcctl_ControlService
536 ********************************************************************/
537
538 WERROR _svcctl_ControlService(struct pipes_struct *p,
539                               struct svcctl_ControlService *r)
540 {
541         SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
542
543         /* perform access checks */
544
545         if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
546                 return WERR_BADFID;
547
548         switch ( r->in.control ) {
549         case SVCCTL_CONTROL_STOP:
550                 if ( !(info->access_granted & SC_RIGHT_SVC_STOP) )
551                         return WERR_ACCESS_DENIED;
552
553                 return info->ops->stop_service( info->name,
554                                                 r->out.service_status );
555
556         case SVCCTL_CONTROL_INTERROGATE:
557                 if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_STATUS) )
558                         return WERR_ACCESS_DENIED;
559
560                 return info->ops->service_status( info->name,
561                                                   r->out.service_status );
562         default:
563                 return WERR_INVALID_PARAM;
564         }
565 }
566
567 /********************************************************************
568  _svcctl_EnumDependentServicesW
569 ********************************************************************/
570
571 WERROR _svcctl_EnumDependentServicesW(struct pipes_struct *p,
572                                       struct svcctl_EnumDependentServicesW *r)
573 {
574         SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.service );
575
576         /* perform access checks */
577
578         if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
579                 return WERR_BADFID;
580
581         if ( !(info->access_granted & SC_RIGHT_SVC_ENUMERATE_DEPENDENTS) )
582                 return WERR_ACCESS_DENIED;
583
584         switch (r->in.state) {
585         case SERVICE_STATE_ACTIVE:
586         case SERVICE_STATE_INACTIVE:
587         case SERVICE_STATE_ALL:
588                 break;
589         default:
590                 return WERR_INVALID_PARAM;
591         }
592
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 */
596
597         *r->out.needed = r->in.offered;
598
599         /* no dependent services...basically a stub function */
600         *r->out.services_returned = 0;
601
602         return WERR_OK;
603 }
604
605 /********************************************************************
606  _svcctl_QueryServiceStatusEx
607 ********************************************************************/
608
609 WERROR _svcctl_QueryServiceStatusEx(struct pipes_struct *p,
610                                     struct svcctl_QueryServiceStatusEx *r)
611 {
612         SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
613         uint32 buffer_size;
614
615         /* perform access checks */
616
617         if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
618                 return WERR_BADFID;
619
620         if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_STATUS) )
621                 return WERR_ACCESS_DENIED;
622
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;
626
627         switch ( r->in.info_level ) {
628                 case SVC_STATUS_PROCESS_INFO:
629                 {
630                         struct SERVICE_STATUS_PROCESS svc_stat_proc;
631                         enum ndr_err_code ndr_err;
632                         DATA_BLOB blob;
633
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;
638
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;
643                         }
644
645                         r->out.buffer = blob.data;
646                         buffer_size = sizeof(struct SERVICE_STATUS_PROCESS);
647                         break;
648                 }
649
650                 default:
651                         return WERR_UNKNOWN_LEVEL;
652         }
653
654
655         buffer_size += buffer_size % 4;
656         *r->out.needed = (buffer_size > r->in.offered) ? buffer_size : r->in.offered;
657
658         if (buffer_size > r->in.offered ) {
659                 return WERR_INSUFFICIENT_BUFFER;
660         }
661
662         return WERR_OK;
663 }
664
665 /********************************************************************
666 ********************************************************************/
667
668 static WERROR fill_svc_config(TALLOC_CTX *ctx,
669                               struct messaging_context *msg_ctx,
670                               struct auth_serversupplied_info *server_info,
671                               const char *name,
672                               struct QUERY_SERVICE_CONFIG *config)
673 {
674         TALLOC_CTX *mem_ctx = talloc_stackframe();
675         const char *result = NULL;
676
677         /* now fill in the individual values */
678
679         config->displayname = svcctl_lookup_dispname(mem_ctx,
680                                                      msg_ctx,
681                                                      server_info,
682                                                      name);
683
684         result = svcctl_get_string_value(mem_ctx,
685                                          msg_ctx,
686                                          server_info,
687                                          name,
688                                          "ObjectName");
689         if (result != NULL) {
690                 config->startname = result;
691         }
692
693         result = svcctl_get_string_value(mem_ctx,
694                                          msg_ctx,
695                                          server_info,
696                                          name,
697                                          "ImagePath");
698         if (result != NULL) {
699                 config->executablepath = result;
700         }
701
702         /* a few hard coded values */
703         /* loadordergroup and dependencies are empty */
704
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;
708
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
711            are not running */
712
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;
717         else
718                 config->start_type = SVCCTL_DEMAND_START;
719
720
721         talloc_free(mem_ctx);
722
723         return WERR_OK;
724 }
725
726 /********************************************************************
727  _svcctl_QueryServiceConfigW
728 ********************************************************************/
729
730 WERROR _svcctl_QueryServiceConfigW(struct pipes_struct *p,
731                                    struct svcctl_QueryServiceConfigW *r)
732 {
733         SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
734         uint32 buffer_size;
735         WERROR wresult;
736
737         /* perform access checks */
738
739         if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
740                 return WERR_BADFID;
741
742         if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_CONFIG) )
743                 return WERR_ACCESS_DENIED;
744
745         /* we have to set the outgoing buffer size to the same as the
746            incoming buffer size (even in the case of failure */
747
748         *r->out.needed = r->in.offered;
749
750         wresult = fill_svc_config(p->mem_ctx,
751                                   p->msg_ctx,
752                                   p->server_info,
753                                   info->name,
754                                   r->out.query);
755         if ( !W_ERROR_IS_OK(wresult) )
756                 return wresult;
757
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;
760
761         if (buffer_size > r->in.offered ) {
762                 ZERO_STRUCTP(r->out.query);
763                 return WERR_INSUFFICIENT_BUFFER;
764         }
765
766         return WERR_OK;
767 }
768
769 /********************************************************************
770  _svcctl_QueryServiceConfig2W
771 ********************************************************************/
772
773 WERROR _svcctl_QueryServiceConfig2W(struct pipes_struct *p,
774                                     struct svcctl_QueryServiceConfig2W *r)
775 {
776         SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
777         uint32 buffer_size;
778
779         /* perform access checks */
780
781         if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
782                 return WERR_BADFID;
783
784         if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_CONFIG) )
785                 return WERR_ACCESS_DENIED;
786
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;
790
791         switch ( r->in.info_level ) {
792         case SERVICE_CONFIG_DESCRIPTION:
793                 {
794                         struct SERVICE_DESCRIPTION desc_buf;
795                         const char *description;
796                         enum ndr_err_code ndr_err;
797                         DATA_BLOB blob;
798
799                         description = svcctl_lookup_description(p->mem_ctx,
800                                                                 p->msg_ctx,
801                                                                 p->server_info,
802                                                                 info->name);
803
804                         desc_buf.description = description;
805
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;
810                         }
811
812                         buffer_size = ndr_size_SERVICE_DESCRIPTION(&desc_buf, 0);
813                         r->out.buffer = blob.data;
814
815                         break;
816                 }
817                 break;
818         case SERVICE_CONFIG_FAILURE_ACTIONS:
819                 {
820                         struct SERVICE_FAILURE_ACTIONS actions;
821                         enum ndr_err_code ndr_err;
822                         DATA_BLOB blob;
823
824                         /* nothing to say...just service the request */
825
826                         ZERO_STRUCT( actions );
827
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;
832                         }
833
834                         buffer_size = ndr_size_SERVICE_FAILURE_ACTIONS(&actions, 0);
835                         r->out.buffer = blob.data;
836
837                         break;
838                 }
839                 break;
840
841         default:
842                 return WERR_UNKNOWN_LEVEL;
843         }
844
845         buffer_size += buffer_size % 4;
846         *r->out.needed = (buffer_size > r->in.offered) ? buffer_size : r->in.offered;
847
848         if (buffer_size > r->in.offered)
849                 return WERR_INSUFFICIENT_BUFFER;
850
851         return WERR_OK;
852 }
853
854 /********************************************************************
855  _svcctl_LockServiceDatabase
856 ********************************************************************/
857
858 WERROR _svcctl_LockServiceDatabase(struct pipes_struct *p,
859                                    struct svcctl_LockServiceDatabase *r)
860 {
861         SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
862
863         /* perform access checks */
864
865         if ( !info || (info->type != SVC_HANDLE_IS_SCM) )
866                 return WERR_BADFID;
867
868         if ( !(info->access_granted & SC_RIGHT_MGR_LOCK) )
869                 return WERR_ACCESS_DENIED;
870
871         /* Just open a handle.  Doesn't actually lock anything */
872
873         return create_open_service_handle( p, r->out.lock, SVC_HANDLE_IS_DBLOCK, NULL, 0 );
874 }
875
876 /********************************************************************
877  _svcctl_UnlockServiceDatabase
878 ********************************************************************/
879
880 WERROR _svcctl_UnlockServiceDatabase(struct pipes_struct *p,
881                                      struct svcctl_UnlockServiceDatabase *r)
882 {
883         SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.lock );
884
885
886         if ( !info || (info->type != SVC_HANDLE_IS_DBLOCK) )
887                 return WERR_BADFID;
888
889         return close_policy_hnd( p, r->out.lock) ? WERR_OK : WERR_BADFID;
890 }
891
892 /********************************************************************
893  _svcctl_QueryServiceObjectSecurity
894 ********************************************************************/
895
896 WERROR _svcctl_QueryServiceObjectSecurity(struct pipes_struct *p,
897                                           struct svcctl_QueryServiceObjectSecurity *r)
898 {
899         SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
900         struct security_descriptor *sec_desc;
901         NTSTATUS status;
902         uint8_t *buffer = NULL;
903         size_t len = 0;
904
905
906         /* only support the SCM and individual services */
907
908         if ( !info || !(info->type & (SVC_HANDLE_IS_SERVICE|SVC_HANDLE_IS_SCM)) )
909                 return WERR_BADFID;
910
911         /* check access reights (according to MSDN) */
912
913         if ( !(info->access_granted & SEC_STD_READ_CONTROL) )
914                 return WERR_ACCESS_DENIED;
915
916         /* TODO: handle something besides SECINFO_DACL */
917
918         if ( (r->in.security_flags & SECINFO_DACL) != SECINFO_DACL )
919                 return WERR_INVALID_PARAM;
920
921         /* Lookup the security descriptor and marshall it up for a reply */
922         sec_desc = svcctl_get_secdesc(p->mem_ctx,
923                                       p->msg_ctx,
924                                       get_server_info_system(),
925                                       info->name);
926         if (sec_desc == NULL) {
927                 return WERR_NOMEM;
928         }
929
930         *r->out.needed = ndr_size_security_descriptor(sec_desc, 0);
931
932         if ( *r->out.needed > r->in.offered) {
933                 return WERR_INSUFFICIENT_BUFFER;
934         }
935
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);
939         }
940
941         *r->out.needed = len;
942         r->out.buffer = buffer;
943
944         return WERR_OK;
945 }
946
947 /********************************************************************
948  _svcctl_SetServiceObjectSecurity
949 ********************************************************************/
950
951 WERROR _svcctl_SetServiceObjectSecurity(struct pipes_struct *p,
952                                         struct svcctl_SetServiceObjectSecurity *r)
953 {
954         SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
955         struct security_descriptor *sec_desc = NULL;
956         uint32 required_access;
957         NTSTATUS status;
958
959         if ( !info || !(info->type & (SVC_HANDLE_IS_SERVICE|SVC_HANDLE_IS_SCM))  )
960                 return WERR_BADFID;
961
962         /* can't set the security de4scriptor on the ServiceControlManager */
963
964         if ( info->type == SVC_HANDLE_IS_SCM )
965                 return WERR_ACCESS_DENIED;
966
967         /* check the access on the open handle */
968
969         switch ( r->in.security_flags ) {
970                 case SECINFO_DACL:
971                         required_access = SEC_STD_WRITE_DAC;
972                         break;
973
974                 case SECINFO_OWNER:
975                 case SECINFO_GROUP:
976                         required_access = SEC_STD_WRITE_OWNER;
977                         break;
978
979                 case SECINFO_SACL:
980                         return WERR_INVALID_PARAM;
981                 default:
982                         return WERR_INVALID_PARAM;
983         }
984
985         if ( !(info->access_granted & required_access) )
986                 return WERR_ACCESS_DENIED;
987
988         /* read the security descfriptor */
989
990         status = unmarshall_sec_desc(p->mem_ctx,
991                                      r->in.buffer,
992                                      r->in.offered,
993                                      &sec_desc);
994         if (!NT_STATUS_IS_OK(status)) {
995                 return ntstatus_to_werror(status);
996         }
997
998         /* store the new SD */
999
1000         if (!svcctl_set_secdesc(p->msg_ctx, p->server_info, info->name, sec_desc))
1001                 return WERR_ACCESS_DENIED;
1002
1003         return WERR_OK;
1004 }
1005
1006
1007 WERROR _svcctl_DeleteService(struct pipes_struct *p,
1008                              struct svcctl_DeleteService *r)
1009 {
1010         p->rng_fault_state = True;
1011         return WERR_NOT_SUPPORTED;
1012 }
1013
1014 WERROR _svcctl_SetServiceStatus(struct pipes_struct *p,
1015                                 struct svcctl_SetServiceStatus *r)
1016 {
1017         p->rng_fault_state = True;
1018         return WERR_NOT_SUPPORTED;
1019 }
1020
1021 WERROR _svcctl_NotifyBootConfigStatus(struct pipes_struct *p,
1022                                       struct svcctl_NotifyBootConfigStatus *r)
1023 {
1024         p->rng_fault_state = True;
1025         return WERR_NOT_SUPPORTED;
1026 }
1027
1028 WERROR _svcctl_SCSetServiceBitsW(struct pipes_struct *p,
1029                                  struct svcctl_SCSetServiceBitsW *r)
1030 {
1031         p->rng_fault_state = True;
1032         return WERR_NOT_SUPPORTED;
1033 }
1034
1035 WERROR _svcctl_ChangeServiceConfigW(struct pipes_struct *p,
1036                                     struct svcctl_ChangeServiceConfigW *r)
1037 {
1038         p->rng_fault_state = True;
1039         return WERR_NOT_SUPPORTED;
1040 }
1041
1042 WERROR _svcctl_CreateServiceW(struct pipes_struct *p,
1043                               struct svcctl_CreateServiceW *r)
1044 {
1045         p->rng_fault_state = True;
1046         return WERR_NOT_SUPPORTED;
1047 }
1048
1049 WERROR _svcctl_QueryServiceLockStatusW(struct pipes_struct *p,
1050                                        struct svcctl_QueryServiceLockStatusW *r)
1051 {
1052         p->rng_fault_state = True;
1053         return WERR_NOT_SUPPORTED;
1054 }
1055
1056 WERROR _svcctl_GetServiceKeyNameW(struct pipes_struct *p,
1057                                   struct svcctl_GetServiceKeyNameW *r)
1058 {
1059         p->rng_fault_state = True;
1060         return WERR_NOT_SUPPORTED;
1061 }
1062
1063 WERROR _svcctl_SCSetServiceBitsA(struct pipes_struct *p,
1064                                  struct svcctl_SCSetServiceBitsA *r)
1065 {
1066         p->rng_fault_state = True;
1067         return WERR_NOT_SUPPORTED;
1068 }
1069
1070 WERROR _svcctl_ChangeServiceConfigA(struct pipes_struct *p,
1071                                     struct svcctl_ChangeServiceConfigA *r)
1072 {
1073         p->rng_fault_state = True;
1074         return WERR_NOT_SUPPORTED;
1075 }
1076
1077 WERROR _svcctl_CreateServiceA(struct pipes_struct *p,
1078                               struct svcctl_CreateServiceA *r)
1079 {
1080         p->rng_fault_state = True;
1081         return WERR_NOT_SUPPORTED;
1082 }
1083
1084 WERROR _svcctl_EnumDependentServicesA(struct pipes_struct *p,
1085                                       struct svcctl_EnumDependentServicesA *r)
1086 {
1087         p->rng_fault_state = True;
1088         return WERR_NOT_SUPPORTED;
1089 }
1090
1091 WERROR _svcctl_EnumServicesStatusA(struct pipes_struct *p,
1092                                    struct svcctl_EnumServicesStatusA *r)
1093 {
1094         p->rng_fault_state = True;
1095         return WERR_NOT_SUPPORTED;
1096 }
1097
1098 WERROR _svcctl_OpenSCManagerA(struct pipes_struct *p,
1099                               struct svcctl_OpenSCManagerA *r)
1100 {
1101         p->rng_fault_state = True;
1102         return WERR_NOT_SUPPORTED;
1103 }
1104
1105 WERROR _svcctl_OpenServiceA(struct pipes_struct *p,
1106                             struct svcctl_OpenServiceA *r)
1107 {
1108         p->rng_fault_state = True;
1109         return WERR_NOT_SUPPORTED;
1110 }
1111
1112 WERROR _svcctl_QueryServiceConfigA(struct pipes_struct *p,
1113                                    struct svcctl_QueryServiceConfigA *r)
1114 {
1115         p->rng_fault_state = True;
1116         return WERR_NOT_SUPPORTED;
1117 }
1118
1119 WERROR _svcctl_QueryServiceLockStatusA(struct pipes_struct *p,
1120                                        struct svcctl_QueryServiceLockStatusA *r)
1121 {
1122         p->rng_fault_state = True;
1123         return WERR_NOT_SUPPORTED;
1124 }
1125
1126 WERROR _svcctl_StartServiceA(struct pipes_struct *p,
1127                              struct svcctl_StartServiceA *r)
1128 {
1129         p->rng_fault_state = True;
1130         return WERR_NOT_SUPPORTED;
1131 }
1132
1133 WERROR _svcctl_GetServiceDisplayNameA(struct pipes_struct *p,
1134                                       struct svcctl_GetServiceDisplayNameA *r)
1135 {
1136         p->rng_fault_state = True;
1137         return WERR_NOT_SUPPORTED;
1138 }
1139
1140 WERROR _svcctl_GetServiceKeyNameA(struct pipes_struct *p,
1141                                   struct svcctl_GetServiceKeyNameA *r)
1142 {
1143         p->rng_fault_state = True;
1144         return WERR_NOT_SUPPORTED;
1145 }
1146
1147 WERROR _svcctl_GetCurrentGroupeStateW(struct pipes_struct *p,
1148                                       struct svcctl_GetCurrentGroupeStateW *r)
1149 {
1150         p->rng_fault_state = True;
1151         return WERR_NOT_SUPPORTED;
1152 }
1153
1154 WERROR _svcctl_EnumServiceGroupW(struct pipes_struct *p,
1155                                  struct svcctl_EnumServiceGroupW *r)
1156 {
1157         p->rng_fault_state = True;
1158         return WERR_NOT_SUPPORTED;
1159 }
1160
1161 WERROR _svcctl_ChangeServiceConfig2A(struct pipes_struct *p,
1162                                      struct svcctl_ChangeServiceConfig2A *r)
1163 {
1164         p->rng_fault_state = True;
1165         return WERR_NOT_SUPPORTED;
1166 }
1167
1168 WERROR _svcctl_ChangeServiceConfig2W(struct pipes_struct *p,
1169                                      struct svcctl_ChangeServiceConfig2W *r)
1170 {
1171         p->rng_fault_state = True;
1172         return WERR_NOT_SUPPORTED;
1173 }
1174
1175 WERROR _svcctl_QueryServiceConfig2A(struct pipes_struct *p,
1176                                     struct svcctl_QueryServiceConfig2A *r)
1177 {
1178         p->rng_fault_state = True;
1179         return WERR_NOT_SUPPORTED;
1180 }
1181
1182 WERROR _EnumServicesStatusExA(struct pipes_struct *p,
1183                               struct EnumServicesStatusExA *r)
1184 {
1185         p->rng_fault_state = True;
1186         return WERR_NOT_SUPPORTED;
1187 }
1188
1189 WERROR _EnumServicesStatusExW(struct pipes_struct *p,
1190                               struct EnumServicesStatusExW *r)
1191 {
1192         p->rng_fault_state = True;
1193         return WERR_NOT_SUPPORTED;
1194 }
1195
1196 WERROR _svcctl_SCSendTSMessage(struct pipes_struct *p,
1197                                struct svcctl_SCSendTSMessage *r)
1198 {
1199         p->rng_fault_state = True;
1200         return WERR_NOT_SUPPORTED;
1201 }