s3-talloc Change TALLOC_ARRAY() to talloc_array()
[kai/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_P( 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_serversupplied_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 *ctx,
672                               struct messaging_context *msg_ctx,
673                               struct auth_serversupplied_info *session_info,
674                               const char *name,
675                               struct QUERY_SERVICE_CONFIG *config)
676 {
677         TALLOC_CTX *mem_ctx = talloc_stackframe();
678         const char *result = NULL;
679
680         /* now fill in the individual values */
681
682         config->displayname = svcctl_lookup_dispname(mem_ctx,
683                                                      msg_ctx,
684                                                      session_info,
685                                                      name);
686
687         result = svcctl_get_string_value(mem_ctx,
688                                          msg_ctx,
689                                          session_info,
690                                          name,
691                                          "ObjectName");
692         if (result != NULL) {
693                 config->startname = result;
694         }
695
696         result = svcctl_get_string_value(mem_ctx,
697                                          msg_ctx,
698                                          session_info,
699                                          name,
700                                          "ImagePath");
701         if (result != NULL) {
702                 config->executablepath = result;
703         }
704
705         /* a few hard coded values */
706         /* loadordergroup and dependencies are empty */
707
708         config->tag_id           = 0x00000000;                  /* unassigned loadorder group */
709         config->service_type     = SERVICE_TYPE_WIN32_OWN_PROCESS;
710         config->error_control    = SVCCTL_SVC_ERROR_NORMAL;
711
712         /* set the start type.  NetLogon and WINS are disabled to prevent
713            the client from showing the "Start" button (if of course the services
714            are not running */
715
716         if ( strequal( name, "NETLOGON" ) && ( lp_servicenumber(name) == -1 ) )
717                 config->start_type = SVCCTL_DISABLED;
718         else if ( strequal( name, "WINS" ) && ( !lp_wins_support() ))
719                 config->start_type = SVCCTL_DISABLED;
720         else
721                 config->start_type = SVCCTL_DEMAND_START;
722
723
724         talloc_free(mem_ctx);
725
726         return WERR_OK;
727 }
728
729 /********************************************************************
730  _svcctl_QueryServiceConfigW
731 ********************************************************************/
732
733 WERROR _svcctl_QueryServiceConfigW(struct pipes_struct *p,
734                                    struct svcctl_QueryServiceConfigW *r)
735 {
736         SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
737         uint32 buffer_size;
738         WERROR wresult;
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
751         *r->out.needed = r->in.offered;
752
753         wresult = fill_svc_config(p->mem_ctx,
754                                   p->msg_ctx,
755                                   p->session_info,
756                                   info->name,
757                                   r->out.query);
758         if ( !W_ERROR_IS_OK(wresult) )
759                 return wresult;
760
761         buffer_size = ndr_size_QUERY_SERVICE_CONFIG(r->out.query, 0);
762         *r->out.needed = (buffer_size > r->in.offered) ? buffer_size : r->in.offered;
763
764         if (buffer_size > r->in.offered ) {
765                 ZERO_STRUCTP(r->out.query);
766                 return WERR_INSUFFICIENT_BUFFER;
767         }
768
769         return WERR_OK;
770 }
771
772 /********************************************************************
773  _svcctl_QueryServiceConfig2W
774 ********************************************************************/
775
776 WERROR _svcctl_QueryServiceConfig2W(struct pipes_struct *p,
777                                     struct svcctl_QueryServiceConfig2W *r)
778 {
779         SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
780         uint32 buffer_size;
781
782         /* perform access checks */
783
784         if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
785                 return WERR_BADFID;
786
787         if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_CONFIG) )
788                 return WERR_ACCESS_DENIED;
789
790         /* we have to set the outgoing buffer size to the same as the
791            incoming buffer size (even in the case of failure */
792         *r->out.needed = r->in.offered;
793
794         switch ( r->in.info_level ) {
795         case SERVICE_CONFIG_DESCRIPTION:
796                 {
797                         struct SERVICE_DESCRIPTION desc_buf;
798                         const char *description;
799                         enum ndr_err_code ndr_err;
800                         DATA_BLOB blob;
801
802                         description = svcctl_lookup_description(p->mem_ctx,
803                                                                 p->msg_ctx,
804                                                                 p->session_info,
805                                                                 info->name);
806
807                         desc_buf.description = description;
808
809                         ndr_err = ndr_push_struct_blob(&blob, p->mem_ctx, &desc_buf,
810                                                        (ndr_push_flags_fn_t)ndr_push_SERVICE_DESCRIPTION);
811                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
812                                 return WERR_INVALID_PARAM;
813                         }
814
815                         buffer_size = ndr_size_SERVICE_DESCRIPTION(&desc_buf, 0);
816                         r->out.buffer = blob.data;
817
818                         break;
819                 }
820                 break;
821         case SERVICE_CONFIG_FAILURE_ACTIONS:
822                 {
823                         struct SERVICE_FAILURE_ACTIONS actions;
824                         enum ndr_err_code ndr_err;
825                         DATA_BLOB blob;
826
827                         /* nothing to say...just service the request */
828
829                         ZERO_STRUCT( actions );
830
831                         ndr_err = ndr_push_struct_blob(&blob, p->mem_ctx, &actions,
832                                                        (ndr_push_flags_fn_t)ndr_push_SERVICE_FAILURE_ACTIONS);
833                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
834                                 return WERR_INVALID_PARAM;
835                         }
836
837                         buffer_size = ndr_size_SERVICE_FAILURE_ACTIONS(&actions, 0);
838                         r->out.buffer = blob.data;
839
840                         break;
841                 }
842                 break;
843
844         default:
845                 return WERR_UNKNOWN_LEVEL;
846         }
847
848         buffer_size += buffer_size % 4;
849         *r->out.needed = (buffer_size > r->in.offered) ? buffer_size : r->in.offered;
850
851         if (buffer_size > r->in.offered)
852                 return WERR_INSUFFICIENT_BUFFER;
853
854         return WERR_OK;
855 }
856
857 /********************************************************************
858  _svcctl_LockServiceDatabase
859 ********************************************************************/
860
861 WERROR _svcctl_LockServiceDatabase(struct pipes_struct *p,
862                                    struct svcctl_LockServiceDatabase *r)
863 {
864         SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
865
866         /* perform access checks */
867
868         if ( !info || (info->type != SVC_HANDLE_IS_SCM) )
869                 return WERR_BADFID;
870
871         if ( !(info->access_granted & SC_RIGHT_MGR_LOCK) )
872                 return WERR_ACCESS_DENIED;
873
874         /* Just open a handle.  Doesn't actually lock anything */
875
876         return create_open_service_handle( p, r->out.lock, SVC_HANDLE_IS_DBLOCK, NULL, 0 );
877 }
878
879 /********************************************************************
880  _svcctl_UnlockServiceDatabase
881 ********************************************************************/
882
883 WERROR _svcctl_UnlockServiceDatabase(struct pipes_struct *p,
884                                      struct svcctl_UnlockServiceDatabase *r)
885 {
886         SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.lock );
887
888
889         if ( !info || (info->type != SVC_HANDLE_IS_DBLOCK) )
890                 return WERR_BADFID;
891
892         return close_policy_hnd( p, r->out.lock) ? WERR_OK : WERR_BADFID;
893 }
894
895 /********************************************************************
896  _svcctl_QueryServiceObjectSecurity
897 ********************************************************************/
898
899 WERROR _svcctl_QueryServiceObjectSecurity(struct pipes_struct *p,
900                                           struct svcctl_QueryServiceObjectSecurity *r)
901 {
902         SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
903         struct security_descriptor *sec_desc;
904         NTSTATUS status;
905         uint8_t *buffer = NULL;
906         size_t len = 0;
907
908
909         /* only support the SCM and individual services */
910
911         if ( !info || !(info->type & (SVC_HANDLE_IS_SERVICE|SVC_HANDLE_IS_SCM)) )
912                 return WERR_BADFID;
913
914         /* check access reights (according to MSDN) */
915
916         if ( !(info->access_granted & SEC_STD_READ_CONTROL) )
917                 return WERR_ACCESS_DENIED;
918
919         /* TODO: handle something besides SECINFO_DACL */
920
921         if ( (r->in.security_flags & SECINFO_DACL) != SECINFO_DACL )
922                 return WERR_INVALID_PARAM;
923
924         /* Lookup the security descriptor and marshall it up for a reply */
925         sec_desc = svcctl_get_secdesc(p->mem_ctx,
926                                       p->msg_ctx,
927                                       get_session_info_system(),
928                                       info->name);
929         if (sec_desc == NULL) {
930                 return WERR_NOMEM;
931         }
932
933         *r->out.needed = ndr_size_security_descriptor(sec_desc, 0);
934
935         if ( *r->out.needed > r->in.offered) {
936                 return WERR_INSUFFICIENT_BUFFER;
937         }
938
939         status = marshall_sec_desc(p->mem_ctx, sec_desc, &buffer, &len);
940         if (!NT_STATUS_IS_OK(status)) {
941                 return ntstatus_to_werror(status);
942         }
943
944         *r->out.needed = len;
945         r->out.buffer = buffer;
946
947         return WERR_OK;
948 }
949
950 /********************************************************************
951  _svcctl_SetServiceObjectSecurity
952 ********************************************************************/
953
954 WERROR _svcctl_SetServiceObjectSecurity(struct pipes_struct *p,
955                                         struct svcctl_SetServiceObjectSecurity *r)
956 {
957         SERVICE_INFO *info = find_service_info_by_hnd( p, r->in.handle );
958         struct security_descriptor *sec_desc = NULL;
959         uint32 required_access;
960         NTSTATUS status;
961
962         if ( !info || !(info->type & (SVC_HANDLE_IS_SERVICE|SVC_HANDLE_IS_SCM))  )
963                 return WERR_BADFID;
964
965         /* can't set the security de4scriptor on the ServiceControlManager */
966
967         if ( info->type == SVC_HANDLE_IS_SCM )
968                 return WERR_ACCESS_DENIED;
969
970         /* check the access on the open handle */
971
972         switch ( r->in.security_flags ) {
973                 case SECINFO_DACL:
974                         required_access = SEC_STD_WRITE_DAC;
975                         break;
976
977                 case SECINFO_OWNER:
978                 case SECINFO_GROUP:
979                         required_access = SEC_STD_WRITE_OWNER;
980                         break;
981
982                 case SECINFO_SACL:
983                         return WERR_INVALID_PARAM;
984                 default:
985                         return WERR_INVALID_PARAM;
986         }
987
988         if ( !(info->access_granted & required_access) )
989                 return WERR_ACCESS_DENIED;
990
991         /* read the security descfriptor */
992
993         status = unmarshall_sec_desc(p->mem_ctx,
994                                      r->in.buffer,
995                                      r->in.offered,
996                                      &sec_desc);
997         if (!NT_STATUS_IS_OK(status)) {
998                 return ntstatus_to_werror(status);
999         }
1000
1001         /* store the new SD */
1002
1003         if (!svcctl_set_secdesc(p->msg_ctx, p->session_info, info->name, sec_desc))
1004                 return WERR_ACCESS_DENIED;
1005
1006         return WERR_OK;
1007 }
1008
1009
1010 WERROR _svcctl_DeleteService(struct pipes_struct *p,
1011                              struct svcctl_DeleteService *r)
1012 {
1013         p->rng_fault_state = True;
1014         return WERR_NOT_SUPPORTED;
1015 }
1016
1017 WERROR _svcctl_SetServiceStatus(struct pipes_struct *p,
1018                                 struct svcctl_SetServiceStatus *r)
1019 {
1020         p->rng_fault_state = True;
1021         return WERR_NOT_SUPPORTED;
1022 }
1023
1024 WERROR _svcctl_NotifyBootConfigStatus(struct pipes_struct *p,
1025                                       struct svcctl_NotifyBootConfigStatus *r)
1026 {
1027         p->rng_fault_state = True;
1028         return WERR_NOT_SUPPORTED;
1029 }
1030
1031 WERROR _svcctl_SCSetServiceBitsW(struct pipes_struct *p,
1032                                  struct svcctl_SCSetServiceBitsW *r)
1033 {
1034         p->rng_fault_state = True;
1035         return WERR_NOT_SUPPORTED;
1036 }
1037
1038 WERROR _svcctl_ChangeServiceConfigW(struct pipes_struct *p,
1039                                     struct svcctl_ChangeServiceConfigW *r)
1040 {
1041         p->rng_fault_state = True;
1042         return WERR_NOT_SUPPORTED;
1043 }
1044
1045 WERROR _svcctl_CreateServiceW(struct pipes_struct *p,
1046                               struct svcctl_CreateServiceW *r)
1047 {
1048         p->rng_fault_state = True;
1049         return WERR_NOT_SUPPORTED;
1050 }
1051
1052 WERROR _svcctl_QueryServiceLockStatusW(struct pipes_struct *p,
1053                                        struct svcctl_QueryServiceLockStatusW *r)
1054 {
1055         p->rng_fault_state = True;
1056         return WERR_NOT_SUPPORTED;
1057 }
1058
1059 WERROR _svcctl_GetServiceKeyNameW(struct pipes_struct *p,
1060                                   struct svcctl_GetServiceKeyNameW *r)
1061 {
1062         p->rng_fault_state = True;
1063         return WERR_NOT_SUPPORTED;
1064 }
1065
1066 WERROR _svcctl_SCSetServiceBitsA(struct pipes_struct *p,
1067                                  struct svcctl_SCSetServiceBitsA *r)
1068 {
1069         p->rng_fault_state = True;
1070         return WERR_NOT_SUPPORTED;
1071 }
1072
1073 WERROR _svcctl_ChangeServiceConfigA(struct pipes_struct *p,
1074                                     struct svcctl_ChangeServiceConfigA *r)
1075 {
1076         p->rng_fault_state = True;
1077         return WERR_NOT_SUPPORTED;
1078 }
1079
1080 WERROR _svcctl_CreateServiceA(struct pipes_struct *p,
1081                               struct svcctl_CreateServiceA *r)
1082 {
1083         p->rng_fault_state = True;
1084         return WERR_NOT_SUPPORTED;
1085 }
1086
1087 WERROR _svcctl_EnumDependentServicesA(struct pipes_struct *p,
1088                                       struct svcctl_EnumDependentServicesA *r)
1089 {
1090         p->rng_fault_state = True;
1091         return WERR_NOT_SUPPORTED;
1092 }
1093
1094 WERROR _svcctl_EnumServicesStatusA(struct pipes_struct *p,
1095                                    struct svcctl_EnumServicesStatusA *r)
1096 {
1097         p->rng_fault_state = True;
1098         return WERR_NOT_SUPPORTED;
1099 }
1100
1101 WERROR _svcctl_OpenSCManagerA(struct pipes_struct *p,
1102                               struct svcctl_OpenSCManagerA *r)
1103 {
1104         p->rng_fault_state = True;
1105         return WERR_NOT_SUPPORTED;
1106 }
1107
1108 WERROR _svcctl_OpenServiceA(struct pipes_struct *p,
1109                             struct svcctl_OpenServiceA *r)
1110 {
1111         p->rng_fault_state = True;
1112         return WERR_NOT_SUPPORTED;
1113 }
1114
1115 WERROR _svcctl_QueryServiceConfigA(struct pipes_struct *p,
1116                                    struct svcctl_QueryServiceConfigA *r)
1117 {
1118         p->rng_fault_state = True;
1119         return WERR_NOT_SUPPORTED;
1120 }
1121
1122 WERROR _svcctl_QueryServiceLockStatusA(struct pipes_struct *p,
1123                                        struct svcctl_QueryServiceLockStatusA *r)
1124 {
1125         p->rng_fault_state = True;
1126         return WERR_NOT_SUPPORTED;
1127 }
1128
1129 WERROR _svcctl_StartServiceA(struct pipes_struct *p,
1130                              struct svcctl_StartServiceA *r)
1131 {
1132         p->rng_fault_state = True;
1133         return WERR_NOT_SUPPORTED;
1134 }
1135
1136 WERROR _svcctl_GetServiceDisplayNameA(struct pipes_struct *p,
1137                                       struct svcctl_GetServiceDisplayNameA *r)
1138 {
1139         p->rng_fault_state = True;
1140         return WERR_NOT_SUPPORTED;
1141 }
1142
1143 WERROR _svcctl_GetServiceKeyNameA(struct pipes_struct *p,
1144                                   struct svcctl_GetServiceKeyNameA *r)
1145 {
1146         p->rng_fault_state = True;
1147         return WERR_NOT_SUPPORTED;
1148 }
1149
1150 WERROR _svcctl_GetCurrentGroupeStateW(struct pipes_struct *p,
1151                                       struct svcctl_GetCurrentGroupeStateW *r)
1152 {
1153         p->rng_fault_state = True;
1154         return WERR_NOT_SUPPORTED;
1155 }
1156
1157 WERROR _svcctl_EnumServiceGroupW(struct pipes_struct *p,
1158                                  struct svcctl_EnumServiceGroupW *r)
1159 {
1160         p->rng_fault_state = True;
1161         return WERR_NOT_SUPPORTED;
1162 }
1163
1164 WERROR _svcctl_ChangeServiceConfig2A(struct pipes_struct *p,
1165                                      struct svcctl_ChangeServiceConfig2A *r)
1166 {
1167         p->rng_fault_state = True;
1168         return WERR_NOT_SUPPORTED;
1169 }
1170
1171 WERROR _svcctl_ChangeServiceConfig2W(struct pipes_struct *p,
1172                                      struct svcctl_ChangeServiceConfig2W *r)
1173 {
1174         p->rng_fault_state = True;
1175         return WERR_NOT_SUPPORTED;
1176 }
1177
1178 WERROR _svcctl_QueryServiceConfig2A(struct pipes_struct *p,
1179                                     struct svcctl_QueryServiceConfig2A *r)
1180 {
1181         p->rng_fault_state = True;
1182         return WERR_NOT_SUPPORTED;
1183 }
1184
1185 WERROR _EnumServicesStatusExA(struct pipes_struct *p,
1186                               struct EnumServicesStatusExA *r)
1187 {
1188         p->rng_fault_state = True;
1189         return WERR_NOT_SUPPORTED;
1190 }
1191
1192 WERROR _EnumServicesStatusExW(struct pipes_struct *p,
1193                               struct EnumServicesStatusExW *r)
1194 {
1195         p->rng_fault_state = True;
1196         return WERR_NOT_SUPPORTED;
1197 }
1198
1199 WERROR _svcctl_SCSendTSMessage(struct pipes_struct *p,
1200                                struct svcctl_SCSendTSMessage *r)
1201 {
1202         p->rng_fault_state = True;
1203         return WERR_NOT_SUPPORTED;
1204 }