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