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