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