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