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